From cb4e3e3ef6e47811303ad3413a4ab2048696a6f6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 10 Jan 2019 16:24:57 +1000 Subject: [PATCH] st/mesa: add support for lowering fp64/int64 for nir drivers This might enough for iris and possible r600 (when it gets NIR) This appears to work for iris. v2: * change cap return so DOUBLES == 2 means sw emu v3: * Refactor using int64/doubles lowering options which were added into nir options * Remove DOUBLES == 2 added in v2 [jordan: Remove "2" value on PIPE_CAP_DOUBLES] [jordan: Use lowering options added to nir options] Signed-off-by: Jordan Justen Reviewed-by: Kenneth Graunke Acked-by: Jason Ekstrand --- src/mesa/state_tracker/st_glsl_to_nir.cpp | 99 ++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp index 89f7424e4db..a1e3b6233c6 100644 --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp @@ -36,6 +36,7 @@ #include "main/shaderapi.h" #include "main/uniforms.h" +#include "main/shaderobj.h" #include "st_context.h" #include "st_glsl_types.h" #include "st_program.h" @@ -47,7 +48,7 @@ #include "compiler/glsl/ir.h" #include "compiler/glsl/ir_optimization.h" #include "compiler/glsl/string_to_uint_map.h" - +#include "compiler/glsl/float64_glsl.h" static int type_size(const struct glsl_type *type) @@ -340,6 +341,50 @@ st_nir_opts(nir_shader *nir, bool scalar) } while (progress); } +static nir_shader * +compile_fp64_funcs(struct gl_context *ctx, + const nir_shader_compiler_options *options, + void *mem_ctx, + gl_shader_stage stage) +{ + const GLuint name = ~0; + struct gl_shader *sh; + + sh = _mesa_new_shader(name, stage); + + sh->Source = float64_source; + sh->CompileStatus = COMPILE_FAILURE; + _mesa_compile_shader(ctx, sh); + + if (!sh->CompileStatus) { + if (sh->InfoLog) { + _mesa_problem(ctx, + "fp64 software impl compile failed:\n%s\nsource:\n%s\n", + sh->InfoLog, float64_source); + } + } + + struct gl_shader_program *sh_prog; + sh_prog = _mesa_new_shader_program(name); + sh_prog->Label = NULL; + sh_prog->NumShaders = 1; + sh_prog->Shaders = (struct gl_shader **)malloc(sizeof(struct gl_shader *)); + sh_prog->Shaders[0] = sh; + + struct gl_linked_shader *linked = rzalloc(NULL, struct gl_linked_shader); + linked->Stage = stage; + linked->Program = + ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(stage), + name, false); + + linked->ir = sh->ir; + sh_prog->_LinkedShaders[stage] = linked; + + nir_shader *nir = glsl_to_nir(sh_prog, stage, options); + + return nir_shader_clone(mem_ctx, nir); +} + /* First third of converting glsl_to_nir.. this leaves things in a pre- * nir_lower_io state, so that shader variants can more easily insert/ * replace variables, etc. @@ -355,6 +400,8 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, struct pipe_screen *screen = st->pipe->screen; bool is_scalar = screen->get_shader_param(screen, type, PIPE_SHADER_CAP_SCALAR_ISA); assert(options); + bool lower_64bit = + options->lower_int64_options || options->lower_doubles_options; if (prog->nir) return prog->nir; @@ -376,6 +423,16 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, nir->info.next_stage = MESA_SHADER_FRAGMENT; } + nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); + if (nir->info.uses_64bit && + (options->lower_doubles_options & nir_lower_fp64_full_software) != 0) { + nir_shader *fp64 = + compile_fp64_funcs(st->ctx, options, ralloc_parent(nir), + nir->info.stage); + nir_validate_shader(fp64, "fp64"); + exec_list_append(&nir->functions, &fp64->functions); + } + nir_variable_mode mask = (nir_variable_mode) (nir_var_shader_in | nir_var_shader_out); nir_remove_dead_variables(nir, mask); @@ -396,6 +453,46 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, NIR_PASS_V(nir, nir_split_var_copies); NIR_PASS_V(nir, nir_lower_var_copies); + if (is_scalar) { + NIR_PASS_V(nir, nir_lower_alu_to_scalar); + } + + if (lower_64bit) { + bool lowered_64bit_ops = false; + bool progress = false; + + NIR_PASS_V(nir, nir_opt_algebraic); + + do { + progress = false; + if (options->lower_int64_options) { + NIR_PASS(progress, nir, nir_lower_int64, + options->lower_int64_options); + } + if (options->lower_doubles_options) { + NIR_PASS(progress, nir, nir_lower_doubles, + options->lower_doubles_options); + } + NIR_PASS(progress, nir, nir_opt_algebraic); + lowered_64bit_ops |= progress; + } while (progress); + + if (lowered_64bit_ops) { + NIR_PASS_V(nir, nir_lower_constant_initializers, nir_var_function_temp); + NIR_PASS_V(nir, nir_lower_returns); + NIR_PASS_V(nir, nir_inline_functions); + NIR_PASS_V(nir, nir_opt_deref); + } + + const nir_function *entry_point = nir_shader_get_entrypoint(nir)->function; + foreach_list_typed_safe(nir_function, func, node, &nir->functions) { + if (func != entry_point) { + exec_node_remove(&func->node); + } + } + assert(exec_list_length(&nir->functions) == 1); + } + st_nir_opts(nir, is_scalar); return nir; -- 2.30.2