From 6aa1bf7b6ff86bb7325e5b50709ddf5477b1e855 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 12 Jun 2021 20:14:56 -0400 Subject: [PATCH] glsl: Implement legacy varyings --- .../backend/glsl/emit_context.cpp | 43 ++++++++++++++++++- .../backend/glsl/emit_context.h | 2 +- .../backend/glsl/emit_glsl.cpp | 2 +- .../glsl/emit_glsl_context_get_set.cpp | 31 +++++++++++-- .../ir_opt/collect_shader_info_pass.cpp | 9 +++- src/shader_recompiler/shader_info.h | 2 + 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index ed10eca8a8..f0e9dffc28 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp @@ -200,6 +200,27 @@ std::string_view OutputPrimitive(OutputTopology topology) { throw InvalidArgument("Invalid output topology {}", topology); } +void SetupLegacyOutPerVertex(EmitContext& ctx, std::string& header) { + if (!ctx.info.stores_legacy_varyings) { + return; + } + if (ctx.info.stores_fixed_fnc_textures) { + header += "vec4 gl_TexCoord[8];"; + } + if (ctx.info.stores_color_front_diffuse) { + header += "vec4 gl_FrontColor;"; + } + if (ctx.info.stores_color_front_specular) { + header += "vec4 gl_FrontSecondaryColor;"; + } + if (ctx.info.stores_color_back_diffuse) { + header += "vec4 gl_BackColor;"; + } + if (ctx.info.stores_color_back_specular) { + header += "vec4 gl_BackSecondaryColor;"; + } +} + void SetupOutPerVertex(EmitContext& ctx, std::string& header) { if (!StoresPerVertexAttributes(ctx.stage)) { return; @@ -215,18 +236,34 @@ void SetupOutPerVertex(EmitContext& ctx, std::string& header) { ctx.stage != Stage::Geometry) { header += "int gl_ViewportIndex;"; } + SetupLegacyOutPerVertex(ctx, header); header += "};"; if (ctx.info.stores_viewport_index && ctx.stage == Stage::Geometry) { header += "out int gl_ViewportIndex;"; } } + +void SetupLegacyInPerFragment(EmitContext& ctx, std::string& header) { + if (!ctx.info.loads_legacy_varyings) { + return; + } + header += "in gl_PerFragment{"; + if (ctx.info.loads_fixed_fnc_textures) { + header += "vec4 gl_TexCoord[8];"; + } + if (ctx.info.loads_color_front_diffuse) { + header += "vec4 gl_Color;"; + } + header += "};"; +} + } // Anonymous namespace EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, const RuntimeInfo& runtime_info_) : info{program.info}, profile{profile_}, runtime_info{runtime_info_} { header += "#pragma optionNV(fastmath off)\n"; - SetupExtensions(header); + SetupExtensions(); stage = program.stage; switch (program.stage) { case Stage::VertexA: @@ -271,6 +308,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile break; } SetupOutPerVertex(*this, header); + SetupLegacyInPerFragment(*this, header); + for (size_t index = 0; index < info.input_generics.size(); ++index) { const auto& generic{info.input_generics[index]}; if (generic.used) { @@ -306,7 +345,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile DefineConstants(); } -void EmitContext::SetupExtensions(std::string&) { +void EmitContext::SetupExtensions() { if (profile.support_gl_texture_shadow_lod) { header += "#extension GL_EXT_texture_shadow_lod : enable\n"; } diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h index 685f560893..8fa87c02cb 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.h +++ b/src/shader_recompiler/backend/glsl/emit_context.h @@ -157,7 +157,7 @@ public: bool uses_cc_carry{}; private: - void SetupExtensions(std::string& header); + void SetupExtensions(); void DefineConstantBuffers(Bindings& bindings); void DefineStorageBuffers(Bindings& bindings); void DefineGenericOutput(size_t index, u32 invocations); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index 3e6add7cda..d76b63b2d3 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -166,7 +166,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { } std::string GlslVersionSpecifier(const EmitContext& ctx) { - if (ctx.uses_y_direction) { + if (ctx.uses_y_direction || ctx.info.stores_legacy_varyings) { return " compatibility"; } return ""; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index 96296ad281..3eeccfb3c0 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp @@ -98,6 +98,10 @@ void GetCbuf16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const bit_offset); } } + +u32 TexCoordIndex(IR::Attribute attr) { + return (static_cast(attr) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4; +} } // Anonymous namespace void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, @@ -178,6 +182,17 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ctx.AddF32("{}=in_attr{}{}.{};", inst, index, InputVertexIndex(ctx, vertex), swizzle); return; } + // GLSL only exposes 8 legacy texcoords + if (attr >= IR::Attribute::FixedFncTexture8S && attr <= IR::Attribute::FixedFncTexture9Q) { + // LOG_WARNING(..., "GLSL does not allow access to gl_TexCoord[{}]", TexCoordIndex(attr)); + ctx.AddF32("{}=0.f;", inst); + return; + } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture7Q) { + const u32 index{TexCoordIndex(attr)}; + ctx.AddF32("{}=gl_TexCoord[{}].{};", inst, index, swizzle); + return; + } switch (attr) { case IR::Attribute::PrimitiveId: ctx.AddF32("{}=itof(gl_PrimitiveID);", inst); @@ -227,19 +242,29 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val [[maybe_unused]] std::string_view vertex) { if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - const u32 element{IR::GenericAttributeElement(attr)}; - const GenericElementInfo& info{ctx.output_generics.at(index).at(element)}; + const u32 attr_element{IR::GenericAttributeElement(attr)}; + const GenericElementInfo& info{ctx.output_generics.at(index).at(attr_element)}; const auto output_decorator{OutputVertexIndex(ctx)}; if (info.num_components == 1) { ctx.Add("{}{}={};", info.name, output_decorator, value); } else { - const u32 index_element{element - info.first_element}; + const u32 index_element{attr_element - info.first_element}; ctx.Add("{}{}.{}={};", info.name, output_decorator, "xyzw"[index_element], value); } return; } const u32 element{static_cast(attr) % 4}; const char swizzle{"xyzw"[element]}; + // GLSL only exposes 8 legacy texcoords + if (attr >= IR::Attribute::FixedFncTexture8S && attr <= IR::Attribute::FixedFncTexture9Q) { + // LOG_WARNING(..., "GLSL does not allow access to gl_TexCoord[{}]", TexCoordIndex(attr)); + return; + } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture7Q) { + const u32 index{TexCoordIndex(attr)}; + ctx.Add("gl_TexCoord[{}].{}={};", index, swizzle, value); + return; + } switch (attr) { case IR::Attribute::Layer: if (ctx.stage != Stage::Geometry && diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index dc78cdefb7..10d2822ae2 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -35,6 +35,7 @@ void GetAttribute(Info& info, IR::Attribute attr) { } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { info.loads_fixed_fnc_textures = true; + info.loads_legacy_varyings = true; return; } switch (attr) { @@ -52,6 +53,7 @@ void GetAttribute(Info& info, IR::Attribute attr) { case IR::Attribute::ColorFrontDiffuseB: case IR::Attribute::ColorFrontDiffuseA: info.loads_color_front_diffuse = true; + info.loads_legacy_varyings = true; break; case IR::Attribute::PointSpriteS: case IR::Attribute::PointSpriteT: @@ -82,6 +84,7 @@ void SetAttribute(Info& info, IR::Attribute attr) { } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { info.stores_fixed_fnc_textures = true; + info.stores_legacy_varyings = true; return; } switch (attr) { @@ -105,24 +108,28 @@ void SetAttribute(Info& info, IR::Attribute attr) { case IR::Attribute::ColorFrontDiffuseB: case IR::Attribute::ColorFrontDiffuseA: info.stores_color_front_diffuse = true; + info.stores_legacy_varyings = true; break; case IR::Attribute::ColorFrontSpecularR: case IR::Attribute::ColorFrontSpecularG: case IR::Attribute::ColorFrontSpecularB: case IR::Attribute::ColorFrontSpecularA: info.stores_color_front_specular = true; + info.stores_legacy_varyings = true; break; case IR::Attribute::ColorBackDiffuseR: case IR::Attribute::ColorBackDiffuseG: case IR::Attribute::ColorBackDiffuseB: case IR::Attribute::ColorBackDiffuseA: info.stores_color_back_diffuse = true; + info.stores_legacy_varyings = true; break; case IR::Attribute::ColorBackSpecularR: case IR::Attribute::ColorBackSpecularG: case IR::Attribute::ColorBackSpecularB: case IR::Attribute::ColorBackSpecularA: - info.stores_color_front_specular = true; + info.stores_color_back_specular = true; + info.stores_legacy_varyings = true; break; case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance1: diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 9f7f0b42c3..7536c9caf8 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -128,6 +128,7 @@ struct Info { bool loads_instance_id{}; bool loads_vertex_id{}; bool loads_front_face{}; + bool loads_legacy_varyings{}; bool loads_tess_coord{}; @@ -150,6 +151,7 @@ struct Info { bool stores_clip_distance{}; bool stores_fog_coordinate{}; bool stores_viewport_mask{}; + bool stores_legacy_varyings{}; bool stores_tess_level_outer{}; bool stores_tess_level_inner{};