X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fglsl%2Flinker.cpp;h=eb615ebd30a44a1dd22a69b1668ccf63c6d3fb43;hb=9950523368026f900fe901eb5921fd2283e5280c;hp=94bd7fb65921f23cbe1268c5640c8f628f0f65d4;hpb=4d24a7cb97641cacecd371d1968f6964785822e4;p=mesa.git diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 94bd7fb6592..eb615ebd30a 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -66,7 +66,6 @@ #include #include "util/strndup.h" -#include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ir.h" @@ -77,15 +76,20 @@ #include "util/set.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 { @@ -456,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 = linking_failure; + prog->data->LinkStatus = LINKING_FAILURE; } @@ -583,11 +587,10 @@ static void analyze_clip_cull_usage(struct gl_shader_program *prog, struct gl_linked_shader *shader, struct gl_context *ctx, - GLuint *clip_distance_array_size, - GLuint *cull_distance_array_size) + struct shader_info *info) { - *clip_distance_array_size = 0; - *cull_distance_array_size = 0; + info->clip_distance_array_size = 0; + info->cull_distance_array_size = 0; if (prog->data->Version >= (prog->IsES ? 300 : 130)) { /* From section 7.1 (Vertex Shader Special Variables) of the @@ -639,13 +642,13 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, ir_variable *clip_distance_var = shader->symbols->get_variable("gl_ClipDistance"); assert(clip_distance_var); - *clip_distance_array_size = clip_distance_var->type->length; + info->clip_distance_array_size = clip_distance_var->type->length; } if (gl_CullDistance.found) { ir_variable *cull_distance_var = shader->symbols->get_variable("gl_CullDistance"); assert(cull_distance_var); - *cull_distance_array_size = cull_distance_var->type->length; + info->cull_distance_array_size = cull_distance_var->type->length; } /* From the ARB_cull_distance spec: * @@ -654,7 +657,7 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, * gl_CullDistance arrays to be larger than * gl_MaxCombinedClipAndCullDistances. */ - if ((*clip_distance_array_size + *cull_distance_array_size) > + if ((uint32_t)(info->clip_distance_array_size + info->cull_distance_array_size) > ctx->Const.MaxClipPlanes) { linker_error(prog, "%s shader: the combined size of " "'gl_ClipDistance' and 'gl_CullDistance' size cannot " @@ -725,9 +728,7 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, } } - analyze_clip_cull_usage(prog, shader, ctx, - &shader->Program->info.clip_distance_array_size, - &shader->Program->info.cull_distance_array_size); + analyze_clip_cull_usage(prog, shader, ctx, &shader->Program->info); } static void @@ -738,9 +739,7 @@ validate_tess_eval_shader_executable(struct gl_shader_program *prog, if (shader == NULL) return; - analyze_clip_cull_usage(prog, shader, ctx, - &shader->Program->info.clip_distance_array_size, - &shader->Program->info.cull_distance_array_size); + analyze_clip_cull_usage(prog, shader, ctx, &shader->Program->info); } @@ -787,9 +786,7 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, vertices_per_prim(shader->Program->info.gs.input_primitive); prog->Geom.VerticesIn = num_vertices; - analyze_clip_cull_usage(prog, shader, ctx, - &shader->Program->info.clip_distance_array_size, - &shader->Program->info.cull_distance_array_size); + analyze_clip_cull_usage(prog, shader, ctx, &shader->Program->info); } /** @@ -850,7 +847,8 @@ validate_geometry_shader_emissions(struct gl_context *ctx, bool validate_intrastage_arrays(struct gl_shader_program *prog, ir_variable *const var, - ir_variable *const existing) + ir_variable *const existing, + bool match_precision) { /* Consider the types to be "the same" if both types are arrays * of the same type and one of the arrays is implicitly sized. @@ -858,7 +856,15 @@ validate_intrastage_arrays(struct gl_shader_program *prog, * explicitly sized array. */ if (var->type->is_array() && existing->type->is_array()) { - if ((var->type->fields.array == existing->type->fields.array) && + const glsl_type *no_array_var = var->type->fields.array; + const glsl_type *no_array_existing = existing->type->fields.array; + bool type_matches; + + type_matches = (match_precision ? + no_array_var == no_array_existing : + no_array_var->compare_no_precision(no_array_existing)); + + if (type_matches && ((var->type->length == 0)|| (existing->type->length == 0))) { if (var->type->length != 0) { if ((int)var->type->length <= existing->data.max_array_access) { @@ -893,7 +899,7 @@ validate_intrastage_arrays(struct gl_shader_program *prog, * Perform validation of global variables used across multiple shaders */ static void -cross_validate_globals(struct gl_shader_program *prog, +cross_validate_globals(struct gl_context *ctx, struct gl_shader_program *prog, struct exec_list *ir, glsl_symbol_table *variables, bool uniforms_only) { @@ -1086,7 +1092,7 @@ cross_validate_globals(struct gl_shader_program *prog, } } - if (existing->data.invariant != var->data.invariant) { + if (existing->data.explicit_invariant != var->data.explicit_invariant) { linker_error(prog, "declarations for %s `%s' have " "mismatching invariant qualifiers\n", mode_string(var), var->name); @@ -1111,20 +1117,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); @@ -1136,15 +1174,16 @@ cross_validate_globals(struct gl_shader_program *prog, * Perform validation of uniforms used across multiple shader stages */ static void -cross_validate_uniforms(struct gl_shader_program *prog) +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); } } @@ -1195,8 +1234,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 " @@ -1250,26 +1289,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); } @@ -1373,8 +1462,7 @@ move_non_declarations(exec_list *instructions, exec_node *last, hash_table *temps = NULL; if (make_copies) - temps = _mesa_hash_table_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal); + temps = _mesa_pointer_hash_table_create(NULL); foreach_in_list_safe(ir_instruction, inst, instructions) { if (inst->as_function()) @@ -1420,8 +1508,7 @@ class array_sizing_visitor : public deref_type_updater { public: array_sizing_visitor() : mem_ctx(ralloc_context(NULL)), - unnamed_interfaces(_mesa_hash_table_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal)) + unnamed_interfaces(_mesa_pointer_hash_table_create(NULL)) { } @@ -1956,9 +2043,19 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, 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; } + + linked_shader->Program->info.fs.pixel_center_integer = pixel_center_integer; + linked_shader->Program->info.fs.origin_upper_left = origin_upper_left; } /** @@ -2075,9 +2172,9 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, /** - * Perform cross-validation of compute shader local_size_{x,y,z} layout - * qualifiers for the attached compute shaders, and propagate them to the - * linked CS and linked shader program. + * Perform cross-validation of compute shader local_size_{x,y,z} layout and + * derivative arrangement qualifiers for the attached compute shaders, and + * propagate them to the linked CS and linked shader program. */ static void link_cs_input_layout_qualifiers(struct gl_shader_program *prog, @@ -2096,6 +2193,8 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, gl_prog->info.cs.local_size_variable = false; + gl_prog->info.cs.derivative_group = DERIVATIVE_GROUP_NONE; + /* From the ARB_compute_shader spec, in the section describing local size * declarations: * @@ -2139,6 +2238,17 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, } gl_prog->info.cs.local_size_variable = true; } + + enum gl_derivative_group group = shader->info.Comp.DerivativeGroup; + if (group != DERIVATIVE_GROUP_NONE) { + if (gl_prog->info.cs.derivative_group != DERIVATIVE_GROUP_NONE && + gl_prog->info.cs.derivative_group != group) { + linker_error(prog, "compute shader defined with conflicting " + "derivative groups\n"); + return; + } + gl_prog->info.cs.derivative_group = group; + } } /* Just do the intrastage -> interstage propagation right now, @@ -2151,6 +2261,65 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, "local group size\n"); return; } + + if (gl_prog->info.cs.derivative_group == DERIVATIVE_GROUP_QUADS) { + if (gl_prog->info.cs.local_size[0] % 2 != 0) { + linker_error(prog, "derivative_group_quadsNV must be used with a " + "local group size whose first dimension " + "is a multiple of 2\n"); + return; + } + if (gl_prog->info.cs.local_size[1] % 2 != 0) { + linker_error(prog, "derivative_group_quadsNV must be used with a local" + "group size whose second dimension " + "is a multiple of 2\n"); + return; + } + } else if (gl_prog->info.cs.derivative_group == DERIVATIVE_GROUP_LINEAR) { + if ((gl_prog->info.cs.local_size[0] * + gl_prog->info.cs.local_size[1] * + gl_prog->info.cs.local_size[2]) % 4 != 0) { + linker_error(prog, "derivative_group_linearNV must be used with a " + "local group size whose total number of invocations " + "is a multiple of 4\n"); + return; + } + } +} + +/** + * 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; + + 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 *var = (ir_variable *) ir; + + if (var->data.mode == ir_var_shader_out && + !symbols->get_variable(var->name)) { + var = var->clone(linked_shader, NULL); + symbols->add_variable(var); + linked_shader->ir->push_head(var); + } + } + } + + return; } @@ -2180,7 +2349,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) @@ -2263,13 +2433,12 @@ link_intrastage_shaders(void *mem_ctx, _mesa_shader_stage_to_program(shader_list[0]->Stage), prog->Name, false); if (!gl_prog) { - prog->data->LinkStatus = linking_failure; + prog->data->LinkStatus = LINKING_FAILURE; _mesa_delete_linked_shader(ctx, linked); return NULL; } - if (!prog->data->cache_fallback) - _mesa_reference_shader_program_data(ctx, &gl_prog->sh.data, prog->data); + _mesa_reference_shader_program_data(ctx, &gl_prog->sh.data, prog->data); /* Don't use _mesa_reference_program() just take ownership */ linked->Program = gl_prog; @@ -2288,7 +2457,7 @@ link_intrastage_shaders(void *mem_ctx, 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). @@ -2318,6 +2487,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. @@ -2326,34 +2498,32 @@ link_intrastage_shaders(void *mem_ctx, v.run(linked->ir); v.fixup_unnamed_interface_types(); - if (!prog->data->cache_fallback) { - /* Link up uniform blocks defined within this stage. */ - link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks, - &num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks); + /* Link up uniform blocks defined within this stage. */ + link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks, + &num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks); - if (!prog->data->LinkStatus) { - _mesa_delete_linked_shader(ctx, linked); - return NULL; - } + if (!prog->data->LinkStatus) { + _mesa_delete_linked_shader(ctx, linked); + return NULL; + } - /* Copy ubo blocks to linked shader list */ - linked->Program->sh.UniformBlocks = - ralloc_array(linked, gl_uniform_block *, num_ubo_blocks); - ralloc_steal(linked, ubo_blocks); - for (unsigned i = 0; i < num_ubo_blocks; i++) { - linked->Program->sh.UniformBlocks[i] = &ubo_blocks[i]; - } - linked->Program->info.num_ubos = num_ubo_blocks; - - /* Copy ssbo blocks to linked shader list */ - linked->Program->sh.ShaderStorageBlocks = - ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks); - ralloc_steal(linked, ssbo_blocks); - for (unsigned i = 0; i < num_ssbo_blocks; i++) { - linked->Program->sh.ShaderStorageBlocks[i] = &ssbo_blocks[i]; - } - linked->Program->info.num_ssbos = num_ssbo_blocks; + /* Copy ubo blocks to linked shader list */ + linked->Program->sh.UniformBlocks = + ralloc_array(linked, gl_uniform_block *, num_ubo_blocks); + ralloc_steal(linked, ubo_blocks); + for (unsigned i = 0; i < num_ubo_blocks; i++) { + linked->Program->sh.UniformBlocks[i] = &ubo_blocks[i]; } + linked->Program->info.num_ubos = num_ubo_blocks; + + /* Copy ssbo blocks to linked shader list */ + linked->Program->sh.ShaderStorageBlocks = + ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks); + ralloc_steal(linked, ssbo_blocks); + for (unsigned i = 0; i < num_ssbo_blocks; i++) { + linked->Program->sh.ShaderStorageBlocks[i] = &ssbo_blocks[i]; + } + linked->Program->info.num_ssbos = num_ssbo_blocks; /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. @@ -2509,7 +2679,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. */ @@ -2520,20 +2690,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); } } } @@ -2571,25 +2729,32 @@ 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 + * Assign locations for either VS inputs or FS outputs. * - * \param mem_ctx Temporary ralloc context used for linking - * \param prog Shader program whose variables need locations assigned - * \param constants Driver specific constant values for the program. - * \param target_index Selector for the program target to receive location - * assignmnets. Must be either \c MESA_SHADER_VERTEX or - * \c MESA_SHADER_FRAGMENT. + * \param mem_ctx Temporary ralloc context used for linking. + * \param prog Shader program whose variables need locations + * assigned. + * \param constants Driver specific constant values for the program. + * \param target_index Selector for the program target to receive location + * assignmnets. Must be either \c MESA_SHADER_VERTEX or + * \c MESA_SHADER_FRAGMENT. + * \param do_assignment Whether we are actually marking the assignment or we + * are just doing a dry-run checking. * * \return - * If locations are successfully assigned, true is returned. Otherwise an - * error is emitted to the shader link log and false is returned. + * If locations are (or can be, in case of dry-running) successfully assigned, + * true is returned. Otherwise an error is emitted to the shader link log and + * false is returned. */ static bool assign_attribute_or_color_locations(void *mem_ctx, gl_shader_program *prog, struct gl_constants *constants, - unsigned target_index) + unsigned target_index, + bool do_assignment) { /* Maximum number of generic locations. This corresponds to either the * maximum number of draw buffers or the maximum number of generic @@ -2601,8 +2766,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) @@ -2953,10 +3117,13 @@ assign_attribute_or_color_locations(void *mem_ctx, num_attr++; } + if (!do_assignment) + return true; + 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 ", @@ -3019,8 +3186,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 ", @@ -3057,6 +3224,12 @@ match_explicit_outputs_to_inputs(gl_linked_shader *producer, const unsigned idx = var->data.location - VARYING_SLOT_VAR0; if (explicit_locations[idx][var->data.location_frac] == NULL) explicit_locations[idx][var->data.location_frac] = var; + + /* Always match TCS outputs. They are shared by all invocations + * within a patch and can be used as shared memory. + */ + if (producer->Stage == MESA_SHADER_TESS_CTRL) + var->data.is_unmatched_generic_inout = 0; } } @@ -3508,139 +3681,12 @@ 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; } -static bool -should_add_buffer_variable(struct gl_shader_program *shProg, - GLenum type, const char *name) -{ - bool found_interface = false; - unsigned block_name_len = 0; - const char *block_name_dot = strchr(name, '.'); - - /* These rules only apply to buffer variables. So we return - * true for the rest of types. - */ - if (type != GL_BUFFER_VARIABLE) - return true; - - for (unsigned i = 0; i < shProg->data->NumShaderStorageBlocks; i++) { - const char *block_name = shProg->data->ShaderStorageBlocks[i].Name; - block_name_len = strlen(block_name); - - const char *block_square_bracket = strchr(block_name, '['); - if (block_square_bracket) { - /* The block is part of an array of named interfaces, - * for the name comparison we ignore the "[x]" part. - */ - block_name_len -= strlen(block_square_bracket); - } - - if (block_name_dot) { - /* Check if the variable name starts with the interface - * name. The interface name (if present) should have the - * length than the interface block name we are comparing to. - */ - unsigned len = strlen(name) - strlen(block_name_dot); - if (len != block_name_len) - continue; - } - - if (strncmp(block_name, name, block_name_len) == 0) { - found_interface = true; - break; - } - } - - /* We remove the interface name from the buffer variable name, - * including the dot that follows it. - */ - if (found_interface) - name = name + block_name_len + 1; - - /* The ARB_program_interface_query spec says: - * - * "For an active shader storage block member declared as an array, an - * entry will be generated only for the first array element, regardless - * of its type. For arrays of aggregate types, the enumeration rules - * are applied recursively for the single enumerated array element." - */ - const char *struct_first_dot = strchr(name, '.'); - const char *first_square_bracket = strchr(name, '['); - - /* The buffer variable is on top level and it is not an array */ - if (!first_square_bracket) { - return true; - /* The shader storage block member is a struct, then generate the entry */ - } else if (struct_first_dot && struct_first_dot < first_square_bracket) { - return true; - } else { - /* Shader storage block member is an array, only generate an entry for the - * first array element. - */ - if (strncmp(first_square_bracket, "[0]", 3) == 0) - return true; - } - - 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. * @@ -3812,6 +3858,7 @@ 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(); @@ -3874,7 +3921,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); @@ -3882,6 +3929,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: * @@ -3896,12 +3980,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, @@ -3958,7 +4056,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; @@ -3996,7 +4095,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; } } @@ -4022,7 +4122,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; } } @@ -4138,7 +4239,7 @@ get_array_size(struct gl_uniform_storage *uni, const glsl_struct_field *field, static int get_array_stride(struct gl_context *ctx, struct gl_uniform_storage *uni, - const glsl_type *interface, const glsl_struct_field *field, + const glsl_type *iface, const glsl_struct_field *field, char *interface_name, char *var_name) { /* The ARB_program_interface_query spec says: @@ -4164,9 +4265,9 @@ get_array_stride(struct gl_context *ctx, struct gl_uniform_storage *uni, return 0; if (GLSL_INTERFACE_PACKING_STD140 == - interface-> + iface-> get_internal_ifc_packing(ctx->Const.UseSTD430AsDefaultPacking)) { - if (array_type->is_record() || array_type->is_array()) + if (array_type->is_struct() || array_type->is_array()) return glsl_align(array_type->std140_size(row_major), 16); else return MAX2(array_type->std140_base_alignment(row_major), 16); @@ -4218,17 +4319,17 @@ calculate_array_size_and_stride(struct gl_context *ctx, 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(ctx, 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; @@ -4275,9 +4376,7 @@ build_program_resource_list(struct gl_context *ctx, if (input_stage == MESA_SHADER_STAGES && output_stage == 0) return; - struct set *resource_set = _mesa_set_create(NULL, - _mesa_hash_pointer, - _mesa_key_pointer_equal); + struct set *resource_set = _mesa_pointer_set_create(NULL); /* Program interface needs to expose varyings in case of SSO. */ if (shProg->SeparateShader) { @@ -4309,9 +4408,9 @@ build_program_resource_list(struct gl_context *ctx, /* 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)) + if (!link_util_add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_VARYING, + &linked_xfb->Varyings[i], 0)) return; } } @@ -4320,14 +4419,19 @@ build_program_resource_list(struct gl_context *ctx, 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)) + if (!link_util_add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_BUFFER, + &linked_xfb->Buffers[i], 0)) return; } } } + int top_level_array_base_offset = -1; + int top_level_array_size_in_bytes = -1; + int second_element_offset = -1; + int buffer_block_index = -1; + /* Add uniforms from uniform storage. */ for (unsigned i = 0; i < shProg->data->NumUniformStorage; i++) { /* Do not add uniforms internally used by Mesa. */ @@ -4349,38 +4453,73 @@ build_program_resource_list(struct gl_context *ctx, } GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM; - if (!should_add_buffer_variable(shProg, type, - shProg->data->UniformStorage[i].name)) + if (!link_util_should_add_buffer_variable(shProg, + &shProg->data->UniformStorage[i], + top_level_array_base_offset, + top_level_array_size_in_bytes, + second_element_offset, + buffer_block_index)) continue; if (is_shader_storage) { calculate_array_size_and_stride(ctx, shProg, &shProg->data->UniformStorage[i]); + + /* From the OpenGL 4.6 specification, 7.3.1.1 Naming Active Resources: + * + * "For an active shader storage block member declared as an array + * of an aggregate type, an entry will be generated only for the + * first array element, regardless of its type. Such block members + * are referred to as top-level arrays. If the block member is an + * aggregate type, the enumeration rules are then applied + * recursively." + * + * Below we update our tracking values used by + * link_util_should_add_buffer_variable(). We only want to reset the + * offsets once we have moved past the first element. + */ + if (shProg->data->UniformStorage[i].offset >= second_element_offset) { + top_level_array_base_offset = + shProg->data->UniformStorage[i].offset; + + top_level_array_size_in_bytes = + shProg->data->UniformStorage[i].top_level_array_size * + shProg->data->UniformStorage[i].top_level_array_stride; + + /* Set or reset the second element offset. For non arrays this + * will be set to -1. + */ + second_element_offset = top_level_array_size_in_bytes ? + top_level_array_base_offset + + shProg->data->UniformStorage[i].top_level_array_stride : -1; + } + + buffer_block_index = shProg->data->UniformStorage[i].block_index; } - 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; } @@ -4396,8 +4535,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; } } @@ -4409,8 +4548,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; } } @@ -4517,6 +4656,44 @@ link_assign_subroutine_types(struct gl_shader_program *prog) } } +static void +verify_subroutine_associated_funcs(struct gl_shader_program *prog) +{ + unsigned mask = prog->data->linked_stages; + while (mask) { + const int i = u_bit_scan(&mask); + gl_program *p = prog->_LinkedShaders[i]->Program; + glsl_symbol_table *symbols = prog->_LinkedShaders[i]->symbols; + + /* Section 6.1.2 (Subroutines) of the GLSL 4.00 spec says: + * + * "A program will fail to compile or link if any shader + * or stage contains two or more functions with the same + * name if the name is associated with a subroutine type." + */ + for (unsigned j = 0; j < p->sh.NumSubroutineFunctions; j++) { + unsigned definitions = 0; + char *name = p->sh.SubroutineFunctions[j].name; + ir_function *fn = symbols->get_function(name); + + /* Calculate number of function definitions with the same name */ + foreach_in_list(ir_function_signature, sig, &fn->signatures) { + if (sig->is_defined) { + if (++definitions > 1) { + linker_error(prog, "%s shader contains two or more function " + "definitions with name `%s', which is " + "associated with a subroutine type.\n", + _mesa_shader_stage_to_string(i), + fn->name); + return; + } + } + } + } + } +} + + static void set_always_active_io(exec_list *ir, ir_variable_mode io_mode) { @@ -4588,14 +4765,12 @@ link_and_validate_uniforms(struct gl_context *ctx, update_array_sizes(prog); link_assign_uniform_locations(prog, ctx); - if (!prog->data->cache_fallback) { - link_assign_atomic_counter_resources(ctx, prog); - link_calculate_subroutine_compat(prog); - check_resources(ctx, prog); - check_subroutine_resources(prog); - check_image_resources(ctx, prog); - link_check_atomic_counter_resources(ctx, prog); - } + link_assign_atomic_counter_resources(ctx, prog); + link_calculate_subroutine_compat(prog); + check_resources(ctx, prog); + check_subroutine_resources(prog); + check_image_resources(ctx, prog); + link_check_atomic_counter_resources(ctx, prog); } static bool @@ -4621,12 +4796,12 @@ link_varyings_and_uniforms(unsigned first, unsigned last, } if (!assign_attribute_or_color_locations(mem_ctx, prog, &ctx->Const, - MESA_SHADER_VERTEX)) { + MESA_SHADER_VERTEX, true)) { return false; } if (!assign_attribute_or_color_locations(mem_ctx, prog, &ctx->Const, - MESA_SHADER_FRAGMENT)) { + MESA_SHADER_FRAGMENT, true)) { return false; } @@ -4690,7 +4865,7 @@ linker_optimisation_loop(struct gl_context *ctx, exec_list *ir, void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { - prog->data->LinkStatus = linking_success; /* 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: @@ -4713,16 +4888,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } #ifdef ENABLE_SHADER_CACHE - /* If transform feedback used on the program then compile all shaders. */ - bool skip_cache = false; - if (prog->TransformFeedback.NumVarying > 0) { - for (unsigned i = 0; i < prog->NumShaders; i++) { - _mesa_glsl_compile_shader(ctx, prog->Shaders[i], false, false, true); - } - skip_cache = true; - } - - if (!skip_cache && shader_cache_read_program_metadata(ctx, prog)) + if (shader_cache_read_program_metadata(ctx, prog)) return; #endif @@ -4747,7 +4913,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; @@ -4765,7 +4932,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; @@ -4891,7 +5059,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * 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; @@ -4909,10 +5077,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) last = i; } - if (!prog->data->cache_fallback) { - check_explicit_uniform_locations(ctx, prog); - link_assign_subroutine_types(prog); - } + check_explicit_uniform_locations(ctx, prog); + link_assign_subroutine_types(prog); + verify_subroutine_associated_funcs(prog); if (!prog->data->LinkStatus) goto done; @@ -4941,6 +5108,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prev = i; } + /* The cross validation of outputs/inputs above validates interstage + * explicit locations. 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. + */ + validate_first_and_last_interface_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) @@ -4951,6 +5127,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. @@ -4967,15 +5149,13 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->SeparateShader) disable_varying_optimizations_for_sso(prog); - if (!prog->data->cache_fallback) { - /* Process UBOs */ - if (!interstage_cross_validate_uniform_blocks(prog, false)) - goto done; + /* Process UBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, false)) + goto done; - /* Process SSBOs */ - if (!interstage_cross_validate_uniform_blocks(prog, true)) - goto done; - } + /* Process SSBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, true)) + goto done; /* Do common optimization before assigning storage for attributes, * uniforms, and varyings. Later optimization could possibly make @@ -4997,16 +5177,36 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_tess_level(prog->_LinkedShaders[i]); } + /* Section 13.46 (Vertex Attribute Aliasing) of the OpenGL ES 3.2 + * specification says: + * + * "In general, the behavior of GLSL ES should not depend on compiler + * optimizations which might be implementation-dependent. Name matching + * rules in most languages, including C++ from which GLSL ES is derived, + * are based on declarations rather than use. + * + * RESOLUTION: The existence of aliasing is determined by declarations + * present after preprocessing." + * + * Because of this rule, we do a 'dry-run' of attribute assignment for + * vertex shader inputs here. + */ + if (prog->IsES && i == MESA_SHADER_VERTEX) { + if (!assign_attribute_or_color_locations(mem_ctx, prog, &ctx->Const, + MESA_SHADER_VERTEX, false)) { + goto done; + } + } + /* 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)) + if (ctx->Const.GLSLLowerConstArrays && + lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i)) linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); - - propagate_invariance(prog->_LinkedShaders[i]->ir); } /* Validation for special cases where we allow sampler array indexing @@ -5027,6 +5227,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