From 9d9e2da763f9a7667511abf9995a73d9d089b762 Mon Sep 17 00:00:00 2001 From: niki Date: Tue, 25 Jul 2023 21:39:28 +0200 Subject: [PATCH] vulkan: optimize vkUpdateDescriptorSets calls --- src/modules/graphics/vulkan/Shader.cpp | 78 ++++++++++++++++++-------- src/modules/graphics/vulkan/Shader.h | 6 +- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 4b16d0291..f1863420f 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -360,15 +360,26 @@ void Shader::newFrame() } else streamBuffers.at(0)->nextFrame(); - - if (descriptorSetsVector.at(currentFrame).size() == 0) - descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); - - currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(0); } void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint) { + if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) + descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); + + VkDescriptorSet currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); + + std::vector bufferInfos{}; + bufferInfos.reserve(numBuffers); + + std::vector imageInfos{}; + imageInfos.reserve(numTextures); + + std::vector bufferViews; + bufferViews.reserve(numBufferViews); + + std::vector descriptorWrites; + if (!localUniformData.empty()) { auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; @@ -397,6 +408,8 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind bufferInfo.offset = offset; bufferInfo.range = localUniformData.size(); + bufferInfos.push_back(bufferInfo); + VkWriteDescriptorSet uniformWrite{}; uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; uniformWrite.dstSet = currentDescriptorSet; @@ -404,9 +417,9 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind uniformWrite.dstArrayElement = 0; uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; uniformWrite.descriptorCount = 1; - uniformWrite.pBufferInfo = &bufferInfo; + uniformWrite.pBufferInfo = &bufferInfos[bufferInfos.size() - 1]; - vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr); + descriptorWrites.push_back(uniformWrite); currentUsedUniformStreamBuffersCount++; } @@ -422,8 +435,6 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind { bool isSampler = info.baseType == UNIFORM_SAMPLER; - std::vector imageInfos; - for (int i = 0; i < info.count; i++) { auto vkTexture = dynamic_cast(info.textures[i]); @@ -451,9 +462,9 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind else write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; write.descriptorCount = static_cast(info.count); - write.pImageInfo = imageInfos.data(); + write.pImageInfo = &imageInfos[imageInfos.size() - info.count]; - vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); + descriptorWrites.push_back(write); } if (info.baseType == UNIFORM_STORAGEBUFFER) { @@ -465,8 +476,6 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; write.descriptorCount = info.count; - std::vector bufferInfos; - for (int i = 0; i < info.count; i++) { if (info.buffers[i] == nullptr) @@ -480,9 +489,9 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind bufferInfos.push_back(bufferInfo); } - write.pBufferInfo = bufferInfos.data(); + write.pBufferInfo = &bufferInfos[bufferInfos.size() - info.count]; - vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); + descriptorWrites.push_back(write); } if (info.baseType == UNIFORM_TEXELBUFFER) { @@ -494,8 +503,6 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; write.descriptorCount = info.count; - std::vector bufferViews; - for (int i = 0; i < info.count; i++) { if (info.buffers[i] == nullptr) @@ -504,20 +511,17 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind bufferViews.push_back((VkBufferView)info.buffers[i]->getTexelBufferHandle()); } - write.pTexelBufferView = bufferViews.data(); + write.pTexelBufferView = &bufferViews[bufferViews.size() - info.count]; - vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); + descriptorWrites.push_back(write); } } + vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr); + vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); currentUsedDescriptorSetsCount++; - - if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) - descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); - - currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); } Shader::~Shader() @@ -954,6 +958,32 @@ void Shader::compileShaders() shaderStages.push_back(shaderStageInfo); } + + numBuffers = 0; + numTextures = 0; + numBufferViews = 0; + + if (localUniformData.size() > 0) + numBuffers++; + + for (const auto &u : uniformInfos) + { + switch (u.second.baseType) + { + case UNIFORM_SAMPLER: + case UNIFORM_STORAGETEXTURE: + numTextures++; + break; + case UNIFORM_STORAGEBUFFER: + numBuffers++; + break; + case UNIFORM_TEXELBUFFER: + numBufferViews++; + break; + default: + continue; + } + } } void Shader::createDescriptorSetLayout() diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 2639da477..1af256732 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -105,6 +105,10 @@ private: VkPipeline computePipeline; + uint32_t numTextures; + uint32_t numBuffers; + uint32_t numBufferViews; + VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; std::vector descriptorPoolSizes; @@ -134,8 +138,6 @@ private: std::unordered_map attributes; - VkDescriptorSet currentDescriptorSet; - uint32_t currentFrame; uint32_t currentUsedUniformStreamBuffersCount; uint32_t currentUsedDescriptorSetsCount;