mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-20 23:09:06 +00:00
[TEST] Refinements on RAII
This commit is contained in:
@@ -230,6 +230,9 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
|
||||
if (freed < bytes) {
|
||||
freed += buffer_cache.ReclaimMemory(bytes - freed, false);
|
||||
}
|
||||
auto& master_semaphore = scheduler.GetMasterSemaphore();
|
||||
master_semaphore.Refresh();
|
||||
vk::TickDeletionQueue(master_semaphore.KnownGpuTick());
|
||||
return freed;
|
||||
});
|
||||
}
|
||||
@@ -896,6 +899,9 @@ void RasterizerVulkan::FlushCommands() {
|
||||
|
||||
void RasterizerVulkan::TickFrame() {
|
||||
draw_counter = 0;
|
||||
auto& master_semaphore = scheduler.GetMasterSemaphore();
|
||||
master_semaphore.Refresh();
|
||||
vk::TickDeletionQueue(master_semaphore.KnownGpuTick());
|
||||
guest_descriptor_queue.TickFrame();
|
||||
compute_pass_descriptor_queue.TickFrame();
|
||||
fence_manager.TickFrame();
|
||||
|
||||
@@ -47,6 +47,7 @@ Scheduler::Scheduler(const Device& device_, StateTracker& state_tracker_)
|
||||
master_semaphore{std::make_unique<MasterSemaphore>(device)},
|
||||
command_pool{std::make_unique<CommandPool>(*master_semaphore, device)} {
|
||||
|
||||
vk::SetDeletionTimeline(master_semaphore->CurrentTick());
|
||||
AcquireNewChunk();
|
||||
AllocateWorkerCommandBuffer();
|
||||
worker_thread = std::jthread([this](std::stop_token token) { WorkerThread(token); });
|
||||
@@ -384,6 +385,7 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
|
||||
InvalidateState();
|
||||
|
||||
const u64 signal_value = master_semaphore->NextTick();
|
||||
vk::SetDeletionTimeline(master_semaphore->CurrentTick());
|
||||
RecordWithUploadBuffer([signal_semaphore, wait_semaphore, signal_value,
|
||||
this](vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) {
|
||||
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||
|
||||
@@ -969,7 +969,7 @@ void TextureCache<P>::CommitAsyncFlushes() {
|
||||
|
||||
template <class P>
|
||||
void TextureCache<P>::PopAsyncFlushes() {
|
||||
FlushEvictionDownloads();
|
||||
TickEvictionDownloads(runtime.CompletedSyncPoint());
|
||||
if (committed_downloads.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -770,6 +770,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
|
||||
Device::~Device() {
|
||||
ShutdownGPULogging();
|
||||
vk::FlushDeletionQueue();
|
||||
vmaDestroyAllocator(allocator);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
@@ -24,6 +27,58 @@ namespace {
|
||||
|
||||
std::thread::id allocator_owner_thread;
|
||||
|
||||
template <typename HandleType>
|
||||
struct PendingRelease {
|
||||
VmaAllocator allocator;
|
||||
HandleType handle;
|
||||
VmaAllocation allocation;
|
||||
u64 timeline;
|
||||
};
|
||||
|
||||
std::mutex deletion_mutex;
|
||||
std::atomic<u64> deletion_timeline{1};
|
||||
std::vector<PendingRelease<VkImage>> pending_images;
|
||||
std::vector<PendingRelease<VkBuffer>> pending_buffers;
|
||||
|
||||
template <typename HandleType>
|
||||
void PushPendingRelease(std::vector<PendingRelease<HandleType>>& pending, VmaAllocator allocator,
|
||||
HandleType handle, VmaAllocation allocation) noexcept {
|
||||
std::scoped_lock lock{deletion_mutex};
|
||||
pending.push_back(PendingRelease<HandleType>{
|
||||
.allocator = allocator,
|
||||
.handle = handle,
|
||||
.allocation = allocation,
|
||||
.timeline = deletion_timeline.load(std::memory_order_acquire),
|
||||
});
|
||||
}
|
||||
|
||||
template <typename HandleType>
|
||||
void ExtractReleased(std::vector<PendingRelease<HandleType>>& pending,
|
||||
std::vector<PendingRelease<HandleType>>& released, u64 completed_value) {
|
||||
const auto split = std::partition(pending.begin(), pending.end(),
|
||||
[completed_value](const PendingRelease<HandleType>& entry) {
|
||||
return entry.timeline > completed_value;
|
||||
});
|
||||
released.assign(split, pending.end());
|
||||
pending.erase(split, pending.end());
|
||||
}
|
||||
|
||||
void DrainDeletionQueue(u64 completed_value) noexcept {
|
||||
std::vector<PendingRelease<VkImage>> images;
|
||||
std::vector<PendingRelease<VkBuffer>> buffers;
|
||||
{
|
||||
std::scoped_lock lock{deletion_mutex};
|
||||
ExtractReleased(pending_images, images, completed_value);
|
||||
ExtractReleased(pending_buffers, buffers, completed_value);
|
||||
}
|
||||
for (const auto& entry : images) {
|
||||
vmaDestroyImage(entry.allocator, entry.handle, entry.allocation);
|
||||
}
|
||||
for (const auto& entry : buffers) {
|
||||
vmaDestroyBuffer(entry.allocator, entry.handle, entry.allocation);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld,
|
||||
Func&& func) {
|
||||
@@ -524,14 +579,26 @@ bool OnAllocatorOwnerThread() noexcept {
|
||||
allocator_owner_thread == std::this_thread::get_id();
|
||||
}
|
||||
|
||||
void SetDeletionTimeline(u64 value) noexcept {
|
||||
deletion_timeline.store(value, std::memory_order_release);
|
||||
}
|
||||
|
||||
void TickDeletionQueue(u64 completed_value) noexcept {
|
||||
DEBUG_ASSERT(OnAllocatorOwnerThread());
|
||||
DrainDeletionQueue(completed_value);
|
||||
}
|
||||
|
||||
void FlushDeletionQueue() noexcept {
|
||||
DrainDeletionQueue((std::numeric_limits<u64>::max)());
|
||||
}
|
||||
|
||||
void Image::SetObjectNameEXT(const char* name) const {
|
||||
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name);
|
||||
}
|
||||
|
||||
void Image::Release() const noexcept {
|
||||
if (handle) {
|
||||
DEBUG_ASSERT(OnAllocatorOwnerThread());
|
||||
vmaDestroyImage(allocator, handle, allocation);
|
||||
PushPendingRelease(pending_images, allocator, handle, allocation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,8 +620,7 @@ void Buffer::SetObjectNameEXT(const char* name) const {
|
||||
|
||||
void Buffer::Release() const noexcept {
|
||||
if (handle) {
|
||||
DEBUG_ASSERT(OnAllocatorOwnerThread());
|
||||
vmaDestroyBuffer(allocator, handle, allocation);
|
||||
PushPendingRelease(pending_buffers, allocator, handle, allocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,12 @@ void SetAllocatorOwnerThread();
|
||||
|
||||
[[nodiscard]] bool OnAllocatorOwnerThread() noexcept;
|
||||
|
||||
void SetDeletionTimeline(u64 value) noexcept;
|
||||
|
||||
void TickDeletionQueue(u64 completed_value) noexcept;
|
||||
|
||||
void FlushDeletionQueue() noexcept;
|
||||
|
||||
/// Throws a Vulkan exception if result is not success.
|
||||
inline void Check(VkResult result) {
|
||||
if (result != VK_SUCCESS) {
|
||||
|
||||
Reference in New Issue
Block a user