diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-10-13 03:02:07 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 1876b346fea647e8284a66bb6d62c38801035cff (patch) | |
| tree | 6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics.Gpu/State/GpuState.cs | |
| parent | f617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff) | |
Initial work
Diffstat (limited to 'Ryujinx.Graphics.Gpu/State/GpuState.cs')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/State/GpuState.cs | 425 |
1 files changed, 425 insertions, 0 deletions
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]; + } + } +} |
