Browse Source

vulkan: fix incorrect textures in shader uniforms

niki 2 years ago
parent
commit
8694c44207

+ 6 - 16
src/modules/graphics/vulkan/Graphics.cpp

@@ -358,7 +358,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
 		}
 	}
 
-	endRecordingGraphicsCommands(present);
+	endRecordingGraphicsCommands();
 
 	if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
 		vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
@@ -410,7 +410,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
 			callbacks.clear();
 		}
 
-		startRecordingGraphicsCommands(false);
+		startRecordingGraphicsCommands();
 	}
 }
 
@@ -1103,7 +1103,7 @@ void Graphics::beginFrame()
 		cleanUpFn();
 	cleanUpFunctions.at(currentFrame).clear();
 
-	startRecordingGraphicsCommands(true);
+	startRecordingGraphicsCommands();
 
 	Vulkan::cmdTransitionImageLayout(
 		commandBuffers.at(currentFrame),
@@ -1134,7 +1134,7 @@ void Graphics::beginFrame()
 	usedShadersInFrame.clear();
 }
 
-void Graphics::startRecordingGraphicsCommands(bool newFrame)
+void Graphics::startRecordingGraphicsCommands()
 {
 	VkCommandBufferBeginInfo beginInfo{};
 	beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -1149,7 +1149,7 @@ void Graphics::startRecordingGraphicsCommands(bool newFrame)
 	setDefaultRenderPass();
 }
 
-void Graphics::endRecordingGraphicsCommands(bool present) {
+void Graphics::endRecordingGraphicsCommands() {
 	if (renderPassState.active)
 		endRenderPass();
 
@@ -1157,16 +1157,6 @@ void Graphics::endRecordingGraphicsCommands(bool present) {
 		throw love::Exception("failed to record command buffer");
 }
 
-uint32_t Graphics::getNumImagesInFlight() const
-{
-	return MAX_FRAMES_IN_FLIGHT;
-}
-
-uint32_t Graphics::getFrameIndex() const
-{
-	return static_cast<uint32_t>(currentFrame);
-}
-
 const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const
 {
 	return minUniformBufferOffsetAlignment;
@@ -2263,7 +2253,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
 		}
 	}
 
-	if (usesConstantVertexColor(attributes))
+	if (!usesConstantVertexColor(attributes))
 	{
 		bufferVector.push_back((VkBuffer)defaultConstantColor->getHandle());
 		offsets.push_back((VkDeviceSize)0);

+ 2 - 4
src/modules/graphics/vulkan/Graphics.h

@@ -289,8 +289,6 @@ public:
 	void queueCleanUp(std::function<void()> cleanUp);
 	void addReadbackCallback(std::function<void()> callback);
 	void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
-	uint32_t getNumImagesInFlight() const;
-	uint32_t getFrameIndex() const;
 	const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
 	graphics::Texture *getDefaultTexture() const;
 	VkSampler getCachedSampler(const SamplerState &sampler);
@@ -349,8 +347,8 @@ private:
 	void recreateSwapChain();
 	void initDynamicState();
 	void beginFrame();
-	void startRecordingGraphicsCommands(bool newFrame);
-	void endRecordingGraphicsCommands(bool present);
+	void startRecordingGraphicsCommands();
+	void endRecordingGraphicsCommands();
 	void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
 	bool usesConstantVertexColor(const VertexAttributes &attribs);
 	void createVulkanVertexFormat(

+ 29 - 21
src/modules/graphics/vulkan/Shader.cpp

@@ -196,7 +196,7 @@ bool Shader::loadVolatile()
 	createPipelineLayout();
 	createDescriptorPoolSizes();
 	createStreamBuffers();
-	descriptorSetsVector.resize(vgfx->getNumImagesInFlight());
+	descriptorSetsVector.resize(MAX_FRAMES_IN_FLIGHT);
 	currentFrame = 0;
 	currentUsedUniformStreamBuffersCount = 0;
 	currentUsedDescriptorSetsCount = 0;
@@ -274,10 +274,11 @@ VkPipeline Shader::getComputePipeline() const
 	return computePipeline;
 }
 
-void Shader::newFrame(uint32_t frameIndex)
+void Shader::newFrame()
 {
-	currentFrame = frameIndex;
+	currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
 
+	updatedUniforms.clear();
 	currentUsedUniformStreamBuffersCount = 0;
 	currentUsedDescriptorSetsCount = 0;
 
@@ -295,12 +296,10 @@ void Shader::newFrame(uint32_t frameIndex)
 	else
 		streamBuffers.at(0)->nextFrame();
 
-	if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(descriptorSetsVector.at(currentFrame).size()))
+	if (descriptorSetsVector.at(currentFrame).size() == 0)
 		descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
 
-	currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
-
-	initDescriptorSet();
+	currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(0);
 }
 
 void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint)
@@ -336,7 +335,7 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
 		VkWriteDescriptorSet uniformWrite{};
 		uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 		uniformWrite.dstSet = currentDescriptorSet;
-		uniformWrite.dstBinding = uniformLocation;
+		uniformWrite.dstBinding = localUniformLocation;
 		uniformWrite.dstArrayElement = 0;
 		uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
 		uniformWrite.descriptorCount = 1;
@@ -345,6 +344,8 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
 		vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr);
 
 		currentUsedUniformStreamBuffersCount++;
