diff --git a/rpcs3/Emu/RSX/VK/vkutils/data_heap.h b/rpcs3/Emu/RSX/VK/vkutils/data_heap.h index 13ec2a5fdc..4836db9356 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/data_heap.h +++ b/rpcs3/Emu/RSX/VK/vkutils/data_heap.h @@ -4,6 +4,7 @@ #include "../VulkanAPI.h" #include "buffer_object.h" #include "commands.h" +#include "ex.h" #include #include @@ -34,6 +35,8 @@ namespace vk std::unique_ptr shadow; std::vector dirty_ranges; + mutable utils::address_range64 m_cached_buffer_range{}; + protected: bool grow(usz size) override; bool can_allocate_heap(const vk::memory_type_info& target_heap, usz size, int max_usage_percent); @@ -62,6 +65,35 @@ namespace vk void sync(const vk::command_buffer& cmd); + template + VkDescriptorBufferInfoEx window(usz offset, usz range, u64 window_size) const + { + if (window_size > size()) + { + // Driver specific. AMD allows viewing upto 4GB as UBO no problem. + return { *heap, 0, VK_WHOLE_SIZE }; + } + + if (utils::address_range64::start_length(offset, range).inside(m_cached_buffer_range)) [[ likely ]] + { + return { *heap, m_cached_buffer_range.start, m_cached_buffer_range.length() }; + } + + const u64 aligned_window_size = static_cast(window_size / Alignment) * Alignment; + const u64 start_partition = offset / aligned_window_size; + const u64 end_partition = (offset + range - 1) / aligned_window_size; + + if (start_partition == end_partition) [[ likely ]] + { + m_cached_buffer_range = utils::address_range64::start_length(start_partition * aligned_window_size, aligned_window_size); + return { *heap, m_cached_buffer_range.start, m_cached_buffer_range.length() }; + } + + // We have a partition straddler. Invalidate caching and return exact range. + m_cached_buffer_range = {}; + return { *heap, offset, range }; + } + // Properties bool is_dirty() const; bool has_shadow() const { return !!shadow; }