From 4d42f681c53c8989309571818a174b0428ec4adc Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Wed, 21 Aug 2019 09:30:54 -0400 Subject: [PATCH] GLSL: Implement texldl instruction --- profiles/mojoshader_profile.h | 4 +- profiles/mojoshader_profile_glsl.c | 115 +++++++++++++++++++---------- 2 files changed, 79 insertions(+), 40 deletions(-) diff --git a/profiles/mojoshader_profile.h b/profiles/mojoshader_profile.h index 1fada766..34bcd6b3 100644 --- a/profiles/mojoshader_profile.h +++ b/profiles/mojoshader_profile.h @@ -158,7 +158,7 @@ typedef struct Context // !!! FIXME: move these into SUPPORT_PROFILE sections. int glsl_generated_lit_helper; - int glsl_generated_texldd_setup; + int glsl_generated_texlod_setup; int glsl_generated_texm3x3spec_helper; int arb1_wrote_position; // !!! FIXME: move these into SUPPORT_PROFILE sections. @@ -362,4 +362,4 @@ const char *get_D3D_varname_in_buf(Context *ctx, RegisterType rt, const size_t len); const char *get_D3D_varname(Context *ctx, RegisterType rt, int regnum); -#endif \ No newline at end of file +#endif diff --git a/profiles/mojoshader_profile_glsl.c b/profiles/mojoshader_profile_glsl.c index d473f7b4..8648d7d6 100644 --- a/profiles/mojoshader_profile_glsl.c +++ b/profiles/mojoshader_profile_glsl.c @@ -467,6 +467,45 @@ const char *get_GLSL_comparison_string_vector(Context *ctx) return comps[ctx->instruction_controls]; } // get_GLSL_comparison_string_vector +// special extensions needed for texldd/texldl... + +static void prepend_glsl_texlod_extensions(Context *ctx) +{ + // !!! FIXME: + // GLSL 1.30 introduced textureGrad() for this, but it looks like the + // functions are overloaded instead of texture2DGrad() (etc). + + // !!! FIXME: + // The spec says we can't use GLSL's texture*Lod() built-ins from fragment + // shaders for some inexplicable reason. + // For now, you'll just have to suffer with the potentially wrong mipmap + // until I can figure something out. + + // ARB_shader_texture_lod and EXT_gpu_shader4 added texture2DLod/Grad*(), + // so we'll use them if available. Failing that, we'll just fallback + // to a regular texture2D call and hope the mipmap it chooses is close + // enough. + if (!ctx->glsl_generated_texlod_setup) + { + ctx->glsl_generated_texlod_setup = 1; + push_output(ctx, &ctx->preflight); + output_line(ctx, "#if GL_ARB_shader_texture_lod"); + output_line(ctx, "#extension GL_ARB_shader_texture_lod : enable"); + output_line(ctx, "#define texture2DGrad texture2DGradARB"); + output_line(ctx, "#define texture2DProjGrad texture2DProjARB"); + output_line(ctx, "#define texture2DLod texture2DLodARB"); + output_line(ctx, "#elif GL_EXT_gpu_shader4"); + output_line(ctx, "#extension GL_EXT_gpu_shader4 : enable"); + output_line(ctx, "#else"); + output_line(ctx, "#define texture2DGrad(a,b,c,d) texture2D(a,b)"); + output_line(ctx, "#define texture2DProjGrad(a,b,c,d) texture2DProj(a,b)"); + output_line(ctx, "#define texture2DLod(a,b,c) texture2D(a,b)"); + output_line(ctx, "#endif"); + output_blank_line(ctx); + pop_output(ctx); + } // if +} // prepend_glsl_texlod_extensions + void emit_GLSL_start(Context *ctx, const char *profilestr) { @@ -1654,8 +1693,11 @@ void emit_GLSL_TEXKILL(Context *ctx) output_line(ctx, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;", dst); } // emit_GLSL_TEXKILL -static void glsl_texld(Context *ctx, const int texldd) +static void glsl_texld(Context *ctx, const int texldd, const int texldl) { + if (texldd || texldl) + prepend_glsl_texlod_extensions(ctx); + if (!shader_version_atleast(ctx, 1, 4)) { DestArgInfo *info = &ctx->dest_arg; @@ -1664,6 +1706,7 @@ static void glsl_texld(Context *ctx, const int texldd) char code[128] = {0}; assert(!texldd); + assert(!texldl); RegisterList *sreg; sreg = reglist_find(&ctx->samplers, REG_TYPE_SAMPLER, info->regnum); @@ -1756,13 +1799,18 @@ static void glsl_texld(Context *ctx, const int texldd) funcname = "texture2DProj"; make_GLSL_srcarg_string_full(ctx, 0, src0, sizeof (src0)); } // if - else // texld/texldb + else // texld/texldb/texldl { funcname = "texture2D"; - make_GLSL_srcarg_string_vec2(ctx, 0, src0, sizeof (src0)); + if (texldl) + make_GLSL_srcarg_string_full(ctx, 0, src0, sizeof (src0)); + else + make_GLSL_srcarg_string_vec2(ctx, 0, src0, sizeof (src0)); } // else break; case TEXTURE_TYPE_CUBE: + assert(!texldl); + if (ctx->instruction_controls == CONTROL_TEXLDP) fail(ctx, "TEXLDP on a cubemap"); // !!! FIXME: is this legal? funcname = "textureCube"; @@ -1774,10 +1822,13 @@ static void glsl_texld(Context *ctx, const int texldd) funcname = "texture3DProj"; make_GLSL_srcarg_string_full(ctx, 0, src0, sizeof (src0)); } // if - else // texld/texldb + else // texld/texldb/texldl { funcname = "texture3D"; - make_GLSL_srcarg_string_vec3(ctx, 0, src0, sizeof (src0)); + if (texldl) + make_GLSL_srcarg_string_full(ctx, 0, src0, sizeof (src0)); + else + make_GLSL_srcarg_string_vec3(ctx, 0, src0, sizeof (src0)); } // else break; default: @@ -1797,6 +1848,24 @@ static void glsl_texld(Context *ctx, const int texldd) "%sGrad(%s, %s, %s, %s)%s", funcname, src1, src0, src2, src3, swiz_str); } // if + else if (texldl) + { + const TextureType texType = (const TextureType) sreg->index; + assert(texType != TEXTURE_TYPE_CUBE); + + // HLSL tex2dlod accepts (sampler, uv.xyz, uv.w) where uv.w is the LOD + // GLSL seems to want the dimensionality to match the sampler (.xy vs .xyz) + // so we vary the swizzle accordingly + const char * pattern = 0; + if (texType == TEXTURE_TYPE_VOLUME) + pattern = "%sLod(%s, %s.xyz, %s.w)%s"; + else + pattern = "%sLod(%s, %s.xy, %s.w)%s"; + + make_GLSL_destarg_assign(ctx, code, sizeof(code), + pattern, funcname, + src1, src0, src0, swiz_str); + } // else if else { make_GLSL_destarg_assign(ctx, code, sizeof (code), @@ -1810,7 +1879,7 @@ static void glsl_texld(Context *ctx, const int texldd) void emit_GLSL_TEXLD(Context *ctx) { - glsl_texld(ctx, 0); + glsl_texld(ctx, 0, 0); } // emit_GLSL_TEXLD @@ -2240,33 +2309,7 @@ void emit_GLSL_DSY(Context *ctx) void emit_GLSL_TEXLDD(Context *ctx) { - // !!! FIXME: - // GLSL 1.30 introduced textureGrad() for this, but it looks like the - // functions are overloaded instead of texture2DGrad() (etc). - - // GL_shader_texture_lod and GL_EXT_gpu_shader4 added texture2DGrad*(), - // so we'll use them if available. Failing that, we'll just fallback - // to a regular texture2D call and hope the mipmap it chooses is close - // enough. - if (!ctx->glsl_generated_texldd_setup) - { - ctx->glsl_generated_texldd_setup = 1; - push_output(ctx, &ctx->preflight); - output_line(ctx, "#if GL_ARB_shader_texture_lod"); - output_line(ctx, "#extension GL_ARB_shader_texture_lod : enable"); - output_line(ctx, "#define texture2DGrad texture2DGradARB"); - output_line(ctx, "#define texture2DProjGrad texture2DProjARB"); - output_line(ctx, "#elif GL_EXT_gpu_shader4"); - output_line(ctx, "#extension GL_EXT_gpu_shader4 : enable"); - output_line(ctx, "#else"); - output_line(ctx, "#define texture2DGrad(a,b,c,d) texture2D(a,b)"); - output_line(ctx, "#define texture2DProjGrad(a,b,c,d) texture2DProj(a,b)"); - output_line(ctx, "#endif"); - output_blank_line(ctx); - pop_output(ctx); - } // if - - glsl_texld(ctx, 1); + glsl_texld(ctx, 1, 0); } // emit_GLSL_TEXLDD void emit_GLSL_SETP(Context *ctx) @@ -2295,11 +2338,7 @@ void emit_GLSL_SETP(Context *ctx) void emit_GLSL_TEXLDL(Context *ctx) { - // !!! FIXME: The spec says we can't use GLSL's texture*Lod() built-ins - // !!! FIXME: from fragment shaders for some inexplicable reason. - // !!! FIXME: For now, you'll just have to suffer with the potentially - // !!! FIXME: wrong mipmap until I can figure something out. - emit_GLSL_TEXLD(ctx); + glsl_texld(ctx, 0, 1); } // emit_GLSL_TEXLDL void emit_GLSL_BREAKP(Context *ctx)