video_core: gpu: Implement synchronous mode using threaded GPU.
This commit is contained in:
		
							parent
							
								
									14c825bd1c
								
							
						
					
					
						commit
						40571c073f
					
				| @ -38,7 +38,7 @@ GPU::GPU(Core::System& system_, bool is_async_, bool use_nvdec_) | |||||||
|       maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, |       maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, | ||||||
|       kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, |       kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, | ||||||
|       shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_}, |       shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_}, | ||||||
|       gpu_thread{system_} {} |       gpu_thread{system_, is_async_} {} | ||||||
| 
 | 
 | ||||||
| GPU::~GPU() = default; | GPU::~GPU() = default; | ||||||
| 
 | 
 | ||||||
| @ -524,7 +524,10 @@ void GPU::WaitIdle() const { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GPU::OnCommandListEnd() { | void GPU::OnCommandListEnd() { | ||||||
|     gpu_thread.OnCommandListEnd(); |     if (is_async) { | ||||||
|  |         // This command only applies to asynchronous GPU mode
 | ||||||
|  |         gpu_thread.OnCommandListEnd(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Tegra
 | } // namespace Tegra
 | ||||||
|  | |||||||
| @ -406,10 +406,10 @@ private: | |||||||
|     u64 last_flush_fence{}; |     u64 last_flush_fence{}; | ||||||
|     std::mutex flush_request_mutex; |     std::mutex flush_request_mutex; | ||||||
| 
 | 
 | ||||||
|  |     const bool is_async; | ||||||
|  | 
 | ||||||
|     VideoCommon::GPUThread::ThreadManager gpu_thread; |     VideoCommon::GPUThread::ThreadManager gpu_thread; | ||||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; |     std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | ||||||
| 
 |  | ||||||
|     const bool is_async; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define ASSERT_REG_POSITION(field_name, position)                                                  \ | #define ASSERT_REG_POSITION(field_name, position)                                                  \ | ||||||
|  | |||||||
| @ -65,7 +65,8 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ThreadManager::ThreadManager(Core::System& system_) : system{system_} {} | ThreadManager::ThreadManager(Core::System& system_, bool is_async_) | ||||||
|  |     : system{system_}, is_async{is_async_} {} | ||||||
| 
 | 
 | ||||||
| ThreadManager::~ThreadManager() { | ThreadManager::~ThreadManager() { | ||||||
|     if (!thread.joinable()) { |     if (!thread.joinable()) { | ||||||
| @ -97,19 +98,30 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ThreadManager::FlushRegion(VAddr addr, u64 size) { | void ThreadManager::FlushRegion(VAddr addr, u64 size) { | ||||||
|     if (!Settings::IsGPULevelHigh()) { |     if (!is_async) { | ||||||
|  |         // Always flush with synchronous GPU mode
 | ||||||
|         PushCommand(FlushRegionCommand(addr, size)); |         PushCommand(FlushRegionCommand(addr, size)); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (!Settings::IsGPULevelExtreme()) { | 
 | ||||||
|         return; |     // Asynchronous GPU mode
 | ||||||
|     } |     switch (Settings::values.gpu_accuracy.GetValue()) { | ||||||
|     if (system.Renderer().Rasterizer().MustFlushRegion(addr, size)) { |     case Settings::GPUAccuracy::Normal: | ||||||
|  |         PushCommand(FlushRegionCommand(addr, size)); | ||||||
|  |         break; | ||||||
|  |     case Settings::GPUAccuracy::High: | ||||||
|  |         // TODO(bunnei): Is this right? Preserving existing behavior for now
 | ||||||
|  |         break; | ||||||
|  |     case Settings::GPUAccuracy::Extreme: { | ||||||
|         auto& gpu = system.GPU(); |         auto& gpu = system.GPU(); | ||||||
|         u64 fence = gpu.RequestFlush(addr, size); |         u64 fence = gpu.RequestFlush(addr, size); | ||||||
|         PushCommand(GPUTickCommand()); |         PushCommand(GPUTickCommand()); | ||||||
|         while (fence > gpu.CurrentFlushRequestFence()) { |         while (fence > gpu.CurrentFlushRequestFence()) { | ||||||
|         } |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     default: | ||||||
|  |         UNIMPLEMENTED_MSG("Unsupported gpu_accuracy {}", Settings::values.gpu_accuracy.GetValue()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -134,6 +146,12 @@ void ThreadManager::OnCommandListEnd() { | |||||||
| u64 ThreadManager::PushCommand(CommandData&& command_data) { | u64 ThreadManager::PushCommand(CommandData&& command_data) { | ||||||
|     const u64 fence{++state.last_fence}; |     const u64 fence{++state.last_fence}; | ||||||
|     state.queue.Push(CommandDataContainer(std::move(command_data), fence)); |     state.queue.Push(CommandDataContainer(std::move(command_data), fence)); | ||||||
|  | 
 | ||||||
|  |     if (!is_async) { | ||||||
|  |         // In synchronous GPU mode, block the caller until the command has executed
 | ||||||
|  |         WaitIdle(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return fence; |     return fence; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -27,7 +27,7 @@ class System; | |||||||
| } // namespace Core
 | } // namespace Core
 | ||||||
| 
 | 
 | ||||||
| namespace VideoCore { | namespace VideoCore { | ||||||
|     class RendererBase; | class RendererBase; | ||||||
| } // namespace VideoCore
 | } // namespace VideoCore
 | ||||||
| 
 | 
 | ||||||
| namespace VideoCommon::GPUThread { | namespace VideoCommon::GPUThread { | ||||||
| @ -117,7 +117,7 @@ struct SynchState final { | |||||||
| /// Class used to manage the GPU thread
 | /// Class used to manage the GPU thread
 | ||||||
| class ThreadManager final { | class ThreadManager final { | ||||||
| public: | public: | ||||||
|     explicit ThreadManager(Core::System& system_); |     explicit ThreadManager(Core::System& system_, bool is_async_); | ||||||
|     ~ThreadManager(); |     ~ThreadManager(); | ||||||
| 
 | 
 | ||||||
|     /// Creates and starts the GPU thread.
 |     /// Creates and starts the GPU thread.
 | ||||||
| @ -155,6 +155,7 @@ private: | |||||||
|     Core::System& system; |     Core::System& system; | ||||||
|     std::thread thread; |     std::thread thread; | ||||||
|     std::thread::id thread_id; |     std::thread::id thread_id; | ||||||
|  |     const bool is_async; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace VideoCommon::GPUThread
 | } // namespace VideoCommon::GPUThread
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei