diff options
Diffstat (limited to 'mesalib/src/glsl')
33 files changed, 1610 insertions, 390 deletions
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index e69c1ac61..5945590a5 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -67,6 +67,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_jumps.cpp \ $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ $(GLSL_SRCDIR)/lower_noise.cpp \ + $(GLSL_SRCDIR)/lower_offset_array.cpp \ $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ $(GLSL_SRCDIR)/lower_named_interface_blocks.cpp \ $(GLSL_SRCDIR)/lower_packing_builtins.cpp \ diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 61fd923bc..1efb30679 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -280,14 +280,14 @@ class ast_array_specifier : public ast_node { public: /** Unsized array specifier ([]) */ explicit ast_array_specifier(const struct YYLTYPE &locp) - : dimension_count(1), is_unsized_array(true) + : is_unsized_array(true) { set_location(locp); } /** Sized array specifier ([dim]) */ ast_array_specifier(const struct YYLTYPE &locp, ast_expression *dim) - : dimension_count(1), is_unsized_array(false) + : is_unsized_array(false) { set_location(locp); array_dimensions.push_tail(&dim->link); @@ -296,14 +296,10 @@ public: void add_dimension(ast_expression *dim) { array_dimensions.push_tail(&dim->link); - dimension_count++; } virtual void print(void) const; - /* Count including sized and unsized dimensions */ - unsigned dimension_count; - /* If true, this means that the array has an unsized outermost dimension. */ bool is_unsized_array; @@ -466,17 +462,36 @@ struct ast_type_qualifier { * local_size_x, and so on. */ unsigned local_size:3; + + /** \name Layout and memory qualifiers for ARB_shader_image_load_store. */ + /** \{ */ + unsigned early_fragment_tests:1; + unsigned explicit_image_format:1; + unsigned coherent:1; + unsigned _volatile:1; + unsigned restrict_flag:1; + unsigned read_only:1; /**< "readonly" qualifier. */ + unsigned write_only:1; /**< "writeonly" qualifier. */ + /** \} */ + + /** \name Layout qualifiers for GL_ARB_gpu_shader5 */ + /** \{ */ + unsigned invocations:1; + /** \} */ } /** \brief Set of flags, accessed by name. */ q; /** \brief Set of flags, accessed as a bitmask. */ - unsigned i; + uint64_t i; } flags; /** Precision of the type (highp/medium/lowp). */ unsigned precision:2; + /** Geometry shader invocations for GL_ARB_gpu_shader5. */ + int invocations; + /** * Location specified via GL_ARB_explicit_attrib_location layout * @@ -523,6 +538,25 @@ struct ast_type_qualifier { int local_size[3]; /** + * Image format specified with an ARB_shader_image_load_store + * layout qualifier. + * + * \note + * This field is only valid if \c explicit_image_format is set. + */ + GLenum image_format; + + /** + * Base type of the data read from or written to this image. Only + * the following enumerants are allowed: GLSL_TYPE_UINT, + * GLSL_TYPE_INT, GLSL_TYPE_FLOAT. + * + * \note + * This field is only valid if \c explicit_image_format is set. + */ + glsl_base_type image_base_type; + + /** * Return true if and only if an interpolation qualifier is present. */ bool has_interpolation() const; @@ -557,6 +591,12 @@ struct ast_type_qualifier { bool merge_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, ast_type_qualifier q); + + bool merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node); + }; class ast_declarator_list; diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 4c5b0e4aa..4b8447067 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -93,6 +93,57 @@ prototype_string(const glsl_type *return_type, const char *name, return str; } +static bool +verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state, + const ir_variable *formal, const ir_variable *actual) +{ + /** + * From the ARB_shader_image_load_store specification: + * + * "The values of image variables qualified with coherent, + * volatile, restrict, readonly, or writeonly may not be passed + * to functions whose formal parameters lack such + * qualifiers. [...] It is legal to have additional qualifiers + * on a formal parameter, but not to have fewer." + */ + if (actual->data.image.coherent && !formal->data.image.coherent) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`coherent' qualifier", formal->name); + return false; + } + + if (actual->data.image._volatile && !formal->data.image._volatile) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`volatile' qualifier", formal->name); + return false; + } + + if (actual->data.image.restrict_flag && !formal->data.image.restrict_flag) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`restrict' qualifier", formal->name); + return false; + } + + if (actual->data.image.read_only && !formal->data.image.read_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`readonly' qualifier", formal->name); + return false; + } + + if (actual->data.image.write_only && !formal->data.image.write_only) { + _mesa_glsl_error(loc, state, + "function call parameter `%s' drops " + "`writeonly' qualifier", formal->name); + return false; + } + + return true; +} + /** * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify * that 'const_in' formal parameters (an extension in our IR) correspond to @@ -180,6 +231,13 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, } } + if (formal->type->is_image() && + actual->variable_referenced()) { + if (!verify_image_parameter(&loc, state, formal, + actual->variable_referenced())) + return false; + } + actual_ir_node = actual_ir_node->next; actual_ast_node = actual_ast_node->next; } diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index c89a26bf9..8f6e90174 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -969,6 +969,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_ERROR: case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_ATOMIC_UINT: /* I assume a comparison of a struct containing a sampler just @@ -1796,7 +1797,7 @@ ast_compound_statement::hir(exec_list *instructions, * Evaluate the given exec_node (which should be an ast_node representing * a single array dimension) and return its integer value. */ -static const unsigned +static unsigned process_array_size(exec_node *node, struct _mesa_glsl_parse_state *state) { @@ -2122,11 +2123,16 @@ validate_explicit_location(const struct ast_type_qualifier *qual, { bool fail = false; - /* In the vertex shader only shader inputs can be given explicit - * locations. + /* Between GL_ARB_explicit_attrib_location an + * GL_ARB_separate_shader_objects, the inputs and outputs of any shader + * stage can be assigned explicit locations. The checking here associates + * the correct extension with the correct stage's input / output: * - * In the fragment shader only shader outputs can be given explicit - * locations. + * input output + * ----- ------ + * vertex explicit_loc sso + * geometry sso sso + * fragment sso explicit_loc */ switch (state->stage) { case MESA_SHADER_VERTEX: @@ -2137,16 +2143,35 @@ validate_explicit_location(const struct ast_type_qualifier *qual, break; } + if (var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + fail = true; break; case MESA_SHADER_GEOMETRY: - _mesa_glsl_error(loc, state, - "geometry shader variables cannot be given " - "explicit locations"); - return; + if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + if (var->data.mode == ir_var_shader_out) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2180,9 +2205,26 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * ensures that negative values stay negative. */ if (qual->location >= 0) { - var->data.location = (state->stage == MESA_SHADER_VERTEX) - ? (qual->location + VERT_ATTRIB_GENERIC0) - : (qual->location + FRAG_RESULT_DATA0); + switch (state->stage) { + case MESA_SHADER_VERTEX: + var->data.location = (var->data.mode == ir_var_shader_in) + ? (qual->location + VERT_ATTRIB_GENERIC0) + : (qual->location + VARYING_SLOT_VAR0); + break; + + case MESA_SHADER_GEOMETRY: + var->data.location = qual->location + VARYING_SLOT_VAR0; + break; + + case MESA_SHADER_FRAGMENT: + var->data.location = (var->data.mode == ir_var_shader_out) + ? (qual->location + FRAG_RESULT_DATA0) + : (qual->location + VARYING_SLOT_VAR0); + break; + case MESA_SHADER_COMPUTE: + assert(!"Unexpected shader type"); + break; + } } else { var->data.location = qual->location; } @@ -2206,8 +2248,54 @@ validate_explicit_location(const struct ast_type_qualifier *qual, } } } +} + +static void +apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + const glsl_type *base_type = + (var->type->is_array() ? var->type->element_type() : var->type); + + if (base_type->is_image()) { + if (var->data.mode != ir_var_uniform && + var->data.mode != ir_var_function_in) { + _mesa_glsl_error(loc, state, "image variables may only be declared as " + "function parameters or uniform-qualified " + "global variables"); + } + + var->data.image.read_only |= qual->flags.q.read_only; + var->data.image.write_only |= qual->flags.q.write_only; + var->data.image.coherent |= qual->flags.q.coherent; + var->data.image._volatile |= qual->flags.q._volatile; + var->data.image.restrict_flag |= qual->flags.q.restrict_flag; + var->data.read_only = true; + + if (qual->flags.q.explicit_image_format) { + if (var->data.mode == ir_var_function_in) { + _mesa_glsl_error(loc, state, "format qualifiers cannot be " + "used on image function parameters"); + } + + if (qual->image_base_type != base_type->sampler_type) { + _mesa_glsl_error(loc, state, "format qualifier doesn't match the " + "base data type of the image"); + } + + var->data.image.format = qual->image_format; + } else { + if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) { + _mesa_glsl_error(loc, state, "uniforms not qualified with " + "`writeonly' must have a format layout " + "qualifier"); + } - return; + var->data.image.format = GL_NONE; + } + } } static void @@ -2500,6 +2588,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.row_major || qual->flags.q.column_major) { validate_matrix_layout_for_type(state, loc, var->type, var); } + + if (var->type->contains_image()) + apply_image_qualifier_to_variable(qual, var, state, loc); } /** @@ -2659,9 +2750,15 @@ process_initializer(ir_variable *var, ast_declaration *decl, "cannot initialize uniforms"); } - if (var->type->is_sampler()) { + /* From section 4.1.7 of the GLSL 4.40 spec: + * + * "Opaque variables [...] are initialized only through the + * OpenGL API; they cannot be declared with an initializer in a + * shader." + */ + if (var->type->contains_opaque()) { _mesa_glsl_error(& initializer_loc, state, - "cannot initialize samplers"); + "cannot initialize opaque variable"); } if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { @@ -2784,7 +2881,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, { unsigned num_vertices = 0; if (state->gs_input_prim_type_specified) { - num_vertices = vertices_per_prim(state->gs_input_prim_type); + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); } /* Geometry shader input variables must be arrays. Caller should have @@ -2870,10 +2967,17 @@ validate_identifier(const char *identifier, YYLTYPE loc, * "In addition, all identifiers containing two * consecutive underscores (__) are reserved as * possible future keywords." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Names simply containing __ are dangerous to use, + * but should be allowed. + * + * A future version of the GLSL specification will clarify this. */ - _mesa_glsl_error(&loc, state, - "identifier `%s' uses reserved `__' string", - identifier); + _mesa_glsl_warning(&loc, state, + "identifier `%s' uses reserved `__' string", + identifier); } } @@ -3082,6 +3186,7 @@ ast_declarator_list::hir(exec_list *instructions, */ if (!state->is_version(130, 300) && !state->has_explicit_attrib_location() + && !state->has_separate_shader_objects() && !state->ARB_fragment_coord_conventions_enable) { if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(& loc, state, @@ -3421,15 +3526,15 @@ ast_declarator_list::hir(exec_list *instructions, ", integer and sampler types"); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function - * parameters or uniform variables (see Section 4.3.5 - * "Uniform")". + * "[Opaque types] can only be declared as function + * parameters or uniform-qualified variables." */ - if (var_type->contains_sampler() && + if (var_type->contains_opaque() && !this->type->qualifier.flags.q.uniform) { - _mesa_glsl_error(&loc, state, "samplers must be declared uniform"); + _mesa_glsl_error(&loc, state, + "opaque variables must be declared uniform"); } /* Process the initializer and add its instructions to a temporary @@ -3621,15 +3726,16 @@ ast_parameter_declarator::hir(exec_list *instructions, apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, true); - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "Samplers cannot be treated as l-values; hence cannot be used - * as out or inout function parameters, nor can they be assigned - * into." + * "Opaque variables cannot be treated as l-values; hence cannot + * be used as out or inout function parameters, nor can they be + * assigned into." */ if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) - && type->contains_sampler()) { - _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); + && type->contains_opaque()) { + _mesa_glsl_error(&loc, state, "out and inout parameters cannot " + "contain opaque variables"); type = glsl_type::error_type; } @@ -3784,15 +3890,15 @@ ast_function::hir(exec_list *instructions, "sized", name); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function parameters - * or uniform variables (see Section 4.3.5 "Uniform")". + * "[Opaque types] can only be declared as function parameters + * or uniform-qualified variables." */ - if (return_type->contains_sampler()) { + if (return_type->contains_opaque()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, - "function `%s' return type can't contain a sampler", + "function `%s' return type can't contain an opaque type", name); } @@ -4693,12 +4799,9 @@ ast_process_structure_or_interface_block(exec_list *instructions, if (!allow_reserved_names) validate_identifier(decl->identifier, loc, state); - /* From the GL_ARB_uniform_buffer_object spec: + /* From section 4.3.9 of the GLSL 4.40 spec: * - * "Sampler types are not allowed inside of uniform - * blocks. All other types, arrays, and structures - * allowed for uniforms are allowed within a uniform - * block." + * "[In interface blocks] opaque types are not allowed." * * It should be impossible for decl_type to be NULL here. Cases that * might naturally lead to decl_type being NULL, especially for the @@ -4708,10 +4811,11 @@ ast_process_structure_or_interface_block(exec_list *instructions, const struct glsl_type *field_type = decl_type != NULL ? decl_type : glsl_type::error_type; - if (is_interface && field_type->contains_sampler()) { + if (is_interface && field_type->contains_opaque()) { YYLTYPE loc = decl_list->get_location(); _mesa_glsl_error(&loc, state, - "uniform in non-default uniform block contains sampler"); + "uniform in non-default uniform block contains " + "opaque variable"); } if (field_type->contains_atomic()) { @@ -4725,6 +4829,16 @@ ast_process_structure_or_interface_block(exec_list *instructions, "uniform block"); } + if (field_type->contains_image()) { + /* FINISHME: Same problem as with atomic counters. + * FINISHME: Request clarification from Khronos and add + * FINISHME: spec quotation here. + */ + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "image in structure or uniform block"); + } + const struct ast_type_qualifier *const qual = & decl_list->type->qualifier; if (qual->flags.q.std140 || @@ -5258,7 +5372,7 @@ ast_gs_input_layout::hir(exec_list *instructions, * was consistent with this one. */ if (state->gs_input_prim_type_specified && - state->gs_input_prim_type != this->prim_type) { + state->in_qualifier->prim_type != this->prim_type) { _mesa_glsl_error(&loc, state, "geometry shader input layout does not match" " previous declaration"); @@ -5279,7 +5393,6 @@ ast_gs_input_layout::hir(exec_list *instructions, } state->gs_input_prim_type_specified = true; - state->gs_input_prim_type = this->prim_type; /* If any shader inputs occurred before this declaration and did not * specify an array size, their size is determined now. diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index bbc430808..0ee2c495a 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -190,6 +190,117 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, if (q.precision != ast_precision_none) this->precision = q.precision; + if (q.flags.q.explicit_image_format) { + this->image_format = q.image_format; + this->image_base_type = q.image_base_type; + } + return true; } +bool +ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q, + ast_node* &node) +{ + void *mem_ctx = state; + bool create_gs_ast = false; + bool create_cs_ast = false; + ast_type_qualifier valid_in_mask; + valid_in_mask.flags.i = 0; + + switch (state->stage) { + case MESA_SHADER_GEOMETRY: + if (q.flags.q.prim_type) { + /* Make sure this is a valid input primitive type. */ + switch (q.prim_type) { + case GL_POINTS: + case GL_LINES: + case GL_LINES_ADJACENCY: + case GL_TRIANGLES: + case GL_TRIANGLES_ADJACENCY: + break; + default: + _mesa_glsl_error(loc, state, + "invalid geometry shader input primitive type"); + break; + } + } + + create_gs_ast |= + q.flags.q.prim_type && + !state->in_qualifier->flags.q.prim_type; + + valid_in_mask.flags.q.prim_type = 1; + valid_in_mask.flags.q.invocations = 1; + break; + case MESA_SHADER_FRAGMENT: + if (q.flags.q.early_fragment_tests) { + state->early_fragment_tests = true; + } else { + _mesa_glsl_error(loc, state, "invalid input layout qualifier"); + } + break; + case MESA_SHADER_COMPUTE: + create_cs_ast |= + q.flags.q.local_size != 0 && + state->in_qualifier->flags.q.local_size == 0; + + valid_in_mask.flags.q.local_size = 1; + break; + default: + _mesa_glsl_error(loc, state, + "input layout qualifiers only valid in " + "geometry, fragment and compute shaders"); + break; + } + + /* Generate an error when invalid input layout qualifiers are used. */ + if ((q.flags.i & ~valid_in_mask.flags.i) != 0) { + _mesa_glsl_error(loc, state, + "invalid input layout qualifiers used"); + return false; + } + + /* Input layout qualifiers can be specified multiple + * times in separate declarations, as long as they match. + */ + if (this->flags.q.prim_type) { + if (q.flags.q.prim_type && + this->prim_type != q.prim_type) { + _mesa_glsl_error(loc, state, + "conflicting input primitive types specified"); + } + } else if (q.flags.q.prim_type) { + state->in_qualifier->flags.q.prim_type = 1; + state->in_qualifier->prim_type = q.prim_type; + } + + if (this->flags.q.invocations && + q.flags.q.invocations && + this->invocations != q.invocations) { + _mesa_glsl_error(loc, state, + "conflicting invocations counts specified"); + return false; + } else if (q.flags.q.invocations) { + this->flags.q.invocations = 1; + this->invocations = q.invocations; + } + + if (create_gs_ast) { + node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); + } else if (create_cs_ast) { + /* Infer a local_size of 1 for every unspecified dimension */ + unsigned local_size[3]; + for (int i = 0; i < 3; i++) { + if (q.flags.q.local_size & (1 << i)) + local_size[i] = q.local_size[i]; + else + local_size[i] = 1; + } + node = new(mem_ctx) ast_cs_input_layout(*loc, local_size); + } + + return true; +} diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index aeb8e5d94..a52077d06 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -340,6 +340,13 @@ shader_trinary_minmax(const _mesa_glsl_parse_state *state) return state->AMD_shader_trinary_minmax_enable; } +static bool +shader_image_load_store(const _mesa_glsl_parse_state *state) +{ + return (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable); +} + /** @} */ /******************************************************************************/ @@ -413,6 +420,33 @@ private: /** Create a new function and add the given signatures. */ void add_function(const char *name, ...); + enum image_function_flags { + IMAGE_FUNCTION_EMIT_STUB = (1 << 0), + IMAGE_FUNCTION_RETURNS_VOID = (1 << 1), + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2), + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3), + IMAGE_FUNCTION_READ_ONLY = (1 << 4), + IMAGE_FUNCTION_WRITE_ONLY = (1 << 5) + }; + + /** + * Create a new image built-in function for all known image types. + * \p flags is a bitfield of \c image_function_flags flags. + */ + void add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + /** + * Create new functions for all known image built-ins and types. + * If \p glsl is \c true, use the GLSL built-in names and emit code + * to call into the actual compiler intrinsic. If \p glsl is + * false, emit a function prototype with no body for each image + * intrinsic name. + */ + void add_image_functions(bool glsl); + ir_function_signature *new_sig(const glsl_type *return_type, builtin_available_predicate avail, int num_params, ...); @@ -580,6 +614,20 @@ private: B1(max3) B1(mid3) + ir_function_signature *_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + ir_function_signature *_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + ir_function_signature *_memory_barrier_intrinsic( + builtin_available_predicate avail); + ir_function_signature *_memory_barrier( + builtin_available_predicate avail); + #undef B0 #undef B1 #undef B2 @@ -694,6 +742,12 @@ builtin_builder::create_intrinsics() add_function("__intrinsic_atomic_predecrement", _atomic_intrinsic(shader_atomic_counters), NULL); + + add_image_functions(false); + + add_function("__intrinsic_memory_barrier", + _memory_barrier_intrinsic(shader_image_load_store), + NULL); } /** @@ -2167,6 +2221,12 @@ builtin_builder::create_builtins() _mid3(glsl_type::uvec4_type), NULL); + add_image_functions(true); + + add_function("memoryBarrier", + _memory_barrier(shader_image_load_store), + NULL); + #undef F #undef FI #undef FIU @@ -2200,6 +2260,104 @@ builtin_builder::add_function(const char *name, ...) shader->symbols->add_function(f); } +void +builtin_builder::add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + static const glsl_type *const types[] = { + glsl_type::image1D_type, + glsl_type::image2D_type, + glsl_type::image3D_type, + glsl_type::image2DRect_type, + glsl_type::imageCube_type, + glsl_type::imageBuffer_type, + glsl_type::image1DArray_type, + glsl_type::image2DArray_type, + glsl_type::imageCubeArray_type, + glsl_type::image2DMS_type, + glsl_type::image2DMSArray_type, + glsl_type::iimage1D_type, + glsl_type::iimage2D_type, + glsl_type::iimage3D_type, + glsl_type::iimage2DRect_type, + glsl_type::iimageCube_type, + glsl_type::iimageBuffer_type, + glsl_type::iimage1DArray_type, + glsl_type::iimage2DArray_type, + glsl_type::iimageCubeArray_type, + glsl_type::iimage2DMS_type, + glsl_type::iimage2DMSArray_type, + glsl_type::uimage1D_type, + glsl_type::uimage2D_type, + glsl_type::uimage3D_type, + glsl_type::uimage2DRect_type, + glsl_type::uimageCube_type, + glsl_type::uimageBuffer_type, + glsl_type::uimage1DArray_type, + glsl_type::uimage2DArray_type, + glsl_type::uimageCubeArray_type, + glsl_type::uimage2DMS_type, + glsl_type::uimage2DMSArray_type + }; + ir_function *f = new(mem_ctx) ir_function(name); + + for (unsigned i = 0; i < Elements(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, + num_arguments, flags)); + } + + shader->symbols->add_function(f); +} + +void +builtin_builder::add_image_functions(bool glsl) +{ + const unsigned flags = (glsl ? IMAGE_FUNCTION_EMIT_STUB : 0); + + add_image_function(glsl ? "imageLoad" : "__intrinsic_image_load", + "__intrinsic_image_load", 0, + (flags | IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_READ_ONLY)); + + add_image_function(glsl ? "imageStore" : "__intrinsic_image_store", + "__intrinsic_image_store", 1, + (flags | IMAGE_FUNCTION_RETURNS_VOID | + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_WRITE_ONLY)); + + add_image_function(glsl ? "imageAtomicAdd" : "__intrinsic_image_atomic_add", + "__intrinsic_image_atomic_add", 1, flags); + + add_image_function(glsl ? "imageAtomicMin" : "__intrinsic_image_atomic_min", + "__intrinsic_image_atomic_min", 1, flags); + + add_image_function(glsl ? "imageAtomicMax" : "__intrinsic_image_atomic_max", + "__intrinsic_image_atomic_max", 1, flags); + + add_image_function(glsl ? "imageAtomicAnd" : "__intrinsic_image_atomic_and", + "__intrinsic_image_atomic_and", 1, flags); + + add_image_function(glsl ? "imageAtomicOr" : "__intrinsic_image_atomic_or", + "__intrinsic_image_atomic_or", 1, flags); + + add_image_function(glsl ? "imageAtomicXor" : "__intrinsic_image_atomic_xor", + "__intrinsic_image_atomic_xor", 1, flags); + + add_image_function((glsl ? "imageAtomicExchange" : + "__intrinsic_image_atomic_exchange"), + "__intrinsic_image_atomic_exchange", 1, flags); + + add_image_function((glsl ? "imageAtomicCompSwap" : + "__intrinsic_image_atomic_comp_swap"), + "__intrinsic_image_atomic_comp_swap", 2, flags); +} + ir_variable * builtin_builder::in_var(const glsl_type *type, const char *name) { @@ -3549,7 +3707,7 @@ builtin_builder::_texture(ir_texture_opcode opcode, ir_texture *tex = new(mem_ctx) ir_texture(opcode); tex->set_sampler(var_ref(s), return_type); - const int coord_size = sampler_type->sampler_coordinate_components(); + const int coord_size = sampler_type->coordinate_components(); if (coord_size == coord_type->vector_elements) { tex->coordinate = var_ref(P); @@ -4094,12 +4252,106 @@ builtin_builder::_mid3(const glsl_type *type) return sig; } +ir_function_signature * +builtin_builder::_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + const glsl_type *data_type = glsl_type::get_instance( + image_type->sampler_type, + (flags & IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE ? 4 : 1), + 1); + const glsl_type *ret_type = (flags & IMAGE_FUNCTION_RETURNS_VOID ? + glsl_type::void_type : data_type); + + /* Addressing arguments that are always present. */ + ir_variable *image = in_var(image_type, "image"); + ir_variable *coord = in_var( + glsl_type::ivec(image_type->coordinate_components()), "coord"); + + ir_function_signature *sig = new_sig( + ret_type, shader_image_load_store, 2, image, coord); + + /* Sample index for multisample images. */ + if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) + sig->parameters.push_tail(in_var(glsl_type::int_type, "sample")); + + /* Data arguments. */ + for (unsigned i = 0; i < num_arguments; ++i) + sig->parameters.push_tail(in_var(data_type, + ralloc_asprintf(NULL, "arg%d", i))); + + /* Set the maximal set of qualifiers allowed for this image + * built-in. Function calls with arguments having fewer + * qualifiers than present in the prototype are allowed by the + * spec, but not with more, i.e. this will make the compiler + * accept everything that needs to be accepted, and reject cases + * like loads from write-only or stores to read-only images. + */ + image->data.image.read_only = flags & IMAGE_FUNCTION_READ_ONLY; + image->data.image.write_only = flags & IMAGE_FUNCTION_WRITE_ONLY; + image->data.image.coherent = true; + image->data.image._volatile = true; + image->data.image.restrict_flag = true; + + return sig; +} + +ir_function_signature * +builtin_builder::_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + ir_function_signature *sig = _image_prototype(image_type, intrinsic_name, + num_arguments, flags); + + if (flags & IMAGE_FUNCTION_EMIT_STUB) { + ir_factory body(&sig->body, mem_ctx); + ir_function *f = shader->symbols->get_function(intrinsic_name); + + if (flags & IMAGE_FUNCTION_RETURNS_VOID) { + body.emit(call(f, NULL, sig->parameters)); + } else { + ir_variable *ret_val = + body.make_temp(sig->return_type, "_ret_val"); + body.emit(call(f, ret_val, sig->parameters)); + body.emit(ret(ret_val)); + } + + sig->is_defined = true; + + } else { + sig->is_intrinsic = true; + } + + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier_intrinsic(builtin_available_predicate avail) +{ + MAKE_INTRINSIC(glsl_type::void_type, avail, 0); + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier(builtin_available_predicate avail) +{ + MAKE_SIG(glsl_type::void_type, avail, 0); + body.emit(call(shader->symbols->get_function("__intrinsic_memory_barrier"), + NULL, sig->parameters)); + return sig; +} + /** @} */ /******************************************************************************/ /* The singleton instance of builtin_builder. */ static builtin_builder builtins; +static mtx_t builtins_lock = _MTX_INITIALIZER_NP; /** * External API (exposing the built-in module to the rest of the compiler): @@ -4108,20 +4360,28 @@ static builtin_builder builtins; void _mesa_glsl_initialize_builtin_functions() { + mtx_lock(&builtins_lock); builtins.initialize(); + mtx_unlock(&builtins_lock); } void _mesa_glsl_release_builtin_functions() { + mtx_lock(&builtins_lock); builtins.release(); + mtx_unlock(&builtins_lock); } ir_function_signature * _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters) { - return builtins.find(state, name, actual_parameters); + ir_function_signature * s; + mtx_lock(&builtins_lock); + s = builtins.find(state, name, actual_parameters); + mtx_unlock(&builtins_lock); + return s; } gl_shader * diff --git a/mesalib/src/glsl/builtin_type_macros.h b/mesalib/src/glsl/builtin_type_macros.h index 06b4dbd0f..236e1ce8c 100644 --- a/mesalib/src/glsl/builtin_type_macros.h +++ b/mesalib/src/glsl/builtin_type_macros.h @@ -64,51 +64,85 @@ DECL_TYPE(mat3x4, GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3) DECL_TYPE(mat4x2, GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4) DECL_TYPE(mat4x3, GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4) -DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) - -DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) - -DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) - -DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) - -DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) + +DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) + +DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) + +DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(image1D, GL_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2D, GL_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image3D, GL_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DRect, GL_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCube, GL_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageBuffer, GL_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image1DArray, GL_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DArray, GL_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCubeArray, GL_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMS, GL_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMSArray, GL_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(iimage1D, GL_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2D, GL_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage3D, GL_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DRect, GL_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageCube, GL_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageBuffer, GL_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage1DArray, GL_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DArray, GL_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimageCubeArray, GL_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMS, GL_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMSArray, GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(uimage1D, GL_UNSIGNED_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2D, GL_UNSIGNED_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage3D, GL_UNSIGNED_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DRect, GL_UNSIGNED_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageCube, GL_UNSIGNED_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageBuffer, GL_UNSIGNED_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage1DArray, GL_UNSIGNED_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DArray, GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimageCubeArray, GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT); DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1) diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp index 92e386057..dd42ecb05 100644 --- a/mesalib/src/glsl/builtin_types.cpp +++ b/mesalib/src/glsl/builtin_types.cpp @@ -204,6 +204,40 @@ const static struct builtin_type_versions { T(struct_gl_DepthRangeParameters, 110, 100) + T(image1D, 420, 999) + T(image2D, 420, 999) + T(image3D, 420, 999) + T(image2DRect, 420, 999) + T(imageCube, 420, 999) + T(imageBuffer, 420, 999) + T(image1DArray, 420, 999) + T(image2DArray, 420, 999) + T(imageCubeArray, 420, 999) + T(image2DMS, 420, 999) + T(image2DMSArray, 420, 999) + T(iimage1D, 420, 999) + T(iimage2D, 420, 999) + T(iimage3D, 420, 999) + T(iimage2DRect, 420, 999) + T(iimageCube, 420, 999) + T(iimageBuffer, 420, 999) + T(iimage1DArray, 420, 999) + T(iimage2DArray, 420, 999) + T(iimageCubeArray, 420, 999) + T(iimage2DMS, 420, 999) + T(iimage2DMSArray, 420, 999) + T(uimage1D, 420, 999) + T(uimage2D, 420, 999) + T(uimage3D, 420, 999) + T(uimage2DRect, 420, 999) + T(uimageCube, 420, 999) + T(uimageBuffer, 420, 999) + T(uimage1DArray, 420, 999) + T(uimage2DArray, 420, 999) + T(uimageCubeArray, 420, 999) + T(uimage2DMS, 420, 999) + T(uimage2DMSArray, 420, 999) + T(atomic_uint, 420, 999) }; @@ -287,6 +321,42 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) add_type(symbols, glsl_type::sampler3D_type); } + if (state->ARB_shader_image_load_store_enable) { + add_type(symbols, glsl_type::image1D_type); + add_type(symbols, glsl_type::image2D_type); + add_type(symbols, glsl_type::image3D_type); + add_type(symbols, glsl_type::image2DRect_type); + add_type(symbols, glsl_type::imageCube_type); + add_type(symbols, glsl_type::imageBuffer_type); + add_type(symbols, glsl_type::image1DArray_type); + add_type(symbols, glsl_type::image2DArray_type); + add_type(symbols, glsl_type::imageCubeArray_type); + add_type(symbols, glsl_type::image2DMS_type); + add_type(symbols, glsl_type::image2DMSArray_type); + add_type(symbols, glsl_type::iimage1D_type); + add_type(symbols, glsl_type::iimage2D_type); + add_type(symbols, glsl_type::iimage3D_type); + add_type(symbols, glsl_type::iimage2DRect_type); + add_type(symbols, glsl_type::iimageCube_type); + add_type(symbols, glsl_type::iimageBuffer_type); + add_type(symbols, glsl_type::iimage1DArray_type); + add_type(symbols, glsl_type::iimage2DArray_type); + add_type(symbols, glsl_type::iimageCubeArray_type); + add_type(symbols, glsl_type::iimage2DMS_type); + add_type(symbols, glsl_type::iimage2DMSArray_type); + add_type(symbols, glsl_type::uimage1D_type); + add_type(symbols, glsl_type::uimage2D_type); + add_type(symbols, glsl_type::uimage3D_type); + add_type(symbols, glsl_type::uimage2DRect_type); + add_type(symbols, glsl_type::uimageCube_type); + add_type(symbols, glsl_type::uimageBuffer_type); + add_type(symbols, glsl_type::uimage1DArray_type); + add_type(symbols, glsl_type::uimage2DArray_type); + add_type(symbols, glsl_type::uimageCubeArray_type); + add_type(symbols, glsl_type::uimage2DMS_type); + add_type(symbols, glsl_type::uimage2DMSArray_type); + } + if (state->ARB_shader_atomic_counters_enable) { add_type(symbols, glsl_type::atomic_uint_type); } diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index cc423383d..4176ae6e6 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -711,6 +711,26 @@ builtin_variable_generator::generate_constants() * in ast_cs_input_layout::hir(). */ } + + if (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable) { + add_const("gl_MaxImageUnits", + state->Const.MaxImageUnits); + add_const("gl_MaxCombinedImageUnitsAndFragmentOutputs", + state->Const.MaxCombinedImageUnitsAndFragmentOutputs); + add_const("gl_MaxImageSamples", + state->Const.MaxImageSamples); + add_const("gl_MaxVertexImageUniforms", + state->Const.MaxVertexImageUniforms); + add_const("gl_MaxTessControlImageUniforms", 0); + add_const("gl_MaxTessEvaluationImageUniforms", 0); + add_const("gl_MaxGeometryImageUniforms", + state->Const.MaxGeometryImageUniforms); + add_const("gl_MaxFragmentImageUniforms", + state->Const.MaxFragmentImageUniforms); + add_const("gl_MaxCombinedImageUniforms", + state->Const.MaxCombinedImageUniforms); + } } @@ -834,6 +854,8 @@ builtin_variable_generator::generate_gs_special_vars() add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer"); if (state->ARB_viewport_array_enable) add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex"); + if (state->ARB_gpu_shader5_enable) + add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID"); /* Although gl_PrimitiveID appears in tessellation control and tessellation * evaluation shaders, it has a different function there than it has in diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index eeafa4d39..f28d8531e 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1770,11 +1770,27 @@ static void _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc, const char *identifier) { - /* According to the GLSL specification, macro names starting with "__" - * or "GL_" are reserved for future use. So, don't allow them. + /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and + * the GLSL ES spec (all versions) say: + * + * "All macro names containing two consecutive underscores ( __ ) + * are reserved for future use as predefined macro names. All + * macro names prefixed with "GL_" ("GL" followed by a single + * underscore) are also reserved." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Since every extension adds a name prefixed + * with GL_ (i.e., the name of the extension), that should be an + * error. Names simply containing __ are dangerous to use, but should + * be allowed. + * + * A future version of the GLSL specification will clarify this. */ if (strstr(identifier, "__")) { - glcpp_error (loc, parser, "Macro names containing \"__\" are reserved.\n"); + glcpp_warning(loc, parser, + "Macro names containing \"__\" are reserved " + "for use by the implementation.\n"); } if (strncmp(identifier, "GL_", 3) == 0) { glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); @@ -2118,6 +2134,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_texture_gather) add_builtin_define(parser, "GL_ARB_texture_gather", 1); + if (extensions->ARB_separate_shader_objects) + add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1); + if (extensions->ARB_shader_atomic_counters) add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); @@ -2126,6 +2145,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_compute_shader) add_builtin_define(parser, "GL_ARB_compute_shader", 1); + + if (extensions->ARB_shader_image_load_store) + add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1); } } diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 3208b32da..9fd9b80d3 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -337,6 +337,51 @@ samplerExternalOES { return IDENTIFIER; } + /* keywords available with ARB_shader_image_load_store */ +image1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1D); +image2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2D); +image3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE3D); +image2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DRECT); +imageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBE); +imageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGEBUFFER); +image1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1DARRAY); +image2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DARRAY); +imageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBEARRAY); +image2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMS); +image2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMSARRAY); +iimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1D); +iimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2D); +iimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE3D); +iimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DRECT); +iimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBE); +iimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGEBUFFER); +iimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1DARRAY); +iimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DARRAY); +iimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBEARRAY); +iimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMS); +iimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMSARRAY); +uimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1D); +uimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2D); +uimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE3D); +uimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DRECT); +uimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBE); +uimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGEBUFFER); +uimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1DARRAY); +uimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DARRAY); +uimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBEARRAY); +uimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMS); +uimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMSARRAY); +image1DShadow KEYWORD(130, 300, 0, 0, IMAGE1DSHADOW); +image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW); +image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW); +image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); + +coherent KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, COHERENT); +volatile KEYWORD_WITH_ALT(110, 100, 420, 0, yyextra->ARB_shader_image_load_store_enable, VOLATILE); +restrict KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, RESTRICT); +readonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, READONLY); +writeonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, WRITEONLY); + atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT); struct return STRUCT; @@ -347,6 +392,7 @@ layout { || yyextra->AMD_conservative_depth_enable || yyextra->ARB_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable + || yyextra->has_separate_shader_objects() || yyextra->ARB_uniform_buffer_object_enable || yyextra->ARB_fragment_coord_conventions_enable || yyextra->ARB_shading_language_420pack_enable @@ -436,7 +482,6 @@ switch KEYWORD(110, 100, 130, 300, SWITCH); default KEYWORD(110, 100, 130, 300, DEFAULT); inline KEYWORD(110, 100, 0, 0, INLINE_TOK); noinline KEYWORD(110, 100, 0, 0, NOINLINE); -volatile KEYWORD(110, 100, 0, 0, VOLATILE); public KEYWORD(110, 100, 0, 0, PUBLIC_TOK); static KEYWORD(110, 100, 0, 0, STATIC); extern KEYWORD(110, 100, 0, 0, EXTERN); @@ -481,31 +526,6 @@ active KEYWORD(130, 300, 0, 0, ACTIVE); superp KEYWORD(130, 100, 0, 0, SUPERP); samplerBuffer KEYWORD(130, 300, 140, 0, SAMPLERBUFFER); filter KEYWORD(130, 300, 0, 0, FILTER); -image1D KEYWORD(130, 300, 0, 0, IMAGE1D); -image2D KEYWORD(130, 300, 0, 0, IMAGE2D); -image3D KEYWORD(130, 300, 0, 0, IMAGE3D); -imageCube KEYWORD(130, 300, 0, 0, IMAGECUBE); -iimage1D KEYWORD(130, 300, 0, 0, IIMAGE1D); -iimage2D KEYWORD(130, 300, 0, 0, IIMAGE2D); -iimage3D KEYWORD(130, 300, 0, 0, IIMAGE3D); -iimageCube KEYWORD(130, 300, 0, 0, IIMAGECUBE); -uimage1D KEYWORD(130, 300, 0, 0, UIMAGE1D); -uimage2D KEYWORD(130, 300, 0, 0, UIMAGE2D); -uimage3D KEYWORD(130, 300, 0, 0, UIMAGE3D); -uimageCube KEYWORD(130, 300, 0, 0, UIMAGECUBE); -image1DArray KEYWORD(130, 300, 0, 0, IMAGE1DARRAY); -image2DArray KEYWORD(130, 300, 0, 0, IMAGE2DARRAY); -iimage1DArray KEYWORD(130, 300, 0, 0, IIMAGE1DARRAY); -iimage2DArray KEYWORD(130, 300, 0, 0, IIMAGE2DARRAY); -uimage1DArray KEYWORD(130, 300, 0, 0, UIMAGE1DARRAY); -uimage2DArray KEYWORD(130, 300, 0, 0, UIMAGE2DARRAY); -image1DShadow KEYWORD(130, 300, 0, 0, IMAGE1DSHADOW); -image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW); -image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW); -image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); -imageBuffer KEYWORD(130, 300, 0, 0, IMAGEBUFFER); -iimageBuffer KEYWORD(130, 300, 0, 0, IIMAGEBUFFER); -uimageBuffer KEYWORD(130, 300, 0, 0, UIMAGEBUFFER); row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable && !yyextra->es_shader, ROW_MAJOR); /* Additional reserved words in GLSL 1.40 */ @@ -515,10 +535,6 @@ isamplerBuffer KEYWORD(140, 300, 140, 0, ISAMPLERBUFFER); usamplerBuffer KEYWORD(140, 300, 140, 0, USAMPLERBUFFER); /* Additional reserved words in GLSL ES 3.00 */ -coherent KEYWORD(0, 300, 0, 0, COHERENT); -restrict KEYWORD(0, 300, 0, 0, RESTRICT); -readonly KEYWORD(0, 300, 0, 0, READONLY); -writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); resource KEYWORD(0, 300, 0, 0, RESOURCE); patch KEYWORD(0, 300, 0, 0, PATCH); sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index dc35c1a51..1df572254 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -145,6 +145,14 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token SAMPLEREXTERNALOES +%token IMAGE1D IMAGE2D IMAGE3D IMAGE2DRECT IMAGECUBE IMAGEBUFFER +%token IMAGE1DARRAY IMAGE2DARRAY IMAGECUBEARRAY IMAGE2DMS IMAGE2DMSARRAY +%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGE2DRECT IIMAGECUBE IIMAGEBUFFER +%token IIMAGE1DARRAY IIMAGE2DARRAY IIMAGECUBEARRAY IIMAGE2DMS IIMAGE2DMSARRAY +%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGE2DRECT UIMAGECUBE UIMAGEBUFFER +%token UIMAGE1DARRAY UIMAGE2DARRAY UIMAGECUBEARRAY UIMAGE2DMS UIMAGE2DMSARRAY +%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW +%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY %token ATOMIC_UINT %token STRUCT VOID_TOK WHILE %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER @@ -170,23 +178,17 @@ static bool match_layout_qualifier(const char *s1, const char *s2, /* Reserved words that are not actually used in the grammar. */ %token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO -%token INLINE_TOK NOINLINE VOLATILE PUBLIC_TOK STATIC EXTERN EXTERNAL +%token INLINE_TOK NOINLINE PUBLIC_TOK STATIC EXTERN EXTERNAL %token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 %token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING -%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE PATCH SAMPLE +%token RESOURCE PATCH SAMPLE %token SUBROUTINE %token ERROR_TOK -%token COMMON PARTITION ACTIVE FILTER -%token IMAGE1D IMAGE2D IMAGE3D IMAGECUBE IMAGE1DARRAY IMAGE2DARRAY -%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY -%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY -%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER -%token IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW -%token ROW_MAJOR +%token COMMON PARTITION ACTIVE FILTER ROW_MAJOR %type <identifier> variable_identifier %type <node> statement @@ -1229,6 +1231,72 @@ layout_qualifier_id: } } + /* Layout qualifiers for ARB_shader_image_load_store. */ + if (state->ARB_shader_image_load_store_enable || + state->is_version(420, 0)) { + if (!$$.flags.i) { + static const struct { + const char *name; + GLenum format; + glsl_base_type base_type; + } map[] = { + { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT }, + { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT }, + { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT }, + { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT }, + { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT }, + { "r32f", GL_R32F, GLSL_TYPE_FLOAT }, + { "r16f", GL_R16F, GLSL_TYPE_FLOAT }, + { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT }, + { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT }, + { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT }, + { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT }, + { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT }, + { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT }, + { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT }, + { "r32ui", GL_R32UI, GLSL_TYPE_UINT }, + { "r16ui", GL_R16UI, GLSL_TYPE_UINT }, + { "r8ui", GL_R8UI, GLSL_TYPE_UINT }, + { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT }, + { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT }, + { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT }, + { "rg32i", GL_RG32I, GLSL_TYPE_INT }, + { "rg16i", GL_RG16I, GLSL_TYPE_INT }, + { "rg8i", GL_RG8I, GLSL_TYPE_INT }, + { "r32i", GL_R32I, GLSL_TYPE_INT }, + { "r16i", GL_R16I, GLSL_TYPE_INT }, + { "r8i", GL_R8I, GLSL_TYPE_INT }, + { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT }, + { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT }, + { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT }, + { "rg16", GL_RG16, GLSL_TYPE_FLOAT }, + { "rg8", GL_RG8, GLSL_TYPE_FLOAT }, + { "r16", GL_R16, GLSL_TYPE_FLOAT }, + { "r8", GL_R8, GLSL_TYPE_FLOAT }, + { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT }, + { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT }, + { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT }, + { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT }, + { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT }, + { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT } + }; + + for (unsigned i = 0; i < Elements(map); i++) { + if (match_layout_qualifier($1, map[i].name, state) == 0) { + $$.flags.q.explicit_image_format = 1; + $$.image_format = map[i].format; + $$.image_base_type = map[i].base_type; + break; + } + } + } + + if (!$$.flags.i && + match_layout_qualifier($1, "early_fragment_tests", state) == 0) { + $$.flags.q.early_fragment_tests = 1; + } + } + if (!$$.flags.i) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'", $1); @@ -1319,6 +1387,29 @@ layout_qualifier_id: } } + if (match_layout_qualifier("invocations", $1, state) == 0) { + $$.flags.q.invocations = 1; + + if ($3 <= 0) { + _mesa_glsl_error(& @3, state, + "invalid invocations %d specified", $3); + YYERROR; + } else if ($3 > MAX_GEOMETRY_SHADER_INVOCATIONS) { + _mesa_glsl_error(& @3, state, + "invocations (%d) exceeds " + "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", $3); + YYERROR; + } else { + $$.invocations = $3; + if (!state->is_version(400, 0) && + !state->ARB_gpu_shader5_enable) { + _mesa_glsl_error(& @3, state, + "GL_ARB_gpu_shader5 invocations " + "qualifier specified", $3); + } + } + } + /* If the identifier didn't match any known layout identifiers, * emit an error. */ @@ -1573,6 +1664,32 @@ storage_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.uniform = 1; } + | COHERENT + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.coherent = 1; + } + | VOLATILE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q._volatile = 1; + } + | RESTRICT + { + STATIC_ASSERT(sizeof($$.flags.q) <= sizeof($$.flags.i)); + memset(& $$, 0, sizeof($$)); + $$.flags.q.restrict_flag = 1; + } + | READONLY + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.read_only = 1; + } + | WRITEONLY + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.write_only = 1; + } ; array_specifier: @@ -1712,6 +1829,39 @@ basic_type_specifier_nonarray: | SAMPLER2DMSARRAY { $$ = "sampler2DMSArray"; } | ISAMPLER2DMSARRAY { $$ = "isampler2DMSArray"; } | USAMPLER2DMSARRAY { $$ = "usampler2DMSArray"; } + | IMAGE1D { $$ = "image1D"; } + | IMAGE2D { $$ = "image2D"; } + | IMAGE3D { $$ = "image3D"; } + | IMAGE2DRECT { $$ = "image2DRect"; } + | IMAGECUBE { $$ = "imageCube"; } + | IMAGEBUFFER { $$ = "imageBuffer"; } + | IMAGE1DARRAY { $$ = "image1DArray"; } + | IMAGE2DARRAY { $$ = "image2DArray"; } + | IMAGECUBEARRAY { $$ = "imageCubeArray"; } + | IMAGE2DMS { $$ = "image2DMS"; } + | IMAGE2DMSARRAY { $$ = "image2DMSArray"; } + | IIMAGE1D { $$ = "iimage1D"; } + | IIMAGE2D { $$ = "iimage2D"; } + | IIMAGE3D { $$ = "iimage3D"; } + | IIMAGE2DRECT { $$ = "iimage2DRect"; } + | IIMAGECUBE { $$ = "iimageCube"; } + | IIMAGEBUFFER { $$ = "iimageBuffer"; } + | IIMAGE1DARRAY { $$ = "iimage1DArray"; } + | IIMAGE2DARRAY { $$ = "iimage2DArray"; } + | IIMAGECUBEARRAY { $$ = "iimageCubeArray"; } + | IIMAGE2DMS { $$ = "iimage2DMS"; } + | IIMAGE2DMSARRAY { $$ = "iimage2DMSArray"; } + | UIMAGE1D { $$ = "uimage1D"; } + | UIMAGE2D { $$ = "uimage2D"; } + | UIMAGE3D { $$ = "uimage3D"; } + | UIMAGE2DRECT { $$ = "uimage2DRect"; } + | UIMAGECUBE { $$ = "uimageCube"; } + | UIMAGEBUFFER { $$ = "uimageBuffer"; } + | UIMAGE1DARRAY { $$ = "uimage1DArray"; } + | UIMAGE2DARRAY { $$ = "uimage2DArray"; } + | UIMAGECUBEARRAY { $$ = "uimageCubeArray"; } + | UIMAGE2DMS { $$ = "uimage2DMS"; } + | UIMAGE2DMSARRAY { $$ = "uimage2DMSArray"; } | ATOMIC_UINT { $$ = "atomic_uint"; } ; @@ -2228,7 +2378,7 @@ basic_interface_block: "an instance name are not allowed"); } - unsigned interface_type_mask; + uint64_t interface_type_mask; struct ast_type_qualifier temp_type_qualifier; /* Get a bitmask containing only the in/out/uniform flags, allowing us @@ -2244,7 +2394,7 @@ basic_interface_block: * production rule guarantees that only one bit will be set (and * it will be in/out/uniform). */ - unsigned block_interface_qualifier = $1.flags.i; + uint64_t block_interface_qualifier = $1.flags.i; block->layout.flags.i |= block_interface_qualifier; @@ -2360,55 +2510,9 @@ layout_defaults: | layout_qualifier IN_TOK ';' { - void *ctx = state; $$ = NULL; - switch (state->stage) { - case MESA_SHADER_GEOMETRY: { - if (!$1.flags.q.prim_type) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a primitive" - " type"); - } else { - /* Make sure this is a valid input primitive type. */ - switch ($1.prim_type) { - case GL_POINTS: - case GL_LINES: - case GL_LINES_ADJACENCY: - case GL_TRIANGLES: - case GL_TRIANGLES_ADJACENCY: - $$ = new(ctx) ast_gs_input_layout(@1, $1.prim_type); - break; - default: - _mesa_glsl_error(&@1, state, - "invalid geometry shader input primitive type"); - break; - } - } - } - break; - case MESA_SHADER_COMPUTE: { - if ($1.flags.q.local_size == 0) { - _mesa_glsl_error(& @1, state, - "input layout qualifiers must specify a local " - "size"); - } else { - /* Infer a local_size of 1 for every unspecified dimension */ - unsigned local_size[3]; - for (int i = 0; i < 3; i++) { - if ($1.flags.q.local_size & (1 << i)) - local_size[i] = $1.local_size[i]; - else - local_size[i] = 1; - } - $$ = new(ctx) ast_cs_input_layout(@1, local_size); - } - } - break; - default: - _mesa_glsl_error(& @1, state, - "input layout qualifiers only valid in " - "geometry and compute shaders"); - break; + if (!state->in_qualifier->merge_in_qualifier(& @1, state, $1, $$)) { + YYERROR; } } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index b822d2292..d7f5202fe 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -130,6 +130,14 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++) this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i]; + this->Const.MaxImageUnits = ctx->Const.MaxImageUnits; + this->Const.MaxCombinedImageUnitsAndFragmentOutputs = ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs; + this->Const.MaxImageSamples = ctx->Const.MaxImageSamples; + this->Const.MaxVertexImageUniforms = ctx->Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms; + this->Const.MaxGeometryImageUniforms = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms; + this->Const.MaxFragmentImageUniforms = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms; + this->Const.MaxCombinedImageUniforms = ctx->Const.MaxCombinedImageUniforms; + this->current_function = NULL; this->toplevel_ir = NULL; this->found_return = false; @@ -194,9 +202,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier->flags.q.column_major = 1; this->gs_input_prim_type_specified = false; - this->gs_input_prim_type = GL_POINTS; this->gs_input_size = 0; + this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); + this->early_fragment_tests = false; memset(this->atomic_counter_offsets, 0, sizeof(this->atomic_counter_offsets)); } @@ -503,6 +512,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions), EXT(ARB_texture_rectangle, true, false, dummy_true), EXT(EXT_texture_array, true, false, EXT_texture_array), + EXT(ARB_separate_shader_objects, true, false, ARB_separate_shader_objects), EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod), EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export), EXT(AMD_conservative_depth, true, false, ARB_conservative_depth), @@ -527,6 +537,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(AMD_shader_trinary_minmax, true, false, dummy_true), EXT(ARB_viewport_array, true, false, ARB_viewport_array), EXT(ARB_compute_shader, true, false, ARB_compute_shader), + EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store), }; #undef EXT @@ -1338,7 +1349,7 @@ set_shader_inout_layout(struct gl_shader *shader, { if (shader->Stage != MESA_SHADER_GEOMETRY) { /* Should have been prevented by the parser. */ - assert(!state->gs_input_prim_type_specified); + assert(!state->in_qualifier->flags.i); assert(!state->out_qualifier->flags.i); } @@ -1354,7 +1365,7 @@ set_shader_inout_layout(struct gl_shader *shader, shader->Geom.VerticesOut = state->out_qualifier->max_vertices; if (state->gs_input_prim_type_specified) { - shader->Geom.InputType = state->gs_input_prim_type; + shader->Geom.InputType = state->in_qualifier->prim_type; } else { shader->Geom.InputType = PRIM_UNKNOWN; } @@ -1364,6 +1375,10 @@ set_shader_inout_layout(struct gl_shader *shader, } else { shader->Geom.OutputType = PRIM_UNKNOWN; } + + shader->Geom.Invocations = 0; + if (state->in_qualifier->flags.q.invocations) + shader->Geom.Invocations = state->in_qualifier->invocations; break; case MESA_SHADER_COMPUTE: @@ -1419,7 +1434,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, /* Print out the unoptimized IR. */ if (dump_hir) { - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); } } diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 7d661473d..300d90051 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -135,6 +135,23 @@ struct _mesa_glsl_parse_state { return true; } + bool check_separate_shader_objects_allowed(YYLTYPE *locp, + const ir_variable *var) + { + if (!this->has_separate_shader_objects()) { + const char *const requirement = this->es_shader + ? "GL_EXT_separate_shader_objects (not supported by this " + "implementation)" + : "GL_ARB_separate_shader_objects extension or GLSL 420"; + + _mesa_glsl_error(locp, this, "%s explicit location requires %s", + mode_string(var), requirement); + return false; + } + + return true; + } + bool has_explicit_attrib_location() const { return ARB_explicit_attrib_location_enable || is_version(330, 300); @@ -145,6 +162,11 @@ struct _mesa_glsl_parse_state { return ARB_uniform_buffer_object_enable || is_version(140, 300); } + bool has_separate_shader_objects() const + { + return ARB_separate_shader_objects_enable || is_version(410, 0); + } + void process_version_directive(YYLTYPE *locp, int version, const char *ident); @@ -190,11 +212,8 @@ struct _mesa_glsl_parse_state { */ bool gs_input_prim_type_specified; - /** - * If gs_input_prim_type_specified is true, the primitive type that was - * specified. Otherwise ignored. - */ - GLenum gs_input_prim_type; + /** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + struct ast_type_qualifier *in_qualifier; /** * True if a compute shader input local size was specified using a layout @@ -269,6 +288,15 @@ struct _mesa_glsl_parse_state { /* ARB_compute_shader */ unsigned MaxComputeWorkGroupCount[3]; unsigned MaxComputeWorkGroupSize[3]; + + /* ARB_shader_image_load_store */ + unsigned MaxImageUnits; + unsigned MaxCombinedImageUnitsAndFragmentOutputs; + unsigned MaxImageSamples; + unsigned MaxVertexImageUniforms; + unsigned MaxGeometryImageUniforms; + unsigned MaxFragmentImageUniforms; + unsigned MaxCombinedImageUniforms; } Const; /** @@ -329,6 +357,8 @@ struct _mesa_glsl_parse_state { bool ARB_texture_gather_warn; bool EXT_texture_array_enable; bool EXT_texture_array_warn; + bool ARB_separate_shader_objects_enable; + bool ARB_separate_shader_objects_warn; bool ARB_shader_texture_lod_enable; bool ARB_shader_texture_lod_warn; bool ARB_shader_stencil_export_enable; @@ -377,6 +407,8 @@ struct _mesa_glsl_parse_state { bool ARB_viewport_array_warn; bool ARB_compute_shader_enable; bool ARB_compute_shader_warn; + bool ARB_shader_image_load_store_enable; + bool ARB_shader_image_load_store_warn; /*@}*/ /** Extensions supported by the OpenGL implementation. */ @@ -393,6 +425,8 @@ struct _mesa_glsl_parse_state { */ unsigned gs_input_size; + bool early_fragment_tests; + /** Atomic counter offsets by binding */ unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS]; }; diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 1b0b3ef88..849a79af4 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -64,20 +64,26 @@ glsl_type::glsl_type(GLenum gl_type, memset(& fields, 0, sizeof(fields)); } -glsl_type::glsl_type(GLenum gl_type, +glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, enum glsl_sampler_dim dim, bool shadow, bool array, unsigned type, const char *name) : gl_type(gl_type), - base_type(GLSL_TYPE_SAMPLER), + base_type(base_type), sampler_dimensionality(dim), sampler_shadow(shadow), sampler_array(array), sampler_type(type), interface_packing(0), - vector_elements(0), matrix_columns(0), length(0) { init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); memset(& fields, 0, sizeof(fields)); + + if (base_type == GLSL_TYPE_SAMPLER) { + /* Samplers take no storage whatsoever. */ + matrix_columns = vector_elements = 0; + } else { + matrix_columns = vector_elements = 1; + } } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -174,6 +180,7 @@ bool glsl_type::contains_opaque() const { switch (base_type) { case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: return true; case GLSL_TYPE_ARRAY: @@ -219,6 +226,21 @@ glsl_type::sampler_index() const } } +bool +glsl_type::contains_image() const +{ + if (this->is_array()) { + return this->fields.array->contains_image(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_image()) + return true; + } + return false; + } else { + return this->is_image(); + } +} const glsl_type *glsl_type::get_base_type() const { @@ -642,6 +664,9 @@ glsl_type::component_slots() const case GLSL_TYPE_ARRAY: return this->length * this->fields.array->component_slots(); + case GLSL_TYPE_IMAGE: + return 1; + case GLSL_TYPE_SAMPLER: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: @@ -932,6 +957,7 @@ glsl_type::count_attribute_slots() const return this->length * this->fields.array->count_attribute_slots(); case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: @@ -944,10 +970,8 @@ glsl_type::count_attribute_slots() const } int -glsl_type::sampler_coordinate_components() const +glsl_type::coordinate_components() const { - assert(is_sampler()); - int size; switch (sampler_dimensionality) { diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index f88758a9a..ae3829f30 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -53,6 +53,7 @@ enum glsl_base_type { GLSL_TYPE_FLOAT, GLSL_TYPE_BOOL, GLSL_TYPE_SAMPLER, + GLSL_TYPE_IMAGE, GLSL_TYPE_ATOMIC_UINT, GLSL_TYPE_STRUCT, GLSL_TYPE_INTERFACE, @@ -89,8 +90,9 @@ struct glsl_type { unsigned sampler_dimensionality:3; /**< \see glsl_sampler_dim */ unsigned sampler_shadow:1; unsigned sampler_array:1; - unsigned sampler_type:2; /**< Type of data returned using this sampler. - * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, + unsigned sampler_type:2; /**< Type of data returned using this + * sampler or image. Only \c + * GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, * and \c GLSL_TYPE_UINT are valid. */ unsigned interface_packing:2; @@ -402,6 +404,20 @@ struct glsl_type { gl_texture_index sampler_index() const; /** + * Query whether or not type is an image, or for struct and array + * types, contains an image. + */ + bool contains_image() const; + + /** + * Query whether or not a type is an image + */ + bool is_image() const + { + return base_type == GLSL_TYPE_IMAGE; + } + + /** * Query whether or not a type is an array */ bool is_array() const @@ -531,7 +547,8 @@ struct glsl_type { } /** - * Return the number of coordinate components needed for this sampler type. + * Return the number of coordinate components needed for this + * sampler or image type. * * This is based purely on the sampler's dimensionality. For example, this * returns 1 for sampler1D, and 3 for sampler2DArray. @@ -540,7 +557,7 @@ struct glsl_type { * a texturing built-in function, since those pack additional values (such * as the shadow comparitor or projector) into the coordinate type. */ - int sampler_coordinate_components() const; + int coordinate_components() const; /** * Compare a record type against another record type. @@ -564,8 +581,8 @@ private: glsl_base_type base_type, unsigned vector_elements, unsigned matrix_columns, const char *name); - /** Constructor for sampler types */ - glsl_type(GLenum gl_type, + /** Constructor for sampler or image types */ + glsl_type(GLenum gl_type, glsl_base_type base_type, enum glsl_sampler_dim dim, bool shadow, bool array, unsigned type, const char *name); diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 1a36bd631..a41eddfcb 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1311,13 +1311,13 @@ ir_dereference::is_lvalue() const if ((var == NULL) || var->data.read_only) return false; - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "Samplers cannot be treated as l-values; hence cannot be used - * as out or inout function parameters, nor can they be - * assigned into." + * "Opaque variables cannot be treated as l-values; hence cannot + * be used as out or inout function parameters, nor can they be + * assigned into." */ - if (this->type->contains_sampler()) + if (this->type->contains_opaque()) return false; return true; @@ -1554,6 +1554,11 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->data.max_array_access = 0; this->data.atomic.buffer_index = 0; this->data.atomic.offset = 0; + this->data.image.read_only = false; + this->data.image.write_only = false; + this->data.image.coherent = false; + this->data.image._volatile = false; + this->data.image.restrict_flag = false; if (type != NULL) { if (type->base_type == GLSL_TYPE_SAMPLER) @@ -1658,7 +1663,12 @@ ir_function_signature::qualifiers_match(exec_list *params) !modes_match(a->data.mode, b->data.mode) || a->data.interpolation != b->data.interpolation || a->data.centroid != b->data.centroid || - a->data.sample != b->data.sample) { + a->data.sample != b->data.sample || + a->data.image.read_only != b->data.image.read_only || + a->data.image.write_only != b->data.image.write_only || + a->data.image.coherent != b->data.image.coherent || + a->data.image._volatile != b->data.image._volatile || + a->data.image.restrict_flag != b->data.image.restrict_flag) { /* parameter a's qualifiers don't match */ return a->name; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index e266328b2..ed3f086ce 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -106,6 +106,7 @@ public: /** ir_print_visitor helper for debugging. */ void print(void) const; + void fprint(FILE *f) const; virtual void accept(ir_visitor *) = 0; virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0; @@ -691,6 +692,20 @@ public: } atomic; /** + * ARB_shader_image_load_store qualifiers. + */ + struct { + bool read_only; /**< "readonly" qualifier. */ + bool write_only; /**< "writeonly" qualifier. */ + bool coherent; + bool _volatile; + bool restrict_flag; + + /** Image internal format if specified explicitly, otherwise GL_NONE. */ + GLenum format; + } image; + + /** * Highest element accessed with a constant expression array index * * Not used for non-array variables. @@ -1444,6 +1459,18 @@ public: } /** + * Return whether the expression operates on vectors horizontally. + */ + bool is_horizontal() const + { + return operation == ir_binop_all_equal || + operation == ir_binop_any_nequal || + operation == ir_unop_any || + operation == ir_binop_dot || + operation == ir_quadop_vector; + } + + /** * Return a string representing this expression's operator. */ const char *operator_string(); @@ -2339,7 +2366,7 @@ mode_string(const ir_variable *var); extern "C" { #endif /* __cplusplus */ -extern void _mesa_print_ir(struct exec_list *instructions, +extern void _mesa_print_ir(FILE *f, struct exec_list *instructions, struct _mesa_glsl_parse_state *state); #ifdef __cplusplus diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index cb732a51a..311c992be 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -373,6 +373,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const } case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 055d65547..5f4a2f405 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -36,9 +36,8 @@ #define LOG_TO_LOG2 0x10 #define MOD_TO_FRACT 0x20 #define INT_DIV_TO_MUL_RCP 0x40 -#define LRP_TO_ARITH 0x80 -#define BITFIELD_INSERT_TO_BFM_BFI 0x100 -#define LDEXP_TO_ARITH 0x200 +#define BITFIELD_INSERT_TO_BFM_BFI 0x80 +#define LDEXP_TO_ARITH 0x100 /** * \see class lower_packing_builtins_visitor @@ -120,6 +119,7 @@ bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index); void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader); bool optimize_redundant_jumps(exec_list *instructions); bool optimize_split_arrays(exec_list *instructions, bool linked); +bool lower_offset_arrays(exec_list *instructions); ir_rvalue * compare_index_block(exec_list *instructions, ir_variable *index, diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index 935782184..c7786ba9f 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -27,52 +27,59 @@ #include "main/macros.h" #include "program/hash_table.h" -static void print_type(const glsl_type *t); +static void print_type(FILE *f, const glsl_type *t); void ir_instruction::print(void) const { + this->fprint(stdout); +} + +void +ir_instruction::fprint(FILE *f) const +{ ir_instruction *deconsted = const_cast<ir_instruction *>(this); - ir_print_visitor v; + ir_print_visitor v(f); deconsted->accept(&v); } extern "C" { void -_mesa_print_ir(exec_list *instructions, +_mesa_print_ir(FILE *f, exec_list *instructions, struct _mesa_glsl_parse_state *state) { if (state) { for (unsigned i = 0; i < state->num_user_structures; i++) { const glsl_type *const s = state->user_structures[i]; - printf("(structure (%s) (%s@%p) (%u) (\n", - s->name, s->name, (void *) s, s->length); + fprintf(f, "(structure (%s) (%s@%p) (%u) (\n", + s->name, s->name, (void *) s, s->length); for (unsigned j = 0; j < s->length; j++) { - printf("\t(("); - print_type(s->fields.structure[j].type); - printf(")(%s))\n", s->fields.structure[j].name); + fprintf(f, "\t(("); + print_type(f, s->fields.structure[j].type); + fprintf(f, ")(%s))\n", s->fields.structure[j].name); } - printf(")\n"); + fprintf(f, ")\n"); } } - printf("(\n"); + fprintf(f, "(\n"); foreach_list(n, instructions) { ir_instruction *ir = (ir_instruction *) n; - ir->print(); + ir->fprint(f); if (ir->ir_type != ir_type_function) - printf("\n"); + fprintf(f, "\n"); } - printf("\n)"); + fprintf(f, "\n)"); } } /* extern "C" */ -ir_print_visitor::ir_print_visitor() +ir_print_visitor::ir_print_visitor(FILE *f) + : f(f) { indentation = 0; printable_names = @@ -91,7 +98,7 @@ ir_print_visitor::~ir_print_visitor() void ir_print_visitor::indent(void) { for (int i = 0; i < indentation; i++) - printf(" "); + fprintf(f, " "); } const char * @@ -125,28 +132,28 @@ ir_print_visitor::unique_name(ir_variable *var) } static void -print_type(const glsl_type *t) +print_type(FILE *f, const glsl_type *t) { if (t->base_type == GLSL_TYPE_ARRAY) { - printf("(array "); - print_type(t->fields.array); - printf(" %u)", t->length); + fprintf(f, "(array "); + print_type(f, t->fields.array); + fprintf(f, " %u)", t->length); } else if ((t->base_type == GLSL_TYPE_STRUCT) && (strncmp("gl_", t->name, 3) != 0)) { - printf("%s@%p", t->name, (void *) t); + fprintf(f, "%s@%p", t->name, (void *) t); } else { - printf("%s", t->name); + fprintf(f, "%s", t->name); } } void ir_print_visitor::visit(ir_rvalue *ir) { - printf("error"); + fprintf(f, "error"); } void ir_print_visitor::visit(ir_variable *ir) { - printf("(declare "); + fprintf(f, "(declare "); const char *const cent = (ir->data.centroid) ? "centroid " : ""; const char *const samp = (ir->data.sample) ? "sample " : ""; @@ -158,25 +165,25 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - printf("(%s%s%s%s%s) ", + fprintf(f, "(%s%s%s%s%s) ", cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]); - print_type(ir->type); - printf(" %s)", unique_name(ir)); + print_type(f, ir->type); + fprintf(f, " %s)", unique_name(ir)); } void ir_print_visitor::visit(ir_function_signature *ir) { _mesa_symbol_table_push_scope(symbols); - printf("(signature "); + fprintf(f, "(signature "); indentation++; - print_type(ir->return_type); - printf("\n"); + print_type(f, ir->return_type); + fprintf(f, "\n"); indent(); - printf("(parameters\n"); + fprintf(f, "(parameters\n"); indentation++; foreach_list(n, &ir->parameters) { @@ -184,16 +191,16 @@ void ir_print_visitor::visit(ir_function_signature *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n"); + fprintf(f, ")\n"); indent(); - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->body) { @@ -201,11 +208,11 @@ void ir_print_visitor::visit(ir_function_signature *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); indentation--; _mesa_symbol_table_pop_scope(symbols); } @@ -213,58 +220,58 @@ void ir_print_visitor::visit(ir_function_signature *ir) void ir_print_visitor::visit(ir_function *ir) { - printf("(function %s\n", ir->name); + fprintf(f, "(function %s\n", ir->name); indentation++; foreach_list(n, &ir->signatures) { ir_function_signature *const sig = (ir_function_signature *) n; indent(); sig->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n\n"); + fprintf(f, ")\n\n"); } void ir_print_visitor::visit(ir_expression *ir) { - printf("(expression "); + fprintf(f, "(expression "); - print_type(ir->type); + print_type(f, ir->type); - printf(" %s ", ir->operator_string()); + fprintf(f, " %s ", ir->operator_string()); for (unsigned i = 0; i < ir->get_num_operands(); i++) { ir->operands[i]->accept(this); } - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_texture *ir) { - printf("(%s ", ir->opcode_string()); + fprintf(f, "(%s ", ir->opcode_string()); - print_type(ir->type); - printf(" "); + print_type(f, ir->type); + fprintf(f, " "); ir->sampler->accept(this); - printf(" "); + fprintf(f, " "); if (ir->op != ir_txs && ir->op != ir_query_levels) { ir->coordinate->accept(this); - printf(" "); + fprintf(f, " "); if (ir->offset != NULL) { ir->offset->accept(this); } else { - printf("0"); + fprintf(f, "0"); } - printf(" "); + fprintf(f, " "); } if (ir->op != ir_txf && ir->op != ir_txf_ms && @@ -273,17 +280,17 @@ void ir_print_visitor::visit(ir_texture *ir) if (ir->projector) ir->projector->accept(this); else - printf("1"); + fprintf(f, "1"); if (ir->shadow_comparitor) { - printf(" "); + fprintf(f, " "); ir->shadow_comparitor->accept(this); } else { - printf(" ()"); + fprintf(f, " ()"); } } - printf(" "); + fprintf(f, " "); switch (ir->op) { case ir_tex: @@ -302,17 +309,17 @@ void ir_print_visitor::visit(ir_texture *ir) ir->lod_info.sample_index->accept(this); break; case ir_txd: - printf("("); + fprintf(f, "("); ir->lod_info.grad.dPdx->accept(this); - printf(" "); + fprintf(f, " "); ir->lod_info.grad.dPdy->accept(this); - printf(")"); + fprintf(f, ")"); break; case ir_tg4: ir->lod_info.component->accept(this); break; }; - printf(")"); + fprintf(f, ")"); } @@ -325,43 +332,43 @@ void ir_print_visitor::visit(ir_swizzle *ir) ir->mask.w, }; - printf("(swiz "); + fprintf(f, "(swiz "); for (unsigned i = 0; i < ir->mask.num_components; i++) { - printf("%c", "xyzw"[swiz[i]]); + fprintf(f, "%c", "xyzw"[swiz[i]]); } - printf(" "); + fprintf(f, " "); ir->val->accept(this); - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_dereference_variable *ir) { ir_variable *var = ir->variable_referenced(); - printf("(var_ref %s) ", unique_name(var)); + fprintf(f, "(var_ref %s) ", unique_name(var)); } void ir_print_visitor::visit(ir_dereference_array *ir) { - printf("(array_ref "); + fprintf(f, "(array_ref "); ir->array->accept(this); ir->array_index->accept(this); - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_dereference_record *ir) { - printf("(record_ref "); + fprintf(f, "(record_ref "); ir->record->accept(this); - printf(" %s) ", ir->field); + fprintf(f, " %s) ", ir->field); } void ir_print_visitor::visit(ir_assignment *ir) { - printf("(assign "); + fprintf(f, "(assign "); if (ir->condition) ir->condition->accept(this); @@ -377,22 +384,22 @@ void ir_print_visitor::visit(ir_assignment *ir) } mask[j] = '\0'; - printf(" (%s) ", mask); + fprintf(f, " (%s) ", mask); ir->lhs->accept(this); - printf(" "); + fprintf(f, " "); ir->rhs->accept(this); - printf(") "); + fprintf(f, ") "); } void ir_print_visitor::visit(ir_constant *ir) { - printf("(constant "); - print_type(ir->type); - printf(" ("); + fprintf(f, "(constant "); + print_type(f, ir->type); + fprintf(f, " ("); if (ir->type->is_array()) { for (unsigned i = 0; i < ir->type->length; i++) @@ -400,91 +407,91 @@ void ir_print_visitor::visit(ir_constant *ir) } else if (ir->type->is_record()) { ir_constant *value = (ir_constant *) ir->components.get_head(); for (unsigned i = 0; i < ir->type->length; i++) { - printf("(%s ", ir->type->fields.structure[i].name); + fprintf(f, "(%s ", ir->type->fields.structure[i].name); value->accept(this); - printf(")"); + fprintf(f, ")"); value = (ir_constant *) value->next; } } else { for (unsigned i = 0; i < ir->type->components(); i++) { if (i != 0) - printf(" "); + fprintf(f, " "); switch (ir->type->base_type) { - case GLSL_TYPE_UINT: printf("%u", ir->value.u[i]); break; - case GLSL_TYPE_INT: printf("%d", ir->value.i[i]); break; + case GLSL_TYPE_UINT: fprintf(f, "%u", ir->value.u[i]); break; + case GLSL_TYPE_INT: fprintf(f, "%d", ir->value.i[i]); break; case GLSL_TYPE_FLOAT: if (ir->value.f[i] == 0.0f) /* 0.0 == -0.0, so print with %f to get the proper sign. */ - printf("%.1f", ir->value.f[i]); + fprintf(f, "%.1f", ir->value.f[i]); else if (fabs(ir->value.f[i]) < 0.000001f) - printf("%a", ir->value.f[i]); + fprintf(f, "%a", ir->value.f[i]); else if (fabs(ir->value.f[i]) > 1000000.0f) - printf("%e", ir->value.f[i]); + fprintf(f, "%e", ir->value.f[i]); else - printf("%f", ir->value.f[i]); + fprintf(f, "%f", ir->value.f[i]); break; - case GLSL_TYPE_BOOL: printf("%d", ir->value.b[i]); break; + case GLSL_TYPE_BOOL: fprintf(f, "%d", ir->value.b[i]); break; default: assert(0); } } } - printf(")) "); + fprintf(f, ")) "); } void ir_print_visitor::visit(ir_call *ir) { - printf("(call %s ", ir->callee_name()); + fprintf(f, "(call %s ", ir->callee_name()); if (ir->return_deref) ir->return_deref->accept(this); - printf(" ("); + fprintf(f, " ("); foreach_list(n, &ir->actual_parameters) { ir_rvalue *const param = (ir_rvalue *) n; param->accept(this); } - printf("))\n"); + fprintf(f, "))\n"); } void ir_print_visitor::visit(ir_return *ir) { - printf("(return"); + fprintf(f, "(return"); ir_rvalue *const value = ir->get_value(); if (value) { - printf(" "); + fprintf(f, " "); value->accept(this); } - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_discard *ir) { - printf("(discard "); + fprintf(f, "(discard "); if (ir->condition != NULL) { - printf(" "); + fprintf(f, " "); ir->condition->accept(this); } - printf(")"); + fprintf(f, ")"); } void ir_print_visitor::visit(ir_if *ir) { - printf("(if "); + fprintf(f, "(if "); ir->condition->accept(this); - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->then_instructions) { @@ -492,16 +499,16 @@ ir_print_visitor::visit(ir_if *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf(")\n"); + fprintf(f, ")\n"); indent(); if (!ir->else_instructions.is_empty()) { - printf("(\n"); + fprintf(f, "(\n"); indentation++; foreach_list(n, &ir->else_instructions) { @@ -509,13 +516,13 @@ ir_print_visitor::visit(ir_if *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); } else { - printf("())\n"); + fprintf(f, "())\n"); } } @@ -523,7 +530,7 @@ ir_print_visitor::visit(ir_if *ir) void ir_print_visitor::visit(ir_loop *ir) { - printf("(loop (\n"); + fprintf(f, "(loop (\n"); indentation++; foreach_list(n, &ir->body_instructions) { @@ -531,28 +538,28 @@ ir_print_visitor::visit(ir_loop *ir) indent(); inst->accept(this); - printf("\n"); + fprintf(f, "\n"); } indentation--; indent(); - printf("))\n"); + fprintf(f, "))\n"); } void ir_print_visitor::visit(ir_loop_jump *ir) { - printf("%s", ir->is_break() ? "break" : "continue"); + fprintf(f, "%s", ir->is_break() ? "break" : "continue"); } void ir_print_visitor::visit(ir_emit_vertex *ir) { - printf("(emit-vertex)"); + fprintf(f, "(emit-vertex)"); } void ir_print_visitor::visit(ir_end_primitive *ir) { - printf("(end-primitive)"); + fprintf(f, "(end-primitive)"); } diff --git a/mesalib/src/glsl/ir_print_visitor.h b/mesalib/src/glsl/ir_print_visitor.h index 865376fe0..98f041d1a 100644 --- a/mesalib/src/glsl/ir_print_visitor.h +++ b/mesalib/src/glsl/ir_print_visitor.h @@ -38,7 +38,7 @@ extern "C" { */ class ir_print_visitor : public ir_visitor { public: - ir_print_visitor(); + ir_print_visitor(FILE *f); virtual ~ir_print_visitor(); void indent(void); @@ -87,6 +87,7 @@ private: _mesa_symbol_table *symbols; void *mem_ctx; + FILE *f; int indentation; }; diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index f678c2c5c..7508f795d 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -78,6 +78,26 @@ struct gl_uniform_driver_storage { void *data; }; +struct gl_opaque_uniform_index { + /** + * Base opaque uniform index + * + * If \c gl_uniform_storage::base_type is an opaque type, this + * represents its uniform index. If \c + * gl_uniform_storage::array_elements is not zero, the array will + * use opaque uniform indices \c index through \c index + \c + * gl_uniform_storage::array_elements - 1, inclusive. + * + * Note that the index may be different in each shader stage. + */ + uint8_t index; + + /** + * Whether this opaque uniform is used in this shader stage. + */ + bool active; +}; + struct gl_uniform_storage { char *name; /** Type of this uniform data stored. @@ -99,24 +119,9 @@ struct gl_uniform_storage { */ bool initialized; - struct { - /** - * Base sampler index - * - * If \c ::base_type is \c GLSL_TYPE_SAMPLER, this represents the index - * of this sampler. If \c ::array_elements is not zero, the array will - * use sampler indices \c ::sampler through \c ::sampler + - * \c ::array_elements - 1, inclusive. - * - * Note that the index may be different in each shader stage. - */ - uint8_t index; - - /** - * Whether this sampler is used in this shader stage. - */ - bool active; - } sampler[MESA_SHADER_STAGES]; + struct gl_opaque_uniform_index sampler[MESA_SHADER_STAGES]; + + struct gl_opaque_uniform_index image[MESA_SHADER_STAGES]; /** * Storage used by the driver for the uniform diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 7d5c1472d..9d6977d57 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -69,6 +69,7 @@ copy_constant_to_storage(union gl_constant_value *storage, break; case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 1c97e1957..1cf376d5d 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -240,7 +240,8 @@ class count_uniform_size : public program_resource_visitor { public: count_uniform_size(struct string_to_uint_map *map) : num_active_uniforms(0), num_values(0), num_shader_samplers(0), - num_shader_uniform_components(0), is_ubo_var(false), map(map) + num_shader_images(0), num_shader_uniform_components(0), + is_ubo_var(false), map(map) { /* empty */ } @@ -248,6 +249,7 @@ public: void start_shader() { this->num_shader_samplers = 0; + this->num_shader_images = 0; this->num_shader_uniform_components = 0; } @@ -277,6 +279,11 @@ public: unsigned num_shader_samplers; /** + * Number of images used + */ + unsigned num_shader_images; + + /** * Number of uniforms used in the current shader */ unsigned num_shader_uniform_components; @@ -303,6 +310,15 @@ private: if (type->contains_sampler()) { this->num_shader_samplers += type->is_array() ? type->array_size() : 1; + } else if (type->contains_image()) { + this->num_shader_images += values; + + /* As drivers are likely to represent image uniforms as + * scalar indices, count them against the limit of uniform + * components in the default block. The spec allows image + * uniforms to use up no more than one scalar slot. + */ + 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 @@ -364,6 +380,7 @@ public: this->shader_samplers_used = 0; this->shader_shadow_samplers = 0; this->next_sampler = 0; + this->next_image = 0; memset(this->targets, 0, sizeof(this->targets)); } @@ -460,6 +477,24 @@ private: } } + void handle_images(const glsl_type *base_type, + struct gl_uniform_storage *uniform) + { + if (base_type->is_image()) { + uniform->image[shader_type].index = this->next_image; + uniform->image[shader_type].active = true; + + /* Increment the image index by 1 for non-arrays and by the + * number of array elements for arrays. + */ + this->next_image += MAX2(1, uniform->array_elements); + + } else { + uniform->image[shader_type].index = ~0; + uniform->image[shader_type].active = false; + } + } + virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { @@ -495,8 +530,9 @@ private: base_type = type; } - /* This assigns sampler uniforms to sampler units. */ + /* This assigns uniform indices to sampler and image uniforms. */ handle_samplers(base_type, &this->uniforms[id]); + handle_images(base_type, &this->uniforms[id]); /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For @@ -554,6 +590,7 @@ private: struct gl_uniform_storage *uniforms; unsigned next_sampler; + unsigned next_image; public: union gl_constant_value *values; @@ -720,6 +757,40 @@ link_assign_uniform_block_offsets(struct gl_shader *shader) } } +/** + * Scan the program for image uniforms and store image unit access + * information into the gl_shader data structure. + */ +static void +link_set_image_access_qualifiers(struct gl_shader_program *prog) +{ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh == NULL) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + + if (var && var->data.mode == ir_var_uniform && + var->type->contains_image()) { + unsigned id; + bool found = prog->UniformHash->get(id, var->name); + assert(found); + const gl_uniform_storage *storage = &prog->UniformStorage[id]; + const unsigned index = storage->image[i].index; + const GLenum access = (var->data.image.read_only ? GL_READ_ONLY : + var->data.image.write_only ? GL_WRITE_ONLY : + GL_READ_WRITE); + + for (unsigned j = 0; j < MAX2(1, storage->array_elements); ++j) + sh->ImageAccess[index + j] = access; + } + } + } +} + void link_assign_uniform_locations(struct gl_shader_program *prog) { @@ -757,6 +828,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) * types cannot have initializers." */ memset(sh->SamplerUnits, 0, sizeof(sh->SamplerUnits)); + memset(sh->ImageUnits, 0, sizeof(sh->ImageUnits)); link_update_uniform_buffer_variables(sh); @@ -782,6 +854,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) } sh->num_samplers = uniform_size.num_shader_samplers; + sh->NumImages = uniform_size.num_shader_images; sh->num_uniform_components = uniform_size.num_shader_uniform_components; sh->num_combined_uniform_components = sh->num_uniform_components; @@ -862,6 +935,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) prog->NumUserUniformStorage = num_user_uniforms; prog->UniformStorage = uniforms; + link_set_image_access_qualifiers(prog); link_set_uniform_initializers(prog); return; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index bcd739476..f6b266185 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1206,6 +1206,7 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, unsigned num_shaders) { linked_shader->Geom.VerticesOut = 0; + linked_shader->Geom.Invocations = 0; linked_shader->Geom.InputType = PRIM_UNKNOWN; linked_shader->Geom.OutputType = PRIM_UNKNOWN; @@ -1259,6 +1260,18 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, } linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut; } + + if (shader->Geom.Invocations != 0) { + if (linked_shader->Geom.Invocations != 0 && + linked_shader->Geom.Invocations != shader->Geom.Invocations) { + linker_error(prog, "geometry shader defined with conflicting " + "invocation count (%d and %d)\n", + linked_shader->Geom.Invocations, + shader->Geom.Invocations); + return; + } + linked_shader->Geom.Invocations = shader->Geom.Invocations; + } } /* Just do the intrastage -> interstage propagation right now, @@ -1285,6 +1298,11 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, return; } prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut; + + if (linked_shader->Geom.Invocations == 0) + linked_shader->Geom.Invocations = 1; + + prog->Geom.Invocations = linked_shader->Geom.Invocations; } @@ -2031,6 +2049,46 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } } +/** + * Validate shader image resources. + */ +static void +check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) +{ + unsigned total_image_units = 0; + unsigned fragment_outputs = 0; + + if (!ctx->Extensions.ARB_shader_image_load_store) + return; + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh) { + if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms) + linker_error(prog, "Too many %s shader image uniforms", + _mesa_shader_stage_to_string(i)); + + total_image_units += sh->NumImages; + + if (i == MESA_SHADER_FRAGMENT) { + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + if (var && var->data.mode == ir_var_shader_out) + fragment_outputs += var->type->count_attribute_slots(); + } + } + } + } + + if (total_image_units > ctx->Const.MaxCombinedImageUniforms) + linker_error(prog, "Too many combined image uniforms"); + + if (total_image_units + fragment_outputs > + ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs) + linker_error(prog, "Too many combined image uniforms and fragment outputs"); +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -2394,17 +2452,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) store_fragdepth_layout(prog); check_resources(ctx, prog); + check_image_resources(ctx, prog); link_check_atomic_counter_resources(ctx, prog); if (!prog->LinkStatus) goto done; /* OpenGL ES requires that a vertex shader and a fragment shader both be - * present in a linked program. By checking prog->IsES, we also - * catch the GL_ARB_ES2_compatibility case. + * present in a linked program. GL_ARB_ES2_compatibility doesn't say + * anything about shader linking when one of the shaders (vertex or + * fragment shader) is absent. So, the extension shouldn't change the + * behavior specified in GLSL specification. */ - if (!prog->InternalSeparateShader && - (ctx->API == API_OPENGLES2 || prog->IsES)) { + if (!prog->InternalSeparateShader && ctx->API == API_OPENGLES2) { if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { linker_error(prog, "program lacks a vertex shader\n"); } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index 44a6e8021..01ea0f01f 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -38,7 +38,6 @@ * - LOG_TO_LOG2 * - MOD_TO_FRACT * - LDEXP_TO_ARITH - * - LRP_TO_ARITH * - BITFIELD_INSERT_TO_BFM_BFI * * SUB_TO_ADD_NEG: @@ -87,10 +86,6 @@ * ------------- * Converts ir_binop_ldexp to arithmetic and bit operations. * - * LRP_TO_ARITH: - * ------------- - * Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2). - * * BITFIELD_INSERT_TO_BFM_BFI: * --------------------------- * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and @@ -130,7 +125,6 @@ private: void exp_to_exp2(ir_expression *); void pow_to_exp2(ir_expression *); void log_to_log2(ir_expression *); - void lrp_to_arith(ir_expression *); void bitfield_insert_to_bfm_bfi(ir_expression *); void ldexp_to_arith(ir_expression *); }; @@ -299,27 +293,6 @@ lower_instructions_visitor::mod_to_fract(ir_expression *ir) } void -lower_instructions_visitor::lrp_to_arith(ir_expression *ir) -{ - /* (lrp x y a) -> x*(1-a) + y*a */ - - /* Save op2 */ - ir_variable *temp = new(ir) ir_variable(ir->operands[2]->type, "lrp_factor", - ir_var_temporary); - this->base_ir->insert_before(temp); - this->base_ir->insert_before(assign(temp, ir->operands[2])); - - ir_constant *one = new(ir) ir_constant(1.0f); - - ir->operation = ir_binop_add; - ir->operands[0] = mul(ir->operands[0], sub(one, temp)); - ir->operands[1] = mul(ir->operands[1], temp); - ir->operands[2] = NULL; - - this->progress = true; -} - -void lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir) { /* Translates @@ -499,11 +472,6 @@ lower_instructions_visitor::visit_leave(ir_expression *ir) pow_to_exp2(ir); break; - case ir_triop_lrp: - if (lowering(LRP_TO_ARITH)) - lrp_to_arith(ir); - break; - case ir_quadop_bitfield_insert: if (lowering(BITFIELD_INSERT_TO_BFM_BFI)) bitfield_insert_to_bfm_bfi(ir); diff --git a/mesalib/src/glsl/lower_offset_array.cpp b/mesalib/src/glsl/lower_offset_array.cpp new file mode 100644 index 000000000..0c235eda3 --- /dev/null +++ b/mesalib/src/glsl/lower_offset_array.cpp @@ -0,0 +1,90 @@ +/* + * Copyright © 2013 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 brw_lower_offset_array.cpp + * + * IR lower pass to decompose ir_texture ir_tg4 with an array of offsets + * into four ir_tg4s with a single ivec2 offset, select the .w component of each, + * and return those four values packed into a gvec4. + * + * \author Chris Forbes <chrisf@ijw.co.nz> + */ + +#include "glsl_types.h" +#include "ir.h" +#include "ir_builder.h" +#include "ir_optimization.h" +#include "ir_rvalue_visitor.h" + +using namespace ir_builder; + +class brw_lower_offset_array_visitor : public ir_rvalue_visitor { +public: + brw_lower_offset_array_visitor() + { + progress = false; + } + + void handle_rvalue(ir_rvalue **rv); + + bool progress; +}; + +void +brw_lower_offset_array_visitor::handle_rvalue(ir_rvalue **rv) +{ + if (*rv == NULL || (*rv)->ir_type != ir_type_texture) + return; + + ir_texture *ir = (ir_texture *) *rv; + if (ir->op != ir_tg4 || !ir->offset || !ir->offset->type->is_array()) + return; + + void *mem_ctx = ralloc_parent(ir); + + ir_variable *var = new (mem_ctx) ir_variable(ir->type, "result", ir_var_auto); + base_ir->insert_before(var); + + for (int i = 0; i < 4; i++) { + ir_texture *tex = ir->clone(mem_ctx, NULL); + tex->offset = new (mem_ctx) ir_dereference_array(tex->offset, + new (mem_ctx) ir_constant(i)); + + base_ir->insert_before(assign(var, swizzle_w(tex), 1 << i)); + } + + *rv = new (mem_ctx) ir_dereference_variable(var); + + progress = true; +} + +bool +lower_offset_arrays(exec_list *instructions) +{ + brw_lower_offset_array_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index 3a0f812f2..4ae8f0987 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -294,7 +294,7 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader) /* Print out the resulting IR */ if (!state->error && dump_lir) { - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); } return; diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 1b4d31936..5c49a785c 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -568,6 +568,12 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) return ir->operands[1]; } else if (ir->operands[0]->equals(ir->operands[1])) { return ir->operands[0]; + } else if (is_vec_zero(op_const[0])) { + return mul(ir->operands[1], ir->operands[2]); + } else if (is_vec_zero(op_const[1])) { + unsigned op2_components = ir->operands[2]->type->vector_elements; + ir_constant *one = new(mem_ctx) ir_constant(1.0f, op2_components); + return mul(ir->operands[0], add(one, neg(ir->operands[2]))); } break; diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp index f37d09022..97d3a57e9 100644 --- a/mesalib/src/glsl/opt_array_splitting.cpp +++ b/mesalib/src/glsl/opt_array_splitting.cpp @@ -400,7 +400,7 @@ optimize_split_arrays(exec_list *instructions, bool linked) visit_list_elements(&split, instructions); if (debug) - _mesa_print_ir(instructions, NULL); + _mesa_print_ir(stdout, instructions, NULL); ralloc_free(mem_ctx); diff --git a/mesalib/src/glsl/opt_vectorize.cpp b/mesalib/src/glsl/opt_vectorize.cpp index 8ee81f1a3..13faac05e 100644 --- a/mesalib/src/glsl/opt_vectorize.cpp +++ b/mesalib/src/glsl/opt_vectorize.cpp @@ -82,6 +82,8 @@ public: virtual ir_visitor_status visit_enter(ir_assignment *); virtual ir_visitor_status visit_enter(ir_swizzle *); + virtual ir_visitor_status visit_enter(ir_dereference_array *); + virtual ir_visitor_status visit_enter(ir_expression *); virtual ir_visitor_status visit_enter(ir_if *); virtual ir_visitor_status visit_enter(ir_loop *); @@ -289,6 +291,33 @@ ir_vectorize_visitor::visit_enter(ir_swizzle *ir) return visit_continue; } +/* Upon entering an ir_array_dereference, remove the current assignment from + * further consideration. Since the index of an array dereference must scalar, + * we are not able to vectorize it. + * + * FINISHME: If all of scalar indices are identical we could vectorize. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_dereference_array *ir) +{ + this->current_assignment = NULL; + return visit_continue_with_parent; +} + +/** + * Upon entering an ir_expression, remove the current assignment from further + * consideration if the expression operates horizontally on vectors. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_expression *ir) +{ + if (ir->is_horizontal()) { + this->current_assignment = NULL; + return visit_continue_with_parent; + } + return visit_continue; +} + /* Since there is no statement to visit between the "then" and "else" * instructions try to vectorize before, in between, and after them to avoid * combining statements from different basic blocks. diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp index 1a15f3c63..f1b9579cd 100644 --- a/mesalib/src/glsl/test_optpass.cpp +++ b/mesalib/src/glsl/test_optpass.cpp @@ -235,7 +235,7 @@ int test_optpass(int argc, char **argv) /* Print out the initial IR */ if (!state->error && !quiet) { printf("*** pre-optimization IR:\n"); - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); printf("\n--\n"); } @@ -255,7 +255,7 @@ int test_optpass(int argc, char **argv) if (!quiet) { printf("*** resulting IR:\n"); } - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); if (!quiet) { printf("\n--\n"); } |