Browse Source

Use löve's uniform data object for vulkan shader

niki 3 years ago
parent
commit
c996860602

+ 2 - 1
src/common/runtime.h

@@ -673,7 +673,8 @@ int luax_catchexcept(lua_State *L, const T& func)
 	catch (const std::exception &e)
 	catch (const std::exception &e)
 	{
 	{
 		should_error = true;
 		should_error = true;
-		lua_pushstring(L, e.what());
+		const char* msg = e.what();
+		lua_pushstring(L, msg);
 	}
 	}
 
 
 	if (should_error)
 	if (should_error)

+ 48 - 49
src/modules/graphics/Shader.cpp

@@ -94,7 +94,7 @@ static const char global_syntax[] = R"(
 
 
 static const char render_uniforms[] = R"(
 static const char render_uniforms[] = R"(
 #ifdef USE_VULKAN
 #ifdef USE_VULKAN
-	VULKAN_BINDING(0) uniform LoveUniformsPerDraw {
+	layout(binding=0) uniform LoveUniformsPerDraw {
 		vec4 uniformsPerDraw[13];
 		vec4 uniformsPerDraw[13];
 	} udp;
 	} udp;
 	#define love_UniformsPerDraw udp.uniformsPerDraw
 	#define love_UniformsPerDraw udp.uniformsPerDraw
@@ -433,25 +433,20 @@ void main() {
 )";
 )";
 
 
 static const char vulkan_vert[] = R"(
 static const char vulkan_vert[] = R"(
-#version 450
-
 layout(location = 0) in vec2 inPosition;
 layout(location = 0) in vec2 inPosition;
 layout(location = 1) in vec2 iTexCoords;
 layout(location = 1) in vec2 iTexCoords;
 
 
 layout(location = 0) out vec4 fragColor;
 layout(location = 0) out vec4 fragColor;
 layout(location = 1) out vec2 texCoords;
 layout(location = 1) out vec2 texCoords;
 
 
-layout(binding = 0) uniform LoveUniforms {
-	float windowWidth;
-	float windowHeight;
-} loveUniforms;
-
+vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) {
+	return clipSpaceFromLocal * localPosition;
+}
 
 
 void main() {
 void main() {
-    gl_Position = vec4(
-        2 * inPosition.x / loveUniforms.windowWidth - 1,
-        2 * inPosition.y / loveUniforms.windowHeight - 1, 
-        0.0, 1.0);
+	love_initializeBuiltinUniforms();
+	
+	gl_Position = position(ClipSpaceFromLocal, vec4(inPosition, 0, 1));
 
 
     fragColor = vec4(1, 1, 1, 1);
     fragColor = vec4(1, 1, 1, 1);
 	texCoords = iTexCoords;
 	texCoords = iTexCoords;
@@ -459,8 +454,6 @@ void main() {
 )";
 )";
 
 
 static const char vulkan_pixel[] = R"(
 static const char vulkan_pixel[] = R"(
-#version 450
-
 layout(location = 0) in vec4 fragColor;
 layout(location = 0) in vec4 fragColor;
 layout(location = 1) in vec2 texCoords;
 layout(location = 1) in vec2 texCoords;
 
 
@@ -617,47 +610,53 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
 	if (glsl1on3)
 	if (glsl1on3)
 		lang = LANGUAGE_GLSL3;
 		lang = LANGUAGE_GLSL3;
 
 
+	glsl::StageInfo stageinfo = glsl::stageInfo[stage];
+
+	std::stringstream ss;
+
 	if (info.vulkan) {
 	if (info.vulkan) {
+		ss << "#version 450\n";
+		ss << "#define LOVE_HIGHP_OR_MEDIUMP highp\n";
+		ss << "#define USE_VULKAN 1\n";
+		ss << stageinfo.uniforms;
+
 		if (stage == SHADERSTAGE_VERTEX) {
 		if (stage == SHADERSTAGE_VERTEX) {
-			return love::graphics::glsl::vulkan_vert;
+			ss << love::graphics::glsl::vulkan_vert;
 		}
 		}
 		if (stage == SHADERSTAGE_PIXEL) {
 		if (stage == SHADERSTAGE_PIXEL) {
-			return love::graphics::glsl::vulkan_pixel;
+			ss << love::graphics::glsl::vulkan_pixel;
 		}
 		}
 	}
 	}
-
-	glsl::StageInfo stageinfo = glsl::stageInfo[stage];
-
-	std::stringstream ss;
-
-	ss << (gles ? glsl::versions[lang].glsles : glsl::versions[lang].glsl) << "\n";
-	ss << "#define " << stageinfo.name << " " << stageinfo.name << "\n";
-	if (glsl1on3)
-		ss << "#define LOVE_GLSL1_ON_GLSL3 1\n";
-	if (isGammaCorrect())
-		ss << "#define LOVE_GAMMA_CORRECT 1\n";
-	if (info.usesMRT)
-		ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
-
-	for (const auto &def : options.defines)
-		ss << "#define " + def.first + " " + def.second + "\n";
-
-	ss << glsl::global_syntax;
-	ss << stageinfo.header;
-	ss << stageinfo.uniforms;
-	ss << glsl::global_functions;
-	ss << stageinfo.functions;
-
-	if (info.stages[stage] == ENTRYPOINT_HIGHLEVEL)
-		ss << stageinfo.main;
-	else if (info.stages[stage] == ENTRYPOINT_CUSTOM)
-		ss << stageinfo.main_custom;
-	else if (info.stages[stage] == ENTRYPOINT_RAW)
-		ss << stageinfo.main_raw;
-	else
-		throw love::Exception("Unknown shader entry point %d", info.stages[stage]);
-	ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n");
-	ss << code;
+	else {
+		ss << (gles ? glsl::versions[lang].glsles : glsl::versions[lang].glsl) << "\n";
+		ss << "#define " << stageinfo.name << " " << stageinfo.name << "\n";
+		if (glsl1on3)
+			ss << "#define LOVE_GLSL1_ON_GLSL3 1\n";
+		if (isGammaCorrect())
+			ss << "#define LOVE_GAMMA_CORRECT 1\n";
+		if (info.usesMRT)
+			ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
+
+		for (const auto &def : options.defines)
+			ss << "#define " + def.first + " " + def.second + "\n";
+
+		ss << glsl::global_syntax;
+		ss << stageinfo.header;
+		ss << stageinfo.uniforms;
+		ss << glsl::global_functions;
+		ss << stageinfo.functions;
+
+		if (info.stages[stage] == ENTRYPOINT_HIGHLEVEL)
+			ss << stageinfo.main;
+		else if (info.stages[stage] == ENTRYPOINT_CUSTOM)
+			ss << stageinfo.main_custom;
+		else if (info.stages[stage] == ENTRYPOINT_RAW)
+			ss << stageinfo.main_raw;
+		else
+			throw love::Exception("Unknown shader entry point %d", info.stages[stage]);
+		ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n");
+		ss << code;
+	}
 
 
 	return ss.str();
 	return ss.str();
 }
 }

