diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index a45e9b35f1..7bcfd7091d 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -6,15 +6,11 @@ #pragma once -#include #include -#include -#include #include -#include #include -#include -#include +#include +#include #include "common/common_types.h" #include "common/div_ceil.h" @@ -455,15 +451,14 @@ private: MemoryTracker memory_tracker; Common::RangeSet uncommitted_gpu_modified_ranges; Common::RangeSet gpu_modified_ranges; - std::deque> committed_gpu_modified_ranges; // Async Buffers Common::OverlapRangeSet async_downloads; - std::deque> async_buffers; - std::deque> pending_downloads; std::optional current_buffer; - - std::deque async_buffers_death_ring; + std::vector async_buffers_death_ring; + std::vector> committed_gpu_modified_ranges; + boost::container::devector> async_buffers; + boost::container::devector> pending_downloads; size_t immediate_buffer_capacity = 0; Common::ScratchBuffer immediate_buffer_alloc; diff --git a/src/video_core/query_cache/bank_base.h b/src/video_core/query_cache/bank_base.h index 44769ea971..b686225f40 100644 --- a/src/video_core/query_cache/bank_base.h +++ b/src/video_core/query_cache/bank_base.h @@ -1,105 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once -#include -#include -#include - -#include "common/common_types.h" - namespace VideoCommon { -class BankBase { -protected: - const size_t base_bank_size{}; - size_t bank_size{}; - std::atomic references{}; - size_t current_slot{}; - -public: - explicit BankBase(size_t bank_size_) : base_bank_size{bank_size_}, bank_size(bank_size_) {} - - virtual ~BankBase() = default; - - virtual std::pair Reserve() { - if (IsClosed()) { - return {false, bank_size}; - } - const size_t result = current_slot++; - return {true, result}; - } - - virtual void Reset() { - current_slot = 0; - references = 0; - bank_size = base_bank_size; - } - - size_t Size() const { - return bank_size; - } - - void AddReference(size_t how_many = 1) { - references.fetch_add(how_many, std::memory_order_relaxed); - } - - void CloseReference(size_t how_many = 1) { - if (how_many > references.load(std::memory_order_relaxed)) { - UNREACHABLE(); - } - references.fetch_sub(how_many, std::memory_order_relaxed); - } - - void Close() { - bank_size = current_slot; - } - - bool IsClosed() const { - return current_slot >= bank_size; - } - - bool IsDead() const { - return IsClosed() && references == 0; - } -}; - -template -class BankPool { -private: - std::deque bank_pool; - std::deque bank_indices; - -public: - BankPool() = default; - ~BankPool() = default; - - // Reserve a bank from the pool and return its index - template - size_t ReserveBank(Func&& builder) { - if (!bank_indices.empty() && bank_pool[bank_indices.front()].IsDead()) { - size_t new_index = bank_indices.front(); - bank_indices.pop_front(); - bank_pool[new_index].Reset(); - bank_indices.push_back(new_index); - return new_index; - } - size_t new_index = bank_pool.size(); - builder(bank_pool, new_index); - bank_indices.push_back(new_index); - return new_index; - } - - // Get a reference to a bank using its index - BankType& GetBank(size_t index) { - return bank_pool[index]; - } - - // Get the total number of banks in the pool - size_t BankCount() const { - return bank_pool.size(); - } -}; - } // namespace VideoCommon diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 6e084cc079..53e7be22fa 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -7,11 +7,12 @@ #pragma once #include -#include #include #include #include #include +#include +#include #include "common/assert.h" #include "common/common_types.h" @@ -22,7 +23,6 @@ #include "video_core/gpu.h" #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/memory_manager.h" -#include "video_core/query_cache/bank_base.h" #include "video_core/query_cache/query_base.h" #include "video_core/query_cache/query_cache_base.h" #include "video_core/query_cache/query_stream.h" @@ -87,7 +87,7 @@ public: private: RuntimeType& runtime; - std::deque pending_sync; + std::vector pending_sync; }; template @@ -168,7 +168,7 @@ struct QueryCacheBase::QueryCacheBaseImpl { std::array(QueryType::MaxQueryTypes)> streamers; u64 streamer_mask; std::mutex flush_guard; - std::deque flushes_pending; + boost::container::devector flushes_pending; std::vector::QueryLocation> pending_unregister; }; diff --git a/src/video_core/query_cache/query_stream.h b/src/video_core/query_cache/query_stream.h index 1d11b12752..bd960ecda2 100644 --- a/src/video_core/query_cache/query_stream.h +++ b/src/video_core/query_cache/query_stream.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -9,7 +12,6 @@ #include "common/assert.h" #include "common/common_types.h" -#include "video_core/query_cache/bank_base.h" #include "video_core/query_cache/query_base.h" namespace VideoCommon { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 89e0b1114e..f83fc63fa1 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -13,6 +13,8 @@ #include #include #include +#include + #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "common/bit_util.h" #include "common/common_types.h" @@ -37,12 +39,71 @@ using Tegra::Engines::Maxwell3D; using VideoCommon::QueryType; namespace { -class SamplesQueryBank : public VideoCommon::BankBase { -public: +struct BankBase { + explicit BankBase(size_t index_, size_t bank_size_) : index{index_}, base_bank_size{bank_size_}, bank_size(bank_size_) {} + ~BankBase() = default; + std::pair Reserve() { + if (IsClosed()) + return {false, bank_size}; + const size_t result = current_slot++; + return {true, result}; + } + void Reset() { + current_slot = 0; + references = 0; + bank_size = base_bank_size; + } + size_t Size() const { + return bank_size; + } + void AddReference(size_t how_many = 1) { + references.fetch_add(how_many, std::memory_order_relaxed); + } + void CloseReference(size_t how_many = 1) { + ASSERT(how_many <= references.load(std::memory_order_relaxed)); + references.fetch_sub(how_many, std::memory_order_relaxed); + } + void Close() { + bank_size = current_slot; + } + bool IsClosed() const { + return current_slot >= bank_size; + } + bool IsDead() const { + return IsClosed() && references.load(std::memory_order_relaxed) == 0; + } + size_t index; + size_t base_bank_size{}; + size_t bank_size{}; + size_t current_slot{}; + std::atomic references{}; +}; + +template +struct BankPool { + // Reserve a bank from the pool and return its index + template + size_t ReserveBank(Func&& builder) { + if (!indices.empty() && elems[indices.front()].IsDead()) { + size_t new_index = indices.front(); + indices.pop_front(); + elems[new_index].Reset(); + indices.push_back(new_index); + return new_index; + } + size_t new_index = elems.size(); + builder(elems, new_index); + indices.push_back(new_index); + return new_index; + } + boost::container::deque elems; + boost::container::devector indices; +}; +struct SamplesQueryBank final : public BankBase { static constexpr size_t BANK_SIZE = 256; static constexpr size_t QUERY_SIZE = 8; explicit SamplesQueryBank(const Device& device_, size_t index_) - : BankBase(BANK_SIZE), device{device_}, index{index_} { + : BankBase(index_, BANK_SIZE), device{device_} { const auto& dev = device.GetLogical(); query_pool = dev.CreateQueryPool({ .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, @@ -54,12 +115,11 @@ public: }); Reset(); } - ~SamplesQueryBank() = default; - void Reset() override { + void Reset() { ASSERT(references == 0); - VideoCommon::BankBase::Reset(); + BankBase::Reset(); const auto& dev = device.GetLogical(); dev.ResetQueryPool(*query_pool, 0, BANK_SIZE); host_results.fill(0ULL); @@ -85,22 +145,62 @@ public: VkQueryPool GetInnerPool() { return *query_pool; } - size_t GetIndex() const { return index; } - const std::array& GetResults() const { return host_results; } - - size_t next_bank; - -private: - const Device& device; - const size_t index; - vk::QueryPool query_pool; + Device const& device; std::array host_results; + vk::QueryPool query_pool; + size_t next_bank; +}; + +// Transform feedback queries +struct TFBQueryBank final : public BankBase { + static constexpr size_t BANK_SIZE = 1024; + static constexpr size_t QUERY_SIZE = 4; + explicit TFBQueryBank(Scheduler& scheduler_, const MemoryAllocator& memory_allocator, size_t index_) + : BankBase(index_, BANK_SIZE), scheduler{scheduler_} { + const VkBufferCreateInfo buffer_ci = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = QUERY_SIZE * BANK_SIZE, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + }; + buffer = memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal); + } + ~TFBQueryBank() = default; + void Reset() { + ASSERT(references == 0); + BankBase::Reset(); + } + void Sync(StagingBufferRef& stagging_buffer, size_t extra_offset, size_t start, size_t size) { + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start, + size](vk::CommandBuffer cmdbuf) { + std::array copy{VkBufferCopy{ + .srcOffset = start * QUERY_SIZE, + .dstOffset = extra_offset, + .size = size * QUERY_SIZE, + }}; + cmdbuf.CopyBuffer(*buffer, dst_buffer, copy); + }); + } + size_t GetIndex() const { + return index; + } + VkBuffer GetBuffer() const { + return *buffer; + } +private: + Scheduler& scheduler; + vk::Buffer buffer; }; using BaseStreamer = VideoCommon::SimpleStreamer; @@ -413,7 +513,7 @@ private: size_t banks_set = query->size_banks; size_t start_slot = query->start_slot; for (size_t i = 0; i < banks_set; i++) { - auto& the_bank = bank_pool.GetBank(bank_id); + auto& the_bank = bank_pool.elems[bank_id]; size_t amount = (std::min)(the_bank.Size() - start_slot, size_slots); func(&the_bank, start_slot, amount); bank_id = the_bank.next_bank - 1; @@ -439,20 +539,19 @@ private: }); } for (auto& cont : indexer) { - func(&bank_pool.GetBank(cont.first), cont.second.first, + func(&bank_pool.elems[cont.first], cont.second.first, cont.second.second - cont.second.first); } } void ReserveBank() { - current_bank_id = - bank_pool.ReserveBank([this](std::deque& queue, size_t index) { - queue.emplace_back(device, index); - }); + current_bank_id = bank_pool.ReserveBank([this](auto& queue, size_t index) { + queue.emplace_back(device, index); + }); if (current_bank) { current_bank->next_bank = current_bank_id + 1; } - current_bank = &bank_pool.GetBank(current_bank_id); + current_bank = &bank_pool.elems[current_bank_id]; current_query_pool = current_bank->GetInnerPool(); } @@ -474,7 +573,7 @@ private: size_t banks_set = current_query->size_banks - 1; bool found = bank_id == current_bank_id; while (!found && banks_set > 0) { - SamplesQueryBank& some_bank = bank_pool.GetBank(bank_id); + SamplesQueryBank& some_bank = bank_pool.elems[bank_id]; bank_id = some_bank.next_bank - 1; found = bank_id == current_bank_id; banks_set--; @@ -577,12 +676,12 @@ private: const Device& device; Scheduler& scheduler; const MemoryAllocator& memory_allocator; - VideoCommon::BankPool bank_pool; - std::deque buffers; + BankPool bank_pool; + boost::container::devector buffers; std::array resolve_table{}; std::array intermediary_table{}; vk::Buffer accumulation_buffer; - std::deque> sync_values_stash; + boost::container::devector> sync_values_stash; std::vector resolve_buffers; // syncing queue @@ -590,7 +689,7 @@ private: // flush levels std::vector pending_flush_queries; - std::deque> pending_flush_sets; + boost::container::devector> pending_flush_sets; // State Machine size_t current_bank_slot; @@ -609,61 +708,6 @@ private: std::unique_ptr queries_prefix_scan_pass; }; -// Transform feedback queries -class TFBQueryBank : public VideoCommon::BankBase { -public: - static constexpr size_t BANK_SIZE = 1024; - static constexpr size_t QUERY_SIZE = 4; - explicit TFBQueryBank(Scheduler& scheduler_, const MemoryAllocator& memory_allocator, - size_t index_) - : BankBase(BANK_SIZE), scheduler{scheduler_}, index{index_} { - const VkBufferCreateInfo buffer_ci = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = QUERY_SIZE * BANK_SIZE, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - }; - buffer = memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal); - } - - ~TFBQueryBank() = default; - - void Reset() override { - ASSERT(references == 0); - VideoCommon::BankBase::Reset(); - } - - void Sync(StagingBufferRef& stagging_buffer, size_t extra_offset, size_t start, size_t size) { - scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start, - size](vk::CommandBuffer cmdbuf) { - std::array copy{VkBufferCopy{ - .srcOffset = start * QUERY_SIZE, - .dstOffset = extra_offset, - .size = size * QUERY_SIZE, - }}; - cmdbuf.CopyBuffer(*buffer, dst_buffer, copy); - }); - } - - size_t GetIndex() const { - return index; - } - - VkBuffer GetBuffer() const { - return *buffer; - } - -private: - Scheduler& scheduler; - const size_t index; - vk::Buffer buffer; -}; - class PrimitivesSucceededStreamer; class TFBCounterStreamer : public BaseStreamer { @@ -753,7 +797,7 @@ public: }); } for (auto& p : sync_values_stash) { - auto& bank = bank_pool.GetBank(p.first); + auto& bank = bank_pool.elems[p.first]; runtime.template SyncValues(p.second, bank.GetBuffer()); } pending_sync.clear(); @@ -813,7 +857,7 @@ public: size_t offset_base = staging_ref.offset; for (auto q : pending_flush_queries) { auto* query = GetQuery(q); - auto& bank = bank_pool.GetBank(query->start_bank_id); + auto& bank = bank_pool.elems[query->start_bank_id]; bank.Sync(staging_ref, offset_base, query->start_slot, 1); offset_base += TFBQueryBank::QUERY_SIZE; bank.CloseReference(); @@ -925,11 +969,10 @@ private: std::pair ProduceCounterBuffer(size_t stream) { if (current_bank == nullptr || current_bank->IsClosed()) { - current_bank_id = - bank_pool.ReserveBank([this](std::deque& queue, size_t index) { - queue.emplace_back(scheduler, memory_allocator, index); - }); - current_bank = &bank_pool.GetBank(current_bank_id); + current_bank_id = bank_pool.ReserveBank([this](auto& queue, size_t index) { + queue.emplace_back(scheduler, memory_allocator, index); + }); + current_bank = &bank_pool.elems[current_bank_id]; } auto [dont_care, other] = current_bank->Reserve(); const size_t slot = other; // workaround to compile bug. @@ -974,7 +1017,7 @@ private: Scheduler& scheduler; const MemoryAllocator& memory_allocator; StagingBufferPool& staging_pool; - VideoCommon::BankPool bank_pool; + BankPool bank_pool; size_t current_bank_id; TFBQueryBank* current_bank; vk::Buffer counters_buffer; @@ -984,8 +1027,8 @@ private: // flush levels std::vector pending_flush_queries; - std::deque download_buffers; - std::deque> pending_flush_sets; + boost::container::devector download_buffers; + boost::container::devector> pending_flush_sets; std::vector free_queue; std::mutex flush_guard; @@ -1167,7 +1210,7 @@ private: // flush levels std::vector pending_flush_queries; - std::deque> pending_flush_sets; + boost::container::devector> pending_flush_sets; std::mutex flush_guard; };