X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fast_to_hir.cpp;h=5157661b39eca7c6e15bc58a3157026ed1bfd618;hb=2acc7193743199701f8f6d1877a59ece0ec4fa5b;hp=8c739653fbe02fef996d99c52f2c58b84dadd276;hpb=f7561e8ecd80e915150ca63c0c79a5f9839c8e12;p=mesa.git diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 8c739653fbe..5157661b39e 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -2086,9 +2086,24 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } else { var->location = qual->location; } + if (qual->flags.q.explicit_index) { - var->explicit_index = true; - var->index = qual->index; + /* From the GLSL 4.30 specification, section 4.4.2 (Output + * Layout Qualifiers): + * + * "It is also a compile-time error if a fragment shader + * sets a layout index to less than 0 or greater than 1." + * + * 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) { + _mesa_glsl_error(loc, state, + "explicit index may only be 0 or 1\n"); + } else { + var->explicit_index = true; + var->index = qual->index; + } } } } else if (qual->flags.q.explicit_index) { @@ -3994,6 +4009,25 @@ ast_struct_specifier::hir(exec_list *instructions, return NULL; } +static struct gl_uniform_block * +get_next_uniform_block(struct _mesa_glsl_parse_state *state) +{ + if (state->num_uniform_blocks >= state->uniform_block_array_size) { + state->uniform_block_array_size *= 2; + if (state->uniform_block_array_size <= 4) + state->uniform_block_array_size = 4; + + state->uniform_blocks = reralloc(state, + state->uniform_blocks, + struct gl_uniform_block, + state->uniform_block_array_size); + } + + memset(&state->uniform_blocks[state->num_uniform_blocks], + 0, sizeof(*state->uniform_blocks)); + return &state->uniform_blocks[state->num_uniform_blocks++]; +} + ir_rvalue * ast_uniform_block::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -4002,11 +4036,63 @@ ast_uniform_block::hir(exec_list *instructions, * need to turn those into ir_variables with an association * with this uniform block. */ + struct gl_uniform_block *ubo = get_next_uniform_block(state); + ubo->Name = ralloc_strdup(state->uniform_blocks, this->block_name); + + unsigned int num_variables = 0; + foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { + foreach_list_const(node, &decl_list->declarations) { + num_variables++; + } + } + + bool block_row_major = this->layout.flags.q.row_major; + + ubo->Uniforms = rzalloc_array(state->uniform_blocks, + struct gl_uniform_buffer_variable, + num_variables); + foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { exec_list declared_variables; decl_list->hir(&declared_variables, state); + foreach_list_const(node, &declared_variables) { + struct ir_variable *var = (ir_variable *)node; + + struct gl_uniform_buffer_variable *ubo_var = + &ubo->Uniforms[ubo->NumUniforms++]; + + var->uniform_block = ubo - state->uniform_blocks; + + ubo_var->Name = ralloc_strdup(state->uniform_blocks, var->name); + ubo_var->Type = var->type; + ubo_var->Buffer = ubo - state->uniform_blocks; + ubo_var->Offset = 0; /* Assigned at link time. */ + + if (var->type->is_matrix() || + (var->type->is_array() && var->type->fields.array->is_matrix())) { + ubo_var->RowMajor = block_row_major; + if (decl_list->type->qualifier.flags.q.row_major) + ubo_var->RowMajor = true; + else if (decl_list->type->qualifier.flags.q.column_major) + ubo_var->RowMajor = false; + } + + /* From the GL_ARB_uniform_buffer_object 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." + */ + if (var->type->contains_sampler()) { + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "Uniform in non-default uniform block contains sampler\n"); + } + } + instructions->append_list(&declared_variables); }