+ 2 - 1
src/modules/graphics/ShaderStage.cpp

@@ -178,7 +178,8 @@ ShaderStage::ShaderStage(Graphics *gfx, ShaderStageType stage, const std::string
 
 
 		std::string err = "Error validating " + std::string(stagename) + " shader:\n\n"
 		std::string err = "Error validating " + std::string(stagename) + " shader:\n\n"
 			+ std::string(glslangShader->getInfoLog()) + "\n"
 			+ std::string(glslangShader->getInfoLog()) + "\n"
-			+ std::string(glslangShader->getInfoDebugLog());
+			+ std::string(glslangShader->getInfoDebugLog()) + "\n\nShader Code:\n" 
+			+ glsl;
 
 
 		delete glslangShader;
 		delete glslangShader;
 		throw love::Exception("%s", err.c_str());
 		throw love::Exception("%s", err.c_str());

+ 49 - 7
src/modules/graphics/vulkan/Graphics.cpp

@@ -191,6 +191,13 @@ namespace love {
 
 
 			void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
 			void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
 				std::cout << "setViewPortSize ";
 				std::cout << "setViewPortSize ";
+				this->width = width;
+				this->height = height;
+				this->pixelWidth = pixelwidth;
+				this->pixelHeight = pixelheight;
+
+				resetProjection();
+
 				recreateSwapChain();
 				recreateSwapChain();
 			}
 			}
 
 
@@ -323,6 +330,11 @@ namespace love {
 				return new StreamBuffer(vmaAllocator, type, size);
 				return new StreamBuffer(vmaAllocator, type, size);
 			}
 			}
 
 
