mirror of
https://github.com/yuzu-mirror/yuzu.git
synced 2024-09-02 10:59:07 +01:00
Fence Manager: Add fences on Reference Count.
This commit is contained in:
parent
35327dbde3
commit
63915bf2de
8 changed files with 57 additions and 6 deletions
|
@ -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),
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue