WIP: [video_core] better datastructures (deque -> devector) experiment, remove uneeded overhead from deque() on places where it wasn't needed #2604

Closed
Lizzie wants to merge 2 commits from liz-deque-to-devec into master
17 changed files with 200 additions and 235 deletions

View file

@ -1,11 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <deque>
#include <memory>
#include <vector>
#include <type_traits>
#include <boost/container/devector.hpp>
#include "common/common_types.h"
@ -130,8 +133,8 @@ private:
}
}
std::deque<Item> item_pool;
std::deque<size_t> free_items;
std::vector<Item> item_pool;
boost::container::devector<size_t> free_items;
Item* first_item{};
Item* last_item{};
};

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2012 PPSSPP Project
// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -5,7 +8,7 @@
#pragma once
#include <array>
#include <deque>
#include <boost/container/devector.hpp>
namespace Common {
@ -145,7 +148,7 @@ private:
// Points to the next active priority, skipping over ones that have never been used.
Queue* next_nonempty = UnlinkedTag();
// Double-ended queue of threads in this priority level
std::deque<T> data;
boost::container::devector<T> data;
};
/// Special tag used to mark priority levels that have never been used.

View file

@ -566,7 +566,7 @@ struct System::Impl {
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
gpu_dirty_memory_managers;
std::deque<std::vector<u8>> user_channel;
boost::container::devector<std::vector<u8>> user_channel;
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
@ -976,7 +976,7 @@ void System::ExecuteProgram(std::size_t program_index) {
}
}
std::deque<std::vector<u8>>& System::GetUserChannel() {
boost::container::devector<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}

View file

