From c996860602d44be16e3e61bdc7cf74d0cc83ca61 Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 13 Jun 2022 16:50:12 +0200 Subject: [PATCH] =?UTF-8?q?Use=20l=C3=B6ve's=20uniform=20data=20object=20f?= =?UTF-8?q?or=20vulkan=20shader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/runtime.h | 3 +- src/modules/graphics/Shader.cpp | 95 ++++++++++++------------ src/modules/graphics/ShaderStage.cpp | 3 +- src/modules/graphics/vulkan/Graphics.cpp | 56 ++++++++++++-- src/modules/graphics/vulkan/Graphics.h | 2 +- src/modules/graphics/vulkan/Shader.h | 13 ---- 6 files changed, 101 insertions(+), 71 deletions(-) diff --git a/src/common/runtime.h b/src/common/runtime.h index 4592e7bec..6f3dee5ae 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -673,7 +673,8 @@ int luax_catchexcept(lua_State *L, const T& func) catch (const std::exception &e) { should_error = true; - lua_pushstring(L, e.what()); + const char* msg = e.what(); + lua_pushstring(L, msg); } if (should_error) diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index f66f344a7..76ab1ada9 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -94,7 +94,7 @@ static const char global_syntax[] = R"( static const char render_uniforms[] = R"( #ifdef USE_VULKAN - VULKAN_BINDING(0) uniform LoveUniformsPerDraw { + layout(binding=0) uniform LoveUniformsPerDraw { vec4 uniformsPerDraw[13]; } udp; #define love_UniformsPerDraw udp.uniformsPerDraw @@ -433,25 +433,20 @@ void main() { )"; static const char vulkan_vert[] = R"( -#version 450 - layout(location = 0) in vec2 inPosition; layout(location = 1) in vec2 iTexCoords; layout(location = 0) out vec4 fragColor; 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() { - 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); texCoords = iTexCoords; @@ -459,8 +454,6 @@ void main() { )"; static const char vulkan_pixel[] = R"( -#version 450 - layout(location = 0) in vec4 fragColor; layout(location = 1) in vec2 texCoords; @@ -617,47 +610,53 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage, if (glsl1on3) lang = LANGUAGE_GLSL3; - if (info.vulkan) { - if (stage == SHADERSTAGE_VERTEX) { - return love::graphics::glsl::vulkan_vert; - } - if (stage == SHADERSTAGE_PIXEL) { - return 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"; + if (info.vulkan) { + ss << "#version 450\n"; + ss << "#define LOVE_HIGHP_OR_MEDIUMP highp\n"; + ss << "#define USE_VULKAN 1\n"; + ss << stageinfo.uniforms; - for (const auto &def : options.defines) - ss << "#define " + def.first + " " + def.second + "\n"; + if (stage == SHADERSTAGE_VERTEX) { + ss << love::graphics::glsl::vulkan_vert; + } + if (stage == SHADERSTAGE_PIXEL) { + ss << love::graphics::glsl::vulkan_pixel; + } + } + 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"; - ss << glsl::global_syntax; - ss << stageinfo.header; - ss << stageinfo.uniforms; - ss << glsl::global_functions; - ss << stageinfo.functions; + for (const auto &def : options.defines) + ss << "#define " + def.first + " " + def.second + "\n"; - 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; + 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(); } diff --git a/src/modules/graphics/ShaderStage.cpp b/src/modules/graphics/ShaderStage.cpp index 352604f0c..650e5f966 100644 --- a/src/modules/graphics/ShaderStage.cpp +++ b/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(glslangShader->getInfoLog()) + "\n" - + std::string(glslangShader->getInfoDebugLog()); + + std::string(glslangShader->getInfoDebugLog()) + "\n\nShader Code:\n" + + glsl; delete glslangShader; throw love::Exception("%s", err.c_str()); diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index b0d1ac3b8..cf2777257 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -191,6 +191,13 @@ namespace love { void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) { std::cout << "setViewPortSize "; + this->width = width; + this->height = height; + this->pixelWidth = pixelwidth; + this->pixelHeight = pixelheight; + + resetProjection(); + recreateSwapChain(); } @@ -323,6 +330,11 @@ namespace love { 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 void Graphics::updatedBatchedDrawBuffers() { @@ -378,12 +390,42 @@ namespace love { void Graphics::prepareDraw(uint32_t currentImage) { auto& buffer = uniformBuffers.at(currentImage); - Shader::UniformBufferObject ubo{}; - ubo.windowWidth = static_cast(swapChainExtent.width); - ubo.windowHeight = static_cast(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); - memcpy(mappedInfo.data, &ubo, sizeof(ubo)); + memcpy(mappedInfo.data, &data, sizeof(data)); buffer->unmap(0); } @@ -896,7 +938,7 @@ namespace love { } 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++) { uniformBuffers.push_back(std::make_unique(vmaAllocator, BUFFERUSAGE_UNIFORM, bufferSize)); @@ -953,7 +995,7 @@ namespace love { VkDescriptorBufferInfo bufferInfo{}; bufferInfo.buffer = (VkBuffer)uniformBuffers.at(i)->getHandle(); bufferInfo.offset = 0; - bufferInfo.range = sizeof(Shader::UniformBufferObject); + bufferInfo.range = sizeof(graphics::Shader::BuiltinUniformData); VkDescriptorImageInfo imageInfo{}; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -1004,7 +1046,7 @@ namespace love { VkVertexInputBindingDescription texCoordsBindingDescription; 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; VkVertexInputAttributeDescription texCoordsInputAttributeDescription; diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 3d325d362..f89ed6bda 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/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& 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(const std::vector& 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& colorbuffers, bool depthstencil) override { std::cout << "discard "; } void present(void* screenshotCallbackdata) override; void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 5b5c1aca1..479866618 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -40,20 +40,7 @@ namespace love { void setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) override {} - struct UniformBufferObject { - float windowWidth; - float windowHeight; - }; - private: - struct Vec4 { - float x, y, z, w; - }; - - struct LoveUniformsPerDraw { - Vec4 uniformsPerDraw[13]; - }; - std::vector shaderStages; std::map vertexAttributeIndices = {