Fence Manager: Add fences on Reference Count.

This commit is contained in:
Fernando Sahmkow 2021-07-06 22:23:10 +02:00
parent 35327dbde3
commit 63915bf2de
8 changed files with 57 additions and 6 deletions

View file

@ -586,7 +586,9 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
cpu_addr_base += u64(std::max<s64>(difference2, 0)); cpu_addr_base += u64(std::max<s64>(difference2, 0));
const u64 new_size = cpu_addr_end2 - cpu_addr_base; const u64 new_size = cpu_addr_end2 - cpu_addr_base;
const u64 new_offset = cpu_addr_base - buffer.CpuAddr(); const u64 new_offset = cpu_addr_base - buffer.CpuAddr();
ASSERT(!IsRegionCpuModified(cpu_addr_base, new_size)); if (IsRegionCpuModified(cpu_addr_base, new_size)) {
return;
}
downloads.push_back({ downloads.push_back({
BufferCopy{ BufferCopy{
.src_offset = new_offset, .src_offset = new_offset,
@ -596,8 +598,15 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
buffer_id, buffer_id,
}); });
total_size_bytes += new_size; total_size_bytes += new_size;
buffer.UnmarkRegionAsGpuModified(cpu_addr_base, new_size);
largest_copy = std::max(largest_copy, 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 = align_up_address - cpu_addr_base;
if (difference > new_size) {
return;
}
const u64 fixed_size = new_size - difference;
buffer.UnmarkRegionAsGpuModified(align_up_address, fixed_size & align_mask);
}); });
}); });
} }
@ -1380,7 +1389,8 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
// Binding the whole map range would be technically correct, but games have large maps that make // Binding the whole map range would be technically correct, but games have large maps that make
// this approach unaffordable for now. // this approach unaffordable for now.
static constexpr u32 arbitrary_extra_bytes = 0xc000; static constexpr u32 arbitrary_extra_bytes = 0xc000;
const u32 bytes_to_map_end = static_cast<u32>(gpu_memory.BytesToMapEnd(gpu_addr)); const u32 bytes_to_map_end =
std::max(size, static_cast<u32>(gpu_memory.BytesToMapEnd(gpu_addr)));
const Binding binding{ const Binding binding{
.cpu_addr = *cpu_addr, .cpu_addr = *cpu_addr,
.size = std::min(size + arbitrary_extra_bytes, bytes_to_map_end), .size = std::min(size + arbitrary_extra_bytes, bytes_to_map_end),

View file

@ -8,6 +8,7 @@
#include <queue> #include <queue>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "video_core/delayed_destruction_ring.h" #include "video_core/delayed_destruction_ring.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
@ -53,6 +54,23 @@ public:
delayed_destruction_ring.Tick(); delayed_destruction_ring.Tick();
} }
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) { void SignalSemaphore(GPUVAddr addr, u32 value) {
TryReleasePendingFences(); TryReleasePendingFences();
const bool should_flush = ShouldFlush(); const bool should_flush = ShouldFlush();
@ -87,8 +105,10 @@ public:
} }
PopAsyncFlushes(); PopAsyncFlushes();
if (current_fence->IsSemaphore()) { if (current_fence->IsSemaphore()) {
gpu_memory.template Write<u32>(current_fence->GetAddress(), if (current_fence->GetAddress() != 0) {
current_fence->GetPayload()); gpu_memory.template Write<u32>(current_fence->GetAddress(),
current_fence->GetPayload());
}
} else { } else {
gpu.IncrementSyncPoint(current_fence->GetPayload()); gpu.IncrementSyncPoint(current_fence->GetPayload());
} }

View file

@ -268,11 +268,13 @@ void GPU::CallPullerMethod(const MethodCall& method_call) {
case BufferMethods::SemaphoreAddressHigh: case BufferMethods::SemaphoreAddressHigh:
case BufferMethods::SemaphoreAddressLow: case BufferMethods::SemaphoreAddressLow:
case BufferMethods::SemaphoreSequence: case BufferMethods::SemaphoreSequence:
case BufferMethods::RefCnt:
case BufferMethods::UnkCacheFlush: case BufferMethods::UnkCacheFlush:
case BufferMethods::WrcacheFlush: case BufferMethods::WrcacheFlush:
case BufferMethods::FenceValue: case BufferMethods::FenceValue:
break; break;
case BufferMethods::RefCnt:
rasterizer->SignalReference();
break;
case BufferMethods::FenceAction: case BufferMethods::FenceAction:
ProcessFenceActionMethod(); ProcessFenceActionMethod();
break; break;

View file

@ -63,6 +63,9 @@ public:
/// Signal a GPU based syncpoint as a fence /// Signal a GPU based syncpoint as a fence
virtual void SignalSyncPoint(u32 value) = 0; virtual void SignalSyncPoint(u32 value) = 0;
/// Signal a GPU based reference as point
virtual void SignalReference() = 0;
/// Release all pending fences. /// Release all pending fences.
virtual void ReleaseFences() = 0; virtual void ReleaseFences() = 0;

View file

@ -634,6 +634,13 @@ void RasterizerOpenGL::SignalSyncPoint(u32 value) {
fence_manager.SignalSyncPoint(value); fence_manager.SignalSyncPoint(value);
} }
void RasterizerOpenGL::SignalReference() {
if (!gpu.IsAsync()) {
return;
}
fence_manager.SignalReference();
}
void RasterizerOpenGL::ReleaseFences() { void RasterizerOpenGL::ReleaseFences() {
if (!gpu.IsAsync()) { if (!gpu.IsAsync()) {
return; return;

View file

@ -83,6 +83,7 @@ public:
void ModifyGPUMemory(GPUVAddr addr, u64 size) override; void ModifyGPUMemory(GPUVAddr addr, u64 size) override;
void SignalSemaphore(GPUVAddr addr, u32 value) override; void SignalSemaphore(GPUVAddr addr, u32 value) override;
void SignalSyncPoint(u32 value) override; void SignalSyncPoint(u32 value) override;
void SignalReference() override;
void ReleaseFences() override; void ReleaseFences() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void WaitForIdle() override; void WaitForIdle() override;

View file

@ -580,6 +580,13 @@ void RasterizerVulkan::SignalSyncPoint(u32 value) {
fence_manager.SignalSyncPoint(value); fence_manager.SignalSyncPoint(value);
} }
void RasterizerVulkan::SignalReference() {
if (!gpu.IsAsync()) {
return;
}
fence_manager.SignalReference();
}
void RasterizerVulkan::ReleaseFences() { void RasterizerVulkan::ReleaseFences() {
if (!gpu.IsAsync()) { if (!gpu.IsAsync()) {
return; return;

View file

@ -75,6 +75,7 @@ public:
void ModifyGPUMemory(GPUVAddr addr, u64 size) override; void ModifyGPUMemory(GPUVAddr addr, u64 size) override;
void SignalSemaphore(GPUVAddr addr, u32 value) override; void SignalSemaphore(GPUVAddr addr, u32 value) override;
void SignalSyncPoint(u32 value) override; void SignalSyncPoint(u32 value) override;
void SignalReference() override;
void ReleaseFences() override; void ReleaseFences() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void WaitForIdle() override; void WaitForIdle() override;