From f4b74e9ce18b16f48f4e006d98675798874c3b54 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sun, 14 Jan 2024 05:37:19 -0300
Subject: 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(-)

(limited to 'src')

diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs
index 8c72663f..d8de14de 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
         /// <param name="argument">Method call argument</param>
         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 8113c182..03b5e3f3 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
         /// </summary>
         public bool DrawIndirect;
 
+        /// <summary>
+        /// Indicates that the draw is using the draw parameters on the 3D engine state, rather than inline parameters submitted with the draw command.
+        /// </summary>
+        public bool DrawUsesEngineState;
+
         /// <summary>
         /// Indicates if any of the currently used vertex shaders reads the instance ID.
         /// </summary>
@@ -48,11 +53,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
         /// </summary>
         public bool IsAnyVbInstanced;
 
-        /// <summary>
-        /// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0.
-        /// </summary>
-        public bool HasConstantBufferDrawParameters;
-
         /// <summary>
         /// Primitive topology for the next draw.
         /// </summary>
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index 24a4d58c..2b65b456 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
-- 
cgit v1.2.3-70-g09d2