aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/State
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-13 03:02:07 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit1876b346fea647e8284a66bb6d62c38801035cff (patch)
tree6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics.Gpu/State
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'Ryujinx.Graphics.Gpu/State')
-rw-r--r--Ryujinx.Graphics.Gpu/State/BlendState.cs15
-rw-r--r--Ryujinx.Graphics.Gpu/State/Bool.cs17
-rw-r--r--Ryujinx.Graphics.Gpu/State/ClearColors.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/State/Condition.cs11
-rw-r--r--Ryujinx.Graphics.Gpu/State/ConditionState.cs8
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyBufferParams.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs22
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyBufferTexture.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyRegion.cs14
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyTexture.cs15
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyTextureControl.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/State/DepthBiasState.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/State/FaceState.cs11
-rw-r--r--Ryujinx.Graphics.Gpu/State/GpuState.cs425
-rw-r--r--Ryujinx.Graphics.Gpu/State/GpuVa.cs18
-rw-r--r--Ryujinx.Graphics.Gpu/State/IndexBufferState.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/State/Inline2MemoryParams.cs17
-rw-r--r--Ryujinx.Graphics.Gpu/State/MemoryLayout.cs32
-rw-r--r--Ryujinx.Graphics.Gpu/State/MethodOffset.cs62
-rw-r--r--Ryujinx.Graphics.Gpu/State/PoolState.cs8
-rw-r--r--Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs8
-rw-r--r--Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs50
-rw-r--r--Ryujinx.Graphics.Gpu/State/ReportCounterType.cs25
-rw-r--r--Ryujinx.Graphics.Gpu/State/ReportMode.cs8
-rw-r--r--Ryujinx.Graphics.Gpu/State/ReportState.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/State/ResetCounterType.cs21
-rw-r--r--Ryujinx.Graphics.Gpu/State/RtColorMask.cs27
-rw-r--r--Ryujinx.Graphics.Gpu/State/RtColorState.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/State/RtDepthStencilState.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/State/RtFormat.cs137
-rw-r--r--Ryujinx.Graphics.Gpu/State/ShaderState.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/State/ShaderType.cs11
-rw-r--r--Ryujinx.Graphics.Gpu/State/Size3D.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/State/StateWriteFlags.cs34
-rw-r--r--Ryujinx.Graphics.Gpu/State/StencilBackMasks.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs14
-rw-r--r--Ryujinx.Graphics.Gpu/State/StencilTestState.cs17
-rw-r--r--Ryujinx.Graphics.Gpu/State/UniformBufferState.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/State/VertexAttribState.cs22
-rw-r--r--Ryujinx.Graphics.Gpu/State/VertexBufferDrawState.cs8
-rw-r--r--Ryujinx.Graphics.Gpu/State/VertexBufferState.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/State/ViewportExtents.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/State/ViewportTransform.cs36
43 files changed, 1271 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/State/BlendState.cs b/Ryujinx.Graphics.Gpu/State/BlendState.cs
new file mode 100644
index 00000000..cf22dc1b
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/BlendState.cs
@@ -0,0 +1,15 @@
+using Ryujinx.Graphics.GAL.Blend;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct BlendState
+ {
+ public Bool SeparateAlpha;
+ public BlendOp ColorOp;
+ public BlendFactor ColorSrcFactor;
+ public BlendFactor ColorDstFactor;
+ public BlendOp AlphaOp;
+ public BlendFactor AlphaSrcFactor;
+ public BlendFactor AlphaDstFactor;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/Bool.cs b/Ryujinx.Graphics.Gpu/State/Bool.cs
new file mode 100644
index 00000000..8aadcfcc
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/Bool.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct Bool
+ {
+ private uint _value;
+
+ public bool IsTrue()
+ {
+ return (_value & 1) != 0;
+ }
+
+ public bool IsFalse()
+ {
+ return (_value & 1) == 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ClearColors.cs b/Ryujinx.Graphics.Gpu/State/ClearColors.cs
new file mode 100644
index 00000000..584c4791
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ClearColors.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ClearColors
+ {
+ public float Red;
+ public float Green;
+ public float Blue;
+ public float Alpha;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/Condition.cs b/Ryujinx.Graphics.Gpu/State/Condition.cs
new file mode 100644
index 00000000..41cce519
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/Condition.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum Condition
+ {
+ Never,
+ Always,
+ ResultNonZero,
+ Equal,
+ NotEqual
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ConditionState.cs b/Ryujinx.Graphics.Gpu/State/ConditionState.cs
new file mode 100644
index 00000000..24302c60
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ConditionState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ConditionState
+ {
+ public GpuVa Address;
+ public Condition Condition;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/CopyBufferParams.cs b/Ryujinx.Graphics.Gpu/State/CopyBufferParams.cs
new file mode 100644
index 00000000..2876dedd
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyBufferParams.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyBufferParams
+ {
+ public GpuVa SrcAddress;
+ public GpuVa DstAddress;
+ public int SrcStride;
+ public int DstStride;
+ public int XCount;
+ public int YCount;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs b/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs
new file mode 100644
index 00000000..24071372
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyBufferSwizzle
+ {
+ public uint Swizzle;
+
+ public int UnpackComponentSize()
+ {
+ return (int)((Swizzle >> 16) & 3) + 1;
+ }
+
+ public int UnpackSrcComponentsCount()
+ {
+ return (int)((Swizzle >> 20) & 7) + 1;
+ }
+
+ public int UnpackDstComponentsCount()
+ {
+ return (int)((Swizzle >> 24) & 7) + 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/CopyBufferTexture.cs b/Ryujinx.Graphics.Gpu/State/CopyBufferTexture.cs
new file mode 100644
index 00000000..cb63c607
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyBufferTexture.cs
@@ -0,0 +1,13 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyBufferTexture
+ {
+ public MemoryLayout MemoryLayout;
+ public int Width;
+ public int Height;
+ public int Depth;
+ public int RegionZ;
+ public ushort RegionX;
+ public ushort RegionY;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/CopyRegion.cs b/Ryujinx.Graphics.Gpu/State/CopyRegion.cs
new file mode 100644
index 00000000..cad9a5db
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyRegion.cs
@@ -0,0 +1,14 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyRegion
+ {
+ public int DstX;
+ public int DstY;
+ public int DstWidth;
+ public int DstHeight;
+ public long SrcWidthRF;
+ public long SrcHeightRF;
+ public long SrcXF;
+ public long SrcYF;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/CopyTexture.cs b/Ryujinx.Graphics.Gpu/State/CopyTexture.cs
new file mode 100644
index 00000000..363d84a2
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyTexture.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyTexture
+ {
+ public RtFormat Format;
+ public bool LinearLayout;
+ public MemoryLayout MemoryLayout;
+ public int Depth;
+ public int Layer;
+ public int Stride;
+ public int Width;
+ public int Height;
+ public GpuVa Address;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/CopyTextureControl.cs b/Ryujinx.Graphics.Gpu/State/CopyTextureControl.cs
new file mode 100644
index 00000000..c49cf276
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/CopyTextureControl.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct CopyTextureControl
+ {
+ public uint Packed;
+
+ public bool UnpackLinearFilter()
+ {
+ return (Packed & (1u << 4)) != 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs b/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs
new file mode 100644
index 00000000..c88d27dd
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct DepthBiasState
+ {
+ public Bool PointEnable;
+ public Bool LineEnable;
+ public Bool FillEnable;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/FaceState.cs b/Ryujinx.Graphics.Gpu/State/FaceState.cs
new file mode 100644
index 00000000..53763032
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/FaceState.cs
@@ -0,0 +1,11 @@
+using Ryujinx.Graphics.GAL;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct FaceState
+ {
+ public Bool CullEnable;
+ public FrontFace FrontFace;
+ public Face CullFace;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs
new file mode 100644
index 00000000..4e4241ca
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs
@@ -0,0 +1,425 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ class GpuState
+ {
+ private const int RegistersCount = 0xe00;
+
+ public delegate void MethodCallback(int argument);
+
+ private int[] _backingMemory;
+
+ private struct Register
+ {
+ public MethodCallback Callback;
+
+ public StateWriteFlags WriteFlag;
+ }
+
+ private Register[] _registers;
+
+ public StateWriteFlags StateWriteFlags { get; set; }
+
+ public GpuState()
+ {
+ _backingMemory = new int[RegistersCount];
+
+ _registers = new Register[RegistersCount];
+
+ StateWriteFlags = StateWriteFlags.Any;
+
+ InitializeDefaultState();
+ InitializeStateWatchers();
+ }
+
+ public bool ExitEarly;
+
+ public void CallMethod(MethodParams meth)
+ {
+ if (ExitEarly)
+ {
+ return;
+ }
+
+ Register register = _registers[meth.Method];
+
+ if (_backingMemory[meth.Method] != meth.Argument)
+ {
+ StateWriteFlags |= register.WriteFlag;
+ }
+
+ _backingMemory[meth.Method] = meth.Argument;
+
+ MethodCallback callback = register.Callback;
+
+ if (callback != null)
+ {
+ callback(meth.Argument);
+ }
+ }
+
+ public int Read(int offset)
+ {
+ return _backingMemory[offset];
+ }
+
+ public void RegisterCopyBufferCallback(MethodCallback callback)
+ {
+ RegisterCallback(0xc0, callback);
+ }
+
+ public void RegisterCopyTextureCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x237, callback);
+ }
+
+ public void RegisterDrawEndCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x585, callback);
+ }
+
+ public void RegisterDrawBeginCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x586, callback);
+ }
+
+ public void RegisterSetIndexCountCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x5f8, callback);
+ }
+
+ public void RegisterClearCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x674, callback);
+ }
+
+ public void RegisterReportCallback(MethodCallback callback)
+ {
+ RegisterCallback(0x6c3, callback);
+ }
+
+ public void RegisterUniformBufferUpdateCallback(MethodCallback callback)
+ {
+ for (int index = 0; index < 16; index++)
+ {
+ RegisterCallback(0x8e4 + index, callback);
+ }
+ }
+
+ public void RegisterUniformBufferBind0Callback(MethodCallback callback)
+ {
+ RegisterCallback(0x904, callback);
+ }
+
+ public void RegisterUniformBufferBind1Callback(MethodCallback callback)
+ {
+ RegisterCallback(0x90c, callback);
+ }
+
+ public void RegisterUniformBufferBind2Callback(MethodCallback callback)
+ {
+ RegisterCallback(0x914, callback);
+ }
+
+ public void RegisterUniformBufferBind3Callback(MethodCallback callback)
+ {
+ RegisterCallback(0x91c, callback);
+ }
+
+ public void RegisterUniformBufferBind4Callback(MethodCallback callback)
+ {
+ RegisterCallback(0x924, callback);
+ }
+
+ public CopyTexture GetCopyDstTexture()
+ {
+ return Get<CopyTexture>(MethodOffset.CopyDstTexture);
+ }
+
+ public CopyTexture GetCopySrcTexture()
+ {
+ return Get<CopyTexture>(MethodOffset.CopySrcTexture);
+ }
+
+ public RtColorState GetRtColorState(int index)
+ {
+ return Get<RtColorState>(MethodOffset.RtColorState + 16 * index);
+ }
+
+ public CopyTextureControl GetCopyTextureControl()
+ {
+ return Get<CopyTextureControl>(MethodOffset.CopyTextureControl);
+ }
+
+ public CopyRegion GetCopyRegion()
+ {
+ return Get<CopyRegion>(MethodOffset.CopyRegion);
+ }
+
+ public ViewportTransform GetViewportTransform(int index)
+ {
+ return Get<ViewportTransform>(MethodOffset.ViewportTransform + 8 * index);
+ }
+
+ public ViewportExtents GetViewportExtents(int index)
+ {
+ return Get<ViewportExtents>(MethodOffset.ViewportExtents + 4 * index);
+ }
+
+ public VertexBufferDrawState GetVertexBufferDrawState()
+ {
+ return Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
+ }
+
+ public ClearColors GetClearColors()
+ {
+ return Get<ClearColors>(MethodOffset.ClearColors);
+ }
+
+ public float GetClearDepthValue()
+ {
+ return Get<float>(MethodOffset.ClearDepthValue);
+ }
+
+ public int GetClearStencilValue()
+ {
+ return _backingMemory[(int)MethodOffset.ClearStencilValue];
+ }
+
+ public StencilBackMasks GetStencilBackMasks()
+ {
+ return Get<StencilBackMasks>(MethodOffset.StencilBackMasks);
+ }
+
+ public RtDepthStencilState GetRtDepthStencilState()
+ {
+ return Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
+ }
+
+ public VertexAttribState GetVertexAttribState(int index)
+ {
+ return Get<VertexAttribState>(MethodOffset.VertexAttribState + index);
+ }
+
+ public Size3D GetRtDepthStencilSize()
+ {
+ return Get<Size3D>(MethodOffset.RtDepthStencilSize);
+ }
+
+ public Bool GetDepthTestEnable()
+ {
+ return Get<Bool>(MethodOffset.DepthTestEnable);
+ }
+
+ public CompareOp GetDepthTestFunc()
+ {
+ return Get<CompareOp>(MethodOffset.DepthTestFunc);
+ }
+
+ public Bool GetDepthWriteEnable()
+ {
+ return Get<Bool>(MethodOffset.DepthWriteEnable);
+ }
+
+ public Bool GetBlendEnable(int index)
+ {
+ return Get<Bool>(MethodOffset.BlendEnable + index);
+ }
+
+ public StencilTestState GetStencilTestState()
+ {
+ return Get<StencilTestState>(MethodOffset.StencilTestState);
+ }
+
+ public int GetBaseVertex()
+ {
+ return _backingMemory[(int)MethodOffset.FirstVertex];
+ }
+
+ public int GetBaseInstance()
+ {
+ return _backingMemory[(int)MethodOffset.FirstInstance];
+ }
+
+ public PoolState GetSamplerPoolState()
+ {
+ return Get<PoolState>(MethodOffset.SamplerPoolState);
+ }
+
+ public PoolState GetTexturePoolState()
+ {
+ return Get<PoolState>(MethodOffset.TexturePoolState);
+ }
+
+ public StencilBackTestState GetStencilBackTestState()
+ {
+ return Get<StencilBackTestState>(MethodOffset.StencilBackTestState);
+ }
+
+ public TextureMsaaMode GetRtMsaaMode()
+ {
+ return Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
+ }
+
+ public GpuVa GetShaderBaseAddress()
+ {
+ return Get<GpuVa>(MethodOffset.ShaderBaseAddress);
+ }
+
+ public PrimitiveRestartState GetPrimitiveRestartState()
+ {
+ return Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
+ }
+
+ public IndexBufferState GetIndexBufferState()
+ {
+ return Get<IndexBufferState>(MethodOffset.IndexBufferState);
+ }
+
+ public FaceState GetFaceState()
+ {
+ return Get<FaceState>(MethodOffset.FaceState);
+ }
+
+ public ReportState GetReportState()
+ {
+ return Get<ReportState>(MethodOffset.ReportState);
+ }
+
+ public VertexBufferState GetVertexBufferState(int index)
+ {
+ return Get<VertexBufferState>(MethodOffset.VertexBufferState + 4 * index);
+ }
+
+ public BlendState GetBlendState(int index)
+ {
+ return Get<BlendState>(MethodOffset.BlendState + 8 * index);
+ }
+
+ public GpuVa GetVertexBufferEndAddress(int index)
+ {
+ return Get<GpuVa>(MethodOffset.VertexBufferEndAddress + 2 * index);
+ }
+
+ public ShaderState GetShaderState(int index)
+ {
+ return Get<ShaderState>(MethodOffset.ShaderState + 16 * index);
+ }
+
+ public UniformBufferState GetUniformBufferState()
+ {
+ return Get<UniformBufferState>(MethodOffset.UniformBufferState);
+ }
+
+ public void SetUniformBufferOffset(int offset)
+ {
+ _backingMemory[(int)MethodOffset.UniformBufferState + 3] = offset;
+ }
+
+ public int GetTextureBufferIndex()
+ {
+ return _backingMemory[(int)MethodOffset.TextureBufferIndex];
+ }
+
+ private void InitializeDefaultState()
+ {
+ // Depth ranges.
+ for (int index = 0; index < 8; index++)
+ {
+ _backingMemory[(int)MethodOffset.ViewportExtents + index * 4 + 2] = 0;
+ _backingMemory[(int)MethodOffset.ViewportExtents + index * 4 + 3] = 0x3F800000;
+ }
+
+ // Default front stencil mask.
+ _backingMemory[0x4e7] = 0xff;
+
+ // Default color mask.
+ _backingMemory[(int)MethodOffset.RtColorMask] = 0x1111;
+ }
+
+ private void InitializeStateWatchers()
+ {
+ SetWriteStateFlag(MethodOffset.RtColorState, StateWriteFlags.RtColorState, 16 * 8);
+
+ SetWriteStateFlag(MethodOffset.ViewportTransform, StateWriteFlags.ViewportTransform, 8 * 8);
+ SetWriteStateFlag(MethodOffset.ViewportExtents, StateWriteFlags.ViewportTransform, 4 * 8);
+
+ SetWriteStateFlag<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState, StateWriteFlags.VertexBufferState);
+
+ SetWriteStateFlag<DepthBiasState>(MethodOffset.DepthBiasState, StateWriteFlags.DepthBiasState);
+
+ SetWriteStateFlag(MethodOffset.DepthBiasFactor, StateWriteFlags.DepthBiasState, 1);
+ SetWriteStateFlag(MethodOffset.DepthBiasUnits, StateWriteFlags.DepthBiasState, 1);
+ SetWriteStateFlag(MethodOffset.DepthBiasClamp, StateWriteFlags.DepthBiasState, 1);
+
+ SetWriteStateFlag<RtDepthStencilState>(MethodOffset.RtDepthStencilState, StateWriteFlags.RtDepthStencilState);
+ SetWriteStateFlag<Size3D> (MethodOffset.RtDepthStencilSize, StateWriteFlags.RtDepthStencilState);
+
+ SetWriteStateFlag(MethodOffset.DepthTestEnable, StateWriteFlags.DepthTestState, 1);
+ SetWriteStateFlag(MethodOffset.DepthWriteEnable, StateWriteFlags.DepthTestState, 1);
+ SetWriteStateFlag(MethodOffset.DepthTestFunc, StateWriteFlags.DepthTestState, 1);
+
+ SetWriteStateFlag(MethodOffset.VertexAttribState, StateWriteFlags.VertexAttribState, 16);
+
+ SetWriteStateFlag<StencilBackMasks> (MethodOffset.StencilBackMasks, StateWriteFlags.StencilTestState);
+ SetWriteStateFlag<StencilTestState> (MethodOffset.StencilTestState, StateWriteFlags.StencilTestState);
+ SetWriteStateFlag<StencilBackTestState>(MethodOffset.StencilBackTestState, StateWriteFlags.StencilTestState);
+
+ SetWriteStateFlag<PoolState>(MethodOffset.SamplerPoolState, StateWriteFlags.SamplerPoolState);
+ SetWriteStateFlag<PoolState>(MethodOffset.TexturePoolState, StateWriteFlags.TexturePoolState);
+
+ SetWriteStateFlag<ShaderState>(MethodOffset.ShaderBaseAddress, StateWriteFlags.ShaderState);
+
+ SetWriteStateFlag<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState, StateWriteFlags.PrimitiveRestartState);
+
+ SetWriteStateFlag<IndexBufferState>(MethodOffset.IndexBufferState, StateWriteFlags.IndexBufferState);
+
+ SetWriteStateFlag<FaceState>(MethodOffset.FaceState, StateWriteFlags.FaceState);
+
+ SetWriteStateFlag<RtColorMask>(MethodOffset.RtColorMask, StateWriteFlags.RtColorMask);
+
+ SetWriteStateFlag(MethodOffset.VertexBufferInstanced, StateWriteFlags.VertexBufferState, 16);
+ SetWriteStateFlag(MethodOffset.VertexBufferState, StateWriteFlags.VertexBufferState, 4 * 16);
+ SetWriteStateFlag(MethodOffset.VertexBufferEndAddress, StateWriteFlags.VertexBufferState, 2 * 16);
+
+ SetWriteStateFlag(MethodOffset.BlendEnable, StateWriteFlags.BlendState, 8);
+ SetWriteStateFlag(MethodOffset.BlendState, StateWriteFlags.BlendState, 8 * 8);
+
+ SetWriteStateFlag(MethodOffset.ShaderState, StateWriteFlags.ShaderState, 16 * 6);
+
+ SetWriteStateFlag(MethodOffset.TextureBufferIndex, StateWriteFlags.TexturePoolState, 1);
+ }
+
+ private void SetWriteStateFlag<T>(MethodOffset offset, StateWriteFlags flag)
+ {
+ SetWriteStateFlag(offset, flag, Marshal.SizeOf<T>());
+ }
+
+ private void SetWriteStateFlag(MethodOffset offset, StateWriteFlags flag, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ _registers[(int)offset + index].WriteFlag = flag;
+ }
+ }
+
+ public void RegisterCallback(MethodOffset offset, MethodCallback callback)
+ {
+ _registers[(int)offset].Callback = callback;
+ }
+
+ private void RegisterCallback(int offset, MethodCallback callback)
+ {
+ _registers[offset].Callback = callback;
+ }
+
+ public T Get<T>(MethodOffset offset) where T : struct
+ {
+ return MemoryMarshal.Cast<int, T>(_backingMemory.AsSpan().Slice((int)offset))[0];
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/GpuVa.cs b/Ryujinx.Graphics.Gpu/State/GpuVa.cs
new file mode 100644
index 00000000..01ad70b7
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/GpuVa.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct GpuVa
+ {
+ public uint High;
+ public uint Low;
+
+ public ulong Pack()
+ {
+ return Low | ((ulong)High << 32);
+ }
+
+ public bool IsNullPtr()
+ {
+ return (Low | High) == 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/IndexBufferState.cs b/Ryujinx.Graphics.Gpu/State/IndexBufferState.cs
new file mode 100644
index 00000000..8a07bb52
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/IndexBufferState.cs
@@ -0,0 +1,13 @@
+using Ryujinx.Graphics.GAL;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct IndexBufferState
+ {
+ public GpuVa Address;
+ public GpuVa EndAddress;
+ public IndexType Type;
+ public int First;
+ public int Count;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/Inline2MemoryParams.cs b/Ryujinx.Graphics.Gpu/State/Inline2MemoryParams.cs
new file mode 100644
index 00000000..10d24900
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/Inline2MemoryParams.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct Inline2MemoryParams
+ {
+ public int LineLengthIn;
+ public int LineCount;
+ public GpuVa DstAddress;
+ public int DstStride;
+ public MemoryLayout DstMemoryLayout;
+ public int DstWidth;
+ public int DstHeight;
+ public int DstDepth;
+ public int DstZ;
+ public int DstX;
+ public int DstY;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/MemoryLayout.cs b/Ryujinx.Graphics.Gpu/State/MemoryLayout.cs
new file mode 100644
index 00000000..8e53a36a
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/MemoryLayout.cs
@@ -0,0 +1,32 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct MemoryLayout
+ {
+ public uint Packed;
+
+ public int UnpackGobBlocksInX()
+ {
+ return 1 << (int)(Packed & 0xf);
+ }
+
+ public int UnpackGobBlocksInY()
+ {
+ return 1 << (int)((Packed >> 4) & 0xf);
+ }
+
+ public int UnpackGobBlocksInZ()
+ {
+ return 1 << (int)((Packed >> 8) & 0xf);
+ }
+
+ public bool UnpackIsLinear()
+ {
+ return (Packed & 0x1000) != 0;
+ }
+
+ public bool UnpackIsTarget3D()
+ {
+ return (Packed & 0x10000) != 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
new file mode 100644
index 00000000..91dffe9f
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -0,0 +1,62 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum MethodOffset
+ {
+ Inline2MemoryParams = 0x60,
+ Inline2MemoryExecute = 0x6c,
+ Inline2MemoryPushData = 0x6d,
+ CopyDstTexture = 0x80,
+ CopySrcTexture = 0x8c,
+ DispatchParamsAddress = 0xad,
+ Dispatch = 0xaf,
+ CopyBufferParams = 0x100,
+ CopyBufferSwizzle = 0x1c2,
+ CopyBufferDstTexture = 0x1c3,
+ CopyBufferSrcTexture = 0x1ca,
+ RtColorState = 0x200,
+ CopyTextureControl = 0x223,
+ CopyRegion = 0x22c,
+ ViewportTransform = 0x280,
+ ViewportExtents = 0x300,
+ VertexBufferDrawState = 0x35d,
+ ClearColors = 0x360,
+ ClearDepthValue = 0x364,
+ ClearStencilValue = 0x368,
+ DepthBiasState = 0x370,
+ StencilBackMasks = 0x3d5,
+ InvalidateTextures = 0x3dd,
+ RtDepthStencilState = 0x3f8,
+ VertexAttribState = 0x458,
+ RtDepthStencilSize = 0x48a,
+ DepthTestEnable = 0x4b3,
+ DepthWriteEnable = 0x4ba,
+ DepthTestFunc = 0x4c3,
+ BlendEnable = 0x4d8,
+ StencilTestState = 0x4e0,
+ FirstVertex = 0x50d,
+ FirstInstance = 0x50e,
+ ResetCounter = 0x54c,
+ RtDepthStencilEnable = 0x54e,
+ ConditionState = 0x554,
+ SamplerPoolState = 0x557,
+ DepthBiasFactor = 0x55b,
+ TexturePoolState = 0x55d,
+ StencilBackTestState = 0x565,
+ DepthBiasUnits = 0x56f,
+ RtMsaaMode = 0x574,
+ ShaderBaseAddress = 0x582,
+ PrimitiveRestartState = 0x591,
+ IndexBufferState = 0x5f2,
+ DepthBiasClamp = 0x61f,
+ VertexBufferInstanced = 0x620,
+ FaceState = 0x646,
+ RtColorMask = 0x680,
+ ReportState = 0x6c0,
+ VertexBufferState = 0x700,
+ BlendState = 0x780,
+ VertexBufferEndAddress = 0x7c0,
+ ShaderState = 0x800,
+ UniformBufferState = 0x8e0,
+ TextureBufferIndex = 0x982
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/PoolState.cs b/Ryujinx.Graphics.Gpu/State/PoolState.cs
new file mode 100644
index 00000000..3d51eb7e
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/PoolState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct PoolState
+ {
+ public GpuVa Address;
+ public int MaximumId;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs b/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs
new file mode 100644
index 00000000..21405be7
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct PrimitiveRestartState
+ {
+ public bool Enable;
+ public int Index;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs b/Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs
new file mode 100644
index 00000000..02df9ac1
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs
@@ -0,0 +1,50 @@
+using Ryujinx.Graphics.GAL;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum PrimitiveType
+ {
+ Points,
+ Lines,
+ LineLoop,
+ LineStrip,
+ Triangles,
+ TriangleStrip,
+ TriangleFan,
+ Quads,
+ QuadStrip,
+ Polygon,
+ LinesAdjacency,
+ LineStripAdjacency,
+ TrianglesAdjacency,
+ TriangleStripAdjacency,
+ Patches
+ }
+
+ static class PrimitiveTypeConverter
+ {
+ public static PrimitiveTopology Convert(this PrimitiveType topology)
+ {
+ switch (topology)
+ {
+ case PrimitiveType.Points: return PrimitiveTopology.Points;
+ case PrimitiveType.Lines: return PrimitiveTopology.Lines;
+ case PrimitiveType.LineLoop: return PrimitiveTopology.LineLoop;
+ case PrimitiveType.LineStrip: return PrimitiveTopology.LineStrip;
+ case PrimitiveType.Triangles: return PrimitiveTopology.Triangles;
+ case PrimitiveType.TriangleStrip: return PrimitiveTopology.TriangleStrip;
+ case PrimitiveType.TriangleFan: return PrimitiveTopology.TriangleFan;
+ case PrimitiveType.Quads: return PrimitiveTopology.Quads;
+ case PrimitiveType.QuadStrip: return PrimitiveTopology.QuadStrip;
+ case PrimitiveType.Polygon: return PrimitiveTopology.Polygon;
+ case PrimitiveType.LinesAdjacency: return PrimitiveTopology.LinesAdjacency;
+ case PrimitiveType.LineStripAdjacency: return PrimitiveTopology.LineStripAdjacency;
+ case PrimitiveType.TrianglesAdjacency: return PrimitiveTopology.TrianglesAdjacency;
+ case PrimitiveType.TriangleStripAdjacency: return PrimitiveTopology.TriangleStripAdjacency;
+ case PrimitiveType.Patches: return PrimitiveTopology.Patches;
+ }
+
+ return PrimitiveTopology.Triangles;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs b/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs
new file mode 100644
index 00000000..38a0de71
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs
@@ -0,0 +1,25 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum ReportCounterType
+ {
+ Zero = 0,
+ InputVertices = 1,
+ InputPrimitives = 3,
+ VertexShaderInvocations = 5,
+ GeometryShaderInvocations = 7,
+ GeometryShaderPrimitives = 9,
+ TransformFeedbackPrimitivesWritten = 0xb,
+ ClipperInputPrimitives = 0xf,
+ ClipperOutputPrimitives = 0x11,
+ PrimitivesGenerated = 0x12,
+ FragmentShaderInvocations = 0x13,
+ SamplesPassed = 0x15,
+ TessControlShaderInvocations = 0x1b,
+ TessEvaluationShaderInvocations = 0x1d,
+ TessEvaluationShaderPrimitives = 0x1f,
+ ZcullStats0 = 0x2a,
+ ZcullStats1 = 0x2c,
+ ZcullStats2 = 0x2e,
+ ZcullStats3 = 0x30
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/ReportMode.cs b/Ryujinx.Graphics.Gpu/State/ReportMode.cs
new file mode 100644
index 00000000..84af3d75
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ReportMode.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum ReportMode
+ {
+ Semaphore = 0,
+ Counter = 2
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/ReportState.cs b/Ryujinx.Graphics.Gpu/State/ReportState.cs
new file mode 100644
index 00000000..212281aa
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ReportState.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ReportState
+ {
+ public GpuVa Address;
+ public int Payload;
+ public uint Control;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ResetCounterType.cs b/Ryujinx.Graphics.Gpu/State/ResetCounterType.cs
new file mode 100644
index 00000000..49b3b6da
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ResetCounterType.cs
@@ -0,0 +1,21 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum ResetCounterType
+ {
+ SamplesPassed = 1,
+ ZcullStats = 2,
+ TransformFeedbackPrimitivesWritten = 0x10,
+ InputVertices = 0x12,
+ InputPrimitives = 0x13,
+ VertexShaderInvocations = 0x15,
+ TessControlShaderInvocations = 0x16,
+ TessEvaluationShaderInvocations = 0x17,
+ TessEvaluationShaderPrimitives = 0x18,
+ GeometryShaderInvocations = 0x1a,
+ GeometryShaderPrimitives = 0x1b,
+ ClipperInputPrimitives = 0x1c,
+ ClipperOutputPrimitives = 0x1d,
+ FragmentShaderInvocations = 0x1e,
+ PrimitivesGenerated = 0x1f
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/RtColorMask.cs b/Ryujinx.Graphics.Gpu/State/RtColorMask.cs
new file mode 100644
index 00000000..5992673f
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/RtColorMask.cs
@@ -0,0 +1,27 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct RtColorMask
+ {
+ public uint Packed;
+
+ public bool UnpackRed()
+ {
+ return (Packed & 0x1) != 0;
+ }
+
+ public bool UnpackGreen()
+ {
+ return (Packed & 0x10) != 0;
+ }
+
+ public bool UnpackBlue()
+ {
+ return (Packed & 0x100) != 0;
+ }
+
+ public bool UnpackAlpha()
+ {
+ return (Packed & 0x1000) != 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/RtColorState.cs b/Ryujinx.Graphics.Gpu/State/RtColorState.cs
new file mode 100644
index 00000000..bb6ae208
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/RtColorState.cs
@@ -0,0 +1,13 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct RtColorState
+ {
+ public GpuVa Address;
+ public int WidthOrStride;
+ public int Height;
+ public RtFormat Format;
+ public MemoryLayout MemoryLayout;
+ public int Depth;
+ public int LayerSize;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/RtDepthStencilState.cs b/Ryujinx.Graphics.Gpu/State/RtDepthStencilState.cs
new file mode 100644
index 00000000..bfa812cb
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/RtDepthStencilState.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct RtDepthStencilState
+ {
+ public GpuVa Address;
+ public RtFormat Format;
+ public MemoryLayout MemoryLayout;
+ public int LayerSize;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/RtFormat.cs b/Ryujinx.Graphics.Gpu/State/RtFormat.cs
new file mode 100644
index 00000000..960da445
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/RtFormat.cs
@@ -0,0 +1,137 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum RtFormat
+ {
+ D32Float = 0xa,
+ D16Unorm = 0x13,
+ D24UnormS8Uint = 0x14,
+ S8Uint = 0x17,
+ D32FloatS8Uint = 0x19,
+ R32G32B32A32Float = 0xc0,
+ R32G32B32A32Sint = 0xc1,
+ R32G32B32A32Uint = 0xc2,
+ R32G32B32X32Float = 0xc3,
+ R32G32B32X32Sint = 0xc4,
+ R32G32B32X32Uint = 0xc5,
+ R16G16B16X16Unorm = 0xc6,
+ R16G16B16X16Snorm = 0xc7,
+ R16G16B16X16Sint = 0xc8,
+ R16G16B16X16Uint = 0xc9,
+ R16G16B16A16Float = 0xca,
+ R32G32Float = 0xcb,
+ R32G32Sint = 0xcc,
+ R32G32Uint = 0xcd,
+ R16G16B16X16Float = 0xce,
+ B8G8R8A8Unorm = 0xcf,
+ B8G8R8A8Srgb = 0xd0,
+ R10G10B10A2Unorm = 0xd1,
+ R10G10B10A2Uint = 0xd2,
+ R8G8B8A8Unorm = 0xd5,
+ R8G8B8A8Srgb = 0xd6,
+ R8G8B8X8Snorm = 0xd7,
+ R8G8B8X8Sint = 0xd8,
+ R8G8B8X8Uint = 0xd9,
+ R16G16Unorm = 0xda,
+ R16G16Snorm = 0xdb,
+ R16G16Sint = 0xdc,
+ R16G16Uint = 0xdd,
+ R16G16Float = 0xde,
+ R11G11B10Float = 0xe0,
+ R32Sint = 0xe3,
+ R32Uint = 0xe4,
+ R32Float = 0xe5,
+ B8G8R8X8Unorm = 0xe6,
+ B8G8R8X8Srgb = 0xe7,
+ B5G6R5Unorm = 0xe8,
+ B5G5R5A1Unorm = 0xe9,
+ R8G8Unorm = 0xea,
+ R8G8Snorm = 0xeb,
+ R8G8Sint = 0xec,
+ R8G8Uint = 0xed,
+ R16Unorm = 0xee,
+ R16Snorm = 0xef,
+ R16Sint = 0xf0,
+ R16Uint = 0xf1,
+ R16Float = 0xf2,
+ R8Unorm = 0xf3,
+ R8Snorm = 0xf4,
+ R8Sint = 0xf5,
+ R8Uint = 0xf6,
+ B5G5R5X1Unorm = 0xf8,
+ R8G8B8X8Unorm = 0xf9,
+ R8G8B8X8Srgb = 0xfa
+ }
+
+ static class RtFormatConverter
+ {
+ public static FormatInfo Convert(this RtFormat format)
+ {
+ switch (format)
+ {
+ case RtFormat.D32Float: return new FormatInfo(Format.D32Float, 1, 1, 4);
+ case RtFormat.D16Unorm: return new FormatInfo(Format.D16Unorm, 1, 1, 2);
+ case RtFormat.D24UnormS8Uint: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4);
+ case RtFormat.S8Uint: return new FormatInfo(Format.S8Uint, 1, 1, 1);
+ case RtFormat.D32FloatS8Uint: return new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8);
+ case RtFormat.R32G32B32A32Float: return new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16);
+ case RtFormat.R32G32B32A32Sint: return new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16);
+ case RtFormat.R32G32B32A32Uint: return new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16);
+ case RtFormat.R32G32B32X32Float: return new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16);
+ case RtFormat.R32G32B32X32Sint: return new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16);
+ case RtFormat.R32G32B32X32Uint: return new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16);
+ case RtFormat.R16G16B16X16Unorm: return new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8);
+ case RtFormat.R16G16B16X16Snorm: return new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8);
+ case RtFormat.R16G16B16X16Sint: return new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8);
+ case RtFormat.R16G16B16X16Uint: return new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8);
+ case RtFormat.R16G16B16A16Float: return new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8);
+ case RtFormat.R32G32Float: return new FormatInfo(Format.R32G32Float, 1, 1, 8);
+ case RtFormat.R32G32Sint: return new FormatInfo(Format.R32G32Sint, 1, 1, 8);
+ case RtFormat.R32G32Uint: return new FormatInfo(Format.R32G32Uint, 1, 1, 8);
+ case RtFormat.R16G16B16X16Float: return new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8);
+ case RtFormat.B8G8R8A8Unorm: return new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4);
+ case RtFormat.B8G8R8A8Srgb: return new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4);
+ case RtFormat.R10G10B10A2Unorm: return new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4);
+ case RtFormat.R10G10B10A2Uint: return new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4);
+ case RtFormat.R8G8B8A8Unorm: return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
+ case RtFormat.R8G8B8A8Srgb: return new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4);
+ case RtFormat.R8G8B8X8Snorm: return new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4);
+ case RtFormat.R8G8B8X8Sint: return new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4);
+ case RtFormat.R8G8B8X8Uint: return new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4);
+ case RtFormat.R16G16Unorm: return new FormatInfo(Format.R16G16Unorm, 1, 1, 4);
+ case RtFormat.R16G16Snorm: return new FormatInfo(Format.R16G16Snorm, 1, 1, 4);
+ case RtFormat.R16G16Sint: return new FormatInfo(Format.R16G16Sint, 1, 1, 4);
+ case RtFormat.R16G16Uint: return new FormatInfo(Format.R16G16Uint, 1, 1, 4);
+ case RtFormat.R16G16Float: return new FormatInfo(Format.R16G16Float, 1, 1, 4);
+ case RtFormat.R11G11B10Float: return new FormatInfo(Format.R11G11B10Float, 1, 1, 4);
+ case RtFormat.R32Sint: return new FormatInfo(Format.R32Sint, 1, 1, 4);
+ case RtFormat.R32Uint: return new FormatInfo(Format.R32Uint, 1, 1, 4);
+ case RtFormat.R32Float: return new FormatInfo(Format.R32Float, 1, 1, 4);
+ case RtFormat.B8G8R8X8Unorm: return new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4);
+ case RtFormat.B8G8R8X8Srgb: return new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4);
+ case RtFormat.B5G6R5Unorm: return new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2);
+ case RtFormat.B5G5R5A1Unorm: return new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2);
+ case RtFormat.R8G8Unorm: return new FormatInfo(Format.R8G8Unorm, 1, 1, 2);
+ case RtFormat.R8G8Snorm: return new FormatInfo(Format.R8G8Snorm, 1, 1, 2);
+ case RtFormat.R8G8Sint: return new FormatInfo(Format.R8G8Sint, 1, 1, 2);
+ case RtFormat.R8G8Uint: return new FormatInfo(Format.R8G8Uint, 1, 1, 2);
+ case RtFormat.R16Unorm: return new FormatInfo(Format.R16Unorm, 1, 1, 2);
+ case RtFormat.R16Snorm: return new FormatInfo(Format.R16Snorm, 1, 1, 2);
+ case RtFormat.R16Sint: return new FormatInfo(Format.R16Sint, 1, 1, 2);
+ case RtFormat.R16Uint: return new FormatInfo(Format.R16Uint, 1, 1, 2);
+ case RtFormat.R16Float: return new FormatInfo(Format.R16Float, 1, 1, 2);
+ case RtFormat.R8Unorm: return new FormatInfo(Format.R8Unorm, 1, 1, 1);
+ case RtFormat.R8Snorm: return new FormatInfo(Format.R8Snorm, 1, 1, 1);
+ case RtFormat.R8Sint: return new FormatInfo(Format.R8Sint, 1, 1, 1);
+ case RtFormat.R8Uint: return new FormatInfo(Format.R8Uint, 1, 1, 1);
+ case RtFormat.B5G5R5X1Unorm: return new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2);
+ case RtFormat.R8G8B8X8Unorm: return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
+ case RtFormat.R8G8B8X8Srgb: return new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4);
+ }
+
+ return FormatInfo.Default;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/ShaderState.cs b/Ryujinx.Graphics.Gpu/State/ShaderState.cs
new file mode 100644
index 00000000..536d7dcf
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ShaderState.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ShaderState
+ {
+ public uint Control;
+ public uint Offset;
+ public uint Unknown0x8;
+ public int MaxRegisters;
+ public ShaderType Type;
+ public uint Unknown0x14;
+ public uint Unknown0x18;
+ public uint Unknown0x1c;
+
+ public bool UnpackEnable()
+ {
+ return (Control & 1) != 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ShaderType.cs b/Ryujinx.Graphics.Gpu/State/ShaderType.cs
new file mode 100644
index 00000000..703159f4
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ShaderType.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum ShaderType
+ {
+ Vertex,
+ TessellationControl,
+ TessellationEvaluation,
+ Geometry,
+ Fragment
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/Size3D.cs b/Ryujinx.Graphics.Gpu/State/Size3D.cs
new file mode 100644
index 00000000..82771389
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/Size3D.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct Size3D
+ {
+ public int Width;
+ public int Height;
+ public int Depth;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/StateWriteFlags.cs b/Ryujinx.Graphics.Gpu/State/StateWriteFlags.cs
new file mode 100644
index 00000000..32d5127a
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/StateWriteFlags.cs
@@ -0,0 +1,34 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum StateWriteFlags
+ {
+ InputAssemblerGroup =
+ VertexAttribState |
+ PrimitiveRestartState |
+ IndexBufferState |
+ VertexBufferState,
+
+ RenderTargetGroup =
+ RtColorState |
+ RtDepthStencilState,
+
+ RtColorState = 1 << 0,
+ ViewportTransform = 1 << 1,
+ DepthBiasState = 1 << 2,
+ RtDepthStencilState = 1 << 3,
+ DepthTestState = 1 << 4,
+ VertexAttribState = 1 << 5,
+ StencilTestState = 1 << 6,
+ SamplerPoolState = 1 << 7,
+ TexturePoolState = 1 << 8,
+ PrimitiveRestartState = 1 << 9,
+ IndexBufferState = 1 << 10,
+ FaceState = 1 << 11,
+ RtColorMask = 1 << 12,
+ VertexBufferState = 1 << 13,
+ BlendState = 1 << 14,
+ ShaderState = 1 << 15,
+
+ Any = -1
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/StencilBackMasks.cs b/Ryujinx.Graphics.Gpu/State/StencilBackMasks.cs
new file mode 100644
index 00000000..d3779f87
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/StencilBackMasks.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct StencilBackMasks
+ {
+ public int FuncRef;
+ public int Mask;
+ public int FuncMask;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs b/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs
new file mode 100644
index 00000000..18b31eaa
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs
@@ -0,0 +1,14 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.GAL.DepthStencil;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct StencilBackTestState
+ {
+ public Bool TwoSided;
+ public StencilOp BackSFail;
+ public StencilOp BackDpFail;
+ public StencilOp BackDpPass;
+ public CompareOp BackFunc;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/StencilTestState.cs b/Ryujinx.Graphics.Gpu/State/StencilTestState.cs
new file mode 100644
index 00000000..b60f002f
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/StencilTestState.cs
@@ -0,0 +1,17 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.GAL.DepthStencil;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct StencilTestState
+ {
+ public Bool Enable;
+ public StencilOp FrontSFail;
+ public StencilOp FrontDpFail;
+ public StencilOp FrontDpPass;
+ public CompareOp FrontFunc;
+ public int FrontFuncRef;
+ public int FrontFuncMask;
+ public int FrontMask;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/UniformBufferState.cs b/Ryujinx.Graphics.Gpu/State/UniformBufferState.cs
new file mode 100644
index 00000000..80e4b6bc
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/UniformBufferState.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct UniformBufferState
+ {
+ public int Size;
+ public GpuVa Address;
+ public int Offset;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/VertexAttribState.cs b/Ryujinx.Graphics.Gpu/State/VertexAttribState.cs
new file mode 100644
index 00000000..0e327a75
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/VertexAttribState.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct VertexAttribState
+ {
+ public uint Attribute;
+
+ public int UnpackBufferIndex()
+ {
+ return (int)(Attribute & 0x1f);
+ }
+
+ public int UnpackOffset()
+ {
+ return (int)((Attribute >> 7) & 0x3fff);
+ }
+
+ public uint UnpackFormat()
+ {
+ return Attribute & 0x3fe00000;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/VertexBufferDrawState.cs b/Ryujinx.Graphics.Gpu/State/VertexBufferDrawState.cs
new file mode 100644
index 00000000..c2f3b7bb
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/VertexBufferDrawState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct VertexBufferDrawState
+ {
+ public int First;
+ public int Count;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/VertexBufferState.cs b/Ryujinx.Graphics.Gpu/State/VertexBufferState.cs
new file mode 100644
index 00000000..a8bd2c92
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/VertexBufferState.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct VertexBufferState
+ {
+ public uint Control;
+ public GpuVa Address;
+ public int Divisor;
+
+ public int UnpackStride()
+ {
+ return (int)(Control & 0xfff);
+ }
+
+ public bool UnpackEnable()
+ {
+ return (Control & (1 << 12)) != 0;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ViewportExtents.cs b/Ryujinx.Graphics.Gpu/State/ViewportExtents.cs
new file mode 100644
index 00000000..4be2db90
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ViewportExtents.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ViewportExtents
+ {
+ public ushort X;
+ public ushort Width;
+ public ushort Y;
+ public ushort Height;
+ public float DepthNear;
+ public float DepthFar;
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/ViewportTransform.cs b/Ryujinx.Graphics.Gpu/State/ViewportTransform.cs
new file mode 100644
index 00000000..335b039c
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/ViewportTransform.cs
@@ -0,0 +1,36 @@
+using Ryujinx.Graphics.GAL;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct ViewportTransform
+ {
+ public float ScaleX;
+ public float ScaleY;
+ public float ScaleZ;
+ public float TranslateX;
+ public float TranslateY;
+ public float TranslateZ;
+ public uint Swizzle;
+ public uint SubpixelPrecisionBias;
+
+ public ViewportSwizzle UnpackSwizzleX()
+ {
+ return (ViewportSwizzle)(Swizzle & 7);
+ }
+
+ public ViewportSwizzle UnpackSwizzleY()
+ {
+ return (ViewportSwizzle)((Swizzle >> 4) & 7);
+ }
+
+ public ViewportSwizzle UnpackSwizzleZ()
+ {
+ return (ViewportSwizzle)((Swizzle >> 8) & 7);
+ }
+
+ public ViewportSwizzle UnpackSwizzleW()
+ {
+ return (ViewportSwizzle)((Swizzle >> 12) & 7);
+ }
+ }
+}