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 Silk.NET.Vulkan;
using System; using System;
using VkBuffer = Silk.NET.Vulkan.Buffer;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan
{ {
@ -15,17 +16,15 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSets = descriptorSets; _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]; Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[countPerUnit];
for (int j = 0; j < countPerUnit; j++) infos.Fill(new DescriptorBufferInfo()
{ {
infos[j] = new DescriptorBufferInfo() Buffer = dummyBuffer,
{ Range = Vk.WholeSize
Range = Vk.WholeSize });
};
}
UpdateBuffers(setIndex, baseBinding, infos, type); UpdateBuffers(setIndex, baseBinding, infos, type);
} }

View file

@ -45,6 +45,7 @@ namespace Ryujinx.Graphics.Vulkan
private DirtyFlags _dirty; private DirtyFlags _dirty;
private readonly BufferHolder _dummyBuffer;
private readonly TextureView _dummyTexture; private readonly TextureView _dummyTexture;
private readonly SamplerHolder _dummySampler; private readonly SamplerHolder _dummySampler;
@ -62,6 +63,17 @@ namespace Ryujinx.Graphics.Vulkan
_bufferTextures = Array.Empty<BufferView>(); _bufferTextures = Array.Empty<BufferView>();
_bufferImages = 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( _dummyTexture = (TextureView)gd.CreateTexture(new GAL.TextureCreateInfo(
1, 1,
1, 1,
@ -283,13 +295,18 @@ namespace Ryujinx.Graphics.Vulkan
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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; 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. // The spec requires that buffers with null handle have offset as 0 and range as VK_WHOLE_SIZE.
if (info.Buffer.Handle == 0) if (info.Buffer.Handle == 0)
{ {
info.Buffer = dummyBuffer?.Get(cbs).Value ?? default;
info.Offset = 0; info.Offset = 0;
info.Range = Vk.WholeSize; info.Range = Vk.WholeSize;
} }
@ -304,6 +321,8 @@ namespace Ryujinx.Graphics.Vulkan
return; return;
} }
var dummyBuffer = _dummyBuffer?.GetBuffer();
var dsc = _program.GetNewDescriptorSetCollection(_gd, cbs.CommandBufferIndex, setIndex, out var isNew).Get(cbs); var dsc = _program.GetNewDescriptorSetCollection(_gd, cbs.CommandBufferIndex, setIndex, out var isNew).Get(cbs);
if (isNew) if (isNew)
@ -352,7 +371,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++) 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; ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
@ -369,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++) 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; ReadOnlySpan<DescriptorBufferInfo> storageBuffers = _storageBuffers;
@ -461,6 +480,8 @@ namespace Ryujinx.Graphics.Vulkan
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc) private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
{ {
var dummyBuffer = _dummyBuffer?.GetBuffer().Get(cbs).Value ?? default;
uint stages = _program.Stages; uint stages = _program.Stages;
while (stages != 0) while (stages != 0)
@ -470,11 +491,21 @@ namespace Ryujinx.Graphics.Vulkan
if (setIndex == PipelineBase.UniformSetIndex) 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) 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 SupportsConditionalRendering { get; }
public bool SupportsExtendedDynamicState { get; } public bool SupportsExtendedDynamicState { get; }
public bool SupportsNullDescriptors { get; }
public bool SupportsTransformFeedback { get; } public bool SupportsTransformFeedback { get; }
public bool SupportsTransformFeedbackQueries { get; } public bool SupportsTransformFeedbackQueries { get; }
public bool SupportsGeometryShader { get; } public bool SupportsGeometryShader { get; }
@ -16,6 +17,7 @@ namespace Ryujinx.Graphics.Vulkan
public HardwareCapabilities( public HardwareCapabilities(
bool supportsConditionalRendering, bool supportsConditionalRendering,
bool supportsExtendedDynamicState, bool supportsExtendedDynamicState,
bool supportsNullDescriptors,
bool supportsTransformFeedback, bool supportsTransformFeedback,
bool supportsTransformFeedbackQueries, bool supportsTransformFeedbackQueries,
bool supportsGeometryShader, bool supportsGeometryShader,
@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
SupportsConditionalRendering = supportsConditionalRendering; SupportsConditionalRendering = supportsConditionalRendering;
SupportsExtendedDynamicState = supportsExtendedDynamicState; SupportsExtendedDynamicState = supportsExtendedDynamicState;
SupportsNullDescriptors = supportsNullDescriptors;
SupportsTransformFeedback = supportsTransformFeedback; SupportsTransformFeedback = supportsTransformFeedback;
SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries; SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
SupportsGeometryShader = supportsGeometryShader; SupportsGeometryShader = supportsGeometryShader;

View file

@ -195,9 +195,27 @@ namespace Ryujinx.Graphics.Vulkan
Api.GetPhysicalDeviceProperties2(_physicalDevice, &properties2); 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( Capabilities = new HardwareCapabilities(
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName), supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName), supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
featuresRobustness2.NullDescriptor,
supportsTransformFeedback, supportsTransformFeedback,
propertiesTransformFeedback.TransformFeedbackQueries, propertiesTransformFeedback.TransformFeedbackQueries,
supportedFeatures.GeometryShader, supportedFeatures.GeometryShader,
@ -392,7 +410,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
uint driverVersionRaw = properties.DriverVersion; 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) if (properties.VendorID == 0x10DE)
{ {
return $"{(driverVersionRaw >> 22) & 0x3FF}.{(driverVersionRaw >> 14) & 0xFF}.{(driverVersionRaw >> 6) & 0xFF}.{driverVersionRaw & 0x3F}"; return $"{(driverVersionRaw >> 22) & 0x3FF}.{(driverVersionRaw >> 14) & 0xFF}.{(driverVersionRaw >> 6) & 0xFF}.{driverVersionRaw & 0x3F}";