mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-22 09:03:36 +00:00
Use push descriptors for uniform buffer updates (disabled for now)
This commit is contained in:
parent
f2b1cfe10c
commit
db4e7d28ea
8 changed files with 105 additions and 14 deletions
|
@ -223,22 +223,29 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Uniform))
|
if (_dirty.HasFlag(DirtyFlags.Uniform))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.UniformSetIndex, DirtyFlags.Uniform, pbp);
|
if (_program.UsePushDescriptors)
|
||||||
|
{
|
||||||
|
UpdateAndBindUniformBufferPd(cbs, pbp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateAndBind(cbs, PipelineBase.UniformSetIndex, pbp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Storage))
|
if (_dirty.HasFlag(DirtyFlags.Storage))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.StorageSetIndex, DirtyFlags.Storage, pbp);
|
UpdateAndBind(cbs, PipelineBase.StorageSetIndex, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Texture))
|
if (_dirty.HasFlag(DirtyFlags.Texture))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.TextureSetIndex, DirtyFlags.Texture, pbp);
|
UpdateAndBind(cbs, PipelineBase.TextureSetIndex, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Image))
|
if (_dirty.HasFlag(DirtyFlags.Image))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.ImageSetIndex, DirtyFlags.Image, pbp);
|
UpdateAndBind(cbs, PipelineBase.ImageSetIndex, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = DirtyFlags.None;
|
_dirty = DirtyFlags.None;
|
||||||
|
@ -263,7 +270,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void UpdateAndBind(CommandBufferScoped cbs, int setIndex, DirtyFlags flag, PipelineBindPoint pbp)
|
private void UpdateAndBind(CommandBufferScoped cbs, int setIndex, PipelineBindPoint pbp)
|
||||||
{
|
{
|
||||||
var program = _program;
|
var program = _program;
|
||||||
int stagesCount = program.Bindings[setIndex].Length;
|
int stagesCount = program.Bindings[setIndex].Length;
|
||||||
|
@ -402,6 +409,77 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe void UpdateBuffers(
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
PipelineBindPoint pbp,
|
||||||
|
int baseBinding,
|
||||||
|
ReadOnlySpan<DescriptorBufferInfo> bufferInfo,
|
||||||
|
DescriptorType type)
|
||||||
|
{
|
||||||
|
if (bufferInfo.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed (DescriptorBufferInfo* pBufferInfo = bufferInfo)
|
||||||
|
{
|
||||||
|
var writeDescriptorSet = new WriteDescriptorSet
|
||||||
|
{
|
||||||
|
SType = StructureType.WriteDescriptorSet,
|
||||||
|
DstBinding = (uint)baseBinding,
|
||||||
|
DescriptorType = type,
|
||||||
|
DescriptorCount = (uint)bufferInfo.Length,
|
||||||
|
PBufferInfo = pBufferInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
_gd.PushDescriptorApi.CmdPushDescriptorSet(cbs.CommandBuffer, pbp, _program.PipelineLayout, 0, 1, &writeDescriptorSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs, PipelineBindPoint pbp)
|
||||||
|
{
|
||||||
|
var dummyBuffer = _dummyBuffer?.GetBuffer();
|
||||||
|
int stagesCount = _program.Bindings[PipelineBase.UniformSetIndex].Length;
|
||||||
|
|
||||||
|
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer);
|
||||||
|
|
||||||
|
for (int stageIndex = 0; stageIndex < stagesCount; stageIndex++)
|
||||||
|
{
|
||||||
|
var stageBindings = _program.Bindings[PipelineBase.UniformSetIndex][stageIndex];
|
||||||
|
int bindingsCount = stageBindings.Length;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
for (int bindingIndex = 0; bindingIndex < bindingsCount; bindingIndex += count)
|
||||||
|
{
|
||||||
|
int binding = stageBindings[bindingIndex];
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
while (bindingIndex + count < bindingsCount && stageBindings[bindingIndex + count] == binding + count)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlySpan<DescriptorBufferInfo> uniformBuffers = _uniformBuffers;
|
||||||
|
UpdateBuffers(cbs, pbp, binding, uniformBuffers.Slice(binding, count), DescriptorType.UniformBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
|
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,11 +22,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return plce;
|
return plce;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PipelineLayoutCacheEntry GetOrCreate(VulkanGraphicsDevice gd, Device device, uint stages)
|
public PipelineLayoutCacheEntry GetOrCreate(VulkanGraphicsDevice gd, Device device, uint stages, bool usePd)
|
||||||
{
|
{
|
||||||
if (_plce[stages] == null)
|
if (_plce[stages] == null)
|
||||||
{
|
{
|
||||||
_plce[stages] = new PipelineLayoutCacheEntry(gd, device, stages);
|
_plce[stages] = new PipelineLayoutCacheEntry(gd, device, stages, usePd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _plce[stages];
|
return _plce[stages];
|
||||||
|
|
|
@ -36,9 +36,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
_dsCacheCursor = new int[PipelineBase.DescriptorSetLayouts];
|
_dsCacheCursor = new int[PipelineBase.DescriptorSetLayouts];
|
||||||
}
|
}
|
||||||
|
|
||||||
public PipelineLayoutCacheEntry(VulkanGraphicsDevice gd, Device device, uint stages) : this(gd, device)
|
public PipelineLayoutCacheEntry(VulkanGraphicsDevice gd, Device device, uint stages, bool usePd) : this(gd, device)
|
||||||
{
|
{
|
||||||
DescriptorSetLayouts = PipelineLayoutFactory.Create(gd, device, stages, out var pipelineLayout);
|
DescriptorSetLayouts = PipelineLayoutFactory.Create(gd, device, stages, usePd, out var pipelineLayout);
|
||||||
PipelineLayout = pipelineLayout;
|
PipelineLayout = pipelineLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
ShaderStageFlags.ShaderStageFragmentBit |
|
ShaderStageFlags.ShaderStageFragmentBit |
|
||||||
ShaderStageFlags.ShaderStageComputeBit;
|
ShaderStageFlags.ShaderStageComputeBit;
|
||||||
|
|
||||||
public static unsafe DescriptorSetLayout[] Create(VulkanGraphicsDevice gd, Device device, uint stages, out PipelineLayout layout)
|
public static unsafe DescriptorSetLayout[] Create(VulkanGraphicsDevice gd, Device device, uint stages, bool usePd, out PipelineLayout layout)
|
||||||
{
|
{
|
||||||
int stagesCount = BitOperations.PopCount(stages);
|
int stagesCount = BitOperations.PopCount(stages);
|
||||||
|
|
||||||
|
@ -92,7 +92,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
||||||
PBindings = uLayoutBindings,
|
PBindings = uLayoutBindings,
|
||||||
BindingCount = (uint)uCount
|
BindingCount = (uint)uCount,
|
||||||
|
Flags = usePd ? DescriptorSetLayoutCreateFlags.DescriptorSetLayoutCreatePushDescriptorBitKhr : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
|
var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
public PipelineLayout PipelineLayout => _plce.PipelineLayout;
|
public PipelineLayout PipelineLayout => _plce.PipelineLayout;
|
||||||
|
|
||||||
public bool HasMinimalLayout { get; }
|
public bool HasMinimalLayout { get; }
|
||||||
|
public bool UsePushDescriptors { get; }
|
||||||
|
|
||||||
public uint Stages { get; }
|
public uint Stages { get; }
|
||||||
|
|
||||||
|
@ -89,11 +90,14 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
_shaders = internalShaders;
|
_shaders = internalShaders;
|
||||||
|
|
||||||
|
bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors;
|
||||||
|
|
||||||
_plce = isMinimal
|
_plce = isMinimal
|
||||||
? gd.PipelineLayoutCache.Create(gd, device, shaders)
|
? gd.PipelineLayoutCache.Create(gd, device, shaders)
|
||||||
: gd.PipelineLayoutCache.GetOrCreate(gd, device, stages);
|
: gd.PipelineLayoutCache.GetOrCreate(gd, device, stages, usePd);
|
||||||
|
|
||||||
HasMinimalLayout = isMinimal;
|
HasMinimalLayout = isMinimal;
|
||||||
|
UsePushDescriptors = usePd;
|
||||||
|
|
||||||
Stages = stages;
|
Stages = stages;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
public const bool UseFastBufferUpdates = true;
|
public const bool UseFastBufferUpdates = true;
|
||||||
public const bool UseGranularBufferTracking = true;
|
public const bool UseGranularBufferTracking = true;
|
||||||
public const bool UseSlowSafeBlitOnAmd = true;
|
public const bool UseSlowSafeBlitOnAmd = true;
|
||||||
|
public const bool UsePushDescriptors = false;
|
||||||
|
|
||||||
public const bool ForceD24S8Unsupported = false;
|
public const bool ForceD24S8Unsupported = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
internal KhrSwapchain SwapchainApi { get; private set; }
|
internal KhrSwapchain SwapchainApi { get; private set; }
|
||||||
internal ExtConditionalRendering ConditionalRenderingApi { get; private set; }
|
internal ExtConditionalRendering ConditionalRenderingApi { get; private set; }
|
||||||
internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; }
|
internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; }
|
||||||
|
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
||||||
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
||||||
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
||||||
internal ExtDebugReport DebugReportApi { get; private set; }
|
internal ExtDebugReport DebugReportApi { get; private set; }
|
||||||
|
@ -137,6 +138,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
ExtendedDynamicStateApi = extendedDynamicStateApi;
|
ExtendedDynamicStateApi = extendedDynamicStateApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Api.TryGetDeviceExtension(_instance, _device, out KhrPushDescriptor pushDescriptorApi))
|
||||||
|
{
|
||||||
|
PushDescriptorApi = pushDescriptorApi;
|
||||||
|
}
|
||||||
|
|
||||||
if (Api.TryGetDeviceExtension(_instance, _device, out ExtTransformFeedback transformFeedbackApi))
|
if (Api.TryGetDeviceExtension(_instance, _device, out ExtTransformFeedback transformFeedbackApi))
|
||||||
{
|
{
|
||||||
TransformFeedbackApi = transformFeedbackApi;
|
TransformFeedbackApi = transformFeedbackApi;
|
||||||
|
|
|
@ -22,14 +22,15 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
ExtConditionalRendering.ExtensionName,
|
ExtConditionalRendering.ExtensionName,
|
||||||
ExtExtendedDynamicState.ExtensionName,
|
ExtExtendedDynamicState.ExtensionName,
|
||||||
KhrDrawIndirectCount.ExtensionName,
|
KhrDrawIndirectCount.ExtensionName,
|
||||||
|
KhrPushDescriptor.ExtensionName,
|
||||||
"VK_EXT_custom_border_color",
|
"VK_EXT_custom_border_color",
|
||||||
|
"VK_EXT_descriptor_indexing", // Enabling this works around an issue with disposed buffer bindings on RADV.
|
||||||
"VK_EXT_fragment_shader_interlock",
|
"VK_EXT_fragment_shader_interlock",
|
||||||
"VK_EXT_index_type_uint8",
|
"VK_EXT_index_type_uint8",
|
||||||
"VK_EXT_robustness2",
|
"VK_EXT_robustness2",
|
||||||
"VK_EXT_shader_subgroup_ballot",
|
"VK_EXT_shader_subgroup_ballot",
|
||||||
"VK_EXT_subgroup_size_control",
|
"VK_EXT_subgroup_size_control",
|
||||||
"VK_NV_geometry_shader_passthrough",
|
"VK_NV_geometry_shader_passthrough"
|
||||||
"VK_EXT_descriptor_indexing" // Enabling this works around an issue with disposed buffer bindings on RADV.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string[] RequiredExtensions { get; } = new string[]
|
public static string[] RequiredExtensions { get; } = new string[]
|
||||||
|
|
Loading…
Reference in a new issue