Ver Fonte

Calculate vertex buffer size from index buffer type (#3253)

* Calculate vertex buffer size from index buffer type

* We also need to update the size if first vertex changes
gdkchan há 4 anos atrás
pai
commit
952f6f8a65
1 ficheiros alterados com 31 adições e 0 exclusões
  1. 31 0
      Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs

+ 31 - 0
Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs

@@ -35,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
         private byte _vsClipDistancesWritten;
 
         private bool _prevDrawIndexed;
+        private IndexType _prevIndexType;
+        private uint _prevFirstVertex;
         private bool _prevTfEnable;
 
         /// <summary>
@@ -214,6 +216,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
                 _prevDrawIndexed = _drawState.DrawIndexed;
             }
 
+            // In some cases, the index type is also used to guess the
+            // vertex buffer size, so we must update it if the type changed too.
+            if (_drawState.DrawIndexed &&
+                (_prevIndexType != _state.State.IndexBufferState.Type ||
+                 _prevFirstVertex != _state.State.FirstVertex))
+            {
+                _updateTracker.ForceDirty(VertexBufferStateIndex);
+                _prevIndexType = _state.State.IndexBufferState.Type;
+                _prevFirstVertex = _state.State.FirstVertex;
+            }
+
             bool tfEnable = _state.State.TfEnable;
 
             if (!tfEnable && _prevTfEnable)
@@ -867,6 +880,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
         /// </summary>
         private void UpdateVertexBufferState()
         {
+            IndexType indexType = _state.State.IndexBufferState.Type;
+            bool indexTypeSmall = indexType == IndexType.UByte || indexType == IndexType.UShort;
+
             _drawState.IsAnyVbInstanced = false;
 
             for (int index = 0; index < Constants.TotalVertexBuffers; index++)
@@ -898,12 +914,27 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
                 {
                     // This size may be (much) larger than the real vertex buffer size.
                     // Avoid calculating it this way, unless we don't have any other option.
+
                     size = endAddress.Pack() - address + 1;
+
+                    if (stride > 0 && indexTypeSmall)
+                    {
+                        // If the index type is a small integer type, then we might be still able
+                        // to reduce the vertex buffer size based on the maximum possible index value.
+
+                        ulong maxVertexBufferSize = indexType == IndexType.UByte ? 0x100UL : 0x10000UL;
+
+                        maxVertexBufferSize += _state.State.FirstVertex;
+                        maxVertexBufferSize *= (uint)stride;
+
+                        size = Math.Min(size, maxVertexBufferSize);
+                    }
                 }
                 else
                 {
                     // For non-indexed draws, we can guess the size from the vertex count
                     // and stride.
+
                     int firstInstance = (int)_state.State.FirstInstance;
 
                     var drawState = _state.State.VertexBufferDrawState;