Browse Source

vulkan: optionally use VK_KHR_PUSH_DESCRIPTOR

nikeinikei 3 years ago
parent
commit
adc02a4939

+ 55 - 34
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<const char*> 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<uint32_t>(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
+		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
-		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.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()) {

+ 10 - 2
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<love::graphics::ShaderStage> 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;

+ 36 - 8
src/modules/graphics/vulkan/Shader.cpp

@@ -148,6 +148,13 @@ static EShLanguage getGlslShaderType(ShaderStageType stage) {
 
 Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[])
 	: graphics::Shader(stages) {
+	gfx = Module::getInstance<Graphics>(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<uint32_t>(descriptorSetsVector.at(currentFrame).size())) {
-		descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
+	VkDescriptorSet currentDescriptorSet;
+
+	if (pfn_vkCmdPushDescriptorSetKHR) {
+		currentDescriptorSet = 0;
+	}
+	else {
+		if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(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<VkWriteDescriptorSet> descriptorWrite{};
 
 	VkDescriptorBufferInfo* bufferInfo = nullptr;
@@ -333,7 +348,22 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
 		}
 	}
 
-	vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
+	if (currentDescriptorSet) {
+		vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
+
+		vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
+
+		currentUsedDescriptorSetsCount++;
+	}
+	else {
+		pfn_vkCmdPushDescriptorSetKHR(
+			commandBuffer, 
+			bindPoint, 
+			pipelineLayout, 
+			0, 
+			static_cast<uint32_t>(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, &currentDescriptorSet, 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<Graphics>(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<uint32_t>(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");

+ 2 - 0
src/modules/graphics/vulkan/Shader.h

@@ -74,6 +74,8 @@ private:
 
 	VkDescriptorSet allocateDescriptorSet();
 
+	PFN_vkCmdPushDescriptorSetKHR pfn_vkCmdPushDescriptorSetKHR = nullptr;
+
 	VkDeviceSize uniformBufferSizeAligned;
 
 	VkPipeline computePipeline;