X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fglsl%2Flinker.cpp;h=3fde7e78d31cf1e239ee96c6e16b939ea2cea568;hb=9b5c0c520f6e41f19b3568a4e0532c836bc522e4;hp=fb26be489509a77b5d213c431a15731c42b3528a;hpb=aa38bf1e593eba3e65c4e10154410158d6d263c5;p=mesa.git diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index fb26be48950..3fde7e78d31 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -66,49 +66,59 @@ #include #include "util/strndup.h" -#include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ir.h" #include "program.h" #include "program/prog_instruction.h" #include "program/program.h" +#include "util/mesa-sha1.h" #include "util/set.h" -#include "util/string_to_uint_map.h" +#include "string_to_uint_map.h" #include "linker.h" +#include "linker_util.h" #include "link_varyings.h" #include "ir_optimization.h" #include "ir_rvalue_visitor.h" #include "ir_uniform.h" #include "builtin_functions.h" +#include "shader_cache.h" +#include "util/u_string.h" +#include "util/u_math.h" +#include "main/imports.h" #include "main/shaderobj.h" #include "main/enums.h" +#include "main/mtypes.h" namespace { +struct find_variable { + const char *name; + bool found; + + find_variable(const char *name) : name(name), found(false) {} +}; + /** * Visitor that determines whether or not a variable is ever written. + * + * Use \ref find_assignments for convenience. */ class find_assignment_visitor : public ir_hierarchical_visitor { public: - find_assignment_visitor(const char *name) - : name(name), found(false) + find_assignment_visitor(unsigned num_vars, + find_variable * const *vars) + : num_variables(num_vars), num_found(0), variables(vars) { - /* empty */ } virtual ir_visitor_status visit_enter(ir_assignment *ir) { ir_variable *const var = ir->lhs->variable_referenced(); - if (strcmp(name, var->name) == 0) { - found = true; - return visit_stop; - } - - return visit_continue_with_parent; + return check_variable_name(var->name); } virtual ir_visitor_status visit_enter(ir_call *ir) @@ -121,35 +131,71 @@ public: if (sig_param->data.mode == ir_var_function_out || sig_param->data.mode == ir_var_function_inout) { ir_variable *var = param_rval->variable_referenced(); - if (var && strcmp(name, var->name) == 0) { - found = true; + if (var && check_variable_name(var->name) == visit_stop) return visit_stop; - } } } if (ir->return_deref != NULL) { ir_variable *const var = ir->return_deref->variable_referenced(); - if (strcmp(name, var->name) == 0) { - found = true; + if (check_variable_name(var->name) == visit_stop) return visit_stop; - } } return visit_continue_with_parent; } - bool variable_found() +private: + ir_visitor_status check_variable_name(const char *name) { - return found; + for (unsigned i = 0; i < num_variables; ++i) { + if (strcmp(variables[i]->name, name) == 0) { + if (!variables[i]->found) { + variables[i]->found = true; + + assert(num_found < num_variables); + if (++num_found == num_variables) + return visit_stop; + } + break; + } + } + + return visit_continue_with_parent; } private: - const char *name; /**< Find writes to a variable with this name. */ - bool found; /**< Was a write to the variable found? */ + unsigned num_variables; /**< Number of variables to find */ + unsigned num_found; /**< Number of variables already found */ + find_variable * const *variables; /**< Variables to find */ }; +/** + * Determine whether or not any of NULL-terminated list of variables is ever + * written to. + */ +static void +find_assignments(exec_list *ir, find_variable * const *vars) +{ + unsigned num_variables = 0; + + for (find_variable * const *v = vars; *v; ++v) + num_variables++; + + find_assignment_visitor visitor(num_variables, vars); + visitor.run(ir); +} + +/** + * Determine whether or not the given variable is ever written to. + */ +static void +find_assignments(exec_list *ir, find_variable *var) +{ + find_assignment_visitor visitor(1, &var); + visitor.run(ir); +} /** * Visitor that determines whether or not a variable is ever read. @@ -206,14 +252,7 @@ public: virtual ir_visitor_status visit_leave(ir_dereference_record *ir) { - for (unsigned i = 0; i < ir->record->type->length; i++) { - const struct glsl_struct_field *field = - &ir->record->type->fields.structure[i]; - if (strcmp(field->name, ir->field) == 0) { - ir->type = field->type; - break; - } - } + ir->type = ir->record->type->fields.structure[ir->field_idx].type; return visit_continue; } }; @@ -393,7 +432,7 @@ public: if (!ir->variable_referenced()->type->contains_sampler()) return visit_continue; - if (!ir->array_index->constant_expression_value()) { + if (!ir->array_index->constant_expression_value(ralloc_parent(ir))) { dynamic_sampler_array_indexing = true; return visit_stop; } @@ -421,7 +460,7 @@ linker_error(gl_shader_program *prog, const char *fmt, ...) ralloc_vasprintf_append(&prog->data->InfoLog, fmt, ap); va_end(ap); - prog->data->LinkStatus = false; + prog->data->LinkStatus = LINKING_FAILURE; } @@ -565,11 +604,16 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, * gl_ClipVertex nor gl_ClipDistance. However with * GL_EXT_clip_cull_distance, this functionality is exposed in ES 3.0. */ - find_assignment_visitor clip_distance("gl_ClipDistance"); - find_assignment_visitor cull_distance("gl_CullDistance"); - - clip_distance.run(shader->ir); - cull_distance.run(shader->ir); + find_variable gl_ClipDistance("gl_ClipDistance"); + find_variable gl_CullDistance("gl_CullDistance"); + find_variable gl_ClipVertex("gl_ClipVertex"); + find_variable * const variables[] = { + &gl_ClipDistance, + &gl_CullDistance, + !prog->IsES ? &gl_ClipVertex : NULL, + NULL + }; + find_assignments(shader->ir, variables); /* From the ARB_cull_distance spec: * @@ -581,17 +625,13 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, * gl_ClipVertex. */ if (!prog->IsES) { - find_assignment_visitor clip_vertex("gl_ClipVertex"); - - clip_vertex.run(shader->ir); - - if (clip_vertex.variable_found() && clip_distance.variable_found()) { + if (gl_ClipVertex.found && gl_ClipDistance.found) { linker_error(prog, "%s shader writes to both `gl_ClipVertex' " "and `gl_ClipDistance'\n", _mesa_shader_stage_to_string(shader->Stage)); return; } - if (clip_vertex.variable_found() && cull_distance.variable_found()) { + if (gl_ClipVertex.found && gl_CullDistance.found) { linker_error(prog, "%s shader writes to both `gl_ClipVertex' " "and `gl_CullDistance'\n", _mesa_shader_stage_to_string(shader->Stage)); @@ -599,13 +639,13 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, } } - if (clip_distance.variable_found()) { + if (gl_ClipDistance.found) { ir_variable *clip_distance_var = shader->symbols->get_variable("gl_ClipDistance"); assert(clip_distance_var); *clip_distance_array_size = clip_distance_var->type->length; } - if (cull_distance.variable_found()) { + if (gl_CullDistance.found) { ir_variable *cull_distance_var = shader->symbols->get_variable("gl_CullDistance"); assert(cull_distance_var); @@ -634,12 +674,12 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, /** * Verify that a vertex shader executable meets all semantic requirements. * - * Also sets prog->Vert.ClipDistanceArraySize and - * prog->Vert.CullDistanceArraySize as a side effect. + * Also sets info.clip_distance_array_size and + * info.cull_distance_array_size as a side effect. * * \param shader Vertex shader executable to be verified */ -void +static void validate_vertex_shader_executable(struct gl_shader_program *prog, struct gl_linked_shader *shader, struct gl_context *ctx) @@ -674,9 +714,9 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, * gl_Position is not an error. */ if (prog->data->Version < (prog->IsES ? 300 : 140)) { - find_assignment_visitor find("gl_Position"); - find.run(shader->ir); - if (!find.variable_found()) { + find_variable gl_Position("gl_Position"); + find_assignments(shader->ir, &gl_Position); + if (!gl_Position.found) { if (prog->IsES) { linker_warning(prog, "vertex shader does not write to `gl_Position'. " @@ -690,11 +730,11 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, } analyze_clip_cull_usage(prog, shader, ctx, - &prog->Vert.ClipDistanceArraySize, - &prog->Vert.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } -void +static void validate_tess_eval_shader_executable(struct gl_shader_program *prog, struct gl_linked_shader *shader, struct gl_context *ctx) @@ -703,8 +743,8 @@ validate_tess_eval_shader_executable(struct gl_shader_program *prog, return; analyze_clip_cull_usage(prog, shader, ctx, - &prog->TessEval.ClipDistanceArraySize, - &prog->TessEval.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } @@ -713,20 +753,19 @@ validate_tess_eval_shader_executable(struct gl_shader_program *prog, * * \param shader Fragment shader executable to be verified */ -void +static void validate_fragment_shader_executable(struct gl_shader_program *prog, struct gl_linked_shader *shader) { if (shader == NULL) return; - find_assignment_visitor frag_color("gl_FragColor"); - find_assignment_visitor frag_data("gl_FragData"); + find_variable gl_FragColor("gl_FragColor"); + find_variable gl_FragData("gl_FragData"); + find_variable * const variables[] = { &gl_FragColor, &gl_FragData, NULL }; + find_assignments(shader->ir, variables); - frag_color.run(shader->ir); - frag_data.run(shader->ir); - - if (frag_color.variable_found() && frag_data.variable_found()) { + if (gl_FragColor.found && gl_FragData.found) { linker_error(prog, "fragment shader writes to both " "`gl_FragColor' and `gl_FragData'\n"); } @@ -735,12 +774,12 @@ validate_fragment_shader_executable(struct gl_shader_program *prog, /** * Verify that a geometry shader executable meets all semantic requirements * - * Also sets prog->Geom.VerticesIn, and prog->Geom.ClipDistanceArraySize and - * prog->Geom.CullDistanceArraySize as a side effect. + * Also sets prog->Geom.VerticesIn, and info.clip_distance_array_sizeand + * info.cull_distance_array_size as a side effect. * * \param shader Geometry shader executable to be verified */ -void +static void validate_geometry_shader_executable(struct gl_shader_program *prog, struct gl_linked_shader *shader, struct gl_context *ctx) @@ -748,12 +787,13 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, if (shader == NULL) return; - unsigned num_vertices = vertices_per_prim(shader->info.Geom.InputType); + unsigned num_vertices = + vertices_per_prim(shader->Program->info.gs.input_primitive); prog->Geom.VerticesIn = num_vertices; analyze_clip_cull_usage(prog, shader, ctx, - &prog->Geom.ClipDistanceArraySize, - &prog->Geom.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } /** @@ -803,7 +843,8 @@ validate_geometry_shader_emissions(struct gl_context *ctx, * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero * stream. */ - if (prog->Geom.UsesStreams && sh->info.Geom.OutputType != GL_POINTS) { + if (prog->Geom.UsesStreams && + sh->Program->info.gs.output_primitive != GL_POINTS) { linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) " "with n>0 requires point output\n"); } @@ -846,14 +887,6 @@ validate_intrastage_arrays(struct gl_shader_program *prog, } return true; } - } else { - /* The arrays of structs could have different glsl_type pointers but - * they are actually the same type. Use record_compare() to check that. - */ - if (existing->type->fields.array->is_record() && - var->type->fields.array->is_record() && - existing->type->fields.array->record_compare(var->type->fields.array)) - return true; } } return false; @@ -863,8 +896,8 @@ validate_intrastage_arrays(struct gl_shader_program *prog, /** * Perform validation of global variables used across multiple shaders */ -void -cross_validate_globals(struct gl_shader_program *prog, +static void +cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog, struct exec_list *ir, glsl_symbol_table *variables, bool uniforms_only) { @@ -881,6 +914,13 @@ cross_validate_globals(struct gl_shader_program *prog, if (var->type->contains_subroutine()) continue; + /* Don't cross validate interface instances. These are only relevant + * inside a shader. The cross validation is done at the Interface Block + * name level. + */ + if (var->is_interface_instance()) + continue; + /* Don't cross validate temporaries that are at global scope. These * will eventually get pulled into the shaders 'main'. */ @@ -893,34 +933,26 @@ cross_validate_globals(struct gl_shader_program *prog, */ ir_variable *const existing = variables->get_variable(var->name); if (existing != NULL) { - /* Check if types match. Interface blocks have some special - * rules so we handle those elsewhere. - */ - if (var->type != existing->type && - !var->is_interface_instance()) { + /* Check if types match. */ + if (var->type != existing->type) { if (!validate_intrastage_arrays(prog, var, existing)) { - if (var->type->is_record() && existing->type->is_record() - && existing->type->record_compare(var->type)) { - existing->type = var->type; - } else { - /* If it is an unsized array in a Shader Storage Block, - * two different shaders can access to different elements. - * Because of that, they might be converted to different - * sized arrays, then check that they are compatible but - * ignore the array size. - */ - if (!(var->data.mode == ir_var_shader_storage && - var->data.from_ssbo_unsized_array && - existing->data.mode == ir_var_shader_storage && - existing->data.from_ssbo_unsized_array && - var->type->gl_type == existing->type->gl_type)) { - linker_error(prog, "%s `%s' declared as type " - "`%s' and type `%s'\n", - mode_string(var), - var->name, var->type->name, - existing->type->name); - return; - } + /* If it is an unsized array in a Shader Storage Block, + * two different shaders can access to different elements. + * Because of that, they might be converted to different + * sized arrays, then check that they are compatible but + * ignore the array size. + */ + if (!(var->data.mode == ir_var_shader_storage && + var->data.from_ssbo_unsized_array && + existing->data.mode == ir_var_shader_storage && + existing->data.from_ssbo_unsized_array && + var->type->gl_type == existing->type->gl_type)) { + linker_error(prog, "%s `%s' declared as type " + "`%s' and type `%s'\n", + mode_string(var), + var->name, var->type->name, + existing->type->name); + return; } } } @@ -1083,20 +1115,52 @@ cross_validate_globals(struct gl_shader_program *prog, return; } - /* Only in GLSL ES 3.10, the precision qualifier should not match - * between block members defined in matched block names within a - * shader interface. - * - * In GLSL ES 3.00 and ES 3.20, precision qualifier for each block - * member should match. + /* Check the precision qualifier matches for uniform variables on + * GLSL ES. */ - if (prog->IsES && (prog->data->Version != 310 || - !var->get_interface_type()) && + if (!ctx->Const.AllowGLSLRelaxedES && + prog->IsES && !var->get_interface_type() && existing->data.precision != var->data.precision) { - linker_error(prog, "declarations for %s `%s` have " - "mismatching precision qualifiers\n", - mode_string(var), var->name); - return; + if ((existing->data.used && var->data.used) || prog->data->Version >= 300) { + linker_error(prog, "declarations for %s `%s` have " + "mismatching precision qualifiers\n", + mode_string(var), var->name); + return; + } else { + linker_warning(prog, "declarations for %s `%s` have " + "mismatching precision qualifiers\n", + mode_string(var), var->name); + } + } + + /* In OpenGL GLSL 3.20 spec, section 4.3.9: + * + * "It is a link-time error if any particular shader interface + * contains: + * + * - two different blocks, each having no instance name, and each + * having a member of the same name, or + * + * - a variable outside a block, and a block with no instance name, + * where the variable has the same name as a member in the block." + */ + const glsl_type *var_itype = var->get_interface_type(); + const glsl_type *existing_itype = existing->get_interface_type(); + if (var_itype != existing_itype) { + if (!var_itype || !existing_itype) { + linker_error(prog, "declarations for %s `%s` are inside block " + "`%s` and outside a block", + mode_string(var), var->name, + var_itype ? var_itype->name : existing_itype->name); + return; + } else if (strcmp(var_itype->name, existing_itype->name) != 0) { + linker_error(prog, "declarations for %s `%s` are inside blocks " + "`%s` and `%s`", + mode_string(var), var->name, + existing_itype->name, + var_itype->name); + return; + } } } else variables->add_variable(var); @@ -1107,16 +1171,17 @@ cross_validate_globals(struct gl_shader_program *prog, /** * Perform validation of uniforms used across multiple shader stages */ -void -cross_validate_uniforms(struct gl_shader_program *prog) +static void +cross_validate_uniforms(struct gl_context *ctx, + struct gl_shader_program *prog) { glsl_symbol_table variables; for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i] == NULL) continue; - cross_validate_globals(prog, prog->_LinkedShaders[i]->ir, &variables, - true); + cross_validate_globals(ctx, prog, prog->_LinkedShaders[i]->ir, + &variables, true); } } @@ -1167,8 +1232,8 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, } for (unsigned int j = 0; j < sh_num_blocks; j++) { - int index = link_cross_validate_uniform_block(prog, &blks, num_blks, - sh_blks[j]); + int index = link_cross_validate_uniform_block(prog->data, &blks, + num_blks, sh_blks[j]); if (index == -1) { linker_error(prog, "buffer block `%s' has mismatching " @@ -1177,6 +1242,12 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, for (unsigned k = 0; k <= i; k++) { delete[] InterfaceBlockStageIndex[k]; } + + /* Reset the block count. This will help avoid various segfaults + * from api calls that assume the array exists due to the count + * being non-zero. + */ + *num_blks = 0; return false; } @@ -1216,26 +1287,76 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, return true; } +/** + * Verifies the invariance of built-in special variables. + */ +static bool +validate_invariant_builtins(struct gl_shader_program *prog, + const gl_linked_shader *vert, + const gl_linked_shader *frag) +{ + const ir_variable *var_vert; + const ir_variable *var_frag; + + if (!vert || !frag) + return true; + + /* + * From OpenGL ES Shading Language 1.0 specification + * (4.6.4 Invariance and Linkage): + * "The invariance of varyings that are declared in both the vertex and + * fragment shaders must match. For the built-in special variables, + * gl_FragCoord can only be declared invariant if and only if + * gl_Position is declared invariant. Similarly gl_PointCoord can only + * be declared invariant if and only if gl_PointSize is declared + * invariant. It is an error to declare gl_FrontFacing as invariant. + * The invariance of gl_FrontFacing is the same as the invariance of + * gl_Position." + */ + var_frag = frag->symbols->get_variable("gl_FragCoord"); + if (var_frag && var_frag->data.invariant) { + var_vert = vert->symbols->get_variable("gl_Position"); + if (var_vert && !var_vert->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' has invariant qualifier, " + "but vertex shader built-in `%s' lacks invariant qualifier\n", + var_frag->name, var_vert->name); + return false; + } + } + + var_frag = frag->symbols->get_variable("gl_PointCoord"); + if (var_frag && var_frag->data.invariant) { + var_vert = vert->symbols->get_variable("gl_PointSize"); + if (var_vert && !var_vert->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' has invariant qualifier, " + "but vertex shader built-in `%s' lacks invariant qualifier\n", + var_frag->name, var_vert->name); + return false; + } + } + + var_frag = frag->symbols->get_variable("gl_FrontFacing"); + if (var_frag && var_frag->data.invariant) { + linker_error(prog, + "fragment shader built-in `%s' can not be declared as invariant\n", + var_frag->name); + return false; + } + + return true; +} /** * Populates a shaders symbol table with all global declarations */ static void -populate_symbol_table(gl_linked_shader *sh) +populate_symbol_table(gl_linked_shader *sh, glsl_symbol_table *symbols) { sh->symbols = new(sh) glsl_symbol_table; - foreach_in_list(ir_instruction, inst, sh->ir) { - ir_variable *var; - ir_function *func; - - if ((func = inst->as_function()) != NULL) { - sh->symbols->add_function(func); - } else if ((var = inst->as_variable()) != NULL) { - if (var->data.mode != ir_var_temporary) - sh->symbols->add_variable(var); - } - } + _mesa_glsl_copy_symbols_from_table(sh->ir, symbols, sh->symbols); } @@ -1258,7 +1379,7 @@ populate_symbol_table(gl_linked_shader *sh) * \param instructions Instruction stream where new variable declarations * should be added. */ -void +static void remap_variables(ir_instruction *inst, struct gl_linked_shader *target, hash_table *temps) { @@ -1332,7 +1453,7 @@ remap_variables(ir_instruction *inst, struct gl_linked_shader *target, * is suitable for use as the \c last parameter of a later call to this * function. */ -exec_node * +static exec_node * move_non_declarations(exec_list *instructions, exec_node *last, bool make_copies, gl_linked_shader *target) { @@ -1618,7 +1739,6 @@ validate_xfb_buffer_stride(struct gl_context *ctx, unsigned idx, static void link_xfb_stride_layout_qualifiers(struct gl_context *ctx, struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, struct gl_shader **shader_list, unsigned num_shaders) { @@ -1650,6 +1770,48 @@ link_xfb_stride_layout_qualifiers(struct gl_context *ctx, } } +/** + * Check for conflicting bindless/bound sampler/image layout qualifiers at + * global scope. + */ +static void +link_bindless_layout_qualifiers(struct gl_shader_program *prog, + struct gl_shader **shader_list, + unsigned num_shaders) +{ + bool bindless_sampler, bindless_image; + bool bound_sampler, bound_image; + + bindless_sampler = bindless_image = false; + bound_sampler = bound_image = false; + + for (unsigned i = 0; i < num_shaders; i++) { + struct gl_shader *shader = shader_list[i]; + + if (shader->bindless_sampler) + bindless_sampler = true; + if (shader->bindless_image) + bindless_image = true; + if (shader->bound_sampler) + bound_sampler = true; + if (shader->bound_image) + bound_image = true; + + if ((bindless_sampler && bound_sampler) || + (bindless_image && bound_image)) { + /* From section 4.4.6 of the ARB_bindless_texture spec: + * + * "If both bindless_sampler and bound_sampler, or bindless_image + * and bound_image, are declared at global scope in any + * compilation unit, a link- time error will be generated." + */ + linker_error(prog, "both bindless_sampler and bound_sampler, or " + "bindless_image and bound_image, can't be declared at " + "global scope"); + } + } +} + /** * Performs the cross-validation of tessellation control shader vertices and * layout qualifiers for the attached tessellation control shaders, @@ -1714,18 +1876,19 @@ link_tcs_out_layout_qualifiers(struct gl_shader_program *prog, */ static void link_tes_in_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.TessEval.PrimitiveMode = PRIM_UNKNOWN; - linked_shader->info.TessEval.Spacing = TESS_SPACING_UNSPECIFIED; - linked_shader->info.TessEval.VertexOrder = 0; - linked_shader->info.TessEval.PointMode = -1; - - if (linked_shader->Stage != MESA_SHADER_TESS_EVAL) + if (gl_prog->info.stage != MESA_SHADER_TESS_EVAL) return; + int point_mode = -1; + unsigned vertex_order = 0; + + gl_prog->info.tess.primitive_mode = PRIM_UNKNOWN; + gl_prog->info.tess.spacing = TESS_SPACING_UNSPECIFIED; + /* From the GLSL 4.0 spec (chapter 4.3.8.1): * * "At least one tessellation evaluation shader (compilation unit) in @@ -1744,49 +1907,45 @@ link_tes_in_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[i]; if (shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN) { - if (linked_shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN && - linked_shader->info.TessEval.PrimitiveMode != + if (gl_prog->info.tess.primitive_mode != PRIM_UNKNOWN && + gl_prog->info.tess.primitive_mode != shader->info.TessEval.PrimitiveMode) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting input primitive modes.\n"); return; } - linked_shader->info.TessEval.PrimitiveMode = shader->info.TessEval.PrimitiveMode; + gl_prog->info.tess.primitive_mode = + shader->info.TessEval.PrimitiveMode; } if (shader->info.TessEval.Spacing != 0) { - if (linked_shader->info.TessEval.Spacing != 0 && - linked_shader->info.TessEval.Spacing != + if (gl_prog->info.tess.spacing != 0 && gl_prog->info.tess.spacing != shader->info.TessEval.Spacing) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting vertex spacing.\n"); return; } - linked_shader->info.TessEval.Spacing = shader->info.TessEval.Spacing; + gl_prog->info.tess.spacing = shader->info.TessEval.Spacing; } if (shader->info.TessEval.VertexOrder != 0) { - if (linked_shader->info.TessEval.VertexOrder != 0 && - linked_shader->info.TessEval.VertexOrder != - shader->info.TessEval.VertexOrder) { + if (vertex_order != 0 && + vertex_order != shader->info.TessEval.VertexOrder) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting ordering.\n"); return; } - linked_shader->info.TessEval.VertexOrder = - shader->info.TessEval.VertexOrder; + vertex_order = shader->info.TessEval.VertexOrder; } if (shader->info.TessEval.PointMode != -1) { - if (linked_shader->info.TessEval.PointMode != -1 && - linked_shader->info.TessEval.PointMode != - shader->info.TessEval.PointMode) { + if (point_mode != -1 && + point_mode != shader->info.TessEval.PointMode) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting point modes.\n"); return; } - linked_shader->info.TessEval.PointMode = - shader->info.TessEval.PointMode; + point_mode = shader->info.TessEval.PointMode; } } @@ -1795,21 +1954,26 @@ link_tes_in_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.TessEval.PrimitiveMode == PRIM_UNKNOWN) { + if (gl_prog->info.tess.primitive_mode == PRIM_UNKNOWN) { linker_error(prog, "tessellation evaluation shader didn't declare input " "primitive modes.\n"); return; } - if (linked_shader->info.TessEval.Spacing == TESS_SPACING_UNSPECIFIED) - linked_shader->info.TessEval.Spacing = TESS_SPACING_EQUAL; + if (gl_prog->info.tess.spacing == TESS_SPACING_UNSPECIFIED) + gl_prog->info.tess.spacing = TESS_SPACING_EQUAL; + + if (vertex_order == 0 || vertex_order == GL_CCW) + gl_prog->info.tess.ccw = true; + else + gl_prog->info.tess.ccw = false; - if (linked_shader->info.TessEval.VertexOrder == 0) - linked_shader->info.TessEval.VertexOrder = GL_CCW; - if (linked_shader->info.TessEval.PointMode == -1) - linked_shader->info.TessEval.PointMode = GL_FALSE; + if (point_mode == -1 || point_mode == GL_FALSE) + gl_prog->info.tess.point_mode = false; + else + gl_prog->info.tess.point_mode = true; } @@ -1875,10 +2039,18 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, } linked_shader->Program->info.fs.early_fragment_tests |= - shader->EarlyFragmentTests; + shader->EarlyFragmentTests || shader->PostDepthCoverage; linked_shader->Program->info.fs.inner_coverage |= shader->InnerCoverage; linked_shader->Program->info.fs.post_depth_coverage |= shader->PostDepthCoverage; + linked_shader->Program->info.fs.pixel_interlock_ordered |= + shader->PixelInterlockOrdered; + linked_shader->Program->info.fs.pixel_interlock_unordered |= + shader->PixelInterlockUnordered; + linked_shader->Program->info.fs.sample_interlock_ordered |= + shader->SampleInterlockOrdered; + linked_shader->Program->info.fs.sample_interlock_unordered |= + shader->SampleInterlockUnordered; linked_shader->Program->sh.fs.BlendSupport |= shader->BlendSupport; } @@ -1891,22 +2063,23 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, */ static void link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.Geom.VerticesOut = -1; - linked_shader->info.Geom.Invocations = 0; - linked_shader->info.Geom.InputType = PRIM_UNKNOWN; - linked_shader->info.Geom.OutputType = PRIM_UNKNOWN; - /* No in/out qualifiers defined for anything but GLSL 1.50+ * geometry shaders so far. */ - if (linked_shader->Stage != MESA_SHADER_GEOMETRY || + if (gl_prog->info.stage != MESA_SHADER_GEOMETRY || prog->data->Version < 150) return; + int vertices_out = -1; + + gl_prog->info.gs.invocations = 0; + gl_prog->info.gs.input_primitive = PRIM_UNKNOWN; + gl_prog->info.gs.output_primitive = PRIM_UNKNOWN; + /* From the GLSL 1.50 spec, page 46: * * "All geometry shader output layout declarations in a program @@ -1921,51 +2094,49 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[i]; if (shader->info.Geom.InputType != PRIM_UNKNOWN) { - if (linked_shader->info.Geom.InputType != PRIM_UNKNOWN && - linked_shader->info.Geom.InputType != + if (gl_prog->info.gs.input_primitive != PRIM_UNKNOWN && + gl_prog->info.gs.input_primitive != shader->info.Geom.InputType) { linker_error(prog, "geometry shader defined with conflicting " "input types\n"); return; } - linked_shader->info.Geom.InputType = shader->info.Geom.InputType; + gl_prog->info.gs.input_primitive = shader->info.Geom.InputType; } if (shader->info.Geom.OutputType != PRIM_UNKNOWN) { - if (linked_shader->info.Geom.OutputType != PRIM_UNKNOWN && - linked_shader->info.Geom.OutputType != + if (gl_prog->info.gs.output_primitive != PRIM_UNKNOWN && + gl_prog->info.gs.output_primitive != shader->info.Geom.OutputType) { linker_error(prog, "geometry shader defined with conflicting " "output types\n"); return; } - linked_shader->info.Geom.OutputType = shader->info.Geom.OutputType; + gl_prog->info.gs.output_primitive = shader->info.Geom.OutputType; } if (shader->info.Geom.VerticesOut != -1) { - if (linked_shader->info.Geom.VerticesOut != -1 && - linked_shader->info.Geom.VerticesOut != - shader->info.Geom.VerticesOut) { + if (vertices_out != -1 && + vertices_out != shader->info.Geom.VerticesOut) { linker_error(prog, "geometry shader defined with conflicting " "output vertex count (%d and %d)\n", - linked_shader->info.Geom.VerticesOut, - shader->info.Geom.VerticesOut); + vertices_out, shader->info.Geom.VerticesOut); return; } - linked_shader->info.Geom.VerticesOut = shader->info.Geom.VerticesOut; + vertices_out = shader->info.Geom.VerticesOut; } if (shader->info.Geom.Invocations != 0) { - if (linked_shader->info.Geom.Invocations != 0 && - linked_shader->info.Geom.Invocations != - shader->info.Geom.Invocations) { + if (gl_prog->info.gs.invocations != 0 && + gl_prog->info.gs.invocations != + (unsigned) shader->info.Geom.Invocations) { linker_error(prog, "geometry shader defined with conflicting " "invocation count (%d and %d)\n", - linked_shader->info.Geom.Invocations, + gl_prog->info.gs.invocations, shader->info.Geom.Invocations); return; } - linked_shader->info.Geom.Invocations = shader->info.Geom.Invocations; + gl_prog->info.gs.invocations = shader->info.Geom.Invocations; } } @@ -1973,26 +2144,28 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.Geom.InputType == PRIM_UNKNOWN) { + if (gl_prog->info.gs.input_primitive == PRIM_UNKNOWN) { linker_error(prog, "geometry shader didn't declare primitive input type\n"); return; } - if (linked_shader->info.Geom.OutputType == PRIM_UNKNOWN) { + if (gl_prog->info.gs.output_primitive == PRIM_UNKNOWN) { linker_error(prog, "geometry shader didn't declare primitive output type\n"); return; } - if (linked_shader->info.Geom.VerticesOut == -1) { + if (vertices_out == -1) { linker_error(prog, "geometry shader didn't declare max_vertices\n"); return; + } else { + gl_prog->info.gs.vertices_out = vertices_out; } - if (linked_shader->info.Geom.Invocations == 0) - linked_shader->info.Geom.Invocations = 1; + if (gl_prog->info.gs.invocations == 0) + gl_prog->info.gs.invocations = 1; } @@ -2003,21 +2176,21 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, */ static void link_cs_input_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - for (int i = 0; i < 3; i++) - linked_shader->info.Comp.LocalSize[i] = 0; - - linked_shader->info.Comp.LocalSizeVariable = false; - /* This function is called for all shader stages, but it only has an effect * for compute shaders. */ - if (linked_shader->Stage != MESA_SHADER_COMPUTE) + if (gl_prog->info.stage != MESA_SHADER_COMPUTE) return; + for (int i = 0; i < 3; i++) + gl_prog->info.cs.local_size[i] = 0; + + gl_prog->info.cs.local_size_variable = false; + /* From the ARB_compute_shader spec, in the section describing local size * declarations: * @@ -2032,9 +2205,9 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[sh]; if (shader->info.Comp.LocalSize[0] != 0) { - if (linked_shader->info.Comp.LocalSize[0] != 0) { + if (gl_prog->info.cs.local_size[0] != 0) { for (int i = 0; i < 3; i++) { - if (linked_shader->info.Comp.LocalSize[i] != + if (gl_prog->info.cs.local_size[i] != shader->info.Comp.LocalSize[i]) { linker_error(prog, "compute shader defined with conflicting " "local sizes\n"); @@ -2043,11 +2216,11 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, } } for (int i = 0; i < 3; i++) { - linked_shader->info.Comp.LocalSize[i] = + gl_prog->info.cs.local_size[i] = shader->info.Comp.LocalSize[i]; } } else if (shader->info.Comp.LocalSizeVariable) { - if (linked_shader->info.Comp.LocalSize[0] != 0) { + if (gl_prog->info.cs.local_size[0] != 0) { /* The ARB_compute_variable_group_size spec says: * * If one compute shader attached to a program declares a @@ -2059,7 +2232,7 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, "variable local group size\n"); return; } - linked_shader->info.Comp.LocalSizeVariable = true; + gl_prog->info.cs.local_size_variable = true; } } @@ -2067,17 +2240,46 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.Comp.LocalSize[0] == 0 && - !linked_shader->info.Comp.LocalSizeVariable) { + if (gl_prog->info.cs.local_size[0] == 0 && + !gl_prog->info.cs.local_size_variable) { linker_error(prog, "compute shader must contain a fixed or a variable " "local group size\n"); return; } - for (int i = 0; i < 3; i++) - prog->Comp.LocalSize[i] = linked_shader->info.Comp.LocalSize[i]; +} + +/** + * Link all out variables on a single stage which are not + * directly used in a shader with the main function. + */ +static void +link_output_variables(struct gl_linked_shader *linked_shader, + struct gl_shader **shader_list, + unsigned num_shaders) +{ + struct glsl_symbol_table *symbols = linked_shader->symbols; - prog->Comp.LocalSizeVariable = - linked_shader->info.Comp.LocalSizeVariable; + for (unsigned i = 0; i < num_shaders; i++) { + + /* Skip shader object with main function */ + if (shader_list[i]->symbols->get_function("main")) + continue; + + foreach_in_list(ir_instruction, ir, shader_list[i]->ir) { + if (ir->ir_type != ir_type_variable) + continue; + + ir_variable *const var = (ir_variable *) ir; + + if (var->data.mode == ir_var_shader_out && + !symbols->get_variable(var->name)) { + symbols->add_variable(var); + linked_shader->ir->push_head(var); + } + } + } + + return; } @@ -2107,7 +2309,8 @@ link_intrastage_shaders(void *mem_ctx, for (unsigned i = 0; i < num_shaders; i++) { if (shader_list[i] == NULL) continue; - cross_validate_globals(prog, shader_list[i]->ir, &variables, false); + cross_validate_globals(ctx, prog, shader_list[i]->ir, &variables, + false); } if (!prog->data->LinkStatus) @@ -2190,7 +2393,7 @@ link_intrastage_shaders(void *mem_ctx, _mesa_shader_stage_to_program(shader_list[0]->Stage), prog->Name, false); if (!gl_prog) { - prog->data->LinkStatus = false; + prog->data->LinkStatus = LINKING_FAILURE; _mesa_delete_linked_shader(ctx, linked); return NULL; } @@ -2205,13 +2408,16 @@ link_intrastage_shaders(void *mem_ctx, link_fs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders); link_tcs_out_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); - link_tes_in_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_xfb_stride_layout_qualifiers(ctx, prog, linked, shader_list, - num_shaders); + link_tes_in_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + link_gs_inout_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + link_cs_input_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + + if (linked->Stage != MESA_SHADER_FRAGMENT) + link_xfb_stride_layout_qualifiers(ctx, prog, shader_list, num_shaders); + + link_bindless_layout_qualifiers(prog, shader_list, num_shaders); - populate_symbol_table(linked); + populate_symbol_table(linked, shader_list[0]->symbols); /* The pointer to the main function in the final linked shader (i.e., the * copy of the original shader that contained the main function). @@ -2241,6 +2447,9 @@ link_intrastage_shaders(void *mem_ctx, return NULL; } + if (linked->Stage != MESA_SHADER_FRAGMENT) + link_output_variables(linked, shader_list, num_shaders); + /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the * max_array_access field. @@ -2283,7 +2492,8 @@ link_intrastage_shaders(void *mem_ctx, /* Set the size of geometry shader input arrays */ if (linked->Stage == MESA_SHADER_GEOMETRY) { - unsigned num_vertices = vertices_per_prim(linked->info.Geom.InputType); + unsigned num_vertices = + vertices_per_prim(gl_prog->info.gs.input_primitive); array_resize_visitor input_resize_visitor(num_vertices, prog, MESA_SHADER_GEOMETRY); foreach_in_list(ir_instruction, ir, linked->ir) { @@ -2294,6 +2504,9 @@ link_intrastage_shaders(void *mem_ctx, if (ctx->Const.VertexID_is_zero_based) lower_vertex_id(linked); + if (ctx->Const.LowerCsDerivedVariables) + lower_cs_derived(linked); + #ifdef DEBUG /* Compute the source checksum. */ linked->SourceChecksum = 0; @@ -2426,7 +2639,7 @@ resize_tes_inputs(struct gl_context *ctx, ir->accept(&input_resize_visitor); } - if (tcs || ctx->Const.LowerTESPatchVerticesIn) { + if (tcs) { /* Convert the gl_PatchVerticesIn system value into a constant, since * the value is known at this point. */ @@ -2437,20 +2650,8 @@ resize_tes_inputs(struct gl_context *ctx, void *mem_ctx = ralloc_parent(var); var->data.location = 0; var->data.explicit_location = false; - if (tcs) { - var->data.mode = ir_var_auto; - var->constant_value = new(mem_ctx) ir_constant(num_vertices); - } else { - var->data.mode = ir_var_uniform; - var->data.how_declared = ir_var_hidden; - var->allocate_state_slots(1); - ir_state_slot *slot0 = &var->get_state_slots()[0]; - slot0->swizzle = SWIZZLE_XXXX; - slot0->tokens[0] = STATE_INTERNAL; - slot0->tokens[1] = STATE_TES_PATCH_VERTICES_IN; - for (int i = 2; i < STATE_LENGTH; i++) - slot0->tokens[i] = 0; - } + var->data.mode = ir_var_auto; + var->constant_value = new(mem_ctx) ir_constant(num_vertices); } } } @@ -2465,7 +2666,7 @@ resize_tes_inputs(struct gl_context *ctx, * \return * Base location of the available bits on success or -1 on failure. */ -int +static int find_available_slots(unsigned used_mask, unsigned needed_count) { unsigned needed_mask = (1 << needed_count) - 1; @@ -2488,6 +2689,8 @@ find_available_slots(unsigned used_mask, unsigned needed_count) } +#define SAFE_MASK_FROM_INDEX(i) (((i) >= 32) ? ~0 : ((1 << (i)) - 1)) + /** * Assign locations for either VS inputs or FS outputs * @@ -2502,7 +2705,7 @@ find_available_slots(unsigned used_mask, unsigned needed_count) * If locations are successfully assigned, true is returned. Otherwise an * error is emitted to the shader link log and false is returned. */ -bool +static bool assign_attribute_or_color_locations(void *mem_ctx, gl_shader_program *prog, struct gl_constants *constants, @@ -2518,8 +2721,7 @@ assign_attribute_or_color_locations(void *mem_ctx, /* Mark invalid locations as being used. */ - unsigned used_locations = (max_index >= 32) - ? ~0 : ~((1 << max_index) - 1); + unsigned used_locations = ~SAFE_MASK_FROM_INDEX(max_index); unsigned double_storage_locations = 0; assert((target_index == MESA_SHADER_VERTEX) @@ -2571,12 +2773,14 @@ assign_attribute_or_color_locations(void *mem_ctx, } to_assign[32]; assert(max_index <= 32); - /* Temporary array for the set of attributes that have locations assigned. + /* Temporary array for the set of attributes that have locations assigned, + * for the purpose of checking overlapping slots/components of (non-ES) + * fragment shader outputs. */ - ir_variable *assigned[16]; + ir_variable *assigned[12 * 4]; /* (max # of FS outputs) * # components */ + unsigned assigned_attr = 0; unsigned num_attr = 0; - unsigned assigned_attr = 0; foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *const var = node->as_variable(); @@ -2815,6 +3019,18 @@ assign_attribute_or_color_locations(void *mem_ctx, } } + if (target_index == MESA_SHADER_FRAGMENT && !prog->IsES) { + /* Only track assigned variables for non-ES fragment shaders + * to avoid overflowing the array. + * + * At most one variable per fragment output component should + * reach this. + */ + assert(assigned_attr < ARRAY_SIZE(assigned)); + assigned[assigned_attr] = var; + assigned_attr++; + } + used_locations |= (use_mask << attr); /* From the GL 4.5 core spec, section 11.1.1 (Vertex Attributes): @@ -2841,9 +3057,6 @@ assign_attribute_or_color_locations(void *mem_ctx, double_storage_locations |= (use_mask << attr); } - assigned[assigned_attr] = var; - assigned_attr++; - continue; } @@ -2861,8 +3074,8 @@ assign_attribute_or_color_locations(void *mem_ctx, if (target_index == MESA_SHADER_VERTEX) { unsigned total_attribs_size = - _mesa_bitcount(used_locations & ((1 << max_index) - 1)) + - _mesa_bitcount(double_storage_locations); + util_bitcount(used_locations & SAFE_MASK_FROM_INDEX(max_index)) + + util_bitcount(double_storage_locations); if (total_attribs_size > max_index) { linker_error(prog, "attempt to use %d vertex attribute slots only %d available ", @@ -2925,8 +3138,8 @@ assign_attribute_or_color_locations(void *mem_ctx, */ if (target_index == MESA_SHADER_VERTEX) { unsigned total_attribs_size = - _mesa_bitcount(used_locations & ((1 << max_index) - 1)) + - _mesa_bitcount(double_storage_locations); + util_bitcount(used_locations & SAFE_MASK_FROM_INDEX(max_index)) + + util_bitcount(double_storage_locations); if (total_attribs_size > max_index) { linker_error(prog, "attempt to use %d vertex attribute slots only %d available ", @@ -3414,23 +3627,7 @@ check_explicit_uniform_locations(struct gl_context *ctx, } } - struct empty_uniform_block *current_block = NULL; - - for (unsigned i = 0; i < prog->NumUniformRemapTable; i++) { - /* We found empty space in UniformRemapTable. */ - if (prog->UniformRemapTable[i] == NULL) { - /* We've found the beginning of a new continous block of empty slots */ - if (!current_block || current_block->start + current_block->slots != i) { - current_block = rzalloc(prog, struct empty_uniform_block); - current_block->start = i; - exec_list_push_tail(&prog->EmptyUniformLocations, - ¤t_block->link); - } - - /* The current block continues, so we simply increment its slots */ - current_block->slots++; - } - } + link_util_update_empty_uniform_locations(prog); delete uniform_map; prog->NumExplicitUniformLocations = entries_total; @@ -3511,42 +3708,6 @@ should_add_buffer_variable(struct gl_shader_program *shProg, return false; } -static bool -add_program_resource(struct gl_shader_program *prog, - struct set *resource_set, - GLenum type, const void *data, uint8_t stages) -{ - assert(data); - - /* If resource already exists, do not add it again. */ - if (_mesa_set_search(resource_set, data)) - return true; - - prog->data->ProgramResourceList = - reralloc(prog, - prog->data->ProgramResourceList, - gl_program_resource, - prog->data->NumProgramResourceList + 1); - - if (!prog->data->ProgramResourceList) { - linker_error(prog, "Out of memory during linking.\n"); - return false; - } - - struct gl_program_resource *res = - &prog->data->ProgramResourceList[prog->data->NumProgramResourceList]; - - res->Type = type; - res->Data = data; - res->StageReferences = stages; - - prog->data->NumProgramResourceList++; - - _mesa_set_add(resource_set, data); - - return true; -} - /* Function checks if a variable var is a packed varying and * if given name is part of packed varying's list. * @@ -3642,7 +3803,10 @@ create_shader_variable(struct gl_shader_program *shProg, bool use_implicit_location, int location, const glsl_type *outermost_struct_type) { - gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable); + /* Allocate zero-initialized memory to ensure that bitfield padding + * is zero. + */ + gl_shader_variable *out = rzalloc(shProg, struct gl_shader_variable); if (!out) return NULL; @@ -3686,8 +3850,7 @@ create_shader_variable(struct gl_shader_program *shProg, * qualifier, except for vertex shader inputs and fragment shader * outputs." */ - if (in->type->base_type == GLSL_TYPE_ATOMIC_UINT || - is_gl_identifier(in->name) || + if (in->type->is_atomic_uint() || is_gl_identifier(in->name) || !(in->data.explicit_location || use_implicit_location)) { out->location = -1; } else { @@ -3708,17 +3871,6 @@ create_shader_variable(struct gl_shader_program *shProg, return out; } -static const glsl_type * -resize_to_max_patch_vertices(const struct gl_context *ctx, - const glsl_type *type) -{ - if (!type) - return NULL; - - return glsl_type::get_array_instance(type->fields.array, - ctx->Const.MaxPatchVertices); -} - static bool add_shader_variable(const struct gl_context *ctx, struct gl_shader_program *shProg, @@ -3727,32 +3879,12 @@ add_shader_variable(const struct gl_context *ctx, GLenum programInterface, ir_variable *var, const char *name, const glsl_type *type, bool use_implicit_location, int location, + bool inouts_share_location, const glsl_type *outermost_struct_type = NULL) { const glsl_type *interface_type = var->get_interface_type(); if (outermost_struct_type == NULL) { - /* Unsized (non-patch) TCS output/TES input arrays are implicitly - * sized to gl_MaxPatchVertices. Internally, we shrink them to a - * smaller size. - * - * This can cause trouble with SSO programs. Since the TCS declares - * the number of output vertices, we can always shrink TCS output - * arrays. However, the TES might not be linked with a TCS, in - * which case it won't know the size of the patch. In other words, - * the TCS and TES may disagree on the (smaller) array sizes. This - * can result in the resource names differing across stages, causing - * SSO validation failures and other cascading issues. - * - * Expanding the array size to the full gl_MaxPatchVertices fixes - * these issues. It's also what program interface queries expect, - * as that is the official size of the array. - */ - if (var->data.tess_varying_implicit_sized_array) { - type = resize_to_max_patch_vertices(ctx, type); - interface_type = resize_to_max_patch_vertices(ctx, interface_type); - } - if (var->data.from_named_ifc_block) { const char *interface_name = interface_type->name; @@ -3810,7 +3942,7 @@ add_shader_variable(const struct gl_context *ctx, stage_mask, programInterface, var, field_name, field->type, use_implicit_location, field_location, - outermost_struct_type)) + false, outermost_struct_type)) return false; field_location += field->type->count_attribute_slots(false); @@ -3818,6 +3950,43 @@ add_shader_variable(const struct gl_context *ctx, return true; } + case GLSL_TYPE_ARRAY: { + /* The ARB_program_interface_query spec says: + * + * "For an active variable declared as an array of basic types, a + * single entry will be generated, with its name string formed by + * concatenating the name of the array and the string "[0]"." + * + * "For an active variable declared as an array of an aggregate data + * type (structures or arrays), a separate entry will be generated + * for each active array element, unless noted immediately below. + * The name of each entry is formed by concatenating the name of + * the array, the "[" character, an integer identifying the element + * number, and the "]" character. These enumeration rules are + * applied recursively, treating each enumerated array element as a + * separate active variable." + */ + const struct glsl_type *array_type = type->fields.array; + if (array_type->base_type == GLSL_TYPE_STRUCT || + array_type->base_type == GLSL_TYPE_ARRAY) { + unsigned elem_location = location; + unsigned stride = inouts_share_location ? 0 : + array_type->count_attribute_slots(false); + for (unsigned i = 0; i < type->length; i++) { + char *elem = ralloc_asprintf(shProg, "%s[%d]", name, i); + if (!add_shader_variable(ctx, shProg, resource_set, + stage_mask, programInterface, + var, elem, array_type, + use_implicit_location, elem_location, + false, outermost_struct_type)) + return false; + elem_location += stride; + } + return true; + } + /* fallthrough */ + } + default: { /* The ARB_program_interface_query spec says: * @@ -3832,12 +4001,26 @@ add_shader_variable(const struct gl_context *ctx, if (!sha_v) return false; - return add_program_resource(shProg, resource_set, - programInterface, sha_v, stage_mask); + return link_util_add_program_resource(shProg, resource_set, + programInterface, sha_v, stage_mask); } } } +static bool +inout_has_same_location(const ir_variable *var, unsigned stage) +{ + if (!var->data.patch && + ((var->data.mode == ir_var_shader_out && + stage == MESA_SHADER_TESS_CTRL) || + (var->data.mode == ir_var_shader_in && + (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL || + stage == MESA_SHADER_GEOMETRY)))) + return true; + else + return false; +} + static bool add_interface_variables(const struct gl_context *ctx, struct gl_shader_program *shProg, @@ -3894,7 +4077,8 @@ add_interface_variables(const struct gl_context *ctx, if (!add_shader_variable(ctx, shProg, resource_set, 1 << stage, programInterface, var, var->name, var->type, vs_input_or_fs_output, - var->data.location - loc_bias)) + var->data.location - loc_bias, + inout_has_same_location(var, stage))) return false; } return true; @@ -3932,7 +4116,8 @@ add_packed_varyings(const struct gl_context *ctx, if (!add_shader_variable(ctx, shProg, resource_set, stage_mask, iface, var, var->name, var->type, false, - var->data.location - VARYING_SLOT_VAR0)) + var->data.location - VARYING_SLOT_VAR0, + inout_has_same_location(var, stage))) return false; } } @@ -3958,7 +4143,8 @@ add_fragdata_arrays(const struct gl_context *ctx, if (!add_shader_variable(ctx, shProg, resource_set, 1 << MESA_SHADER_FRAGMENT, GL_PROGRAM_OUTPUT, var, var->name, var->type, - true, var->data.location - FRAG_RESULT_DATA0)) + true, var->data.location - FRAG_RESULT_DATA0, + false)) return false; } } @@ -4032,8 +4218,8 @@ is_top_level_shader_storage_block_member(const char* name, return false; } - snprintf(full_instanced_name, name_length, "%s.%s", - interface_name, field_name); + util_snprintf(full_instanced_name, name_length, "%s.%s", + interface_name, field_name); /* Check if its top-level shader storage block member of an * instanced interface block, or of a unnamed interface block. @@ -4073,9 +4259,9 @@ get_array_size(struct gl_uniform_storage *uni, const glsl_struct_field *field, } static int -get_array_stride(struct gl_uniform_storage *uni, const glsl_type *interface, - const glsl_struct_field *field, char *interface_name, - char *var_name) +get_array_stride(struct gl_context *ctx, struct gl_uniform_storage *uni, + const glsl_type *iface, const glsl_struct_field *field, + char *interface_name, char *var_name) { /* The ARB_program_interface_query spec says: * @@ -4099,7 +4285,9 @@ get_array_stride(struct gl_uniform_storage *uni, const glsl_type *interface, var_name)) return 0; - if (interface->interface_packing != GLSL_INTERFACE_PACKING_STD430) { + if (GLSL_INTERFACE_PACKING_STD140 == + iface-> + get_internal_ifc_packing(ctx->Const.UseSTD430AsDefaultPacking)) { if (array_type->is_record() || array_type->is_array()) return glsl_align(array_type->std140_size(row_major), 16); else @@ -4112,7 +4300,8 @@ get_array_stride(struct gl_uniform_storage *uni, const glsl_type *interface, } static void -calculate_array_size_and_stride(struct gl_shader_program *shProg, +calculate_array_size_and_stride(struct gl_context *ctx, + struct gl_shader_program *shProg, struct gl_uniform_storage *uni) { int block_index = uni->block_index; @@ -4151,17 +4340,17 @@ calculate_array_size_and_stride(struct gl_shader_program *shProg, var->data.mode != ir_var_shader_storage) continue; - const glsl_type *interface = var->get_interface_type(); + const glsl_type *iface = var->get_interface_type(); - if (strcmp(interface_name, interface->name) != 0) + if (strcmp(interface_name, iface->name) != 0) continue; - for (unsigned i = 0; i < interface->length; i++) { - const glsl_struct_field *field = &interface->fields.structure[i]; + for (unsigned i = 0; i < iface->length; i++) { + const glsl_struct_field *field = &iface->fields.structure[i]; if (strcmp(field->name, var_name) != 0) continue; - array_stride = get_array_stride(uni, interface, field, + array_stride = get_array_stride(ctx, uni, iface, field, interface_name, var_name); array_size = get_array_size(uni, field, interface_name, var_name); goto write_top_level_array_size_and_stride; @@ -4235,27 +4424,29 @@ build_program_resource_list(struct gl_context *ctx, output_stage, GL_PROGRAM_OUTPUT)) return; - struct gl_transform_feedback_info *linked_xfb = - shProg->xfb_program->sh.LinkedTransformFeedback; + if (shProg->last_vert_prog) { + struct gl_transform_feedback_info *linked_xfb = + shProg->last_vert_prog->sh.LinkedTransformFeedback; - /* Add transform feedback varyings. */ - if (linked_xfb->NumVarying > 0) { - for (int i = 0; i < linked_xfb->NumVarying; i++) { - if (!add_program_resource(shProg, resource_set, - GL_TRANSFORM_FEEDBACK_VARYING, - &linked_xfb->Varyings[i], 0)) - return; + /* Add transform feedback varyings. */ + if (linked_xfb->NumVarying > 0) { + for (int i = 0; i < linked_xfb->NumVarying; i++) { + if (!link_util_add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_VARYING, + &linked_xfb->Varyings[i], 0)) + return; + } } - } - /* Add transform feedback buffers. */ - for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { - if ((linked_xfb->ActiveBuffers >> i) & 1) { - linked_xfb->Buffers[i].Binding = i; - if (!add_program_resource(shProg, resource_set, - GL_TRANSFORM_FEEDBACK_BUFFER, - &linked_xfb->Buffers[i], 0)) - return; + /* Add transform feedback buffers. */ + for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { + if ((linked_xfb->ActiveBuffers >> i) & 1) { + linked_xfb->Buffers[i].Binding = i; + if (!link_util_add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_BUFFER, + &linked_xfb->Buffers[i], 0)) + return; + } } } @@ -4285,33 +4476,33 @@ build_program_resource_list(struct gl_context *ctx, continue; if (is_shader_storage) { - calculate_array_size_and_stride(shProg, + calculate_array_size_and_stride(ctx, shProg, &shProg->data->UniformStorage[i]); } - if (!add_program_resource(shProg, resource_set, type, - &shProg->data->UniformStorage[i], stageref)) + if (!link_util_add_program_resource(shProg, resource_set, type, + &shProg->data->UniformStorage[i], stageref)) return; } /* Add program uniform blocks. */ for (unsigned i = 0; i < shProg->data->NumUniformBlocks; i++) { - if (!add_program_resource(shProg, resource_set, GL_UNIFORM_BLOCK, - &shProg->data->UniformBlocks[i], 0)) + if (!link_util_add_program_resource(shProg, resource_set, GL_UNIFORM_BLOCK, + &shProg->data->UniformBlocks[i], 0)) return; } /* Add program shader storage blocks. */ for (unsigned i = 0; i < shProg->data->NumShaderStorageBlocks; i++) { - if (!add_program_resource(shProg, resource_set, GL_SHADER_STORAGE_BLOCK, - &shProg->data->ShaderStorageBlocks[i], 0)) + if (!link_util_add_program_resource(shProg, resource_set, GL_SHADER_STORAGE_BLOCK, + &shProg->data->ShaderStorageBlocks[i], 0)) return; } /* Add atomic counter buffers. */ for (unsigned i = 0; i < shProg->data->NumAtomicBuffers; i++) { - if (!add_program_resource(shProg, resource_set, GL_ATOMIC_COUNTER_BUFFER, - &shProg->data->AtomicBuffers[i], 0)) + if (!link_util_add_program_resource(shProg, resource_set, GL_ATOMIC_COUNTER_BUFFER, + &shProg->data->AtomicBuffers[i], 0)) return; } @@ -4327,8 +4518,8 @@ build_program_resource_list(struct gl_context *ctx, type = _mesa_shader_stage_to_subroutine_uniform((gl_shader_stage)j); /* add shader subroutines */ - if (!add_program_resource(shProg, resource_set, - type, &shProg->data->UniformStorage[i], 0)) + if (!link_util_add_program_resource(shProg, resource_set, + type, &shProg->data->UniformStorage[i], 0)) return; } } @@ -4340,8 +4531,8 @@ build_program_resource_list(struct gl_context *ctx, GLuint type = _mesa_shader_stage_to_subroutine((gl_shader_stage)i); for (unsigned j = 0; j < p->sh.NumSubroutineFunctions; j++) { - if (!add_program_resource(shProg, resource_set, - type, &p->sh.SubroutineFunctions[j], 0)) + if (!link_util_add_program_resource(shProg, resource_set, + type, &p->sh.SubroutineFunctions[j], 0)) return; } } @@ -4498,24 +4689,17 @@ disable_varying_optimizations_for_sso(struct gl_shader_program *prog) if (!sh) continue; - if (first == last) { - /* For a single shader program only allow inputs to the vertex shader - * and outputs from the fragment shader to be removed. - */ - if (stage != MESA_SHADER_VERTEX) - set_always_active_io(sh->ir, ir_var_shader_in); - if (stage != MESA_SHADER_FRAGMENT) - set_always_active_io(sh->ir, ir_var_shader_out); - } else { - /* For multi-stage separate shader programs only allow inputs and - * outputs between the shader stages to be removed as well as inputs - * to the vertex shader and outputs from the fragment shader. - */ - if (stage == first && stage != MESA_SHADER_VERTEX) - set_always_active_io(sh->ir, ir_var_shader_in); - else if (stage == last && stage != MESA_SHADER_FRAGMENT) - set_always_active_io(sh->ir, ir_var_shader_out); - } + /* Prevent the removal of inputs to the first and outputs from the last + * stage, unless they are the initial pipeline inputs or final pipeline + * outputs, respectively. + * + * The removal of IO between shaders in the same program is always + * allowed. + */ + if (stage == first && stage != MESA_SHADER_VERTEX) + set_always_active_io(sh->ir, ir_var_shader_in); + if (stage == last && stage != MESA_SHADER_FRAGMENT) + set_always_active_io(sh->ir, ir_var_shader_out); } } @@ -4566,15 +4750,12 @@ link_varyings_and_uniforms(unsigned first, unsigned last, return false; } - /* Find the program used for xfb. Even if we don't use xfb we still want to - * set this so we can fill the default values for program interface query. - */ - prog->xfb_program = prog->_LinkedShaders[last]->Program; + prog->last_vert_prog = NULL; for (int i = MESA_SHADER_GEOMETRY; i >= MESA_SHADER_VERTEX; i--) { if (prog->_LinkedShaders[i] == NULL) continue; - prog->xfb_program = prog->_LinkedShaders[i]->Program; + prog->last_vert_prog = prog->_LinkedShaders[i]->Program; break; } @@ -4595,11 +4776,11 @@ link_varyings_and_uniforms(unsigned first, unsigned last, if (options->LowerBufferInterfaceBlocks) lower_ubo_reference(prog->_LinkedShaders[i], - options->ClampBlockIndicesToArrayBounds); + options->ClampBlockIndicesToArrayBounds, + ctx->Const.UseSTD430AsDefaultPacking); if (i == MESA_SHADER_COMPUTE) - lower_shared_reference(prog->_LinkedShaders[i], - &prog->Comp.SharedSize); + lower_shared_reference(ctx, prog, prog->_LinkedShaders[i]); lower_vector_derefs(prog->_LinkedShaders[i]); do_vec_index_to_swizzle(prog->_LinkedShaders[i]->ir); @@ -4608,10 +4789,28 @@ link_varyings_and_uniforms(unsigned first, unsigned last, return true; } +static void +linker_optimisation_loop(struct gl_context *ctx, exec_list *ir, + unsigned stage) +{ + if (ctx->Const.GLSLOptimizeConservatively) { + /* Run it just once. */ + do_common_optimization(ir, true, false, + &ctx->Const.ShaderCompilerOptions[stage], + ctx->Const.NativeIntegers); + } else { + /* Repeat it until it stops making changes. */ + while (do_common_optimization(ir, true, false, + &ctx->Const.ShaderCompilerOptions[stage], + ctx->Const.NativeIntegers)) + ; + } +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { - prog->data->LinkStatus = true; /* All error paths will set this to false */ + prog->data->LinkStatus = LINKING_SUCCESS; /* All error paths will set this to false */ prog->data->Validated = false; /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec says: @@ -4633,6 +4832,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) return; } +#ifdef ENABLE_SHADER_CACHE + if (shader_cache_read_program_metadata(ctx, prog)) + return; +#endif + void *mem_ctx = ralloc_context(NULL); // temporary linker context prog->ARB_fragment_coord_conventions_enable = false; @@ -4654,7 +4858,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) min_version = MIN2(min_version, prog->Shaders[i]->Version); max_version = MAX2(max_version, prog->Shaders[i]->Version); - if (prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) { + if (!ctx->Const.AllowGLSLRelaxedES && + prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) { linker_error(prog, "all shaders must use same shading " "language version\n"); goto done; @@ -4672,7 +4877,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* In desktop GLSL, different shader versions may be linked together. In * GLSL ES, all shader versions must be the same. */ - if (prog->Shaders[0]->IsES && min_version != max_version) { + if (!ctx->Const.AllowGLSLRelaxedES && prog->Shaders[0]->IsES && + min_version != max_version) { linker_error(prog, "all shaders must use same shading " "language version\n"); goto done; @@ -4703,7 +4909,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - /* The spec is self-contradictory here. It allows linking without a tess + /* Section 7.3 of the OpenGL ES 3.2 specification says: + * + * "Linking can fail for [...] any of the following reasons: + * + * * program contains an object to form a tessellation control + * shader [...] and [...] the program is not separable and + * contains no object to form a tessellation evaluation shader" + * + * The OpenGL spec is contradictory. It allows linking without a tess * eval shader, but that can only be used with transform feedback and * rasterization disabled. However, transform feedback isn't allowed * with GL_PATCHES, so it can't be used. @@ -4725,6 +4939,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) "tessellation evaluation shader\n"); goto done; } + + if (prog->IsES) { + if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 && + num_shaders[MESA_SHADER_TESS_CTRL] == 0) { + linker_error(prog, "GLSL ES requires non-separable programs " + "containing a tessellation evaluation shader to also " + "be linked with a tessellation control shader\n"); + goto done; + } + } } /* Compute shaders have additional restrictions. */ @@ -4776,25 +5000,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } } - if (num_shaders[MESA_SHADER_GEOMETRY] > 0) { - prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->Geom.CullDistanceArraySize; - } else if (num_shaders[MESA_SHADER_TESS_EVAL] > 0) { - prog->LastClipDistanceArraySize = prog->TessEval.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->TessEval.CullDistanceArraySize; - } else if (num_shaders[MESA_SHADER_VERTEX] > 0) { - prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->Vert.CullDistanceArraySize; - } else { - prog->LastClipDistanceArraySize = 0; /* Not used */ - prog->LastCullDistanceArraySize = 0; /* Not used */ - } - /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and * varyings. */ - cross_validate_uniforms(prog); + cross_validate_uniforms(ctx, prog); if (!prog->data->LinkStatus) goto done; @@ -4833,7 +5043,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (!prog->data->LinkStatus) goto done; - cross_validate_outputs_to_inputs(prog, + cross_validate_outputs_to_inputs(ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i]); if (!prog->data->LinkStatus) @@ -4842,6 +5052,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prev = i; } + /* The cross validation of outputs/inputs above validates explicit locations + * but for SSO programs we need to do this also for the inputs in the + * first stage and outputs of the last stage included in the program, since + * there is no cross validation for these. + */ + if (prog->SeparateShader) + validate_sso_explicit_locations(ctx, prog, + (gl_shader_stage) first, + (gl_shader_stage) last); + /* Cross-validate uniform blocks between shader stages */ validate_interstage_uniform_blocks(prog, prog->_LinkedShaders); if (!prog->data->LinkStatus) @@ -4852,6 +5072,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_named_interface_blocks(mem_ctx, prog->_LinkedShaders[i]); } + if (prog->IsES && prog->data->Version == 100) + if (!validate_invariant_builtins(prog, + prog->_LinkedShaders[MESA_SHADER_VERTEX], + prog->_LinkedShaders[MESA_SHADER_FRAGMENT])) + goto done; + /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do * it before optimization because we want most of the checks to get * dropped thanks to constant propagation. @@ -4896,20 +5122,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_tess_level(prog->_LinkedShaders[i]); } - if (ctx->Const.GLSLOptimizeConservatively) { - /* Run it just once. */ - do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, - &ctx->Const.ShaderCompilerOptions[i], - ctx->Const.NativeIntegers); - } else { - /* Repeat it until it stops making changes. */ - while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, - &ctx->Const.ShaderCompilerOptions[i], - ctx->Const.NativeIntegers)) - ; - } + /* Call opts before lowering const arrays to uniforms so we can const + * propagate any elements accessed directly. + */ + linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); + + /* Call opts after lowering const arrays to copy propagate things. */ + if (lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i)) + linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); - lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i); propagate_invariance(prog->_LinkedShaders[i]->ir); } @@ -4931,6 +5152,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if(!link_varyings_and_uniforms(first, last, ctx, prog, mem_ctx)) goto done; + /* Linking varyings can cause some extra, useless swizzles to be generated + * due to packing and unpacking. + */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + + optimize_swizzles(prog->_LinkedShaders[i]->ir); + } + /* OpenGL ES < 3.1 requires that a vertex shader and a fragment shader both * be present in a linked program. GL_ARB_ES2_compatibility doesn't say * anything about shader linking when one of the shaders (vertex or