WIP: [video_core] better datastructures (deque -> devector) experiment, remove uneeded overhead from deque() on places where it wasn't needed #2604
17 changed files with 200 additions and 235 deletions
|
@ -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{};
|
||||
};
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()>;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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{};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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{};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue