From eddde3e6c8d8ea37a724e66dbc82b432ae63df96 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 20 Apr 2019 23:44:33 +1000 Subject: [PATCH] ShaderGen: Use interface blocks when geometry shaders are supported We don't use explicit locations in OpenGL currently, so this breaks when we use alternative names in the geometry shaders. --- .../Core/VideoCommon/FramebufferShaderGen.cpp | 68 ++++++++++++++----- .../VideoCommon/TextureConversionShader.cpp | 22 +++++- .../VideoCommon/TextureConverterShaderGen.cpp | 26 +++++-- 3 files changed, 92 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoCommon/FramebufferShaderGen.cpp b/Source/Core/VideoCommon/FramebufferShaderGen.cpp index de7bdf3ee8..c69f07c10d 100644 --- a/Source/Core/VideoCommon/FramebufferShaderGen.cpp +++ b/Source/Core/VideoCommon/FramebufferShaderGen.cpp @@ -104,10 +104,23 @@ static void EmitVertexMainDeclaration(std::stringstream& ss, u32 num_tex_inputs, << ";\n"; if (position_input) ss << "ATTRIBUTE_LOCATION(" << SHADER_POSITION_ATTRIB << ") in float4 rawpos;\n"; - for (u32 i = 0; i < num_tex_outputs; i++) - ss << "VARYING_LOCATION(" << i << ") out float3 v_tex" << i << ";\n"; - for (u32 i = 0; i < num_color_outputs; i++) - ss << "VARYING_LOCATION(" << (num_tex_inputs + i) << ") out float4 v_col" << i << ";\n"; + + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + ss << "VARYING_LOCATION(0) out VertexData {\n"; + for (u32 i = 0; i < num_tex_outputs; i++) + ss << " float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_color_outputs; i++) + ss << " float4 v_col" << i << ";\n"; + ss << "};\n"; + } + else + { + for (u32 i = 0; i < num_tex_outputs; i++) + ss << "VARYING_LOCATION(" << i << ") out float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_color_outputs; i++) + ss << "VARYING_LOCATION(" << (num_tex_inputs + i) << ") out float4 v_col" << i << ";\n"; + } ss << "#define opos gl_Position\n"; ss << extra_inputs << "\n"; ss << "void main()\n"; @@ -138,10 +151,23 @@ static void EmitPixelMainDeclaration(std::stringstream& ss, u32 num_tex_inputs, case APIType::OpenGL: case APIType::Vulkan: { - for (u32 i = 0; i < num_tex_inputs; i++) - ss << "VARYING_LOCATION(" << i << ") in float3 v_tex" << i << ";\n"; - for (u32 i = 0; i < num_color_inputs; i++) - ss << "VARYING_LOCATION(" << (num_tex_inputs + i) << ") in float4 v_col" << i << ";\n"; + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + ss << "VARYING_LOCATION(0) in VertexData {\n"; + for (u32 i = 0; i < num_tex_inputs; i++) + ss << " in float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_color_inputs; i++) + ss << " in float4 v_col" << i << ";\n"; + ss << "};\n"; + } + else + { + for (u32 i = 0; i < num_tex_inputs; i++) + ss << "VARYING_LOCATION(" << i << ") in float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_color_inputs; i++) + ss << "VARYING_LOCATION(" << (num_tex_inputs + i) << ") in float4 v_col" << i << ";\n"; + } + ss << "FRAGMENT_OUTPUT_LOCATION(0) out " << output_type << " ocol0;\n"; ss << extra_vars << "\n"; ss << "void main()\n"; @@ -218,15 +244,20 @@ std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors) { ss << "layout(triangles) in;\n"; ss << "layout(triangle_strip, max_vertices = 6) out;\n"; - for (u32 i = 0; i < num_tex; i++) + if (num_tex > 0 || num_colors > 0) { - ss << "layout(location = " << i << ") in float3 v_tex" << i << "[];\n"; - ss << "layout(location = " << i << ") out float3 out_tex" << i << ";\n"; - } - for (u32 i = 0; i < num_colors; i++) - { - ss << "layout(location = " << (num_tex + i) << ") in float4 v_col" << i << "[];\n"; - ss << "layout(location = " << (num_tex + i) << ") out float4 out_col" << i << ";\n"; + ss << "VARYING_LOCATION(0) in VertexData {\n"; + for (u32 i = 0; i < num_tex; i++) + ss << " float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_colors; i++) + ss << " float4 v_col" << i << ";\n"; + ss << "} v_in[];\n"; + ss << "VARYING_LOCATION(0) out VertexData {\n"; + for (u32 i = 0; i < num_tex; i++) + ss << " float3 v_tex" << i << ";\n"; + for (u32 i = 0; i < num_colors; i++) + ss << " float4 v_col" << i << ";\n"; + ss << "} v_out;\n"; } ss << "\n"; ss << "void main()\n"; @@ -240,9 +271,10 @@ std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors) { ss << " gl_Position = gl_in[" << v << "].gl_Position;\n"; for (u32 i = 0; i < num_tex; i++) - ss << " out_tex" << i << " = float3(v_tex" << i << "[" << v << "].xy, float(j));\n"; + ss << " v_out.v_tex" << i << " = float3(v_in[" << v << "].v_tex" << i + << ".xy, float(j));\n"; for (u32 i = 0; i < num_colors; i++) - ss << " out_col" << i << " = v_col" << i << "[" << v << "];\n"; + ss << " v_out.v_col" << i << " = v_in[" << v << "].v_col" << i << ";\n"; ss << " EmitVertex();\n\n"; } ss << " EndPrimitive();\n"; diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 29c7cccc1b..69a42e26d5 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -72,7 +72,16 @@ static void WriteHeader(char*& p, APIType ApiType) WRITE(p, " float2 clamp_tb;\n"); WRITE(p, " float3 filter_coefficients;\n"); WRITE(p, "};\n"); - WRITE(p, "VARYING_LOCATION(0) in float3 v_tex0;\n"); + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + WRITE(p, "VARYING_LOCATION(0) in VertexData {\n"); + WRITE(p, " float3 v_tex0;\n"); + WRITE(p, "};\n"); + } + else + { + WRITE(p, "VARYING_LOCATION(0) in float3 v_tex0;\n"); + } WRITE(p, "SAMPLER_BINDING(0) uniform sampler2DArray samp0;\n"); WRITE(p, "FRAGMENT_OUTPUT_LOCATION(0) out float4 ocol0;\n"); } @@ -1510,7 +1519,16 @@ float4 DecodePixel(int val) } else { - ss << "VARYING_LOCATION(0) in float3 v_tex0;\n"; + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + ss << "VARYING_LOCATION(0) in VertexData {\n"; + ss << " float3 v_tex0;\n"; + ss << "};\n"; + } + else + { + ss << "VARYING_LOCATION(0) in float3 v_tex0;\n"; + } ss << "FRAGMENT_OUTPUT_LOCATION(0) out float4 ocol0;\n"; ss << "void main() {\n"; ss << " float3 coords = v_tex0;\n"; diff --git a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp index 15de7ba9a7..df46254d91 100644 --- a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp +++ b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp @@ -67,8 +67,17 @@ ShaderCode GenerateVertexShader(APIType api_type) } else if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) { - out.Write("VARYING_LOCATION(0) out float3 v_tex0;\n" - "#define id gl_VertexID\n" + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + out.Write("VARYING_LOCATION(0) out VertexData {\n"); + out.Write(" float3 v_tex0;\n"); + out.Write("};\n"); + } + else + { + out.Write("VARYING_LOCATION(0) out float3 v_tex0;\n"); + } + out.Write("#define id gl_VertexID\n" "#define opos gl_Position\n" "void main() {\n"); } @@ -112,8 +121,17 @@ ShaderCode GeneratePixelShader(APIType api_type, const UidData* uid_data) "clamp_tb.x, clamp_tb.y), %s));\n" "}\n", mono_depth ? "0.0" : "uv.z"); - out.Write("VARYING_LOCATION(0) in vec3 v_tex0;\n" - "FRAGMENT_OUTPUT_LOCATION(0) out vec4 ocol0;" + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + out.Write("VARYING_LOCATION(0) in VertexData {\n"); + out.Write(" float3 v_tex0;\n"); + out.Write("};\n"); + } + else + { + out.Write("VARYING_LOCATION(0) in vec3 v_tex0;\n"); + } + out.Write("FRAGMENT_OUTPUT_LOCATION(0) out vec4 ocol0;" "void main()\n{\n"); }