From adc02a493913939294b647954b7d846c71653dc7 Mon Sep 17 00:00:00 2001 From: nikeinikei Date: Thu, 1 Sep 2022 14:51:06 +0200 Subject: [PATCH] vulkan: optionally use VK_KHR_PUSH_DESCRIPTOR --- src/modules/graphics/vulkan/Graphics.cpp | 89 +++++++++++++++--------- src/modules/graphics/vulkan/Graphics.h | 12 +++- src/modules/graphics/vulkan/Shader.cpp | 44 +++++++++--- src/modules/graphics/vulkan/Shader.h | 2 + 4 files changed, 103 insertions(+), 44 deletions(-) diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index c43d96aa5..4fe19fdf8 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -407,7 +407,7 @@ void Graphics::setFrontFaceWinding(Winding winding) { states.back().winding = winding; if (optionalDeviceFeatures.extendedDynamicState) { - extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT( + ext.vkCmdSetFrontFaceEXT( commandBuffers.at(currentFrame), Vulkan::getFrontFace(winding)); } @@ -448,7 +448,9 @@ Graphics::RendererInfo Graphics::getRendererInfo() const { std::stringstream ss; ss << "Vulkan( "; if (optionalDeviceFeatures.extendedDynamicState) - ss << "VK_EXT_extended_dynamic_state2 "; + ss << VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME << " "; + if (optionalDeviceFeatures.pushDescriptor) + ss << VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME << " "; ss << ")"; info.name = ss.str(); @@ -572,7 +574,7 @@ void Graphics::setStencilMode(StencilAction action, CompareMode compare, int val vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, value); if (optionalDeviceFeatures.extendedDynamicState) { - extendedDynamicStateFunctions.vkCmdSetStencilOpEXT( + ext.vkCmdSetStencilOpEXT( commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(action), @@ -590,10 +592,10 @@ void Graphics::setDepthMode(CompareMode compare, bool write) { flushBatchedDraws(); if (optionalDeviceFeatures.extendedDynamicState) { - extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT( + ext.vkCmdSetDepthCompareOpEXT( commandBuffers.at(currentFrame), Vulkan::getCompareOp(compare)); - extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT( + ext.vkCmdSetDepthWriteEnableEXT( commandBuffers.at(currentFrame), Vulkan::getBool(write)); } @@ -701,19 +703,19 @@ void Graphics::initDynamicState() { vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.value); if (optionalDeviceFeatures.extendedDynamicState) { - extendedDynamicStateFunctions.vkCmdSetStencilOpEXT( + ext.vkCmdSetStencilOpEXT( commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(states.back().stencil.action), VK_STENCIL_OP_KEEP, Vulkan::getCompareOp(states.back().stencil.compare)); - extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT( + ext.vkCmdSetDepthCompareOpEXT( commandBuffers.at(currentFrame), Vulkan::getCompareOp(states.back().depthTest)); - extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT( + ext.vkCmdSetDepthWriteEnableEXT( commandBuffers.at(currentFrame), Vulkan::getBool(states.back().depthWrite)); - extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT( + ext.vkCmdSetFrontFaceEXT( commandBuffers.at(currentFrame), Vulkan::getFrontFace(states.back().winding)); } } @@ -1169,6 +1171,9 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0) { optionalDeviceFeatures.extendedDynamicState = true; } + if (strcmp(extension.extensionName, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) == 0) { + optionalDeviceFeatures.pushDescriptor = true; + } } } @@ -1206,9 +1211,10 @@ void Graphics::createLogicalDevice() { std::vector enabledExtensions(deviceExtensions.begin(), deviceExtensions.end()); - if (optionalDeviceFeatures.extendedDynamicState) { + if (optionalDeviceFeatures.extendedDynamicState) enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - } + if (optionalDeviceFeatures.pushDescriptor) + enabledExtensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); createInfo.enabledExtensionCount = static_cast(enabledExtensions.size()); createInfo.ppEnabledExtensionNames = enabledExtensions.data(); @@ -1241,29 +1247,36 @@ void Graphics::createLogicalDevice() { if (optionalDeviceFeatures.extendedDynamicState) { #ifdef LOVE_ANDROID - extendedDynamicStateFunctions.vkCmdSetCullModeEXT = vkCmdSetCullModeEXT; - extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetDepthBoundsTestEnableEXT; - extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetCullModeEXT; - extendedDynamicStateFunctions.vkCmdSetDepthTestEnableEXT = vkCmdSetDepthTestEnableEXT; - extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT = vkCmdSetDepthWriteEnableEXT; - extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT = vkCmdSetFrontFaceEXT; - extendedDynamicStateFunctions.vkCmdSetPrimitiveTopologyEXT = vkCmdSetPrimitiveTopologyEXT; - extendedDynamicStateFunctions.vkCmdSetScissorWithCountEXT = vkCmdSetScissorWithCountEXT; - extendedDynamicStateFunctions.vkCmdSetStencilOpEXT = vkCmdSetStencilOpEXT; - extendedDynamicStateFunctions.vkCmdSetStencilTestEnableEXT = vkCmdSetStencilTestEnableEXT; - extendedDynamicStateFunctions.vkCmdSetViewportWithCountEXT = vkCmdSetViewportWithCountEXT; + ext.vkCmdSetCullModeEXT = vkCmdSetCullModeEXT; + ext.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetDepthBoundsTestEnableEXT; + ext.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetCullModeEXT; + ext.vkCmdSetDepthTestEnableEXT = vkCmdSetDepthTestEnableEXT; + ext.vkCmdSetDepthWriteEnableEXT = vkCmdSetDepthWriteEnableEXT; + ext.vkCmdSetFrontFaceEXT = vkCmdSetFrontFaceEXT; + ext.vkCmdSetPrimitiveTopologyEXT = vkCmdSetPrimitiveTopologyEXT; + ext.vkCmdSetScissorWithCountEXT = vkCmdSetScissorWithCountEXT; + ext.vkCmdSetStencilOpEXT = vkCmdSetStencilOpEXT; + ext.vkCmdSetStencilTestEnableEXT = vkCmdSetStencilTestEnableEXT; + ext.vkCmdSetViewportWithCountEXT = vkCmdSetViewportWithCountEXT; #else - extendedDynamicStateFunctions.vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT"); - extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthBoundsTestEnableEXT"); - extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOpEXT"); - extendedDynamicStateFunctions.vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT"); - extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT"); - extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT"); - extendedDynamicStateFunctions.vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT"); - extendedDynamicStateFunctions.vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCountEXT"); - extendedDynamicStateFunctions.vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilOpEXT"); - extendedDynamicStateFunctions.vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT"); - extendedDynamicStateFunctions.vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT"); + ext.vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT"); + ext.vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthBoundsTestEnableEXT"); + ext.vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOpEXT"); + ext.vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT"); + ext.vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT"); + ext.vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT"); + ext.vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT"); + ext.vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCountEXT"); + ext.vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilOpEXT"); + ext.vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT"); + ext.vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT"); +#endif + } + if (optionalDeviceFeatures.pushDescriptor) { +#ifdef LOVE_ANDROID + ext.vkCmdPushDescriptorSetKHR = vkCmdPushDescriptorSetKHR; +#else + ext.vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(device, "vkCmdPushDescriptorSetKHR"); #endif } } @@ -1814,7 +1827,7 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi configuration.primitiveType = primitiveType; if (optionalDeviceFeatures.extendedDynamicState) { - extendedDynamicStateFunctions.vkCmdSetCullModeEXT(commandBuffers.at(currentFrame), Vulkan::getCullMode(cullmode)); + ext.vkCmdSetCullModeEXT(commandBuffers.at(currentFrame), Vulkan::getCullMode(cullmode)); } else { configuration.dynamicState.winding = states.back().winding; configuration.dynamicState.depthState.compare = states.back().depthTest; @@ -2016,6 +2029,14 @@ void Graphics::setComputeShader(Shader* shader) { computeShader = shader; } +const OptionalDeviceFeatures &Graphics::getOptionalDeviceFeatures() const { + return optionalDeviceFeatures; +} + +const OptionalDeviceExtensionFunctions &Graphics::getExtensionFunctions() const { + return ext; +} + VkSampler Graphics::getCachedSampler(const SamplerState& samplerState) { auto it = samplers.find(samplerState); if (it != samplers.end()) { diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 76db1adeb..d174a7d47 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -85,9 +85,11 @@ struct OptionalInstanceExtensions { struct OptionalDeviceFeatures { bool extendedDynamicState = false; + bool pushDescriptor = false; }; -struct ExtendedDynamicStateFunctions { +struct OptionalDeviceExtensionFunctions { + // extended dynamic state PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr; PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr; PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT = nullptr; @@ -99,6 +101,9 @@ struct ExtendedDynamicStateFunctions { PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT = nullptr; PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT = nullptr; PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT = nullptr; + + // push descriptor + PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = nullptr; }; struct GraphicsPipelineConfiguration { @@ -243,6 +248,9 @@ public: void setComputeShader(Shader*); + const OptionalDeviceFeatures &getOptionalDeviceFeatures() const; + const OptionalDeviceExtensionFunctions &getExtensionFunctions() const; + protected: graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override; graphics::Shader* newShaderInternal(StrongRef stages[SHADERSTAGE_MAX_ENUM]) override; @@ -313,7 +321,7 @@ private: VkDevice device = VK_NULL_HANDLE; OptionalInstanceExtensions optionalInstanceExtensions; OptionalDeviceFeatures optionalDeviceFeatures; - ExtendedDynamicStateFunctions extendedDynamicStateFunctions; + OptionalDeviceExtensionFunctions ext; VkQueue graphicsQueue = VK_NULL_HANDLE; VkQueue presentQueue = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE; diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index e8018f00e..36af256fa 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -148,6 +148,13 @@ static EShLanguage getGlslShaderType(ShaderStageType stage) { Shader::Shader(StrongRef stages[]) : graphics::Shader(stages) { + gfx = Module::getInstance(Module::ModuleType::M_GRAPHICS); + auto vgfx = (Graphics*)gfx; + auto &optionalDeviceFeaures = vgfx->getOptionalDeviceFeatures(); + if (optionalDeviceFeaures.pushDescriptor) { + pfn_vkCmdPushDescriptorSetKHR = vgfx->getExtensionFunctions().vkCmdPushDescriptorSetKHR; + } + loadVolatile(); } @@ -260,11 +267,19 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame } } - if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) { - descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); + VkDescriptorSet currentDescriptorSet; + + if (pfn_vkCmdPushDescriptorSetKHR) { + currentDescriptorSet = 0; + } + else { + if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) { + descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); + } + + currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); } - VkDescriptorSet currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); std::vector descriptorWrite{}; VkDescriptorBufferInfo* bufferInfo = nullptr; @@ -333,7 +348,22 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame } } - vkUpdateDescriptorSets(device, static_cast(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr); + if (currentDescriptorSet) { + vkUpdateDescriptorSets(device, static_cast(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr); + + vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); + + currentUsedDescriptorSetsCount++; + } + else { + pfn_vkCmdPushDescriptorSetKHR( + commandBuffer, + bindPoint, + pipelineLayout, + 0, + static_cast(descriptorWrite.size()), + descriptorWrite.data()); + } for (const auto imageInfo : imageInfos) { delete imageInfo; @@ -342,10 +372,7 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame delete bufferInfo; } - vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); - currentUsedUniformStreamBuffersCount++; - currentUsedDescriptorSetsCount++; } Shader::~Shader() { @@ -387,7 +414,6 @@ void Shader::sendTextures(const UniformInfo* info, graphics::Texture** textures, } void Shader::calculateUniformBufferSizeAligned() { - gfx = Module::getInstance(Module::ModuleType::M_GRAPHICS); auto vgfx = (Graphics*)gfx; auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment(); size_t size = localUniformStagingData.size(); @@ -764,6 +790,8 @@ void Shader::createDescriptorSetLayout() { layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.bindingCount = static_cast(bindings.size()); layoutInfo.pBindings = bindings.data(); + if (pfn_vkCmdPushDescriptorSetKHR) + layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) { throw love::Exception("failed to create descriptor set layout"); diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 72a97778e..b7c89b0b0 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -74,6 +74,8 @@ private: VkDescriptorSet allocateDescriptorSet(); + PFN_vkCmdPushDescriptorSetKHR pfn_vkCmdPushDescriptorSetKHR = nullptr; + VkDeviceSize uniformBufferSizeAligned; VkPipeline computePipeline;