Browse Source

[TEST] Refinements on RAII

vk-experiments9
CamilleLaVey 5 days ago
parent
commit
9289f5f55a
  1. 6
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  2. 2
      src/video_core/renderer_vulkan/vk_scheduler.cpp
  3. 2
      src/video_core/texture_cache/texture_cache.h
  4. 1
      src/video_core/vulkan_common/vulkan_device.cpp
  5. 74
      src/video_core/vulkan_common/vulkan_wrapper.cpp
  6. 6
      src/video_core/vulkan_common/vulkan_wrapper.h

6
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -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;
});
}
@ -892,6 +895,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();

2
src/video_core/renderer_vulkan/vk_scheduler.cpp

@ -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); });
@ -322,6 +323,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{

2
src/video_core/texture_cache/texture_cache.h

@ -969,7 +969,7 @@ void TextureCache<P>::CommitAsyncFlushes() {
template <class P>
void TextureCache<P>::PopAsyncFlushes() {
FlushEvictionDownloads();
TickEvictionDownloads(runtime.CompletedSyncPoint());
if (committed_downloads.empty()) {
return;
}

1
src/video_core/vulkan_common/vulkan_device.cpp

@ -770,6 +770,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
Device::~Device() {
ShutdownGPULogging();
vk::FlushDeletionQueue();
vmaDestroyAllocator(allocator);
}

74
src/video_core/vulkan_common/vulkan_wrapper.cpp

@ -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) {
@ -515,14 +570,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);
}
}
@ -544,8 +611,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);
}
}

6
src/video_core/vulkan_common/vulkan_wrapper.h

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

Loading…
Cancel
Save