[Vulkan] Smarter transient cache

Detect cases where requested vertex data has already been uploaded in a larger buffer
This commit is contained in:
DrChat 2018-02-10 21:08:17 -06:00
parent e3787c05c1
commit d015de4a84
2 changed files with 28 additions and 7 deletions

View File

@ -415,10 +415,22 @@ VkDeviceSize BufferCache::TryAllocateTransientData(VkDeviceSize length,
VkDeviceSize BufferCache::FindCachedTransientData(uint32_t guest_address, VkDeviceSize BufferCache::FindCachedTransientData(uint32_t guest_address,
uint32_t guest_length) { uint32_t guest_length) {
uint64_t key = uint64_t(guest_length) << 32 | uint64_t(guest_address); if (transient_cache_.empty()) {
auto it = transient_cache_.find(key); // Short-circuit exit.
if (it != transient_cache_.end()) { return VK_WHOLE_SIZE;
return it->second; }
// Find the first element > guest_address
auto it = transient_cache_.upper_bound(guest_address);
if (it != transient_cache_.begin()) {
// it = first element < guest_address
--it;
if (it->first <= guest_address &&
(it->first + it->second.first) >= (guest_address + guest_length)) {
// This element is contained within some existing transient data.
return it->second.second + (guest_address - it->first);
}
} }
return VK_WHOLE_SIZE; return VK_WHOLE_SIZE;
@ -427,8 +439,17 @@ VkDeviceSize BufferCache::FindCachedTransientData(uint32_t guest_address,
void BufferCache::CacheTransientData(uint32_t guest_address, void BufferCache::CacheTransientData(uint32_t guest_address,
uint32_t guest_length, uint32_t guest_length,
VkDeviceSize offset) { VkDeviceSize offset) {
uint64_t key = uint64_t(guest_length) << 32 | uint64_t(guest_address); transient_cache_[guest_address] = {guest_length, offset};
transient_cache_[key] = offset;
// Erase any entries contained within
auto it = transient_cache_.upper_bound(guest_address);
while (it != transient_cache_.end()) {
if ((guest_address + guest_length) >= (it->first + it->second.first)) {
it = transient_cache_.erase(it);
} else {
break;
}
}
} }
void BufferCache::Flush(VkCommandBuffer command_buffer) { void BufferCache::Flush(VkCommandBuffer command_buffer) {

View File

@ -122,7 +122,7 @@ class BufferCache {
// Staging ringbuffer we cycle through fast. Used for data we don't // Staging ringbuffer we cycle through fast. Used for data we don't
// plan on keeping past the current frame. // plan on keeping past the current frame.
std::unique_ptr<ui::vulkan::CircularBuffer> transient_buffer_ = nullptr; std::unique_ptr<ui::vulkan::CircularBuffer> transient_buffer_ = nullptr;
std::map<uint64_t, VkDeviceSize> transient_cache_; std::map<uint32_t, std::pair<uint32_t, VkDeviceSize>> transient_cache_;
VkDescriptorPool descriptor_pool_ = nullptr; VkDescriptorPool descriptor_pool_ = nullptr;
VkDescriptorSetLayout descriptor_set_layout_ = nullptr; VkDescriptorSetLayout descriptor_set_layout_ = nullptr;