diff options
Diffstat (limited to 'src/compiler')
39 files changed, 662 insertions, 259 deletions
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources index 2a4568aa679..b0b8281869d 100644 --- a/src/compiler/Makefile.sources +++ b/src/compiler/Makefile.sources @@ -188,10 +188,10 @@ NIR_FILES = \ nir/nir_lower_clip.c \ nir/nir_lower_global_vars_to_local.c \ nir/nir_lower_gs_intrinsics.c \ - nir/nir_lower_indirect_derefs.c \ nir/nir_lower_load_const_to_scalar.c \ nir/nir_lower_locals_to_regs.c \ nir/nir_lower_idiv.c \ + nir/nir_lower_indirect_derefs.c \ nir/nir_lower_io.c \ nir/nir_lower_outputs_to_temporaries.c \ nir/nir_lower_phis_to_scalar.c \ diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index 9aa5bb99f49..727aa432631 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -479,6 +479,12 @@ struct ast_type_qualifier { unsigned pixel_center_integer:1; /*@}*/ + /** + * Flag set if GL_ARB_enhanced_layouts "align" layout qualifier is + * used. + */ + unsigned explicit_align:1; + /** * Flag set if GL_ARB_explicit_attrib_location "location" layout * qualifier is used. @@ -577,6 +583,11 @@ struct ast_type_qualifier { /** Precision of the type (highp/medium/lowp). */ unsigned precision:2; + /** + * Alignment specified via GL_ARB_enhanced_layouts "align" layout qualifier + */ + ast_expression *align; + /** Geometry shader invocations for GL_ARB_gpu_shader5. */ ast_layout_expression *invocations; @@ -1061,10 +1072,9 @@ public: class ast_interface_block : public ast_node { public: - ast_interface_block(ast_type_qualifier layout, - const char *instance_name, + ast_interface_block(const char *instance_name, ast_array_specifier *array_specifier) - : layout(layout), block_name(NULL), instance_name(instance_name), + : block_name(NULL), instance_name(instance_name), array_specifier(array_specifier) { } diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index db5ec9a4ad9..5262bd87655 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -4223,6 +4223,18 @@ ast_declarator_list::hir(exec_list *instructions, type_name); } else { if (decl_type->base_type == GLSL_TYPE_ARRAY) { + /* From Section 13.22 (Array Declarations) of the GLSL ES 3.2 + * spec: + * + * "... any declaration that leaves the size undefined is + * disallowed as this would add complexity and there are no + * use-cases." + */ + if (state->es_shader && decl_type->is_unsized_array()) { + _mesa_glsl_error(&loc, state, "array size must be explicitly " + "or implicitly defined"); + } + /* From Section 4.12 (Empty Declarations) of the GLSL 4.5 spec: * * "The combinations of types and qualifiers that cause @@ -6244,9 +6256,11 @@ ast_process_struct_or_iface_block_members(exec_list *instructions, ir_variable_mode var_mode, ast_type_qualifier *layout, unsigned block_stream, - unsigned expl_location) + unsigned expl_location, + unsigned expl_align) { unsigned decl_count = 0; + unsigned next_offset = 0; /* Make an initial pass over the list of fields to determine how * many there are. Each element in this list is an ast_declarator_list. @@ -6460,13 +6474,93 @@ ast_process_struct_or_iface_block_members(exec_list *instructions, } } + /* Offset can only be used with std430 and std140 layouts an initial + * value of 0 is used for error detection. + */ + unsigned align = 0; + unsigned size = 0; + if (layout) { + bool row_major; + if (qual->flags.q.row_major || + matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + row_major = true; + } else { + row_major = false; + } + + if(layout->flags.q.std140) { + align = field_type->std140_base_alignment(row_major); + size = field_type->std140_size(row_major); + } else if (layout->flags.q.std430) { + align = field_type->std430_base_alignment(row_major); + size = field_type->std430_size(row_major); + } + } + + if (qual->flags.q.explicit_offset) { + unsigned qual_offset; + if (process_qualifier_constant(state, &loc, "offset", + qual->offset, &qual_offset)) { + if (align != 0 && size != 0) { + if (next_offset > qual_offset) + _mesa_glsl_error(&loc, state, "layout qualifier " + "offset overlaps previous member"); + + if (qual_offset % align) { + _mesa_glsl_error(&loc, state, "layout qualifier offset " + "must be a multiple of the base " + "alignment of %s", field_type->name); + } + fields[i].offset = qual_offset; + next_offset = glsl_align(qual_offset + size, align); + } else { + _mesa_glsl_error(&loc, state, "offset can only be used " + "with std430 and std140 layouts"); + } + } + } else { + fields[i].offset = -1; + } + + if (qual->flags.q.explicit_align || expl_align != 0) { + unsigned offset = fields[i].offset != -1 ? fields[i].offset : + next_offset; + if (align == 0 || size == 0) { + _mesa_glsl_error(&loc, state, "align can only be used with " + "std430 and std140 layouts"); + } else if (qual->flags.q.explicit_align) { + unsigned member_align; + if (process_qualifier_constant(state, &loc, "align", + qual->align, &member_align)) { + if (member_align == 0 || + member_align & (member_align - 1)) { + _mesa_glsl_error(&loc, state, "align layout qualifier " + "in not a power of 2"); + } else { + fields[i].offset = glsl_align(offset, member_align); + next_offset = glsl_align(fields[i].offset + size, align); + } + } + } else { + fields[i].offset = glsl_align(offset, expl_align); + next_offset = glsl_align(fields[i].offset + size, align); + } + } + + if (!qual->flags.q.explicit_offset) { + if (align != 0 && size != 0) + next_offset = glsl_align(next_offset + size, align); + } + /* Propogate row- / column-major information down the fields of the * structure or interface block. Structures need this data because * the structure may contain a structure that contains ... a matrix * that need the proper layout. */ - if (field_type->without_array()->is_matrix() - || field_type->without_array()->is_record()) { + if (is_interface && + (layout->flags.q.uniform || layout->flags.q.buffer) && + (field_type->without_array()->is_matrix() + || field_type->without_array()->is_record())) { /* If no layout is specified for the field, inherit the layout * from the block. */ @@ -6477,11 +6571,10 @@ ast_process_struct_or_iface_block_members(exec_list *instructions, else if (qual->flags.q.column_major) fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; - /* If we're processing an interface block, the matrix layout must - * be decided by this point. + /* If we're processing an uniform or buffer block, the matrix + * layout must be decided by this point. */ - assert(!is_interface - || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR + assert(fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR); } @@ -6553,7 +6646,8 @@ ast_struct_specifier::hir(exec_list *instructions, ir_var_auto, layout, 0, /* for interface only */ - expl_location); + expl_location, + 0 /* for interface only */); validate_identifier(this->name, loc, state); @@ -6721,6 +6815,20 @@ ast_interface_block::hir(exec_list *instructions, } } + unsigned expl_align = 0; + if (layout.flags.q.explicit_align) { + if (!process_qualifier_constant(state, &loc, "align", + layout.align, &expl_align)) { + return NULL; + } else { + if (expl_align == 0 || expl_align & (expl_align - 1)) { + _mesa_glsl_error(&loc, state, "align layout qualifier in not a " + "power of 2."); + return NULL; + } + } + } + unsigned int num_variables = ast_process_struct_or_iface_block_members(&declared_variables, state, @@ -6732,7 +6840,8 @@ ast_interface_block::hir(exec_list *instructions, var_mode, &this->layout, qual_stream, - expl_location); + expl_location, + expl_align); if (!redeclaring_per_vertex) { validate_identifier(this->block_name, loc, state); @@ -6833,6 +6942,8 @@ ast_interface_block::hir(exec_list *instructions, } else { fields[i].location = earlier_per_vertex->fields.structure[j].location; + fields[i].offset = + earlier_per_vertex->fields.structure[j].offset; fields[i].interpolation = earlier_per_vertex->fields.structure[j].interpolation; fields[i].centroid = diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp index dcd83efa6ff..07ed4f2356c 100644 --- a/src/compiler/glsl/ast_type.cpp +++ b/src/compiler/glsl/ast_type.cpp @@ -73,6 +73,7 @@ ast_type_qualifier::has_layout() const || this->flags.q.column_major || this->flags.q.row_major || this->flags.q.packed + || this->flags.q.explicit_align || this->flags.q.explicit_location || this->flags.q.explicit_image_format || this->flags.q.explicit_index @@ -134,6 +135,28 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, stream_layout_mask.flags.i = 0; stream_layout_mask.flags.q.stream = 1; + /* FIXME: We should probably do interface and function param validation + * separately. + */ + ast_type_qualifier input_layout_mask; + input_layout_mask.flags.i = 0; + input_layout_mask.flags.q.centroid = 1; + /* Function params can have constant */ + input_layout_mask.flags.q.constant = 1; + input_layout_mask.flags.q.explicit_location = 1; + input_layout_mask.flags.q.flat = 1; + input_layout_mask.flags.q.in = 1; + input_layout_mask.flags.q.invariant = 1; + input_layout_mask.flags.q.noperspective = 1; + input_layout_mask.flags.q.origin_upper_left = 1; + /* Function params 'inout' will set this */ + input_layout_mask.flags.q.out = 1; + input_layout_mask.flags.q.patch = 1; + input_layout_mask.flags.q.pixel_center_integer = 1; + input_layout_mask.flags.q.precise = 1; + input_layout_mask.flags.q.sample = 1; + input_layout_mask.flags.q.smooth = 1; + /* Uniform block layout qualifiers get to overwrite each * other (rightmost having priority), while all other * qualifiers currently don't allow duplicates. @@ -258,6 +281,16 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, this->flags.i |= q.flags.i; + if (this->flags.q.in && + (this->flags.i & ~input_layout_mask.flags.i) != 0) { + _mesa_glsl_error(loc, state, + "invalid input layout qualifier used"); + return false; + } + + if (q.flags.q.explicit_align) + this->align = q.align; + if (q.flags.q.explicit_location) this->location = q.location; diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 0a0dcc68a05..ff6b628eb64 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -432,6 +432,12 @@ shader_atomic_counters(const _mesa_glsl_parse_state *state) } static bool +shader_atomic_counter_ops(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shader_atomic_counter_ops_enable; +} + +static bool shader_clock(const _mesa_glsl_parse_state *state) { return state->ARB_shader_clock_enable; @@ -578,7 +584,7 @@ private: ir_dereference_array *array_ref(ir_variable *var, int i); ir_swizzle *matrix_elt(ir_variable *var, int col, int row); - ir_expression *asin_expr(ir_variable *x); + ir_expression *asin_expr(ir_variable *x, float p0, float p1); void do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x); /** @@ -792,8 +798,14 @@ private: B1(interpolateAtSample) ir_function_signature *_atomic_counter_intrinsic(builtin_available_predicate avail); + ir_function_signature *_atomic_counter_intrinsic1(builtin_available_predicate avail); + ir_function_signature *_atomic_counter_intrinsic2(builtin_available_predicate avail); ir_function_signature *_atomic_counter_op(const char *intrinsic, builtin_available_predicate avail); + ir_function_signature *_atomic_counter_op1(const char *intrinsic, + builtin_available_predicate avail); + ir_function_signature *_atomic_counter_op2(const char *intrinsic, + builtin_available_predicate avail); ir_function_signature *_atomic_intrinsic2(builtin_available_predicate avail, const glsl_type *type); @@ -968,48 +980,59 @@ builtin_builder::create_intrinsics() glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), + NULL); + add_function("__intrinsic_atomic_sub", + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_min", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_max", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_and", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_or", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_xor", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_exchange", _atomic_intrinsic2(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic2(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic1(shader_atomic_counter_ops), NULL); add_function("__intrinsic_atomic_comp_swap", _atomic_intrinsic3(buffer_atomics_supported, glsl_type::uint_type), _atomic_intrinsic3(buffer_atomics_supported, glsl_type::int_type), + _atomic_counter_intrinsic2(shader_atomic_counter_ops), NULL); add_image_functions(false); @@ -2714,6 +2737,43 @@ builtin_builder::create_builtins() shader_atomic_counters), NULL); + add_function("atomicCounterAddARB", + _atomic_counter_op1("__intrinsic_atomic_add", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterSubtractARB", + _atomic_counter_op1("__intrinsic_atomic_sub", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterMinARB", + _atomic_counter_op1("__intrinsic_atomic_min", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterMaxARB", + _atomic_counter_op1("__intrinsic_atomic_max", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterAndARB", + _atomic_counter_op1("__intrinsic_atomic_and", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterOrARB", + _atomic_counter_op1("__intrinsic_atomic_or", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterXorARB", + _atomic_counter_op1("__intrinsic_atomic_xor", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterExchangeARB", + _atomic_counter_op1("__intrinsic_atomic_exchange", + shader_atomic_counter_ops), + NULL); + add_function("atomicCounterCompSwapARB", + _atomic_counter_op2("__intrinsic_atomic_comp_swap", + shader_atomic_counter_ops), + NULL); + add_function("atomicAdd", _atomic_op2("__intrinsic_atomic_add", buffer_atomics_supported, @@ -3212,7 +3272,7 @@ builtin_builder::_tan(const glsl_type *type) } ir_expression * -builtin_builder::asin_expr(ir_variable *x) +builtin_builder::asin_expr(ir_variable *x, float p0, float p1) { return mul(sign(x), sub(imm(M_PI_2f), @@ -3221,8 +3281,8 @@ builtin_builder::asin_expr(ir_variable *x) mul(abs(x), add(imm(M_PI_4f - 1.0f), mul(abs(x), - add(imm(0.086566724f), - mul(abs(x), imm(-0.03102955f)))))))))); + add(imm(p0), + mul(abs(x), imm(p1)))))))))); } ir_call * @@ -3251,7 +3311,7 @@ builtin_builder::_asin(const glsl_type *type) ir_variable *x = in_var(type, "x"); MAKE_SIG(type, always_available, 1, x); - body.emit(ret(asin_expr(x))); + body.emit(ret(asin_expr(x, 0.086566724f, -0.03102955f))); return sig; } @@ -3262,7 +3322,7 @@ builtin_builder::_acos(const glsl_type *type) ir_variable *x = in_var(type, "x"); MAKE_SIG(type, always_available, 1, x); - body.emit(ret(sub(imm(M_PI_2f), asin_expr(x)))); + body.emit(ret(sub(imm(M_PI_2f), asin_expr(x, 0.08132463f, -0.02363318f)))); return sig; } @@ -5145,6 +5205,25 @@ builtin_builder::_atomic_counter_intrinsic(builtin_available_predicate avail) } ir_function_signature * +builtin_builder::_atomic_counter_intrinsic1(builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter"); + ir_variable *data = in_var(glsl_type::uint_type, "data"); + MAKE_INTRINSIC(glsl_type::uint_type, avail, 2, counter, data); + return sig; +} + +ir_function_signature * +builtin_builder::_atomic_counter_intrinsic2(builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter"); + ir_variable *compare = in_var(glsl_type::uint_type, "compare"); + ir_variable *data = in_var(glsl_type::uint_type, "data"); + MAKE_INTRINSIC(glsl_type::uint_type, avail, 3, counter, compare, data); + return sig; +} + +ir_function_signature * builtin_builder::_atomic_intrinsic2(builtin_available_predicate avail, const glsl_type *type) { @@ -5180,6 +5259,37 @@ builtin_builder::_atomic_counter_op(const char *intrinsic, } ir_function_signature * +builtin_builder::_atomic_counter_op1(const char *intrinsic, + builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter"); + ir_variable *data = in_var(glsl_type::uint_type, "data"); + MAKE_SIG(glsl_type::uint_type, avail, 2, counter, data); + + ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval"); + body.emit(call(shader->symbols->get_function(intrinsic), retval, + sig->parameters)); + body.emit(ret(retval)); + return sig; +} + +ir_function_signature * +builtin_builder::_atomic_counter_op2(const char *intrinsic, + builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter"); + ir_variable *compare = in_var(glsl_type::uint_type, "compare"); + ir_variable *data = in_var(glsl_type::uint_type, "data"); + MAKE_SIG(glsl_type::uint_type, avail, 3, counter, compare, data); + + ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval"); + body.emit(call(shader->symbols->get_function(intrinsic), retval, + sig->parameters)); + body.emit(ret(retval)); + return sig; +} + +ir_function_signature * builtin_builder::_atomic_op2(const char *intrinsic, builtin_available_predicate avail, const glsl_type *type) diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp index d20fc4a816c..4e2de37fbba 100644 --- a/src/compiler/glsl/builtin_variables.cpp +++ b/src/compiler/glsl/builtin_variables.cpp @@ -323,6 +323,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type, this->fields[this->num_fields].name = name; this->fields[this->num_fields].matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED; this->fields[this->num_fields].location = slot; + this->fields[this->num_fields].offset = -1; this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE; this->fields[this->num_fields].centroid = 0; this->fields[this->num_fields].sample = 0; diff --git a/src/compiler/glsl/glcpp/glcpp-lex.l b/src/compiler/glsl/glcpp/glcpp-lex.l index fa9aa506912..d09441aac88 100644 --- a/src/compiler/glsl/glcpp/glcpp-lex.l +++ b/src/compiler/glsl/glcpp/glcpp-lex.l @@ -120,6 +120,11 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); static int glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token) { + if (token != NEWLINE && token != SPACE && token != HASH_TOKEN && + !parser->lexing_version_directive) { + glcpp_parser_resolve_implicit_version(parser); + } + /* After the first non-space token in a line, we won't * allow any '#' to introduce a directive. */ if (token == NEWLINE) { @@ -285,6 +290,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? <HASH>version{HSPACE}+ { BEGIN INITIAL; yyextra->space_tokens = 0; + yyextra->lexing_version_directive = 1; RETURN_STRING_TOKEN (VERSION_TOKEN); } @@ -314,6 +320,9 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? <HASH>{NEWLINE} { BEGIN INITIAL; + yyextra->space_tokens = 0; + yylineno++; + yycolumn = 0; RETURN_TOKEN_NEVER_SKIP (NEWLINE); } @@ -536,6 +545,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } yyextra->space_tokens = 1; yyextra->lexing_directive = 0; + yyextra->lexing_version_directive = 0; yylineno++; yycolumn = 0; RETURN_TOKEN_NEVER_SKIP (NEWLINE); @@ -546,6 +556,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? glcpp_error(yylloc, yyextra, "Unterminated comment"); BEGIN DONE; /* Don't keep matching this rule forever. */ yyextra->lexing_directive = 0; + yyextra->lexing_version_directive = 0; if (! parser->last_token_was_newline) RETURN_TOKEN (NEWLINE); } diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index 5c38f86d333..007b70b020d 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -266,45 +266,37 @@ control_line: ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); } | control_line_error -| HASH_TOKEN LINE { - glcpp_parser_resolve_implicit_version(parser); - } pp_tokens NEWLINE { +| HASH_TOKEN LINE pp_tokens NEWLINE { if (parser->skip_stack == NULL || parser->skip_stack->type == SKIP_NO_SKIP) { _glcpp_parser_expand_and_lex_from (parser, - LINE_EXPANDED, $4, + LINE_EXPANDED, $3, EXPANSION_MODE_IGNORE_DEFINED); } } ; control_line_success: - HASH_TOKEN DEFINE_TOKEN { - glcpp_parser_resolve_implicit_version(parser); - } define -| HASH_TOKEN UNDEF { - glcpp_parser_resolve_implicit_version(parser); - } IDENTIFIER NEWLINE { + HASH_TOKEN DEFINE_TOKEN define +| HASH_TOKEN UNDEF IDENTIFIER NEWLINE { macro_t *macro; - if (strcmp("__LINE__", $4) == 0 - || strcmp("__FILE__", $4) == 0 - || strcmp("__VERSION__", $4) == 0 - || strncmp("GL_", $4, 3) == 0) + if (strcmp("__LINE__", $3) == 0 + || strcmp("__FILE__", $3) == 0 + || strcmp("__VERSION__", $3) == 0 + || strncmp("GL_", $3, 3) == 0) glcpp_error(& @1, parser, "Built-in (pre-defined)" " macro names cannot be undefined."); - macro = hash_table_find (parser->defines, $4); + macro = hash_table_find (parser->defines, $3); if (macro) { - hash_table_remove (parser->defines, $4); + hash_table_remove (parser->defines, $3); ralloc_free (macro); } - ralloc_free ($4); + ralloc_free ($3); } -| HASH_TOKEN IF { - glcpp_parser_resolve_implicit_version(parser); - } pp_tokens NEWLINE { +| HASH_TOKEN IF pp_tokens NEWLINE { /* Be careful to only evaluate the 'if' expression if * we are not skipping. When we are skipping, we * simply push a new 0-valued 'if' onto the skip @@ -316,7 +308,7 @@ control_line_success: parser->skip_stack->type == SKIP_NO_SKIP) { _glcpp_parser_expand_and_lex_from (parser, - IF_EXPANDED, $4, + IF_EXPANDED, $3, EXPANSION_MODE_EVALUATE_DEFINED); } else @@ -335,18 +327,14 @@ control_line_success: } _glcpp_parser_skip_stack_push_if (parser, & @1, 0); } -| HASH_TOKEN IFDEF { - glcpp_parser_resolve_implicit_version(parser); - } IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $4); - ralloc_free ($4); +| HASH_TOKEN IFDEF IDENTIFIER junk NEWLINE { + macro_t *macro = hash_table_find (parser->defines, $3); + ralloc_free ($3); _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); } -| HASH_TOKEN IFNDEF { - glcpp_parser_resolve_implicit_version(parser); - } IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $4); - ralloc_free ($4); +| HASH_TOKEN IFNDEF IDENTIFIER junk NEWLINE { + macro_t *macro = hash_table_find (parser->defines, $3); + ralloc_free ($3); _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL); } | HASH_TOKEN ELIF pp_tokens NEWLINE { @@ -2494,6 +2482,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_shader_atomic_counters) add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); + if (extensions->ARB_shader_atomic_counter_ops) + add_builtin_define(parser, "GL_ARB_shader_atomic_counter_ops", 1); + if (extensions->ARB_viewport_array) add_builtin_define(parser, "GL_ARB_viewport_array", 1); diff --git a/src/compiler/glsl/glcpp/glcpp.h b/src/compiler/glsl/glcpp/glcpp.h index 70aa14b6ec0..d87e6b77dc5 100644 --- a/src/compiler/glsl/glcpp/glcpp.h +++ b/src/compiler/glsl/glcpp/glcpp.h @@ -176,6 +176,7 @@ struct glcpp_parser { struct hash_table *defines; active_list_t *active; int lexing_directive; + int lexing_version_directive; int space_tokens; int last_token_was_newline; int last_token_was_space; diff --git a/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected b/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected index fd0b41347fa..5206a5c553c 100644 --- a/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected +++ b/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected @@ -1,2 +1,2 @@ 0:1(9): preprocessor error: #define followed by a non-identifier: 123 -0:1(9): preprocessor error: syntax error, unexpected INTEGER_STRING, expecting FUNC_IDENTIFIER or OBJ_IDENTIFIER +0:1(9): preprocessor error: syntax error, unexpected INTEGER_STRING, expecting FUNC_IDENTIFIER or OBJ_IDENTIFIER or NEWLINE diff --git a/src/compiler/glsl/glcpp/tests/144-implicit-version.c b/src/compiler/glsl/glcpp/tests/144-implicit-version.c new file mode 100644 index 00000000000..7bf72fc19e9 --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/144-implicit-version.c @@ -0,0 +1 @@ +int x = __VERSION__; diff --git a/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected b/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected new file mode 100644 index 00000000000..8c2dfd9ce30 --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected @@ -0,0 +1 @@ +int x = 110; diff --git a/src/compiler/glsl/glcpp/tests/145-version-first.c b/src/compiler/glsl/glcpp/tests/145-version-first.c new file mode 100644 index 00000000000..f9fcfb08246 --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/145-version-first.c @@ -0,0 +1,2 @@ +123 +#version 120 diff --git a/src/compiler/glsl/glcpp/tests/145-version-first.c.expected b/src/compiler/glsl/glcpp/tests/145-version-first.c.expected new file mode 100644 index 00000000000..f4092b04af7 --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/145-version-first.c.expected @@ -0,0 +1,3 @@ +0:2(1): preprocessor error: #version must appear on the first line +123 + diff --git a/src/compiler/glsl/glcpp/tests/146-version-first-hash.c b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c new file mode 100644 index 00000000000..14dbe964bd6 --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c @@ -0,0 +1,2 @@ +# +#version 120 diff --git a/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected new file mode 100644 index 00000000000..e8e449793fd --- /dev/null +++ b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected @@ -0,0 +1,3 @@ +0:2(1): preprocessor error: #version must appear on the first line + + diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index 99bd0e61d0e..5ed051a6705 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -170,7 +170,6 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER %type <identifier> any_identifier %type <interface_block> instance_name_opt -%type <interface_block> buffer_instance_name_opt %token <real> FLOATCONSTANT %token <dreal> DOUBLECONSTANT %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT @@ -220,6 +219,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %type <type_qualifier> subroutine_qualifier %type <subroutine_list> subroutine_type_list %type <type_qualifier> interface_qualifier +%type <type_qualifier> uniform_interface_qualifier %type <type_qualifier> buffer_interface_qualifier %type <type_specifier> type_specifier %type <type_specifier> type_specifier_nonarray @@ -894,6 +894,7 @@ parameter_declarator: $$->type->set_location(@1); $$->type->specifier = $1; $$->identifier = $2; + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } | type_specifier any_identifier array_specifier { @@ -905,6 +906,7 @@ parameter_declarator: $$->type->specifier = $1; $$->identifier = $2; $$->array_specifier = $3; + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } ; @@ -1062,6 +1064,7 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location_range(@1, @2); $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } | fully_specified_type any_identifier array_specifier { @@ -1072,6 +1075,7 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location_range(@1, @3); $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } | fully_specified_type any_identifier array_specifier '=' initializer { @@ -1082,6 +1086,7 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location_range(@1, @3); $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } | fully_specified_type any_identifier '=' initializer { @@ -1092,6 +1097,7 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location_range(@1, @2); $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto)); } | INVARIANT variable_identifier { @@ -1468,6 +1474,17 @@ layout_qualifier_id: "GLSL 4.40 or ARB_enhanced_layouts"); } + if (match_layout_qualifier("align", $1, state) == 0) { + if (!state->has_enhanced_layouts()) { + _mesa_glsl_error(& @1, state, + "align qualifier requires " + "GLSL 4.40 or ARB_enhanced_layouts"); + } else { + $$.flags.q.explicit_align = 1; + $$.align = $3; + } + } + if (match_layout_qualifier("location", $1, state) == 0) { $$.flags.q.explicit_location = 1; @@ -1498,7 +1515,8 @@ layout_qualifier_id: $$.binding = $3; } - if (state->has_atomic_counters() && + if ((state->has_atomic_counters() || + state->has_enhanced_layouts()) && match_layout_qualifier("offset", $1, state) == 0) { $$.flags.q.explicit_offset = 1; $$.offset = $3; @@ -2625,10 +2643,23 @@ basic_interface_block: $$ = block; } - | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' buffer_instance_name_opt ';' + | uniform_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';' + { + ast_interface_block *const block = $6; + + block->layout = *state->default_uniform_qualifier; + block->block_name = $2; + block->declarations.push_degenerate_list_at_head(& $4->link); + + _mesa_ast_process_interface_block(& @1, state, block, $1); + + $$ = block; + } + | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';' { ast_interface_block *const block = $6; + block->layout = *state->default_shader_storage_qualifier; block->block_name = $2; block->declarations.push_degenerate_list_at_head(& $4->link); @@ -2649,7 +2680,10 @@ interface_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.out = 1; } - | UNIFORM + ; + +uniform_interface_qualifier: + UNIFORM { memset(& $$, 0, sizeof($$)); $$.flags.q.uniform = 1; @@ -2667,39 +2701,16 @@ buffer_interface_qualifier: instance_name_opt: /* empty */ { - $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - NULL, NULL); - } - | NEW_IDENTIFIER - { - $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - $1, NULL); - $$->set_location(@1); - } - | NEW_IDENTIFIER array_specifier - { - $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - $1, $2); - $$->set_location_range(@1, @2); - } - ; - -buffer_instance_name_opt: - /* empty */ - { - $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, - NULL, NULL); + $$ = new(state) ast_interface_block(NULL, NULL); } | NEW_IDENTIFIER { - $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, - $1, NULL); + $$ = new(state) ast_interface_block($1, NULL); $$->set_location(@1); } | NEW_IDENTIFIER array_specifier { - $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, - $1, $2); + $$ = new(state) ast_interface_block($1, $2); $$->set_location_range(@1, @2); } ; diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index fe8b3bb2e79..1ac8489b45a 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -575,6 +575,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_gpu_shader_fp64, true, false, ARB_gpu_shader_fp64), EXT(ARB_sample_shading, true, false, ARB_sample_shading), EXT(ARB_separate_shader_objects, true, false, dummy_true), + EXT(ARB_shader_atomic_counter_ops, true, false, ARB_shader_atomic_counter_ops), EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters), EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding), EXT(ARB_shader_clock, true, false, ARB_shader_clock), @@ -926,7 +927,8 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, block->layout.flags.i |= block_interface_qualifier; if (state->stage == MESA_SHADER_GEOMETRY && - state->has_explicit_attrib_stream()) { + state->has_explicit_attrib_stream() && + block->layout.flags.q.out) { /* Assign global layout's stream value. */ block->layout.flags.q.stream = 1; block->layout.flags.q.explicit_stream = 0; diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index 74825a0bd35..12a3a46928c 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -533,6 +533,8 @@ struct _mesa_glsl_parse_state { bool ARB_sample_shading_warn; bool ARB_separate_shader_objects_enable; bool ARB_separate_shader_objects_warn; + bool ARB_shader_atomic_counter_ops_enable; + bool ARB_shader_atomic_counter_ops_warn; bool ARB_shader_atomic_counters_enable; bool ARB_shader_atomic_counters_warn; bool ARB_shader_bit_encoding_enable; diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index f6ed16de0c3..f4519679ff3 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -866,7 +866,7 @@ public: unsigned stream; /** - * Location an atomic counter is stored at. + * Atomic or block member offset. */ unsigned offset; diff --git a/src/compiler/glsl/ir_builder.cpp b/src/compiler/glsl/ir_builder.cpp index c9cf1240dfe..d68647f4234 100644 --- a/src/compiler/glsl/ir_builder.cpp +++ b/src/compiler/glsl/ir_builder.cpp @@ -51,7 +51,7 @@ assign(deref lhs, operand rhs, operand condition, int writemask) void *mem_ctx = ralloc_parent(lhs.val); ir_assignment *assign = new(mem_ctx) ir_assignment(lhs.val, - rhs.val, + rhs.val, condition.val, writemask); @@ -89,11 +89,11 @@ swizzle(operand a, int swizzle, int components) void *mem_ctx = ralloc_parent(a.val); return new(mem_ctx) ir_swizzle(a.val, - GET_SWZ(swizzle, 0), - GET_SWZ(swizzle, 1), - GET_SWZ(swizzle, 2), - GET_SWZ(swizzle, 3), - components); + GET_SWZ(swizzle, 0), + GET_SWZ(swizzle, 1), + GET_SWZ(swizzle, 2), + GET_SWZ(swizzle, 3), + components); } ir_swizzle * diff --git a/src/compiler/glsl/link_interface_blocks.cpp b/src/compiler/glsl/link_interface_blocks.cpp index 64c30fea9a3..4c6fb56f891 100644 --- a/src/compiler/glsl/link_interface_blocks.cpp +++ b/src/compiler/glsl/link_interface_blocks.cpp @@ -81,6 +81,66 @@ intrastage_match(ir_variable *a, return true; } +/** + * Return true if interface members mismatch and its not allowed by GLSL. + */ +static bool +interstage_member_mismatch(struct gl_shader_program *prog, + const glsl_type *c, const glsl_type *p) { + + if (c->length != p->length) + return true; + + for (unsigned i = 0; i < c->length; i++) { + if (c->fields.structure[i].type != p->fields.structure[i].type) + return true; + if (strcmp(c->fields.structure[i].name, + p->fields.structure[i].name) != 0) + return true; + if (c->fields.structure[i].location != + p->fields.structure[i].location) + return true; + if (c->fields.structure[i].patch != + p->fields.structure[i].patch) + return true; + + /* From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.40 spec: + * + * "It is a link-time error if, within the same stage, the + * interpolation qualifiers of variables of the same name do not + * match." + */ + if (prog->IsES || prog->Version < 440) + if (c->fields.structure[i].interpolation != + p->fields.structure[i].interpolation) + return true; + + /* From Section 4.3.4 (Input Variables) of the GLSL ES 3.0 spec: + * + * "The output of the vertex shader and the input of the fragment + * shader form an interface. For this interface, vertex shader + * output variables and fragment shader input variables of the same + * name must match in type and qualification (other than precision + * and out matching to in). + * + * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.1 spec + * says that centroid no longer needs to match for varyings. + * + * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.2 spec + * says that sample need not match for varyings. + */ + if (!prog->IsES || prog->Version < 310) + if (c->fields.structure[i].centroid != + p->fields.structure[i].centroid) + return true; + if (!prog->IsES) + if (c->fields.structure[i].sample != + p->fields.structure[i].sample) + return true; + } + + return false; +} /** * Check if two interfaces match, according to interstage (in/out) interface @@ -90,10 +150,9 @@ intrastage_match(ir_variable *a, * an array and the producer interface is required to be a non-array. * This is used for tessellation control and geometry shader consumers. */ -bool -interstage_match(ir_variable *producer, - ir_variable *consumer, - bool extra_array_level) +static bool +interstage_match(struct gl_shader_program *prog, ir_variable *producer, + ir_variable *consumer, bool extra_array_level) { /* Unsized arrays should not occur during interstage linking. They * should have all been assigned a size by link_intrastage_shaders. @@ -106,9 +165,16 @@ interstage_match(ir_variable *producer, /* Exception: if both the interface blocks are implicitly declared, * don't force their types to match. They might mismatch due to the two * shaders using different GLSL versions, and that's ok. + * + * Also we store some member information such as interpolation in + * glsl_type that doesn't always have to match across shader stages. + * Therefore we make a pass over the members glsl_struct_field to make + * sure we don't reject shaders where fields don't need to match. */ - if (consumer->data.how_declared != ir_var_declared_implicitly || - producer->data.how_declared != ir_var_declared_implicitly) + if ((consumer->data.how_declared != ir_var_declared_implicitly || + producer->data.how_declared != ir_var_declared_implicitly) && + interstage_member_mismatch(prog, consumer->get_interface_type(), + producer->get_interface_type())) return false; } @@ -311,7 +377,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog, if (consumer_def == NULL) continue; - if (!interstage_match(var, consumer_def, extra_array_level)) { + if (!interstage_match(prog, var, consumer_def, extra_array_level)) { linker_error(prog, "definitions of interface block `%s' do not " "match\n", var->get_interface_type()->name); return; diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp index 7d755765852..c8fa181a15d 100644 --- a/src/compiler/glsl/link_uniform_blocks.cpp +++ b/src/compiler/glsl/link_uniform_blocks.cpp @@ -97,6 +97,11 @@ private: this->offset, type->std140_base_alignment(row_major)); } + virtual void set_buffer_offset(unsigned offset) + { + this->offset = offset; + } + virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *, const unsigned packing, diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index deaba94df1c..940cc61181d 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -188,12 +188,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, this->enter_record(t, *name, row_major, packing); for (unsigned i = 0; i < t->length; i++) { - const char *field = t->fields.structure[i].name; - size_t new_length = name_length; + const char *field = t->fields.structure[i].name; + size_t new_length = name_length; if (t->fields.structure[i].type->is_record()) this->visit_field(&t->fields.structure[i]); + if (t->is_interface() && t->fields.structure[i].offset != -1) + this->set_buffer_offset(t->fields.structure[i].offset); + /* Append '.field' to the current variable name. */ if (name_length == 0) { ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field); @@ -247,10 +250,10 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, record_array_count *= length; for (unsigned i = 0; i < length; i++) { - size_t new_length = name_length; + size_t new_length = name_length; - /* Append the subscript to the current variable name */ - ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i); + /* Append the subscript to the current variable name */ + ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i); recursion(t->fields.array, name, new_length, row_major, record_type, @@ -298,6 +301,11 @@ program_resource_visitor::leave_record(const glsl_type *, const char *, bool, } void +program_resource_visitor::set_buffer_offset(unsigned) +{ +} + +void program_resource_visitor::set_record_array_count(unsigned) { } @@ -415,19 +423,19 @@ private: if(!is_shader_storage) this->num_shader_uniform_components += values; } else { - /* Accumulate the total number of uniform slots used by this shader. - * Note that samplers do not count against this limit because they - * don't use any storage on current hardware. - */ - if (!is_ubo_var && !is_shader_storage) - this->num_shader_uniform_components += values; + /* Accumulate the total number of uniform slots used by this shader. + * Note that samplers do not count against this limit because they + * don't use any storage on current hardware. + */ + if (!is_ubo_var && !is_shader_storage) + this->num_shader_uniform_components += values; } /* If the uniform is already in the map, there's nothing more to do. */ unsigned id; if (this->map->get(id, name)) - return; + return; if (this->current_var->data.how_declared == ir_var_hidden) { this->hidden_map->put(this->num_hidden_uniforms, name); @@ -473,8 +481,8 @@ class parcel_out_uniform_storage : public program_resource_visitor { public: parcel_out_uniform_storage(struct gl_shader_program *prog, struct string_to_uint_map *map, - struct gl_uniform_storage *uniforms, - union gl_constant_value *values) + struct gl_uniform_storage *uniforms, + union gl_constant_value *values) : prog(prog), map(map), uniforms(uniforms), values(values) { } @@ -520,9 +528,9 @@ public: ubo_block_index = i; break; } - } - } - assert(ubo_block_index != -1); + } + } + assert(ubo_block_index != -1); /* Uniform blocks that were specified with an instance name must be * handled a little bit differently. The name of the variable is the @@ -676,6 +684,11 @@ private: } } + virtual void set_buffer_offset(unsigned offset) + { + this->ubo_byte_offset = offset; + } + virtual void set_record_array_count(unsigned record_array_count) { this->record_array_count = record_array_count; @@ -730,15 +743,15 @@ private: assert(found); if (!found) - return; + return; const glsl_type *base_type; if (type->is_array()) { - this->uniforms[id].array_elements = type->length; - base_type = type->fields.array; + this->uniforms[id].array_elements = type->length; + base_type = type->fields.array; } else { - this->uniforms[id].array_elements = 0; - base_type = type; + this->uniforms[id].array_elements = 0; + base_type = type; } /* Initialise opaque data */ @@ -822,11 +835,11 @@ private: this->uniforms[id].array_stride = glsl_align(type->without_array()->std140_size(row_major), 16); - } else { - this->uniforms[id].array_stride = 0; - } + } else { + this->uniforms[id].array_stride = 0; + } - if (type->without_array()->is_matrix()) { + if (type->without_array()->is_matrix()) { const glsl_type *matrix = type->without_array(); const unsigned N = matrix->base_type == GLSL_TYPE_DOUBLE ? 8 : 4; const unsigned items = @@ -838,17 +851,17 @@ private: glsl_align(items * N, 16); else this->uniforms[id].matrix_stride = glsl_align(items * N, 16); - this->uniforms[id].row_major = row_major; - } else { - this->uniforms[id].matrix_stride = 0; - this->uniforms[id].row_major = false; - } + this->uniforms[id].row_major = row_major; + } else { + this->uniforms[id].matrix_stride = 0; + this->uniforms[id].row_major = false; + } } else { - this->uniforms[id].block_index = -1; - this->uniforms[id].offset = -1; - this->uniforms[id].array_stride = -1; - this->uniforms[id].matrix_stride = -1; - this->uniforms[id].row_major = false; + this->uniforms[id].block_index = -1; + this->uniforms[id].offset = -1; + this->uniforms[id].array_stride = -1; + this->uniforms[id].matrix_stride = -1; + this->uniforms[id].row_major = false; } this->values += values_for_type(type); @@ -914,36 +927,36 @@ public: */ int link_cross_validate_uniform_block(void *mem_ctx, - struct gl_uniform_block **linked_blocks, - unsigned int *num_linked_blocks, - struct gl_uniform_block *new_block) + struct gl_uniform_block **linked_blocks, + unsigned int *num_linked_blocks, + struct gl_uniform_block *new_block) { for (unsigned int i = 0; i < *num_linked_blocks; i++) { struct gl_uniform_block *old_block = &(*linked_blocks)[i]; if (strcmp(old_block->Name, new_block->Name) == 0) - return link_uniform_blocks_are_compatible(old_block, new_block) - ? i : -1; + return link_uniform_blocks_are_compatible(old_block, new_block) + ? i : -1; } *linked_blocks = reralloc(mem_ctx, *linked_blocks, - struct gl_uniform_block, - *num_linked_blocks + 1); + struct gl_uniform_block, + *num_linked_blocks + 1); int linked_block_index = (*num_linked_blocks)++; struct gl_uniform_block *linked_block = &(*linked_blocks)[linked_block_index]; memcpy(linked_block, new_block, sizeof(*new_block)); linked_block->Uniforms = ralloc_array(*linked_blocks, - struct gl_uniform_buffer_variable, - linked_block->NumUniforms); + struct gl_uniform_buffer_variable, + linked_block->NumUniforms); memcpy(linked_block->Uniforms, - new_block->Uniforms, - sizeof(*linked_block->Uniforms) * linked_block->NumUniforms); + new_block->Uniforms, + sizeof(*linked_block->Uniforms) * linked_block->NumUniforms); for (unsigned int i = 0; i < linked_block->NumUniforms; i++) { struct gl_uniform_buffer_variable *ubo_var = - &linked_block->Uniforms[i]; + &linked_block->Uniforms[i]; if (ubo_var->Name == ubo_var->IndexName) { ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name); @@ -970,7 +983,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) ir_variable *const var = node->as_variable(); if ((var == NULL) || !var->is_in_buffer_block()) - continue; + continue; assert(var->data.mode == ir_var_uniform || var->data.mode == ir_var_shader_storage); @@ -992,7 +1005,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) const unsigned l = strlen(var->name); for (unsigned i = 0; i < shader->NumBufferInterfaceBlocks; i++) { - for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i].NumUniforms; j++) { + for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i].NumUniforms; j++) { if (sentinel) { const char *begin = shader->BufferInterfaceBlocks[i].Uniforms[j].Name; const char *end = strchr(begin, sentinel); @@ -1010,13 +1023,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) } } else if (!strcmp(var->name, shader->BufferInterfaceBlocks[i].Uniforms[j].Name)) { - found = true; - var->data.location = j; - break; - } - } - if (found) - break; + found = true; + var->data.location = j; + break; + } + } + if (found) + break; } assert(found); } @@ -1099,7 +1112,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog, struct gl_shader *sh = prog->_LinkedShaders[i]; if (sh == NULL) - continue; + continue; /* Uniforms that lack an initializer in the shader code have an initial * value of zero. This includes sampler uniforms. @@ -1120,13 +1133,13 @@ link_assign_uniform_locations(struct gl_shader_program *prog, uniform_size.start_shader(); foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *const var = node->as_variable(); + ir_variable *const var = node->as_variable(); - if ((var == NULL) || (var->data.mode != ir_var_uniform && - var->data.mode != ir_var_shader_storage)) - continue; + if ((var == NULL) || (var->data.mode != ir_var_uniform && + var->data.mode != ir_var_shader_storage)) + continue; - uniform_size.process(var); + uniform_size.process(var); } sh->num_samplers = uniform_size.num_shader_samplers; @@ -1136,8 +1149,8 @@ link_assign_uniform_locations(struct gl_shader_program *prog, for (unsigned i = 0; i < sh->NumBufferInterfaceBlocks; i++) { if (!sh->BufferInterfaceBlocks[i].IsShaderStorage) { - sh->num_combined_uniform_components += - sh->BufferInterfaceBlocks[i].UniformBufferSize / 4; + sh->num_combined_uniform_components += + sh->BufferInterfaceBlocks[i].UniformBufferSize / 4; } } } @@ -1170,18 +1183,18 @@ link_assign_uniform_locations(struct gl_shader_program *prog, for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i] == NULL) - continue; + continue; parcel.start_shader((gl_shader_stage)i); foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) { - ir_variable *const var = node->as_variable(); + ir_variable *const var = node->as_variable(); if ((var == NULL) || (var->data.mode != ir_var_uniform && var->data.mode != ir_var_shader_storage)) - continue; + continue; - parcel.set_and_process(var); + parcel.set_and_process(var); } prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used; diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 05cc1a2b7f8..34eb848a9c1 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -219,7 +219,7 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog, */ void cross_validate_outputs_to_inputs(struct gl_shader_program *prog, - gl_shader *producer, gl_shader *consumer) + gl_shader *producer, gl_shader *consumer) { glsl_symbol_table parameters; ir_variable *explicit_locations[MAX_VARYING] = { NULL, }; @@ -312,8 +312,14 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, } if (output != NULL) { - cross_validate_types_and_qualifiers(prog, input, output, - consumer->Stage, producer->Stage); + /* Interface blocks have their own validation elsewhere so don't + * try validating them here. + */ + if (!(input->get_interface_type() && + output->get_interface_type())) + cross_validate_types_and_qualifiers(prog, input, output, + consumer->Stage, + producer->Stage); } else { /* Check for input vars with unmatched output vars in prev stage * taking into account that interface blocks could have a matching @@ -348,7 +354,7 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object, ir_variable *const var = node->as_variable(); if ((var == NULL) || (var->data.mode != int(mode))) - continue; + continue; /* A shader 'in' or 'out' variable is only really an input or output if * its value is used by other shader stages. This will cause the @@ -356,7 +362,7 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object, */ if (var->data.is_unmatched_generic_inout) { assert(var->data.mode != ir_var_temporary); - var->data.mode = ir_var_auto; + var->data.mode = ir_var_auto; } } @@ -748,8 +754,8 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, prog->LinkedTransformFeedback.Varyings = rzalloc_array(prog, - struct gl_transform_feedback_varying_info, - num_tfeedback_decls); + struct gl_transform_feedback_varying_info, + num_tfeedback_decls); unsigned num_outputs = 0; for (unsigned i = 0; i < num_tfeedback_decls; ++i) @@ -1561,9 +1567,9 @@ reserved_varying_slot(struct gl_shader *stage, ir_variable_mode io_mode) */ bool assign_varying_locations(struct gl_context *ctx, - void *mem_ctx, - struct gl_shader_program *prog, - gl_shader *producer, gl_shader *consumer, + void *mem_ctx, + struct gl_shader_program *prog, + gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { @@ -1755,7 +1761,7 @@ assign_varying_locations(struct gl_context *ctx, linker_error(prog, "%s shader varying %s not written " "by %s shader\n.", _mesa_shader_stage_to_string(consumer->Stage), - var->name, + var->name, _mesa_shader_stage_to_string(producer->Stage)); } else { linker_warning(prog, "%s shader varying %s not written " diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 3039232162a..76b700d3451 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -2417,7 +2417,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, /* Reversed because we want a descending order sort below. */ return r->slots - l->slots; } - } to_assign[16]; + } to_assign[32]; + assert(max_index <= 32); unsigned num_attr = 0; @@ -2625,6 +2626,13 @@ assign_attribute_or_color_locations(gl_shader_program *prog, continue; } + if (num_attr >= max_index) { + linker_error(prog, "too many %s (max %u)", + target_index == MESA_SHADER_VERTEX ? + "vertex shader inputs" : "fragment shader outputs", + max_index); + return false; + } to_assign[num_attr].slots = slots; to_assign[num_attr].var = var; num_attr++; diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h index a60bb6ed087..4311d1659ec 100644 --- a/src/compiler/glsl/linker.h +++ b/src/compiler/glsl/linker.h @@ -182,6 +182,8 @@ protected: virtual void leave_record(const glsl_type *type, const char *name, bool row_major, const unsigned packing); + virtual void set_buffer_offset(unsigned offset); + virtual void set_record_array_count(unsigned record_array_count); private: diff --git a/src/compiler/glsl/lower_buffer_access.cpp b/src/compiler/glsl/lower_buffer_access.cpp index 9ad811de9f1..f85b421cf27 100644 --- a/src/compiler/glsl/lower_buffer_access.cpp +++ b/src/compiler/glsl/lower_buffer_access.cpp @@ -440,6 +440,10 @@ lower_buffer_access::setup_buffer_access(void *mem_ctx, else field_align = type->std140_base_alignment(field_row_major); + if (struct_type->fields.structure[i].offset != -1) { + intra_struct_offset = struct_type->fields.structure[i].offset; + } + intra_struct_offset = glsl_align(intra_struct_offset, field_align); if (strcmp(struct_type->fields.structure[i].name, diff --git a/src/compiler/glsl/opt_array_splitting.cpp b/src/compiler/glsl/opt_array_splitting.cpp index cceec6b6431..a294da56616 100644 --- a/src/compiler/glsl/opt_array_splitting.cpp +++ b/src/compiler/glsl/opt_array_splitting.cpp @@ -55,9 +55,9 @@ public: this->components = NULL; this->mem_ctx = NULL; if (var->type->is_array()) - this->size = var->type->length; + this->size = var->type->length; else - this->size = var->type->matrix_columns; + this->size = var->type->matrix_columns; } ir_variable *var; /* The key: the variable's pointer. */ @@ -137,7 +137,7 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var) foreach_in_list(variable_entry, entry, &this->variable_list) { if (entry->var == var) - return entry; + return entry; } variable_entry *entry = new(mem_ctx) variable_entry(var); @@ -185,8 +185,18 @@ ir_array_reference_visitor::visit_enter(ir_dereference_array *ir) /* If the access to the array has a variable index, we wouldn't * know which split variable this dereference should go to. */ - if (entry && !ir->array_index->as_constant()) - entry->split = false; + if (!ir->array_index->as_constant()) { + if (entry) + entry->split = false; + /* This variable indexing could come from a different array dereference + * that also has variable indexing, that is, something like a[b[a[b[0]]]]. + * If we return visit_continue_with_parent here for the first appearence + * of a, then we can miss that b also has indirect indexing (if this is + * the only place in the program where such indirect indexing into b + * happens), so keep going. + */ + return visit_continue; + } /* If the index is also array dereference, visit index. */ if (ir->array_index->as_dereference_array()) @@ -208,7 +218,7 @@ ir_array_reference_visitor::visit_enter(ir_function_signature *ir) bool ir_array_reference_visitor::get_split_list(exec_list *instructions, - bool linked) + bool linked) { visit_list_elements(this, instructions); @@ -217,25 +227,25 @@ ir_array_reference_visitor::get_split_list(exec_list *instructions, */ if (!linked) { foreach_in_list(ir_instruction, node, instructions) { - ir_variable *var = node->as_variable(); - if (var) { - variable_entry *entry = get_variable_entry(var); - if (entry) - entry->remove(); - } + ir_variable *var = node->as_variable(); + if (var) { + variable_entry *entry = get_variable_entry(var); + if (entry) + entry->remove(); + } } } /* Trim out variables we found that we can't split. */ foreach_in_list_safe(variable_entry, entry, &variable_list) { if (debug) { - printf("array %s@%p: decl %d, split %d\n", - entry->var->name, (void *) entry->var, entry->declaration, - entry->split); + printf("array %s@%p: decl %d, split %d\n", + entry->var->name, (void *) entry->var, entry->declaration, + entry->split); } if (!(entry->declaration && entry->split)) { - entry->remove(); + entry->remove(); } } @@ -273,7 +283,7 @@ ir_array_splitting_visitor::get_splitting_entry(ir_variable *var) foreach_in_list(variable_entry, entry, this->variable_list) { if (entry->var == var) { - return entry; + return entry; } } @@ -301,7 +311,7 @@ ir_array_splitting_visitor::split_deref(ir_dereference **deref) if (constant->value.i[0] >= 0 && constant->value.i[0] < (int)entry->size) { *deref = new(entry->mem_ctx) - ir_dereference_variable(entry->components[constant->value.i[0]]); + ir_dereference_variable(entry->components[constant->value.i[0]]); } else { /* There was a constant array access beyond the end of the * array. This might have happened due to constant folding @@ -310,8 +320,8 @@ ir_array_splitting_visitor::split_deref(ir_dereference **deref) * variable. */ ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type, - "undef", - ir_var_temporary); + "undef", + ir_var_temporary); entry->components[0]->insert_before(temp); *deref = new(entry->mem_ctx) ir_dereference_variable(temp); } @@ -373,23 +383,21 @@ optimize_split_arrays(exec_list *instructions, bool linked) const struct glsl_type *subtype; if (type->is_matrix()) - subtype = type->column_type(); + subtype = type->column_type(); else - subtype = type->fields.array; + subtype = type->fields.array; entry->mem_ctx = ralloc_parent(entry->var); - entry->components = ralloc_array(mem_ctx, - ir_variable *, - entry->size); + entry->components = ralloc_array(mem_ctx, ir_variable *, entry->size); for (unsigned int i = 0; i < entry->size; i++) { - const char *name = ralloc_asprintf(mem_ctx, "%s_%d", - entry->var->name, i); + const char *name = ralloc_asprintf(mem_ctx, "%s_%d", + entry->var->name, i); - entry->components[i] = - new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary); - entry->var->insert_before(entry->components[i]); + entry->components[i] = + new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary); + entry->var->insert_before(entry->components[i]); } entry->var->remove(); diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index c549230a83c..2421bd61954 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/glsl_types.cpp @@ -120,6 +120,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].name = ralloc_strdup(this->fields.structure, fields[i].name); this->fields.structure[i].location = fields[i].location; + this->fields.structure[i].offset = fields[i].offset; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; this->fields.structure[i].sample = fields[i].sample; @@ -159,6 +160,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].name = ralloc_strdup(this->fields.structure, fields[i].name); this->fields.structure[i].location = fields[i].location; + this->fields.structure[i].offset = fields[i].offset; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; this->fields.structure[i].sample = fields[i].sample; @@ -880,6 +882,9 @@ glsl_type::record_compare(const glsl_type *b) const if (this->fields.structure[i].location != b->fields.structure[i].location) return false; + if (this->fields.structure[i].offset + != b->fields.structure[i].offset) + return false; if (this->fields.structure[i].interpolation != b->fields.structure[i].interpolation) return false; diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index 2f612d8857d..b0e6f3f730f 100644 --- a/src/compiler/glsl_types.h +++ b/src/compiler/glsl_types.h @@ -838,6 +838,14 @@ struct glsl_struct_field { int location; /** + * For interface blocks, members may have an explicit byte offset + * specified; -1 otherwise. + * + * Ignored for structs. + */ + int offset; + + /** * For interface blocks, the interpolation mode (as in * ir_variable::interpolation). 0 otherwise. */ diff --git a/src/compiler/nir/Makefile.sources b/src/compiler/nir/Makefile.sources index 04e8ab88a35..a876eff289a 100644 --- a/src/compiler/nir/Makefile.sources +++ b/src/compiler/nir/Makefile.sources @@ -32,10 +32,10 @@ NIR_FILES = \ nir_lower_clip.c \ nir_lower_global_vars_to_local.c \ nir_lower_gs_intrinsics.c \ - nir_lower_indirect_derefs.c \ nir_lower_load_const_to_scalar.c \ nir_lower_locals_to_regs.c \ nir_lower_idiv.c \ + nir_lower_indirect_derefs.c \ nir_lower_io.c \ nir_lower_outputs_to_temporaries.c \ nir_lower_phis_to_scalar.c \ diff --git a/src/compiler/nir/glsl_to_nir.cpp b/src/compiler/nir/glsl_to_nir.cpp index 6671691fd06..da5d730b49e 100644 --- a/src/compiler/nir/glsl_to_nir.cpp +++ b/src/compiler/nir/glsl_to_nir.cpp @@ -454,34 +454,8 @@ nir_visitor::create_function(ir_function_signature *ir) nir_function *func = nir_function_create(shader, ir->function_name()); - unsigned num_params = ir->parameters.length(); - func->num_params = num_params; - func->params = ralloc_array(shader, nir_parameter, num_params); - - unsigned i = 0; - foreach_in_list(ir_variable, param, &ir->parameters) { - switch (param->data.mode) { - case ir_var_function_in: - func->params[i].param_type = nir_parameter_in; - break; - - case ir_var_function_out: - func->params[i].param_type = nir_parameter_out; - break; - - case ir_var_function_inout: - func->params[i].param_type = nir_parameter_inout; - break; - - default: - unreachable("not reached"); - } - - func->params[i].type = param->type; - i++; - } - - func->return_type = ir->return_type; + assert(ir->parameters.is_empty()); + assert(ir->return_type == glsl_type::void_type); _mesa_hash_table_insert(this->overload_table, ir, func); } @@ -509,24 +483,9 @@ nir_visitor::visit(ir_function_signature *ir) nir_function_impl *impl = nir_function_impl_create(func); this->impl = impl; - unsigned num_params = func->num_params; - impl->num_params = num_params; - impl->params = ralloc_array(this->shader, nir_variable *, num_params); - unsigned i = 0; - foreach_in_list(ir_variable, param, &ir->parameters) { - param->accept(this); - impl->params[i] = this->var; - i++; - } - - if (func->return_type == glsl_type::void_type) { - impl->return_var = NULL; - } else { - impl->return_var = ralloc(this->shader, nir_variable); - impl->return_var->name = ralloc_strdup(impl->return_var, - "return_var"); - impl->return_var->type = func->return_type; - } + assert(strcmp(func->name, "main") == 0); + assert(ir->parameters.is_empty()); + assert(func->return_type == glsl_type::void_type); this->is_global = false; diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 91206a92717..7e41ed37b0d 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -323,6 +323,8 @@ nir_function_impl_create(nir_function *function) impl->return_var->type = function->return_type; impl->return_var->data.mode = nir_var_param; impl->return_var->data.location = -1; + } else { + impl->return_var = NULL; } return impl; diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 0f8c78100bf..ae37cbf7325 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2094,8 +2094,8 @@ void nir_index_blocks(nir_function_impl *impl); void nir_print_shader(nir_shader *shader, FILE *fp); void nir_print_instr(const nir_instr *instr, FILE *fp); -nir_shader *nir_shader_clone(void *mem_ctx, const nir_shader *s); -nir_function_impl *nir_function_impl_clone(const nir_function_impl *impl); +nir_shader * nir_shader_clone(void *mem_ctx, const nir_shader *s); +nir_function_impl *nir_function_impl_clone(const nir_function_impl *fi); nir_constant *nir_constant_clone(const nir_constant *c, nir_variable *var); #ifdef DEBUG diff --git a/src/compiler/nir/nir_lower_indirect_derefs.c b/src/compiler/nir/nir_lower_indirect_derefs.c index 69f2df4ba6d..a4affa7bdcf 100644 --- a/src/compiler/nir/nir_lower_indirect_derefs.c +++ b/src/compiler/nir/nir_lower_indirect_derefs.c @@ -134,7 +134,7 @@ emit_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr, nir_intrinsic_instr *store = nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var); store->num_components = orig_instr->num_components; - store->const_index[0] = orig_instr->const_index[0]; /* writemask */ + nir_intrinsic_set_write_mask(store, nir_intrinsic_write_mask(orig_instr)); store->variables[0] = nir_deref_as_var(nir_copy_deref(store, &deref->deref)); store->src[0] = nir_src_for_ssa(src); diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index c9c917b77a5..54f7d86843a 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -164,6 +164,8 @@ optimizations = [ (('ishr', a, 0), a), (('ushr', 0, a), 0), (('ushr', a, 0), a), + (('iand', 0xff, ('ushr', a, 24)), ('ushr', a, 24)), + (('iand', 0xffff, ('ushr', a, 16)), ('ushr', a, 16)), # Exponential/logarithmic identities (('fexp2', ('flog2', a)), a), # 2^lg2(a) = a (('flog2', ('fexp2', a)), a), # lg2(2^a) = a @@ -215,6 +217,16 @@ optimizations = [ (('f2i', ('ftrunc', a)), ('f2i', a)), (('f2u', ('ftrunc', a)), ('f2u', a)), + # Byte extraction + (('ushr', a, 24), ('extract_u8', a, 3), '!options->lower_extract_byte'), + (('iand', 0xff, ('ushr', a, 16)), ('extract_u8', a, 2), '!options->lower_extract_byte'), + (('iand', 0xff, ('ushr', a, 8)), ('extract_u8', a, 1), '!options->lower_extract_byte'), + (('iand', 0xff, a), ('extract_u8', a, 0), '!options->lower_extract_byte'), + + # Word extraction + (('ushr', a, 16), ('extract_u16', a, 1), '!options->lower_extract_word'), + (('iand', 0xffff, a), ('extract_u16', a, 0), '!options->lower_extract_word'), + # Subtracts (('fsub', a, ('fsub', 0.0, b)), ('fadd', a, b)), (('isub', a, ('isub', 0, b)), ('iadd', a, b)), diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 63e34ea5255..24d5281ec54 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -381,6 +381,14 @@ print_var(nir_variable *var, print_state *state) } static void +print_arg(nir_variable *var, print_state *state) +{ + FILE *fp = state->fp; + glsl_print_type(var->type, fp); + fprintf(fp, " %s", get_var_name(var, state)); +} + +static void print_deref_var(nir_deref_var *deref, print_state *state) { print_var(deref->var, state); @@ -942,14 +950,14 @@ print_function_impl(nir_function_impl *impl, print_state *state) if (i != 0) fprintf(fp, ", "); - print_var(impl->params[i], state); + print_arg(impl->params[i], state); } if (impl->return_var != NULL) { if (impl->num_params != 0) fprintf(fp, ", "); fprintf(fp, "returning "); - print_var(impl->return_var, state); + print_arg(impl->return_var, state); } fprintf(fp, "{\n"); diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index a9d213b95c4..0c32d5fe07a 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -938,6 +938,7 @@ validate_function_impl(nir_function_impl *impl, validate_state *state) assert(impl->num_params == impl->function->num_params); for (unsigned i = 0; i < impl->num_params; i++) { assert(impl->params[i]->type == impl->function->params[i].type); + assert(impl->params[i]->data.mode == nir_var_param); assert(impl->params[i]->data.location == i); validate_var_decl(impl->params[i], false, state); } @@ -946,6 +947,7 @@ validate_function_impl(nir_function_impl *impl, validate_state *state) assert(impl->return_var == NULL); } else { assert(impl->return_var->type == impl->function->return_type); + assert(impl->return_var->data.mode == nir_var_param); assert(impl->return_var->data.location == -1); validate_var_decl(impl->return_var, false, state); } |