mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 00:23: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))
|
||||
{
|
||||
UpdateAndBind(cbs, PipelineBase.UniformSetIndex, DirtyFlags.Uniform, pbp);
|
||||
if (_program.UsePushDescriptors)
|
||||
{
|
||||
UpdateAndBindUniformBufferPd(cbs, pbp);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAndBind(cbs, PipelineBase.UniformSetIndex, pbp);
|
||||
}
|
||||
}
|
||||
|
||||
if (_dirty.HasFlag(DirtyFlags.Storage))
|
||||
{
|
||||
UpdateAndBind(cbs, PipelineBase.StorageSetIndex, DirtyFlags.Storage, pbp);
|
||||
UpdateAndBind(cbs, PipelineBase.StorageSetIndex, pbp);
|
||||
}
|
||||
|
||||
if (_dirty.HasFlag(DirtyFlags.Texture))
|
||||
{
|
||||
UpdateAndBind(cbs, PipelineBase.TextureSetIndex, DirtyFlags.Texture, pbp);
|
||||
UpdateAndBind(cbs, PipelineBase.TextureSetIndex, pbp);
|
||||
}
|
||||
|
||||
if (_dirty.HasFlag(DirtyFlags.Image))
|
||||
{
|
||||
UpdateAndBind(cbs, PipelineBase.ImageSetIndex, DirtyFlags.Image, pbp);
|
||||
UpdateAndBind(cbs, PipelineBase.ImageSetIndex, pbp);
|
||||
}
|
||||
|
||||
_dirty = DirtyFlags.None;
|
||||
|
@ -263,7 +270,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
}
|
||||
|
||||
[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;
|
||||
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);
|
||||
}
|
||||
|
||||
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)]
|
||||
private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc)
|
||||
{
|
||||
|
|
|
@ -22,11 +22,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
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)
|
||||
{
|
||||
_plce[stages] = new PipelineLayoutCacheEntry(gd, device, stages);
|
||||
_plce[stages] = new PipelineLayoutCacheEntry(gd, device, stages, usePd);
|
||||
}
|
||||
|
||||
return _plce[stages];
|
||||
|
|
|
@ -36,9 +36,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
ShaderStageFlags.ShaderStageFragmentBit |
|
||||
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);
|
||||
|
||||
|
@ -92,7 +92,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
{
|
||||
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
||||
PBindings = uLayoutBindings,
|
||||
BindingCount = (uint)uCount
|
||||
BindingCount = (uint)uCount,
|
||||
Flags = usePd ? DescriptorSetLayoutCreateFlags.DescriptorSetLayoutCreatePushDescriptorBitKhr : 0
|
||||
};
|
||||
|
||||
var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
public PipelineLayout PipelineLayout => _plce.PipelineLayout;
|
||||
|
||||
public bool HasMinimalLayout { get; }
|
||||
public bool UsePushDescriptors { get; }
|
||||
|
||||
public uint Stages { get; }
|
||||
|
||||
|
@ -89,11 +90,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
_shaders = internalShaders;
|
||||
|
||||
bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors;
|
||||
|
||||
_plce = isMinimal
|
||||
? gd.PipelineLayoutCache.Create(gd, device, shaders)
|
||||
: gd.PipelineLayoutCache.GetOrCreate(gd, device, stages);
|
||||
: gd.PipelineLayoutCache.GetOrCreate(gd, device, stages, usePd);
|
||||
|
||||
HasMinimalLayout = isMinimal;
|
||||
UsePushDescriptors = usePd;
|
||||
|
||||
Stages = stages;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
public const bool UseFastBufferUpdates = true;
|
||||
public const bool UseGranularBufferTracking = true;
|
||||
public const bool UseSlowSafeBlitOnAmd = true;
|
||||
public const bool UsePushDescriptors = false;
|
||||
|
||||
public const bool ForceD24S8Unsupported = false;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
internal KhrSwapchain SwapchainApi { get; private set; }
|
||||
internal ExtConditionalRendering ConditionalRenderingApi { get; private set; }
|
||||
internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; }
|
||||
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
||||
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
||||
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
||||
internal ExtDebugReport DebugReportApi { get; private set; }
|
||||
|
@ -137,6 +138,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
ExtendedDynamicStateApi = extendedDynamicStateApi;
|
||||
}
|
||||
|
||||
if (Api.TryGetDeviceExtension(_instance, _device, out KhrPushDescriptor pushDescriptorApi))
|
||||
{
|
||||
PushDescriptorApi = pushDescriptorApi;
|
||||
}
|
||||
|
||||
if (Api.TryGetDeviceExtension(_instance, _device, out ExtTransformFeedback transformFeedbackApi))
|
||||
{
|
||||
TransformFeedbackApi = transformFeedbackApi;
|
||||
|
|
|
@ -22,14 +22,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
ExtConditionalRendering.ExtensionName,
|
||||
ExtExtendedDynamicState.ExtensionName,
|
||||
KhrDrawIndirectCount.ExtensionName,
|
||||
KhrPushDescriptor.ExtensionName,
|
||||
"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_index_type_uint8",
|
||||
"VK_EXT_robustness2",
|
||||
"VK_EXT_shader_subgroup_ballot",
|
||||
"VK_EXT_subgroup_size_control",
|
||||
"VK_NV_geometry_shader_passthrough",
|
||||
"VK_EXT_descriptor_indexing" // Enabling this works around an issue with disposed buffer bindings on RADV.
|
||||
"VK_NV_geometry_shader_passthrough"
|
||||
};
|
||||
|
||||
public static string[] RequiredExtensions { get; } = new string[]
|
||||
|
|
Loading…
Reference in a new issue