2021-03-24 21:09:21 +01:00
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
2021-08-20 22:17:13 +02:00
// Copyright © 2018-2020 fincs (https://github.com/devkitPro/deko3d)
2021-03-24 21:09:21 +01:00
# pragma once
2021-09-14 18:00:12 +02:00
# include <gpu/interconnect/graphics_context.h>
2021-03-24 21:09:21 +01:00
# include "engine.h"
2021-10-08 21:25:21 +02:00
namespace skyline : : soc : : gm20b {
struct ChannelContext ;
}
2021-03-24 21:09:21 +01:00
namespace skyline : : soc : : gm20b : : engine : : maxwell3d {
/**
* @ brief The Maxwell 3 D engine handles processing 3 D graphics
*/
2022-01-19 21:45:51 +01:00
class Maxwell3D : public MacroEngineBase {
2021-03-24 21:09:21 +01:00
private :
2022-01-19 21:45:51 +01:00
host1x : : SyncpointSet & syncpoints ;
2021-09-14 18:00:12 +02:00
gpu : : interconnect : : GraphicsContext context ;
2021-03-24 21:09:21 +01:00
2021-11-12 09:54:43 +01:00
/**
* @ brief Calls the appropriate function corresponding to a certain method with the supplied argument
*/
2021-11-12 09:59:17 +01:00
void HandleMethod ( u32 method , u32 argument ) ;
2021-11-12 09:54:43 +01:00
2021-07-23 04:57:11 +02:00
/**
* @ brief Writes back a semaphore result to the guest with an auto - generated timestamp ( if required )
* @ note If the semaphore is OneWord then the result will be downcasted to a 32 - bit unsigned integer
*/
2021-03-24 21:09:21 +01:00
void WriteSemaphoreResult ( u64 result ) ;
public :
static constexpr u32 RegisterCount { 0xE00 } ; //!< The number of Maxwell 3D registers
/**
2021-07-23 04:57:11 +02:00
* @ url https : //github.com/devkitPro/deko3d/blob/master/source/maxwell/engine_3d.def
2021-03-24 21:09:21 +01:00
*/
2021-04-16 17:05:24 +02:00
# pragma pack(push, 1)
2021-03-24 21:09:21 +01:00
union Registers {
std : : array < u32 , RegisterCount > raw ;
2021-11-10 17:01:45 +01:00
template < size_t Offset , typename Type >
using Register = util : : OffsetMember < Offset , Type , u32 > ;
Register < 0x40 , u32 > noOperation ;
Register < 0x44 , u32 > waitForIdle ;
struct MME {
u32 instructionRamPointer ; // 0x45
u32 instructionRamLoad ; // 0x46
u32 startAddressRamPointer ; // 0x47
u32 startAddressRamLoad ; // 0x48
type : : MmeShadowRamControl shadowRamControl ; // 0x49
} ;
Register < 0x45 , MME > mme ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0xB2 , type : : SyncpointAction > syncpointAction ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0xDF , u32 > rasterizerEnable ;
2021-12-07 20:13:39 +01:00
Register < 0x200 , std : : array < type : : ColorRenderTarget , type : : RenderTargetCount > > renderTargets ;
2021-11-10 17:01:45 +01:00
Register < 0x280 , std : : array < type : : ViewportTransform , type : : ViewportCount > > viewportTransforms ;
Register < 0x300 , std : : array < type : : Viewport , type : : ViewportCount > > viewports ;
2021-03-24 21:09:21 +01:00
2021-12-24 17:04:52 +01:00
Register < 0x35D , u32 > drawVertexFirst ; //!< The first vertex to draw
Register < 0x35E , u32 > drawVertexCount ; //!< The amount of vertices to draw, calling this method triggers non-indexed drawing
2021-12-06 22:48:25 +01:00
2022-03-16 21:51:49 +01:00
Register < 0x35F , type : : DepthMode > depthMode ;
2021-11-10 17:01:45 +01:00
Register < 0x360 , std : : array < u32 , 4 > > clearColorValue ;
2021-12-07 21:55:48 +01:00
Register < 0x364 , float > clearDepthValue ;
Register < 0x368 , u32 > clearStencilValue ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
struct PolygonMode {
type : : PolygonMode front ; // 0x36B
type : : PolygonMode back ; // 0x36C
} ;
Register < 0x36B , PolygonMode > polygonMode ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x380 , std : : array < type : : Scissor , type : : ViewportCount > > scissors ;
2021-03-24 21:09:21 +01:00
2021-11-11 21:11:04 +01:00
struct DepthBiasEnable {
u32 point ; // 0x370
u32 line ; // 0x371
u32 fill ; // 0x372
} ;
Register < 0x370 , DepthBiasEnable > depthBiasEnable ;
2021-11-10 17:01:45 +01:00
struct StencilBackExtra {
2022-01-12 21:57:43 +01:00
u32 compareReference ; // 0x3D5
2021-11-10 17:01:45 +01:00
u32 writeMask ; // 0x3D6
u32 compareMask ; // 0x3D7
} ;
Register < 0x3D5 , StencilBackExtra > stencilBackExtra ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x3D8 , u32 > tiledCacheEnable ;
struct TiledCacheSize {
u16 width ;
u16 height ;
} ;
Register < 0x3D9 , TiledCacheSize > tiledCacheSize ;
2021-11-15 19:25:32 +01:00
Register < 0x3E4 , u32 > commonColorWriteMask ; //!< If enabled, the color write masks for all RTs must be set to that of the first RT
2022-01-12 21:57:43 +01:00
Register < 0x3E7 , float > depthBoundsNear ;
Register < 0x3E8 , float > depthBoundsFar ;
2021-11-10 17:01:45 +01:00
Register < 0x3EB , u32 > rtSeparateFragData ;
2021-12-07 20:12:54 +01:00
2022-03-20 19:00:34 +01:00
Register < 0x3F8 , Address > depthTargetAddress ;
2021-12-07 20:12:54 +01:00
Register < 0x3FA , type : : DepthRtFormat > depthTargetFormat ;
Register < 0x3FB , type : : RenderTargetTileMode > depthTargetTileMode ;
Register < 0x3FC , u32 > depthTargetLayerStride ;
2021-11-16 16:50:34 +01:00
Register < 0x458 , std : : array < type : : VertexAttribute , type : : VertexAttributeCount > > vertexAttributeState ;
2022-01-12 21:57:43 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x487 , type : : RenderTargetControl > renderTargetControl ;
2021-12-07 20:12:54 +01:00
Register < 0x48A , u32 > depthTargetWidth ;
Register < 0x48B , u32 > depthTargetHeight ;
Register < 0x48C , type : : RenderTargetArrayMode > depthTargetArrayMode ;
2022-01-12 21:57:43 +01:00
Register < 0x4B3 , u32 > depthTestEnable ;
2021-11-15 19:22:47 +01:00
Register < 0x4B9 , u32 > independentBlendEnable ;
2022-01-12 21:57:43 +01:00
Register < 0x4BA , u32 > depthWriteEnable ;
2021-11-14 15:27:25 +01:00
Register < 0x4BB , u32 > alphaTestEnable ;
2021-11-10 17:01:45 +01:00
Register < 0x4C3 , type : : CompareOp > depthTestFunc ;
Register < 0x4C4 , float > alphaTestRef ;
Register < 0x4C5 , type : : CompareOp > alphaTestFunc ;
Register < 0x4C6 , u32 > drawTFBStride ;
struct BlendConstant {
2021-11-15 19:22:47 +01:00
float red ; // 0x4C7
float green ; // 0x4C8
float blue ; // 0x4C9
float alpha ; // 0x4CA
2021-11-10 17:01:45 +01:00
} ;
2021-11-15 19:22:47 +01:00
Register < 0x4C7 , std : : array < float , type : : BlendColorChannelCount > > blendConstant ;
2021-11-10 17:01:45 +01:00
2021-11-15 19:22:47 +01:00
struct BlendStateCommon {
2021-11-10 17:01:45 +01:00
u32 seperateAlpha ; // 0x4CF
2021-11-15 19:22:47 +01:00
type : : BlendOp colorOp ; // 0x4D0
type : : BlendFactor colorSrcFactor ; // 0x4D1
type : : BlendFactor colorDstFactor ; // 0x4D2
type : : BlendOp alphaOp ; // 0x4D3
type : : BlendFactor alphaSrcFactor ; // 0x4D4
u32 pad ; // 0x4D5
type : : BlendFactor alphaDstFactor ; // 0x4D6
u32 enable ; // 0x4D7
2021-11-10 17:01:45 +01:00
} ;
2021-11-15 19:22:47 +01:00
Register < 0x4CF , BlendStateCommon > blendStateCommon ;
Register < 0x4D8 , std : : array < u32 , type : : RenderTargetCount > > rtBlendEnable ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x4E0 , u32 > stencilEnable ;
struct StencilFront {
type : : StencilOp failOp ; // 0x4E1
type : : StencilOp zFailOp ; // 0x4E2
2022-01-12 21:57:43 +01:00
type : : StencilOp passOp ; // 0x4E3
2021-03-24 21:09:21 +01:00
2022-01-12 21:57:43 +01:00
type : : CompareOp compareOp ; // 0x4E4
u32 compareReference ; // 0x4E5
u32 compareMask ; // 0x4E6
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
u32 writeMask ; // 0x4E7
} ;
Register < 0x4E1 , StencilFront > stencilFront ;
2021-03-24 21:09:21 +01:00
2022-01-21 22:34:49 +01:00
struct WindowOriginMode {
bool isOriginLowerLeft : 1 ;
u8 _pad_ : 3 ;
bool flipFrontFace : 1 ;
} ;
Register < 0x4EB , WindowOriginMode > windowOriginMode ;
2021-11-10 17:01:45 +01:00
Register < 0x4EC , float > lineWidthSmooth ;
2021-11-14 16:19:42 +01:00
Register < 0x4ED , float > lineWidthAliased ;
2021-03-24 21:09:21 +01:00
2021-12-24 17:04:52 +01:00
Register < 0x50D , i32 > drawBaseVertex ;
2021-11-10 17:01:45 +01:00
Register < 0x50E , u32 > drawBaseInstance ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x544 , u32 > clipDistanceEnable ;
Register < 0x545 , u32 > sampleCounterEnable ;
Register < 0x546 , float > pointSpriteSize ;
Register < 0x547 , u32 > zCullStatCountersEnable ;
Register < 0x548 , u32 > pointSpriteEnable ;
Register < 0x54A , u32 > shaderExceptions ;
Register < 0x54D , u32 > multisampleEnable ;
Register < 0x54E , u32 > depthTargetEnable ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x54F , type : : MultisampleControl > multisampleControl ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
struct SamplerPool {
2022-03-20 19:00:34 +01:00
Address address ; // 0x557
2021-11-10 17:01:45 +01:00
u32 maximumIndex ; // 0x559
} ;
Register < 0x557 , SamplerPool > samplerPool ;
2021-03-24 21:09:21 +01:00
2021-11-11 21:11:04 +01:00
Register < 0x55B , float > depthBiasFactor ;
2021-11-10 17:01:45 +01:00
Register < 0x55C , u32 > lineSmoothEnable ;
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
struct TexturePool {
2022-03-20 19:00:34 +01:00
Address address ; // 0x55D
2021-11-10 17:01:45 +01:00
u32 maximumIndex ; // 0x55F
} ;
Register < 0x55D , TexturePool > texturePool ;
2021-03-24 21:09:21 +01:00
2022-01-22 00:42:48 +01:00
Register < 0x565 , u32 > stencilTwoSideEnable ; //!< Determines if the back-facing stencil state uses the front facing stencil state or independent stencil state
2021-03-24 21:09:21 +01:00
2021-11-10 17:01:45 +01:00
struct StencilBack {
type : : StencilOp failOp ; // 0x566
type : : StencilOp zFailOp ; // 0x567
2022-01-12 21:57:43 +01:00
type : : StencilOp passOp ; // 0x568
2021-11-10 17:01:45 +01:00
type : : CompareOp compareOp ; // 0x569
} ;
Register < 0x566 , StencilBack > stencilBack ;
2021-11-11 21:11:04 +01:00
Register < 0x56F , float > depthBiasUnits ;
2021-11-10 17:01:45 +01:00
Register < 0x581 , type : : PointCoordReplace > pointCoordReplace ;
2022-03-20 19:00:34 +01:00
Register < 0x582 , Address > setProgramRegion ;
2021-11-11 21:11:04 +01:00
2021-12-08 13:12:39 +01:00
Register < 0x585 , u32 > vertexEndGl ; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw
2021-11-17 12:28:03 +01:00
Register < 0x586 , type : : VertexBeginGl > vertexBeginGl ; //!< Similar to glVertexBegin semantically, supplies a primitive topology for draws alongside instancing data
2021-11-11 21:11:04 +01:00
Register < 0x5A1 , u32 > provokingVertexIsLast ;
2021-11-10 17:01:45 +01:00
2021-12-24 18:50:30 +01:00
Register < 0x5F2 , type : : IndexBuffer > indexBuffer ;
2022-01-22 00:42:48 +01:00
Register < 0x5F7 , u32 > drawIndexFirst ; //!< The first element in the index buffer to draw
2021-12-24 17:04:52 +01:00
Register < 0x5F8 , u32 > drawIndexCount ; //!< The amount of elements to draw, calling this method triggers indexed drawing
2021-11-16 10:43:15 +01:00
Register < 0x61F , float > depthBiasClamp ;
2021-11-16 10:58:05 +01:00
Register < 0x620 , std : : array < u32 , type : : VertexBufferCount > > isVertexInputRatePerInstance ; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance
2021-11-10 17:01:45 +01:00
Register < 0x646 , u32 > cullFaceEnable ;
Register < 0x647 , type : : FrontFace > frontFace ;
Register < 0x648 , type : : CullFace > cullFace ;
2021-11-11 21:11:04 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x649 , u32 > pixelCentreImage ;
Register < 0x64B , u32 > viewportTransformEnable ;
2021-11-16 10:43:15 +01:00
Register < 0x64F , type : : ViewVolumeClipControl > viewVolumeClipControl ;
2022-01-12 21:57:43 +01:00
Register < 0x66F , u32 > depthBoundsEnable ;
2021-11-16 10:43:15 +01:00
struct ColorLogicOp {
u32 enable ;
type : : ColorLogicOp type ;
} ;
Register < 0x671 , ColorLogicOp > colorLogicOp ;
2021-11-10 17:01:45 +01:00
Register < 0x674 , type : : ClearBuffers > clearBuffers ;
2021-11-15 19:25:32 +01:00
Register < 0x680 , std : : array < type : : ColorWriteMask , type : : RenderTargetCount > > colorWriteMask ;
2021-11-10 17:01:45 +01:00
struct Semaphore {
2022-03-20 19:00:34 +01:00
Address address ; // 0x6C0
2021-11-10 17:01:45 +01:00
u32 payload ; // 0x6C2
type : : SemaphoreInfo info ; // 0x6C3
2021-03-24 21:09:21 +01:00
} ;
2021-11-10 17:01:45 +01:00
Register < 0x6C0 , Semaphore > semaphore ;
2021-11-16 06:02:01 +01:00
struct VertexBuffer {
union {
u32 raw ;
struct {
u32 stride : 12 ;
u32 enable : 1 ;
} ;
} config ;
2022-03-20 19:00:34 +01:00
Address iova ;
2021-11-16 06:02:01 +01:00
u32 divisor ;
} ;
static_assert ( sizeof ( VertexBuffer ) = = sizeof ( u32 ) * 4 ) ;
Register < 0x700 , std : : array < VertexBuffer , type : : VertexBufferCount > > vertexBuffers ;
2021-11-15 19:22:47 +01:00
struct IndependentBlend {
u32 seperateAlpha ;
type : : BlendOp colorOp ;
type : : BlendFactor colorSrcFactor ;
type : : BlendFactor colorDstFactor ;
type : : BlendOp alphaOp ;
type : : BlendFactor alphaSrcFactor ;
type : : BlendFactor alphaDstFactor ;
u32 _pad_ ;
} ;
Register < 0x780 , std : : array < IndependentBlend , type : : RenderTargetCount > > independentBlend ;
2021-11-11 20:06:05 +01:00
2022-03-20 19:00:34 +01:00
Register < 0x7C0 , std : : array < Address , type : : VertexBufferCount > > vertexBufferLimits ; //!< A per-VBO IOVA denoting the end of the vertex buffer
2021-11-16 11:42:30 +01:00
2021-12-23 16:51:01 +01:00
Register < 0x800 , std : : array < type : : SetProgramInfo , type : : ShaderStageCount > > setProgram ;
2021-11-11 20:06:05 +01:00
2021-11-10 17:01:45 +01:00
Register < 0x8C0 , u32 [ 0x20 ] > firmwareCall ;
2021-12-11 08:27:30 +01:00
struct ConstantBufferSelector {
u32 size ;
2022-03-20 19:00:34 +01:00
Address address ;
2021-12-11 08:27:30 +01:00
} ;
Register < 0x8E0 , ConstantBufferSelector > constantBufferSelector ;
2021-12-23 18:33:00 +01:00
2022-01-05 20:20:55 +01:00
/**
* @ brief Allows updating the currently selected constant buffer inline with an offset and up to 16 words of data
*/
struct ConstantBufferUpdate {
u32 offset ;
std : : array < u32 , 16 > data ;
} ;
Register < 0x8E3 , ConstantBufferUpdate > constantBufferUpdate ;
2021-12-23 18:33:00 +01:00
Register < 0x900 , std : : array < type : : Bind , type : : PipelineStageCount > > bind ; //!< Binds constant buffers to pipeline stages
2021-12-24 17:35:58 +01:00
Register < 0x982 , u32 > bindlessTextureConstantBufferIndex ; //!< The index of the constant buffer containing bindless texture descriptors
2021-03-24 21:09:21 +01:00
} ;
static_assert ( sizeof ( Registers ) = = ( RegisterCount * sizeof ( u32 ) ) ) ;
2021-04-16 17:05:24 +02:00
# pragma pack(pop)
2021-03-24 21:09:21 +01:00
Registers registers { } ;
2021-07-23 04:57:11 +02:00
Registers shadowRegisters { } ; //!< A shadow-copy of the registers, their function is controlled by the 'shadowRamControl' register
2021-03-24 21:09:21 +01:00
2021-10-08 21:25:21 +02:00
ChannelContext & channelCtx ;
2021-03-24 21:09:21 +01:00
2022-01-19 21:45:51 +01:00
Maxwell3D ( const DeviceState & state , ChannelContext & channelCtx , MacroState & macroState , gpu : : interconnect : : CommandExecutor & executor ) ;
2021-03-24 21:09:21 +01:00
/**
2021-11-12 09:54:43 +01:00
* @ brief Initializes Maxwell 3 D registers to their default values
2021-03-24 21:09:21 +01:00
*/
2021-11-12 09:54:43 +01:00
void InitializeRegisters ( ) ;
2021-03-24 21:09:21 +01:00
2022-01-19 21:45:51 +01:00
void CallMethod ( u32 method , u32 argument ) ;
2022-03-04 20:41:22 +01:00
void CallMethodBatchNonInc ( u32 method , span < u32 > arguments ) ;
2022-01-19 21:45:51 +01:00
void CallMethodFromMacro ( u32 method , u32 argument ) override ;
u32 ReadMethodFromMacro ( u32 method ) override ;
2021-03-24 21:09:21 +01:00
} ;
}