| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | // Copyright 2018 yuzu Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 13:54:50 +02:00
										 |  |  | #include <array>
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2018-09-06 15:48:08 +02:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | #include "common/common_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-23 14:58:27 -04:00
										 |  |  | #include "core/hle/service/nvflinger/buffer_queue.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-23 23:20:56 -05:00
										 |  |  | #include "video_core/dma_pusher.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | #include "video_core/memory_manager.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  | namespace VideoCore { | 
					
						
							|  |  |  | class RasterizerInterface; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | namespace Tegra { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 00:45:24 -04:00
										 |  |  | enum class RenderTargetFormat : u32 { | 
					
						
							| 
									
										
										
										
											2018-03-25 17:57:53 -04:00
										 |  |  |     NONE = 0x0, | 
					
						
							| 
									
										
										
										
											2018-06-05 21:07:40 -05:00
										 |  |  |     RGBA32_FLOAT = 0xC0, | 
					
						
							| 
									
										
										
										
											2018-06-30 14:23:13 -05:00
										 |  |  |     RGBA32_UINT = 0xC2, | 
					
						
							| 
									
										
										
										
											2018-08-13 00:34:20 -04:00
										 |  |  |     RGBA16_UNORM = 0xC6, | 
					
						
							| 
									
										
										
										
											2018-08-13 00:04:52 -04:00
										 |  |  |     RGBA16_UINT = 0xC9, | 
					
						
							| 
									
										
										
										
											2018-04-15 20:41:02 -04:00
										 |  |  |     RGBA16_FLOAT = 0xCA, | 
					
						
							| 
									
										
										
										
											2018-07-23 19:10:00 -04:00
										 |  |  |     RG32_FLOAT = 0xCB, | 
					
						
							| 
									
										
										
										
											2018-08-13 22:55:16 +10:00
										 |  |  |     RG32_UINT = 0xCD, | 
					
						
							| 
									
										
										
										
											2018-07-23 16:56:52 -04:00
										 |  |  |     BGRA8_UNORM = 0xCF, | 
					
						
							| 
									
										
										
										
											2018-09-09 23:41:37 -04:00
										 |  |  |     BGRA8_SRGB = 0xD0, | 
					
						
							| 
									
										
										
										
											2018-04-15 20:41:02 -04:00
										 |  |  |     RGB10_A2_UNORM = 0xD1, | 
					
						
							| 
									
										
										
										
											2018-03-22 16:40:11 -05:00
										 |  |  |     RGBA8_UNORM = 0xD5, | 
					
						
							| 
									
										
										
										
											2018-04-15 20:41:02 -04:00
										 |  |  |     RGBA8_SRGB = 0xD6, | 
					
						
							| 
									
										
										
										
											2018-08-10 11:44:43 -04:00
										 |  |  |     RGBA8_SNORM = 0xD7, | 
					
						
							| 
									
										
										
										
											2018-08-20 22:26:54 +10:00
										 |  |  |     RGBA8_UINT = 0xD9, | 
					
						
							| 
									
										
										
										
											2018-07-26 02:01:29 +02:00
										 |  |  |     RG16_UNORM = 0xDA, | 
					
						
							|  |  |  |     RG16_SNORM = 0xDB, | 
					
						
							|  |  |  |     RG16_SINT = 0xDC, | 
					
						
							|  |  |  |     RG16_UINT = 0xDD, | 
					
						
							|  |  |  |     RG16_FLOAT = 0xDE, | 
					
						
							| 
									
										
										
										
											2018-06-05 21:57:16 -05:00
										 |  |  |     R11G11B10_FLOAT = 0xE0, | 
					
						
							| 
									
										
										
										
											2018-08-13 22:55:16 +10:00
										 |  |  |     R32_UINT = 0xE4, | 
					
						
							| 
									
										
										
										
											2018-08-01 15:31:42 +02:00
										 |  |  |     R32_FLOAT = 0xE5, | 
					
						
							| 
									
										
										
										
											2018-08-08 01:22:48 -04:00
										 |  |  |     B5G6R5_UNORM = 0xE8, | 
					
						
							| 
									
										
										
										
											2018-09-15 23:48:02 +08:00
										 |  |  |     BGR5A1_UNORM = 0xE9, | 
					
						
							| 
									
										
										
										
											2018-08-12 23:02:34 -04:00
										 |  |  |     RG8_UNORM = 0xEA, | 
					
						
							| 
									
										
										
										
											2018-08-10 12:07:37 -04:00
										 |  |  |     RG8_SNORM = 0xEB, | 
					
						
							| 
									
										
										
										
											2018-08-11 20:01:50 +02:00
										 |  |  |     R16_UNORM = 0xEE, | 
					
						
							|  |  |  |     R16_SNORM = 0xEF, | 
					
						
							|  |  |  |     R16_SINT = 0xF0, | 
					
						
							|  |  |  |     R16_UINT = 0xF1, | 
					
						
							| 
									
										
										
										
											2018-07-25 23:19:15 -05:00
										 |  |  |     R16_FLOAT = 0xF2, | 
					
						
							| 
									
										
										
										
											2018-07-24 16:47:50 -05:00
										 |  |  |     R8_UNORM = 0xF3, | 
					
						
							| 
									
										
										
										
											2018-08-12 03:44:42 +02:00
										 |  |  |     R8_UINT = 0xF6, | 
					
						
							| 
									
										
										
										
											2018-03-22 16:40:11 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 12:42:04 -05:00
										 |  |  | enum class DepthFormat : u32 { | 
					
						
							|  |  |  |     Z32_FLOAT = 0xA, | 
					
						
							|  |  |  |     Z16_UNORM = 0x13, | 
					
						
							|  |  |  |     S8_Z24_UNORM = 0x14, | 
					
						
							|  |  |  |     Z24_X8_UNORM = 0x15, | 
					
						
							|  |  |  |     Z24_S8_UNORM = 0x16, | 
					
						
							|  |  |  |     Z24_C8_UNORM = 0x18, | 
					
						
							| 
									
										
										
										
											2018-07-24 20:41:40 -05:00
										 |  |  |     Z32_S8_X24_FLOAT = 0x19, | 
					
						
							| 
									
										
										
										
											2018-07-02 12:42:04 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-24 21:57:10 -05:00
										 |  |  | /// Returns the number of bytes per pixel of each rendertarget format.
 | 
					
						
							|  |  |  | u32 RenderTargetBytesPerPixel(RenderTargetFormat format); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-11 20:01:50 +02:00
										 |  |  | /// Returns the number of bytes per pixel of each depth format.
 | 
					
						
							|  |  |  | u32 DepthFormatBytesPerPixel(DepthFormat format); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 15:48:08 +02:00
										 |  |  | struct CommandListHeader; | 
					
						
							| 
									
										
										
										
											2018-03-22 15:19:35 -05:00
										 |  |  | class DebugContext; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 21:04:30 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Struct describing framebuffer configuration | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct FramebufferConfig { | 
					
						
							|  |  |  |     enum class PixelFormat : u32 { | 
					
						
							|  |  |  |         ABGR8 = 1, | 
					
						
							| 
									
										
										
										
											2019-01-11 21:15:30 +01:00
										 |  |  |         BGRA8 = 5, | 
					
						
							| 
									
										
										
										
											2018-03-22 21:04:30 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Returns the number of bytes per pixel. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-08-10 18:39:37 -04:00
										 |  |  |     static u32 BytesPerPixel(PixelFormat format); | 
					
						
							| 
									
										
										
										
											2018-03-22 21:04:30 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     VAddr address; | 
					
						
							|  |  |  |     u32 offset; | 
					
						
							|  |  |  |     u32 width; | 
					
						
							|  |  |  |     u32 height; | 
					
						
							|  |  |  |     u32 stride; | 
					
						
							|  |  |  |     PixelFormat pixel_format; | 
					
						
							| 
									
										
										
										
											2018-03-23 14:58:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; | 
					
						
							|  |  |  |     TransformFlags transform_flags; | 
					
						
							| 
									
										
										
										
											2018-07-17 20:11:41 -04:00
										 |  |  |     MathUtil::Rectangle<int> crop_rect; | 
					
						
							| 
									
										
										
										
											2018-03-22 21:04:30 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-18 15:15:05 -05:00
										 |  |  | namespace Engines { | 
					
						
							|  |  |  | class Fermi2D; | 
					
						
							|  |  |  | class Maxwell3D; | 
					
						
							| 
									
										
										
										
											2018-06-10 17:02:33 -05:00
										 |  |  | class MaxwellDMA; | 
					
						
							| 
									
										
										
										
											2019-01-22 20:49:31 -03:00
										 |  |  | class KeplerCompute; | 
					
						
							| 
									
										
										
										
											2018-09-08 15:58:20 -05:00
										 |  |  | class KeplerMemory; | 
					
						
							| 
									
										
										
										
											2018-03-18 15:15:05 -05:00
										 |  |  | } // namespace Engines
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | enum class EngineID { | 
					
						
							|  |  |  |     FERMI_TWOD_A = 0x902D, // 2D Engine
 | 
					
						
							|  |  |  |     MAXWELL_B = 0xB197,    // 3D Engine
 | 
					
						
							| 
									
										
										
										
											2019-01-22 20:49:31 -03:00
										 |  |  |     KEPLER_COMPUTE_B = 0xB1C0, | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  |     KEPLER_INLINE_TO_MEMORY_B = 0xA140, | 
					
						
							|  |  |  |     MAXWELL_DMA_COPY_A = 0xB0B5, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class GPU final { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  |     explicit GPU(VideoCore::RasterizerInterface& rasterizer); | 
					
						
							| 
									
										
										
										
											2018-03-18 15:15:05 -05:00
										 |  |  |     ~GPU(); | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-23 23:20:56 -05:00
										 |  |  |     struct MethodCall { | 
					
						
							|  |  |  |         u32 method{}; | 
					
						
							|  |  |  |         u32 argument{}; | 
					
						
							|  |  |  |         u32 subchannel{}; | 
					
						
							|  |  |  |         u32 method_count{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool IsLastCall() const { | 
					
						
							|  |  |  |             return method_count <= 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         MethodCall(u32 method, u32 argument, u32 subchannel = 0, u32 method_count = 0) | 
					
						
							|  |  |  |             : method(method), argument(argument), subchannel(subchannel), | 
					
						
							|  |  |  |               method_count(method_count) {} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Calls a GPU method.
 | 
					
						
							|  |  |  |     void CallMethod(const MethodCall& method_call); | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 10:57:56 -04:00
										 |  |  |     /// Returns a reference to the Maxwell3D GPU engine.
 | 
					
						
							|  |  |  |     Engines::Maxwell3D& Maxwell3D(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 18:31:36 -04:00
										 |  |  |     /// Returns a const reference to the Maxwell3D GPU engine.
 | 
					
						
							|  |  |  |     const Engines::Maxwell3D& Maxwell3D() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 10:57:56 -04:00
										 |  |  |     /// Returns a reference to the GPU memory manager.
 | 
					
						
							|  |  |  |     Tegra::MemoryManager& MemoryManager(); | 
					
						
							| 
									
										
										
										
											2018-03-22 15:19:35 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 10:57:56 -04:00
										 |  |  |     /// Returns a const reference to the GPU memory manager.
 | 
					
						
							|  |  |  |     const Tegra::MemoryManager& MemoryManager() const; | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-23 23:20:56 -05:00
										 |  |  |     /// Returns a reference to the GPU DMA pusher.
 | 
					
						
							|  |  |  |     Tegra::DmaPusher& DmaPusher(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Returns a const reference to the GPU DMA pusher.
 | 
					
						
							|  |  |  |     const Tegra::DmaPusher& DmaPusher() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 18:49:18 -08:00
										 |  |  |     struct Regs { | 
					
						
							|  |  |  |         static constexpr size_t NUM_REGS = 0x100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         union { | 
					
						
							|  |  |  |             struct { | 
					
						
							|  |  |  |                 INSERT_PADDING_WORDS(0x4); | 
					
						
							|  |  |  |                 struct { | 
					
						
							|  |  |  |                     u32 address_high; | 
					
						
							|  |  |  |                     u32 address_low; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     GPUVAddr SmaphoreAddress() const { | 
					
						
							|  |  |  |                         return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | | 
					
						
							|  |  |  |                                                      address_low); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } smaphore_address; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 u32 semaphore_sequence; | 
					
						
							|  |  |  |                 u32 semaphore_trigger; | 
					
						
							|  |  |  |                 INSERT_PADDING_WORDS(0xC); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // The puser and the puller share the reference counter, the pusher only has read
 | 
					
						
							|  |  |  |                 // access
 | 
					
						
							|  |  |  |                 u32 reference_count; | 
					
						
							|  |  |  |                 INSERT_PADDING_WORDS(0x5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 u32 semaphore_acquire; | 
					
						
							|  |  |  |                 u32 semaphore_release; | 
					
						
							|  |  |  |                 INSERT_PADDING_WORDS(0xE4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Puller state
 | 
					
						
							|  |  |  |                 u32 acquire_mode; | 
					
						
							|  |  |  |                 u32 acquire_source; | 
					
						
							|  |  |  |                 u32 acquire_active; | 
					
						
							|  |  |  |                 u32 acquire_timeout; | 
					
						
							|  |  |  |                 u32 acquire_value; | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |             std::array<u32, NUM_REGS> reg_array; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } regs{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2018-11-23 23:20:56 -05:00
										 |  |  |     std::unique_ptr<Tegra::DmaPusher> dma_pusher; | 
					
						
							| 
									
										
										
										
											2018-08-28 10:57:56 -04:00
										 |  |  |     std::unique_ptr<Tegra::MemoryManager> memory_manager; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  |     /// Mapping of command subchannels to their bound engine ids.
 | 
					
						
							| 
									
										
										
										
											2018-09-04 13:54:50 +02:00
										 |  |  |     std::array<EngineID, 8> bound_engines = {}; | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// 3D engine
 | 
					
						
							|  |  |  |     std::unique_ptr<Engines::Maxwell3D> maxwell_3d; | 
					
						
							|  |  |  |     /// 2D engine
 | 
					
						
							|  |  |  |     std::unique_ptr<Engines::Fermi2D> fermi_2d; | 
					
						
							|  |  |  |     /// Compute engine
 | 
					
						
							| 
									
										
										
										
											2019-01-22 20:49:31 -03:00
										 |  |  |     std::unique_ptr<Engines::KeplerCompute> kepler_compute; | 
					
						
							| 
									
										
										
										
											2018-06-10 17:02:33 -05:00
										 |  |  |     /// DMA engine
 | 
					
						
							|  |  |  |     std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; | 
					
						
							| 
									
										
										
										
											2018-09-08 15:58:20 -05:00
										 |  |  |     /// Inline memory engine
 | 
					
						
							|  |  |  |     std::unique_ptr<Engines::KeplerMemory> kepler_memory; | 
					
						
							| 
									
										
										
										
											2019-01-29 18:49:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void ProcessBindMethod(const MethodCall& method_call); | 
					
						
							|  |  |  |     void ProcessSemaphoreTriggerMethod(); | 
					
						
							|  |  |  |     void ProcessSemaphoreRelease(); | 
					
						
							|  |  |  |     void ProcessSemaphoreAcquire(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Calls a GPU puller method.
 | 
					
						
							|  |  |  |     void CallPullerMethod(const MethodCall& method_call); | 
					
						
							|  |  |  |     // Calls a GPU engine method.
 | 
					
						
							|  |  |  |     void CallEngineMethod(const MethodCall& method_call); | 
					
						
							|  |  |  |     // Determines where the method should be executed.
 | 
					
						
							|  |  |  |     bool ExecuteMethodOnEngine(const MethodCall& method_call); | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 18:49:18 -08:00
										 |  |  | #define ASSERT_REG_POSITION(field_name, position)                                                  \
 | 
					
						
							|  |  |  |     static_assert(offsetof(GPU::Regs, field_name) == position * 4,                                 \ | 
					
						
							|  |  |  |                   "Field " #field_name " has invalid position") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASSERT_REG_POSITION(smaphore_address, 0x4); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(semaphore_sequence, 0x6); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(semaphore_trigger, 0x7); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(reference_count, 0x14); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(semaphore_acquire, 0x1A); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(semaphore_release, 0x1B); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASSERT_REG_POSITION(acquire_mode, 0x100); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(acquire_source, 0x101); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(acquire_active, 0x102); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(acquire_timeout, 0x103); | 
					
						
							|  |  |  | ASSERT_REG_POSITION(acquire_value, 0x104); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef ASSERT_REG_POSITION
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | } // namespace Tegra
 |