forked from ShuriZma/suyu
1
0
Fork 0

FenceManager: Manage syncpoints and rename fences to semaphores.

This commit is contained in:
Fernando Sahmkow 2020-02-19 13:40:37 -04:00
parent 96bb961a64
commit b7bc3c2549
11 changed files with 123 additions and 25 deletions

View File

@ -229,6 +229,13 @@ public:
return true; return true;
} }
bool HasUncommitedFlushes() {
if (uncommited_flushes) {
return true;
}
return false;
}
void PopAsyncFlushes() { void PopAsyncFlushes() {
if (commited_flushes.empty()) { if (commited_flushes.empty()) {
return; return;

View File

@ -405,7 +405,7 @@ void Maxwell3D::ProcessQueryGet() {
switch (regs.query.query_get.operation) { switch (regs.query.query_get.operation) {
case Regs::QueryOperation::Release: case Regs::QueryOperation::Release:
if (regs.query.query_get.fence == 1) { if (regs.query.query_get.fence == 1) {
rasterizer.SignalFence(regs.query.QueryAddress(), regs.query.query_sequence); rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
} else { } else {
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
} }
@ -487,7 +487,7 @@ void Maxwell3D::ProcessSyncPoint() {
const u32 increment = regs.sync_info.increment.Value(); const u32 increment = regs.sync_info.increment.Value();
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
if (increment) { if (increment) {
system.GPU().IncrementSyncPoint(sync_point); rasterizer.SignalSyncPoint(sync_point);
} }
} }

View File

@ -22,7 +22,11 @@ namespace VideoCommon {
class FenceBase { class FenceBase {
public: public:
FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {} FenceBase(u32 payload, bool is_stubbed)
: address{}, payload{payload}, is_semaphore{false}, is_stubbed{is_stubbed} {}
FenceBase(GPUVAddr address, u32 payload, bool is_stubbed)
: address{address}, payload{payload}, is_semaphore{true}, is_stubbed{is_stubbed} {}
constexpr GPUVAddr GetAddress() const { constexpr GPUVAddr GetAddress() const {
return address; return address;
@ -32,22 +36,49 @@ public:
return payload; return payload;
} }
constexpr bool IsSemaphore() const {
return is_semaphore;
}
private: private:
GPUVAddr address; GPUVAddr address;
u32 payload; u32 payload;
bool is_semaphore;
protected:
bool is_stubbed;
}; };
template <typename TFence, typename TTextureCache, typename TTBufferCache> template <typename TFence, typename TTextureCache, typename TTBufferCache>
class FenceManager { class FenceManager {
public: public:
void SignalFence(GPUVAddr addr, u32 value) { void SignalSemaphore(GPUVAddr addr, u32 value) {
TryReleasePendingFences(); TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes(); texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes(); buffer_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(addr, value); TFence new_fence = CreateFence(addr, value, !should_flush);
fences.push(new_fence); fences.push(new_fence);
QueueFence(new_fence); QueueFence(new_fence);
rasterizer.FlushCommands(); if (should_flush) {
rasterizer.FlushCommands();
}
rasterizer.SyncGuestHost();
}
void SignalSyncPoint(u32 value) {
TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(value, !should_flush);
fences.push(new_fence);
QueueFence(new_fence);
if (should_flush) {
rasterizer.FlushCommands();
}
rasterizer.SyncGuestHost(); rasterizer.SyncGuestHost();
} }
@ -62,8 +93,12 @@ public:
texture_cache.PopAsyncFlushes(); texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes(); buffer_cache.PopAsyncFlushes();
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
auto& memory_manager{gpu.MemoryManager()}; if (current_fence->IsSemaphore()) {
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
} else {
gpu.IncrementSyncPoint(current_fence->GetPayload());
}
fences.pop(); fences.pop();
} }
} }
@ -74,7 +109,8 @@ protected:
: system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{ : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{
buffer_cache} {} buffer_cache} {}
virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0; virtual TFence CreateFence(u32 value, bool is_stubbed) = 0;
virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0;
virtual void QueueFence(TFence& fence) = 0; virtual void QueueFence(TFence& fence) = 0;
virtual bool IsFenceSignaled(TFence& fence) = 0; virtual bool IsFenceSignaled(TFence& fence) = 0;
virtual void WaitFence(TFence& fence) = 0; virtual void WaitFence(TFence& fence) = 0;
@ -96,8 +132,12 @@ private:
texture_cache.PopAsyncFlushes(); texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes(); buffer_cache.PopAsyncFlushes();
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
auto& memory_manager{gpu.MemoryManager()}; if (current_fence->IsSemaphore()) {
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
} else {
gpu.IncrementSyncPoint(current_fence->GetPayload());
}
fences.pop(); fences.pop();
} }
} }

View File

@ -49,8 +49,11 @@ public:
/// Records a GPU query and caches it /// Records a GPU query and caches it
virtual void Query(GPUVAddr gpu_addr, QueryType type, std::optional<u64> timestamp) = 0; virtual void Query(GPUVAddr gpu_addr, QueryType type, std::optional<u64> timestamp) = 0;
/// Signal a GPU based fence /// Signal a GPU based semaphore as a fence
virtual void SignalFence(GPUVAddr addr, u32 value) = 0; virtual void SignalSemaphore(GPUVAddr addr, u32 value) = 0;
/// Signal a GPU based syncpoint as a fence
virtual void SignalSyncPoint(u32 value) = 0;
/// Release all pending fences. /// Release all pending fences.
virtual void ReleaseFences() = 0; virtual void ReleaseFences() = 0;

View File

@ -8,17 +8,26 @@
namespace OpenGL { namespace OpenGL {
GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload) GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed)
: VideoCommon::FenceBase(address, payload), sync_object{} {} : VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {}
GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed)
: VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {}
GLInnerFence::~GLInnerFence() = default; GLInnerFence::~GLInnerFence() = default;
void GLInnerFence::Queue() { void GLInnerFence::Queue() {
if (is_stubbed) {
return;
}
ASSERT(sync_object.handle == 0); ASSERT(sync_object.handle == 0);
sync_object.Create(); sync_object.Create();
} }
bool GLInnerFence::IsSignaled() const { bool GLInnerFence::IsSignaled() const {
if (is_stubbed) {
return true;
}
ASSERT(sync_object.handle != 0); ASSERT(sync_object.handle != 0);
GLsizei length; GLsizei length;
GLint sync_status; GLint sync_status;
@ -27,6 +36,9 @@ bool GLInnerFence::IsSignaled() const {
} }
void GLInnerFence::Wait() { void GLInnerFence::Wait() {
if (is_stubbed) {
return;
}
ASSERT(sync_object.handle != 0); ASSERT(sync_object.handle != 0);
while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED) while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED)
; ;
@ -36,8 +48,12 @@ FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::Rasteriz
TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache) TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache)
: GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {} : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {}
Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) { Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) {
return std::make_shared<GLInnerFence>(addr, value); return std::make_shared<GLInnerFence>(value, is_stubbed);
}
Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
return std::make_shared<GLInnerFence>(addr, value, is_stubbed);
} }
void FenceManagerOpenGL::QueueFence(Fence& fence) { void FenceManagerOpenGL::QueueFence(Fence& fence) {

View File

@ -17,7 +17,8 @@ namespace OpenGL {
class GLInnerFence : public VideoCommon::FenceBase { class GLInnerFence : public VideoCommon::FenceBase {
public: public:
GLInnerFence(GPUVAddr address, u32 payload); GLInnerFence(u32 payload, bool is_stubbed);
GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed);
~GLInnerFence(); ~GLInnerFence();
void Queue(); void Queue();
@ -39,7 +40,8 @@ public:
TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache); TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache);
protected: protected:
Fence CreateFence(GPUVAddr addr, u32 value) override; Fence CreateFence(u32 value, bool is_stubbed) override;
Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override;
void QueueFence(Fence& fence) override; void QueueFence(Fence& fence) override;
bool IsFenceSignaled(Fence& fence) override; bool IsFenceSignaled(Fence& fence) override;
void WaitFence(Fence& fence) override; void WaitFence(Fence& fence) override;

View File

@ -683,14 +683,23 @@ void RasterizerOpenGL::SyncGuestHost() {
buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
} }
void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) { void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) {
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
if (!gpu.IsAsync()) { if (!gpu.IsAsync()) {
auto& memory_manager{gpu.MemoryManager()}; auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(addr, value); memory_manager.Write<u32>(addr, value);
return; return;
} }
fence_manager.SignalFence(addr, value); fence_manager.SignalSemaphore(addr, value);
}
void RasterizerOpenGL::SignalSyncPoint(u32 value) {
auto& gpu{system.GPU()};
if (!gpu.IsAsync()) {
gpu.IncrementSyncPoint(value);
return;
}
fence_manager.SignalSyncPoint(value);
} }
void RasterizerOpenGL::ReleaseFences() { void RasterizerOpenGL::ReleaseFences() {

View File

@ -71,7 +71,8 @@ public:
void InvalidateRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override;
void OnCPUWrite(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override;
void SyncGuestHost() override; void SyncGuestHost() override;
void SignalFence(GPUVAddr addr, u32 value) override; void SignalSemaphore(GPUVAddr addr, u32 value) override;
void SignalSyncPoint(u32 value) override;
void ReleaseFences() override; void ReleaseFences() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void FlushCommands() override; void FlushCommands() override;

View File

@ -543,7 +543,7 @@ void RasterizerVulkan::SyncGuestHost() {
buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
} }
void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) { void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) {
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
auto& memory_manager{gpu.MemoryManager()}; auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(addr, value); memory_manager.Write<u32>(addr, value);
@ -553,7 +553,19 @@ void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) {
memory_manager.Write<u32>(addr, value); memory_manager.Write<u32>(addr, value);
return; return;
} }
fence_manager.SignalFence(addr, value); fence_manager.SignalSemaphore(addr, value);
*/
}
void RasterizerVulkan::SignalSyncPoint(u32 value) {
auto& gpu{system.GPU()};
gpu.IncrementSyncPoint(value);
/*
if (!gpu.IsAsync()) {
gpu.IncrementSyncPoint(value);
return;
}
fence_manager.SignalSyncPoint(value);
*/ */
} }

View File

@ -122,7 +122,8 @@ public:
void InvalidateRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override;
void OnCPUWrite(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override;
void SyncGuestHost() override; void SyncGuestHost() override;
void SignalFence(GPUVAddr addr, u32 value) override; void SignalSemaphore(GPUVAddr addr, u32 value) override;
void SignalSyncPoint(u32 value) override;
void ReleaseFences() override; void ReleaseFences() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void FlushCommands() override; void FlushCommands() override;

View File

@ -337,6 +337,13 @@ public:
uncommited_flushes.reset(); uncommited_flushes.reset();
} }
bool HasUncommitedFlushes() {
if (uncommited_flushes) {
return true;
}
return false;
}
bool ShouldWaitAsyncFlushes() { bool ShouldWaitAsyncFlushes() {
if (commited_flushes.empty()) { if (commited_flushes.empty()) {
return false; return false;