Browse Source

vulkan: better api use of descriptor pools
Some implementations allow for bottomless pools,
which never run out of pool memory.
This new implementation allows for this case to happen.

niki 2 years ago
parent
commit
f30bf9bee0
2 changed files with 37 additions and 39 deletions
  1. 35 32
      src/modules/graphics/vulkan/Shader.cpp
  2. 2 7
      src/modules/graphics/vulkan/Shader.h

+ 35 - 32
src/modules/graphics/vulkan/Shader.cpp

@@ -141,7 +141,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
 };
 };
 
 
 static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16;
 static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16;
-static const uint32_t DESCRIPTOR_POOL_SIZE = 1;
+static const uint32_t DESCRIPTOR_POOL_SIZE = 16;
 
 
 class BindingMapper
 class BindingMapper
 {
 {
@@ -315,9 +315,6 @@ void Shader::unloadVolatile()
 			vkDestroyPipeline(device, computePipeline, nullptr);
 			vkDestroyPipeline(device, computePipeline, nullptr);
 	});
 	});
 
 
-	while (!freeDescriptorSets.empty())
-		freeDescriptorSets.pop();
-
 	for (const auto streamBuffer : streamBuffers)
 	for (const auto streamBuffer : streamBuffers)
 		streamBuffer->release();
 		streamBuffer->release();
 
 
@@ -1102,42 +1099,48 @@ void Shader::setMainTex(graphics::Texture *texture)
 	}
 	}
 }
 }
 
 
-VkDescriptorSet Shader::allocateDescriptorSet()
+VkDescriptorPool Shader::createDescriptorPool()
 {
 {
-	if (freeDescriptorSets.empty())
-	{
-		VkDescriptorPoolCreateInfo createInfo{};
-		createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
-		createInfo.maxSets = DESCRIPTOR_POOL_SIZE;
-		createInfo.poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size());
-		createInfo.pPoolSizes = descriptorPoolSizes.data();
+	VkDescriptorPoolCreateInfo createInfo{};
+	createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+	createInfo.maxSets = DESCRIPTOR_POOL_SIZE;
+	createInfo.poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size());
+	createInfo.pPoolSizes = descriptorPoolSizes.data();
+
+	VkDescriptorPool pool;
+	if (vkCreateDescriptorPool(device, &createInfo, nullptr, &pool) != VK_SUCCESS)
+		throw love::Exception("failed to create descriptor pool");
 
 
-		VkDescriptorPool pool;
-		if (vkCreateDescriptorPool(device, &createInfo, nullptr, &pool) != VK_SUCCESS)
-			throw love::Exception("failed to create descriptor pool");
-		descriptorPools.push_back(pool);
+	descriptorPools.push_back(pool);
+}
 
 
-		std::vector<VkDescriptorSetLayout> layouts(DESCRIPTOR_POOL_SIZE, descriptorSetLayout);
+VkDescriptorSet Shader::allocateDescriptorSet()
+{
+	if (descriptorPools.empty())
+		createDescriptorPool();
 
 
+	while (true)
+	{
 		VkDescriptorSetAllocateInfo allocInfo{};
 		VkDescriptorSetAllocateInfo allocInfo{};
 		allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
 		allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-		allocInfo.descriptorPool = pool;
-		allocInfo.descriptorSetCount = DESCRIPTOR_POOL_SIZE;
-		allocInfo.pSetLayouts = layouts.data();
-
-		std::vector<VkDescriptorSet> descriptorSet;
-		descriptorSet.resize(DESCRIPTOR_POOL_SIZE);
-		VkResult result = vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data());
-		if (result != VK_SUCCESS)
-			throw love::Exception("failed to allocate descriptor set");
+		allocInfo.descriptorPool = descriptorPools.back();
+		allocInfo.descriptorSetCount = 1;
+		allocInfo.pSetLayouts = &descriptorSetLayout;
 
 
-		for (const auto ds : descriptorSet)
-			freeDescriptorSets.push(ds);
-	}
+		VkDescriptorSet descriptorSet;
+		VkResult result = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet);
 
 
-	auto ds = freeDescriptorSets.front();
-	freeDescriptorSets.pop();
-	return ds;
+		switch (result)
+		{
+		case VK_SUCCESS:
+			return descriptorSet;
+		case VK_ERROR_OUT_OF_POOL_MEMORY:
+			createDescriptorPool();
+			continue;
+		default:
+			throw love::Exception("failed to allocate descriptor set");
+		}
+	}
 }
 }
 
 
 } // vulkan
 } // vulkan

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

@@ -97,12 +97,8 @@ private:
 	void createPipelineLayout();
 	void createPipelineLayout();
 	void createDescriptorPoolSizes();
 	void createDescriptorPoolSizes();
 	void createStreamBuffers();
 	void createStreamBuffers();
-	void buildLocalUniforms(
-		spirv_cross::Compiler &comp, 
-		const spirv_cross::SPIRType &type, 
-		size_t baseoff, 
-		const std::string &basename);
-
+	void buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename);
+	VkDescriptorPool createDescriptorPool();
 	VkDescriptorSet allocateDescriptorSet();
 	VkDescriptorSet allocateDescriptorSet();
 
 
 	VkDeviceSize uniformBufferSizeAligned;
 	VkDeviceSize uniformBufferSizeAligned;
@@ -117,7 +113,6 @@ private:
 	// we keep a vector of stream buffers that gets dynamically increased if more memory is needed
 	// we keep a vector of stream buffers that gets dynamically increased if more memory is needed
 	std::vector<StreamBuffer*> streamBuffers;
 	std::vector<StreamBuffer*> streamBuffers;
 	std::vector<VkDescriptorPool> descriptorPools;
 	std::vector<VkDescriptorPool> descriptorPools;
-	std::queue<VkDescriptorSet> freeDescriptorSets;
 	std::vector<std::vector<VkDescriptorSet>> descriptorSetsVector;
 	std::vector<std::vector<VkDescriptorSet>> descriptorSetsVector;
 
 
 	std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
 	std::vector<VkPipelineShaderStageCreateInfo> shaderStages;