From: Timothy Arceri <timothy.arc...@collabora.com> This patch replaces the old interger constant qualifiers with either the new ast_layout_expression type if the qualifier requires merging or ast_expression if the qualifier can't have mulitple declorations or if all but he newest qualifier is simply ignored.
This also remove the location field that was temporarily added to ast_type_qualifier to keep track of the parser location. --- src/glsl/ast.h | 33 +++--- src/glsl/ast_to_hir.cpp | 253 +++++++++++++++++++++++++--------------- src/glsl/ast_type.cpp | 81 +++++-------- src/glsl/glsl_parser.yy | 25 ++-- src/glsl/glsl_parser_extras.cpp | 43 ++++--- 5 files changed, 236 insertions(+), 199 deletions(-) diff --git a/src/glsl/ast.h b/src/glsl/ast.h index ef94cff..4fd049c 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -573,13 +573,11 @@ struct ast_type_qualifier { uint64_t i; } flags; - struct YYLTYPE *loc; - /** Precision of the type (highp/medium/lowp). */ unsigned precision:2; /** Geometry shader invocations for GL_ARB_gpu_shader5. */ - int invocations; + ast_layout_expression *invocations; /** * Location specified via GL_ARB_explicit_attrib_location layout @@ -587,20 +585,20 @@ struct ast_type_qualifier { * \note * This field is only valid if \c explicit_location is set. */ - int location; + ast_expression *location; /** * Index specified via GL_ARB_explicit_attrib_location layout * * \note * This field is only valid if \c explicit_index is set. */ - int index; + ast_expression *index; /** Maximum output vertices in GLSL 1.50 geometry shaders. */ - int max_vertices; + ast_layout_expression *max_vertices; /** Stream in GLSL 1.50 geometry shaders. */ - unsigned stream; + ast_expression *stream; /** * Input or output primitive type in GLSL 1.50 geometry shaders @@ -614,7 +612,7 @@ struct ast_type_qualifier { * \note * This field is only valid if \c explicit_binding is set. */ - int binding; + ast_expression *binding; /** * Offset specified via GL_ARB_shader_atomic_counter's "offset" @@ -623,14 +621,14 @@ struct ast_type_qualifier { * \note * This field is only valid if \c explicit_offset is set. */ - int offset; + ast_expression *offset; /** * Local size specified via GL_ARB_compute_shader's "local_size_{x,y,z}" * layout qualifier. Element i of this array is only valid if * flags.q.local_size & (1 << i) is set. */ - int local_size[3]; + ast_layout_expression *local_size[3]; /** Tessellation evaluation shader: vertex spacing (equal, fractional even/odd) */ GLenum vertex_spacing; @@ -642,7 +640,7 @@ struct ast_type_qualifier { bool point_mode; /** Tessellation control shader: number of output vertices */ - int vertices; + ast_layout_expression *vertices; /** * Image format specified with an ARB_shader_image_load_store @@ -1114,17 +1112,13 @@ public: class ast_tcs_output_layout : public ast_node { public: - ast_tcs_output_layout(const struct YYLTYPE &locp, int vertices) - : vertices(vertices) + ast_tcs_output_layout(const struct YYLTYPE &locp) { set_location(locp); } virtual ir_rvalue *hir(exec_list *instructions, struct _mesa_glsl_parse_state *state); - -private: - const int vertices; }; @@ -1156,9 +1150,10 @@ private: class ast_cs_input_layout : public ast_node { public: - ast_cs_input_layout(const struct YYLTYPE &locp, const unsigned *local_size) + ast_cs_input_layout(const struct YYLTYPE &locp, + ast_layout_expression **local_size) { - memcpy(this->local_size, local_size, sizeof(this->local_size)); + memcpy(this->local_size, *local_size, sizeof(this->local_size)); set_location(locp); } @@ -1166,7 +1161,7 @@ public: struct _mesa_glsl_parse_state *state); private: - unsigned local_size[3]; + ast_layout_expression *local_size[3]; }; /*@}*/ diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index fcf7566..d55a99e 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -2319,7 +2319,8 @@ static bool validate_binding_qualifier(struct _mesa_glsl_parse_state *state, YYLTYPE *loc, const glsl_type *type, - const ast_type_qualifier *qual) + const ast_type_qualifier *qual, + unsigned qual_binding) { if (!qual->flags.q.uniform && !qual->flags.q.buffer) { _mesa_glsl_error(loc, state, @@ -2328,14 +2329,9 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, return false; } - if (qual->binding < 0) { - _mesa_glsl_error(loc, state, "binding values must be >= 0"); - return false; - } - const struct gl_context *const ctx = state->ctx; unsigned elements = type->is_array() ? type->arrays_of_arrays_size() : 1; - unsigned max_index = qual->binding + elements - 1; + unsigned max_index = qual_binding + elements - 1; const glsl_type *base_type = type->without_array(); if (base_type->is_interface()) { @@ -2351,9 +2347,9 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, */ if (qual->flags.q.uniform && max_index >= ctx->Const.MaxUniformBufferBindings) { - _mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds " + _mesa_glsl_error(loc, state, "layout(binding = %u) for %d UBOs exceeds " "the maximum number of UBO binding points (%d)", - qual->binding, elements, + qual_binding, elements, ctx->Const.MaxUniformBufferBindings); return false; } @@ -2369,9 +2365,9 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, */ if (qual->flags.q.buffer && max_index >= ctx->Const.MaxShaderStorageBufferBindings) { - _mesa_glsl_error(loc, state, "layout(binding = %d) for %d SSBOs exceeds " + _mesa_glsl_error(loc, state, "layout(binding = %u) for %d SSBOs exceeds " "the maximum number of SSBO binding points (%d)", - qual->binding, elements, + qual_binding, elements, ctx->Const.MaxShaderStorageBufferBindings); return false; } @@ -2386,18 +2382,18 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, unsigned limit = ctx->Const.MaxCombinedTextureImageUnits; if (max_index >= limit) { - _mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers " + _mesa_glsl_error(loc, state, "layout(binding = %u) for %d samplers " "exceeds the maximum number of texture image units " - "(%d)", qual->binding, elements, limit); + "(%d)", qual_binding, elements, limit); return false; } } else if (base_type->contains_atomic()) { assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS); - if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) { + if (qual_binding >= ctx->Const.MaxAtomicBufferBindings) { _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the " " maximum number of atomic counter buffer bindings" - "(%d)", qual->binding, + "(%u)", qual_binding, ctx->Const.MaxAtomicBufferBindings); return false; @@ -2467,11 +2463,11 @@ validate_explicit_location(const struct ast_type_qualifier *qual, YYLTYPE *loc) { bool fail = false; + unsigned qual_location; - if (qual->location < 0) { - _mesa_glsl_error(loc, state, "invalid location %d specified", - qual->location); - return; + if (!process_qualifier_constant(state, loc, "location", + qual->location, &qual_location, 0)) { + return; } /* Checks for GL_ARB_explicit_uniform_location. */ @@ -2480,7 +2476,7 @@ validate_explicit_location(const struct ast_type_qualifier *qual, return; const struct gl_context *const ctx = state->ctx; - unsigned max_loc = qual->location + var->type->uniform_locations() - 1; + unsigned max_loc = qual_location + var->type->uniform_locations() - 1; if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) { _mesa_glsl_error(loc, state, "location(s) consumed by uniform %s " @@ -2490,7 +2486,7 @@ validate_explicit_location(const struct ast_type_qualifier *qual, } var->data.explicit_location = true; - var->data.location = qual->location; + var->data.location = qual_location; return; } @@ -2575,23 +2571,23 @@ validate_explicit_location(const struct ast_type_qualifier *qual, 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); + ? (qual_location + VERT_ATTRIB_GENERIC0) + : (qual_location + VARYING_SLOT_VAR0); break; case MESA_SHADER_TESS_CTRL: case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: if (var->data.patch) - var->data.location = qual->location + VARYING_SLOT_PATCH0; + var->data.location = qual_location + VARYING_SLOT_PATCH0; else - var->data.location = qual->location + VARYING_SLOT_VAR0; + 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); + ? (qual_location + FRAG_RESULT_DATA0) + : (qual_location + VARYING_SLOT_VAR0); break; case MESA_SHADER_COMPUTE: assert(!"Unexpected shader type"); @@ -2620,22 +2616,30 @@ validate_layout_qualifiers(const struct ast_type_qualifier *qual, * Older specifications don't mandate a behavior; we take * this as a clarification and always generate the error. */ - if (qual->index < 0 || qual->index > 1) { + unsigned qual_index; + if (process_qualifier_constant(state, loc, "index", + qual->index, &qual_index, 0) && + qual_index > 1) { _mesa_glsl_error(loc, state, "explicit index may only be 0 or 1"); } else { var->data.explicit_index = true; - var->data.index = qual->index; + var->data.index = qual_index; } } } else if (qual->flags.q.explicit_index) { _mesa_glsl_error(loc, state, "explicit index requires explicit location"); } - if (qual->flags.q.explicit_binding && - validate_binding_qualifier(state, loc, var->type, qual)) { - var->data.explicit_binding = true; - var->data.binding = qual->binding; + if (qual->flags.q.explicit_binding) { + unsigned qual_binding; + if (process_qualifier_constant(state, loc, "binding", + qual->binding, &qual_binding, 0) && + validate_binding_qualifier(state, loc, var->type, qual, + qual_binding)) { + var->data.explicit_binding = true; + var->data.binding = qual_binding; + } } if (var->type->contains_atomic()) { @@ -2839,7 +2843,12 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (state->stage == MESA_SHADER_GEOMETRY && qual->flags.q.out && qual->flags.q.stream) { - var->data.stream = qual->stream; + unsigned qual_stream; + if (process_qualifier_constant(state, loc, "stream", qual->stream, + &qual_stream, 0)) { + validate_stream_qualifier(loc, state, qual_stream); + var->data.stream = qual_stream; + } } if (qual->flags.q.patch) @@ -3598,15 +3607,16 @@ static void handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state, YYLTYPE loc, ir_variable *var) { - int num_vertices = 0; + unsigned num_vertices = 0; if (state->tcs_output_vertices_specified) { - num_vertices = state->out_qualifier->vertices; - if (num_vertices <= 0) { - _mesa_glsl_error(&loc, state, "invalid vertices (%d) specified", - num_vertices); + if (!state->out_qualifier->vertices-> + process_qualifier_constant(state, "vertices", + &num_vertices, 0)) { return; - } else if ((unsigned) num_vertices > state->Const.MaxPatchVertices) { + } + + if (num_vertices > state->Const.MaxPatchVertices) { _mesa_glsl_error(&loc, state, "vertices (%d) exceeds " "GL_MAX_PATCH_VERTICES", num_vertices); return; @@ -3624,8 +3634,7 @@ handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state, if (var->data.patch) return; - validate_layout_qualifier_vertex_count(state, loc, var, - (unsigned) num_vertices, + validate_layout_qualifier_vertex_count(state, loc, var, num_vertices, &state->tcs_output_size, "tessellation control shader output"); } @@ -3881,9 +3890,19 @@ ast_declarator_list::hir(exec_list *instructions, */ if (decl_type && decl_type->contains_atomic()) { if (type->qualifier.flags.q.explicit_binding && - type->qualifier.flags.q.explicit_offset) - state->atomic_counter_offsets[type->qualifier.binding] = - type->qualifier.offset; + type->qualifier.flags.q.explicit_offset) { + unsigned qual_binding; + if (process_qualifier_constant(state, &loc, "binding", + type->qualifier.binding, + &qual_binding, 0)) { + unsigned qual_offset; + if (process_qualifier_constant(state, &loc, "offset", + type->qualifier.offset, + &qual_offset, 0)) { + state->atomic_counter_offsets[qual_binding] = qual_offset; + } + } + } } if (this->declarations.is_empty()) { @@ -5917,7 +5936,8 @@ ast_process_structure_or_interface_block(exec_list *instructions, enum glsl_matrix_layout matrix_layout, bool allow_reserved_names, ir_variable_mode var_mode, - ast_type_qualifier *layout) + ast_type_qualifier *layout, + unsigned *block_stream) { unsigned decl_count = 0; @@ -5929,6 +5949,15 @@ ast_process_structure_or_interface_block(exec_list *instructions, "Interface block sets both readonly and writeonly"); } + bool block_stream_processed = false; + if (layout) { + if (process_qualifier_constant(state, &loc, "stream", layout->stream, + block_stream, 0)) { + block_stream_processed = true; + validate_stream_qualifier(&loc, state, *block_stream); + } + } + /* Make an initial pass over the list of fields to determine how * many there are. Each element in this list is an ast_declarator_list. * This means that we actually need to count the number of elements in the @@ -6011,8 +6040,12 @@ ast_process_structure_or_interface_block(exec_list *instructions, const struct ast_type_qualifier *const qual = & decl_list->type->qualifier; - if (qual->flags.q.explicit_binding) - validate_binding_qualifier(state, &loc, decl_type, qual); + unsigned qual_binding; + if (qual->flags.q.explicit_binding && + process_qualifier_constant(state, &loc, "binding", + qual->binding, &qual_binding, 0)) + validate_binding_qualifier(state, &loc, decl_type, + qual, qual_binding); if (qual->flags.q.std140 || qual->flags.q.std430 || @@ -6050,12 +6083,17 @@ ast_process_structure_or_interface_block(exec_list *instructions, * the specified stream must match the stream associated with the * containing block." */ - if (qual->flags.q.explicit_stream && - qual->stream != layout->stream) { - _mesa_glsl_error(&loc, state, "stream layout qualifier on " - "interface block member `%s' does not match " - "the interface block (%d vs %d)", - fields[i].name, qual->stream, layout->stream); + if (qual->flags.q.explicit_stream && block_stream_processed) { + unsigned qual_stream; + if (process_qualifier_constant(state, &loc, "stream", + qual->stream, &qual_stream, 0)) { + if (qual_stream != *block_stream) { + _mesa_glsl_error(&loc, state, "stream layout qualifier on " + "interface block member `%s' does not " + "match the interface block (%d vs %d)", + fields[i].name, qual_stream, *block_stream); + } + } } if (qual->flags.q.row_major || qual->flags.q.column_major) { @@ -6198,6 +6236,7 @@ ast_struct_specifier::hir(exec_list *instructions, GLSL_MATRIX_LAYOUT_INHERITED, false /* allow_reserved_names */, ir_var_auto, + NULL, NULL); validate_identifier(this->name, loc, state); @@ -6344,6 +6383,7 @@ ast_interface_block::hir(exec_list *instructions, */ state->struct_specifier_depth++; + unsigned qual_stream; unsigned int num_variables = ast_process_structure_or_interface_block(&declared_variables, state, @@ -6354,7 +6394,8 @@ ast_interface_block::hir(exec_list *instructions, matrix_layout, redeclaring_per_vertex, var_mode, - &this->layout); + &this->layout, + &qual_stream); state->struct_specifier_depth--; @@ -6494,8 +6535,12 @@ ast_interface_block::hir(exec_list *instructions, num_variables, packing, this->block_name); - if (this->layout.flags.q.explicit_binding) - validate_binding_qualifier(state, &loc, block_type, &this->layout); + unsigned qual_binding; + if (this->layout.flags.q.explicit_binding && + process_qualifier_constant(state, &loc, "binding", this->layout.binding, + &qual_binding, 0)) + validate_binding_qualifier(state, &loc, block_type, + &this->layout, qual_binding); if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) { YYLTYPE loc = this->get_location(); @@ -6626,9 +6671,13 @@ ast_interface_block::hir(exec_list *instructions, "not allowed"); } - if (this->layout.flags.q.explicit_binding) + unsigned qual_binding; + if (this->layout.flags.q.explicit_binding && + process_qualifier_constant(state, &loc, "binding", + this->layout.binding, &qual_binding, + 0)) validate_binding_qualifier(state, &loc, block_array_type, - &this->layout); + &this->layout, qual_binding); var = new(state) ir_variable(block_array_type, this->instance_name, @@ -6696,9 +6745,15 @@ ast_interface_block::hir(exec_list *instructions, * has an instance name. This is ugly. */ var->data.explicit_binding = this->layout.flags.q.explicit_binding; - var->data.binding = this->layout.binding; + unsigned qual_binding; + if (this->layout.flags.q.explicit_binding && + process_qualifier_constant(state, &loc, "binding", + this->layout.binding, + &qual_binding, 0)) { + var->data.binding = qual_binding; + } - var->data.stream = this->layout.stream; + var->data.stream = qual_stream; state->symbols->add_variable(var); instructions->push_tail(var); @@ -6718,7 +6773,7 @@ ast_interface_block::hir(exec_list *instructions, var->data.centroid = fields[i].centroid; var->data.sample = fields[i].sample; var->data.patch = fields[i].patch; - var->data.stream = this->layout.stream; + var->data.stream = qual_stream; var->init_interface_type(block_type); if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) @@ -6769,7 +6824,13 @@ ast_interface_block::hir(exec_list *instructions, * has an instance name. This is ugly. */ var->data.explicit_binding = this->layout.flags.q.explicit_binding; - var->data.binding = this->layout.binding; + unsigned qual_binding; + if (this->layout.flags.q.explicit_binding && + process_qualifier_constant(state, &loc, "binding", + this->layout.binding, + &qual_binding, 0)) { + var->data.binding = qual_binding; + } if (var->type->is_unsized_array()) { if (var->is_in_shader_storage_block()) { @@ -6851,14 +6912,10 @@ ast_tcs_output_layout::hir(exec_list *instructions, { YYLTYPE loc = this->get_location(); - /* If any tessellation control output layout declaration preceded this - * one, make sure it was consistent with this one. - */ - if (state->tcs_output_vertices_specified && - state->out_qualifier->vertices != this->vertices) { - _mesa_glsl_error(&loc, state, - "tessellation control shader output layout does not " - "match previous declaration"); + unsigned num_vertices; + if (!state->out_qualifier->vertices-> + process_qualifier_constant(state, "vertices", &num_vertices, 1)) { + /* return here to stop cascading incorrect error messages */ return NULL; } @@ -6866,8 +6923,8 @@ ast_tcs_output_layout::hir(exec_list *instructions, * array size, make sure the size they specified is consistent with the * primitive type. */ - unsigned num_vertices = this->vertices; - if (state->tcs_output_size != 0 && state->tcs_output_size != num_vertices) { + if (state->tcs_output_size != 0 && + state->tcs_output_size != num_vertices) { _mesa_glsl_error(&loc, state, "this tessellation control shader output layout " "specifies %u vertices, but a previous output " @@ -6893,7 +6950,7 @@ ast_tcs_output_layout::hir(exec_list *instructions, if (var->data.max_array_access >= num_vertices) { _mesa_glsl_error(&loc, state, "this tessellation control shader output layout " - "specifies %u vertices, but an access to element " + "specifies %d vertices, but an access to element " "%u of output `%s' already exists", num_vertices, var->data.max_array_access, var->name); } else { @@ -6974,20 +7031,6 @@ ast_cs_input_layout::hir(exec_list *instructions, { YYLTYPE loc = this->get_location(); - /* If any compute input layout declaration preceded this one, make sure it - * was consistent with this one. - */ - if (state->cs_input_local_size_specified) { - for (int i = 0; i < 3; i++) { - if (state->cs_input_local_size[i] != this->local_size[i]) { - _mesa_glsl_error(&loc, state, - "compute shader input layout does not match" - " previous declaration"); - return NULL; - } - } - } - /* From the ARB_compute_shader specification: * * If the local size of the shader in any dimension is greater @@ -7000,22 +7043,26 @@ ast_cs_input_layout::hir(exec_list *instructions, * report it at compile time as well. */ GLuint64 total_invocations = 1; + unsigned qual_local_size[3]; for (int i = 0; i < 3; i++) { - if (this->local_size[i] <= 0) { - _mesa_glsl_error(state->in_qualifier->loc, state, - "invalid local_size_%c of %d specified", - 'x' + i, this->local_size[i]); + char *local_size_str = ralloc_asprintf(NULL, "invalid local_size_%c", + 'x' + i); + if (!this->local_size[i]-> + process_qualifier_constant(state, local_size_str, + &qual_local_size[i], 1)) { + ralloc_free(local_size_str); break; } + ralloc_free(local_size_str); - if (this->local_size[i] > state->ctx->Const.MaxComputeWorkGroupSize[i]) { + if (qual_local_size[i] > state->ctx->Const.MaxComputeWorkGroupSize[i]) { _mesa_glsl_error(&loc, state, "local_size_%c exceeds MAX_COMPUTE_WORK_GROUP_SIZE" " (%d)", 'x' + i, state->ctx->Const.MaxComputeWorkGroupSize[i]); break; } - total_invocations *= this->local_size[i]; + total_invocations *= qual_local_size[i]; if (total_invocations > state->ctx->Const.MaxComputeWorkGroupInvocations) { _mesa_glsl_error(&loc, state, @@ -7026,9 +7073,23 @@ ast_cs_input_layout::hir(exec_list *instructions, } } + /* If any compute input layout declaration preceded this one, make sure it + * was consistent with this one. + */ + if (state->cs_input_local_size_specified) { + for (int i = 0; i < 3; i++) { + if (state->cs_input_local_size[i] != qual_local_size[i]) { + _mesa_glsl_error(&loc, state, + "compute shader input layout does not match" + " previous declaration"); + return NULL; + } + } + } + state->cs_input_local_size_specified = true; for (int i = 0; i < 3; i++) - state->cs_input_local_size[i] = this->local_size[i]; + state->cs_input_local_size[i] = qual_local_size[i]; /* We may now declare the built-in constant gl_WorkGroupSize (see * builtin_variable_generator::generate_constants() for why we didn't @@ -7043,7 +7104,7 @@ ast_cs_input_layout::hir(exec_list *instructions, ir_constant_data data; memset(&data, 0, sizeof(data)); for (int i = 0; i < 3; i++) - data.u[i] = this->local_size[i]; + data.u[i] = qual_local_size[i]; var->constant_value = new(var) ir_constant(glsl_type::uvec3_type, &data); var->constant_initializer = new(var) ir_constant(glsl_type::uvec3_type, &data); diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp index 8ceb3b1..1986ccb 100644 --- a/src/glsl/ast_type.cpp +++ b/src/glsl/ast_type.cpp @@ -168,41 +168,23 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, } if (q.flags.q.max_vertices) { - if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) { - _mesa_glsl_error(loc, state, - "geometry shader set conflicting max_vertices " - "(%d and %d)", this->max_vertices, q.max_vertices); - return false; + if (this->max_vertices) { + this->max_vertices->merge_qualifier(q.max_vertices); + } else { + this->max_vertices = q.max_vertices; } - this->max_vertices = q.max_vertices; } if (q.flags.q.invocations) { - if (this->flags.q.invocations && this->invocations != q.invocations) { - _mesa_glsl_error(loc, state, - "geometry shader set conflicting invocations " - "(%d and %d)", this->invocations, q.invocations); - return false; + if (this->invocations) { + this->invocations->merge_qualifier(q.invocations); + } else { + this->invocations = q.invocations; } - this->invocations = q.invocations; } if (state->stage == MESA_SHADER_GEOMETRY && state->has_explicit_attrib_stream()) { - if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) { - _mesa_glsl_error(loc, state, - "`stream' value is larger than MAX_VERTEX_STREAMS - 1 " - "(%d > %d)", - q.stream, state->ctx->Const.MaxVertexStreams - 1); - } - if (this->flags.q.explicit_stream && - this->stream >= state->ctx->Const.MaxVertexStreams) { - _mesa_glsl_error(loc, state, - "`stream' value is larger than MAX_VERTEX_STREAMS - 1 " - "(%d > %d)", - this->stream, state->ctx->Const.MaxVertexStreams - 1); - } - if (!this->flags.q.explicit_stream) { if (q.flags.q.stream) { this->flags.q.stream = 1; @@ -221,14 +203,11 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, } if (q.flags.q.vertices) { - if (this->flags.q.vertices && this->vertices != q.vertices) { - _mesa_glsl_error(loc, state, - "tessellation control shader set conflicting " - "vertices (%d and %d)", - this->vertices, q.vertices); - return false; + if (this->vertices) { + this->vertices->merge_qualifier(q.vertices); + } else { + this->vertices = q.vertices; } - this->vertices = q.vertices; } if (q.flags.q.vertex_spacing) { @@ -265,14 +244,6 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, for (int i = 0; i < 3; i++) { if (q.flags.q.local_size & (1 << i)) { - if ((this->flags.q.local_size & (1 << i)) && - this->local_size[i] != q.local_size[i]) { - _mesa_glsl_error(loc, state, - "compute shader set conflicting values for " - "local_size_%c (%d and %d)", 'x' + i, - this->local_size[i], q.local_size[i]); - return false; - } this->local_size[i] = q.local_size[i]; } } @@ -310,10 +281,9 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc, { void *mem_ctx = state; const bool r = this->merge_qualifier(loc, state, q); - this->loc = loc; if (state->stage == MESA_SHADER_TESS_CTRL) { - node = new(mem_ctx) ast_tcs_output_layout(*loc, q.vertices); + node = new(mem_ctx) ast_tcs_output_layout(*loc); } return r; @@ -330,7 +300,6 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, bool create_cs_ast = false; ast_type_qualifier valid_in_mask; valid_in_mask.flags.i = 0; - this->loc = loc; switch (state->stage) { case MESA_SHADER_TESS_EVAL: @@ -418,15 +387,13 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, 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) { + if (q.flags.q.invocations) { this->flags.q.invocations = 1; - this->invocations = q.invocations; + if (this->invocations) { + this->invocations->merge_qualifier(q.invocations); + } else { + this->invocations = q.invocations; + } } if (q.flags.q.early_fragment_tests) { @@ -470,12 +437,16 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, 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]; + ast_layout_expression *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; + else { + ast_expression *const_expr = new(mem_ctx) + ast_expression(ast_uint_constant, NULL, NULL, NULL); + const_expr->primary_expression.uint_constant = 1; + local_size[i]->layout_const_expressions.push_tail(&const_expr->link); + } } node = new(mem_ctx) ast_cs_input_layout(*loc, local_size); } diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 44853b0..4186022 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -297,7 +297,6 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %type <node> conditionopt %type <node> for_init_statement %type <for_rest_statement> for_rest_statement -%type <n> integer_constant %type <node> layout_defaults %right THEN ELSE @@ -1139,11 +1138,6 @@ layout_qualifier_id_list: } ; -integer_constant: - INTCONSTANT { $$ = $1; } - | UINTCONSTANT { $$ = $1; } - ; - layout_qualifier_id: any_identifier { @@ -1440,9 +1434,18 @@ layout_qualifier_id: YYERROR; } } - | any_identifier '=' integer_constant + | any_identifier '=' constant_expression { memset(& $$, 0, sizeof($$)); + void *ctx = state; + + if ($3->oper != ast_int_constant && + $3->oper != ast_uint_constant && + !state->has_enhanced_layouts()) { + _mesa_glsl_error(& @1, state, + "compile-time constant expressions require " + "GLSL 4.40 or ARB_enhanced_layouts"); + } if (match_layout_qualifier("location", $1, state) == 0) { $$.flags.q.explicit_location = 1; @@ -1477,7 +1480,7 @@ layout_qualifier_id: if (match_layout_qualifier("max_vertices", $1, state) == 0) { $$.flags.q.max_vertices = 1; - $$.max_vertices = $3; + $$.max_vertices = new(ctx) ast_layout_expression(@1, $3); if (!state->is_version(150, 0)) { _mesa_glsl_error(& @1, state, @@ -1511,7 +1514,7 @@ layout_qualifier_id: YYERROR; } else { $$.flags.q.local_size |= (1 << i); - $$.local_size[i] = $3; + $$.local_size[i] = new(ctx) ast_layout_expression(@1, $3); } break; } @@ -1519,7 +1522,7 @@ layout_qualifier_id: if (match_layout_qualifier("invocations", $1, state) == 0) { $$.flags.q.invocations = 1; - $$.invocations = $3; + $$.invocations = new(ctx) ast_layout_expression(@1, $3); if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) { _mesa_glsl_error(& @1, state, @@ -1531,7 +1534,7 @@ layout_qualifier_id: /* Layout qualifiers for tessellation control shaders. */ if (match_layout_qualifier("vertices", $1, state) == 0) { $$.flags.q.vertices = 1; - $$.vertices = $3; + $$.vertices = new(ctx) ast_layout_expression(@1, $3); if (!state->ARB_tessellation_shader_enable && !state->is_version(400, 0)) { _mesa_glsl_error(& @1, state, diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 7d7f45c..b90fc68 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -1652,8 +1652,13 @@ set_shader_inout_layout(struct gl_shader *shader, switch (shader->Stage) { case MESA_SHADER_TESS_CTRL: shader->TessCtrl.VerticesOut = 0; - if (state->tcs_output_vertices_specified) - shader->TessCtrl.VerticesOut = state->out_qualifier->vertices; + if (state->tcs_output_vertices_specified) { + unsigned vertices; + if (state->out_qualifier->vertices-> + process_qualifier_constant(state, "vertices", &vertices, 0)) { + shader->TessCtrl.VerticesOut = vertices; + } + } break; case MESA_SHADER_TESS_EVAL: shader->TessEval.PrimitiveMode = PRIM_UNKNOWN; @@ -1675,12 +1680,12 @@ set_shader_inout_layout(struct gl_shader *shader, case MESA_SHADER_GEOMETRY: shader->Geom.VerticesOut = 0; if (state->out_qualifier->flags.q.max_vertices) { - if (state->out_qualifier->max_vertices < 0) { - _mesa_glsl_error(state->out_qualifier->loc, state, - "invalid max_vertices %d specified", - state->out_qualifier->max_vertices); + unsigned qual_max_vertices; + if (state->out_qualifier->max_vertices-> + process_qualifier_constant(state, "max_vertices", + &qual_max_vertices, 0)) { + shader->Geom.VerticesOut = qual_max_vertices; } - shader->Geom.VerticesOut = state->out_qualifier->max_vertices; } if (state->gs_input_prim_type_specified) { @@ -1697,18 +1702,20 @@ set_shader_inout_layout(struct gl_shader *shader, shader->Geom.Invocations = 0; if (state->in_qualifier->flags.q.invocations) { - if (state->in_qualifier->invocations <= 0) { - _mesa_glsl_error(state->in_qualifier->loc, state, - "invalid invocations %d specified", - state->in_qualifier->invocations); - } else if (state->in_qualifier->invocations > - MAX_GEOMETRY_SHADER_INVOCATIONS) { - _mesa_glsl_error(state->in_qualifier->loc, state, - "invocations (%d) exceeds " - "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", - state->in_qualifier->invocations); + unsigned invocations; + if (state->in_qualifier->invocations-> + process_qualifier_constant(state, "invocations", + &invocations, 1)) { + + YYLTYPE loc = state->in_qualifier->invocations->get_location(); + if (invocations > MAX_GEOMETRY_SHADER_INVOCATIONS) { + _mesa_glsl_error(&loc, state, + "invocations (%d) exceeds " + "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", + invocations); + } + shader->Geom.Invocations = invocations; } - shader->Geom.Invocations = state->in_qualifier->invocations; } break; -- 2.4.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev