[vulkan] Implement push descriptors for compute pipelines (#3666)

Implements push descriptor for compute pipelines along with a bug fix, the increment logic was, offset += sizeof(DescriptorUpdateEntry);
This only advances the byte offset by a single descriptor slot, regardless of the array's size (descriptorCount).Now suppose if a shader utilized an array of descriptors (eg, layout(binding = 0) uniform sampler2D textures[4]) and if this happened to fit within the MaxPushDescriptors limit, the template would consume 4 * sizeof(DescriptorUpdateEntry) bytes, but the offset for the next binding would only advance by 1 slot.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3666
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
This commit is contained in:
wildcard 2026-03-04 22:46:55 +01:00 committed by crueter
parent 9d2341eaea
commit c682306788
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
3 changed files with 26 additions and 10 deletions

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -61,7 +64,8 @@ public:
.pDescriptorUpdateEntries = entries.data(), .pDescriptorUpdateEntries = entries.data(),
.templateType = type, .templateType = type,
.descriptorSetLayout = descriptor_set_layout, .descriptorSetLayout = descriptor_set_layout,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .pipelineBindPoint =
is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
.pipelineLayout = pipeline_layout, .pipelineLayout = pipeline_layout,
.set = 0, .set = 0,
}); });
@ -122,7 +126,7 @@ private:
}); });
++binding; ++binding;
num_descriptors += descriptors[i].count; num_descriptors += descriptors[i].count;
offset += sizeof(DescriptorUpdateEntry); offset += sizeof(DescriptorUpdateEntry) * descriptors[i].count;
} }
} }

View file

@ -50,11 +50,14 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
DescriptorLayoutBuilder builder{device}; DescriptorLayoutBuilder builder{device};
builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT);
descriptor_set_layout = builder.CreateDescriptorSetLayout(false); uses_push_descriptor = builder.CanUsePushDescriptor();
descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor);
pipeline_layout = builder.CreatePipelineLayout(*descriptor_set_layout); pipeline_layout = builder.CreatePipelineLayout(*descriptor_set_layout);
descriptor_update_template = descriptor_update_template =
builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout, false); builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout, uses_push_descriptor);
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info); if (!uses_push_descriptor) {
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info);
}
const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
.pNext = nullptr, .pNext = nullptr,
@ -241,11 +244,16 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
RESCALING_LAYOUT_WORDS_OFFSET, sizeof(rescaling_data), RESCALING_LAYOUT_WORDS_OFFSET, sizeof(rescaling_data),
rescaling_data.data()); rescaling_data.data());
} }
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; if (uses_push_descriptor) {
const vk::Device& dev{device.GetLogical()}; cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); 0, descriptor_data);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, } else {
descriptor_set, nullptr); const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
const vk::Device& dev{device.GetLogical()};
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
descriptor_set, nullptr);
}
}); });
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -55,6 +58,7 @@ private:
vk::ShaderModule spv_module; vk::ShaderModule spv_module;
vk::DescriptorSetLayout descriptor_set_layout; vk::DescriptorSetLayout descriptor_set_layout;
bool uses_push_descriptor{false};
DescriptorAllocator descriptor_allocator; DescriptorAllocator descriptor_allocator;
vk::PipelineLayout pipeline_layout; vk::PipelineLayout pipeline_layout;
vk::DescriptorUpdateTemplate descriptor_update_template; vk::DescriptorUpdateTemplate descriptor_update_template;