Commit e4bff8a6 authored by Dave Airlie's avatar Dave Airlie

st/mesa: add support for lowering fp64/int64 for nir drivers. (v2)

This might enough for iris and possible r600 (when it gets NIR)

V2: chance cap return so DOUBLES == 2 means sw emu
parent 34724d6e
...@@ -1405,11 +1405,19 @@ void st_init_extensions(struct pipe_screen *screen, ...@@ -1405,11 +1405,19 @@ void st_init_extensions(struct pipe_screen *screen,
} }
#endif #endif
if (screen->get_param(screen, PIPE_CAP_DOUBLES)) { enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
PIPE_SHADER_CAP_PREFERRED_IR);
bool use_nir = preferred_ir == PIPE_SHADER_IR_NIR;
int doubles = screen->get_param(screen, PIPE_CAP_DOUBLES);
if ((doubles == 1) || (doubles == 2 && use_nir)) {
extensions->ARB_gpu_shader_fp64 = GL_TRUE; extensions->ARB_gpu_shader_fp64 = GL_TRUE;
extensions->ARB_vertex_attrib_64bit = GL_TRUE; extensions->ARB_vertex_attrib_64bit = GL_TRUE;
} }
if (doubles == 2 && use_nir)
extensions->ARB_gpu_shader_int64 = GL_TRUE;
if ((ST_DEBUG & DEBUG_GREMEDY) && if ((ST_DEBUG & DEBUG_GREMEDY) &&
screen->get_param(screen, PIPE_CAP_STRING_MARKER)) screen->get_param(screen, PIPE_CAP_STRING_MARKER))
extensions->GREMEDY_string_marker = GL_TRUE; extensions->GREMEDY_string_marker = GL_TRUE;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "main/shaderapi.h" #include "main/shaderapi.h"
#include "main/uniforms.h" #include "main/uniforms.h"
#include "main/shaderobj.h"
#include "st_context.h" #include "st_context.h"
#include "st_glsl_types.h" #include "st_glsl_types.h"
#include "st_program.h" #include "st_program.h"
...@@ -47,7 +48,7 @@ ...@@ -47,7 +48,7 @@
#include "compiler/glsl/ir.h" #include "compiler/glsl/ir.h"
#include "compiler/glsl/ir_optimization.h" #include "compiler/glsl/ir_optimization.h"
#include "compiler/glsl/string_to_uint_map.h" #include "compiler/glsl/string_to_uint_map.h"
#include "compiler/glsl/float64_glsl.h"
static int static int
type_size(const struct glsl_type *type) type_size(const struct glsl_type *type)
...@@ -340,6 +341,51 @@ st_nir_opts(nir_shader *nir, bool scalar) ...@@ -340,6 +341,51 @@ st_nir_opts(nir_shader *nir, bool scalar)
} while (progress); } 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- /* 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/ * nir_lower_io state, so that shader variants can more easily insert/
* replace variables, etc. * replace variables, etc.
...@@ -354,6 +400,7 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, ...@@ -354,6 +400,7 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
enum pipe_shader_type type = pipe_shader_type_from_mesa(stage); enum pipe_shader_type type = pipe_shader_type_from_mesa(stage);
struct pipe_screen *screen = st->pipe->screen; struct pipe_screen *screen = st->pipe->screen;
bool is_scalar = screen->get_shader_param(screen, type, PIPE_SHADER_CAP_SCALAR_ISA); bool is_scalar = screen->get_shader_param(screen, type, PIPE_SHADER_CAP_SCALAR_ISA);
bool lower_fp64 = (screen->get_param(screen, PIPE_CAP_DOUBLES) == 2);
assert(options); assert(options);
if (prog->nir) if (prog->nir)
...@@ -376,6 +423,13 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, ...@@ -376,6 +423,13 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
nir->info.next_stage = MESA_SHADER_FRAGMENT; nir->info.next_stage = MESA_SHADER_FRAGMENT;
} }
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
if (nir->info.uses_64bit && lower_fp64) {
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 mask =
(nir_variable_mode) (nir_var_shader_in | nir_var_shader_out); (nir_variable_mode) (nir_var_shader_in | nir_var_shader_out);
nir_remove_dead_variables(nir, mask); nir_remove_dead_variables(nir, mask);
...@@ -396,6 +450,64 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog, ...@@ -396,6 +450,64 @@ 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_split_var_copies);
NIR_PASS_V(nir, nir_lower_var_copies); NIR_PASS_V(nir, nir_lower_var_copies);
if (is_scalar) {
NIR_PASS_V(nir, nir_lower_alu_to_scalar,nir_lower_alu_to_scalar_all);
}
if (lower_fp64) {
bool lowered_64bit_ops = false;
bool progress = false;
NIR_PASS_V(nir, nir_opt_algebraic);
do {
progress = false;
nir_lower_int64_options int64_options =
(nir_lower_int64_options)(nir_lower_imul64 |
nir_lower_isign64 |
nir_lower_divmod64 |
nir_lower_imul_high64 |
nir_lower_mov64 |
nir_lower_icmp64 |
nir_lower_iadd64 |
nir_lower_iabs64 |
nir_lower_ineg64 |
nir_lower_logic64 |
nir_lower_minmax64 |
nir_lower_shift64);
nir_lower_doubles_options fp64_options =
(nir_lower_doubles_options)(nir_lower_drcp |
nir_lower_dsqrt |
nir_lower_drsq |
nir_lower_dtrunc |
nir_lower_dfloor |
nir_lower_dceil |
nir_lower_dfract |
nir_lower_dround_even |
nir_lower_dmod |
nir_lower_fp64_full_software);
NIR_PASS(progress, nir, nir_lower_int64, int64_options);
NIR_PASS(progress, nir, nir_lower_doubles, fp64_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);
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); st_nir_opts(nir, is_scalar);
return nir; return nir;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment