Browse Source

vulkan: fix video rendering

When rewriting the shader part rendering videos was broken.
This commit fixes that again.
niki 3 years ago
parent
commit
84df8fee03
2 changed files with 55 additions and 19 deletions
  1. 52 15
      src/modules/graphics/vulkan/Shader.cpp
  2. 3 4
      src/modules/graphics/vulkan/Shader.h

+ 52 - 15
src/modules/graphics/vulkan/Shader.cpp

@@ -150,6 +150,10 @@ Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[])
 }
 }
 
 
 bool Shader::loadVolatile() {
 bool Shader::loadVolatile() {
+	for (int i = 0; i < BUILTIN_MAX_ENUM; i++) {
+		builtinUniformInfo[i] = nullptr;
+	}
+
 	compileShaders();
 	compileShaders();
 	calculateUniformBufferSizeAligned();
 	calculateUniformBufferSizeAligned();
 	createDescriptorSetLayout();
 	createDescriptorSetLayout();
@@ -192,12 +196,15 @@ const VkPipelineLayout Shader::getGraphicsPipelineLayout() const {
 	return pipelineLayout;
 	return pipelineLayout;
 }
 }
 
 
-static VkDescriptorImageInfo createDescriptorImageInfo(graphics::Texture* texture) {
-	VkDescriptorImageInfo imageInfo{};
-	imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture* texture) {
 	Texture* vkTexture = (Texture*)texture;
 	Texture* vkTexture = (Texture*)texture;
-	imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle();
-	imageInfo.sampler = (VkSampler)vkTexture->getSamplerHandle();
+
+	VkDescriptorImageInfo* imageInfo = new VkDescriptorImageInfo();
+
+	imageInfo->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+	imageInfo->imageView = (VkImageView)vkTexture->getRenderTargetHandle();
+	imageInfo->sampler = (VkSampler)vkTexture->getSamplerHandle();
+
 	return imageInfo;
 	return imageInfo;
 }
 }
 
 
@@ -259,6 +266,11 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
 
 
 	descriptorWrite.push_back(uniformWrite);
 	descriptorWrite.push_back(uniformWrite);
 
 
+	// Vulkan needs the image infos as a pointer.
+	// we collect them all here to properly free them up
+	// after the vulkan call.
+	std::vector<VkDescriptorImageInfo*> imageInfos;
+	
 	// update everything other than uniform buffers (since that's already taken care of.
 	// update everything other than uniform buffers (since that's already taken care of.
 	for (const auto& [key, val] : uniformInfos) {
 	for (const auto& [key, val] : uniformInfos) {
 		// fixme: other types.
 		// fixme: other types.
@@ -270,8 +282,13 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
 			write.dstArrayElement = 0;
 			write.dstArrayElement = 0;
 			write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 			write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 			write.descriptorCount = 1;
 			write.descriptorCount = 1;
-			const auto imageInfo =  createDescriptorImageInfo(val.textures[0]);	// fixme: arrays
-			write.pImageInfo = &imageInfo;
+
+			uint32_t index = static_cast<uint32_t>(imageInfos.size());
+
+			VkDescriptorImageInfo* imageInfo = createDescriptorImageInfo(val.textures[0]);	// fixme: arrays
+			imageInfos.push_back(imageInfo);
+
+			write.pImageInfo = imageInfo;
 
 
 			descriptorWrite.push_back(write);
 			descriptorWrite.push_back(write);
 		}
 		}
@@ -282,6 +299,10 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
 		pipelineLayout, 0, 
 		pipelineLayout, 0, 
 		static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data());
 		static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data());
 
 
+	for (const auto imageInfo : imageInfos) {
+		delete imageInfo;
+	}
+
 	count++;
 	count++;
 }
 }
 
 
