#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"
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);
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
}
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);
}
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);
}