+
+		updatedUniforms.insert(localUniformLocation);
 	}
 
 	static const std::vector<BuiltinUniform> builtinUniformTextures = {
@@ -365,18 +366,28 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
 			imageInfo.imageView = (VkImageView)texture->getRenderTargetHandle();
 			imageInfo.sampler = (VkSampler)texture->getSamplerHandle();
 
+			auto location = builtinUniformInfo[builtin]->location;
+
 			VkWriteDescriptorSet textureWrite{};
 			textureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 			textureWrite.dstSet = currentDescriptorSet;
-			textureWrite.dstBinding = builtinUniformInfo[builtin]->location;
+			textureWrite.dstBinding = location;
 			textureWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 			textureWrite.descriptorCount = 1;
 			textureWrite.pImageInfo = &imageInfo;
 
 			vkUpdateDescriptorSets(device, 1, &textureWrite, 0, nullptr);
+
+			updatedUniforms.insert(location);
 		}
 	}
 
+	for (const auto &u : uniformInfos)
+	{
+		if (updatedUniforms.find(u.second.location) == updatedUniforms.end())
+			updateUniform(&u.second, u.second.count);
+	}
+
 	vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
 
 	currentUsedDescriptorSetsCount++;
@@ -385,8 +396,6 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
 		descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
 
 	currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
-
-	initDescriptorSet();
 }
 
 Shader::~Shader()
@@ -399,7 +408,7 @@ void Shader::attach()
 	auto &usedShadersInFrame = vgfx->getUsedShadersInFrame();
 	if (usedShadersInFrame.find(this) == usedShadersInFrame.end())
 	{
-		newFrame(vgfx->getFrameIndex());
+		newFrame();
 		usedShadersInFrame.insert(this);
 	}
 
@@ -532,6 +541,8 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
 
 		vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
 	}
+
+	updatedUniforms.insert(info->location);
 }
 
 void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
@@ -544,6 +555,8 @@ void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures,
 		if (oldTexture)
 			oldTexture->release();
 	}
+
+	updateUniform(info, count);
 }
 
 void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count)
@@ -556,6 +569,8 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
 		if (oldBuffer)
 			oldBuffer->release();
 	}
+
+	updateUniform(info, count);
 }
 
 void Shader::calculateUniformBufferSizeAligned()
@@ -568,13 +583,6 @@ void Shader::calculateUniformBufferSizeAligned()
 	uniformBufferSizeAligned = factor * minAlignment;
 }
 
-void Shader::initDescriptorSet()
-{
-	for (const auto &entry : uniformInfos)
-		if (Vulkan::getDescriptorType(entry.second.baseType) != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
-			updateUniform(&entry.second, entry.second.count, true);
-}
-
 void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
 {
 	using namespace spirv_cross;
@@ -776,7 +784,7 @@ void Shader::compileShaders()
 				auto defaultUniformBlockSize = comp.get_declared_struct_size(type);
 				localUniformStagingData.resize(defaultUniformBlockSize);
 				localUniformData.resize(defaultUniformBlockSize);
-				uniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
+				localUniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
 
 				memset(localUniformStagingData.data(), 0, defaultUniformBlockSize);
 				memset(localUniformData.data(), 0, defaultUniformBlockSize);
@@ -956,7 +964,7 @@ void Shader::createDescriptorSetLayout()
 	if (!localUniformStagingData.empty())
 	{
 		VkDescriptorSetLayoutBinding uniformBinding{};
-		uniformBinding.binding = uniformLocation;
+		uniformBinding.binding = localUniformLocation;
 		uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
 		uniformBinding.descriptorCount = 1;
 		uniformBinding.stageFlags = stageFlags;

+ 5 - 3
src/modules/graphics/vulkan/Shader.h

@@ -35,6 +35,7 @@
 #include <memory>
 #include <unordered_map>
 #include <queue>
+#include <set>
 
 
 namespace love
@@ -63,7 +64,7 @@ public:
 
 	const VkPipelineLayout getGraphicsPipelineLayout() const;
 
-	void newFrame(uint32_t frameIndex);
+	void newFrame();
 
 	void cmdPushDescriptorSets(VkCommandBuffer, VkPipelineBindPoint);
 
@@ -101,7 +102,6 @@ private:
 		const spirv_cross::SPIRType &type, 
 		size_t baseoff, 
 		const std::string &basename);
-	void initDescriptorSet();
 	void updateUniform(const UniformInfo *info, int count, bool internal);
 
 	VkDescriptorSet allocateDescriptorSet();
@@ -121,6 +121,8 @@ private:
 	std::queue<VkDescriptorSet> freeDescriptorSets;
 	std::vector<std::vector<VkDescriptorSet>> descriptorSetsVector;
 
+	std::set<uint32_t> updatedUniforms;
+
 	std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
 	std::vector<VkShaderModule> shaderModules;
 
@@ -135,7 +137,7 @@ private:
 	std::unique_ptr<StreamBuffer> uniformBufferObjectBuffer;
 	std::vector<uint8> localUniformData;
 	std::vector<uint8> localUniformStagingData;
-	uint32_t uniformLocation;
+	uint32_t localUniformLocation;
 	OptionalInt builtinUniformDataOffset;
 
 	std::unordered_map<std::string, int> attributes;