diff options
author | marha <marha@users.sourceforge.net> | 2014-03-04 08:57:07 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2014-03-04 08:57:07 +0100 |
commit | 321c01267ae1c446f1bd22b642567fcafa016c02 (patch) | |
tree | 69f6e12bdfd1ccda5d054398321bc1876dd3fc89 /mesalib/src/glsl | |
parent | 982ac918afe6a1c02d5cf735d7b6c56443a048cc (diff) | |
download | vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.tar.gz vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.tar.bz2 vcxsrv-321c01267ae1c446f1bd22b642567fcafa016c02.zip |
libX11 libxcb mesa xserver xcb-proto xkeyboard-config git update 4 Mar 2014
xserver commit b634e909895f6001e7d9543e1350b20c82c8c01c
libxcb commit 4ffa6f83b92763eb901c7ddb7c20775e24d507ca
libxcb/xcb-proto commit 4270141a7cb3c68f50251be19a5a628aa18553e6
xkeyboard-config commit d9e3d0ec1a48a5f61ea6dd6d20b8682eeecf3a39
libX11 commit d6bd988bc00494914b38b95ee5df77ac4f32f19f
libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854
libXext commit d5447c0156f556114dbf97d6064c0c7b0fcd5f70
libfontenc commit 0037a42107b952c9d903719615747e760e4e7247
libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909
libXau commit 1e4635be11154dd8262f37b379511bd627defa2a
xkbcomp commit 31b90ee4ffc774e0da540277907fc5540c0b012c
pixman commit 82d094654a46bd97d47f1f132a01ae0a74b986f3
xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7
randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6
glproto commit f84853d97d5749308992412a215fa518b6536eb3
mkfontscale commit eac564e0fc9052a39981ea47b271f7f3d2821944
xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13
libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4
libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63
libxtrans commit 3f0de269abe59353acbd7a5587d68ce0da91db67
fontconfig commit e310d2fac2d874d5aa76c609df70cc7b871c0b6d
mesa commit 1a568e0f2b65e4e1e1d19a6dece3a792a33da825
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"); } |