From 7e60d5a501f311fa5e7bca5335adc6013dc1aeb9 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 20 Feb 2019 17:13:49 +1100 Subject: [PATCH] glsl: use NIR function inlining for drivers that use glsl_to_nir() glsl_to_nir() is still missing support for converting certain functions to NIR, so for those we use the GLSL IR optimisations to remove the functions. Reviewed-by: Eric Anholt --- src/compiler/glsl/glsl_to_nir.cpp | 82 ++++++++++++++++++- src/compiler/glsl/glsl_to_nir.h | 3 +- .../drivers/freedreno/ir3/ir3_cmdline.c | 2 +- .../drivers/panfrost/midgard/cmdline.c | 6 +- src/mesa/drivers/dri/i965/brw_program.c | 2 +- src/mesa/state_tracker/st_glsl_to_nir.cpp | 2 +- 6 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 062434d066b..004a430d124 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -30,6 +30,7 @@ #include "ir_visitor.h" #include "ir_hierarchical_visitor.h" #include "ir.h" +#include "ir_optimization.h" #include "program.h" #include "compiler/nir/nir_control_flow.h" #include "compiler/nir/nir_builder.h" @@ -133,15 +134,74 @@ private: nir_visitor *visitor; }; +/* glsl_to_nir can only handle converting certain function paramaters + * to NIR. This visitor checks for parameters it can't currently handle. + */ +class ir_function_param_visitor : public ir_hierarchical_visitor +{ +public: + ir_function_param_visitor() + : unsupported(false) + { + } + + virtual ir_visitor_status visit_enter(ir_function_signature *ir) + { + + if (ir->is_intrinsic()) + return visit_continue; + + foreach_in_list(ir_variable, param, &ir->parameters) { + if (!param->type->is_vector() || !param->type->is_scalar()) { + unsupported = true; + return visit_stop; + } + + if (param->data.mode == ir_var_function_inout) { + unsupported = true; + return visit_stop; + } + } + + return visit_continue; + } + + bool unsupported; +}; + } /* end of anonymous namespace */ + +static bool +has_unsupported_function_param(exec_list *ir) +{ + ir_function_param_visitor visitor; + visit_list_elements(&visitor, ir); + return visitor.unsupported; +} + nir_shader * -glsl_to_nir(const struct gl_shader_program *shader_prog, +glsl_to_nir(struct gl_context *ctx, + const struct gl_shader_program *shader_prog, gl_shader_stage stage, const nir_shader_compiler_options *options) { struct gl_linked_shader *sh = shader_prog->_LinkedShaders[stage]; + const struct gl_shader_compiler_options *gl_options = + &ctx->Const.ShaderCompilerOptions[stage]; + + /* glsl_to_nir can only handle converting certain function paramaters + * to NIR. If we find something we can't handle then we get the GLSL IR + * opts to remove it before we continue on. + * + * TODO: add missing glsl ir to nir support and remove this loop. + */ + while (has_unsupported_function_param(sh->ir)) { + do_common_optimization(sh->ir, true, true, gl_options, + ctx->Const.NativeIntegers); + } + nir_shader *shader = nir_shader_create(NULL, stage, options, &sh->Program->info); @@ -150,7 +210,27 @@ glsl_to_nir(const struct gl_shader_program *shader_prog, v2.run(sh->ir); visit_exec_list(sh->ir, &v1); + nir_validate_shader(shader, "after glsl to nir, before function inline"); + + /* We have to lower away local constant initializers right before we + * inline functions. That way they get properly initialized at the top + * of the function and not at the top of its caller. + */ nir_lower_constant_initializers(shader, (nir_variable_mode)~0); + nir_lower_returns(shader); + nir_inline_functions(shader); + nir_opt_deref(shader); + + nir_validate_shader(shader, "after function inlining and return lowering"); + + /* Now that we have inlined everything remove all of the functions except + * main(). + */ + foreach_list_typed_safe(nir_function, function, node, &(shader)->functions){ + if (strcmp("main", function->name) != 0) { + exec_node_remove(&function->node); + } + } /* Remap the locations to slots so those requiring two slots will occupy * two locations. For instance, if we have in the IR code a dvec3 attr0 in diff --git a/src/compiler/glsl/glsl_to_nir.h b/src/compiler/glsl/glsl_to_nir.h index 115c8e1270b..38728d3ff26 100644 --- a/src/compiler/glsl/glsl_to_nir.h +++ b/src/compiler/glsl/glsl_to_nir.h @@ -36,7 +36,8 @@ extern "C" { struct gl_shader_program; -nir_shader *glsl_to_nir(const struct gl_shader_program *shader_prog, +nir_shader *glsl_to_nir(struct gl_context *ctx, + const struct gl_shader_program *shader_prog, gl_shader_stage stage, const nir_shader_compiler_options *options); diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c index 0850618bc3d..a8120578283 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c @@ -116,7 +116,7 @@ load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage) if (!prog) errx(1, "couldn't parse `%s'", files[0]); - nir_shader *nir = glsl_to_nir(prog, stage, nir_options); + nir_shader *nir = glsl_to_nir(&local_ctx, prog, stage, nir_options); /* required NIR passes: */ if (nir_options->lower_all_io_to_temps || diff --git a/src/gallium/drivers/panfrost/midgard/cmdline.c b/src/gallium/drivers/panfrost/midgard/cmdline.c index 7326402dd09..acd810b2f34 100644 --- a/src/gallium/drivers/panfrost/midgard/cmdline.c +++ b/src/gallium/drivers/panfrost/midgard/cmdline.c @@ -66,11 +66,11 @@ compile_shader(char **argv) } midgard_program compiled; - nir = glsl_to_nir(prog, MESA_SHADER_VERTEX, &midgard_nir_options); + nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_VERTEX, &midgard_nir_options); midgard_compile_shader_nir(nir, &compiled, false); finalise_to_disk("vertex.bin", &compiled.compiled); - nir = glsl_to_nir(prog, MESA_SHADER_FRAGMENT, &midgard_nir_options); + nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_FRAGMENT, &midgard_nir_options); midgard_compile_shader_nir(nir, &compiled, false); finalise_to_disk("fragment.bin", &compiled.compiled); } @@ -91,7 +91,7 @@ compile_blend(char **argv) prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->info.stage = MESA_SHADER_FRAGMENT; midgard_program program; - nir = glsl_to_nir(prog, MESA_SHADER_FRAGMENT, &midgard_nir_options); + nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_FRAGMENT, &midgard_nir_options); midgard_compile_shader_nir(nir, &program, true); finalise_to_disk("blend.bin", &program.compiled); } diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index ffb49c35cd4..e58ed7c8e48 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -93,7 +93,7 @@ brw_create_nir(struct brw_context *brw, if (shader_prog->data->spirv) { nir = _mesa_spirv_to_nir(ctx, shader_prog, stage, options); } else { - nir = glsl_to_nir(shader_prog, stage, options); + nir = glsl_to_nir(ctx, shader_prog, stage, options); } assert (nir); diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp index fa0cdf771e4..7b339e9e043 100644 --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp @@ -361,7 +361,7 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, if (prog->nir) return prog->nir; - nir_shader *nir = glsl_to_nir(shader_program, stage, options); + nir_shader *nir = glsl_to_nir(st->ctx, shader_program, stage, options); /* Set the next shader stage hint for VS and TES. */ if (!nir->info.separate_shader && -- 2.30.2