diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index f4408959..8d67d0fd 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/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; /// @@ -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 /// 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;