From 63915bf2de3358029cb5e904f51f6b147b64bfa1 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 6 Jul 2021 22:23:10 +0200 Subject: Fence Manager: Add fences on Reference Count. --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 7 +++++++ src/video_core/renderer_vulkan/vk_rasterizer.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bd4d649cc..687c13009 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -580,6 +580,13 @@ void RasterizerVulkan::SignalSyncPoint(u32 value) { fence_manager.SignalSyncPoint(value); } +void RasterizerVulkan::SignalReference() { + if (!gpu.IsAsync()) { + return; + } + fence_manager.SignalReference(); +} + void RasterizerVulkan::ReleaseFences() { if (!gpu.IsAsync()) { return; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 41459c5c5..5450ccfb5 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -75,6 +75,7 @@ public: void ModifyGPUMemory(GPUVAddr addr, u64 size) override; void SignalSemaphore(GPUVAddr addr, u32 value) override; void SignalSyncPoint(u32 value) override; + void SignalReference() override; void ReleaseFences() override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void WaitForIdle() override; -- cgit v1.2.3 From cf38faee9ba6223721223c0a16b2ece2383bfc9a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 7 Jul 2021 16:42:26 +0200 Subject: Fence Manager: Force ordering on WFI. --- src/video_core/buffer_cache/buffer_cache.h | 95 ++++++++++++++---------- src/video_core/fence_manager.h | 6 ++ src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 + src/video_core/renderer_vulkan/vk_rasterizer.cpp | 4 + 4 files changed, 71 insertions(+), 38 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 2bd86f215..33fa5305e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -152,6 +152,8 @@ public: /// Return true when there are uncommitted buffers to be downloaded [[nodiscard]] bool HasUncommittedFlushes() const noexcept; + void AccumulateFlushes(); + /// Return true when the caller should wait for async downloads [[nodiscard]] bool ShouldWaitAsyncFlushes() const noexcept; @@ -334,6 +336,7 @@ private: std::vector cached_write_buffer_ids; IntervalSet uncommitted_ranges; + std::deque committed_ranges; size_t immediate_buffer_capacity = 0; std::unique_ptr immediate_buffer_alloc; @@ -551,7 +554,19 @@ void BufferCache

::FlushCachedWrites() { template bool BufferCache

::HasUncommittedFlushes() const noexcept { - return !uncommitted_ranges.empty(); + return !uncommitted_ranges.empty() || !committed_ranges.empty(); +} + +template +void BufferCache

::AccumulateFlushes() { + if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { + uncommitted_ranges.clear(); + return; + } + if (uncommitted_ranges.empty()) { + return; + } + committed_ranges.emplace_back(std::move(uncommitted_ranges)); } template @@ -561,8 +576,8 @@ bool BufferCache

::ShouldWaitAsyncFlushes() const noexcept { template void BufferCache

::CommitAsyncFlushesHigh() { - const IntervalSet& intervals = uncommitted_ranges; - if (intervals.empty()) { + AccumulateFlushes(); + if (committed_ranges.empty()) { return; } MICROPROFILE_SCOPE(GPU_DownloadMemory); @@ -570,43 +585,46 @@ void BufferCache

::CommitAsyncFlushesHigh() { boost::container::small_vector, 1> downloads; u64 total_size_bytes = 0; u64 largest_copy = 0; - for (auto& interval : intervals) { - const std::size_t size = interval.upper() - interval.lower(); - const VAddr cpu_addr = interval.lower(); - const VAddr cpu_addr_end = interval.upper(); - ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { - boost::container::small_vector copies; - buffer.ForEachDownloadRange( - cpu_addr, size, false, [&](u64 range_offset, u64 range_size) { - VAddr cpu_addr_base = buffer.CpuAddr() + range_offset; - VAddr cpu_addr_end2 = cpu_addr_base + range_size; - const s64 difference = s64(cpu_addr_end2 - cpu_addr_end); - cpu_addr_end2 -= u64(std::max(difference, 0)); - const s64 difference2 = s64(cpu_addr - cpu_addr_base); - cpu_addr_base += u64(std::max(difference2, 0)); - const u64 new_size = cpu_addr_end2 - cpu_addr_base; - const u64 new_offset = cpu_addr_base - buffer.CpuAddr(); - downloads.push_back({ - BufferCopy{ - .src_offset = new_offset, - .dst_offset = total_size_bytes, - .size = new_size, - }, - buffer_id, + for (const IntervalSet& intervals : committed_ranges) { + for (auto& interval : intervals) { + const std::size_t size = interval.upper() - interval.lower(); + const VAddr cpu_addr = interval.lower(); + const VAddr cpu_addr_end = interval.upper(); + ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { + boost::container::small_vector copies; + buffer.ForEachDownloadRange( + cpu_addr, size, false, [&](u64 range_offset, u64 range_size) { + VAddr cpu_addr_base = buffer.CpuAddr() + range_offset; + VAddr cpu_addr_end2 = cpu_addr_base + range_size; + const s64 difference = s64(cpu_addr_end2 - cpu_addr_end); + cpu_addr_end2 -= u64(std::max(difference, 0)); + const s64 difference2 = s64(cpu_addr - cpu_addr_base); + cpu_addr_base += u64(std::max(difference2, 0)); + const u64 new_size = cpu_addr_end2 - cpu_addr_base; + const u64 new_offset = cpu_addr_base - buffer.CpuAddr(); + downloads.push_back({ + BufferCopy{ + .src_offset = new_offset, + .dst_offset = total_size_bytes, + .size = new_size, + }, + buffer_id, + }); + total_size_bytes += new_size; + largest_copy = std::max(largest_copy, new_size); + constexpr u64 align_mask = ~(32ULL - 1); + const VAddr align_up_address = (cpu_addr_base + 31) & align_mask; + const u64 difference_base = align_up_address - cpu_addr_base; + if (difference_base > new_size) { + return; + } + const u64 fixed_size = new_size - difference_base; + buffer.UnmarkRegionAsGpuModified(align_up_address, fixed_size & align_mask); }); - total_size_bytes += new_size; - largest_copy = std::max(largest_copy, new_size); - constexpr u64 align_mask = ~(32ULL - 1); - const VAddr align_up_address = (cpu_addr_base + 31) & align_mask; - const u64 difference_base = align_up_address - cpu_addr_base; - if (difference_base > new_size) { - return; - } - const u64 fixed_size = new_size - difference_base; - buffer.UnmarkRegionAsGpuModified(align_up_address, fixed_size & align_mask); - }); - }); + }); + } } + committed_ranges.clear(); if (downloads.empty()) { return; } @@ -644,6 +662,7 @@ void BufferCache

::CommitAsyncFlushes() { CommitAsyncFlushesHigh(); } else { uncommitted_ranges.clear(); + committed_ranges.clear(); } } diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index cd17667cb..b702b2015 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -54,6 +54,12 @@ public: delayed_destruction_ring.Tick(); } + // Unlike other fences, this one doesn't + void SignalOrdering() { + std::scoped_lock lock{buffer_cache.mutex}; + buffer_cache.AccumulateFlushes(); + } + void SignalReference() { // Only sync references on High if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 64869abf9..514c2f47d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -657,6 +657,10 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::WaitForIdle() { glMemoryBarrier(GL_ALL_BARRIER_BITS); + if (!gpu.IsAsync()) { + return; + } + fence_manager.SignalOrdering(); } void RasterizerOpenGL::FragmentBarrier() { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 687c13009..392de47d0 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -619,6 +619,10 @@ void RasterizerVulkan::WaitForIdle() { cmdbuf.SetEvent(event, flags); cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {}); }); + if (!gpu.IsAsync()) { + return; + } + fence_manager.SignalOrdering(); } void RasterizerVulkan::FragmentBarrier() { -- cgit v1.2.3 From 4a0951733621a89a5048e7ff5d44ea4f4fbc7461 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 8 Jul 2021 03:05:23 +0200 Subject: Fence Manager: remove reference fencing. --- src/video_core/fence_manager.h | 23 ++--------------------- src/video_core/renderer_opengl/gl_rasterizer.cpp | 7 ++----- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 7 ++----- 3 files changed, 6 insertions(+), 31 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index b702b2015..34dc6c596 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -60,23 +60,6 @@ public: buffer_cache.AccumulateFlushes(); } - void SignalReference() { - // Only sync references on High - if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { - return; - } - TryReleasePendingFences(); - const bool should_flush = ShouldFlush(); - CommitAsyncFlushes(); - TFence new_fence = CreateFence(0, 0, !should_flush); - fences.push(new_fence); - QueueFence(new_fence); - if (should_flush) { - rasterizer.FlushCommands(); - } - rasterizer.SyncGuestHost(); - } - void SignalSemaphore(GPUVAddr addr, u32 value) { TryReleasePendingFences(); const bool should_flush = ShouldFlush(); @@ -111,10 +94,8 @@ public: } PopAsyncFlushes(); if (current_fence->IsSemaphore()) { - if (current_fence->GetAddress() != 0) { - gpu_memory.template Write(current_fence->GetAddress(), - current_fence->GetPayload()); - } + gpu_memory.template Write(current_fence->GetAddress(), + current_fence->GetPayload()); } else { gpu.IncrementSyncPoint(current_fence->GetPayload()); } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 514c2f47d..a4ed8f68f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -638,7 +638,7 @@ void RasterizerOpenGL::SignalReference() { if (!gpu.IsAsync()) { return; } - fence_manager.SignalReference(); + fence_manager.SignalOrdering(); } void RasterizerOpenGL::ReleaseFences() { @@ -657,10 +657,7 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::WaitForIdle() { glMemoryBarrier(GL_ALL_BARRIER_BITS); - if (!gpu.IsAsync()) { - return; - } - fence_manager.SignalOrdering(); + SignalReference(); } void RasterizerOpenGL::FragmentBarrier() { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 392de47d0..9ea4b6653 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -584,7 +584,7 @@ void RasterizerVulkan::SignalReference() { if (!gpu.IsAsync()) { return; } - fence_manager.SignalReference(); + fence_manager.SignalOrdering(); } void RasterizerVulkan::ReleaseFences() { @@ -619,10 +619,7 @@ void RasterizerVulkan::WaitForIdle() { cmdbuf.SetEvent(event, flags); cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {}); }); - if (!gpu.IsAsync()) { - return; - } - fence_manager.SignalOrdering(); + SignalReference(); } void RasterizerVulkan::FragmentBarrier() { -- cgit v1.2.3