| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | // Copyright 2019 yuzu Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <atomic>
 | 
					
						
							|  |  |  | #include <condition_variable>
 | 
					
						
							|  |  |  | #include <mutex>
 | 
					
						
							|  |  |  | #include <optional>
 | 
					
						
							|  |  |  | #include <thread>
 | 
					
						
							|  |  |  | #include <variant>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  | #include "common/threadsafe_queue.h"
 | 
					
						
							|  |  |  | #include "video_core/gpu.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | namespace Tegra { | 
					
						
							|  |  |  | struct FramebufferConfig; | 
					
						
							|  |  |  | class DmaPusher; | 
					
						
							|  |  |  | } // namespace Tegra
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | class System; | 
					
						
							|  |  |  | } // namespace Core
 | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace VideoCommon::GPUThread { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  | /// Command to signal to the GPU thread that processing has ended
 | 
					
						
							|  |  |  | struct EndProcessingCommand final {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | /// Command to signal to the GPU thread that a command list is ready for processing
 | 
					
						
							|  |  |  | struct SubmitListCommand final { | 
					
						
							|  |  |  |     explicit SubmitListCommand(Tegra::CommandList&& entries) : entries{std::move(entries)} {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Tegra::CommandList entries; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Command to signal to the GPU thread that a swap buffers is pending
 | 
					
						
							|  |  |  | struct SwapBuffersCommand final { | 
					
						
							|  |  |  |     explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer) | 
					
						
							|  |  |  |         : framebuffer{std::move(framebuffer)} {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     std::optional<Tegra::FramebufferConfig> framebuffer; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Command to signal to the GPU thread to flush a region
 | 
					
						
							|  |  |  | struct FlushRegionCommand final { | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     explicit constexpr FlushRegionCommand(CacheAddr addr, u64 size) : addr{addr}, size{size} {} | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     CacheAddr addr; | 
					
						
							|  |  |  |     u64 size; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Command to signal to the GPU thread to invalidate a region
 | 
					
						
							|  |  |  | struct InvalidateRegionCommand final { | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     explicit constexpr InvalidateRegionCommand(CacheAddr addr, u64 size) : addr{addr}, size{size} {} | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     CacheAddr addr; | 
					
						
							|  |  |  |     u64 size; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Command to signal to the GPU thread to flush and invalidate a region
 | 
					
						
							|  |  |  | struct FlushAndInvalidateRegionCommand final { | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     explicit constexpr FlushAndInvalidateRegionCommand(CacheAddr addr, u64 size) | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  |         : addr{addr}, size{size} {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     CacheAddr addr; | 
					
						
							|  |  |  |     u64 size; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  | using CommandData = | 
					
						
							|  |  |  |     std::variant<EndProcessingCommand, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand, | 
					
						
							|  |  |  |                  InvalidateRegionCommand, FlushAndInvalidateRegionCommand>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct CommandDataContainer { | 
					
						
							|  |  |  |     CommandDataContainer() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  |     CommandDataContainer(CommandData&& data, u64 next_fence) | 
					
						
							|  |  |  |         : data{std::move(data)}, fence{next_fence} {} | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     CommandData data; | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  |     u64 fence{}; | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | /// Struct used to synchronize the GPU thread
 | 
					
						
							|  |  |  | struct SynchState final { | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     std::atomic_bool is_running{true}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 21:01:47 -05:00
										 |  |  |     using CommandQueue = Common::MPSCQueue<CommandDataContainer>; | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     CommandQueue queue; | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  |     u64 last_fence{}; | 
					
						
							|  |  |  |     std::atomic<u64> signaled_fence{}; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Class used to manage the GPU thread
 | 
					
						
							|  |  |  | class ThreadManager final { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2019-04-09 14:02:00 -04:00
										 |  |  |     explicit ThreadManager(Core::System& system); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  |     ~ThreadManager(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-09 14:02:00 -04:00
										 |  |  |     /// Creates and starts the GPU thread.
 | 
					
						
							|  |  |  |     void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  |     /// Push GPU command entries to be processed
 | 
					
						
							|  |  |  |     void SubmitList(Tegra::CommandList&& entries); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Swap buffers (render frame)
 | 
					
						
							| 
									
										
										
										
											2019-08-21 01:55:25 -03:00
										 |  |  |     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     void FlushRegion(CacheAddr addr, u64 size); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Notify rasterizer that any caches of the specified region should be invalidated
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     void InvalidateRegion(CacheAddr addr, u64 size); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
 | 
					
						
							| 
									
										
										
										
											2019-02-18 20:58:32 -05:00
										 |  |  |     void FlushAndInvalidateRegion(CacheAddr addr, u64 size); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-26 19:08:22 -04:00
										 |  |  |     // Wait until the gpu thread is idle.
 | 
					
						
							|  |  |  |     void WaitIdle() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | private: | 
					
						
							|  |  |  |     /// Pushes a command to be executed by the GPU thread
 | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  |     u64 PushCommand(CommandData&& command_data); | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     SynchState state; | 
					
						
							| 
									
										
										
										
											2019-03-30 20:08:09 -04:00
										 |  |  |     Core::System& system; | 
					
						
							| 
									
										
										
										
											2019-03-07 16:05:46 -05:00
										 |  |  |     std::thread thread; | 
					
						
							|  |  |  |     std::thread::id thread_id; | 
					
						
							| 
									
										
										
										
											2019-01-23 22:17:55 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace VideoCommon::GPUThread
 |