FenceManager: Manage syncpoints and rename fences to semaphores.
This commit is contained in:
		
							parent
							
								
									96bb961a64
								
							
						
					
					
						commit
						b7bc3c2549
					
				| @ -229,6 +229,13 @@ public: | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool HasUncommitedFlushes() { | ||||
|         if (uncommited_flushes) { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     void PopAsyncFlushes() { | ||||
|         if (commited_flushes.empty()) { | ||||
|             return; | ||||
|  | ||||
| @ -405,7 +405,7 @@ void Maxwell3D::ProcessQueryGet() { | ||||
|     switch (regs.query.query_get.operation) { | ||||
|     case Regs::QueryOperation::Release: | ||||
|         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 { | ||||
|             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(); | ||||
|     [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); | ||||
|     if (increment) { | ||||
|         system.GPU().IncrementSyncPoint(sync_point); | ||||
|         rasterizer.SignalSyncPoint(sync_point); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -22,7 +22,11 @@ namespace VideoCommon { | ||||
| 
 | ||||
| class FenceBase { | ||||
| 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 { | ||||
|         return address; | ||||
| @ -32,22 +36,49 @@ public: | ||||
|         return payload; | ||||
|     } | ||||
| 
 | ||||
|     constexpr bool IsSemaphore() const { | ||||
|         return is_semaphore; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     GPUVAddr address; | ||||
|     u32 payload; | ||||
|     bool is_semaphore; | ||||
| 
 | ||||
| protected: | ||||
|     bool is_stubbed; | ||||
| }; | ||||
| 
 | ||||
| template <typename TFence, typename TTextureCache, typename TTBufferCache> | ||||
| class FenceManager { | ||||
| public: | ||||
|     void SignalFence(GPUVAddr addr, u32 value) { | ||||
|     void SignalSemaphore(GPUVAddr addr, u32 value) { | ||||
|         TryReleasePendingFences(); | ||||
|         bool should_flush = texture_cache.HasUncommitedFlushes(); | ||||
|         should_flush |= buffer_cache.HasUncommitedFlushes(); | ||||
|         texture_cache.CommitAsyncFlushes(); | ||||
|         buffer_cache.CommitAsyncFlushes(); | ||||
|         TFence new_fence = CreateFence(addr, value); | ||||
|         TFence new_fence = CreateFence(addr, value, !should_flush); | ||||
|         fences.push(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(); | ||||
|     } | ||||
| 
 | ||||
| @ -62,8 +93,12 @@ public: | ||||
|             texture_cache.PopAsyncFlushes(); | ||||
|             buffer_cache.PopAsyncFlushes(); | ||||
|             auto& gpu{system.GPU()}; | ||||
|             auto& memory_manager{gpu.MemoryManager()}; | ||||
|             memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             if (current_fence->IsSemaphore()) { | ||||
|                 auto& memory_manager{gpu.MemoryManager()}; | ||||
|                 memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             } else { | ||||
|                 gpu.IncrementSyncPoint(current_fence->GetPayload()); | ||||
|             } | ||||
|             fences.pop(); | ||||
|         } | ||||
|     } | ||||
| @ -74,7 +109,8 @@ protected: | ||||
|         : system{system}, rasterizer{rasterizer}, texture_cache{texture_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 bool IsFenceSignaled(TFence& fence) = 0; | ||||
|     virtual void WaitFence(TFence& fence) = 0; | ||||
| @ -96,8 +132,12 @@ private: | ||||
|             texture_cache.PopAsyncFlushes(); | ||||
|             buffer_cache.PopAsyncFlushes(); | ||||
|             auto& gpu{system.GPU()}; | ||||
|             auto& memory_manager{gpu.MemoryManager()}; | ||||
|             memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             if (current_fence->IsSemaphore()) { | ||||
|                 auto& memory_manager{gpu.MemoryManager()}; | ||||
|                 memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             } else { | ||||
|                 gpu.IncrementSyncPoint(current_fence->GetPayload()); | ||||
|             } | ||||
|             fences.pop(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -49,8 +49,11 @@ public: | ||||
|     /// Records a GPU query and caches it
 | ||||
|     virtual void Query(GPUVAddr gpu_addr, QueryType type, std::optional<u64> timestamp) = 0; | ||||
| 
 | ||||
|     /// Signal a GPU based fence
 | ||||
|     virtual void SignalFence(GPUVAddr addr, u32 value) = 0; | ||||
|     /// Signal a GPU based semaphore as a fence
 | ||||
|     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.
 | ||||
|     virtual void ReleaseFences() = 0; | ||||
|  | ||||
| @ -8,17 +8,26 @@ | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload) | ||||
|     : VideoCommon::FenceBase(address, payload), sync_object{} {} | ||||
| GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) | ||||
|     : 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; | ||||
| 
 | ||||
| void GLInnerFence::Queue() { | ||||
|     if (is_stubbed) { | ||||
|         return; | ||||
|     } | ||||
|     ASSERT(sync_object.handle == 0); | ||||
|     sync_object.Create(); | ||||
| } | ||||
| 
 | ||||
| bool GLInnerFence::IsSignaled() const { | ||||
|     if (is_stubbed) { | ||||
|         return true; | ||||
|     } | ||||
|     ASSERT(sync_object.handle != 0); | ||||
|     GLsizei length; | ||||
|     GLint sync_status; | ||||
| @ -27,6 +36,9 @@ bool GLInnerFence::IsSignaled() const { | ||||
| } | ||||
| 
 | ||||
| void GLInnerFence::Wait() { | ||||
|     if (is_stubbed) { | ||||
|         return; | ||||
|     } | ||||
|     ASSERT(sync_object.handle != 0); | ||||
|     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) | ||||
|     : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {} | ||||
| 
 | ||||
| Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) { | ||||
|     return std::make_shared<GLInnerFence>(addr, value); | ||||
| Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) { | ||||
|     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) { | ||||
|  | ||||
| @ -17,7 +17,8 @@ namespace OpenGL { | ||||
| 
 | ||||
| class GLInnerFence : public VideoCommon::FenceBase { | ||||
| public: | ||||
|     GLInnerFence(GPUVAddr address, u32 payload); | ||||
|     GLInnerFence(u32 payload, bool is_stubbed); | ||||
|     GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed); | ||||
|     ~GLInnerFence(); | ||||
| 
 | ||||
|     void Queue(); | ||||
| @ -39,7 +40,8 @@ public: | ||||
|                        TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache); | ||||
| 
 | ||||
| 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; | ||||
|     bool IsFenceSignaled(Fence& fence) override; | ||||
|     void WaitFence(Fence& fence) override; | ||||
|  | ||||
| @ -683,14 +683,23 @@ void RasterizerOpenGL::SyncGuestHost() { | ||||
|     buffer_cache.SyncGuestHost(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) { | ||||
| void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) { | ||||
|     auto& gpu{system.GPU()}; | ||||
|     if (!gpu.IsAsync()) { | ||||
|         auto& memory_manager{gpu.MemoryManager()}; | ||||
|         memory_manager.Write<u32>(addr, value); | ||||
|         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() { | ||||
|  | ||||
| @ -71,7 +71,8 @@ public: | ||||
|     void InvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void OnCPUWrite(VAddr addr, u64 size) 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 FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void FlushCommands() override; | ||||
|  | ||||
| @ -543,7 +543,7 @@ void RasterizerVulkan::SyncGuestHost() { | ||||
|     buffer_cache.SyncGuestHost(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) { | ||||
| void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) { | ||||
|     auto& gpu{system.GPU()}; | ||||
|     auto& memory_manager{gpu.MemoryManager()}; | ||||
|     memory_manager.Write<u32>(addr, value); | ||||
| @ -553,7 +553,19 @@ void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) { | ||||
|         memory_manager.Write<u32>(addr, value); | ||||
|         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); | ||||
|     */ | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -122,7 +122,8 @@ public: | ||||
|     void InvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void OnCPUWrite(VAddr addr, u64 size) 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 FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void FlushCommands() override; | ||||
|  | ||||
| @ -337,6 +337,13 @@ public: | ||||
|         uncommited_flushes.reset(); | ||||
|     } | ||||
| 
 | ||||
|     bool HasUncommitedFlushes() { | ||||
|         if (uncommited_flushes) { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     bool ShouldWaitAsyncFlushes() { | ||||
|         if (commited_flushes.empty()) { | ||||
|             return false; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Fernando Sahmkow
						Fernando Sahmkow