From f4b74e9ce18b16f48f4e006d98675798874c3b54 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 14 Jan 2024 05:37:19 -0300 Subject: [PATCH] Fix vertex buffer size when switching between inline and state draw parameters (#6101) * Fix vertex buffer size when switching between inline and state draw parameters * Format whitespace --- src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs | 10 ++++++---- src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawState.cs | 10 +++++----- src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs | 10 ++++++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs index 8c72663f1..d8de14de0 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs @@ -103,6 +103,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// Method call argument public void DrawEnd(ThreedClass engine, int argument) { + _drawState.DrawUsesEngineState = true; + DrawEnd( engine, _state.State.IndexBufferState.First, @@ -205,10 +207,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed } else { -#pragma warning disable IDE0059 // Remove unnecessary value assignment - var drawState = _state.State.VertexBufferDrawState; -#pragma warning restore IDE0059 - DrawImpl(engine, drawVertexCount, 1, 0, drawFirstVertex, firstInstance, indexed: false); } @@ -379,6 +377,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed bool oldDrawIndexed = _drawState.DrawIndexed; _drawState.DrawIndexed = true; + _drawState.DrawUsesEngineState = false; engine.ForceStateDirty(IndexBufferCountMethodOffset * 4); DrawEnd(engine, firstIndex, indexCount, 0, 0); @@ -424,6 +423,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed bool oldDrawIndexed = _drawState.DrawIndexed; _drawState.DrawIndexed = false; + _drawState.DrawUsesEngineState = false; engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4); DrawEnd(engine, 0, 0, firstVertex, vertexCount); @@ -544,6 +544,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _state.State.FirstInstance = (uint)firstInstance; _drawState.DrawIndexed = indexed; + _drawState.DrawUsesEngineState = true; _currentSpecState.SetHasConstantBufferDrawParameters(true); engine.UpdateState(); @@ -676,6 +677,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _drawState.DrawIndexed = indexed; _drawState.DrawIndirect = true; + _drawState.DrawUsesEngineState = true; _currentSpecState.SetHasConstantBufferDrawParameters(true); engine.UpdateState(); diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawState.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawState.cs index 8113c1827..03b5e3f3b 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawState.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawState.cs @@ -38,6 +38,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// public bool DrawIndirect; + /// + /// Indicates that the draw is using the draw parameters on the 3D engine state, rather than inline parameters submitted with the draw command. + /// + public bool DrawUsesEngineState; + /// /// Indicates if any of the currently used vertex shaders reads the instance ID. /// @@ -48,11 +53,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// public bool IsAnyVbInstanced; - /// - /// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0. - /// - public bool HasConstantBufferDrawParameters; - /// /// Primitive topology for the next draw. /// diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 24a4d58c7..2b65b4560 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -47,7 +47,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private uint _vbEnableMask; private bool _prevDrawIndexed; - private readonly bool _prevDrawIndirect; + private bool _prevDrawIndirect; + private bool _prevDrawUsesEngineState; private IndexType _prevIndexType; private uint _prevFirstVertex; private bool _prevTfEnable; @@ -236,7 +237,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed // method when doing indexed draws, so we need to make sure // to update the vertex buffers if we are doing a regular // draw after a indexed one and vice-versa. - if (_drawState.DrawIndexed != _prevDrawIndexed) + // Some draws also do not update the engine state, so it is possible for it + // to not be dirty even if the vertex counts or other state changed. We need to force it to be dirty in this case. + if (_drawState.DrawIndexed != _prevDrawIndexed || _drawState.DrawUsesEngineState != _prevDrawUsesEngineState) { _updateTracker.ForceDirty(VertexBufferStateIndex); @@ -251,6 +254,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed } _prevDrawIndexed = _drawState.DrawIndexed; + _prevDrawUsesEngineState = _drawState.DrawUsesEngineState; } // Some draw parameters are used to restrict the vertex buffer size, @@ -260,6 +264,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (_drawState.DrawIndirect != _prevDrawIndirect) { _updateTracker.ForceDirty(VertexBufferStateIndex); + + _prevDrawIndirect = _drawState.DrawIndirect; } // In some cases, the index type is also used to guess the