diff options
Diffstat (limited to 'mesalib/src/glsl')
39 files changed, 545 insertions, 197 deletions
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am index 5a0a643da..b466a3b5c 100644 --- a/mesalib/src/glsl/Makefile.am +++ b/mesalib/src/glsl/Makefile.am @@ -33,8 +33,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/gtest/include \ -I$(top_builddir)/src/glsl/nir \ $(DEFINES) -AM_CFLAGS = $(VISIBILITY_CFLAGS) -AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS) +AM_CFLAGS = \ + $(VISIBILITY_CFLAGS) \ + $(MSVC2013_COMPAT_CFLAGS) +AM_CXXFLAGS = \ + $(VISIBILITY_CXXFLAGS) \ + $(MSVC2013_COMPAT_CXXFLAGS) EXTRA_DIST = tests glcpp/tests README TODO glcpp/README \ glsl_lexer.ll \ diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index d0210d170..b876642e8 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -157,6 +157,7 @@ LIBGLSL_FILES = \ lower_ubo_reference.cpp \ opt_algebraic.cpp \ opt_array_splitting.cpp \ + opt_conditional_discard.cpp \ opt_constant_folding.cpp \ opt_constant_propagation.cpp \ opt_constant_variable.cpp \ diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index 21c8266a6..26de455f0 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -6,6 +6,8 @@ from sys import executable as python_cmd env = env.Clone() +env.MSVC2013Compat() + env.Prepend(CPPPATH = [ '#include', '#src', diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp index ff0c7576d..ecef651f7 100644 --- a/mesalib/src/glsl/ast_array_index.cpp +++ b/mesalib/src/glsl/ast_array_index.cpp @@ -83,11 +83,9 @@ update_max_array_access(ir_rvalue *ir, int idx, YYLTYPE *loc, if (deref_var != NULL) { if (deref_var->var->is_interface_instance()) { - const glsl_type *interface_type = - deref_var->var->get_interface_type(); unsigned field_index = deref_record->record->type->field_index(deref_record->field); - assert(field_index < interface_type->length); + assert(field_index < deref_var->var->get_interface_type()->length); unsigned *const max_ifc_array_access = deref_var->var->get_max_ifc_array_access(); diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index b643927d0..84bbdc2a4 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -2549,7 +2549,7 @@ builtin_builder::add_image_function(const char *name, }; ir_function *f = new(mem_ctx) ir_function(name); - for (unsigned i = 0; i < Elements(types); ++i) { + for (unsigned i = 0; i < ARRAY_SIZE(types); ++i) { if (types[i]->sampler_type != GLSL_TYPE_FLOAT || (flags & IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE)) f->add_signature(_image(types[i], intrinsic_name, diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 65e32ad73..21e7331c7 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -227,7 +227,7 @@ static const struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { #undef MATRIX -#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} +#define STATEVAR(name) {#name, name ## _elements, ARRAY_SIZE(name ## _elements)} static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { STATEVAR(gl_NumSamples), diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c index a54bcbe16..160c6662f 100644 --- a/mesalib/src/glsl/glcpp/pp.c +++ b/mesalib/src/glsl/glcpp/pp.c @@ -25,7 +25,6 @@ #include <string.h> #include <ctype.h> #include "glcpp.h" -#include "main/core.h" /* for isblank() on MSVC */ void glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index ea3bd8a24..90c216ed9 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1280,7 +1280,7 @@ layout_qualifier_id: { "triangles_adjacency", GL_TRIANGLES_ADJACENCY }, { "triangle_strip", GL_TRIANGLE_STRIP }, }; - for (unsigned i = 0; i < Elements(map); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { if (match_layout_qualifier($1, map[i].s, state) == 0) { $$.flags.q.prim_type = 1; $$.prim_type = map[i].e; @@ -1344,7 +1344,7 @@ layout_qualifier_id: { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT } }; - for (unsigned i = 0; i < Elements(map); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { if (match_layout_qualifier($1, map[i].name, state) == 0) { $$.flags.q.explicit_image_format = 1; $$.image_format = map[i].format; diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 9f7931380..79624bc26 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -119,9 +119,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings; /* Compute shader constants */ - for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupCount); i++) + for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++) this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i]; - for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++) + for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupSize); i++) this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i]; this->Const.MaxImageUnits = ctx->Const.MaxImageUnits; @@ -636,7 +636,7 @@ void _mesa_glsl_extension::set_flags(_mesa_glsl_parse_state *state, */ static const _mesa_glsl_extension *find_extension(const char *name) { - for (unsigned i = 0; i < Elements(_mesa_glsl_supported_extensions); ++i) { + for (unsigned i = 0; i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) { if (strcmp(name, _mesa_glsl_supported_extensions[i].name) == 0) { return &_mesa_glsl_supported_extensions[i]; } @@ -674,7 +674,7 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, return false; } else { for (unsigned i = 0; - i < Elements(_mesa_glsl_supported_extensions); ++i) { + i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) { const _mesa_glsl_extension *extension = &_mesa_glsl_supported_extensions[i]; if (extension->compatible_with_state(state)) { @@ -1627,6 +1627,7 @@ do_common_optimization(exec_list *ir, bool linked, } progress = do_if_simplification(ir) || progress; progress = opt_flatten_nested_if_blocks(ir) || progress; + progress = opt_conditional_discard(ir) || progress; progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index f4f92e9df..54656f899 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -618,8 +618,8 @@ static const char *const operator_strs[] = { const char *ir_expression::operator_string(ir_expression_operation op) { - assert((unsigned int) op < Elements(operator_strs)); - assert(Elements(operator_strs) == (ir_quadop_vector + 1)); + assert((unsigned int) op < ARRAY_SIZE(operator_strs)); + assert(ARRAY_SIZE(operator_strs) == (ir_quadop_vector + 1)); return operator_strs[op]; } @@ -1707,7 +1707,7 @@ const char *const ir_variable::warn_extension_table[] = { void ir_variable::enable_extension_warning(const char *extension) { - for (unsigned i = 0; i < Elements(warn_extension_table); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(warn_extension_table); i++) { if (strcmp(warn_extension_table[i], extension) == 0) { this->data.warn_extension_index = i; return; diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 5c7279ca3..914e0e4d5 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -158,7 +158,7 @@ ir_call::clone(void *mem_ctx, struct hash_table *ht) const ir_expression * ir_expression::clone(void *mem_ctx, struct hash_table *ht) const { - ir_rvalue *op[Elements(this->operands)] = { NULL, }; + ir_rvalue *op[ARRAY_SIZE(this->operands)] = { NULL, }; unsigned int i; for (i = 0; i < get_num_operands(); i++) { diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index 07dd439d5..388c4c286 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -506,7 +506,7 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) if (this->type->is_error()) return NULL; - ir_constant *op[Elements(this->operands)] = { NULL, }; + ir_constant *op[ARRAY_SIZE(this->operands)] = { NULL, }; ir_constant_data data; memset(&data, 0, sizeof(data)); diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 7eb861ae5..e6939f3fe 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -77,6 +77,7 @@ bool do_common_optimization(exec_list *ir, bool linked, bool do_rebalance_tree(exec_list *instructions); bool do_algebraic(exec_list *instructions, bool native_integers, const struct gl_shader_compiler_options *options); +bool opt_conditional_discard(exec_list *instructions); bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp index 34cdb1c98..2eee3da7b 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.cpp +++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp @@ -135,6 +135,13 @@ ir_rvalue_base_visitor::rvalue_visit(ir_call *ir) } ir_visitor_status +ir_rvalue_base_visitor::rvalue_visit(ir_discard *ir) +{ + handle_rvalue(&ir->condition); + return visit_continue; +} + +ir_visitor_status ir_rvalue_base_visitor::rvalue_visit(ir_return *ir) { handle_rvalue(&ir->value);; @@ -205,6 +212,12 @@ ir_rvalue_visitor::visit_leave(ir_call *ir) } ir_visitor_status +ir_rvalue_visitor::visit_leave(ir_discard *ir) +{ + return rvalue_visit(ir); +} + +ir_visitor_status ir_rvalue_visitor::visit_leave(ir_return *ir) { return rvalue_visit(ir); @@ -271,6 +284,12 @@ ir_rvalue_enter_visitor::visit_enter(ir_call *ir) } ir_visitor_status +ir_rvalue_enter_visitor::visit_enter(ir_discard *ir) +{ + return rvalue_visit(ir); +} + +ir_visitor_status ir_rvalue_enter_visitor::visit_enter(ir_return *ir) { return rvalue_visit(ir); diff --git a/mesalib/src/glsl/ir_rvalue_visitor.h b/mesalib/src/glsl/ir_rvalue_visitor.h index 04ec0fa39..185c72a5b 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.h +++ b/mesalib/src/glsl/ir_rvalue_visitor.h @@ -36,6 +36,7 @@ public: ir_visitor_status rvalue_visit(ir_call *); ir_visitor_status rvalue_visit(ir_dereference_array *); ir_visitor_status rvalue_visit(ir_dereference_record *); + ir_visitor_status rvalue_visit(ir_discard *); ir_visitor_status rvalue_visit(ir_expression *); ir_visitor_status rvalue_visit(ir_if *); ir_visitor_status rvalue_visit(ir_return *); @@ -54,6 +55,7 @@ public: virtual ir_visitor_status visit_leave(ir_call *); virtual ir_visitor_status visit_leave(ir_dereference_array *); virtual ir_visitor_status visit_leave(ir_dereference_record *); + virtual ir_visitor_status visit_leave(ir_discard *); virtual ir_visitor_status visit_leave(ir_expression *); virtual ir_visitor_status visit_leave(ir_if *); virtual ir_visitor_status visit_leave(ir_return *); @@ -70,6 +72,7 @@ public: virtual ir_visitor_status visit_enter(ir_call *); virtual ir_visitor_status visit_enter(ir_dereference_array *); virtual ir_visitor_status visit_enter(ir_dereference_record *); + virtual ir_visitor_status visit_enter(ir_discard *); virtual ir_visitor_status visit_enter(ir_expression *); virtual ir_visitor_status visit_enter(ir_if *); virtual ir_visitor_status visit_enter(ir_return *); diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 667889480..7a7688cb2 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -61,6 +61,7 @@ public: virtual ir_visitor_status visit(ir_variable *v); virtual ir_visitor_status visit(ir_dereference_variable *ir); + virtual ir_visitor_status visit_enter(ir_discard *ir); virtual ir_visitor_status visit_enter(ir_if *ir); virtual ir_visitor_status visit_enter(ir_function *ir); @@ -133,6 +134,20 @@ ir_validate::visit_enter(class ir_dereference_array *ir) } ir_visitor_status +ir_validate::visit_enter(ir_discard *ir) +{ + if (ir->condition && ir->condition->type != glsl_type::bool_type) { + printf("ir_discard condition %s type instead of bool.\n", + ir->condition->type->name); + ir->print(); + printf("\n"); + abort(); + } + + return visit_continue; +} + +ir_visitor_status ir_validate::visit_enter(ir_if *ir) { if (ir->condition->type != glsl_type::bool_type) { diff --git a/mesalib/src/glsl/link_interface_blocks.cpp b/mesalib/src/glsl/link_interface_blocks.cpp index 0ce502d4f..07f5b4223 100644 --- a/mesalib/src/glsl/link_interface_blocks.cpp +++ b/mesalib/src/glsl/link_interface_blocks.cpp @@ -50,18 +50,20 @@ struct interface_block_definition * represents either the interface instance (for named interfaces), or a * member of the interface (for unnamed interfaces). */ - explicit interface_block_definition(const ir_variable *var) - : type(var->get_interface_type()), - instance_name(NULL), - array_size(-1) + explicit interface_block_definition(ir_variable *var) + : var(var), + type(var->get_interface_type()), + instance_name(NULL) { if (var->is_interface_instance()) { instance_name = var->name; - if (var->type->is_array()) - array_size = var->type->length; } explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly); } + /** + * Interface block ir_variable + */ + ir_variable *var; /** * Interface block type @@ -74,12 +76,6 @@ struct interface_block_definition const char *instance_name; /** - * For an interface block array, the array size (or 0 if unsized). - * Otherwise -1. - */ - int array_size; - - /** * True if this interface block was explicitly declared in the shader; * false if it was an implicitly declared built-in interface block. */ @@ -95,7 +91,8 @@ struct interface_block_definition bool intrastage_match(interface_block_definition *a, const interface_block_definition *b, - ir_variable_mode mode) + ir_variable_mode mode, + struct gl_shader_program *prog) { /* Types must match. */ if (a->type != b->type) { @@ -120,18 +117,13 @@ intrastage_match(interface_block_definition *a, return false; } - /* Array vs. nonarray must be consistent, and sizes must be - * consistent, with the exception that unsized arrays match sized - * arrays. + /* If a block is an array then it must match across the shader. + * Unsized arrays are also processed and matched agaist sized arrays. */ - if ((a->array_size == -1) != (b->array_size == -1)) + if (b->var->type != a->var->type && + (b->instance_name != NULL || a->instance_name != NULL) && + !validate_intrastage_arrays(prog, b->var, a->var)) return false; - if (b->array_size != 0) { - if (a->array_size == 0) - a->array_size = b->array_size; - else if (a->array_size != b->array_size) - return false; - } return true; } @@ -153,8 +145,8 @@ interstage_match(const interface_block_definition *producer, /* Unsized arrays should not occur during interstage linking. They * should have all been assigned a size by link_intrastage_shaders. */ - assert(consumer->array_size != 0); - assert(producer->array_size != 0); + assert(!consumer->var->type->is_unsized_array()); + assert(!producer->var->type->is_unsized_array()); /* Types must match. */ if (consumer->type != producer->type) { @@ -165,20 +157,27 @@ interstage_match(const interface_block_definition *producer, if (consumer->explicitly_declared || producer->explicitly_declared) return false; } + + /* Ignore outermost array if geom shader */ + const glsl_type *consumer_instance_type; if (extra_array_level) { - /* Consumer must be an array, and producer must not. */ - if (consumer->array_size == -1) - return false; - if (producer->array_size != -1) - return false; + consumer_instance_type = consumer->var->type->fields.array; } else { - /* Array vs. nonarray must be consistent, and sizes must be consistent. - * Since unsized arrays have been ruled out, we can check this by just - * making sure the sizes are equal. - */ - if (consumer->array_size != producer->array_size) + consumer_instance_type = consumer->var->type; + } + + /* If a block is an array then it must match across shaders. + * Since unsized arrays have been ruled out, we can check this by just + * making sure the types are equal. + */ + if ((consumer->instance_name != NULL && + consumer_instance_type->is_array()) || + (producer->instance_name != NULL && + producer->var->type->is_array())) { + if (consumer_instance_type != producer->var->type) return false; } + return true; } @@ -298,7 +297,8 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog, */ definitions->store(def); } else if (!intrastage_match(prev_def, &def, - (ir_variable_mode) var->data.mode)) { + (ir_variable_mode) var->data.mode, + prog)) { linker_error(prog, "definitions of interface block `%s' do not" " match\n", iface_type->name); return; @@ -374,7 +374,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog, * uniform matchin rules (for uniforms, it is as though all * shaders are in the same shader stage). */ - if (!intrastage_match(old_def, &new_def, ir_var_uniform)) { + if (!intrastage_match(old_def, &new_def, ir_var_uniform, prog)) { linker_error(prog, "definitions of interface block `%s' do not " "match\n", var->get_interface_type()->name); return; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 3f5eac1e2..0c4467779 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -64,6 +64,7 @@ * \author Ian Romanick <ian.d.romanick@intel.com> */ +#include <ctype.h> #include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" @@ -680,6 +681,45 @@ validate_geometry_shader_emissions(struct gl_context *ctx, } } +bool +validate_intrastage_arrays(struct gl_shader_program *prog, + ir_variable *const var, + ir_variable *const existing) +{ + /* Consider the types to be "the same" if both types are arrays + * of the same type and one of the arrays is implicitly sized. + * In addition, set the type of the linked variable to the + * explicitly sized array. + */ + if (var->type->is_array() && existing->type->is_array() && + (var->type->fields.array == existing->type->fields.array) && + ((var->type->length == 0)|| (existing->type->length == 0))) { + if (var->type->length != 0) { + if (var->type->length <= existing->data.max_array_access) { + linker_error(prog, "%s `%s' declared as type " + "`%s' but outermost dimension has an index" + " of `%i'\n", + mode_string(var), + var->name, var->type->name, + existing->data.max_array_access); + } + existing->type = var->type; + return true; + } else if (existing->type->length != 0) { + if(existing->type->length <= var->data.max_array_access) { + linker_error(prog, "%s `%s' declared as type " + "`%s' but outermost dimension has an index" + " of `%i'\n", + mode_string(var), + var->name, existing->type->name, + var->data.max_array_access); + } + return true; + } + } + return false; +} + /** * Perform validation of global variables used across multiple shaders @@ -719,50 +759,23 @@ cross_validate_globals(struct gl_shader_program *prog, */ ir_variable *const existing = variables.get_variable(var->name); if (existing != NULL) { - if (var->type != existing->type) { - /* Consider the types to be "the same" if both types are arrays - * of the same type and one of the arrays is implicitly sized. - * In addition, set the type of the linked variable to the - * explicitly sized array. - */ - if (var->type->is_array() - && existing->type->is_array() - && (var->type->fields.array == existing->type->fields.array) - && ((var->type->length == 0) - || (existing->type->length == 0))) { - if (var->type->length != 0) { - if (var->type->length <= existing->data.max_array_access) { - linker_error(prog, "%s `%s' declared as type " - "`%s' but outermost dimension has an index" - " of `%i'\n", - mode_string(var), - var->name, var->type->name, - existing->data.max_array_access); - return; - } - existing->type = var->type; - } else if (existing->type->length != 0 - && existing->type->length <= - var->data.max_array_access) { + /* Check if types match. Interface blocks have some special + * rules so we handle those elsewhere. + */ + if (var->type != existing->type && + !var->is_interface_instance()) { + if (!validate_intrastage_arrays(prog, var, existing)) { + if (var->type->is_record() && existing->type->is_record() + && existing->type->record_compare(var->type)) { + existing->type = var->type; + } else { linker_error(prog, "%s `%s' declared as type " - "`%s' but outermost dimension has an index" - " of `%i'\n", + "`%s' and type `%s'\n", mode_string(var), - var->name, existing->type->name, - var->data.max_array_access); + var->name, var->type->name, + existing->type->name); return; } - } else if (var->type->is_record() - && existing->type->is_record() - && existing->type->record_compare(var->type)) { - existing->type = var->type; - } else { - linker_error(prog, "%s `%s' declared as type " - "`%s' and type `%s'\n", - mode_string(var), - var->name, var->type->name, - existing->type->name); - return; } } diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h index be4da5e0a..ce3dc3232 100644 --- a/mesalib/src/glsl/linker.h +++ b/mesalib/src/glsl/linker.h @@ -61,6 +61,11 @@ link_uniform_blocks(void *mem_ctx, unsigned num_shaders, struct gl_uniform_block **blocks_ret); +bool +validate_intrastage_arrays(struct gl_shader_program *prog, + ir_variable *const var, + ir_variable *const existing); + void validate_intrastage_interface_blocks(struct gl_shader_program *prog, const gl_shader **shader_list, diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp index 2459fc1c3..d7f0b2809 100644 --- a/mesalib/src/glsl/loop_controls.cpp +++ b/mesalib/src/glsl/loop_controls.cpp @@ -123,7 +123,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, const int bias[] = { -1, 0, 1 }; bool valid_loop = false; - for (unsigned i = 0; i < Elements(bias); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) { /* Increment may be of type int, uint or float. */ switch (increment->type->base_type) { case GLSL_TYPE_INT: diff --git a/mesalib/src/glsl/lower_discard_flow.cpp b/mesalib/src/glsl/lower_discard_flow.cpp index 1bc56d79e..ee45bf221 100644 --- a/mesalib/src/glsl/lower_discard_flow.cpp +++ b/mesalib/src/glsl/lower_discard_flow.cpp @@ -90,7 +90,14 @@ ir_visitor_status lower_discard_flow_visitor::visit_enter(ir_discard *ir) { ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded); - ir_rvalue *rhs = new(mem_ctx) ir_constant(true); + ir_rvalue *rhs; + if (ir->condition) { + /* discarded <- condition, use (var_ref discarded) as the condition */ + rhs = ir->condition; + ir->condition = new(mem_ctx) ir_dereference_variable(discarded); + } else { + rhs = new(mem_ctx) ir_constant(true); + } ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs); ir->insert_before(assign); diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index 4779de059..845cfff36 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -124,7 +124,7 @@ * Converts double trunc, ceil, floor, round to fract */ -#include "main/core.h" /* for M_LOG2E */ +#include "c99_math.h" #include "program/prog_instruction.h" /* for swizzle */ #include "glsl_types.h" #include "ir.h" diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index 5e844c792..2c9a1c495 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -146,7 +146,11 @@ #include "glsl_symbol_table.h" #include "ir.h" +#include "ir_builder.h" #include "ir_optimization.h" +#include "program/prog_instruction.h" + +using namespace ir_builder; namespace { @@ -163,13 +167,14 @@ public: lower_packed_varyings_visitor(void *mem_ctx, unsigned locations_used, ir_variable_mode mode, unsigned gs_input_vertices, - exec_list *out_instructions); + exec_list *out_instructions, + exec_list *out_variables); void run(exec_list *instructions); private: - ir_assignment *bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs); - ir_assignment *bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs); + void bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs); + void bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs); unsigned lower_rvalue(ir_rvalue *rvalue, unsigned fine_location, ir_variable *unpacked_var, const char *name, bool gs_input_toplevel, unsigned vertex_index); @@ -221,13 +226,19 @@ private: * appropriate place in the shader once the visitor has finished running. */ exec_list *out_instructions; + + /** + * Exec list into which the visitor should insert any new variables. + */ + exec_list *out_variables; }; } /* anonymous namespace */ lower_packed_varyings_visitor::lower_packed_varyings_visitor( void *mem_ctx, unsigned locations_used, ir_variable_mode mode, - unsigned gs_input_vertices, exec_list *out_instructions) + unsigned gs_input_vertices, exec_list *out_instructions, + exec_list *out_variables) : mem_ctx(mem_ctx), locations_used(locations_used), packed_varyings((ir_variable **) @@ -235,7 +246,8 @@ lower_packed_varyings_visitor::lower_packed_varyings_visitor( locations_used)), mode(mode), gs_input_vertices(gs_input_vertices), - out_instructions(out_instructions) + out_instructions(out_instructions), + out_variables(out_variables) { } @@ -274,6 +286,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions) } } +#define SWIZZLE_ZWZW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W) /** * Make an ir_assignment from \c rhs to \c lhs, performing appropriate @@ -281,7 +294,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions) * * This function is called when packing varyings. */ -ir_assignment * +void lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs) { @@ -300,12 +313,28 @@ lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs, rhs = new(this->mem_ctx) ir_expression(ir_unop_bitcast_f2i, lhs->type, rhs); break; + case GLSL_TYPE_DOUBLE: + assert(rhs->type->vector_elements <= 2); + if (rhs->type->vector_elements == 2) { + ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "pack", ir_var_temporary); + + assert(lhs->type->vector_elements == 4); + this->out_variables->push_tail(t); + this->out_instructions->push_tail( + assign(t, u2i(expr(ir_unop_unpack_double_2x32, swizzle_x(rhs->clone(mem_ctx, NULL)))), 0x3)); + this->out_instructions->push_tail( + assign(t, u2i(expr(ir_unop_unpack_double_2x32, swizzle_y(rhs))), 0xc)); + rhs = deref(t).val; + } else { + rhs = u2i(expr(ir_unop_unpack_double_2x32, rhs)); + } + break; default: assert(!"Unexpected type conversion while lowering varyings"); break; } } - return new(this->mem_ctx) ir_assignment(lhs, rhs); + this->out_instructions->push_tail(new (this->mem_ctx) ir_assignment(lhs, rhs)); } @@ -315,7 +344,7 @@ lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs, * * This function is called when unpacking varyings. */ -ir_assignment * +void lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs) { @@ -334,12 +363,27 @@ lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs, rhs = new(this->mem_ctx) ir_expression(ir_unop_bitcast_i2f, lhs->type, rhs); break; + case GLSL_TYPE_DOUBLE: + assert(lhs->type->vector_elements <= 2); + if (lhs->type->vector_elements == 2) { + ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "unpack", ir_var_temporary); + assert(rhs->type->vector_elements == 4); + this->out_variables->push_tail(t); + this->out_instructions->push_tail( + assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle_xy(rhs->clone(mem_ctx, NULL)))), 0x1)); + this->out_instructions->push_tail( + assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle(rhs->clone(mem_ctx, NULL), SWIZZLE_ZWZW, 2))), 0x2)); + rhs = deref(t).val; + } else { + rhs = expr(ir_unop_pack_double_2x32, i2u(rhs)); + } + break; default: assert(!"Unexpected type conversion while lowering varyings"); break; } } - return new(this->mem_ctx) ir_assignment(lhs, rhs); + this->out_instructions->push_tail(new(this->mem_ctx) ir_assignment(lhs, rhs)); } @@ -372,6 +416,7 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, bool gs_input_toplevel, unsigned vertex_index) { + unsigned dmul = rvalue->type->is_double() ? 2 : 1; /* When gs_input_toplevel is set, we should be looking at a geometry shader * input array. */ @@ -405,17 +450,26 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, return this->lower_arraylike(rvalue, rvalue->type->matrix_columns, fine_location, unpacked_var, name, false, vertex_index); - } else if (rvalue->type->vector_elements + fine_location % 4 > 4) { + } else if (rvalue->type->vector_elements * dmul + + fine_location % 4 > 4) { /* This vector is going to be "double parked" across two varying slots, - * so handle it as two separate assignments. + * so handle it as two separate assignments. For doubles, a dvec3/dvec4 + * can end up being spread over 3 slots. However the second splitting + * will happen later, here we just always want to split into 2. */ - unsigned left_components = 4 - fine_location % 4; - unsigned right_components - = rvalue->type->vector_elements - left_components; + unsigned left_components, right_components; unsigned left_swizzle_values[4] = { 0, 0, 0, 0 }; unsigned right_swizzle_values[4] = { 0, 0, 0, 0 }; char left_swizzle_name[4] = { 0, 0, 0, 0 }; char right_swizzle_name[4] = { 0, 0, 0, 0 }; + + left_components = 4 - fine_location % 4; + if (rvalue->type->is_double()) { + /* We might actually end up with 0 left components! */ + left_components /= 2; + } + right_components = rvalue->type->vector_elements - left_components; + for (unsigned i = 0; i < left_components; i++) { left_swizzle_values[i] = i; left_swizzle_name[i] = "xyzw"[i]; @@ -433,9 +487,13 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, = ralloc_asprintf(this->mem_ctx, "%s.%s", name, left_swizzle_name); char *right_name = ralloc_asprintf(this->mem_ctx, "%s.%s", name, right_swizzle_name); - fine_location = this->lower_rvalue(left_swizzle, fine_location, - unpacked_var, left_name, false, - vertex_index); + if (left_components) + fine_location = this->lower_rvalue(left_swizzle, fine_location, + unpacked_var, left_name, false, + vertex_index); + else + /* Top up the fine location to the next slot */ + fine_location++; return this->lower_rvalue(right_swizzle, fine_location, unpacked_var, right_name, false, vertex_index); } else { @@ -443,7 +501,7 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, * varying. */ unsigned swizzle_values[4] = { 0, 0, 0, 0 }; - unsigned components = rvalue->type->vector_elements; + unsigned components = rvalue->type->vector_elements * dmul; unsigned location = fine_location / 4; unsigned location_frac = fine_location % 4; for (unsigned i = 0; i < components; ++i) @@ -454,13 +512,9 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, ir_swizzle *swizzle = new(this->mem_ctx) ir_swizzle(packed_deref, swizzle_values, components); if (this->mode == ir_var_shader_out) { - ir_assignment *assignment - = this->bitwise_assign_pack(swizzle, rvalue); - this->out_instructions->push_tail(assignment); + this->bitwise_assign_pack(swizzle, rvalue); } else { - ir_assignment *assignment - = this->bitwise_assign_unpack(rvalue, swizzle); - this->out_instructions->push_tail(assignment); + this->bitwise_assign_unpack(rvalue, swizzle); } return fine_location + components; } @@ -598,7 +652,7 @@ lower_packed_varyings_visitor::needs_lowering(ir_variable *var) } if (type->is_array()) type = type->fields.array; - if (type->vector_elements == 4) + if (type->vector_elements == 4 && !type->is_double()) return false; return true; } @@ -657,9 +711,11 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used, exec_list void_parameters; ir_function_signature *main_func_sig = main_func->matching_signature(NULL, &void_parameters, false); - exec_list new_instructions; + exec_list new_instructions, new_variables; lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode, - gs_input_vertices, &new_instructions); + gs_input_vertices, + &new_instructions, + &new_variables); visitor.run(instructions); if (mode == ir_var_shader_out) { if (shader->Stage == MESA_SHADER_GEOMETRY) { @@ -667,15 +723,22 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used, * to EmitVertex() */ lower_packed_varyings_gs_splicer splicer(mem_ctx, &new_instructions); + + /* Add all the variables in first. */ + main_func_sig->body.head->insert_before(&new_variables); + + /* Now update all the EmitVertex instances */ splicer.run(instructions); } else { /* For other shader types, outputs need to be lowered at the end of * main() */ + main_func_sig->body.append_list(&new_variables); main_func_sig->body.append_list(&new_instructions); } } else { /* Shader inputs need to be lowered at the beginning of main() */ main_func_sig->body.head->insert_before(&new_instructions); + main_func_sig->body.head->insert_before(&new_variables); } } diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp index 544d0d932..adef19c80 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.cpp +++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp @@ -563,8 +563,14 @@ nir_visitor::visit(ir_discard *ir) * discards will be immediately followed by a return. */ - nir_intrinsic_instr *discard = - nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard); + nir_intrinsic_instr *discard; + if (ir->condition) { + discard = nir_intrinsic_instr_create(this->shader, + nir_intrinsic_discard_if); + discard->src[0] = evaluate_rvalue(ir->condition); + } else { + discard = nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard); + } nir_instr_insert_after_cf_list(this->cf_node_list, &discard->instr); } diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c index 5b0e4bc50..ab57fd4e2 100644 --- a/mesalib/src/glsl/nir/nir.c +++ b/mesalib/src/glsl/nir/nir.c @@ -63,6 +63,7 @@ reg_create(void *mem_ctx, struct exec_list *list) { nir_register *reg = ralloc(mem_ctx, nir_register); + reg->parent_instr = NULL; reg->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); reg->defs = _mesa_set_create(mem_ctx, _mesa_hash_pointer, diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h index d74caa959..d5df59609 100644 --- a/mesalib/src/glsl/nir/nir.h +++ b/mesalib/src/glsl/nir/nir.h @@ -66,6 +66,7 @@ name(const in_type *parent) \ struct nir_function_overload; struct nir_function; struct nir_shader; +struct nir_instr; /** @@ -386,6 +387,14 @@ typedef struct { */ bool is_packed; + /** + * If this pointer is non-NULL then this register has exactly one + * definition and that definition dominates all of its uses. This is + * set by the out-of-SSA pass so that backends can get SSA-like + * information even once they have gone out of SSA. + */ + struct nir_instr *parent_instr; + /** set of nir_instr's where this register is used (read from) */ struct set *uses; @@ -408,7 +417,7 @@ typedef enum { nir_instr_type_parallel_copy, } nir_instr_type; -typedef struct { +typedef struct nir_instr { struct exec_node node; nir_instr_type type; struct nir_block *block; diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c index 7c5009577..c3090fb06 100644 --- a/mesalib/src/glsl/nir/nir_from_ssa.c +++ b/mesalib/src/glsl/nir/nir_from_ssa.c @@ -26,6 +26,7 @@ */ #include "nir.h" +#include "nir_vla.h" /* * This file implements an out-of-SSA pass as described in "Revisiting @@ -181,7 +182,7 @@ merge_merge_sets(merge_set *a, merge_set *b) static bool merge_sets_interfere(merge_set *a, merge_set *b) { - merge_node *dom[a->size + b->size]; + NIR_VLA(merge_node *, dom, a->size + b->size); int dom_idx = -1; struct exec_node *an = exec_list_get_head(&a->nodes); @@ -508,6 +509,13 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state) reg->num_components = def->num_components; reg->num_array_elems = 0; + /* This register comes from an SSA definition that was not part of a + * phi-web. Therefore, we know it has a single unique definition + * that dominates all of its uses. Therefore, we can copy the + * parent_instr from the SSA def safely. + */ + reg->parent_instr = def->parent_instr; + _mesa_hash_table_insert(state->ssa_table, def, reg); return reg; } @@ -666,21 +674,16 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy, } /* The register/source corresponding to the given index */ - nir_src values[num_copies * 2]; - memset(values, 0, sizeof values); - - /* The current location of a given piece of data */ - int loc[num_copies * 2]; + NIR_VLA_ZERO(nir_src, values, num_copies * 2); - /* The piece of data that the given piece of data is to be copied from */ - int pred[num_copies * 2]; + /* The current location of a given piece of data. We will use -1 for "null" */ + NIR_VLA_FILL(int, loc, num_copies * 2, -1); - /* Initialize loc and pred. We will use -1 for "null" */ - memset(loc, -1, sizeof loc); - memset(pred, -1, sizeof pred); + /* The piece of data that the given piece of data is to be copied from. We will use -1 for "null" */ + NIR_VLA_FILL(int, pred, num_copies * 2, -1); /* The destinations we have yet to properly fill */ - int to_do[num_copies * 2]; + NIR_VLA(int, to_do, num_copies * 2); int to_do_idx = -1; /* Now we set everything up: @@ -730,7 +733,7 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy, } /* Currently empty destinations we can go ahead and fill */ - int ready[num_copies * 2]; + NIR_VLA(int, ready, num_copies * 2); int ready_idx = -1; /* Mark the ones that are ready for copying. We know an index is a diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h index d94866c85..3bf102fc1 100644 --- a/mesalib/src/glsl/nir/nir_intrinsics.h +++ b/mesalib/src/glsl/nir/nir_intrinsics.h @@ -68,6 +68,8 @@ INTRINSIC(interp_var_at_offset, 1, ARR(2), true, 0, 1, 0, #define BARRIER(name) INTRINSIC(name, 0, ARR(), false, 0, 0, 0, 0) BARRIER(discard) +/** A conditional discard, with a single boolean source. */ +INTRINSIC(discard_if, 1, ARR(1), false, 0, 0, 0, 0) INTRINSIC(emit_vertex, 0, ARR(), false, 0, 0, 1, 0) INTRINSIC(end_primitive, 0, ARR(), false, 0, 0, 1, 0) diff --git a/mesalib/src/glsl/nir/nir_live_variables.c b/mesalib/src/glsl/nir/nir_live_variables.c index 7402dc087..1c96dcf36 100644 --- a/mesalib/src/glsl/nir/nir_live_variables.c +++ b/mesalib/src/glsl/nir/nir_live_variables.c @@ -26,6 +26,7 @@ #include "nir.h" #include "nir_worklist.h" +#include "nir_vla.h" /* * Basic liveness analysis. This works only in SSA form. @@ -130,8 +131,8 @@ static bool propagate_across_edge(nir_block *pred, nir_block *succ, struct live_variables_state *state) { - BITSET_WORD live[state->bitset_words]; - memcpy(live, succ->live_in, sizeof live); + NIR_VLA(BITSET_WORD, live, state->bitset_words); + memcpy(live, succ->live_in, state->bitset_words * sizeof *live); nir_foreach_instr(succ, instr) { if (instr->type != nir_instr_type_phi) 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 8af753029..9e9a418e3 100644 --- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c @@ -26,6 +26,8 @@ */ #include "nir.h" +#include "nir_vla.h" + struct deref_node { struct deref_node *parent; @@ -899,8 +901,8 @@ rename_variables_block(nir_block *block, struct lower_variables_state *state) static void insert_phi_nodes(struct lower_variables_state *state) { - unsigned work[state->impl->num_blocks]; - unsigned has_already[state->impl->num_blocks]; + NIR_VLA_ZERO(unsigned, work, state->impl->num_blocks); + NIR_VLA_ZERO(unsigned, has_already, state->impl->num_blocks); /* * Since the work flags already prevent us from inserting a node that has @@ -910,10 +912,7 @@ insert_phi_nodes(struct lower_variables_state *state) * function. So all we need to handle W is an array and a pointer to the * next element to be inserted and the next element to be removed. */ - nir_block *W[state->impl->num_blocks]; - - memset(work, 0, sizeof work); - memset(has_already, 0, sizeof has_already); + NIR_VLA(nir_block *, W, state->impl->num_blocks); unsigned w_start, w_end; unsigned iter_count = 0; diff --git a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c index dd0ec01ef..ee78e5aa0 100644 --- a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c +++ b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c @@ -53,22 +53,6 @@ static bool is_move(nir_alu_instr *instr) } -static bool -is_swizzleless_move(nir_alu_instr *instr) -{ - if (!is_move(instr)) - return false; - - for (unsigned i = 0; i < 4; i++) { - if (!((instr->dest.write_mask >> i) & 1)) - break; - if (instr->src[0].swizzle[i] != i) - return false; - } - - return true; -} - static bool is_vec(nir_alu_instr *instr) { for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) @@ -80,6 +64,35 @@ static bool is_vec(nir_alu_instr *instr) instr->op == nir_op_vec4; } +static bool +is_swizzleless_move(nir_alu_instr *instr) +{ + if (is_move(instr)) { + for (unsigned i = 0; i < 4; i++) { + if (!((instr->dest.write_mask >> i) & 1)) + break; + if (instr->src[0].swizzle[i] != i) + return false; + } + return true; + } else if (is_vec(instr)) { + nir_ssa_def *def = NULL; + for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) { + if (instr->src[i].swizzle[0] != i) + return false; + + if (def == NULL) { + def = instr->src[i].src.ssa; + } else if (instr->src[i].src.ssa != def) { + return false; + } + } + return true; + } else { + return false; + } +} + typedef struct { nir_ssa_def *def; bool found; diff --git a/mesalib/src/glsl/nir/nir_opt_gcm.c b/mesalib/src/glsl/nir/nir_opt_gcm.c index bf565b969..b4f5fd3d5 100644 --- a/mesalib/src/glsl/nir/nir_opt_gcm.c +++ b/mesalib/src/glsl/nir/nir_opt_gcm.c @@ -121,9 +121,11 @@ gcm_pin_instructions_block(nir_block *block, void *void_state) case nir_op_fddy_coarse: /* These can only go in uniform control flow; pin them for now */ instr->pass_flags = GCM_INSTR_PINNED; + break; default: instr->pass_flags = 0; + break; } break; @@ -134,9 +136,11 @@ gcm_pin_instructions_block(nir_block *block, void *void_state) case nir_texop_lod: /* These two take implicit derivatives so they need to be pinned */ instr->pass_flags = GCM_INSTR_PINNED; + break; default: instr->pass_flags = 0; + break; } break; diff --git a/mesalib/src/glsl/nir/nir_vla.h b/mesalib/src/glsl/nir/nir_vla.h new file mode 100644 index 000000000..753783316 --- /dev/null +++ b/mesalib/src/glsl/nir/nir_vla.h @@ -0,0 +1,54 @@ +/************************************************************************** + * + * Copyright 2015 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#pragma once + + +#include "c99_alloca.h" + + +/* Declare a variable length array, with no initialization */ +#define NIR_VLA(_type, _name, _length) \ + _type *_name = alloca((_length) * sizeof *_name) + + +/* Declare a variable length array, and initialize it with the given byte. + * + * _length is evaluated twice, so expressions with side-effects must be + * avoided. + */ +#define NIR_VLA_FILL(_type, _name, _length, _byte) \ + _type *_name = memset(alloca((_length) * sizeof *_name), _byte, (_length) * sizeof *_name) + + +/* Declare a variable length array, and zero it. + * + * Just like NIR_VLA_FILL, _length is evaluated twice, so expressions with + * side-effects must be avoided. + */ +#define NIR_VLA_ZERO(_type, _name, _length) \ + NIR_VLA_FILL(_type, _name, _length, 0) diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 6784242ff..c6040bff8 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -744,48 +744,65 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) * a saturate operation */ for (int op = 0; op < 2; op++) { - ir_expression *minmax = op_expr[op]; + ir_expression *inner_expr = op_expr[op]; ir_constant *outer_const = op_const[1 - op]; ir_expression_operation op_cond = (ir->operation == ir_binop_max) ? ir_binop_min : ir_binop_max; - if (!minmax || !outer_const || (minmax->operation != op_cond)) + if (!inner_expr || !outer_const || (inner_expr->operation != op_cond)) continue; + /* One of these has to be a constant */ + if (!inner_expr->operands[0]->as_constant() && + !inner_expr->operands[1]->as_constant()) + break; + /* Found a min(max) combination. Now try to see if its operands * meet our conditions that we can do just a single saturate operation */ for (int minmax_op = 0; minmax_op < 2; minmax_op++) { - ir_rvalue *inner_val_a = minmax->operands[minmax_op]; - ir_rvalue *inner_val_b = minmax->operands[1 - minmax_op]; + ir_rvalue *x = inner_expr->operands[minmax_op]; + ir_rvalue *y = inner_expr->operands[1 - minmax_op]; - if (!inner_val_a || !inner_val_b) + ir_constant *inner_const = y->as_constant(); + if (!inner_const) continue; - /* Found a {min|max} ({max|min} (x, 0.0), 1.0) operation and its variations */ - if ((outer_const->is_one() && inner_val_a->is_zero()) || - (inner_val_a->is_one() && outer_const->is_zero())) - return saturate(inner_val_b); - - /* Found a {min|max} ({max|min} (x, 0.0), b) where b < 1.0 - * and its variations - */ - if (is_less_than_one(outer_const) && inner_val_b->is_zero()) - return expr(ir_binop_min, saturate(inner_val_a), outer_const); - - if (!inner_val_b->as_constant()) - continue; - - if (is_less_than_one(inner_val_b->as_constant()) && outer_const->is_zero()) - return expr(ir_binop_min, saturate(inner_val_a), inner_val_b); - - /* Found a {min|max} ({max|min} (x, b), 1.0), where b > 0.0 - * and its variations - */ - if (outer_const->is_one() && is_greater_than_zero(inner_val_b->as_constant())) - return expr(ir_binop_max, saturate(inner_val_a), inner_val_b); - if (inner_val_b->as_constant()->is_one() && is_greater_than_zero(outer_const)) - return expr(ir_binop_max, saturate(inner_val_a), outer_const); + /* min(max(x, 0.0), 1.0) is sat(x) */ + if (ir->operation == ir_binop_min && + inner_const->is_zero() && + outer_const->is_one()) + return saturate(x); + + /* max(min(x, 1.0), 0.0) is sat(x) */ + if (ir->operation == ir_binop_max && + inner_const->is_one() && + outer_const->is_zero()) + return saturate(x); + + /* min(max(x, 0.0), b) where b < 1.0 is sat(min(x, b)) */ + if (ir->operation == ir_binop_min && + inner_const->is_zero() && + is_less_than_one(outer_const)) + return saturate(expr(ir_binop_min, x, outer_const)); + + /* max(min(x, b), 0.0) where b < 1.0 is sat(min(x, b)) */ + if (ir->operation == ir_binop_max && + is_less_than_one(inner_const) && + outer_const->is_zero()) + return saturate(expr(ir_binop_min, x, inner_const)); + + /* max(min(x, 1.0), b) where b > 0.0 is sat(max(x, b)) */ + if (ir->operation == ir_binop_max && + inner_const->is_one() && + is_greater_than_zero(outer_const)) + return saturate(expr(ir_binop_max, x, outer_const)); + + /* min(max(x, b), 1.0) where b > 0.0 is sat(max(x, b)) */ + if (ir->operation == ir_binop_min && + is_greater_than_zero(inner_const) && + outer_const->is_one()) + return saturate(expr(ir_binop_max, x, inner_const)); } } @@ -849,6 +866,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) one = new(mem_ctx) ir_constant(1.0, op2_components); break; default: + one = NULL; unreachable("unexpected type"); } diff --git a/mesalib/src/glsl/opt_conditional_discard.cpp b/mesalib/src/glsl/opt_conditional_discard.cpp new file mode 100644 index 000000000..8a3ad2487 --- /dev/null +++ b/mesalib/src/glsl/opt_conditional_discard.cpp @@ -0,0 +1,81 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_conditional_discard.cpp + * + * Replace + * + * if (cond) discard; + * + * with + * + * (discard <condition>) + */ + +#include "glsl_types.h" +#include "ir.h" + +namespace { + +class opt_conditional_discard_visitor : public ir_hierarchical_visitor { +public: + opt_conditional_discard_visitor() + { + progress = false; + } + + ir_visitor_status visit_leave(ir_if *); + + bool progress; +}; + +} /* anonymous namespace */ + +bool +opt_conditional_discard(exec_list *instructions) +{ + opt_conditional_discard_visitor v; + v.run(instructions); + return v.progress; +} + +ir_visitor_status +opt_conditional_discard_visitor::visit_leave(ir_if *ir) +{ + /* Look for "if (...) discard" with no else clause or extra statements. */ + if (ir->then_instructions.is_empty() || + !ir->then_instructions.head->next->is_tail_sentinel() || + !((ir_instruction *) ir->then_instructions.head)->as_discard() || + !ir->else_instructions.is_empty()) + return visit_continue; + + /* Move the condition and replace the ir_if with the ir_discard. */ + ir_discard *discard = (ir_discard *) ir->then_instructions.head; + discard->condition = ir->condition; + ir->replace_with(discard); + + progress = true; + + return visit_continue; +} diff --git a/mesalib/src/glsl/opt_constant_folding.cpp b/mesalib/src/glsl/opt_constant_folding.cpp index 74b855e5e..4aae3f0dd 100644 --- a/mesalib/src/glsl/opt_constant_folding.cpp +++ b/mesalib/src/glsl/opt_constant_folding.cpp @@ -50,6 +50,7 @@ public: /* empty */ } + virtual ir_visitor_status visit_enter(ir_discard *ir); virtual ir_visitor_status visit_enter(ir_assignment *ir); virtual ir_visitor_status visit_enter(ir_call *ir); @@ -94,6 +95,29 @@ ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue) } ir_visitor_status +ir_constant_folding_visitor::visit_enter(ir_discard *ir) +{ + if (ir->condition) { + ir->condition->accept(this); + handle_rvalue(&ir->condition); + + ir_constant *const_val = ir->condition->as_constant(); + /* If the condition is constant, either remove the condition or + * remove the never-executed assignment. + */ + if (const_val) { + if (const_val->value.b[0]) + ir->condition = NULL; + else + ir->remove(); + this->progress = true; + } + } + + return visit_continue_with_parent; +} + +ir_visitor_status ir_constant_folding_visitor::visit_enter(ir_assignment *ir) { ir->rhs->accept(this); diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp index 2928a4db8..7eaa491e2 100644 --- a/mesalib/src/glsl/s_expression.cpp +++ b/mesalib/src/glsl/s_expression.cpp @@ -24,6 +24,7 @@ #include <assert.h> #include <limits> +#include <stdio.h> #include "s_expression.h" s_symbol::s_symbol(const char *str, size_t n) diff --git a/mesalib/src/glsl/s_expression.h b/mesalib/src/glsl/s_expression.h index 1d4753530..f0dffb1b2 100644 --- a/mesalib/src/glsl/s_expression.h +++ b/mesalib/src/glsl/s_expression.h @@ -39,8 +39,8 @@ #define SX_AS_INT(x) SX_AS_(int, x) /* Pattern matching macros */ -#define MATCH(list, pat) s_match(list, Elements(pat), pat, false) -#define PARTIAL_MATCH(list, pat) s_match(list, Elements(pat), pat, true) +#define MATCH(list, pat) s_match(list, ARRAY_SIZE(pat), pat, false) +#define PARTIAL_MATCH(list, pat) s_match(list, ARRAY_SIZE(pat), pat, true) /* For our purposes, S-Expressions are: * - <int> diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index ad0d75bf8..6f5a27f85 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -30,6 +30,7 @@ #include "standalone_scaffolding.h" #include <assert.h> +#include <stdio.h> #include <string.h> #include "util/ralloc.h" |