diff options
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 16 | ||||
| -rw-r--r-- | src/video_core/fence_manager.h | 24 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 1 |
8 files changed, 57 insertions, 6 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index dc2b1f447..3faa7e0d0 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -586,7 +586,9 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 586 | cpu_addr_base += u64(std::max<s64>(difference2, 0)); | 586 | cpu_addr_base += u64(std::max<s64>(difference2, 0)); |
| 587 | const u64 new_size = cpu_addr_end2 - cpu_addr_base; | 587 | const u64 new_size = cpu_addr_end2 - cpu_addr_base; |
| 588 | const u64 new_offset = cpu_addr_base - buffer.CpuAddr(); | 588 | const u64 new_offset = cpu_addr_base - buffer.CpuAddr(); |
| 589 | ASSERT(!IsRegionCpuModified(cpu_addr_base, new_size)); | 589 | if (IsRegionCpuModified(cpu_addr_base, new_size)) { |
| 590 | return; | ||
| 591 | } | ||
| 590 | downloads.push_back({ | 592 | downloads.push_back({ |
| 591 | BufferCopy{ | 593 | BufferCopy{ |
| 592 | .src_offset = new_offset, | 594 | .src_offset = new_offset, |
| @@ -596,8 +598,15 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 596 | buffer_id, | 598 | buffer_id, |
| 597 | }); | 599 | }); |
| 598 | total_size_bytes += new_size; | 600 | total_size_bytes += new_size; |
| 599 | buffer.UnmarkRegionAsGpuModified(cpu_addr_base, new_size); | ||
| 600 | largest_copy = std::max(largest_copy, new_size); | 601 | largest_copy = std::max(largest_copy, new_size); |
| 602 | constexpr u64 align_mask = ~(32ULL - 1); | ||
| 603 | const VAddr align_up_address = (cpu_addr_base + 31) & align_mask; | ||
| 604 | const u64 difference = align_up_address - cpu_addr_base; | ||
| 605 | if (difference > new_size) { | ||
| 606 | return; | ||
| 607 | } | ||
| 608 | const u64 fixed_size = new_size - difference; | ||
| 609 | buffer.UnmarkRegionAsGpuModified(align_up_address, fixed_size & align_mask); | ||
| 601 | }); | 610 | }); |
| 602 | }); | 611 | }); |
| 603 | } | 612 | } |
| @@ -1380,7 +1389,8 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s | |||
| 1380 | // Binding the whole map range would be technically correct, but games have large maps that make | 1389 | // Binding the whole map range would be technically correct, but games have large maps that make |
| 1381 | // this approach unaffordable for now. | 1390 | // this approach unaffordable for now. |
| 1382 | static constexpr u32 arbitrary_extra_bytes = 0xc000; | 1391 | static constexpr u32 arbitrary_extra_bytes = 0xc000; |
| 1383 | const u32 bytes_to_map_end = static_cast<u32>(gpu_memory.BytesToMapEnd(gpu_addr)); | 1392 | const u32 bytes_to_map_end = |
| 1393 | std::max(size, static_cast<u32>(gpu_memory.BytesToMapEnd(gpu_addr))); | ||
| 1384 | const Binding binding{ | 1394 | const Binding binding{ |
| 1385 | .cpu_addr = *cpu_addr, | 1395 | .cpu_addr = *cpu_addr, |
| 1386 | .size = std::min(size + arbitrary_extra_bytes, bytes_to_map_end), | 1396 | .size = std::min(size + arbitrary_extra_bytes, bytes_to_map_end), |
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index f055b61e9..cd17667cb 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <queue> | 8 | #include <queue> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "video_core/delayed_destruction_ring.h" | 13 | #include "video_core/delayed_destruction_ring.h" |
| 13 | #include "video_core/gpu.h" | 14 | #include "video_core/gpu.h" |
| @@ -53,6 +54,23 @@ public: | |||
| 53 | delayed_destruction_ring.Tick(); | 54 | delayed_destruction_ring.Tick(); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | void SignalReference() { | ||
| 58 | // Only sync references on High | ||
| 59 | if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | TryReleasePendingFences(); | ||
| 63 | const bool should_flush = ShouldFlush(); | ||
| 64 | CommitAsyncFlushes(); | ||
| 65 | TFence new_fence = CreateFence(0, 0, !should_flush); | ||
| 66 | fences.push(new_fence); | ||
| 67 | QueueFence(new_fence); | ||
| 68 | if (should_flush) { | ||
| 69 | rasterizer.FlushCommands(); | ||
| 70 | } | ||
| 71 | rasterizer.SyncGuestHost(); | ||
| 72 | } | ||
| 73 | |||
| 56 | void SignalSemaphore(GPUVAddr addr, u32 value) { | 74 | void SignalSemaphore(GPUVAddr addr, u32 value) { |
| 57 | TryReleasePendingFences(); | 75 | TryReleasePendingFences(); |
| 58 | const bool should_flush = ShouldFlush(); | 76 | const bool should_flush = ShouldFlush(); |
| @@ -87,8 +105,10 @@ public: | |||
| 87 | } | 105 | } |
| 88 | PopAsyncFlushes(); | 106 | PopAsyncFlushes(); |
| 89 | if (current_fence->IsSemaphore()) { | 107 | if (current_fence->IsSemaphore()) { |
| 90 | gpu_memory.template Write<u32>(current_fence->GetAddress(), | 108 | if (current_fence->GetAddress() != 0) { |
| 91 | current_fence->GetPayload()); | 109 | gpu_memory.template Write<u32>(current_fence->GetAddress(), |
| 110 | current_fence->GetPayload()); | ||
| 111 | } | ||
| 92 | } else { | 112 | } else { |
| 93 | gpu.IncrementSyncPoint(current_fence->GetPayload()); | 113 | gpu.IncrementSyncPoint(current_fence->GetPayload()); |
| 94 | } | 114 | } |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 35cc561be..f317ddc2b 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -268,11 +268,13 @@ void GPU::CallPullerMethod(const MethodCall& method_call) { | |||
| 268 | case BufferMethods::SemaphoreAddressHigh: | 268 | case BufferMethods::SemaphoreAddressHigh: |
| 269 | case BufferMethods::SemaphoreAddressLow: | 269 | case BufferMethods::SemaphoreAddressLow: |
| 270 | case BufferMethods::SemaphoreSequence: | 270 | case BufferMethods::SemaphoreSequence: |
| 271 | case BufferMethods::RefCnt: | ||
| 272 | case BufferMethods::UnkCacheFlush: | 271 | case BufferMethods::UnkCacheFlush: |
| 273 | case BufferMethods::WrcacheFlush: | 272 | case BufferMethods::WrcacheFlush: |
| 274 | case BufferMethods::FenceValue: | 273 | case BufferMethods::FenceValue: |
| 275 | break; | 274 | break; |
| 275 | case BufferMethods::RefCnt: | ||
| 276 | rasterizer->SignalReference(); | ||
| 277 | break; | ||
| 276 | case BufferMethods::FenceAction: | 278 | case BufferMethods::FenceAction: |
| 277 | ProcessFenceActionMethod(); | 279 | ProcessFenceActionMethod(); |
| 278 | break; | 280 | break; |
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 0cec4225b..67aef6000 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -63,6 +63,9 @@ public: | |||
| 63 | /// Signal a GPU based syncpoint as a fence | 63 | /// Signal a GPU based syncpoint as a fence |
| 64 | virtual void SignalSyncPoint(u32 value) = 0; | 64 | virtual void SignalSyncPoint(u32 value) = 0; |
| 65 | 65 | ||
| 66 | /// Signal a GPU based reference as point | ||
| 67 | virtual void SignalReference() = 0; | ||
| 68 | |||
| 66 | /// Release all pending fences. | 69 | /// Release all pending fences. |
| 67 | virtual void ReleaseFences() = 0; | 70 | virtual void ReleaseFences() = 0; |
| 68 | 71 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 07ad0e205..64869abf9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -634,6 +634,13 @@ void RasterizerOpenGL::SignalSyncPoint(u32 value) { | |||
| 634 | fence_manager.SignalSyncPoint(value); | 634 | fence_manager.SignalSyncPoint(value); |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | void RasterizerOpenGL::SignalReference() { | ||
| 638 | if (!gpu.IsAsync()) { | ||
| 639 | return; | ||
| 640 | } | ||
| 641 | fence_manager.SignalReference(); | ||
| 642 | } | ||
| 643 | |||
| 637 | void RasterizerOpenGL::ReleaseFences() { | 644 | void RasterizerOpenGL::ReleaseFences() { |
| 638 | if (!gpu.IsAsync()) { | 645 | if (!gpu.IsAsync()) { |
| 639 | return; | 646 | return; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 482efed7a..d8df71962 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -83,6 +83,7 @@ public: | |||
| 83 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; | 83 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; |
| 84 | void SignalSemaphore(GPUVAddr addr, u32 value) override; | 84 | void SignalSemaphore(GPUVAddr addr, u32 value) override; |
| 85 | void SignalSyncPoint(u32 value) override; | 85 | void SignalSyncPoint(u32 value) override; |
| 86 | void SignalReference() override; | ||
| 86 | void ReleaseFences() override; | 87 | void ReleaseFences() override; |
| 87 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | 88 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; |
| 88 | void WaitForIdle() override; | 89 | void WaitForIdle() override; |
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) { | |||
| 580 | fence_manager.SignalSyncPoint(value); | 580 | fence_manager.SignalSyncPoint(value); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | void RasterizerVulkan::SignalReference() { | ||
| 584 | if (!gpu.IsAsync()) { | ||
| 585 | return; | ||
| 586 | } | ||
| 587 | fence_manager.SignalReference(); | ||
| 588 | } | ||
| 589 | |||
| 583 | void RasterizerVulkan::ReleaseFences() { | 590 | void RasterizerVulkan::ReleaseFences() { |
| 584 | if (!gpu.IsAsync()) { | 591 | if (!gpu.IsAsync()) { |
| 585 | return; | 592 | 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: | |||
| 75 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; | 75 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; |
| 76 | void SignalSemaphore(GPUVAddr addr, u32 value) override; | 76 | void SignalSemaphore(GPUVAddr addr, u32 value) override; |
| 77 | void SignalSyncPoint(u32 value) override; | 77 | void SignalSyncPoint(u32 value) override; |
| 78 | void SignalReference() override; | ||
| 78 | void ReleaseFences() override; | 79 | void ReleaseFences() override; |
| 79 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | 80 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; |
| 80 | void WaitForIdle() override; | 81 | void WaitForIdle() override; |