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

This commit is contained in:
niki
2022-06-13 16:50:12 +02:00
parent 12b9978173
commit c996860602
6 changed files with 101 additions and 71 deletions
+47 -48
View File
@@ -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();
}
+2 -1
View File
@@ -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());
+49 -7
View File
@@ -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<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);
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<StreamBuffer>(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;
+1 -1
View File
@@ -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;
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 "; }
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 present(void* screenshotCallbackdata) override;
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
-13
View File
@@ -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<VkPipelineShaderStageCreateInfo> shaderStages;
std::map<std::string, int> vertexAttributeIndices = {