diff options
author | riperiperi <rhy3756547@hotmail.com> | 2022-10-16 23:38:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-16 19:38:58 -0300 |
commit | 0dbe45ae37a7aea1bf86787a638ddb68df97a50c (patch) | |
tree | ced41a7831a8ba175605a9a39e4da33bfd2c1141 | |
parent | 2b50e52e4815f5dc2306ebfec6b15625ff864839 (diff) |
Fix various issues caused by Vertex/Index buffer conversions (#3762)1.1.304
* Fix various issues caused by #3679
- The arguments for the 0th dummy vertex buffer were incorrect - it was given an offset of 16 rather than a size of 16.
- The wrong size was used when doing `autoBuffer.Get` on a converted vertex buffer.
- The possibility of a vertex buffer being disposed and then rebound can rebindings to find a different buffer where the current range is out of bounds. Avoid binding when out of range to prevent validation errors.
- The above also affects generation of converted buffers, which was a bit more fatal. Conversion functions now attempt to bound input offset/size.
* Fix offset for converted buffer
-rw-r--r-- | Ryujinx.Graphics.Vulkan/BufferHolder.cs | 27 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/IndexBufferState.cs | 7 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VertexBufferState.cs | 49 |
4 files changed, 65 insertions, 22 deletions
diff --git a/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/Ryujinx.Graphics.Vulkan/BufferHolder.cs index 20571253..fb133266 100644 --- a/Ryujinx.Graphics.Vulkan/BufferHolder.cs +++ b/Ryujinx.Graphics.Vulkan/BufferHolder.cs @@ -386,8 +386,25 @@ namespace Ryujinx.Graphics.Vulkan _waitable.WaitForFences(_gd.Api, _device, offset, size); } + private bool BoundToRange(int offset, ref int size) + { + if (offset >= Size) + { + return false; + } + + size = Math.Min(Size - offset, size); + + return true; + } + public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size) { + if (!BoundToRange(offset, ref size)) + { + return null; + } + var key = new I8ToI16CacheKey(_gd); if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder)) @@ -407,6 +424,11 @@ namespace Ryujinx.Graphics.Vulkan public Auto<DisposableBuffer> GetAlignedVertexBuffer(CommandBufferScoped cbs, int offset, int size, int stride, int alignment) { + if (!BoundToRange(offset, ref size)) + { + return null; + } + var key = new AlignedVertexBufferCacheKey(_gd, stride, alignment); if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder)) @@ -428,6 +450,11 @@ namespace Ryujinx.Graphics.Vulkan public Auto<DisposableBuffer> GetBufferTopologyConversion(CommandBufferScoped cbs, int offset, int size, IndexBufferPattern pattern, int indexSize) { + if (!BoundToRange(offset, ref size)) + { + return null; + } + var key = new TopologyConversionCacheKey(_gd, pattern, indexSize); if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder)) diff --git a/Ryujinx.Graphics.Vulkan/IndexBufferState.cs b/Ryujinx.Graphics.Vulkan/IndexBufferState.cs index 1a112d4d..205eab27 100644 --- a/Ryujinx.Graphics.Vulkan/IndexBufferState.cs +++ b/Ryujinx.Graphics.Vulkan/IndexBufferState.cs @@ -49,7 +49,12 @@ namespace Ryujinx.Graphics.Vulkan } else { - autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _); + autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int bufferSize); + + if (_offset >= bufferSize) + { + autoBuffer = null; + } offset = _offset; size = _size; diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 0eb61123..23abde41 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -95,7 +95,7 @@ namespace Ryujinx.Graphics.Vulkan using var emptyVb = gd.BufferManager.Create(gd, EmptyVbSize); emptyVb.SetData(0, new byte[EmptyVbSize]); - _vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, EmptyVbSize, 0); + _vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, 0, EmptyVbSize, 0); _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff); @@ -1243,7 +1243,7 @@ namespace Ryujinx.Graphics.Vulkan _vertexBuffers[i].BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState); - _vertexBuffersDirty &= ~(1u << i); + _vertexBuffersDirty &= ~(1UL << i); } } diff --git a/Ryujinx.Graphics.Vulkan/VertexBufferState.cs b/Ryujinx.Graphics.Vulkan/VertexBufferState.cs index 5710f0b1..661bb774 100644 --- a/Ryujinx.Graphics.Vulkan/VertexBufferState.cs +++ b/Ryujinx.Graphics.Vulkan/VertexBufferState.cs @@ -57,37 +57,48 @@ namespace Ryujinx.Graphics.Vulkan if (gd.NeedsVertexBufferAlignment(AttributeScalarAlignment, out int alignment) && (_stride % alignment) != 0) { autoBuffer = gd.BufferManager.GetAlignedVertexBuffer(cbs, _handle, _offset, _size, _stride, alignment); - int stride = (_stride + (alignment - 1)) & -alignment; - var buffer = autoBuffer.Get(cbs, _offset, _size).Value; - - if (gd.Capabilities.SupportsExtendedDynamicState) - { - gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( - cbs.CommandBuffer, - binding, - 1, - buffer, - 0, - (ulong)(_size / _stride) * (ulong)stride, - (ulong)stride); - } - else + if (autoBuffer != null) { - gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0); + int stride = (_stride + (alignment - 1)) & -alignment; + int newSize = (_size / _stride) * stride; + + var buffer = autoBuffer.Get(cbs, 0, newSize).Value; + + if (gd.Capabilities.SupportsExtendedDynamicState) + { + gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( + cbs.CommandBuffer, + binding, + 1, + buffer, + 0, + (ulong)newSize, + (ulong)stride); + } + else + { + gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0); + } + + _buffer = autoBuffer; } - _buffer = autoBuffer; - state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride; + state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; return; } else { - autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _); + autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size); // The original stride must be reapplied in case it was rewritten. state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; + + if (_offset >= size) + { + autoBuffer = null; + } } } |