From d9c034e8ccaad6db870df765e01d5963af84c9c5 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 13 Aug 2016 00:40:18 +1000 Subject: [PATCH] ShaderGen: Specify attribute/output locations/bindings explicitly This also shifts the SSBO index from index 3 to index 0. --- Source/Core/VideoBackends/OGL/BoundingBox.cpp | 2 +- .../VideoBackends/OGL/ProgramShaderCache.cpp | 21 +++++++++++-- Source/Core/VideoCommon/GeometryShaderGen.cpp | 7 ++--- Source/Core/VideoCommon/PixelShaderGen.cpp | 30 +++++++++---------- .../VideoCommon/TextureConversionShader.cpp | 2 +- Source/Core/VideoCommon/VertexShaderGen.cpp | 25 ++++++++-------- 6 files changed, 50 insertions(+), 37 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/BoundingBox.cpp b/Source/Core/VideoBackends/OGL/BoundingBox.cpp index 7ec094f9f2..fdc449442c 100644 --- a/Source/Core/VideoBackends/OGL/BoundingBox.cpp +++ b/Source/Core/VideoBackends/OGL/BoundingBox.cpp @@ -23,7 +23,7 @@ void BoundingBox::Init() glGenBuffers(1, &s_bbox_buffer_id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id); glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(s32), initial_values, GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, s_bbox_buffer_id); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, s_bbox_buffer_id); } } diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index ca622f7eb0..599f783cef 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -554,7 +554,8 @@ void ProgramShaderCache::CreateHeader() "%s\n" // early-z "%s\n" // 420pack "%s\n" // msaa - "%s\n" // Sampler binding + "%s\n" // Input/output/sampler binding + "%s\n" // Varying location "%s\n" // storage buffer "%s\n" // shader5 "%s\n" // SSAA @@ -595,9 +596,23 @@ void ProgramShaderCache::CreateHeader() (g_ogl_config.bSupportsMSAA && v < GLSL_150) ? "#extension GL_ARB_texture_multisample : enable" : "", + // Attribute and fragment output bindings are still done via glBindAttribLocation and + // glBindFragDataLocation. In the future this could be moved to the layout qualifier + // in GLSL, but requires verification of GL_ARB_explicit_attrib_location. g_ActiveConfig.backend_info.bSupportsBindingLayout ? - "#define SAMPLER_BINDING(x) layout(binding = x)" : - "#define SAMPLER_BINDING(x)", + "#define ATTRIBUTE_LOCATION(x)\n" + "#define FRAGMENT_OUTPUT_LOCATION(x)\n" + "#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n" + "#define UBO_BINDING(packing, x) layout(packing, binding = x)\n" + "#define SAMPLER_BINDING(x) layout(binding = x)\n" + "#define SSBO_BINDING(x) layout(binding = x)\n" : + "#define ATTRIBUTE_LOCATION(x)\n" + "#define FRAGMENT_OUTPUT_LOCATION(x)\n" + "#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n" + "#define UBO_BINDING(packing, x) layout(packing)\n" + "#define SAMPLER_BINDING(x)\n", + // Input/output blocks are matched by name during program linking + "#define VARYING_LOCATION(x)\n", !is_glsles && g_ActiveConfig.backend_info.bSupportsBBox ? "#extension GL_ARB_shader_storage_buffer_object : enable" : "", diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 83b30943bc..6aefdf3e69 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -78,8 +78,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid // uniforms if (ApiType == APIType::OpenGL) - out.Write("layout(std140%s) uniform GSBlock {\n", - g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 3" : ""); + out.Write("UBO_BINDING(std140, 3) uniform GSBlock {\n"); else out.Write("cbuffer GSBlock {\n"); out.Write("\tfloat4 " I_STEREOPARAMS ";\n" @@ -97,13 +96,13 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid if (g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("#define InstanceID gl_InvocationID\n"); - out.Write("in VertexData {\n"); + out.Write("VARYING_LOCATION(0) in VertexData {\n"); GenerateVSOutputMembers( out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true)); out.Write("} vs[%d];\n", vertex_in); - out.Write("out VertexData {\n"); + out.Write("VARYING_LOCATION(0) out VertexData {\n"); GenerateVSOutputMembers( out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true)); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 13d6bdd13e..65722fb7d4 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -394,14 +394,10 @@ ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, APIType ApiType, out.Write("\n"); if (ApiType == APIType::OpenGL) - { - out.Write("layout(std140%s) uniform PSBlock {\n", - g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 1" : ""); - } + out.Write("UBO_BINDING(std140, 1) uniform PSBlock {\n"); else - { out.Write("cbuffer PSBlock : register(b0) {\n"); - } + out.Write("\tint4 " I_COLORS "[4];\n" "\tint4 " I_KCOLORS "[4];\n" "\tint4 " I_ALPHA ";\n" @@ -421,14 +417,10 @@ ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, APIType ApiType, out.Write("%s", s_lighting_struct); if (ApiType == APIType::OpenGL) - { - out.Write("layout(std140%s) uniform VSBlock {\n", - g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : ""); - } + out.Write("UBO_BINDING(std140, 2) uniform VSBlock {\n"); else - { out.Write("cbuffer VSBlock : register(b1) {\n"); - } + out.Write(s_shader_uniforms); out.Write("};\n"); } @@ -437,7 +429,7 @@ ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, APIType ApiType, { if (ApiType == APIType::OpenGL) { - out.Write("layout(std140, binding = 3) buffer BBox {\n" + out.Write("SSBO_BINDING(0) buffer BBox {\n" "\tint4 bbox_data;\n" "};\n"); } @@ -512,16 +504,22 @@ ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, APIType ApiType, if (ApiType == APIType::OpenGL) { - out.Write("out vec4 ocol0;\n"); if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND) - out.Write("out vec4 ocol1;\n"); + { + out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0) out vec4 ocol0;\n"); + out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1) out vec4 ocol1;\n"); + } + else + { + out.Write("FRAGMENT_OUTPUT_LOCATION(0) out vec4 ocol0;\n"); + } if (uid_data->per_pixel_depth) out.Write("#define depth gl_FragDepth\n"); if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { - out.Write("in VertexData {\n"); + out.Write("VARYING_LOCATION(0) in VertexData {\n"); GenerateVSOutputMembers( out, ApiType, uid_data->genMode_numtexgens, uid_data->per_pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true)); diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index cccb7e7334..16ea016675 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -92,7 +92,7 @@ static void WriteSwizzler(char*& p, u32 format, APIType ApiType) WRITE(p, "#define samp0 samp9\n"); WRITE(p, "SAMPLER_BINDING(9) uniform sampler2DArray samp0;\n"); - WRITE(p, " out vec4 ocol0;\n"); + WRITE(p, "FRAGMENT_OUTPUT_LOCATION(0) out vec4 ocol0;\n"); WRITE(p, "void main()\n"); WRITE(p, "{\n" " int2 sampleUv;\n" diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 8376d6b8ea..e7748bd1ae 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -86,8 +86,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // uniforms if (api_type == APIType::OpenGL) - out.Write("layout(std140%s) uniform VSBlock {\n", - g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : ""); + out.Write("UBO_BINDING(std140, 2) uniform VSBlock {\n"); else out.Write("cbuffer VSBlock {\n"); out.Write(s_shader_uniforms); @@ -99,32 +98,34 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da if (api_type == APIType::OpenGL) { - out.Write("in float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float4 rawpos;\n", SHADER_POSITION_ATTRIB); if (uid_data->components & VB_HAS_POSMTXIDX) - out.Write("in int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in int posmtx;\n", SHADER_POSMTX_ATTRIB); if (uid_data->components & VB_HAS_NRM0) - out.Write("in float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float3 rawnorm0;\n", SHADER_NORM0_ATTRIB); if (uid_data->components & VB_HAS_NRM1) - out.Write("in float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float3 rawnorm1;\n", SHADER_NORM1_ATTRIB); if (uid_data->components & VB_HAS_NRM2) - out.Write("in float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float3 rawnorm2;\n", SHADER_NORM2_ATTRIB); if (uid_data->components & VB_HAS_COL0) - out.Write("in float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float4 color0;\n", SHADER_COLOR0_ATTRIB); if (uid_data->components & VB_HAS_COL1) - out.Write("in float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB); + out.Write("ATTRIBUTE_LOCATION(%d) in float4 color1;\n", SHADER_COLOR1_ATTRIB); for (int i = 0; i < 8; ++i) { u32 hastexmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i)); if ((uid_data->components & (VB_HAS_UV0 << i)) || hastexmtx) - out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, - SHADER_TEXTURE0_ATTRIB + i); + { + out.Write("ATTRIBUTE_LOCATION(%d) in float%d tex%d;\n", SHADER_TEXTURE0_ATTRIB + i, + hastexmtx ? 3 : 2, i); + } } if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { - out.Write("out VertexData {\n"); + out.Write("VARYING_LOCATION(0) out VertexData {\n"); GenerateVSOutputMembers( out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true));