Skip to content

Commit

Permalink
Use variableDescriptorCount to avoid the pipeline recreation.
Browse files Browse the repository at this point in the history
Instead of create the graphics pipelines with fixed amount of texture descriptor sets, use variable descriptor count to create pipelines only once and only re-allocate the descriptor set. This can make the asset loading time faster.
  • Loading branch information
stripe2933 committed Jan 21, 2025
1 parent 1d8da85 commit 9ef3682
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 35 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ The extensions and feature used in this application are quite common in the mode
- `bufferDeviceAddress`
- `descriptorIndexing`
- `descriptorBindingSampledImageUpdateAfterBind`
- `descriptorBindingVariableDescriptorCount`
- `runtimeDescriptorArray`
- `storageBuffer8BitAccess`
- `uniformAndStorageBuffer8BitAccess`
Expand Down
1 change: 1 addition & 0 deletions impl/vulkan/Gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ auto vk_gltf_viewer::vulkan::Gpu::createDevice() -> vk::raii::Device {
.setBufferDeviceAddress(true)
.setDescriptorIndexing(true)
.setDescriptorBindingSampledImageUpdateAfterBind(true)
.setDescriptorBindingVariableDescriptorCount(true)
.setRuntimeDescriptorArray(true)
.setStorageBuffer8BitAccess(true)
.setUniformAndStorageBuffer8BitAccess(true)
Expand Down
46 changes: 17 additions & 29 deletions interface/vulkan/SharedData.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace vk_gltf_viewer::vulkan {
SingleTexelSampler singleTexelSampler { gpu.device };

// Descriptor set layouts.
dsl::Asset assetDescriptorSetLayout { gpu.device, 1 }; // TODO: set proper initial texture count.
dsl::Asset assetDescriptorSetLayout { gpu.device };
dsl::ImageBasedLighting imageBasedLightingDescriptorSetLayout { gpu.device, cubemapSampler, brdfLutSampler };
dsl::Scene sceneDescriptorSetLayout { gpu.device };
dsl::Skybox skyboxDescriptorSetLayout { gpu.device, cubemapSampler };
Expand Down Expand Up @@ -73,7 +73,6 @@ namespace vk_gltf_viewer::vulkan {
std::variant<ag::Swapchain, std::reference_wrapper<ag::Swapchain>> imGuiSwapchainAttachmentGroup = getImGuiSwapchainAttachmentGroup();

// Descriptor pools.
vk::raii::DescriptorPool textureDescriptorPool = createTextureDescriptorPool();
vk::raii::DescriptorPool descriptorPool = createDescriptorPool();

// Descriptor sets.
Expand All @@ -86,9 +85,6 @@ namespace vk_gltf_viewer::vulkan {
: gpu { gpu }
, swapchainExtent { swapchainExtent }
, swapchainImages { swapchainImages } {
std::tie(assetDescriptorSet)
= vku::allocateDescriptorSets(*gpu.device, *textureDescriptorPool, std::tie(
assetDescriptorSetLayout));
std::tie(sceneDescriptorSet, imageBasedLightingDescriptorSet, skyboxDescriptorSet)
= vku::allocateDescriptorSets(*gpu.device, *descriptorPool, std::tie(
sceneDescriptorSetLayout,
Expand Down Expand Up @@ -152,25 +148,16 @@ namespace vk_gltf_viewer::vulkan {
}

void updateTextureCount(std::uint32_t textureCount) {
if (assetDescriptorSetLayout.descriptorCounts[2] == textureCount) {
// If texture count is same, descriptor set layouts, pipeline layouts and pipelines doesn't have to be recreated.
return;
}

// Following pipelines are dependent to the assetDescriptorSetLayout.
depthRenderer.reset();
maskDepthPipelines.clear();
jumpFloodSeedRenderer.reset();
maskJumpFloodSeedPipelines.clear();
primitivePipelines.clear();
unlitPrimitivePipelines.clear();

assetDescriptorSetLayout = { gpu.device, textureCount };
primitivePipelineLayout = { gpu.device, std::tie(imageBasedLightingDescriptorSetLayout, assetDescriptorSetLayout, sceneDescriptorSetLayout) };
primitiveNoShadingPipelineLayout = { gpu.device, std::tie(assetDescriptorSetLayout, sceneDescriptorSetLayout) };

textureDescriptorPool = createTextureDescriptorPool();
std::tie(assetDescriptorSet) = vku::allocateDescriptorSets(*gpu.device, *textureDescriptorPool, std::tie(assetDescriptorSetLayout));
(*gpu.device).freeDescriptorSets(*descriptorPool, assetDescriptorSet);
assetDescriptorSet = decltype(assetDescriptorSet) { vku::unsafe, (*gpu.device).allocateDescriptorSets(vk::StructureChain {
vk::DescriptorSetAllocateInfo {
*descriptorPool,
*assetDescriptorSetLayout,
},
vk::DescriptorSetVariableDescriptorCountAllocateInfo {
vk::ArrayProxyNoTemporaries<const std::uint32_t> { textureCount },
}
}.get())[0] };
}

private:
Expand All @@ -195,12 +182,13 @@ namespace vk_gltf_viewer::vulkan {
}
}

[[nodiscard]] auto createTextureDescriptorPool() const -> vk::raii::DescriptorPool {
return { gpu.device, getPoolSizes(assetDescriptorSetLayout).getDescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind) };
}

[[nodiscard]] auto createDescriptorPool() const -> vk::raii::DescriptorPool {
return { gpu.device, getPoolSizes(imageBasedLightingDescriptorSetLayout, sceneDescriptorSetLayout, skyboxDescriptorSetLayout).getDescriptorPoolCreateInfo() };
return { gpu.device, getPoolSizes(
assetDescriptorSetLayout,
imageBasedLightingDescriptorSetLayout,
sceneDescriptorSetLayout,
skyboxDescriptorSetLayout).getDescriptorPoolCreateInfo(
vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet | vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind) };
}
};
}
12 changes: 6 additions & 6 deletions interface/vulkan/descriptor_set_layout/Asset.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ export import vulkan_hpp;

namespace vk_gltf_viewer::vulkan::dsl {
export struct Asset : vku::DescriptorSetLayout<vk::DescriptorType::eStorageBuffer, vk::DescriptorType::eStorageBuffer, vk::DescriptorType::eCombinedImageSampler> {
Asset(const vk::raii::Device &device [[clang::lifetimebound]], std::uint32_t textureCount)
explicit Asset(const vk::raii::Device &device [[clang::lifetimebound]])
: DescriptorSetLayout { device, vk::StructureChain {
vk::DescriptorSetLayoutCreateInfo {
vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
vku::unsafeProxy(getBindings(
{ 1, vk::ShaderStageFlagBits::eVertex },
{ 1, vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment },
{ textureCount, vk::ShaderStageFlagBits::eFragment })),
{ 126, vk::ShaderStageFlagBits::eFragment })),
},
vk::DescriptorSetLayoutBindingFlagsCreateInfo {
vku::unsafeProxy({
vk::DescriptorBindingFlags{},
vk::DescriptorBindingFlags{},
vk::Flags { vk::DescriptorBindingFlagBits::eUpdateAfterBind },
vku::unsafeProxy<vk::DescriptorBindingFlags>({
{},
{},
vk::DescriptorBindingFlagBits::eUpdateAfterBind | vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
}),
},
}.get() } { }
Expand Down

0 comments on commit 9ef3682

Please sign in to comment.