Push descriptor support check, buffer redundancy checks

Should make push descriptors faster, needs more testing though.
This commit is contained in:
riperiperi 2022-06-17 23:23:43 +01:00
parent db4e7d28ea
commit cd3ad0a6ab
4 changed files with 92 additions and 19 deletions

View file

@ -30,6 +30,10 @@ namespace Ryujinx.Graphics.Vulkan
private BufferView[] _bufferTextures;
private BufferView[] _bufferImages;
private bool[] _uniformSet;
private bool[] _storageSet;
private Silk.NET.Vulkan.Buffer _cachedSupportBuffer;
[Flags]
private enum DirtyFlags
{
@ -68,6 +72,9 @@ namespace Ryujinx.Graphics.Vulkan
_bufferTextures = new BufferView[Constants.MaxTextureBindings];
_bufferImages = new BufferView[Constants.MaxImageBindings];
_uniformSet = new bool[Constants.MaxUniformBufferBindings];
_storageSet = new bool[Constants.MaxStorageBufferBindings];
if (gd.Capabilities.SupportsNullDescriptors)
{
// If null descriptors are supported, we can pass null as the handle.
@ -147,14 +154,25 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < buffers.Length; i++)
{
var buffer = buffers[i];
int index = first + i;
_storageBufferRefs[first + i] = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false);
Auto<DisposableBuffer> vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false);
ref Auto<DisposableBuffer> currentVkBuffer = ref _storageBufferRefs[index];
_storageBuffers[first + i] = new DescriptorBufferInfo()
DescriptorBufferInfo info = new DescriptorBufferInfo()
{
Offset = (ulong)buffer.Offset,
Range = (ulong)buffer.Size
};
ref DescriptorBufferInfo currentInfo = ref _storageBuffers[index];
if (vkBuffer != currentVkBuffer || currentInfo.Offset != info.Offset || currentInfo.Range != info.Range)
{
_storageSet[index] = false;
currentInfo = info;
currentVkBuffer = vkBuffer;
}
}
SignalDirty(DirtyFlags.Storage);
@ -194,14 +212,25 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < buffers.Length; i++)
{
var buffer = buffers[i];
int index = first + i;
_uniformBufferRefs[first + i] = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false);
Auto<DisposableBuffer> vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false);
ref Auto<DisposableBuffer> currentVkBuffer = ref _uniformBufferRefs[index];
_uniformBuffers[first + i] = new DescriptorBufferInfo()
DescriptorBufferInfo info = new DescriptorBufferInfo()
{
Offset = (ulong)buffer.Offset,
Range = (ulong)buffer.Size
};
ref DescriptorBufferInfo currentInfo = ref _uniformBuffers[index];
if (vkBuffer != currentVkBuffer || currentInfo.Offset != info.Offset || currentInfo.Range != info.Range)
{
_uniformSet[index] = false;
currentInfo = info;
currentVkBuffer = vkBuffer;
}
}
SignalDirty(DirtyFlags.Uniform);
@ -294,11 +323,17 @@ namespace Ryujinx.Graphics.Vulkan
{
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
if (!_uniformSet[0])
{
_cachedSupportBuffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value;
_uniformSet[0] = true;
}
uniformBuffer[0] = new DescriptorBufferInfo()
{
Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value
Buffer = _cachedSupportBuffer
};
dsc.UpdateBuffers(0, 0, uniformBuffer, DescriptorType.UniformBuffer);
@ -325,7 +360,14 @@ namespace Ryujinx.Graphics.Vulkan
{
for (int i = 0; i < count; i++)
{
UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer);
int index = binding + i;
if (!_uniformSet[index])
{
UpdateBuffer(cbs, ref _uniformBuffers[index], _uniformBufferRefs[index], dummyBuffer);
_uniformSet[index] = true;
}
}
ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
@ -335,7 +377,14 @@ namespace Ryujinx.Graphics.Vulkan
{
for (int i = 0; i < count; i++)
{
UpdateBuffer(cbs, ref _storageBuffers[binding + i], _storageBufferRefs[binding + i], dummyBuffer);
int index = binding + i;
if (!_storageSet[index])
{
UpdateBuffer(cbs, ref _storageBuffers[index], _storageBufferRefs[index], dummyBuffer);
_storageSet[index] = true;
}
}
ReadOnlySpan<DescriptorBufferInfo> storageBuffers = _storageBuffers;
@ -442,16 +491,21 @@ namespace Ryujinx.Graphics.Vulkan
var dummyBuffer = _dummyBuffer?.GetBuffer();
int stagesCount = _program.Bindings[PipelineBase.UniformSetIndex].Length;
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
uniformBuffer[0] = new DescriptorBufferInfo()
if (!_uniformSet[0])
{
Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value
};
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer);
uniformBuffer[0] = new DescriptorBufferInfo()
{
Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value
};
_uniformSet[0] = true;
UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer);
}
for (int stageIndex = 0; stageIndex < stagesCount; stageIndex++)
{
@ -469,13 +523,25 @@ namespace Ryujinx.Graphics.Vulkan
count++;
}
bool doUpdate = false;
for (int i = 0; i < count; i++)
{
UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer);
int index = binding + i;
if (!_uniformSet[index])
{
UpdateBuffer(cbs, ref _uniformBuffers[index], _uniformBufferRefs[index], dummyBuffer);
_uniformSet[index] = true;
doUpdate = true;
}
}
ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
UpdateBuffers(cbs, pbp, binding, uniformBuffers.Slice(binding, count), DescriptorType.UniformBuffer);
if (doUpdate)
{
ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
UpdateBuffers(cbs, pbp, binding, uniformBuffers.Slice(binding, count), DescriptorType.UniformBuffer);
}
}
}
}
@ -516,6 +582,9 @@ namespace Ryujinx.Graphics.Vulkan
public void SignalCommandBufferChange()
{
_dirty = DirtyFlags.All;
Array.Clear(_uniformSet);
Array.Clear(_storageSet);
}
protected virtual void Dispose(bool disposing)

View file

@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsExtendedDynamicState;
public readonly bool SupportsMultiView;
public readonly bool SupportsNullDescriptors;
public readonly bool SupportsPushDescriptors;
public readonly bool SupportsTransformFeedback;
public readonly bool SupportsTransformFeedbackQueries;
public readonly bool SupportsGeometryShader;
@ -20,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsExtendedDynamicState,
bool supportsMultiView,
bool supportsNullDescriptors,
bool supportsPushDescriptors,
bool supportsTransformFeedback,
bool supportsTransformFeedbackQueries,
bool supportsGeometryShader,
@ -31,6 +33,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsExtendedDynamicState = supportsExtendedDynamicState;
SupportsMultiView = supportsMultiView;
SupportsNullDescriptors = supportsNullDescriptors;
SupportsPushDescriptors = supportsPushDescriptors;
SupportsTransformFeedback = supportsTransformFeedback;
SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
SupportsGeometryShader = supportsGeometryShader;

View file

@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
_shaders = internalShaders;
bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors;
bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors;
_plce = isMinimal
? gd.PipelineLayoutCache.Create(gd, device, shaders)

View file

@ -212,6 +212,7 @@ namespace Ryujinx.Graphics.Vulkan
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
features2.Features.MultiViewport,
featuresRobustness2.NullDescriptor,
supportedExtensions.Contains(KhrPushDescriptor.ExtensionName),
supportsTransformFeedback,
propertiesTransformFeedback.TransformFeedbackQueries,
supportedFeatures.GeometryShader,