diff --git a/ARMeilleure/Memory/MemoryManager.cs b/ARMeilleure/Memory/MemoryManager.cs index 2bdbc309..c3f586aa 100644 --- a/ARMeilleure/Memory/MemoryManager.cs +++ b/ARMeilleure/Memory/MemoryManager.cs @@ -14,8 +14,6 @@ namespace ARMeilleure.Memory public const int PageSize = 1 << PageBits; public const int PageMask = PageSize - 1; - private const long PteFlagNotModified = 1; - internal const long PteFlagsMask = 7; public IntPtr Ram { get; private set; } @@ -106,6 +104,11 @@ namespace ARMeilleure.Memory ptr = (byte*)ptrUlong; } + if (ptr == null) + { + return IntPtr.Zero; + } + return new IntPtr(ptr + (position & PageMask)); } @@ -122,10 +125,7 @@ namespace ARMeilleure.Memory if ((ptrUlong & PteFlagsMask) != 0) { - if ((ptrUlong & PteFlagNotModified) != 0) - { - ClearPtEntryFlag(position, PteFlagNotModified); - } + ClearPtEntryFlag(position, PteFlagsMask); ptrUlong &= ~(ulong)PteFlagsMask; @@ -253,8 +253,10 @@ namespace ARMeilleure.Memory return ptePtr; } - public unsafe (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size) + public unsafe (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, int id) { + ulong idMask = 1UL << id; + List<(ulong, ulong)> ranges = new List<(ulong, ulong)>(); ulong endAddress = (address + size + PageMask) & ~(ulong)PageMask; @@ -272,12 +274,12 @@ namespace ARMeilleure.Memory ulong ptrUlong = (ulong)ptr; - if ((ptrUlong & PteFlagNotModified) == 0) + if ((ptrUlong & idMask) == 0) { // Modified. currSize += PageSize; - SetPtEntryFlag((long)address, PteFlagNotModified); + SetPtEntryFlag((long)address, (long)idMask); } else { diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs index b5acca1c..588825d0 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs @@ -27,15 +27,15 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.BindProgram(cs.Interface); - PoolState samplerPool = _context.State.GetSamplerPoolState(); + var samplerPool = _context.State.Get(MethodOffset.SamplerPoolState); _textureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); - PoolState texturePool = _context.State.GetTexturePoolState(); + var texturePool = _context.State.Get(MethodOffset.TexturePoolState); _textureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); - _textureManager.SetComputeTextureBufferIndex(_context.State.GetTextureBufferIndex()); + _textureManager.SetComputeTextureBufferIndex(_context.State.Get(MethodOffset.TextureBufferIndex)); ShaderProgramInfo info = cs.Shader.Info; @@ -117,6 +117,8 @@ namespace Ryujinx.Graphics.Gpu.Engine dispatchParams.UnpackGridSizeX(), dispatchParams.UnpackGridSizeY(), dispatchParams.UnpackGridSizeZ()); + + UpdateShaderState(); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs index d2816ac5..355b7394 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 Execute(int argument) + public void LaunchDma(int argument) { - _params = _context.State.Get(MethodOffset.Inline2MemoryParams); + _params = _context.State.Get(MethodOffset.I2mParams); _isLinear = (argument & 1) != 0; @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Engine _size = _params.LineLengthIn * _params.LineCount; } - public void PushData(int argument) + public void LoadInlineData(int argument) { if (_isLinear) { diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs index 2072f3fc..b50a1766 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs @@ -7,7 +7,9 @@ namespace Ryujinx.Graphics.Gpu.Engine { private void Clear(int argument) { - UpdateState(); + UpdateRenderTargetStateIfNeeded(); + + _textureManager.CommitGraphicsBindings(); bool clearDepth = (argument & 1) != 0; bool clearStencil = (argument & 2) != 0; @@ -18,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (componentMask != 0) { - ClearColors clearColor = _context.State.GetClearColors(); + var clearColor = _context.State.Get(MethodOffset.ClearColors); ColorF color = new ColorF( clearColor.Red, @@ -26,22 +28,19 @@ namespace Ryujinx.Graphics.Gpu.Engine clearColor.Blue, clearColor.Alpha); - _context.Renderer.Pipeline.ClearRenderTargetColor( - index, - componentMask, - color); + _context.Renderer.Pipeline.ClearRenderTargetColor(index, componentMask, color); } if (clearDepth || clearStencil) { - float depthValue = _context.State.GetClearDepthValue(); - int stencilValue = _context.State.GetClearStencilValue(); + float depthValue = _context.State.Get(MethodOffset.ClearDepthValue); + int stencilValue = _context.State.Get (MethodOffset.ClearStencilValue); int stencilMask = 0; if (clearStencil) { - stencilMask = _context.State.GetStencilTestState().FrontMask; + stencilMask = _context.State.Get(MethodOffset.StencilTestState).FrontMask; } _context.Renderer.Pipeline.ClearRenderTargetDepthStencil( diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs index e2c40805..887f520d 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs @@ -7,8 +7,8 @@ namespace Ryujinx.Graphics.Gpu.Engine { private void CopyTexture(int argument) { - CopyTexture dstCopyTexture = _context.State.GetCopyDstTexture(); - CopyTexture srcCopyTexture = _context.State.GetCopySrcTexture(); + var dstCopyTexture = _context.State.Get(MethodOffset.CopyDstTexture); + var srcCopyTexture = _context.State.Get(MethodOffset.CopySrcTexture); Image.Texture srcTexture = _textureManager.FindOrCreateTexture(srcCopyTexture); @@ -32,9 +32,9 @@ namespace Ryujinx.Graphics.Gpu.Engine return; } - CopyTextureControl control = _context.State.GetCopyTextureControl(); + var control = _context.State.Get(MethodOffset.CopyTextureControl); - CopyRegion region = _context.State.GetCopyRegion(); + var region = _context.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 c340aeb8..ee07ca76 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs @@ -39,12 +39,12 @@ namespace Ryujinx.Graphics.Gpu.Engine _instancedIndexed = _drawIndexed; _instancedFirstIndex = _firstIndex; - _instancedFirstVertex = _context.State.GetBaseVertex(); - _instancedFirstInstance = _context.State.GetBaseInstance(); + _instancedFirstVertex = _context.State.Get(MethodOffset.FirstVertex); + _instancedFirstInstance = _context.State.Get(MethodOffset.FirstInstance); _instancedIndexCount = _indexCount; - VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); + var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); _instancedDrawStateFirst = drawState.First; _instancedDrawStateCount = drawState.Count; @@ -53,13 +53,13 @@ namespace Ryujinx.Graphics.Gpu.Engine return; } - int firstInstance = _context.State.GetBaseInstance(); + int firstInstance = _context.State.Get(MethodOffset.FirstInstance); if (_drawIndexed) { _drawIndexed = false; - int firstVertex = _context.State.GetBaseVertex(); + int firstVertex = _context.State.Get(MethodOffset.FirstVertex); _context.Renderer.Pipeline.DrawIndexed( _indexCount, @@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } else { - VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); + var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); _context.Renderer.Pipeline.Draw( drawState.Count, @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - private void SetIndexCount(int argument) + private void SetIndexBufferCount(int argument) { _drawIndexed = true; } diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs index fd0a31a1..dd022eb2 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs @@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Gpu.Engine private void ReportSemaphore() { - ReportState state = _context.State.GetReportState(); + var state = _context.State.Get(MethodOffset.ReportState); _context.MemoryAccessor.Write(state.Address.Pack(), state.Payload); @@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Gpu.Engine Span data = MemoryMarshal.Cast(counterDataSpan); - ReportState state = _context.State.GetReportState(); + var state = _context.State.Get(MethodOffset.ReportState); _context.MemoryAccessor.Write(state.Address.Pack(), data); } diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs index a9ebce83..823d156e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs @@ -4,27 +4,27 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { - private void UniformBufferBind0(int argument) + private void UniformBufferBindVertex(int argument) { UniformBufferBind(argument, ShaderType.Vertex); } - private void UniformBufferBind1(int argument) + private void UniformBufferBindTessControl(int argument) { UniformBufferBind(argument, ShaderType.TessellationControl); } - private void UniformBufferBind2(int argument) + private void UniformBufferBindTessEvaluation(int argument) { UniformBufferBind(argument, ShaderType.TessellationEvaluation); } - private void UniformBufferBind3(int argument) + private void UniformBufferBindGeometry(int argument) { UniformBufferBind(argument, ShaderType.Geometry); } - private void UniformBufferBind4(int argument) + private void UniformBufferBindFragment(int argument) { UniformBufferBind(argument, ShaderType.Fragment); } @@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (enable) { - UniformBufferState uniformBuffer = _context.State.GetUniformBufferState(); + var uniformBuffer = _context.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 f0b8e2d7..229e79a8 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { private void UniformBufferUpdate(int argument) { - UniformBufferState uniformBuffer = _context.State.GetUniformBufferState(); + var uniformBuffer = _context.State.Get(MethodOffset.UniformBufferState); _context.MemoryAccessor.Write(uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset, argument); diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index c35d6634..5d90573c 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -18,6 +18,8 @@ namespace Ryujinx.Graphics.Gpu.Engine private ShaderCache _shaderCache; + private ShaderProgramInfo[] _currentProgramInfo; + private BufferManager _bufferManager; private TextureManager _textureManager; @@ -33,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Engine _shaderCache = new ShaderCache(_context); + _currentProgramInfo = new ShaderProgramInfo[Constants.TotalShaderStages]; + _bufferManager = new BufferManager(context); _textureManager = new TextureManager(context); @@ -41,128 +45,184 @@ namespace Ryujinx.Graphics.Gpu.Engine private void RegisterCallbacks() { - _context.State.RegisterCopyBufferCallback(CopyBuffer); - _context.State.RegisterCopyTextureCallback(CopyTexture); + _context.State.RegisterCallback(MethodOffset.LaunchDma, LaunchDma); + _context.State.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData); - _context.State.RegisterDrawEndCallback(DrawEnd); + _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch); - _context.State.RegisterDrawBeginCallback(DrawBegin); - - _context.State.RegisterSetIndexCountCallback(SetIndexCount); - - _context.State.RegisterClearCallback(Clear); - - _context.State.RegisterReportCallback(Report); - - _context.State.RegisterUniformBufferUpdateCallback(UniformBufferUpdate); - - _context.State.RegisterUniformBufferBind0Callback(UniformBufferBind0); - _context.State.RegisterUniformBufferBind1Callback(UniformBufferBind1); - _context.State.RegisterUniformBufferBind2Callback(UniformBufferBind2); - _context.State.RegisterUniformBufferBind3Callback(UniformBufferBind3); - _context.State.RegisterUniformBufferBind4Callback(UniformBufferBind4); + _context.State.RegisterCallback(MethodOffset.CopyBuffer, CopyBuffer); + _context.State.RegisterCallback(MethodOffset.CopyTexture, CopyTexture); _context.State.RegisterCallback(MethodOffset.TextureBarrier, TextureBarrier); _context.State.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures); _context.State.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled); - _context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter); - _context.State.RegisterCallback(MethodOffset.Inline2MemoryExecute, Execute); - _context.State.RegisterCallback(MethodOffset.Inline2MemoryPushData, PushData); + _context.State.RegisterCallback(MethodOffset.DrawEnd, DrawEnd); + _context.State.RegisterCallback(MethodOffset.DrawBegin, DrawBegin); - _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch); + _context.State.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount); + + _context.State.RegisterCallback(MethodOffset.Clear, Clear); + + _context.State.RegisterCallback(MethodOffset.Report, Report); + + _context.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); } public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address); private void UpdateState() { - if ((_context.State.StateWriteFlags & StateWriteFlags.Any) == 0) - { - CommitBindings(); - - return; - } - // 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.StateWriteFlags & StateWriteFlags.ShaderState) != 0) + if (_context.State.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState)) { UpdateShaderState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.RenderTargetGroup) != 0) - { - UpdateRenderTargetGroupState(); - } + UpdateRenderTargetStateIfNeeded(); - if ((_context.State.StateWriteFlags & StateWriteFlags.DepthTestState) != 0) + if (_context.State.QueryModified(MethodOffset.DepthTestEnable, + MethodOffset.DepthWriteEnable, + MethodOffset.DepthTestFunc)) { UpdateDepthTestState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.ViewportTransform) != 0) + if (_context.State.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents)) { UpdateViewportTransform(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.DepthBiasState) != 0) + if (_context.State.QueryModified(MethodOffset.DepthBiasState, + MethodOffset.DepthBiasFactor, + MethodOffset.DepthBiasUnits, + MethodOffset.DepthBiasClamp)) { UpdateDepthBiasState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.StencilTestState) != 0) + if (_context.State.QueryModified(MethodOffset.StencilBackMasks, + MethodOffset.StencilTestState, + MethodOffset.StencilBackTestState)) { UpdateStencilTestState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.SamplerPoolState) != 0) + // Pools. + if (_context.State.QueryModified(MethodOffset.SamplerPoolState)) { UpdateSamplerPoolState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.TexturePoolState) != 0) + if (_context.State.QueryModified(MethodOffset.TexturePoolState)) { UpdateTexturePoolState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.InputAssemblerGroup) != 0) + // Input assembler state. + if (_context.State.QueryModified(MethodOffset.VertexAttribState)) { - UpdateInputAssemblerGroupState(); + UpdateVertexAttribState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.FaceState) != 0) + if (_context.State.QueryModified(MethodOffset.PrimitiveRestartState)) + { + UpdatePrimitiveRestartState(); + } + + if (_context.State.QueryModified(MethodOffset.IndexBufferState)) + { + UpdateIndexBufferState(); + } + + if (_context.State.QueryModified(MethodOffset.VertexBufferDrawState, + MethodOffset.VertexBufferInstanced, + MethodOffset.VertexBufferState, + MethodOffset.VertexBufferEndAddress)) + { + UpdateVertexBufferState(); + } + + if (_context.State.QueryModified(MethodOffset.FaceState)) { UpdateFaceState(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.RtColorMask) != 0) + if (_context.State.QueryModified(MethodOffset.RtColorMask)) { UpdateRtColorMask(); } - if ((_context.State.StateWriteFlags & StateWriteFlags.BlendState) != 0) + if (_context.State.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState)) { UpdateBlendState(); } - _context.State.StateWriteFlags &= ~StateWriteFlags.Any; - CommitBindings(); } private void CommitBindings() { + UpdateStorageBuffers(); + _bufferManager.CommitBindings(); _textureManager.CommitGraphicsBindings(); } - private void UpdateRenderTargetGroupState() + private void UpdateStorageBuffers() { - TextureMsaaMode msaaMode = _context.State.GetRtMsaaMode(); + for (int stage = 0; stage < _currentProgramInfo.Length; stage++) + { + ShaderProgramInfo info = _currentProgramInfo[stage]; + + if (info == null) + { + continue; + } + + for (int index = 0; index < info.SBuffers.Count; index++) + { + BufferDescriptor sb = info.SBuffers[index]; + + ulong sbDescAddress = _bufferManager.GetGraphicsUniformBufferAddress(stage, 0); + + int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10; + + sbDescAddress += (ulong)sbDescOffset; + + Span sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10); + + SbDescriptor sbDescriptor = MemoryMarshal.Cast(sbDescriptorData)[0]; + + _bufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size); + } + } + } + + private void UpdateRenderTargetStateIfNeeded() + { + if (_context.State.QueryModified(MethodOffset.RtColorState, + MethodOffset.RtDepthStencilState, + MethodOffset.RtDepthStencilSize, + MethodOffset.RtDepthStencilEnable)) + { + UpdateRenderTargetState(); + } + } + + private void UpdateRenderTargetState() + { + var msaaMode = _context.State.Get(MethodOffset.RtMsaaMode); int samplesInX = msaaMode.SamplesInX(); int samplesInY = msaaMode.SamplesInY(); @@ -173,7 +233,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { for (int index = 0; index < Constants.TotalRenderTargets; index++) { - RtColorState colorState = _context.State.GetRtColorState(index); + var colorState = _context.State.Get(MethodOffset.RtColorState, index); if (!IsRtEnabled(colorState)) { @@ -189,7 +249,10 @@ namespace Ryujinx.Graphics.Gpu.Engine _textureManager.SetRenderTargetColor(index, color); - color.Modified = true; + if (color != null) + { + color.Modified = true; + } } } else @@ -199,14 +262,14 @@ namespace Ryujinx.Graphics.Gpu.Engine color3D.Modified = true; } - bool dsEnable = _context.State.Get(MethodOffset.RtDepthStencilEnable); + bool dsEnable = _context.State.Get(MethodOffset.RtDepthStencilEnable); Image.Texture depthStencil = null; if (dsEnable) { - var dsState = _context.State.GetRtDepthStencilState(); - var dsSize = _context.State.GetRtDepthStencilSize(); + var dsState = _context.State.Get(MethodOffset.RtDepthStencilState); + var dsSize = _context.State.Get (MethodOffset.RtDepthStencilSize); depthStencil = _textureManager.FindOrCreateTexture( dsState, @@ -216,11 +279,16 @@ namespace Ryujinx.Graphics.Gpu.Engine } _textureManager.SetRenderTargetDepthStencil(depthStencil); + + if (depthStencil != null) + { + depthStencil.Modified = true; + } } private Image.Texture Get3DRenderTarget(int samplesInX, int samplesInY) { - RtColorState colorState0 = _context.State.GetRtColorState(0); + var colorState0 = _context.State.Get(MethodOffset.RtColorState, 0); if (!IsRtEnabled(colorState0) || !colorState0.MemoryLayout.UnpackIsTarget3D() || colorState0.Depth != 1) { @@ -232,7 +300,7 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 1; index < Constants.TotalRenderTargets; index++) { - RtColorState colorState = _context.State.GetRtColorState(index); + var colorState = _context.State.Get(MethodOffset.RtColorState, index); if (!IsRtEnabled(colorState)) { @@ -266,9 +334,9 @@ namespace Ryujinx.Graphics.Gpu.Engine private void UpdateDepthTestState() { _context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor( - _context.State.GetDepthTestEnable().IsTrue(), - _context.State.GetDepthWriteEnable().IsTrue(), - _context.State.GetDepthTestFunc())); + _context.State.Get(MethodOffset.DepthTestEnable), + _context.State.Get(MethodOffset.DepthWriteEnable), + _context.State.Get(MethodOffset.DepthTestFunc))); } private void UpdateViewportTransform() @@ -277,8 +345,8 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 0; index < Constants.TotalViewports; index++) { - var transform = _context.State.Get(MethodOffset.ViewportTransform + index * 8); - var extents = _context.State.Get (MethodOffset.ViewportExtents + index * 4); + var transform = _context.State.Get(MethodOffset.ViewportTransform, index); + var extents = _context.State.Get (MethodOffset.ViewportExtents, index); float x = transform.TranslateX - MathF.Abs(transform.ScaleX); float y = transform.TranslateY - MathF.Abs(transform.ScaleY); @@ -303,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Engine private void UpdateDepthBiasState() { - var polygonOffset = _context.State.Get(MethodOffset.DepthBiasState); + var depthBias = _context.State.Get(MethodOffset.DepthBiasState); float factor = _context.State.Get(MethodOffset.DepthBiasFactor); float units = _context.State.Get(MethodOffset.DepthBiasUnits); @@ -311,18 +379,18 @@ namespace Ryujinx.Graphics.Gpu.Engine PolygonModeMask enables = 0; - enables = (polygonOffset.PointEnable.IsTrue() ? PolygonModeMask.Point : 0); - enables |= (polygonOffset.LineEnable.IsTrue() ? PolygonModeMask.Line : 0); - enables |= (polygonOffset.FillEnable.IsTrue() ? PolygonModeMask.Fill : 0); + enables = (depthBias.PointEnable ? PolygonModeMask.Point : 0); + enables |= (depthBias.LineEnable ? PolygonModeMask.Line : 0); + enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0); _context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp); } private void UpdateStencilTestState() { - StencilBackMasks backMasks = _context.State.GetStencilBackMasks(); - StencilTestState test = _context.State.GetStencilTestState(); - StencilBackTestState backTest = _context.State.GetStencilBackTestState(); + var backMasks = _context.State.Get (MethodOffset.StencilBackMasks); + var test = _context.State.Get (MethodOffset.StencilTestState); + var backTest = _context.State.Get(MethodOffset.StencilBackTestState); CompareOp backFunc; StencilOp backSFail; @@ -332,7 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine int backFuncMask; int backMask; - if (backTest.TwoSided.IsTrue()) + if (backTest.TwoSided) { backFunc = backTest.BackFunc; backSFail = backTest.BackSFail; @@ -354,7 +422,7 @@ namespace Ryujinx.Graphics.Gpu.Engine } _context.Renderer.Pipeline.SetStencilTest(new StencilTestDescriptor( - test.Enable.IsTrue(), + test.Enable, test.FrontFunc, test.FrontSFail, test.FrontDpPass, @@ -373,42 +441,18 @@ namespace Ryujinx.Graphics.Gpu.Engine private void UpdateSamplerPoolState() { - PoolState samplerPool = _context.State.GetSamplerPoolState(); + var samplerPool = _context.State.Get(MethodOffset.SamplerPoolState); _textureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); } private void UpdateTexturePoolState() { - PoolState texturePool = _context.State.GetTexturePoolState(); + var texturePool = _context.State.Get(MethodOffset.TexturePoolState); _textureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); - _textureManager.SetGraphicsTextureBufferIndex(_context.State.GetTextureBufferIndex()); - } - - private void UpdateInputAssemblerGroupState() - { - // Must be updated before the vertex buffer. - if ((_context.State.StateWriteFlags & StateWriteFlags.VertexAttribState) != 0) - { - UpdateVertexAttribState(); - } - - if ((_context.State.StateWriteFlags & StateWriteFlags.PrimitiveRestartState) != 0) - { - UpdatePrimitiveRestartState(); - } - - if ((_context.State.StateWriteFlags & StateWriteFlags.IndexBufferState) != 0) - { - UpdateIndexBufferState(); - } - - if ((_context.State.StateWriteFlags & StateWriteFlags.VertexBufferState) != 0) - { - UpdateVertexBufferState(); - } + _textureManager.SetGraphicsTextureBufferIndex(_context.State.Get(MethodOffset.TextureBufferIndex)); } private void UpdateVertexAttribState() @@ -417,7 +461,7 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 0; index < 16; index++) { - VertexAttribState vertexAttrib = _context.State.GetVertexAttribState(index); + var vertexAttrib = _context.State.Get(MethodOffset.VertexAttribState, index); if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format)) { @@ -446,7 +490,7 @@ namespace Ryujinx.Graphics.Gpu.Engine private void UpdateIndexBufferState() { - IndexBufferState indexBuffer = _context.State.GetIndexBufferState(); + var indexBuffer = _context.State.Get(MethodOffset.IndexBufferState); _firstIndex = indexBuffer.First; _indexCount = indexBuffer.Count; @@ -475,70 +519,13 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateVertexBufferState(); } - private uint GetIndexBufferMaxIndex(ulong gpuVa, ulong size, IndexType type) - { - ulong address = _context.MemoryManager.Translate(gpuVa); - - Span data = _context.PhysicalMemory.Read(address, size); - - uint maxIndex = 0; - - switch (type) - { - case IndexType.UByte: - { - for (int index = 0; index < data.Length; index++) - { - if (maxIndex < data[index]) - { - maxIndex = data[index]; - } - } - - break; - } - - case IndexType.UShort: - { - Span indices = MemoryMarshal.Cast(data); - - for (int index = 0; index < indices.Length; index++) - { - if (maxIndex < indices[index]) - { - maxIndex = indices[index]; - } - } - - break; - } - - case IndexType.UInt: - { - Span indices = MemoryMarshal.Cast(data); - - for (int index = 0; index < indices.Length; index++) - { - if (maxIndex < indices[index]) - { - maxIndex = indices[index]; - } - } - - break; - } - } - - return maxIndex; - } - private void UpdateVertexBufferState() { _isAnyVbInstanced = false; for (int index = 0; index < 16; index++) { - VertexBufferState vertexBuffer = _context.State.GetVertexBufferState(index); + var vertexBuffer = _context.State.Get(MethodOffset.VertexBufferState, index); if (!vertexBuffer.UnpackEnable()) { @@ -547,13 +534,13 @@ namespace Ryujinx.Graphics.Gpu.Engine continue; } - GpuVa endAddress = _context.State.GetVertexBufferEndAddress(index); + GpuVa endAddress = _context.State.Get(MethodOffset.VertexBufferEndAddress, index); ulong address = vertexBuffer.Address.Pack(); int stride = vertexBuffer.UnpackStride(); - bool instanced = _context.State.Get(MethodOffset.VertexBufferInstanced + index); + bool instanced = _context.State.Get(MethodOffset.VertexBufferInstanced + index); int divisor = instanced ? vertexBuffer.Divisor : 0; @@ -571,9 +558,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.GetBaseInstance(); + int firstInstance = _context.State.Get(MethodOffset.FirstInstance); - VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); + var drawState = _context.State.Get(MethodOffset.VertexBufferDrawState); size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride); } @@ -584,9 +571,9 @@ namespace Ryujinx.Graphics.Gpu.Engine private void UpdateFaceState() { - FaceState face = _context.State.GetFaceState(); + var face = _context.State.Get(MethodOffset.FaceState); - _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable.IsTrue(), face.CullFace); + _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace); _context.Renderer.Pipeline.SetFrontFace(face.FrontFace); } @@ -597,7 +584,7 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 0; index < Constants.TotalRenderTargets; index++) { - RtColorMask colorMask = _context.State.Get(MethodOffset.RtColorMask + index); + var colorMask = _context.State.Get(MethodOffset.RtColorMask, index); uint componentMask = 0; @@ -618,12 +605,12 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 0; index < 8; index++) { - bool blendEnable = _context.State.GetBlendEnable(index).IsTrue(); + bool enable = _context.State.Get(MethodOffset.BlendEnable, index); - BlendState blend = _context.State.GetBlendState(index); + var blend = _context.State.Get(MethodOffset.BlendState, index); BlendDescriptor descriptor = new BlendDescriptor( - blendEnable, + enable, blend.ColorOp, blend.ColorSrcFactor, blend.ColorDstFactor, @@ -656,11 +643,11 @@ namespace Ryujinx.Graphics.Gpu.Engine Span addressesArray = MemoryMarshal.Cast(addressesSpan); - ulong baseAddress = _context.State.GetShaderBaseAddress().Pack(); + ulong baseAddress = _context.State.Get(MethodOffset.ShaderBaseAddress).Pack(); for (int index = 0; index < 6; index++) { - ShaderState shader = _context.State.GetShaderState(index); + var shader = _context.State.Get(MethodOffset.ShaderState, index); if (!shader.UnpackEnable() && index != 1) { @@ -678,6 +665,8 @@ namespace Ryujinx.Graphics.Gpu.Engine { ShaderProgramInfo info = gs.Shader[stage]?.Info; + _currentProgramInfo[stage] = info; + if (info == null) { continue; @@ -714,21 +703,7 @@ namespace Ryujinx.Graphics.Gpu.Engine for (int index = 0; index < info.SBuffers.Count; index++) { - BufferDescriptor sb = info.SBuffers[index]; - - sbEnableMask |= 1u << sb.Slot; - - ulong sbDescAddress = _bufferManager.GetGraphicsUniformBufferAddress(stage, 0); - - int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10; - - sbDescAddress += (ulong)sbDescOffset; - - Span sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10); - - SbDescriptor sbDescriptor = MemoryMarshal.Cast(sbDescriptorData)[0]; - - _bufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size); + sbEnableMask |= 1u << info.SBuffers[index].Slot; } for (int index = 0; index < info.CBuffers.Count; index++) diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs index 196fc137..7457de19 100644 --- a/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -1,3 +1,4 @@ +using Ryujinx.Graphics.Gpu.Memory; using System; namespace Ryujinx.Graphics.Gpu.Image @@ -31,7 +32,7 @@ namespace Ryujinx.Graphics.Gpu.Image public void SynchronizeMemory() { - (ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size); + (ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.TexturePool); for (int index = 0; index < modifiedRanges.Length; index++) { diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 7ebf01b8..8da1041b 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu.Image _sequenceNumber = _context.SequenceNumber; - bool modified = _context.PhysicalMemory.GetModifiedRanges(Address, Size).Length != 0; + bool modified = _context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.Texture).Length != 0; if (!modified && _hasData) { diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 91a9cfd1..7cf79d0f 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -114,7 +114,7 @@ namespace Ryujinx.Graphics.Gpu.Image public void CommitComputeBindings() { - // Evert time we switch between graphics and compute work, + // Every time we switch between graphics and compute work, // we must rebind everything. // Since compute work happens less often, we always do that // before and after the compute dispatch. diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 30bd1ac0..6f904d0f 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -69,7 +69,7 @@ namespace Ryujinx.Graphics.Gpu.Memory return; } - (ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size); + (ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size, ResourceName.Buffer); for (int index = 0; index < modifiedRanges.Length; index++) { diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 3ceee206..6d7fab68 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -116,9 +116,13 @@ namespace Ryujinx.Graphics.Gpu.Memory ulong address = TranslateAndCreateBuffer(gpuVa, size); - _gpStorageBuffers[stage].Bind(index, address, size); + if (_gpStorageBuffers[stage].Buffers[index].Address != address || + _gpStorageBuffers[stage].Buffers[index].Size != size) + { + _gpStorageBuffersDirty = true; + } - _gpStorageBuffersDirty = true; + _gpStorageBuffers[stage].Bind(index, address, size); } public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size) diff --git a/Ryujinx.Graphics.Gpu/Memory/IPhysicalMemory.cs b/Ryujinx.Graphics.Gpu/Memory/IPhysicalMemory.cs index 5f21704d..73b3a9e1 100644 --- a/Ryujinx.Graphics.Gpu/Memory/IPhysicalMemory.cs +++ b/Ryujinx.Graphics.Gpu/Memory/IPhysicalMemory.cs @@ -10,6 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Memory void Write(ulong address, Span data); - (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size); + (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, ResourceName name); } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index d1a3e69c..59319a47 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Memory private const int PtLvl0Bits = 14; private const int PtLvl1Bits = 14; - private const int PtPageBits = 12; + public const int PtPageBits = 12; private const ulong PtLvl0Size = 1UL << PtLvl0Bits; private const ulong PtLvl1Size = 1UL << PtLvl1Bits; diff --git a/Ryujinx.Graphics.Gpu/Memory/ResourceName.cs b/Ryujinx.Graphics.Gpu/Memory/ResourceName.cs new file mode 100644 index 00000000..9476a384 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Memory/ResourceName.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Graphics.Gpu.Memory +{ + public enum ResourceName + { + Buffer, + Texture, + TexturePool, + SamplerPool + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/State/BlendState.cs b/Ryujinx.Graphics.Gpu/State/BlendState.cs index cf22dc1b..7029ed6c 100644 --- a/Ryujinx.Graphics.Gpu/State/BlendState.cs +++ b/Ryujinx.Graphics.Gpu/State/BlendState.cs @@ -4,12 +4,13 @@ namespace Ryujinx.Graphics.Gpu.State { struct BlendState { - public Bool SeparateAlpha; + public Boolean32 SeparateAlpha; public BlendOp ColorOp; public BlendFactor ColorSrcFactor; public BlendFactor ColorDstFactor; public BlendOp AlphaOp; public BlendFactor AlphaSrcFactor; public BlendFactor AlphaDstFactor; + public uint Padding; } } diff --git a/Ryujinx.Graphics.Gpu/State/Bool.cs b/Ryujinx.Graphics.Gpu/State/Bool.cs deleted file mode 100644 index 8aadcfcc..00000000 --- a/Ryujinx.Graphics.Gpu/State/Bool.cs +++ /dev/null @@ -1,17 +0,0 @@ -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/Boolean32.cs b/Ryujinx.Graphics.Gpu/State/Boolean32.cs new file mode 100644 index 00000000..3db912d4 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/State/Boolean32.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Graphics.Gpu.State +{ + struct Boolean32 + { + private uint _value; + + public static implicit operator bool(Boolean32 value) + { + return (value._value & 1) != 0; + } + } +} diff --git a/Ryujinx.Graphics.Gpu/State/CopyTexture.cs b/Ryujinx.Graphics.Gpu/State/CopyTexture.cs index 363d84a2..83e7e430 100644 --- a/Ryujinx.Graphics.Gpu/State/CopyTexture.cs +++ b/Ryujinx.Graphics.Gpu/State/CopyTexture.cs @@ -3,7 +3,7 @@ namespace Ryujinx.Graphics.Gpu.State struct CopyTexture { public RtFormat Format; - public bool LinearLayout; + public Boolean32 LinearLayout; public MemoryLayout MemoryLayout; public int Depth; public int Layer; diff --git a/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs b/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs index c88d27dd..45d9c93f 100644 --- a/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs +++ b/Ryujinx.Graphics.Gpu/State/DepthBiasState.cs @@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Gpu.State { struct DepthBiasState { - public Bool PointEnable; - public Bool LineEnable; - public Bool FillEnable; + public Boolean32 PointEnable; + public Boolean32 LineEnable; + public Boolean32 FillEnable; } } diff --git a/Ryujinx.Graphics.Gpu/State/FaceState.cs b/Ryujinx.Graphics.Gpu/State/FaceState.cs index 53763032..2e62968c 100644 --- a/Ryujinx.Graphics.Gpu/State/FaceState.cs +++ b/Ryujinx.Graphics.Gpu/State/FaceState.cs @@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Gpu.State { struct FaceState { - public Bool CullEnable; + public Boolean32 CullEnable; public FrontFace FrontFace; public Face CullFace; } diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs index 4e4241ca..6c603f30 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuState.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs @@ -1,6 +1,4 @@ -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Gpu.Image; -using System; +using System; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.State @@ -17,39 +15,54 @@ namespace Ryujinx.Graphics.Gpu.State { public MethodCallback Callback; - public StateWriteFlags WriteFlag; + public MethodOffset BaseOffset; + + public int Stride; + public int Count; + + public bool Modified; } private Register[] _registers; - public StateWriteFlags StateWriteFlags { get; set; } - public GpuState() { _backingMemory = new int[RegistersCount]; _registers = new Register[RegistersCount]; - StateWriteFlags = StateWriteFlags.Any; + for (int index = 0; index < _registers.Length; index++) + { + _registers[index].BaseOffset = (MethodOffset)index; + _registers[index].Stride = 1; + _registers[index].Count = 1; + _registers[index].Modified = true; + } + + foreach (var item in GpuStateTable.Table) + { + int totalRegs = item.Size * item.Count; + + for (int regOffset = 0; regOffset < totalRegs; regOffset++) + { + int index = (int)item.Offset + regOffset; + + _registers[index].BaseOffset = item.Offset; + _registers[index].Stride = item.Size; + _registers[index].Count = item.Count; + } + } 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; + _registers[(int)register.BaseOffset].Modified = true; } _backingMemory[meth.Method] = meth.Argument; @@ -67,264 +80,11 @@ namespace Ryujinx.Graphics.Gpu.State 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(MethodOffset.CopyDstTexture); - } - - public CopyTexture GetCopySrcTexture() - { - return Get(MethodOffset.CopySrcTexture); - } - - public RtColorState GetRtColorState(int index) - { - return Get(MethodOffset.RtColorState + 16 * index); - } - - public CopyTextureControl GetCopyTextureControl() - { - return Get(MethodOffset.CopyTextureControl); - } - - public CopyRegion GetCopyRegion() - { - return Get(MethodOffset.CopyRegion); - } - - public ViewportTransform GetViewportTransform(int index) - { - return Get(MethodOffset.ViewportTransform + 8 * index); - } - - public ViewportExtents GetViewportExtents(int index) - { - return Get(MethodOffset.ViewportExtents + 4 * index); - } - - public VertexBufferDrawState GetVertexBufferDrawState() - { - return Get(MethodOffset.VertexBufferDrawState); - } - - public ClearColors GetClearColors() - { - return Get(MethodOffset.ClearColors); - } - - public float GetClearDepthValue() - { - return Get(MethodOffset.ClearDepthValue); - } - - public int GetClearStencilValue() - { - return _backingMemory[(int)MethodOffset.ClearStencilValue]; - } - - public StencilBackMasks GetStencilBackMasks() - { - return Get(MethodOffset.StencilBackMasks); - } - - public RtDepthStencilState GetRtDepthStencilState() - { - return Get(MethodOffset.RtDepthStencilState); - } - - public VertexAttribState GetVertexAttribState(int index) - { - return Get(MethodOffset.VertexAttribState + index); - } - - public Size3D GetRtDepthStencilSize() - { - return Get(MethodOffset.RtDepthStencilSize); - } - - public Bool GetDepthTestEnable() - { - return Get(MethodOffset.DepthTestEnable); - } - - public CompareOp GetDepthTestFunc() - { - return Get(MethodOffset.DepthTestFunc); - } - - public Bool GetDepthWriteEnable() - { - return Get(MethodOffset.DepthWriteEnable); - } - - public Bool GetBlendEnable(int index) - { - return Get(MethodOffset.BlendEnable + index); - } - - public StencilTestState GetStencilTestState() - { - return Get(MethodOffset.StencilTestState); - } - - public int GetBaseVertex() - { - return _backingMemory[(int)MethodOffset.FirstVertex]; - } - - public int GetBaseInstance() - { - return _backingMemory[(int)MethodOffset.FirstInstance]; - } - - public PoolState GetSamplerPoolState() - { - return Get(MethodOffset.SamplerPoolState); - } - - public PoolState GetTexturePoolState() - { - return Get(MethodOffset.TexturePoolState); - } - - public StencilBackTestState GetStencilBackTestState() - { - return Get(MethodOffset.StencilBackTestState); - } - - public TextureMsaaMode GetRtMsaaMode() - { - return Get(MethodOffset.RtMsaaMode); - } - - public GpuVa GetShaderBaseAddress() - { - return Get(MethodOffset.ShaderBaseAddress); - } - - public PrimitiveRestartState GetPrimitiveRestartState() - { - return Get(MethodOffset.PrimitiveRestartState); - } - - public IndexBufferState GetIndexBufferState() - { - return Get(MethodOffset.IndexBufferState); - } - - public FaceState GetFaceState() - { - return Get(MethodOffset.FaceState); - } - - public ReportState GetReportState() - { - return Get(MethodOffset.ReportState); - } - - public VertexBufferState GetVertexBufferState(int index) - { - return Get(MethodOffset.VertexBufferState + 4 * index); - } - - public BlendState GetBlendState(int index) - { - return Get(MethodOffset.BlendState + 8 * index); - } - - public GpuVa GetVertexBufferEndAddress(int index) - { - return Get(MethodOffset.VertexBufferEndAddress + 2 * index); - } - - public ShaderState GetShaderState(int index) - { - return Get(MethodOffset.ShaderState + 16 * index); - } - - public UniformBufferState GetUniformBufferState() - { - return Get(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. @@ -341,69 +101,11 @@ namespace Ryujinx.Graphics.Gpu.State _backingMemory[(int)MethodOffset.RtColorMask] = 0x1111; } - private void InitializeStateWatchers() + public void RegisterCallback(MethodOffset offset, int count, MethodCallback callback) { - SetWriteStateFlag(MethodOffset.RtColorState, StateWriteFlags.RtColorState, 16 * 8); - - SetWriteStateFlag(MethodOffset.ViewportTransform, StateWriteFlags.ViewportTransform, 8 * 8); - SetWriteStateFlag(MethodOffset.ViewportExtents, StateWriteFlags.ViewportTransform, 4 * 8); - - SetWriteStateFlag(MethodOffset.VertexBufferDrawState, StateWriteFlags.VertexBufferState); - - SetWriteStateFlag(MethodOffset.DepthBiasState, StateWriteFlags.DepthBiasState); - - SetWriteStateFlag(MethodOffset.DepthBiasFactor, StateWriteFlags.DepthBiasState, 1); - SetWriteStateFlag(MethodOffset.DepthBiasUnits, StateWriteFlags.DepthBiasState, 1); - SetWriteStateFlag(MethodOffset.DepthBiasClamp, StateWriteFlags.DepthBiasState, 1); - - SetWriteStateFlag(MethodOffset.RtDepthStencilState, StateWriteFlags.RtDepthStencilState); - SetWriteStateFlag (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 (MethodOffset.StencilBackMasks, StateWriteFlags.StencilTestState); - SetWriteStateFlag (MethodOffset.StencilTestState, StateWriteFlags.StencilTestState); - SetWriteStateFlag(MethodOffset.StencilBackTestState, StateWriteFlags.StencilTestState); - - SetWriteStateFlag(MethodOffset.SamplerPoolState, StateWriteFlags.SamplerPoolState); - SetWriteStateFlag(MethodOffset.TexturePoolState, StateWriteFlags.TexturePoolState); - - SetWriteStateFlag(MethodOffset.ShaderBaseAddress, StateWriteFlags.ShaderState); - - SetWriteStateFlag(MethodOffset.PrimitiveRestartState, StateWriteFlags.PrimitiveRestartState); - - SetWriteStateFlag(MethodOffset.IndexBufferState, StateWriteFlags.IndexBufferState); - - SetWriteStateFlag(MethodOffset.FaceState, StateWriteFlags.FaceState); - - SetWriteStateFlag(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(MethodOffset offset, StateWriteFlags flag) - { - SetWriteStateFlag(offset, flag, Marshal.SizeOf()); - } - - private void SetWriteStateFlag(MethodOffset offset, StateWriteFlags flag, int size) - { - for (int index = 0; index < size; index++) + for (int index = 0; index < count; index++) { - _registers[(int)offset + index].WriteFlag = flag; + _registers[(int)offset + index].Callback = callback; } } @@ -412,9 +114,37 @@ namespace Ryujinx.Graphics.Gpu.State _registers[(int)offset].Callback = callback; } - private void RegisterCallback(int offset, MethodCallback callback) + public bool QueryModified(params MethodOffset[] offsets) { - _registers[offset].Callback = callback; + bool modified = false; + + for (int index = 0; index < offsets.Length; index++) + { + modified |= QueryModified(offsets[index]); + } + + return modified; + } + + public bool QueryModified(MethodOffset offset) + { + bool modified = _registers[(int)offset].Modified; + + _registers[(int)offset].Modified = false; + + return modified; + } + + public T Get(MethodOffset offset, int index) where T : struct + { + Register register = _registers[(int)offset]; + + if ((uint)index >= register.Count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return Get(offset + index * register.Stride); } public T Get(MethodOffset offset) where T : struct diff --git a/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs new file mode 100644 index 00000000..268b1fdc --- /dev/null +++ b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs @@ -0,0 +1,56 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.State +{ + static class GpuStateTable + { + public struct TableItem + { + public MethodOffset Offset { get; } + + public int Size { get; } + public int Count { get; } + + public TableItem(MethodOffset offset, Type type, int count) + { + int sizeInBytes = Marshal.SizeOf(type); + + Debug.Assert((sizeInBytes & 3) == 0); + + Offset = offset; + Size = sizeInBytes / 4; + Count = count; + } + } + + public static TableItem[] Table = new TableItem[] + { + new TableItem(MethodOffset.RtColorState, typeof(RtColorState), 8), + new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), 8), + new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8), + new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1), + new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1), + new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1), + new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1), + new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16), + new TableItem(MethodOffset.RtDepthStencilSize, typeof(Size3D), 1), + new TableItem(MethodOffset.BlendEnable, typeof(Boolean32), 8), + new TableItem(MethodOffset.StencilTestState, typeof(StencilTestState), 1), + new TableItem(MethodOffset.SamplerPoolState, typeof(PoolState), 1), + new TableItem(MethodOffset.TexturePoolState, typeof(PoolState), 1), + new TableItem(MethodOffset.StencilBackTestState, typeof(StencilBackTestState), 1), + new TableItem(MethodOffset.ShaderBaseAddress, typeof(GpuVa), 1), + new TableItem(MethodOffset.PrimitiveRestartState, typeof(PrimitiveRestartState), 1), + new TableItem(MethodOffset.IndexBufferState, typeof(IndexBufferState), 1), + new TableItem(MethodOffset.VertexBufferInstanced, typeof(Boolean32), 16), + new TableItem(MethodOffset.FaceState, typeof(FaceState), 1), + new TableItem(MethodOffset.RtColorMask, typeof(RtColorMask), 8), + new TableItem(MethodOffset.VertexBufferState, typeof(VertexBufferState), 16), + new TableItem(MethodOffset.BlendState, typeof(BlendState), 8), + new TableItem(MethodOffset.VertexBufferEndAddress, typeof(GpuVa), 16), + new TableItem(MethodOffset.ShaderState, typeof(ShaderState), 6), + }; + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/State/GpuVa.cs b/Ryujinx.Graphics.Gpu/State/GpuVa.cs index 01ad70b7..4bb56a10 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuVa.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuVa.cs @@ -9,10 +9,5 @@ namespace Ryujinx.Graphics.Gpu.State { return Low | ((ulong)High << 32); } - - public bool IsNullPtr() - { - return (Low | High) == 0; - } } } diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index 3637d874..4c5e0beb 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -2,63 +2,76 @@ 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, - TextureBarrier = 0x378, - StencilBackMasks = 0x3d5, - InvalidateTextures = 0x3dd, - TextureBarrierTiled = 0x3df, - 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 + I2mParams = 0x60, + LaunchDma = 0x6c, + LoadInlineData = 0x6d, + CopyDstTexture = 0x80, + CopySrcTexture = 0x8c, + DispatchParamsAddress = 0xad, + Dispatch = 0xaf, + CopyBuffer = 0xc0, + CopyBufferParams = 0x100, + CopyBufferSwizzle = 0x1c2, + CopyBufferDstTexture = 0x1c3, + CopyBufferSrcTexture = 0x1ca, + RtColorState = 0x200, + CopyTextureControl = 0x223, + CopyRegion = 0x22c, + CopyTexture = 0x237, + ViewportTransform = 0x280, + ViewportExtents = 0x300, + VertexBufferDrawState = 0x35d, + ClearColors = 0x360, + ClearDepthValue = 0x364, + ClearStencilValue = 0x368, + DepthBiasState = 0x370, + TextureBarrier = 0x378, + StencilBackMasks = 0x3d5, + InvalidateTextures = 0x3dd, + TextureBarrierTiled = 0x3df, + 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, + DrawEnd = 0x585, + DrawBegin = 0x586, + PrimitiveRestartState = 0x591, + IndexBufferState = 0x5f2, + IndexBufferCount = 0x5f8, + DepthBiasClamp = 0x61f, + VertexBufferInstanced = 0x620, + FaceState = 0x646, + Clear = 0x674, + RtColorMask = 0x680, + ReportState = 0x6c0, + Report = 0x6c3, + VertexBufferState = 0x700, + BlendState = 0x780, + VertexBufferEndAddress = 0x7c0, + ShaderState = 0x800, + UniformBufferState = 0x8e0, + UniformBufferUpdateData = 0x8e4, + UniformBufferBindVertex = 0x904, + UniformBufferBindTessControl = 0x90c, + UniformBufferBindTessEvaluation = 0x914, + UniformBufferBindGeometry = 0x91c, + UniformBufferBindFragment = 0x924, + TextureBufferIndex = 0x982 } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs b/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs index 21405be7..0b4e1024 100644 --- a/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs +++ b/Ryujinx.Graphics.Gpu/State/PrimitiveRestartState.cs @@ -2,7 +2,7 @@ namespace Ryujinx.Graphics.Gpu.State { struct PrimitiveRestartState { - public bool Enable; - public int Index; + public Boolean32 Enable; + public int Index; } } diff --git a/Ryujinx.Graphics.Gpu/State/RtColorState.cs b/Ryujinx.Graphics.Gpu/State/RtColorState.cs index bb6ae208..beec2593 100644 --- a/Ryujinx.Graphics.Gpu/State/RtColorState.cs +++ b/Ryujinx.Graphics.Gpu/State/RtColorState.cs @@ -9,5 +9,13 @@ namespace Ryujinx.Graphics.Gpu.State public MemoryLayout MemoryLayout; public int Depth; public int LayerSize; + public int BaseLayer; + public int Unknown0x24; + public int Padding0; + public int Padding1; + public int Padding2; + public int Padding3; + public int Padding4; + public int Padding5; } } diff --git a/Ryujinx.Graphics.Gpu/State/RtFormat.cs b/Ryujinx.Graphics.Gpu/State/RtFormat.cs index 960da445..7f9ad63d 100644 --- a/Ryujinx.Graphics.Gpu/State/RtFormat.cs +++ b/Ryujinx.Graphics.Gpu/State/RtFormat.cs @@ -8,6 +8,8 @@ namespace Ryujinx.Graphics.Gpu.State D32Float = 0xa, D16Unorm = 0x13, D24UnormS8Uint = 0x14, + D24Unorm = 0x15, + S8UintD24Unorm = 0x16, S8Uint = 0x17, D32FloatS8Uint = 0x19, R32G32B32A32Float = 0xc0, @@ -74,6 +76,8 @@ namespace Ryujinx.Graphics.Gpu.State 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.D24Unorm: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4); + case RtFormat.S8UintD24Unorm: 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); diff --git a/Ryujinx.Graphics.Gpu/State/ShaderState.cs b/Ryujinx.Graphics.Gpu/State/ShaderState.cs index 536d7dcf..e5c9c35a 100644 --- a/Ryujinx.Graphics.Gpu/State/ShaderState.cs +++ b/Ryujinx.Graphics.Gpu/State/ShaderState.cs @@ -10,6 +10,14 @@ namespace Ryujinx.Graphics.Gpu.State public uint Unknown0x14; public uint Unknown0x18; public uint Unknown0x1c; + public uint Unknown0x20; + public uint Unknown0x24; + public uint Unknown0x28; + public uint Unknown0x2c; + public uint Unknown0x30; + public uint Unknown0x34; + public uint Unknown0x38; + public uint Unknown0x3c; public bool UnpackEnable() { diff --git a/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs b/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs index 18b31eaa..f9f47b40 100644 --- a/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs +++ b/Ryujinx.Graphics.Gpu/State/StencilBackTestState.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.State { struct StencilBackTestState { - public Bool TwoSided; + public Boolean32 TwoSided; public StencilOp BackSFail; public StencilOp BackDpFail; public StencilOp BackDpPass; diff --git a/Ryujinx.Graphics.Gpu/State/StencilTestState.cs b/Ryujinx.Graphics.Gpu/State/StencilTestState.cs index b60f002f..1169a358 100644 --- a/Ryujinx.Graphics.Gpu/State/StencilTestState.cs +++ b/Ryujinx.Graphics.Gpu/State/StencilTestState.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.State { struct StencilTestState { - public Bool Enable; + public Boolean32 Enable; public StencilOp FrontSFail; public StencilOp FrontDpFail; public StencilOp FrontDpPass; diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index e804eff5..5df801f8 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -906,12 +906,15 @@ namespace Ryujinx.Graphics.OpenGL private void RestoreComponentMask(int index) { - GL.ColorMask( - index, - (_componentMasks[index] & 1u) != 0, - (_componentMasks[index] & 2u) != 0, - (_componentMasks[index] & 4u) != 0, - (_componentMasks[index] & 8u) != 0); + if (_componentMasks != null) + { + GL.ColorMask( + index, + (_componentMasks[index] & 1u) != 0, + (_componentMasks[index] & 2u) != 0, + (_componentMasks[index] & 4u) != 0, + (_componentMasks[index] & 8u) != 0); + } } public void RebindProgram() diff --git a/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs b/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs index b8a4f6d5..348a4768 100644 --- a/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs +++ b/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs @@ -6,6 +6,5 @@ namespace Ryujinx.Graphics.Shader.Decoders Green = 1 << 1, Blue = 1 << 2, Alpha = 1 << 3 - } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs b/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs index 3948c899..1f51d93c 100644 --- a/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs +++ b/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs @@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.Shader.Decoders { enum SystemRegister { + ThreadId = 0x20, ThreadIdX = 0x21, ThreadIdY = 0x22, ThreadIdZ = 0x23, diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index f66ebc9f..b9bb18d9 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -27,6 +27,20 @@ namespace Ryujinx.Graphics.Shader.Instructions switch (sysReg) { + case SystemRegister.ThreadId: + { + Operand tidX = Attribute(AttributeConsts.ThreadIdX); + Operand tidY = Attribute(AttributeConsts.ThreadIdY); + Operand tidZ = Attribute(AttributeConsts.ThreadIdZ); + + tidY = context.ShiftLeft(tidY, Const(16)); + tidZ = context.ShiftLeft(tidZ, Const(26)); + + src = context.BitwiseOr(tidX, context.BitwiseOr(tidY, tidZ)); + + break; + } + case SystemRegister.ThreadIdX: src = Attribute(AttributeConsts.ThreadIdX); break; case SystemRegister.ThreadIdY: src = Attribute(AttributeConsts.ThreadIdY); break; case SystemRegister.ThreadIdZ: src = Attribute(AttributeConsts.ThreadIdZ); break; diff --git a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index cb08a213..d6ce76db 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Add(Instruction.ExponentB2, VariableType.Scalar, VariableType.Scalar); Add(Instruction.Floor, VariableType.F32, VariableType.F32); Add(Instruction.FusedMultiplyAdd, VariableType.F32, VariableType.F32, VariableType.F32, VariableType.F32); + Add(Instruction.ImageLoad, VariableType.F32); + Add(Instruction.ImageStore, VariableType.None); Add(Instruction.IsNan, VariableType.Bool, VariableType.F32); Add(Instruction.LoadAttribute, VariableType.F32, VariableType.S32, VariableType.S32); Add(Instruction.LoadConstant, VariableType.F32, VariableType.S32, VariableType.S32); @@ -105,7 +107,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr public static VariableType GetSrcVarType(Instruction inst, int index) { - if (inst == Instruction.TextureSample) + // TODO: Return correct type depending on source index, + // that can improve the decompiler output. + if (inst == Instruction.TextureSample || + inst == Instruction.ImageLoad || + inst == Instruction.ImageStore) { return VariableType.F32; } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs index 5238645e..bca9ba7c 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs @@ -59,9 +59,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types _cpuMemory.WriteBytes((long)address, data.ToArray()); } - public (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size) + public (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, ResourceName name) { - return _cpuMemory.GetModifiedRanges(address, size); + return _cpuMemory.GetModifiedRanges(address, size, (int)name); } public int GetPageSize()