+			Matrix4 Graphics::computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const { 
+				uint32 flags = DEVICE_PROJECTION_DEFAULT;
+				return calculateDeviceProjection(projection, 0);
+			}
+
 			// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
 			// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
 
 
 			void Graphics::updatedBatchedDrawBuffers() {
 			void Graphics::updatedBatchedDrawBuffers() {
@@ -378,12 +390,42 @@ namespace love {
 			void Graphics::prepareDraw(uint32_t currentImage) {
 			void Graphics::prepareDraw(uint32_t currentImage) {
 				auto& buffer = uniformBuffers.at(currentImage);
 				auto& buffer = uniformBuffers.at(currentImage);
 
 
-				Shader::UniformBufferObject ubo{};
-				ubo.windowWidth = static_cast<float>(swapChainExtent.width);
-				ubo.windowHeight = static_cast<float>(swapChainExtent.height);
+				love::graphics::Shader::BuiltinUniformData data;
+
+				data.transformMatrix = getTransform();
+				data.projectionMatrix = getDeviceProjection();
+
+				// The normal matrix is the transpose of the inverse of the rotation portion
+				// (top-left 3x3) of the transform matrix.
+				{
+					Matrix3 normalmatrix = Matrix3(data.transformMatrix).transposedInverse();
+					const float* e = normalmatrix.getElements();
+					for (int i = 0; i < 3; i++)
+					{
+						data.normalMatrix[i].x = e[i * 3 + 0];
+						data.normalMatrix[i].y = e[i * 3 + 1];
+						data.normalMatrix[i].z = e[i * 3 + 2];
+						data.normalMatrix[i].w = 0.0f;
+					}
+				}
+
+				// Store DPI scale in an unused component of another vector.
+				data.normalMatrix[0].w = (float)getCurrentDPIScale();
+
+				// Same with point size.
+				data.normalMatrix[1].w = getPointSize();
+
+				data.screenSizeParams.x = swapChainExtent.width;
+				data.screenSizeParams.y = swapChainExtent.height;
+
+				data.screenSizeParams.z = 1.0f;
+				data.screenSizeParams.w = 0.0f;
+
+				data.constantColor = getColor();
+				gammaCorrectColor(data.constantColor);
 
 
 				auto mappedInfo = buffer->map(0);
 				auto mappedInfo = buffer->map(0);
-				memcpy(mappedInfo.data, &ubo, sizeof(ubo));
+				memcpy(mappedInfo.data, &data, sizeof(data));
 				buffer->unmap(0);
 				buffer->unmap(0);
 			}
 			}
 
 
@@ -896,7 +938,7 @@ namespace love {
 			}
 			}
 
 
 			void Graphics::createUniformBuffers() {
 			void Graphics::createUniformBuffers() {
-				VkDeviceSize bufferSize = sizeof(Shader::UniformBufferObject);
+				VkDeviceSize bufferSize = sizeof(graphics::Shader::BuiltinUniformData);
 				
 				
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
 					uniformBuffers.push_back(std::make_unique<StreamBuffer>(vmaAllocator, BUFFERUSAGE_UNIFORM, bufferSize));
 					uniformBuffers.push_back(std::make_unique<StreamBuffer>(vmaAllocator, BUFFERUSAGE_UNIFORM, bufferSize));
@@ -953,7 +995,7 @@ namespace love {
 					VkDescriptorBufferInfo bufferInfo{};
 					VkDescriptorBufferInfo bufferInfo{};
 					bufferInfo.buffer = (VkBuffer)uniformBuffers.at(i)->getHandle();
 					bufferInfo.buffer = (VkBuffer)uniformBuffers.at(i)->getHandle();
 					bufferInfo.offset = 0;
 					bufferInfo.offset = 0;
-					bufferInfo.range = sizeof(Shader::UniformBufferObject);
+					bufferInfo.range = sizeof(graphics::Shader::BuiltinUniformData);
 
 
 					VkDescriptorImageInfo imageInfo{};
 					VkDescriptorImageInfo imageInfo{};
 					imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 					imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -1004,7 +1046,7 @@ namespace love {
 
 
 				VkVertexInputBindingDescription texCoordsBindingDescription;
 				VkVertexInputBindingDescription texCoordsBindingDescription;
 				texCoordsBindingDescription.binding = 1;
 				texCoordsBindingDescription.binding = 1;
-				texCoordsBindingDescription.stride = 3 * sizeof(float);	// 2 floats for texture coordinates, 1 float for color
+				texCoordsBindingDescription.stride = sizeof(STf_RGBAub);
 				texCoordsBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
 				texCoordsBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
 
 
 				VkVertexInputAttributeDescription texCoordsInputAttributeDescription;
 				VkVertexInputAttributeDescription texCoordsInputAttributeDescription;

+ 1 - 1
src/modules/graphics/vulkan/Graphics.h

@@ -46,7 +46,7 @@ namespace love {
 				love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) override;
 				love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) override;
 				void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear1 "; }
 				void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear1 "; }
 				void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear2 "; }
 				void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear2 "; }
-				Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override { std::cout << "computeDeviceProjection "; return Matrix4(); }
+				Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override;
 				void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { std::cout << "discard "; }
 				void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { std::cout << "discard "; }
 				void present(void* screenshotCallbackdata) override;
 				void present(void* screenshotCallbackdata) override;
 				void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
 				void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;

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

@@ -40,20 +40,7 @@ namespace love {
 
 
 				void setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) override {}
 				void setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) override {}
 
 
-				struct UniformBufferObject {
-					float windowWidth;
-					float windowHeight;
-				};
-
 			private:
 			private:
-				struct Vec4 {
-					float x, y, z, w;
-				};
-				
-				struct LoveUniformsPerDraw {
-					Vec4 uniformsPerDraw[13];
-				};
-
 				std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
 				std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
 
 
 				std::map<std::string, int> vertexAttributeIndices = {
 				std::map<std::string, int> vertexAttributeIndices = {