[Vulkan] Smarter transient cache
Detect cases where requested vertex data has already been uploaded in a larger buffer
This commit is contained in:
parent
e3787c05c1
commit
d015de4a84
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue