diff options
Diffstat (limited to 'mesalib/src/glsl')
25 files changed, 309 insertions, 273 deletions
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index 26de455f0..284b37584 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -24,22 +24,26 @@ env.Prepend(LIBS = [mesautil]) # Make glcpp-parse.h and glsl_parser.h reachable from the include path. env.Append(CPPPATH = [Dir('.').abspath, Dir('glcpp').abspath]) -env.Append(YACCFLAGS = '-d -p "glcpp_parser_"') +glcpp_env = env.Clone() +glcpp_env.Append(YACCFLAGS = [ + '-d', + '-p', 'glcpp_parser_' +]) -parser_env = env.Clone() -parser_env.Append(YACCFLAGS = [ +glsl_env = env.Clone() +glsl_env.Append(YACCFLAGS = [ '--defines=%s' % File('glsl_parser.h').abspath, '-p', '_mesa_glsl_', ]) # without this line scons will expect "glsl_parser.hpp" instead of # "glsl_parser.h", causing glsl_parser.cpp to be regenerated every time -parser_env['YACCHXXFILESUFFIX'] = '.h' +glsl_env['YACCHXXFILESUFFIX'] = '.h' -glcpp_lexer = env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l') -glcpp_parser = env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y') -glsl_lexer = parser_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll') -glsl_parser = parser_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy') +glcpp_lexer = glcpp_env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l') +glcpp_parser = glcpp_env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y') +glsl_lexer = glsl_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll') +glsl_parser = glsl_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy') # common generated sources glsl_sources = [ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index acb5c763c..d387b2e35 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -1617,6 +1617,12 @@ ast_expression::do_hir(exec_list *instructions, && cond_val != NULL) { result = cond_val->value.b[0] ? op[1] : op[2]; } else { + /* The copy to conditional_tmp reads the whole array. */ + if (type->is_array()) { + mark_whole_array_access(op[1]); + mark_whole_array_access(op[2]); + } + ir_variable *const tmp = new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); instructions->push_tail(tmp); diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 28bcfdb3c..e46db8552 100755 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -201,7 +201,7 @@ static bool shader_packing_or_es3(const _mesa_glsl_parse_state *state) { return state->ARB_shading_language_packing_enable || - state->is_version(400, 300); + state->is_version(420, 300); } static bool diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 4a2ebeb40..d33fcfe6b 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -35,6 +35,10 @@ #include "glsl_types.h" #include "main/context.h" +#ifdef _MSC_VER +#pragma warning( disable : 4065 ) // switch statement contains 'default' but no 'case' labels +#endif + #undef yyerror static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 25f2ecada..fdc22edf1 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -119,6 +119,7 @@ public: /*@{*/ class ir_rvalue *as_rvalue() { + assume(this != NULL); if (ir_type == ir_type_dereference_array || ir_type == ir_type_dereference_record || ir_type == ir_type_dereference_variable || @@ -132,6 +133,7 @@ public: class ir_dereference *as_dereference() { + assume(this != NULL); if (ir_type == ir_type_dereference_array || ir_type == ir_type_dereference_record || ir_type == ir_type_dereference_variable) @@ -141,6 +143,7 @@ public: class ir_jump *as_jump() { + assume(this != NULL); if (ir_type == ir_type_loop_jump || ir_type == ir_type_return || ir_type == ir_type_discard) @@ -151,6 +154,7 @@ public: #define AS_CHILD(TYPE) \ class ir_##TYPE * as_##TYPE() \ { \ + assume(this != NULL); \ return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \ } AS_CHILD(variable) diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index e24cad98d..d198276c6 100755 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -35,6 +35,7 @@ #include <math.h> #include "main/core.h" /* for MAX2, MIN2, CLAMP */ +#include "util/rounding.h" /* for _mesa_roundeven */ #include "ir.h" #include "glsl_types.h" #include "program/hash_table.h" @@ -238,8 +239,8 @@ pack_snorm_1x8(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint8_t) (int8_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); } /** @@ -260,8 +261,8 @@ pack_snorm_1x16(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint16_t) (int16_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f); } /** @@ -315,7 +316,7 @@ pack_unorm_1x8(float x) * * packUnorm4x8: round(clamp(c, 0, +1) * 255.0) */ - return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f); + return (uint8_t) (int) _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f); } /** @@ -333,7 +334,8 @@ pack_unorm_1x16(float x) * * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) */ - return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f); } /** @@ -726,9 +728,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) case ir_unop_round_even: for (unsigned c = 0; c < op[0]->type->components(); c++) { if (op[0]->type->base_type == GLSL_TYPE_DOUBLE) - data.d[c] = _mesa_round_to_even(op[0]->value.d[c]); + data.d[c] = _mesa_roundeven(op[0]->value.d[c]); else - data.f[c] = _mesa_round_to_even(op[0]->value.f[c]); + data.f[c] = _mesa_roundevenf(op[0]->value.f[c]); } break; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 0c4467779..4349f0973 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -2542,8 +2542,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - prog->ARB_fragment_coord_conventions_enable |= - prog->Shaders[i]->ARB_fragment_coord_conventions_enable; + if (prog->Shaders[i]->ARB_fragment_coord_conventions_enable) { + prog->ARB_fragment_coord_conventions_enable = true; + } gl_shader_stage shader_type = prog->Shaders[i]->Stage; shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i]; diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h index 8554a4652..d855240cb 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -692,7 +692,7 @@ inline void exec_node::insert_before(exec_list *before) exec_node_data(__type, (__list)->head, __field), \ * __next = \ exec_node_data(__type, (__node)->__field.next, __field); \ - __next != NULL; \ + (__node)->__field.next != NULL; \ __node = __next, __next = \ exec_node_data(__type, (__next)->__field.next, __field)) @@ -701,7 +701,7 @@ inline void exec_node::insert_before(exec_list *before) exec_node_data(__type, (__list)->tail_pred, __field), \ * __prev = \ exec_node_data(__type, (__node)->__field.prev, __field); \ - __prev != NULL; \ + (__node)->__field.prev != NULL; \ __node = __prev, __prev = \ exec_node_data(__type, (__prev)->__field.prev, __field)) diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp index adef19c80..357944da6 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.cpp +++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp @@ -43,7 +43,7 @@ namespace { class nir_visitor : public ir_visitor { public: - nir_visitor(nir_shader *shader, bool supports_ints); + nir_visitor(nir_shader *shader, gl_shader_stage stage); ~nir_visitor(); virtual void visit(ir_variable *); @@ -83,6 +83,7 @@ private: bool supports_ints; nir_shader *shader; + gl_shader_stage stage; nir_function_impl *impl; exec_list *cf_node_list; nir_instr *result; /* result of the expression tree last visited */ @@ -124,59 +125,24 @@ private: }; /* end of anonymous namespace */ -static const nir_shader_compiler_options default_options = { -}; - nir_shader * -glsl_to_nir(exec_list *ir, _mesa_glsl_parse_state *state, - bool native_integers) +glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options) { - const nir_shader_compiler_options *options; - - if (state) { - struct gl_context *ctx = state->ctx; - struct gl_shader_compiler_options *gl_options = - &ctx->Const.ShaderCompilerOptions[state->stage]; - - if (!gl_options->NirOptions) { - nir_shader_compiler_options *new_options = - rzalloc(ctx, nir_shader_compiler_options); - options = gl_options->NirOptions = new_options; - - if (gl_options->EmitNoPow) - new_options->lower_fpow = true; - } else { - options = gl_options->NirOptions; - } - } else { - options = &default_options; - } - nir_shader *shader = nir_shader_create(NULL, options); - if (state) { - shader->num_user_structures = state->num_user_structures; - shader->user_structures = ralloc_array(shader, glsl_type *, - shader->num_user_structures); - memcpy(shader->user_structures, state->user_structures, - shader->num_user_structures * sizeof(glsl_type *)); - } else { - shader->num_user_structures = 0; - shader->user_structures = NULL; - } - - nir_visitor v1(shader, native_integers); + nir_visitor v1(shader, sh->Stage); nir_function_visitor v2(&v1); - v2.run(ir); - visit_exec_list(ir, &v1); + v2.run(sh->ir); + visit_exec_list(sh->ir, &v1); return shader; } -nir_visitor::nir_visitor(nir_shader *shader, bool supports_ints) +nir_visitor::nir_visitor(nir_shader *shader, gl_shader_stage stage) { - this->supports_ints = supports_ints; + this->supports_ints = shader->options->native_integers; this->shader = shader; + this->stage = stage; this->is_global = true; this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -285,7 +251,8 @@ nir_visitor::visit(ir_variable *ir) break; case ir_var_shader_in: - if (ir->data.location == VARYING_SLOT_FACE) { + if (stage == MESA_SHADER_FRAGMENT && + ir->data.location == VARYING_SLOT_FACE) { /* For whatever reason, GLSL IR makes gl_FrontFacing an input */ var->data.location = SYSTEM_VALUE_FRONT_FACE; var->data.mode = nir_var_system_value; @@ -385,15 +352,15 @@ nir_visitor::visit(ir_variable *ir) break; case nir_var_shader_in: - _mesa_hash_table_insert(shader->inputs, var->name, var); + exec_list_push_tail(&shader->inputs, &var->node); break; case nir_var_shader_out: - _mesa_hash_table_insert(shader->outputs, var->name, var); + exec_list_push_tail(&shader->outputs, &var->node); break; case nir_var_uniform: - _mesa_hash_table_insert(shader->uniforms, var->name, var); + exec_list_push_tail(&shader->uniforms, &var->node); break; case nir_var_system_value: diff --git a/mesalib/src/glsl/nir/glsl_to_nir.h b/mesalib/src/glsl/nir/glsl_to_nir.h index 58b2cee6a..3801e8c55 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.h +++ b/mesalib/src/glsl/nir/glsl_to_nir.h @@ -32,8 +32,8 @@ extern "C" { #endif -nir_shader *glsl_to_nir(exec_list * ir, _mesa_glsl_parse_state *state, - bool native_integers); +nir_shader *glsl_to_nir(struct gl_shader *sh, + const nir_shader_compiler_options *options); #ifdef __cplusplus } diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c index ab57fd4e2..6459d5108 100644 --- a/mesalib/src/glsl/nir/nir.c +++ b/mesalib/src/glsl/nir/nir.c @@ -33,18 +33,12 @@ nir_shader_create(void *mem_ctx, const nir_shader_compiler_options *options) { nir_shader *shader = ralloc(mem_ctx, nir_shader); - shader->uniforms = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); - shader->inputs = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); - shader->outputs = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); + exec_list_make_empty(&shader->uniforms); + exec_list_make_empty(&shader->inputs); + exec_list_make_empty(&shader->outputs); shader->options = options; - shader->num_user_structures = 0; - shader->user_structures = NULL; - exec_list_make_empty(&shader->functions); exec_list_make_empty(&shader->registers); exec_list_make_empty(&shader->globals); diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h index d5df59609..29fe94243 100644 --- a/mesalib/src/glsl/nir/nir.h +++ b/mesalib/src/glsl/nir/nir.h @@ -1370,17 +1370,23 @@ typedef struct nir_shader_compiler_options { bool lower_fsqrt; /** lowers fneg and ineg to fsub and isub. */ bool lower_negate; + + /** + * Does the driver support real 32-bit integers? (Otherwise, integers + * are simulated by floats.) + */ + bool native_integers; } nir_shader_compiler_options; typedef struct nir_shader { /** hash table of name -> uniform nir_variable */ - struct hash_table *uniforms; + struct exec_list uniforms; /** hash table of name -> input nir_variable */ - struct hash_table *inputs; + struct exec_list inputs; /** hash table of name -> output nir_variable */ - struct hash_table *outputs; + struct exec_list outputs; /** Set of driver-specific options for the shader. * @@ -1400,10 +1406,6 @@ typedef struct nir_shader { /** list of global register in the shader */ struct exec_list registers; - /** structures used in this shader */ - unsigned num_user_structures; - struct glsl_type **user_structures; - /** next available global register index */ unsigned reg_alloc; @@ -1575,6 +1577,13 @@ void nir_lower_global_vars_to_local(nir_shader *shader); void nir_lower_locals_to_regs(nir_shader *shader); +void nir_assign_var_locations_scalar(struct exec_list *var_list, + unsigned *size); +void nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size); + void nir_lower_io(nir_shader *shader); void nir_lower_vars_to_ssa(nir_shader *shader); diff --git a/mesalib/src/glsl/nir/nir_constant_expressions.py b/mesalib/src/glsl/nir/nir_constant_expressions.py index 22bc4f095..bf82fe533 100644 --- a/mesalib/src/glsl/nir/nir_constant_expressions.py +++ b/mesalib/src/glsl/nir/nir_constant_expressions.py @@ -28,6 +28,7 @@ template = """\ #include <math.h> #include "main/core.h" +#include "util/rounding.h" /* for _mesa_roundeven */ #include "nir_constant_expressions.h" #if defined(_MSC_VER) && (_MSC_VER < 1800) @@ -68,8 +69,8 @@ pack_snorm_1x8(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint8_t) (int8_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); } /** @@ -90,8 +91,8 @@ pack_snorm_1x16(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint16_t) (int16_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f); } /** @@ -145,7 +146,8 @@ pack_unorm_1x8(float x) * * packUnorm4x8: round(clamp(c, 0, +1) * 255.0) */ - return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f); } /** @@ -163,7 +165,8 @@ pack_unorm_1x16(float x) * * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) */ - return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f); } /** diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h index 3bf102fc1..8e28765c1 100644 --- a/mesalib/src/glsl/nir/nir_intrinsics.h +++ b/mesalib/src/glsl/nir/nir_intrinsics.h @@ -95,6 +95,8 @@ ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE) SYSTEM_VALUE(front_face, 1) SYSTEM_VALUE(vertex_id, 1) +SYSTEM_VALUE(vertex_id_zero_base, 1) +SYSTEM_VALUE(base_vertex, 1) SYSTEM_VALUE(instance_id, 1) SYSTEM_VALUE(sample_id, 1) SYSTEM_VALUE(sample_pos, 2) diff --git a/mesalib/src/glsl/nir/nir_lower_io.c b/mesalib/src/glsl/nir/nir_lower_io.c index 207f8daa1..03eed04e1 100644 --- a/mesalib/src/glsl/nir/nir_lower_io.c +++ b/mesalib/src/glsl/nir/nir_lower_io.c @@ -76,15 +76,12 @@ type_size(const struct glsl_type *type) return 0; } -static void -assign_var_locations(struct hash_table *ht, unsigned *size) +void +nir_assign_var_locations_scalar(struct exec_list *var_list, unsigned *size) { unsigned location = 0; - struct hash_entry *entry; - hash_table_foreach(ht, entry) { - nir_variable *var = (nir_variable *) entry->data; - + foreach_list_typed(nir_variable, var, node, var_list) { /* * UBO's have their own address spaces, so don't count them towards the * number of global uniforms @@ -99,14 +96,6 @@ assign_var_locations(struct hash_table *ht, unsigned *size) *size = location; } -static void -assign_var_locations_shader(nir_shader *shader) -{ - assign_var_locations(shader->inputs, &shader->num_inputs); - assign_var_locations(shader->outputs, &shader->num_outputs); - assign_var_locations(shader->uniforms, &shader->num_uniforms); -} - static bool deref_has_indirect(nir_deref_var *deref) { @@ -121,6 +110,77 @@ deref_has_indirect(nir_deref_var *deref) return false; } +static bool +mark_indirect_uses_block(nir_block *block, void *void_state) +{ + struct set *indirect_set = void_state; + + nir_foreach_instr(block, instr) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + for (unsigned i = 0; + i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) { + if (deref_has_indirect(intrin->variables[i])) + _mesa_set_add(indirect_set, intrin->variables[i]->var); + } + } + + return true; +} + +/* Identical to nir_assign_var_locations_packed except that it assigns + * locations to the variables that are used 100% directly first and then + * assigns locations to variables that are used indirectly. + */ +void +nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size) +{ + struct set *indirect_set = _mesa_set_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_foreach_block(overload->impl, mark_indirect_uses_block, + indirect_set); + } + + unsigned location = 0; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *direct_size = location; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (!_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *size = location; + + _mesa_set_destroy(indirect_set, NULL); +} + static unsigned get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect, struct lower_io_state *state) @@ -307,8 +367,6 @@ nir_lower_io_impl(nir_function_impl *impl) void nir_lower_io(nir_shader *shader) { - assign_var_locations_shader(shader); - nir_foreach_overload(shader, overload) { if (overload->impl) nir_lower_io_impl(overload->impl); diff --git a/mesalib/src/glsl/nir/nir_lower_system_values.c b/mesalib/src/glsl/nir/nir_lower_system_values.c index 328d4f1ab..a6eec653e 100644 --- a/mesalib/src/glsl/nir/nir_lower_system_values.c +++ b/mesalib/src/glsl/nir/nir_lower_system_values.c @@ -49,6 +49,12 @@ convert_instr(nir_intrinsic_instr *instr) case SYSTEM_VALUE_VERTEX_ID: op = nir_intrinsic_load_vertex_id; break; + case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: + op = nir_intrinsic_load_vertex_id_zero_base; + break; + case SYSTEM_VALUE_BASE_VERTEX: + op = nir_intrinsic_load_base_vertex; + break; case SYSTEM_VALUE_INSTANCE_ID: op = nir_intrinsic_load_instance_id; break; diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c index 9e9a418e3..86e6ab416 100644 --- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c @@ -35,6 +35,13 @@ struct deref_node { bool lower_to_ssa; + /* Only valid for things that end up in the direct list. + * Note that multiple nir_deref_vars may correspond to this node, but they + * will all be equivalent, so any is as good as the other. + */ + nir_deref_var *deref; + struct exec_node direct_derefs_link; + struct set *loads; struct set *stores; struct set *copies; @@ -69,7 +76,7 @@ struct lower_variables_state { * wildcards and no indirects, these are precisely the derefs that we * can actually consider lowering. */ - struct hash_table *direct_deref_nodes; + struct exec_list direct_deref_nodes; /* Controls whether get_deref_node will add variables to the * direct_deref_nodes table. This is turned on when we are initially @@ -83,88 +90,6 @@ struct lower_variables_state { struct hash_table *phi_table; }; -/* The following two functions implement a hash and equality check for - * variable dreferences. When the hash or equality function encounters an - * array, all indirects are treated as equal and are never equal to a - * direct dereference or a wildcard. - */ -static uint32_t -hash_deref(const void *void_deref) -{ - uint32_t hash = _mesa_fnv32_1a_offset_bias; - - const nir_deref_var *deref_var = void_deref; - hash = _mesa_fnv32_1a_accumulate(hash, deref_var->var); - - for (const nir_deref *deref = deref_var->deref.child; - deref; deref = deref->child) { - switch (deref->deref_type) { - case nir_deref_type_array: { - nir_deref_array *deref_array = nir_deref_as_array(deref); - - hash = _mesa_fnv32_1a_accumulate(hash, deref_array->deref_array_type); - - if (deref_array->deref_array_type == nir_deref_array_type_direct) - hash = _mesa_fnv32_1a_accumulate(hash, deref_array->base_offset); - break; - } - case nir_deref_type_struct: { - nir_deref_struct *deref_struct = nir_deref_as_struct(deref); - hash = _mesa_fnv32_1a_accumulate(hash, deref_struct->index); - break; - } - default: - assert("Invalid deref chain"); - } - } - - return hash; -} - -static bool -derefs_equal(const void *void_a, const void *void_b) -{ - const nir_deref_var *a_var = void_a; - const nir_deref_var *b_var = void_b; - - if (a_var->var != b_var->var) - return false; - - for (const nir_deref *a = a_var->deref.child, *b = b_var->deref.child; - a != NULL; a = a->child, b = b->child) { - if (a->deref_type != b->deref_type) - return false; - - switch (a->deref_type) { - case nir_deref_type_array: { - nir_deref_array *a_arr = nir_deref_as_array(a); - nir_deref_array *b_arr = nir_deref_as_array(b); - - if (a_arr->deref_array_type != b_arr->deref_array_type) - return false; - - if (a_arr->deref_array_type == nir_deref_array_type_direct && - a_arr->base_offset != b_arr->base_offset) - return false; - break; - } - case nir_deref_type_struct: - if (nir_deref_as_struct(a)->index != nir_deref_as_struct(b)->index) - return false; - break; - default: - assert("Invalid deref chain"); - return false; - } - - assert((a->child == NULL) == (b->child == NULL)); - if((a->child == NULL) != (b->child == NULL)) - return false; - } - - return true; -} - static int type_get_length(const struct glsl_type *type) { @@ -195,6 +120,8 @@ deref_node_create(struct deref_node *parent, struct deref_node *node = rzalloc_size(mem_ctx, size); node->type = type; node->parent = parent; + node->deref = NULL; + exec_node_init(&node->direct_derefs_link); return node; } @@ -297,8 +224,14 @@ get_deref_node(nir_deref_var *deref, struct lower_variables_state *state) assert(node); - if (is_direct && state->add_to_direct_deref_nodes) - _mesa_hash_table_insert(state->direct_deref_nodes, deref, node); + /* Only insert if it isn't already in the list. */ + if (is_direct && state->add_to_direct_deref_nodes && + node->direct_derefs_link.next == NULL) { + node->deref = deref; + assert(deref->var != NULL); + exec_list_push_tail(&state->direct_deref_nodes, + &node->direct_derefs_link); + } return node; } @@ -917,10 +850,8 @@ insert_phi_nodes(struct lower_variables_state *state) unsigned w_start, w_end; unsigned iter_count = 0; - struct hash_entry *deref_entry; - hash_table_foreach(state->direct_deref_nodes, deref_entry) { - struct deref_node *node = deref_entry->data; - + foreach_list_typed(struct deref_node, node, direct_derefs_link, + &state->direct_deref_nodes) { if (node->stores == NULL) continue; @@ -1014,8 +945,7 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl) state.deref_var_nodes = _mesa_hash_table_create(state.dead_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); - state.direct_deref_nodes = _mesa_hash_table_create(state.dead_ctx, - hash_deref, derefs_equal); + exec_list_make_empty(&state.direct_deref_nodes); state.phi_table = _mesa_hash_table_create(state.dead_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -1035,18 +965,17 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl) /* We're about to iterate through direct_deref_nodes. Don't modify it. */ state.add_to_direct_deref_nodes = false; - struct hash_entry *entry; - hash_table_foreach(state.direct_deref_nodes, entry) { - nir_deref_var *deref = (void *)entry->key; - struct deref_node *node = entry->data; + foreach_list_typed_safe(struct deref_node, node, direct_derefs_link, + &state.direct_deref_nodes) { + nir_deref_var *deref = node->deref; if (deref->var->data.mode != nir_var_local) { - _mesa_hash_table_remove(state.direct_deref_nodes, entry); + exec_node_remove(&node->direct_derefs_link); continue; } if (deref_may_be_aliased(deref, &state)) { - _mesa_hash_table_remove(state.direct_deref_nodes, entry); + exec_node_remove(&node->direct_derefs_link); continue; } diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py index 77f3bb826..062cd628b 100644 --- a/mesalib/src/glsl/nir/nir_opcodes.py +++ b/mesalib/src/glsl/nir/nir_opcodes.py @@ -183,7 +183,7 @@ unop("ftrunc", tfloat, "truncf(src0)") unop("fceil", tfloat, "ceilf(src0)") unop("ffloor", tfloat, "floorf(src0)") unop("ffract", tfloat, "src0 - floorf(src0)") -unop("fround_even", tfloat, "_mesa_round_to_even(src0)") +unop("fround_even", tfloat, "_mesa_roundevenf(src0)") # Trigonometric operations. diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py index 7bf643134..ef855aa77 100644 --- a/mesalib/src/glsl/nir/nir_opt_algebraic.py +++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py @@ -56,6 +56,10 @@ optimizations = [ (('iabs', ('ineg', a)), ('iabs', a)), (('fadd', a, 0.0), a), (('iadd', a, 0), a), + (('fadd', ('fmul', a, b), ('fmul', a, c)), ('fmul', a, ('fadd', b, c))), + (('iadd', ('imul', a, b), ('imul', a, c)), ('imul', a, ('iadd', b, c))), + (('fadd', ('fneg', a), a), 0.0), + (('iadd', ('ineg', a), a), 0), (('fmul', a, 0.0), 0.0), (('imul', a, 0), 0), (('fmul', a, 1.0), a), diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c index ab08f286f..b89451b09 100644 --- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c +++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c @@ -52,36 +52,66 @@ struct peephole_select_state { }; static bool -are_all_move_to_phi(nir_block *block) +block_check_for_allowed_instrs(nir_block *block) { nir_foreach_instr(block, instr) { - if (instr->type != nir_instr_type_alu) - return false; + switch (instr->type) { + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + switch (intrin->intrinsic) { + case nir_intrinsic_load_var: + switch (intrin->variables[0]->var->data.mode) { + case nir_var_shader_in: + case nir_var_uniform: + break; + + default: + return false; + } + break; + + default: + return false; + } - /* It must be a move operation */ - nir_alu_instr *mov = nir_instr_as_alu(instr); - if (mov->op != nir_op_fmov && mov->op != nir_op_imov) - return false; + break; + } - /* Can't handle saturate */ - if (mov->dest.saturate) - return false; + case nir_instr_type_load_const: + break; - /* It must be SSA */ - if (!mov->dest.dest.is_ssa) - return false; + case nir_instr_type_alu: { + /* It must be a move operation */ + nir_alu_instr *mov = nir_instr_as_alu(instr); + if (mov->op != nir_op_fmov && mov->op != nir_op_imov) + return false; - /* It cannot have any if-uses */ - if (mov->dest.dest.ssa.if_uses->entries != 0) - return false; + /* Can't handle saturate */ + if (mov->dest.saturate) + return false; + + /* It must be SSA */ + if (!mov->dest.dest.is_ssa) + return false; - /* The only uses of this definition must be phi's in the successor */ - struct set_entry *entry; - set_foreach(mov->dest.dest.ssa.uses, entry) { - const nir_instr *dest_instr = entry->key; - if (dest_instr->type != nir_instr_type_phi || - dest_instr->block != block->successors[0]) + /* It cannot have any if-uses */ + if (mov->dest.dest.ssa.if_uses->entries != 0) return false; + + /* The only uses of this definition must be phi's in the successor */ + struct set_entry *entry; + set_foreach(mov->dest.dest.ssa.uses, entry) { + const nir_instr *dest_instr = entry->key; + if (dest_instr->type != nir_instr_type_phi || + dest_instr->block != block->successors[0]) + return false; + } + break; + } + + default: + return false; } } @@ -119,8 +149,9 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) nir_block *then_block = nir_cf_node_as_block(then_node); nir_block *else_block = nir_cf_node_as_block(else_node); - /* ... and those blocks must only contain move-to-phi. */ - if (!are_all_move_to_phi(then_block) || !are_all_move_to_phi(else_block)) + /* ... and those blocks must only contain "allowed" instructions. */ + if (!block_check_for_allowed_instrs(then_block) || + !block_check_for_allowed_instrs(else_block)) return true; /* At this point, we know that the previous CFG node is an if-then @@ -129,6 +160,25 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) * selects. */ + nir_block *prev_block = nir_cf_node_as_block(nir_cf_node_prev(prev_node)); + assert(prev_block->cf_node.type == nir_cf_node_block); + + /* First, we move the remaining instructions from the blocks to the + * block before. We have already guaranteed that this is safe by + * calling block_check_for_allowed_instrs() + */ + nir_foreach_instr_safe(then_block, instr) { + exec_node_remove(&instr->node); + instr->block = prev_block; + exec_list_push_tail(&prev_block->instr_list, &instr->node); + } + + nir_foreach_instr_safe(else_block, instr) { + exec_node_remove(&instr->node); + instr->block = prev_block; + exec_list_push_tail(&prev_block->instr_list, &instr->node); + } + nir_foreach_instr_safe(block, instr) { if (instr->type != nir_instr_type_phi) break; @@ -145,19 +195,7 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) assert(src->src.is_ssa); unsigned idx = src->pred == then_block ? 1 : 2; - - if (src->src.ssa->parent_instr->block == src->pred) { - /* We already know that this instruction must be a move with - * this phi's in this block as its only users. - */ - nir_alu_instr *mov = nir_instr_as_alu(src->src.ssa->parent_instr); - assert(mov->instr.type == nir_instr_type_alu); - assert(mov->op == nir_op_fmov || mov->op == nir_op_imov); - - nir_alu_src_copy(&sel->src[idx], &mov->src[0], state->mem_ctx); - } else { - nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx); - } + nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx); } nir_ssa_dest_init(&sel->instr, &sel->dest.dest, diff --git a/mesalib/src/glsl/nir/nir_print.c b/mesalib/src/glsl/nir/nir_print.c index 6a3c6a027..fa11a312e 100644 --- a/mesalib/src/glsl/nir/nir_print.c +++ b/mesalib/src/glsl/nir/nir_print.c @@ -228,7 +228,7 @@ print_var_decl(nir_variable *var, print_var_state *state, FILE *fp) if (var->data.mode == nir_var_shader_in || var->data.mode == nir_var_shader_out || var->data.mode == nir_var_uniform) { - fprintf(fp, " (%u)", var->data.driver_location); + fprintf(fp, " (%u, %u)", var->data.location, var->data.driver_location); } fprintf(fp, "\n"); @@ -844,22 +844,16 @@ nir_print_shader(nir_shader *shader, FILE *fp) print_var_state state; init_print_state(&state); - for (unsigned i = 0; i < shader->num_user_structures; i++) { - glsl_print_struct(shader->user_structures[i], fp); - } - - struct hash_entry *entry; - - hash_table_foreach(shader->uniforms, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->uniforms) { + print_var_decl(var, &state, fp); } - hash_table_foreach(shader->inputs, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->inputs) { + print_var_decl(var, &state, fp); } - hash_table_foreach(shader->outputs, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->outputs) { + print_var_decl(var, &state, fp); } foreach_list_typed(nir_variable, var, node, &shader->globals) { diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c index a3fe9d620..f247ae069 100644 --- a/mesalib/src/glsl/nir/nir_validate.c +++ b/mesalib/src/glsl/nir/nir_validate.c @@ -931,17 +931,19 @@ nir_validate_shader(nir_shader *shader) state.shader = shader; - struct hash_entry *entry; - hash_table_foreach(shader->uniforms, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->uniforms); + foreach_list_typed(nir_variable, var, node, &shader->uniforms) { + validate_var_decl(var, true, &state); } - hash_table_foreach(shader->inputs, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->inputs); + foreach_list_typed(nir_variable, var, node, &shader->inputs) { + validate_var_decl(var, true, &state); } - hash_table_foreach(shader->outputs, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->outputs); + foreach_list_typed(nir_variable, var, node, &shader->outputs) { + validate_var_decl(var, true, &state); } exec_list_validate(&shader->globals); diff --git a/mesalib/src/glsl/nir/nir_worklist.c b/mesalib/src/glsl/nir/nir_worklist.c index a8baae937..3087a1d23 100644 --- a/mesalib/src/glsl/nir/nir_worklist.c +++ b/mesalib/src/glsl/nir/nir_worklist.c @@ -82,7 +82,7 @@ nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block) } nir_block * -nir_block_worklist_peek_head(nir_block_worklist *w) +nir_block_worklist_peek_head(const nir_block_worklist *w) { assert(w->count > 0); @@ -114,18 +114,18 @@ nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block) w->count++; - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; w->blocks[tail] = block; BITSET_SET(w->blocks_present, block->index); } nir_block * -nir_block_worklist_peek_tail(nir_block_worklist *w) +nir_block_worklist_peek_tail(const nir_block_worklist *w) { assert(w->count > 0); - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; return w->blocks[tail]; } @@ -135,7 +135,7 @@ nir_block_worklist_pop_tail(nir_block_worklist *w) { assert(w->count > 0); - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; w->count--; diff --git a/mesalib/src/glsl/nir/nir_worklist.h b/mesalib/src/glsl/nir/nir_worklist.h index d5a8568e4..829bff24a 100644 --- a/mesalib/src/glsl/nir/nir_worklist.h +++ b/mesalib/src/glsl/nir/nir_worklist.h @@ -74,13 +74,13 @@ nir_block_worklist_is_empty(const nir_block_worklist *w) void nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block); -nir_block *nir_block_worklist_peek_head(nir_block_worklist *w); +nir_block *nir_block_worklist_peek_head(const nir_block_worklist *w); nir_block *nir_block_worklist_pop_head(nir_block_worklist *w); void nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block); -nir_block *nir_block_worklist_peek_tail(nir_block_worklist *w); +nir_block *nir_block_worklist_peek_tail(const nir_block_worklist *w); nir_block *nir_block_worklist_pop_tail(nir_block_worklist *w); diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index c6040bff8..69c03ea8b 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -626,9 +626,18 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (!is_vec_zero(zero)) continue; - return new(mem_ctx) ir_expression(ir->operation, - add->operands[0], - neg(add->operands[1])); + /* Depending of the zero position we want to optimize + * (0 cmp x+y) into (-x cmp y) or (x+y cmp 0) into (x cmp -y) + */ + if (add_pos == 1) { + return new(mem_ctx) ir_expression(ir->operation, + neg(add->operands[0]), + add->operands[1]); + } else { + return new(mem_ctx) ir_expression(ir->operation, + add->operands[0], + neg(add->operands[1])); + } } break; |