From 78a1128711d9724250a7308fd44be30a0a95ff33 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Thu, 31 Mar 2022 17:49:08 -0400 Subject: [PATCH] vk_staging_buffer_pool: Compute stream buffer offsets at compile time --- .../vk_staging_buffer_pool.cpp | 23 +++++++++++++++---- .../renderer_vulkan/vk_staging_buffer_pool.h | 4 ++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index 228bd85d82..7fa989c8f2 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp @@ -29,7 +29,10 @@ constexpr VkDeviceSize MAX_ALIGNMENT = 256; constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB; // Stream buffer size in bytes constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; -constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; + +constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_STREAM_REGIONS; +static_assert(Common::IsAligned(REGION_SIZE, MAX_ALIGNMENT), + "Stream buffer region size must be VK buffer aligned"); constexpr VkMemoryPropertyFlags HOST_FLAGS = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; @@ -83,6 +86,17 @@ u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_ size_t Region(size_t iterator) noexcept { return iterator / REGION_SIZE; } + +constexpr std::array MakeStreamBufferOffset() { + std::array offsets{}; + for (size_t i = 0; i < StagingBufferPool::NUM_STREAM_REGIONS; ++i) { + offsets[i] = static_cast(i * REGION_SIZE); + } + return offsets; +} + +constexpr auto STREAM_BUFFER_OFFSETS_LUT = MakeStreamBufferOffset(); + } // Anonymous namespace StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, @@ -169,8 +183,9 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { const auto begin_itr = sync_ticks.begin() + *available_index; std::fill(begin_itr, begin_itr + num_requested_regions, current_tick); - const size_t offset = *available_index * REGION_SIZE; - next_index = (*available_index + num_requested_regions) % NUM_SYNCS; + const VkDeviceSize offset = STREAM_BUFFER_OFFSETS_LUT[*available_index]; + ASSERT(offset + size <= STREAM_BUFFER_SIZE); + next_index = (*available_index + num_requested_regions) % NUM_STREAM_REGIONS; return StagingBufferRef{ .buffer = *stream_buffer, .offset = static_cast(offset), @@ -181,7 +196,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { std::optional StagingBufferPool::NextAvailableStreamIndex(size_t num_regions) const { const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick(); const auto is_active = [gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; }; - if (next_index + num_regions <= NUM_SYNCS) { + if (next_index + num_regions <= NUM_STREAM_REGIONS) { const auto begin_itr = sync_ticks.begin() + next_index; const bool is_unavailable = std::any_of(begin_itr, begin_itr + num_regions, is_active); return is_unavailable ? std::nullopt : std::optional(next_index); diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h index fee5452198..4b57e3ca44 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h @@ -25,7 +25,7 @@ struct StagingBufferRef { class StagingBufferPool { public: - static constexpr size_t NUM_SYNCS = 16; + static constexpr size_t NUM_STREAM_REGIONS = 0x8000; explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator, VKScheduler& scheduler); @@ -90,7 +90,7 @@ private: u8* stream_pointer = nullptr; size_t next_index = 0; - std::array sync_ticks{}; + std::array sync_ticks{}; StagingBuffersCache device_local_cache; StagingBuffersCache upload_cache;