From e8c500ceeff6c3c662aefbc8606221b5815d8336 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 5 Nov 2020 22:55:44 +0100 Subject: [PATCH] GLSL: Fix support for textureLod in legacy vertex shaders --- .../legacy/fragment/explicit-lod.legacy.vert | 11 +++ .../legacy/vert/implicit-lod.legacy.vert | 2 +- .../legacy/fragment/explicit-lod.legacy.vert | 11 +++ .../legacy/vert/implicit-lod.legacy.vert | 2 +- .../legacy/fragment/explicit-lod.legacy.vert | 12 +++ spirv_glsl.cpp | 91 ++++++------------- spirv_glsl.hpp | 1 - 7 files changed, 62 insertions(+), 68 deletions(-) create mode 100644 reference/opt/shaders/legacy/fragment/explicit-lod.legacy.vert create mode 100644 reference/shaders/legacy/fragment/explicit-lod.legacy.vert create mode 100644 shaders/legacy/fragment/explicit-lod.legacy.vert diff --git a/reference/opt/shaders/legacy/fragment/explicit-lod.legacy.vert b/reference/opt/shaders/legacy/fragment/explicit-lod.legacy.vert new file mode 100644 index 00000000..b73faa47 --- /dev/null +++ b/reference/opt/shaders/legacy/fragment/explicit-lod.legacy.vert @@ -0,0 +1,11 @@ +#version 100 + +uniform mediump sampler2D tex; + +varying mediump vec4 FragColor; + +void main() +{ + FragColor = texture2DLod(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625), 3.0); +} + diff --git a/reference/opt/shaders/legacy/vert/implicit-lod.legacy.vert b/reference/opt/shaders/legacy/vert/implicit-lod.legacy.vert index 6e441074..2d205049 100644 --- a/reference/opt/shaders/legacy/vert/implicit-lod.legacy.vert +++ b/reference/opt/shaders/legacy/vert/implicit-lod.legacy.vert @@ -4,6 +4,6 @@ uniform mediump sampler2D tex; void main() { - gl_Position = texture2D(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625)); + gl_Position = texture2DLod(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625), 0.0); } diff --git a/reference/shaders/legacy/fragment/explicit-lod.legacy.vert b/reference/shaders/legacy/fragment/explicit-lod.legacy.vert new file mode 100644 index 00000000..b73faa47 --- /dev/null +++ b/reference/shaders/legacy/fragment/explicit-lod.legacy.vert @@ -0,0 +1,11 @@ +#version 100 + +uniform mediump sampler2D tex; + +varying mediump vec4 FragColor; + +void main() +{ + FragColor = texture2DLod(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625), 3.0); +} + diff --git a/reference/shaders/legacy/vert/implicit-lod.legacy.vert b/reference/shaders/legacy/vert/implicit-lod.legacy.vert index 6e441074..2d205049 100644 --- a/reference/shaders/legacy/vert/implicit-lod.legacy.vert +++ b/reference/shaders/legacy/vert/implicit-lod.legacy.vert @@ -4,6 +4,6 @@ uniform mediump sampler2D tex; void main() { - gl_Position = texture2D(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625)); + gl_Position = texture2DLod(tex, vec2(0.4000000059604644775390625, 0.60000002384185791015625), 0.0); } diff --git a/shaders/legacy/fragment/explicit-lod.legacy.vert b/shaders/legacy/fragment/explicit-lod.legacy.vert new file mode 100644 index 00000000..d2cbd5a4 --- /dev/null +++ b/shaders/legacy/fragment/explicit-lod.legacy.vert @@ -0,0 +1,12 @@ +#version 310 es + +precision mediump float; + +layout(binding = 0) uniform sampler2D tex; + +layout(location = 0) out vec4 FragColor; + +void main() +{ + FragColor = textureLod(tex, vec2(0.4, 0.6), 3.0); +} diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 712f5e5c..695e986f 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -5641,25 +5641,6 @@ void CompilerGLSL::emit_bitfield_insert_op(uint32_t result_type, uint32_t result inherit_expression_dependencies(result_id, op3); } -// EXT_shader_texture_lod only concerns fragment shaders so lod tex functions -// are not allowed in ES 2 vertex shaders. But SPIR-V only supports lod tex -// functions in vertex shaders so we revert those back to plain calls when -// the lod is a constant value of zero. -bool CompilerGLSL::check_explicit_lod_allowed(uint32_t lod) -{ - auto &execution = get_entry_point(); - bool allowed = !is_legacy_es() || execution.model == ExecutionModelFragment; - if (!allowed && lod != 0) - { - auto *lod_constant = maybe_get(lod); - if (!lod_constant || lod_constant->scalar_f32() != 0.0f) - { - SPIRV_CROSS_THROW("Explicit lod not allowed in legacy ES non-fragment shaders."); - } - } - return allowed; -} - string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t tex) { const char *type; @@ -5691,16 +5672,19 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp break; } - bool use_explicit_lod = check_explicit_lod_allowed(lod); - - if (op == "textureLod" || op == "textureProjLod" || op == "textureGrad" || op == "textureProjGrad") + // In legacy GLSL, an extension is required for textureLod in the fragment + // shader or textureGrad anywhere. + bool legacy_lod_ext = false; + auto &execution = get_entry_point(); + if (op == "textureGrad" || op == "textureProjGrad" || + ((op == "textureLod" || op == "textureProjLod") && execution.model != ExecutionModelVertex)) { if (is_legacy_es()) { - if (use_explicit_lod) - require_extension_internal("GL_EXT_shader_texture_lod"); + legacy_lod_ext = true; + require_extension_internal("GL_EXT_shader_texture_lod"); } - else if (is_legacy()) + else if (is_legacy_desktop()) require_extension_internal("GL_ARB_shader_texture_lod"); } @@ -5729,40 +5713,20 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp if (op == "texture") return is_es_and_depth ? join(type_prefix, type, "EXT") : join(type_prefix, type); else if (op == "textureLod") - { - if (use_explicit_lod) - return join(type_prefix, type, is_legacy_es() ? "LodEXT" : "Lod"); - else - return join(type_prefix, type); - } + return join(type_prefix, type, legacy_lod_ext ? "LodEXT" : "Lod"); else if (op == "textureProj") return join(type_prefix, type, is_es_and_depth ? "ProjEXT" : "Proj"); else if (op == "textureGrad") return join(type_prefix, type, is_legacy_es() ? "GradEXT" : is_legacy_desktop() ? "GradARB" : "Grad"); else if (op == "textureProjLod") - { - if (use_explicit_lod) - return join(type_prefix, type, is_legacy_es() ? "ProjLodEXT" : "ProjLod"); - else - return join(type_prefix, type, "Proj"); - } + return join(type_prefix, type, legacy_lod_ext ? "ProjLodEXT" : "ProjLod"); else if (op == "textureLodOffset") - { - if (use_explicit_lod) - return join(type_prefix, type, "LodOffset"); - else - return join(type_prefix, type); - } + return join(type_prefix, type, "LodOffset"); else if (op == "textureProjGrad") return join(type_prefix, type, is_legacy_es() ? "ProjGradEXT" : is_legacy_desktop() ? "ProjGradARB" : "ProjGrad"); else if (op == "textureProjLodOffset") - { - if (use_explicit_lod) - return join(type_prefix, type, "ProjLodOffset"); - else - return join(type_prefix, type, "ProjOffset"); - } + return join(type_prefix, type, "ProjLodOffset"); else { SPIRV_CROSS_THROW(join("Unsupported legacy texture op: ", op)); @@ -6632,23 +6596,20 @@ string CompilerGLSL::to_function_args(const TextureFunctionArguments &args, bool } else { - if (check_explicit_lod_allowed(args.lod)) + forward = forward && should_forward(args.lod); + farg_str += ", "; + + auto &lod_expr_type = expression_type(args.lod); + + // Lod expression for TexelFetch in GLSL must be int, and only int. + if (args.base.is_fetch && imgtype.image.dim != DimBuffer && !imgtype.image.ms && + lod_expr_type.basetype != SPIRType::Int) { - forward = forward && should_forward(args.lod); - farg_str += ", "; - - auto &lod_expr_type = expression_type(args.lod); - - // Lod expression for TexelFetch in GLSL must be int, and only int. - if (args.base.is_fetch && imgtype.image.dim != DimBuffer && !imgtype.image.ms && - lod_expr_type.basetype != SPIRType::Int) - { - farg_str += join("int(", to_expression(args.lod), ")"); - } - else - { - farg_str += to_expression(args.lod); - } + farg_str += join("int(", to_expression(args.lod), ")"); + } + else + { + farg_str += to_expression(args.lod); } } } diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index d52f786e..78ba10bc 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -750,7 +750,6 @@ protected: void replace_fragment_output(SPIRVariable &var); void replace_fragment_outputs(); - bool check_explicit_lod_allowed(uint32_t lod); std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id); uint32_t indent = 0;