forked from eden-emu/eden
		
	GPU: Implement a Fence Manager.
This commit is contained in:
		
							parent
							
								
									487379c593
								
							
						
					
					
						commit
						1f345ebe3a
					
				
					 6 changed files with 208 additions and 23 deletions
				
			
		|  | @ -23,6 +23,7 @@ add_library(video_core STATIC | |||
|     engines/shader_bytecode.h | ||||
|     engines/shader_header.h | ||||
|     engines/shader_type.h | ||||
|     fence_manager.h | ||||
|     gpu.cpp | ||||
|     gpu.h | ||||
|     gpu_asynch.cpp | ||||
|  | @ -51,6 +52,8 @@ add_library(video_core STATIC | |||
|     renderer_opengl/gl_buffer_cache.h | ||||
|     renderer_opengl/gl_device.cpp | ||||
|     renderer_opengl/gl_device.h | ||||
|     renderer_opengl/gl_fence_manager.cpp | ||||
|     renderer_opengl/gl_fence_manager.h | ||||
|     renderer_opengl/gl_framebuffer_cache.cpp | ||||
|     renderer_opengl/gl_framebuffer_cache.h | ||||
|     renderer_opengl/gl_rasterizer.cpp | ||||
|  |  | |||
							
								
								
									
										97
									
								
								src/video_core/fence_manager.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/video_core/fence_manager.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | |||
| // Copyright 2020 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <queue> | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| #include "video_core/gpu.h" | ||||
| #include "video_core/memory_manager.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
| 
 | ||||
| namespace VideoCommon { | ||||
| 
 | ||||
| class FenceBase { | ||||
| public: | ||||
|     FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {} | ||||
| 
 | ||||
|     constexpr GPUVAddr GetAddress() const { | ||||
|         return address; | ||||
|     } | ||||
| 
 | ||||
|     constexpr u32 GetPayload() const { | ||||
|         return payload; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     GPUVAddr address; | ||||
|     u32 payload; | ||||
| }; | ||||
| 
 | ||||
| template <typename TFence, typename TTextureCache> | ||||
| class FenceManager { | ||||
| public: | ||||
|     void SignalFence(GPUVAddr addr, u32 value) { | ||||
|         TryReleasePendingFences(); | ||||
|         TFence new_fence = CreateFence(addr, value); | ||||
|         QueueFence(new_fence); | ||||
|         fences.push(new_fence); | ||||
|         texture_cache.CommitAsyncFlushes(); | ||||
|         rasterizer.FlushCommands(); | ||||
|         rasterizer.SyncGuestHost(); | ||||
|     } | ||||
| 
 | ||||
|     void WaitPendingFences() { | ||||
|         while (!fences.empty()) { | ||||
|             TFence& current_fence = fences.front(); | ||||
|             WaitFence(current_fence); | ||||
|             texture_cache.PopAsyncFlushes(); | ||||
|             auto& gpu{system.GPU()}; | ||||
|             auto& memory_manager{gpu.MemoryManager()}; | ||||
|             memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             fences.pop(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||||
|                  TTextureCache& texture_cache) | ||||
|         : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache} {} | ||||
| 
 | ||||
|     virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0; | ||||
|     virtual void QueueFence(TFence& fence) = 0; | ||||
|     virtual bool IsFenceSignaled(TFence& fence) = 0; | ||||
|     virtual void WaitFence(TFence& fence) = 0; | ||||
| 
 | ||||
|     Core::System& system; | ||||
|     VideoCore::RasterizerInterface& rasterizer; | ||||
|     TTextureCache& texture_cache; | ||||
| 
 | ||||
| private: | ||||
|     void TryReleasePendingFences() { | ||||
|         while (!fences.empty()) { | ||||
|             TFence& current_fence = fences.front(); | ||||
|             if (!IsFenceSignaled(current_fence)) { | ||||
|                 return; | ||||
|             } | ||||
|             texture_cache.PopAsyncFlushes(); | ||||
|             auto& gpu{system.GPU()}; | ||||
|             auto& memory_manager{gpu.MemoryManager()}; | ||||
|             memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||||
|             fences.pop(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::queue<TFence> fences; | ||||
| }; | ||||
| 
 | ||||
| } // namespace VideoCommon
 | ||||
							
								
								
									
										55
									
								
								src/video_core/renderer_opengl/gl_fence_manager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/video_core/renderer_opengl/gl_fence_manager.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| // Copyright 2020 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| 
 | ||||
| #include "video_core/renderer_opengl/gl_fence_manager.h" | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload) | ||||
|     : VideoCommon::FenceBase(address, payload), sync_object{} {} | ||||
| 
 | ||||
| GLInnerFence::~GLInnerFence() = default; | ||||
| 
 | ||||
| void GLInnerFence::Queue() { | ||||
|     ASSERT(sync_object.handle == 0); | ||||
|     sync_object.Create(); | ||||
| } | ||||
| 
 | ||||
| bool GLInnerFence::IsSignaled() const { | ||||
|     ASSERT(sync_object.handle != 0); | ||||
|     GLsizei length; | ||||
|     GLint sync_status; | ||||
|     glGetSynciv(sync_object.handle, GL_SYNC_STATUS, sizeof(GLint), &length, &sync_status); | ||||
|     return sync_status == GL_SIGNALED; | ||||
| } | ||||
| 
 | ||||
| void GLInnerFence::Wait() { | ||||
|     ASSERT(sync_object.handle != 0); | ||||
|     while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED) | ||||
|         ; | ||||
| } | ||||
| 
 | ||||
| FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||||
|                                TextureCacheOpenGL& texture_cache) | ||||
|     : GenericFenceManager(system, rasterizer, texture_cache) {} | ||||
| 
 | ||||
| Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) { | ||||
|     return std::make_shared<GLInnerFence>(addr, value); | ||||
| } | ||||
| 
 | ||||
| void FenceManagerOpenGL::QueueFence(Fence& fence) { | ||||
|     fence->Queue(); | ||||
| } | ||||
| 
 | ||||
| bool FenceManagerOpenGL::IsFenceSignaled(Fence& fence) { | ||||
|     return fence->IsSignaled(); | ||||
| } | ||||
| 
 | ||||
| void FenceManagerOpenGL::WaitFence(Fence& fence) { | ||||
|     fence->Wait(); | ||||
| } | ||||
| 
 | ||||
| } // namespace OpenGL
 | ||||
							
								
								
									
										47
									
								
								src/video_core/renderer_opengl/gl_fence_manager.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/video_core/renderer_opengl/gl_fence_manager.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| // Copyright 2020 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <glad/glad.h> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/fence_manager.h" | ||||
| #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||
| #include "video_core/renderer_opengl/gl_texture_cache.h" | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| class GLInnerFence : public VideoCommon::FenceBase { | ||||
| public: | ||||
|     GLInnerFence(GPUVAddr address, u32 payload); | ||||
|     ~GLInnerFence(); | ||||
| 
 | ||||
|     void Queue(); | ||||
| 
 | ||||
|     bool IsSignaled() const; | ||||
| 
 | ||||
|     void Wait(); | ||||
| 
 | ||||
| private: | ||||
|     OGLSync sync_object; | ||||
| }; | ||||
| 
 | ||||
| using Fence = std::shared_ptr<GLInnerFence>; | ||||
| using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL>; | ||||
| 
 | ||||
| class FenceManagerOpenGL final : public GenericFenceManager { | ||||
| public: | ||||
|     FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||||
|                    TextureCacheOpenGL& texture_cache); | ||||
| 
 | ||||
| protected: | ||||
|     Fence CreateFence(GPUVAddr addr, u32 value) override; | ||||
|     void QueueFence(Fence& fence) override; | ||||
|     bool IsFenceSignaled(Fence& fence) override; | ||||
|     void WaitFence(Fence& fence) override; | ||||
| }; | ||||
| 
 | ||||
| } // namespace OpenGL
 | ||||