@@ -385,16 +406,14 @@ void Shader::compileShaders() {
 	using namespace glslang;
 	using namespace glslang;
 	using namespace spirv_cross;
 	using namespace spirv_cross;
 
 
+	std::vector<TShader*> glslangShaders;
+
 	TProgram* program = new TProgram();
 	TProgram* program = new TProgram();
 
 
 	gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
 	gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
 	auto vgfx = (Graphics*)gfx;
 	auto vgfx = (Graphics*)gfx;
 	device = vgfx->getDevice();
 	device = vgfx->getDevice();
 
 
-	ytexture = vgfx->getDefaultTexture();
-	crtexture = vgfx->getDefaultTexture();
-	cbtexture = vgfx->getDefaultTexture();
-
 	for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) {
 	for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) {
 		if (!stages[i])
 		if (!stages[i])
 			continue;
 			continue;
@@ -430,6 +449,7 @@ void Shader::compileShaders() {
 		}
 		}
 
 
 		program->addShader(tshader);
 		program->addShader(tshader);
+		glslangShaders.push_back(tshader);
 	}
 	}
 
 
 	if (!program->link(EShMsgDefault)) {
 	if (!program->link(EShMsgDefault)) {
@@ -615,6 +635,11 @@ void Shader::compileShaders() {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	delete program;
+	for (auto shader : glslangShaders) {
+		delete shader;
+	}
 }
 }
 
 
 void Shader::createDescriptorSetLayout() {
 void Shader::createDescriptorSetLayout() {
@@ -666,9 +691,17 @@ void Shader::createStreamBuffers() {
 }
 }
 
 
 void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) {
 void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) {
-	this->ytexture = ytexture;
-	this->cbtexture = cbtexture;
-	this->crtexture = crtexture;
+	// if the shader doesn't actually use these textures they might get optimized out
+	// in that case this function becomes a noop.
+	if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y] != nullptr) {
+		builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y]->textures[0] = ytexture;
+	}
+	if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB] != nullptr) {
+		builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB]->textures[0] = cbtexture;
+	}
+	if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR] != nullptr) {
+		builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR]->textures[0] = crtexture;
+	}
 }
 }
 
 
 void Shader::setUniformData(BuiltinUniformData& data) {
 void Shader::setUniformData(BuiltinUniformData& data) {
@@ -677,7 +710,11 @@ void Shader::setUniformData(BuiltinUniformData& data) {
 }
 }
 
 
 void Shader::setMainTex(graphics::Texture* texture) {
 void Shader::setMainTex(graphics::Texture* texture) {
-	builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0] = texture;
+	// if the shader doesn't actually use the texture it might get optimized out
+	// in that case this function becomes a noop.
+	if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN] != nullptr) {
+		builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0] = texture;
+	}
 }
 }
 } // vulkan
 } // vulkan
 } // graphics
 } // graphics

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

@@ -42,6 +42,9 @@ public:
 	const UniformInfo* getUniformInfo(const std::string& name) const override { return nullptr; }
 	const UniformInfo* getUniformInfo(const std::string& name) const override { return nullptr; }
 	const UniformInfo* getUniformInfo(BuiltinUniform builtin) const override { return nullptr;  }
 	const UniformInfo* getUniformInfo(BuiltinUniform builtin) const override { return nullptr;  }
 
 
+	// Not needed right now, since the logic that links the values of the uniforms to the shader is done in cmdPushDescriptorSets
+	// which gets called from the vulkan::Graphics class whenever a draw call happens.
+	// I'll have to reevaluate the use of this function in the future though.
 	void updateUniform(const UniformInfo* info, int count) override {}
 	void updateUniform(const UniformInfo* info, int count) override {}
 
 
 	void sendTextures(const UniformInfo* info, graphics::Texture** textures, int count) override {}
 	void sendTextures(const UniformInfo* info, graphics::Texture** textures, int count) override {}
@@ -90,10 +93,6 @@ private:
 	std::vector<uint8> localUniformStagingData;
 	std::vector<uint8> localUniformStagingData;
 	size_t builtinUniformDataOffset;
 	size_t builtinUniformDataOffset;
 
 
-	graphics::Texture* ytexture;
-	graphics::Texture* cbtexture;
-	graphics::Texture* crtexture;
-
 	uint32_t currentFrame;
 	uint32_t currentFrame;
 	// todo: give this variable a better name
 	// todo: give this variable a better name
 	uint32_t count;
 	uint32_t count;