aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2022-10-16 23:38:58 +0100
committerGitHub <noreply@github.com>2022-10-16 19:38:58 -0300
commit0dbe45ae37a7aea1bf86787a638ddb68df97a50c (patch)
treeced41a7831a8ba175605a9a39e4da33bfd2c1141
parent2b50e52e4815f5dc2306ebfec6b15625ff864839 (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.cs27
-rw-r--r--Ryujinx.Graphics.Vulkan/IndexBufferState.cs7
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineBase.cs4
-rw-r--r--Ryujinx.Graphics.Vulkan/VertexBufferState.cs49
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;
+ }
}
}