|  | @ -101,7 +101,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind | |||
|     : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, | ||||
|       shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, | ||||
|       screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, | ||||
|       buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { | ||||
|       buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this, | ||||
|                                                                              texture_cache} { | ||||
|     CheckExtensions(); | ||||
| } | ||||
| 
 | ||||
|  | @ -677,31 +678,11 @@ void RasterizerOpenGL::SyncGuestHost() { | |||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) { | ||||
|     if (!fences.empty()) { | ||||
|         const std::pair<GPUVAddr, u32>& current_fence = fences.front(); | ||||
|         const auto [address, payload] = current_fence; | ||||
|         texture_cache.PopAsyncFlushes(); | ||||
|         auto& gpu{system.GPU()}; | ||||
|         auto& memory_manager{gpu.MemoryManager()}; | ||||
|         memory_manager.Write<u32>(address, payload); | ||||
|         fences.pop_front(); | ||||
|     } | ||||
|     fences.emplace_back(addr, value); | ||||
|     texture_cache.CommitAsyncFlushes(); | ||||
|     FlushCommands(); | ||||
|     SyncGuestHost(); | ||||
|     fence_manager.SignalFence(addr, value); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::ReleaseFences() { | ||||
|     while (!fences.empty()) { | ||||
|         const std::pair<GPUVAddr, u32>& current_fence = fences.front(); | ||||
|         const auto [address, payload] = current_fence; | ||||
|         texture_cache.PopAsyncFlushes(); | ||||
|         auto& gpu{system.GPU()}; | ||||
|         auto& memory_manager{gpu.MemoryManager()}; | ||||
|         memory_manager.Write<u32>(address, payload); | ||||
|         fences.pop_front(); | ||||
|     } | ||||
|     fence_manager.WaitPendingFences(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include "video_core/rasterizer_interface.h" | ||||
| #include "video_core/renderer_opengl/gl_buffer_cache.h" | ||||
| #include "video_core/renderer_opengl/gl_device.h" | ||||
| #include "video_core/renderer_opengl/gl_fence_manager.h" | ||||
| #include "video_core/renderer_opengl/gl_framebuffer_cache.h" | ||||
| #include "video_core/renderer_opengl/gl_query_cache.h" | ||||
| #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||
|  | @ -226,6 +227,7 @@ private: | |||
|     SamplerCacheOpenGL sampler_cache; | ||||
|     FramebufferCacheOpenGL framebuffer_cache; | ||||
|     QueryCache query_cache; | ||||
|     FenceManagerOpenGL fence_manager; | ||||
| 
 | ||||
|     Core::System& system; | ||||
|     ScreenInfo& screen_info; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fernando Sahmkow
						Fernando Sahmkow