Do not require null descriptors support

This commit is contained in:
gdk 2022-05-24 19:49:48 -03:00 committed by riperiperi
parent c832f55618
commit 74a8f37f8d
4 changed files with 64 additions and 13 deletions

View file

@ -1,5 +1,6 @@
using Silk.NET.Vulkan;
using System;
using VkBuffer = Silk.NET.Vulkan.Buffer;
namespace Ryujinx.Graphics.Vulkan
{
@ -15,17 +16,15 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSets = descriptorSets;
}
public void InitializeBuffers(int setIndex, int baseBinding, int countPerUnit, DescriptorType type)
public void InitializeBuffers(int setIndex, int baseBinding, int countPerUnit, DescriptorType type, VkBuffer dummyBuffer)
{
Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[countPerUnit];
for (int j = 0; j < countPerUnit; j++)
infos.Fill(new DescriptorBufferInfo()
{
infos[j] = new DescriptorBufferInfo()
{
Range = Vk.WholeSize
};
}
Buffer = dummyBuffer,
Range = Vk.WholeSize
});
UpdateBuffers(setIndex, baseBinding, infos, type);
}

View file

@ -45,6 +45,7 @@ namespace Ryujinx.Graphics.Vulkan
private DirtyFlags _dirty;
private readonly BufferHolder _dummyBuffer;
private readonly TextureView _dummyTexture;
private readonly SamplerHolder _dummySampler;
@ -62,6 +63,17 @@ namespace Ryujinx.Graphics.Vulkan
_bufferTextures = Array.Empty<BufferView>();
_bufferImages = Array.Empty<BufferView>();
if (gd.Capabilities.SupportsNullDescriptors)
{
// If null descriptors are supported, we can pass null as the handle.
_dummyBuffer = null;
}
else
{
// If null descriptors are not supported, we need to pass the handle of a dummy buffer on unused bindings.
_dummyBuffer = gd.BufferManager.Create(gd, 0x10000, forConditionalRendering: false, deviceLocal: true);
}
_dummyTexture = (TextureView)gd.CreateTexture(new GAL.TextureCreateInfo(
1,
1,
@ -283,13 +295,18 @@ namespace Ryujinx.Graphics.Vulkan
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void UpdateBuffer(CommandBufferScoped cbs, ref DescriptorBufferInfo info, Auto<DisposableBuffer> buffer)
private static void UpdateBuffer(
CommandBufferScoped cbs,
ref DescriptorBufferInfo info,
Auto<DisposableBuffer> buffer,
Auto<DisposableBuffer> dummyBuffer)
{
info.Buffer = buffer?.Get(cbs, (int)info.Offset, (int)info.Range).Value ?? default;
// The spec requires that buffers with null handle have offset as 0 and range as VK_WHOLE_SIZE.
if (info.Buffer.Handle == 0)
{
info.Buffer = dummyBuffer?.Get(cbs).Value ?? default;
info.Offset = 0;
info.Range = Vk.WholeSize;
}
@ -304,6 +321,8 @@ namespace Ryujinx.Graphics.Vulkan
return;
}
var dummyBuffer = _dummyBuffer?.GetBuffer();
var dsc = _program.GetNewDescriptorSetCollection(_gd, cbs.CommandBufferIndex, setIndex, out var isNew).Get(cbs);
if (isNew)
@ -352,7 +371,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++)
{
UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i]);
UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer);
}
ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
@ -369,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++)
{
UpdateBuffer(cbs, ref _storageBuffers[binding + i], _storageBufferRefs[binding + i]);
UpdateBuffer(cbs, ref _storageBuffers[binding + i], _storageBufferRefs[binding + i], dummyBuffer);
}
ReadOnlySpan<DescriptorBufferInfo> storageBuffers = _storageBuffers;
@ -461,6 +480,8 @@ namespace Ryujinx.Graphics.Vulkan
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
{
var dummyBuffer = _dummyBuffer?.GetBuffer().Get(cbs).Value ?? default;
uint stages = _program.Stages;
while (stages != 0)
@ -470,11 +491,21 @@ namespace Ryujinx.Graphics.Vulkan
if (setIndex == PipelineBase.UniformSetIndex)
{
dsc.InitializeBuffers(0, 1 + stage * Constants.MaxUniformBuffersPerStage, Constants.MaxUniformBuffersPerStage, DescriptorType.UniformBuffer);
dsc.InitializeBuffers(
0,
1 + stage * Constants.MaxUniformBuffersPerStage,
Constants.MaxUniformBuffersPerStage,
DescriptorType.UniformBuffer,
dummyBuffer);
}
else if (setIndex == PipelineBase.StorageSetIndex)
{
dsc.InitializeBuffers(0, stage * Constants.MaxStorageBuffersPerStage, Constants.MaxStorageBuffersPerStage, DescriptorType.StorageBuffer);
dsc.InitializeBuffers(
0,
stage * Constants.MaxStorageBuffersPerStage,
Constants.MaxStorageBuffersPerStage,
DescriptorType.StorageBuffer,
dummyBuffer);
}
}
}

View file

@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Vulkan
{
public bool SupportsConditionalRendering { get; }
public bool SupportsExtendedDynamicState { get; }
public bool SupportsNullDescriptors { get; }
public bool SupportsTransformFeedback { get; }
public bool SupportsTransformFeedbackQueries { get; }
public bool SupportsGeometryShader { get; }
@ -16,6 +17,7 @@ namespace Ryujinx.Graphics.Vulkan
public HardwareCapabilities(
bool supportsConditionalRendering,
bool supportsExtendedDynamicState,
bool supportsNullDescriptors,
bool supportsTransformFeedback,
bool supportsTransformFeedbackQueries,
bool supportsGeometryShader,
@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
{
SupportsConditionalRendering = supportsConditionalRendering;
SupportsExtendedDynamicState = supportsExtendedDynamicState;
SupportsNullDescriptors = supportsNullDescriptors;
SupportsTransformFeedback = supportsTransformFeedback;
SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
SupportsGeometryShader = supportsGeometryShader;

View file

@ -195,9 +195,27 @@ namespace Ryujinx.Graphics.Vulkan
Api.GetPhysicalDeviceProperties2(_physicalDevice, &properties2);
PhysicalDeviceFeatures2 features2 = new PhysicalDeviceFeatures2()
{
SType = StructureType.PhysicalDeviceFeatures2
};
PhysicalDeviceRobustness2FeaturesEXT featuresRobustness2 = new PhysicalDeviceRobustness2FeaturesEXT()
{
SType = StructureType.PhysicalDeviceRobustness2FeaturesExt
};
if (supportedExtensions.Contains("VK_EXT_robustness2"))
{
features2.PNext = &featuresRobustness2;
}
Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2);
Capabilities = new HardwareCapabilities(
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
featuresRobustness2.NullDescriptor,
supportsTransformFeedback,
propertiesTransformFeedback.TransformFeedbackQueries,
supportedFeatures.GeometryShader,
@ -392,7 +410,7 @@ namespace Ryujinx.Graphics.Vulkan
{
uint driverVersionRaw = properties.DriverVersion;
// NVIDIA differ from the standard here and use a different format.
// NVIDIA differ from the standard here and uses a different format.
if (properties.VendorID == 0x10DE)
{
return $"{(driverVersionRaw >> 22) & 0x3FF}.{(driverVersionRaw >> 14) & 0xFF}.{(driverVersionRaw >> 6) & 0xFF}.{driverVersionRaw & 0x3F}";