summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Arceri <[email protected]>2019-02-20 17:13:49 +1100
committerTimothy Arceri <[email protected]>2019-03-06 23:05:20 +0000
commit7e60d5a501f311fa5e7bca5335adc6013dc1aeb9 (patch)
tree9dac6cae42a538fd3d904920e11058d8a1c8ba8c
parent7530d4abfcf9d39fb1b4abeb77cdbf6cf1d411a7 (diff)
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 <[email protected]>
-rw-r--r--src/compiler/glsl/glsl_to_nir.cpp82
-rw-r--r--src/compiler/glsl/glsl_to_nir.h3
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_cmdline.c2
-rw-r--r--src/gallium/drivers/panfrost/midgard/cmdline.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_program.c2
-rw-r--r--src/mesa/state_tracker/st_glsl_to_nir.cpp2
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 &&