@ -14,6 +14,7 @@
#include <span>
#include <string>
#include <vector>
#include <boost/container/devector.hpp>
#include "common/common_types.h"
#include "core/file_sys/vfs/vfs_types.h"
@ -426,7 +427,7 @@ public:
* Gets a reference to the user channel stack.
* It is used to transfer data between programs.
*/
[[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
[[nodiscard]] boost::container::devector<std::vector<u8>>& GetUserChannel();
/// Type used for the frontend to designate a callback for System to exit the application.
using ExitCallback = std::function<void()>;

View file

@ -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-2.0-or-later
@ -6,9 +9,9 @@
#include <array>
#include <atomic>
#include <bit>
#include <deque>
#include <memory>
#include <mutex>
#include <boost/container/devector.hpp>
#include "common/common_types.h"
#include "common/range_mutex.h"
@ -162,8 +165,8 @@ private:
// Process memory interfaces
std::deque<size_t> id_pool;
std::deque<Memory::Memory*> registered_processes;
boost::container::devector<size_t> id_pool;
boost::container::devector<Memory::Memory*> registered_processes;
// Memory protection management

View file

@ -4,7 +4,7 @@
#include <atomic>
#include <limits>
#include <memory>
#include <type_traits>
#include <boost/container/devector.hpp>
#include "common/address_space.h"
#include "common/address_space.inc"
@ -119,8 +119,8 @@ private:
u32 value{};
};
std::deque<Entry> storage;
std::deque<u32> free_entries;
boost::container::devector<Entry> storage;
boost::container::devector<u32> free_entries;
};
struct EmptyAllocator {

View file

@ -9,6 +9,7 @@
#include <deque>
#include <mutex>
#include <stack>
#include <boost/container/devector.hpp>
#include "common/math_util.h"
#include "core/hle/service/apm/apm_controller.h"
@ -95,9 +96,9 @@ struct Applet {
bool request_exit_to_library_applet_at_execute_next_program_enabled{};
// Channels
std::deque<std::vector<u8>> user_channel_launch_parameter{};
std::deque<std::vector<u8>> preselected_user_launch_parameter{};
std::deque<std::vector<u8>> friend_invitation_storage_channel{};
boost::container::devector<std::vector<u8>> user_channel_launch_parameter{};
boost::container::devector<std::vector<u8>> preselected_user_launch_parameter{};
boost::container::devector<std::vector<u8>> friend_invitation_storage_channel{};
// Context Stack
std::stack<SharedPointer<IStorage>> context_stack{};

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -13,12 +16,12 @@
// https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6
//
#include <deque>
#include <map>
#include <span>
#include <unordered_map>
#include <variant>
#include <vector>
#include <boost/container/small_vector.hpp>
#include <boost/container/devector.hpp>
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/opcodes.h"
@ -370,7 +373,7 @@ void VisitBlock(Pass& pass, IR::Block* block) {
}
IR::Type GetConcreteType(IR::Inst* inst) {
std::deque<IR::Inst*> queue;
boost::container::devector<IR::Inst*> queue;
queue.push_back(inst);
while (!queue.empty()) {
IR::Inst* current = queue.front();

View file

@ -6,15 +6,11 @@
#pragma once
#include <algorithm>
#include <array>
#include <functional>
#include <memory>
#include <mutex>
#include <numeric>
#include <span>
#include <unordered_map>
#include <vector>
#include <boost/container/deque.hpp>
#include <boost/container/devector.hpp>
#include "common/common_types.h"
#include "common/div_ceil.h"
@ -455,15 +451,14 @@ private:
MemoryTracker memory_tracker;
Common::RangeSet<DAddr> uncommitted_gpu_modified_ranges;
Common::RangeSet<DAddr> gpu_modified_ranges;
std::deque<Common::RangeSet<DAddr>> committed_gpu_modified_ranges;
// Async Buffers
Common::OverlapRangeSet<DAddr> async_downloads;
std::deque<std::optional<Async_Buffer>> async_buffers;
std::deque<boost::container::small_vector<BufferCopy, 4>> pending_downloads;
std::optional<Async_Buffer> current_buffer;
std::deque<Async_Buffer> async_buffers_death_ring;
std::vector<Async_Buffer> async_buffers_death_ring;
std::vector<Common::RangeSet<DAddr>> committed_gpu_modified_ranges;
boost::container::devector<std::optional<Async_Buffer>> async_buffers;
boost::container::devector<boost::container::small_vector<BufferCopy, 4>> pending_downloads;
size_t immediate_buffer_capacity = 0;
Common::ScratchBuffer<u8> immediate_buffer_alloc;

View file

@ -8,11 +8,11 @@
#include <algorithm>
#include <bit>
#include <deque>
#include <limits>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <boost/container/devector.hpp>
#include "common/alignment.h"
#include "common/common_types.h"
@ -289,9 +289,8 @@ private:
return on_return();
}
std::deque<std::array<Manager, MANAGER_POOL_SIZE>> manager_pool;
std::deque<Manager*> free_managers;
boost::container::devector<std::array<Manager, MANAGER_POOL_SIZE>> manager_pool;
boost::container::devector<Manager*> free_managers;
std::array<Manager*, NUM_HIGH_PAGES> top_tier{};
std::unordered_set<u32> cached_pages;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -9,6 +12,7 @@
#include <mutex>
#include <thread>
#include <vector>
#include <boost/container/devector.hpp>
#include "common/bit_field.h"
#include "common/common_funcs.h"
@ -131,7 +135,7 @@ private:
std::mutex command_mutex;
std::condition_variable_any command_cv;
std::deque<ChCommandHeaderList> command_lists;
boost::container::devector<ChCommandHeaderList> command_lists;
std::jthread thread;
ThiRegisters thi_regs{};

View file

@ -10,6 +10,7 @@
#include <condition_variable>
#include <list>
#include <memory>
#include <boost/container/devector.hpp>
#include "common/assert.h"
#include "common/settings.h"
@ -378,8 +379,8 @@ struct GPU::Impl {
Tegra::Control::ChannelState* current_channel;
s32 bound_channel{-1};
std::deque<size_t> free_swap_counters;
std::deque<size_t> request_swap_counters;
boost::container::devector<size_t> free_swap_counters;
std::vector<size_t> request_swap_counters;
std::mutex request_swap_mutex;
};

View file

@ -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 <atomic>
#include <deque>
#include <utility>
#include "common/common_types.h"
namespace VideoCommon {
class BankBase {
protected:
const size_t base_bank_size{};
size_t bank_size{};
std::atomic<size_t> 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<bool, size_t> 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 <typename BankType>
class BankPool {
private:
std::deque<BankType> bank_pool;
std::deque<size_t> bank_indices;
public:
BankPool() = default;
~BankPool() = default;
// Reserve a bank from the pool and return its index
template <typename Func>
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

View file

@ -7,11 +7,12 @@
#pragma once
#include <array>
#include <deque>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <utility>
#include <boost/container/devector.hpp>
#include <boost/container/small_vector.hpp>
#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<size_t> pending_sync;
std::vector<size_t> pending_sync;
};
template <typename Traits>
@ -168,7 +168,7 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers;
u64 streamer_mask;
std::mutex flush_guard;
std::deque<u64> flushes_pending;
boost::container::devector<u64> flushes_pending;
std::vector<QueryCacheBase<Traits>::QueryLocation> pending_unregister;
};

View file

@ -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 {

View file

@ -13,6 +13,8 @@
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/container/devector.hpp>
#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<bool, size_t> 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<size_t> references{};
};
template<typename T>
struct BankPool {
// Reserve a bank from the pool and return its index
template <typename Func>
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<T> elems;
boost::container::devector<size_t> 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<u64, BANK_SIZE>& 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<u64, BANK_SIZE> 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<VkBufferCopy, 1> 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<VideoCommon::HostQueryBase>;
@ -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<SamplesQueryBank>& 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<SamplesQueryBank> bank_pool;
std::deque<vk::Buffer> buffers;
BankPool<SamplesQueryBank> bank_pool;
boost::container::devector<vk::Buffer> buffers;
std::array<size_t, 32> resolve_table{};
std::array<size_t, 32> intermediary_table{};
vk::Buffer accumulation_buffer;
std::deque<std::vector<HostSyncValues>> sync_values_stash;
boost::container::devector<std::vector<HostSyncValues>> sync_values_stash;
std::vector<size_t> resolve_buffers;
// syncing queue
@ -590,7 +689,7 @@ private:
// flush levels
std::vector<size_t> pending_flush_queries;
std::deque<std::vector<size_t>> pending_flush_sets;
boost::container::devector<std::vector<size_t>> pending_flush_sets;
// State Machine
size_t current_bank_slot;
@ -609,61 +708,6 @@ private:
std::unique_ptr<QueriesPrefixScanPass> 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<VkBufferCopy, 1> 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<HostSyncValues>(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<size_t, size_t> ProduceCounterBuffer(size_t stream) {
if (current_bank == nullptr || current_bank->IsClosed()) {
current_bank_id =
bank_pool.ReserveBank([this](std::deque<TFBQueryBank>& 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<TFBQueryBank> bank_pool;
BankPool<TFBQueryBank> bank_pool;
size_t current_bank_id;
TFBQueryBank* current_bank;
vk::Buffer counters_buffer;
@ -984,8 +1027,8 @@ private:
// flush levels
std::vector<size_t> pending_flush_queries;
std::deque<StagingBufferRef> download_buffers;
std::deque<std::vector<size_t>> pending_flush_sets;
boost::container::devector<StagingBufferRef> download_buffers;
boost::container::devector<std::vector<size_t>> pending_flush_sets;
std::vector<StagingBufferRef> free_queue;
std::mutex flush_guard;
@ -1167,7 +1210,7 @@ private:
// flush levels
std::vector<size_t> pending_flush_queries;
std::deque<std::vector<size_t>> pending_flush_sets;
boost::container::devector<std::vector<size_t>> pending_flush_sets;
std::mutex flush_guard;
};

View file

@ -10,6 +10,7 @@
#include <deque>
#include <memory>
#include <string>
#include <boost/container/devector.hpp>
#include <QList>
#include <QObject>
@ -92,7 +93,7 @@ private:
std::mutex lock;
std::condition_variable cv;
std::deque<std::function<void(GameList*)>> queued_events;
boost::container::devector<std::function<void(GameList*)>> queued_events;
std::atomic_bool stop_requested = false;
Common::Event processing_completed;