From 2437ccca0e82b8b2a99d8632acf28ca0cc14c523 Mon Sep 17 00:00:00 2001 From: gdk Date: Thu, 21 Nov 2019 23:46:14 -0300 Subject: [PATCH] Separate sub-channel state --- Ryujinx.Graphics.Gpu/Engine/Compute.cs | 14 +- Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs | 6 +- Ryujinx.Graphics.Gpu/Engine/MethodClear.cs | 12 +- .../Engine/MethodCopyBuffer.cs | 10 +- .../Engine/MethodCopyTexture.cs | 10 +- Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs | 20 +- Ryujinx.Graphics.Gpu/Engine/MethodReport.cs | 18 +- .../Engine/MethodResetCounter.cs | 2 +- .../Engine/MethodUniformBufferBind.cs | 24 +- .../Engine/MethodUniformBufferUpdate.cs | 6 +- Ryujinx.Graphics.Gpu/Engine/Methods.cs | 216 +++++++++--------- Ryujinx.Graphics.Gpu/GpuContext.cs | 4 - Ryujinx.Graphics.Gpu/MacroInterpreter.cs | 31 +-- Ryujinx.Graphics.Gpu/NvGpuFifo.cs | 34 ++- Ryujinx.Graphics.Gpu/State/GpuState.cs | 4 +- 15 files changed, 213 insertions(+), 198 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs index 108cc197c8..ba7daf67a3 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs @@ -10,13 +10,13 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - public void Dispatch(int argument) + public void Dispatch(GpuState state, int argument) { - uint dispatchParamsAddress = (uint)_context.State.Get(MethodOffset.DispatchParamsAddress); + uint dispatchParamsAddress = (uint)state.Get(MethodOffset.DispatchParamsAddress); var dispatchParams = _context.MemoryAccessor.Read((ulong)dispatchParamsAddress << 8); - GpuVa shaderBaseAddress = _context.State.Get(MethodOffset.ShaderBaseAddress); + GpuVa shaderBaseAddress = state.Get(MethodOffset.ShaderBaseAddress); ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)dispatchParams.ShaderOffset; @@ -28,15 +28,15 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.BindProgram(cs.HostProgram); - var samplerPool = _context.State.Get(MethodOffset.SamplerPoolState); + var samplerPool = state.Get(MethodOffset.SamplerPoolState); _textureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); - var texturePool = _context.State.Get(MethodOffset.TexturePoolState); + var texturePool = state.Get(MethodOffset.TexturePoolState); _textureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); - _textureManager.SetComputeTextureBufferIndex(_context.State.Get(MethodOffset.TextureBufferIndex)); + _textureManager.SetComputeTextureBufferIndex(state.Get(MethodOffset.TextureBufferIndex)); ShaderProgramInfo info = cs.Shader.Program.Info; @@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Engine dispatchParams.UnpackGridSizeY(), dispatchParams.UnpackGridSizeZ()); - UpdateShaderState(); + UpdateShaderState(state); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs index 355b7394dc..09de992f88 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs @@ -12,9 +12,9 @@ namespace Ryujinx.Graphics.Gpu.Engine private int _offset; private int _size; - public void LaunchDma(int argument) + public void LaunchDma(GpuState state, int argument) { - _params = _context.State.Get(MethodOffset.I2mParams); + _params = state.Get(MethodOffset.I2mParams); _isLinear = (argument & 1) != 0; @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Engine _size = _params.LineLengthIn * _params.LineCount; } - public void LoadInlineData(int argument) + public void LoadInlineData(GpuState state, int argument) { if (_isLinear) { diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs index b50a176602..da6c94e57d 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs @@ -5,9 +5,9 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void Clear(int argument) + private void Clear(GpuState state, int argument) { - UpdateRenderTargetStateIfNeeded(); + UpdateRenderTargetStateIfNeeded(state); _textureManager.CommitGraphicsBindings(); @@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (componentMask != 0) { - var clearColor = _context.State.Get(MethodOffset.ClearColors); + var clearColor = state.Get(MethodOffset.ClearColors); ColorF color = new ColorF( clearColor.Red, @@ -33,14 +33,14 @@ namespace Ryujinx.Graphics.Gpu.Engine if (clearDepth || clearStencil) { - float depthValue = _context.State.Get(MethodOffset.ClearDepthValue); - int stencilValue = _context.State.Get (MethodOffset.ClearStencilValue); + float depthValue = state.Get(MethodOffset.ClearDepthValue); + int stencilValue = state.Get (MethodOffset.ClearStencilValue); int stencilMask = 0; if (clearStencil) { - stencilMask = _context.State.Get(MethodOffset.StencilTestState).FrontMask; + stencilMask = state.Get(MethodOffset.StencilTestState).FrontMask; } _context.Renderer.Pipeline.ClearRenderTargetDepthStencil( diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs index 40560ab13d..0bf836e1a6 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs @@ -6,11 +6,11 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void CopyBuffer(int argument) + private void CopyBuffer(GpuState state, int argument) { - var cbp = _context.State.Get(MethodOffset.CopyBufferParams); + var cbp = state.Get(MethodOffset.CopyBufferParams); - var swizzle = _context.State.Get(MethodOffset.CopyBufferSwizzle); + var swizzle = state.Get(MethodOffset.CopyBufferSwizzle); bool srcLinear = (argument & (1 << 7)) != 0; bool dstLinear = (argument & (1 << 8)) != 0; @@ -29,8 +29,8 @@ namespace Ryujinx.Graphics.Gpu.Engine int srcBpp = swizzle.UnpackSrcComponentsCount() * swizzle.UnpackComponentSize(); int dstBpp = swizzle.UnpackDstComponentsCount() * swizzle.UnpackComponentSize(); - var dst = _context.State.Get(MethodOffset.CopyBufferDstTexture); - var src = _context.State.Get(MethodOffset.CopyBufferSrcTexture); + var dst = state.Get(MethodOffset.CopyBufferDstTexture); + var src = state.Get(MethodOffset.CopyBufferSrcTexture); var srcCalculator = new OffsetCalculator( src.Width, diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs index 887f520d2c..c482451a33 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs @@ -5,10 +5,10 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void CopyTexture(int argument) + private void CopyTexture(GpuState state, int argument) { - var dstCopyTexture = _context.State.Get(MethodOffset.CopyDstTexture); - var srcCopyTexture = _context.State.Get(MethodOffset.CopySrcTexture); + var dstCopyTexture = state.Get(MethodOffset.CopyDstTexture); + var srcCopyTexture = state.Get(MethodOffset.CopySrcTexture); Image.Texture srcTexture = _textureManager.FindOrCreateTexture(srcCopyTexture); @@ -32,9 +32,9 @@ namespace Ryujinx.Graphics.Gpu.Engine return; } - var control = _context.State.Get(MethodOffset.CopyTextureControl); + var control = state.Get(MethodOffset.CopyTextureControl); - var region = _context.State.Get(MethodOffset.CopyRegion); + var region = state.Get(MethodOffset.CopyRegion); int srcX1 = (int)(region.SrcXF >> 32); int srcY1 = (int)(region.SrcYF >> 32); diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs index ee07ca7694..d69b9ea03e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs @@ -24,9 +24,9 @@ namespace Ryujinx.Graphics.Gpu.Engine public PrimitiveType PrimitiveType { get; private set; } - private void DrawEnd(int argument) + private void DrawEnd(GpuState state, int argument) { - UpdateState(); + UpdateState(state); bool instanced = _vsUsesInstanceId || _isAnyVbInstanced; @@ -39,12 +39,12 @@ namespace Ryujinx.Graphics.Gpu.Engine _instancedIndexed = _drawIndexed; _instancedFirstIndex = _firstIndex; - _instancedFirstVertex = _context.State.Get(MethodOffset.FirstVertex); - _instancedFirstInstance = _context.State.Get(MethodOffset.FirstInstance); + _instancedFirstVertex = state.Get(MethodOffset.FirstVertex); + _instancedFirstInstance = state.Get(MethodOffset.FirstInstance); _instancedIndexCount = _indexCount; - var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); + var drawState = state.Get(MethodOffset.VertexBufferDrawState); _instancedDrawStateFirst = drawState.First; _instancedDrawStateCount = drawState.Count; @@ -53,13 +53,13 @@ namespace Ryujinx.Graphics.Gpu.Engine return; } - int firstInstance = _context.State.Get(MethodOffset.FirstInstance); + int firstInstance = state.Get(MethodOffset.FirstInstance); if (_drawIndexed) { _drawIndexed = false; - int firstVertex = _context.State.Get(MethodOffset.FirstVertex); + int firstVertex = state.Get(MethodOffset.FirstVertex); _context.Renderer.Pipeline.DrawIndexed( _indexCount, @@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } else { - var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); + var drawState = state.Get(MethodOffset.VertexBufferDrawState); _context.Renderer.Pipeline.Draw( drawState.Count, @@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void DrawBegin(int argument) + private void DrawBegin(GpuState state, int argument) { PrimitiveType type = (PrimitiveType)(argument & 0xffff); @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void SetIndexBufferCount(int argument) + private void SetIndexBufferCount(GpuState state, int argument) { _drawIndexed = true; } diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs index dd022eb2cd..f73c03cb97 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs @@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { private ulong _runningCounter; - private void Report(int argument) + private void Report(GpuState state, int argument) { ReportMode mode = (ReportMode)(argument & 3); @@ -18,16 +18,16 @@ namespace Ryujinx.Graphics.Gpu.Engine switch (mode) { - case ReportMode.Semaphore: ReportSemaphore(); break; - case ReportMode.Counter: ReportCounter(type); break; + case ReportMode.Semaphore: ReportSemaphore(state); break; + case ReportMode.Counter: ReportCounter(state, type); break; } } - private void ReportSemaphore() + private void ReportSemaphore(GpuState state) { - var state = _context.State.Get(MethodOffset.ReportState); + var rs = state.Get(MethodOffset.ReportState); - _context.MemoryAccessor.Write(state.Address.Pack(), state.Payload); + _context.MemoryAccessor.Write(rs.Address.Pack(), rs.Payload); _context.AdvanceSequence(); } @@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Engine public ulong Timestamp; } - private void ReportCounter(ReportCounterType type) + private void ReportCounter(GpuState state, ReportCounterType type) { CounterData counterData = new CounterData(); @@ -78,9 +78,9 @@ namespace Ryujinx.Graphics.Gpu.Engine Span data = MemoryMarshal.Cast(counterDataSpan); - var state = _context.State.Get(MethodOffset.ReportState); + var rs = state.Get(MethodOffset.ReportState); - _context.MemoryAccessor.Write(state.Address.Pack(), data); + _context.MemoryAccessor.Write(rs.Address.Pack(), data); } private static ulong ConvertNanosecondsToTicks(ulong nanoseconds) diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs b/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs index 12a878459b..574eb5c8f0 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void ResetCounter(int argument) + private void ResetCounter(GpuState state, int argument) { ResetCounterType type = (ResetCounterType)argument; diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs index 823d156e26..87d9612b25 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs @@ -4,32 +4,32 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void UniformBufferBindVertex(int argument) + private void UniformBufferBindVertex(GpuState state, int argument) { - UniformBufferBind(argument, ShaderType.Vertex); + UniformBufferBind(state, argument, ShaderType.Vertex); } - private void UniformBufferBindTessControl(int argument) + private void UniformBufferBindTessControl(GpuState state, int argument) { - UniformBufferBind(argument, ShaderType.TessellationControl); + UniformBufferBind(state, argument, ShaderType.TessellationControl); } - private void UniformBufferBindTessEvaluation(int argument) + private void UniformBufferBindTessEvaluation(GpuState state, int argument) { - UniformBufferBind(argument, ShaderType.TessellationEvaluation); + UniformBufferBind(state, argument, ShaderType.TessellationEvaluation); } - private void UniformBufferBindGeometry(int argument) + private void UniformBufferBindGeometry(GpuState state, int argument) { - UniformBufferBind(argument, ShaderType.Geometry); + UniformBufferBind(state, argument, ShaderType.Geometry); } - private void UniformBufferBindFragment(int argument) + private void UniformBufferBindFragment(GpuState state, int argument) { - UniformBufferBind(argument, ShaderType.Fragment); + UniformBufferBind(state, argument, ShaderType.Fragment); } - private void UniformBufferBind(int argument, ShaderType type) + private void UniformBufferBind(GpuState state, int argument, ShaderType type) { bool enable = (argument & 1) != 0; @@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (enable) { - var uniformBuffer = _context.State.Get(MethodOffset.UniformBufferState); + var uniformBuffer = state.Get(MethodOffset.UniformBufferState); ulong address = uniformBuffer.Address.Pack(); diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs index 229e79a84e..43bab2433b 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs @@ -4,13 +4,13 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void UniformBufferUpdate(int argument) + private void UniformBufferUpdate(GpuState state, int argument) { - var uniformBuffer = _context.State.Get(MethodOffset.UniformBufferState); + var uniformBuffer = state.Get(MethodOffset.UniformBufferState); _context.MemoryAccessor.Write(uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset, argument); - _context.State.SetUniformBufferOffset(uniformBuffer.Offset + 4); + state.SetUniformBufferOffset(uniformBuffer.Offset + 4); _context.AdvanceSequence(); } diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index f48d0a7f82..1832a5e353 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -40,133 +40,131 @@ namespace Ryujinx.Graphics.Gpu.Engine _bufferManager = new BufferManager(context); _textureManager = new TextureManager(context); - - RegisterCallbacks(); } - private void RegisterCallbacks() + public void RegisterCallbacks(GpuState state) { - _context.State.RegisterCallback(MethodOffset.LaunchDma, LaunchDma); - _context.State.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData); + state.RegisterCallback(MethodOffset.LaunchDma, LaunchDma); + state.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData); - _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch); + state.RegisterCallback(MethodOffset.Dispatch, Dispatch); - _context.State.RegisterCallback(MethodOffset.CopyBuffer, CopyBuffer); - _context.State.RegisterCallback(MethodOffset.CopyTexture, CopyTexture); + state.RegisterCallback(MethodOffset.CopyBuffer, CopyBuffer); + state.RegisterCallback(MethodOffset.CopyTexture, CopyTexture); - _context.State.RegisterCallback(MethodOffset.TextureBarrier, TextureBarrier); - _context.State.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures); - _context.State.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled); + state.RegisterCallback(MethodOffset.TextureBarrier, TextureBarrier); + state.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures); + state.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled); - _context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter); + state.RegisterCallback(MethodOffset.ResetCounter, ResetCounter); - _context.State.RegisterCallback(MethodOffset.DrawEnd, DrawEnd); - _context.State.RegisterCallback(MethodOffset.DrawBegin, DrawBegin); + state.RegisterCallback(MethodOffset.DrawEnd, DrawEnd); + state.RegisterCallback(MethodOffset.DrawBegin, DrawBegin); - _context.State.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount); + state.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount); - _context.State.RegisterCallback(MethodOffset.Clear, Clear); + state.RegisterCallback(MethodOffset.Clear, Clear); - _context.State.RegisterCallback(MethodOffset.Report, Report); + state.RegisterCallback(MethodOffset.Report, Report); - _context.State.RegisterCallback(MethodOffset.UniformBufferUpdateData, 16, UniformBufferUpdate); + state.RegisterCallback(MethodOffset.UniformBufferUpdateData, 16, UniformBufferUpdate); - _context.State.RegisterCallback(MethodOffset.UniformBufferBindVertex, UniformBufferBindVertex); - _context.State.RegisterCallback(MethodOffset.UniformBufferBindTessControl, UniformBufferBindTessControl); - _context.State.RegisterCallback(MethodOffset.UniformBufferBindTessEvaluation, UniformBufferBindTessEvaluation); - _context.State.RegisterCallback(MethodOffset.UniformBufferBindGeometry, UniformBufferBindGeometry); - _context.State.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment); + state.RegisterCallback(MethodOffset.UniformBufferBindVertex, UniformBufferBindVertex); + state.RegisterCallback(MethodOffset.UniformBufferBindTessControl, UniformBufferBindTessControl); + state.RegisterCallback(MethodOffset.UniformBufferBindTessEvaluation, UniformBufferBindTessEvaluation); + state.RegisterCallback(MethodOffset.UniformBufferBindGeometry, UniformBufferBindGeometry); + state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment); } public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address); - private void UpdateState() + private void UpdateState(GpuState state) { // Shaders must be the first one to be updated if modified, because // some of the other state depends on information from the currently // bound shaders. - if (_context.State.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState)) + if (state.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState)) { - UpdateShaderState(); + UpdateShaderState(state); } - UpdateRenderTargetStateIfNeeded(); + UpdateRenderTargetStateIfNeeded(state); - if (_context.State.QueryModified(MethodOffset.DepthTestEnable, + if (state.QueryModified(MethodOffset.DepthTestEnable, MethodOffset.DepthWriteEnable, MethodOffset.DepthTestFunc)) { - UpdateDepthTestState(); + UpdateDepthTestState(state); } - if (_context.State.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents)) + if (state.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents)) { - UpdateViewportTransform(); + UpdateViewportTransform(state); } - if (_context.State.QueryModified(MethodOffset.DepthBiasState, + if (state.QueryModified(MethodOffset.DepthBiasState, MethodOffset.DepthBiasFactor, MethodOffset.DepthBiasUnits, MethodOffset.DepthBiasClamp)) { - UpdateDepthBiasState(); + UpdateDepthBiasState(state); } - if (_context.State.QueryModified(MethodOffset.StencilBackMasks, + if (state.QueryModified(MethodOffset.StencilBackMasks, MethodOffset.StencilTestState, MethodOffset.StencilBackTestState)) { - UpdateStencilTestState(); + UpdateStencilTestState(state); } // Pools. - if (_context.State.QueryModified(MethodOffset.SamplerPoolState)) + if (state.QueryModified(MethodOffset.SamplerPoolState)) { - UpdateSamplerPoolState(); + UpdateSamplerPoolState(state); } - if (_context.State.QueryModified(MethodOffset.TexturePoolState)) + if (state.QueryModified(MethodOffset.TexturePoolState)) { - UpdateTexturePoolState(); + UpdateTexturePoolState(state); } // Input assembler state. - if (_context.State.QueryModified(MethodOffset.VertexAttribState)) + if (state.QueryModified(MethodOffset.VertexAttribState)) { - UpdateVertexAttribState(); + UpdateVertexAttribState(state); } - if (_context.State.QueryModified(MethodOffset.PrimitiveRestartState)) + if (state.QueryModified(MethodOffset.PrimitiveRestartState)) { - UpdatePrimitiveRestartState(); + UpdatePrimitiveRestartState(state); } - if (_context.State.QueryModified(MethodOffset.IndexBufferState)) + if (state.QueryModified(MethodOffset.IndexBufferState)) { - UpdateIndexBufferState(); + UpdateIndexBufferState(state); } - if (_context.State.QueryModified(MethodOffset.VertexBufferDrawState, + if (state.QueryModified(MethodOffset.VertexBufferDrawState, MethodOffset.VertexBufferInstanced, MethodOffset.VertexBufferState, MethodOffset.VertexBufferEndAddress)) { - UpdateVertexBufferState(); + UpdateVertexBufferState(state); } - if (_context.State.QueryModified(MethodOffset.FaceState)) + if (state.QueryModified(MethodOffset.FaceState)) { - UpdateFaceState(); + UpdateFaceState(state); } - if (_context.State.QueryModified(MethodOffset.RtColorMask)) + if (state.QueryModified(MethodOffset.RtColorMask)) { - UpdateRtColorMask(); + UpdateRtColorMask(state); } - if (_context.State.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState)) + if (state.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState)) { - UpdateBlendState(); + UpdateBlendState(state); } CommitBindings(); @@ -210,27 +208,27 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void UpdateRenderTargetStateIfNeeded() + private void UpdateRenderTargetStateIfNeeded(GpuState state) { - if (_context.State.QueryModified(MethodOffset.RtColorState, + if (state.QueryModified(MethodOffset.RtColorState, MethodOffset.RtDepthStencilState, MethodOffset.RtDepthStencilSize, MethodOffset.RtDepthStencilEnable)) { - UpdateRenderTargetState(); + UpdateRenderTargetState(state); } } - private void UpdateRenderTargetState() + private void UpdateRenderTargetState(GpuState state) { - var msaaMode = _context.State.Get(MethodOffset.RtMsaaMode); + var msaaMode = state.Get(MethodOffset.RtMsaaMode); int samplesInX = msaaMode.SamplesInX(); int samplesInY = msaaMode.SamplesInY(); for (int index = 0; index < Constants.TotalRenderTargets; index++) { - var colorState = _context.State.Get(MethodOffset.RtColorState, index); + var colorState = state.Get(MethodOffset.RtColorState, index); if (!IsRtEnabled(colorState)) { @@ -252,14 +250,14 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - bool dsEnable = _context.State.Get(MethodOffset.RtDepthStencilEnable); + bool dsEnable = state.Get(MethodOffset.RtDepthStencilEnable); Image.Texture depthStencil = null; if (dsEnable) { - var dsState = _context.State.Get(MethodOffset.RtDepthStencilState); - var dsSize = _context.State.Get (MethodOffset.RtDepthStencilSize); + var dsState = state.Get(MethodOffset.RtDepthStencilState); + var dsSize = state.Get (MethodOffset.RtDepthStencilSize); depthStencil = _textureManager.FindOrCreateTexture( dsState, @@ -282,22 +280,22 @@ namespace Ryujinx.Graphics.Gpu.Engine return colorState.Format != 0 && colorState.WidthOrStride != 0; } - private void UpdateDepthTestState() + private void UpdateDepthTestState(GpuState state) { _context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor( - _context.State.Get(MethodOffset.DepthTestEnable), - _context.State.Get(MethodOffset.DepthWriteEnable), - _context.State.Get(MethodOffset.DepthTestFunc))); + state.Get(MethodOffset.DepthTestEnable), + state.Get(MethodOffset.DepthWriteEnable), + state.Get(MethodOffset.DepthTestFunc))); } - private void UpdateViewportTransform() + private void UpdateViewportTransform(GpuState state) { Viewport[] viewports = new Viewport[Constants.TotalViewports]; for (int index = 0; index < Constants.TotalViewports; index++) { - var transform = _context.State.Get(MethodOffset.ViewportTransform, index); - var extents = _context.State.Get (MethodOffset.ViewportExtents, index); + var transform = state.Get(MethodOffset.ViewportTransform, index); + var extents = state.Get (MethodOffset.ViewportExtents, index); float x = transform.TranslateX - MathF.Abs(transform.ScaleX); float y = transform.TranslateY - MathF.Abs(transform.ScaleY); @@ -320,13 +318,13 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.SetViewports(0, viewports); } - private void UpdateDepthBiasState() + private void UpdateDepthBiasState(GpuState state) { - var depthBias = _context.State.Get(MethodOffset.DepthBiasState); + var depthBias = state.Get(MethodOffset.DepthBiasState); - float factor = _context.State.Get(MethodOffset.DepthBiasFactor); - float units = _context.State.Get(MethodOffset.DepthBiasUnits); - float clamp = _context.State.Get(MethodOffset.DepthBiasClamp); + float factor = state.Get(MethodOffset.DepthBiasFactor); + float units = state.Get(MethodOffset.DepthBiasUnits); + float clamp = state.Get(MethodOffset.DepthBiasClamp); PolygonModeMask enables = 0; @@ -337,11 +335,11 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp); } - private void UpdateStencilTestState() + private void UpdateStencilTestState(GpuState state) { - var backMasks = _context.State.Get (MethodOffset.StencilBackMasks); - var test = _context.State.Get (MethodOffset.StencilTestState); - var backTest = _context.State.Get(MethodOffset.StencilBackTestState); + var backMasks = state.Get (MethodOffset.StencilBackMasks); + var test = state.Get (MethodOffset.StencilTestState); + var backTest = state.Get(MethodOffset.StencilBackTestState); CompareOp backFunc; StencilOp backSFail; @@ -390,29 +388,29 @@ namespace Ryujinx.Graphics.Gpu.Engine backMask)); } - private void UpdateSamplerPoolState() + private void UpdateSamplerPoolState(GpuState state) { - var samplerPool = _context.State.Get(MethodOffset.SamplerPoolState); + var samplerPool = state.Get(MethodOffset.SamplerPoolState); _textureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); } - private void UpdateTexturePoolState() + private void UpdateTexturePoolState(GpuState state) { - var texturePool = _context.State.Get(MethodOffset.TexturePoolState); + var texturePool = state.Get(MethodOffset.TexturePoolState); _textureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); - _textureManager.SetGraphicsTextureBufferIndex(_context.State.Get(MethodOffset.TextureBufferIndex)); + _textureManager.SetGraphicsTextureBufferIndex(state.Get(MethodOffset.TextureBufferIndex)); } - private void UpdateVertexAttribState() + private void UpdateVertexAttribState(GpuState state) { VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16]; for (int index = 0; index < 16; index++) { - var vertexAttrib = _context.State.Get(MethodOffset.VertexAttribState, index); + var vertexAttrib = state.Get(MethodOffset.VertexAttribState, index); if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format)) { @@ -430,18 +428,18 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.BindVertexAttribs(vertexAttribs); } - private void UpdatePrimitiveRestartState() + private void UpdatePrimitiveRestartState(GpuState state) { - PrimitiveRestartState primitiveRestart = _context.State.Get(MethodOffset.PrimitiveRestartState); + PrimitiveRestartState primitiveRestart = state.Get(MethodOffset.PrimitiveRestartState); _context.Renderer.Pipeline.SetPrimitiveRestart( primitiveRestart.Enable, primitiveRestart.Index); } - private void UpdateIndexBufferState() + private void UpdateIndexBufferState(GpuState state) { - var indexBuffer = _context.State.Get(MethodOffset.IndexBufferState); + var indexBuffer = state.Get(MethodOffset.IndexBufferState); _firstIndex = indexBuffer.First; _indexCount = indexBuffer.Count; @@ -467,16 +465,16 @@ namespace Ryujinx.Graphics.Gpu.Engine // The index buffer affects the vertex buffer size calculation, we // need to ensure that they are updated. - UpdateVertexBufferState(); + UpdateVertexBufferState(state); } - private void UpdateVertexBufferState() + private void UpdateVertexBufferState(GpuState state) { _isAnyVbInstanced = false; for (int index = 0; index < 16; index++) { - var vertexBuffer = _context.State.Get(MethodOffset.VertexBufferState, index); + var vertexBuffer = state.Get(MethodOffset.VertexBufferState, index); if (!vertexBuffer.UnpackEnable()) { @@ -485,13 +483,13 @@ namespace Ryujinx.Graphics.Gpu.Engine continue; } - GpuVa endAddress = _context.State.Get(MethodOffset.VertexBufferEndAddress, index); + GpuVa endAddress = state.Get(MethodOffset.VertexBufferEndAddress, index); ulong address = vertexBuffer.Address.Pack(); int stride = vertexBuffer.UnpackStride(); - bool instanced = _context.State.Get(MethodOffset.VertexBufferInstanced + index); + bool instanced = state.Get(MethodOffset.VertexBufferInstanced + index); int divisor = instanced ? vertexBuffer.Divisor : 0; @@ -509,9 +507,9 @@ namespace Ryujinx.Graphics.Gpu.Engine { // For non-indexed draws, we can guess the size from the vertex count // and stride. - int firstInstance = _context.State.Get(MethodOffset.FirstInstance); + int firstInstance = state.Get(MethodOffset.FirstInstance); - var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); + var drawState = state.Get(MethodOffset.VertexBufferDrawState); size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride); } @@ -520,22 +518,22 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void UpdateFaceState() + private void UpdateFaceState(GpuState state) { - var face = _context.State.Get(MethodOffset.FaceState); + var face = state.Get(MethodOffset.FaceState); _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace); _context.Renderer.Pipeline.SetFrontFace(face.FrontFace); } - private void UpdateRtColorMask() + private void UpdateRtColorMask(GpuState state) { uint[] componentMasks = new uint[Constants.TotalRenderTargets]; for (int index = 0; index < Constants.TotalRenderTargets; index++) { - var colorMask = _context.State.Get(MethodOffset.RtColorMask, index); + var colorMask = state.Get(MethodOffset.RtColorMask, index); uint componentMask = 0; @@ -550,15 +548,15 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks); } - private void UpdateBlendState() + private void UpdateBlendState(GpuState state) { BlendState[] blends = new BlendState[8]; for (int index = 0; index < 8; index++) { - bool enable = _context.State.Get(MethodOffset.BlendEnable, index); + bool enable = state.Get(MethodOffset.BlendEnable, index); - var blend = _context.State.Get(MethodOffset.BlendState, index); + var blend = state.Get(MethodOffset.BlendState, index); BlendDescriptor descriptor = new BlendDescriptor( enable, @@ -586,7 +584,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void UpdateShaderState() + private void UpdateShaderState(GpuState state) { ShaderAddresses addresses = new ShaderAddresses(); @@ -594,11 +592,11 @@ namespace Ryujinx.Graphics.Gpu.Engine Span addressesArray = MemoryMarshal.Cast(addressesSpan); - ulong baseAddress = _context.State.Get(MethodOffset.ShaderBaseAddress).Pack(); + ulong baseAddress = state.Get(MethodOffset.ShaderBaseAddress).Pack(); for (int index = 0; index < 6; index++) { - var shader = _context.State.Get(MethodOffset.ShaderState, index); + var shader = state.Get(MethodOffset.ShaderState, index); if (!shader.UnpackEnable() && index != 1) { @@ -711,17 +709,17 @@ namespace Ryujinx.Graphics.Gpu.Engine return Target.Texture2D; } - private void TextureBarrier(int argument) + private void TextureBarrier(GpuState state, int argument) { _context.Renderer.Pipeline.TextureBarrier(); } - private void InvalidateTextures(int argument) + private void InvalidateTextures(GpuState state, int argument) { _textureManager.Flush(); } - private void TextureBarrierTiled(int argument) + private void TextureBarrierTiled(GpuState state, int argument) { _context.Renderer.Pipeline.TextureBarrierTiled(); } diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs index 1e865e6a72..b52e4e497a 100644 --- a/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -12,8 +12,6 @@ namespace Ryujinx.Graphics.Gpu { public IRenderer Renderer { get; } - internal GpuState State { get; } - internal IPhysicalMemory PhysicalMemory { get; private set; } public MemoryManager MemoryManager { get; } @@ -36,8 +34,6 @@ namespace Ryujinx.Graphics.Gpu { Renderer = renderer; - State = new GpuState(); - MemoryManager = new MemoryManager(); MemoryAccessor = new MemoryAccessor(this); diff --git a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs index 93d5c2ca2e..e424b8ffa9 100644 --- a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs +++ b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Logging; +using Ryujinx.Graphics.Gpu.State; using System; using System.Collections.Generic; @@ -70,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu _gprs = new int[8]; } - public void Execute(int[] mme, int position, int param) + public void Execute(int[] mme, int position, int param, GpuState state) { Reset(); @@ -80,11 +81,11 @@ namespace Ryujinx.Graphics.Gpu FetchOpCode(mme); - while (Step(mme)); + while (Step(mme, state)); // Due to the delay slot, we still need to execute // one more instruction before we actually exit. - Step(mme); + Step(mme, state); } private void Reset() @@ -100,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu _carry = false; } - private bool Step(int[] mme) + private bool Step(int[] mme, GpuState state) { int baseAddr = _pc - 1; @@ -111,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu // Operation produces a value. AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7); - int result = GetAluResult(); + int result = GetAluResult(state); switch (asgOp) { @@ -146,7 +147,7 @@ namespace Ryujinx.Graphics.Gpu { SetDstGpr(FetchParam()); - Send(result); + Send(state, result); break; } @@ -156,7 +157,7 @@ namespace Ryujinx.Graphics.Gpu { SetDstGpr(result); - Send(result); + Send(state, result); break; } @@ -178,7 +179,7 @@ namespace Ryujinx.Graphics.Gpu SetMethAddr(result); - Send(FetchParam()); + Send(state, FetchParam()); break; } @@ -190,7 +191,7 @@ namespace Ryujinx.Graphics.Gpu SetMethAddr(result); - Send((result >> 12) & 0x3f); + Send(state, (result >> 12) & 0x3f); break; } @@ -231,7 +232,7 @@ namespace Ryujinx.Graphics.Gpu _pipeOp = mme[_pc++]; } - private int GetAluResult() + private int GetAluResult(GpuState state) { AluOperation op = (AluOperation)(_opCode & 7); @@ -295,7 +296,7 @@ namespace Ryujinx.Graphics.Gpu case AluOperation.ReadImmediate: { - return Read(GetGprA() + GetImm()); + return Read(state, GetGprA() + GetImm()); } } @@ -398,16 +399,16 @@ namespace Ryujinx.Graphics.Gpu return value; } - private int Read(int reg) + private int Read(GpuState state, int reg) { - return _context.State.Read(reg); + return state.Read(reg); } - private void Send(int value) + private void Send(GpuState state, int value) { MethodParams meth = new MethodParams(_methAddr, value); - _context.State.CallMethod(meth); + state.CallMethod(meth); _methAddr += _methIncr; } diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs index f4deea54dc..64947bf63f 100644 --- a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs +++ b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs @@ -1,3 +1,5 @@ +using Ryujinx.Graphics.Gpu.State; + namespace Ryujinx.Graphics.Gpu { class NvGpuFifo @@ -37,13 +39,13 @@ namespace Ryujinx.Graphics.Gpu _executionPending = true; } - public void Execute(int[] mme) + public void Execute(int[] mme, GpuState state) { if (_executionPending) { _executionPending = false; - _interpreter?.Execute(mme, Position, _argument); + _interpreter?.Execute(mme, Position, _argument, state); } } @@ -60,7 +62,18 @@ namespace Ryujinx.Graphics.Gpu private int[] _mme; - private ClassId[] _subChannels; + private class SubChannel + { + public GpuState State { get; } + public ClassId Class { get; set; } + + public SubChannel() + { + State = new GpuState(); + } + } + + private SubChannel[] _subChannels; public NvGpuFifo(GpuContext context) { @@ -70,14 +83,21 @@ namespace Ryujinx.Graphics.Gpu _mme = new int[MmeWords]; - _subChannels = new ClassId[8]; + _subChannels = new SubChannel[8]; + + for (int index = 0; index < _subChannels.Length; index++) + { + _subChannels[index] = new SubChannel(); + + context.Methods.RegisterCallbacks(_subChannels[index].State); + } } public void CallMethod(MethodParams meth) { if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel) { - _subChannels[meth.SubChannel] = (ClassId)meth.Argument; + _subChannels[meth.SubChannel].Class = (ClassId)meth.Argument; } else if (meth.Method < 0x60) { @@ -123,7 +143,7 @@ namespace Ryujinx.Graphics.Gpu } else if (meth.Method < 0xe00) { - _context.State.CallMethod(meth); + _subChannels[meth.SubChannel].State.CallMethod(meth); } else { @@ -140,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu if (meth.IsLastCall) { - _macros[macroIndex].Execute(_mme); + _macros[macroIndex].Execute(_mme, _subChannels[meth.SubChannel].State); _context.Methods.PerformDeferredDraws(); } diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs index 6c603f306d..ecbaa00459 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuState.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Gpu.State { private const int RegistersCount = 0xe00; - public delegate void MethodCallback(int argument); + public delegate void MethodCallback(GpuState state, int argument); private int[] _backingMemory; @@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.State if (callback != null) { - callback(meth.Argument); + callback(this, meth.Argument); } }