ralloc_vasprintf_append(&prog->data->InfoLog, fmt, ap);
va_end(ap);
- prog->data->LinkStatus = linking_failure;
+ prog->data->LinkStatus = LINKING_FAILURE;
}
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 (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);
}
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 "
* 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);
}
_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;
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).
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.
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;
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.
*/
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);
}
}
}
}
+#define SAFE_MASK_FROM_INDEX(i) (((i) >= 32) ? ~0 : ((1 << (i)) - 1))
+
/**
* Assign locations for either VS inputs or FS outputs
*
/* 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)
if (target_index == MESA_SHADER_VERTEX) {
unsigned total_attribs_size =
- _mesa_bitcount(used_locations & ((1 << max_index) - 1)) +
+ _mesa_bitcount(used_locations & SAFE_MASK_FROM_INDEX(max_index)) +
_mesa_bitcount(double_storage_locations);
if (total_attribs_size > max_index) {
linker_error(prog,
*/
if (target_index == MESA_SHADER_VERTEX) {
unsigned total_attribs_size =
- _mesa_bitcount(used_locations & ((1 << max_index) - 1)) +
+ _mesa_bitcount(used_locations & SAFE_MASK_FROM_INDEX(max_index)) +
_mesa_bitcount(double_storage_locations);
if (total_attribs_size > max_index) {
linker_error(prog,
return true;
prog->data->ProgramResourceList =
- reralloc(prog,
+ reralloc(prog->data,
prog->data->ProgramResourceList,
gl_program_resource,
prog->data->NumProgramResourceList + 1);
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();
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);
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:
*
}
}
+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,
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;
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;
}
}
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;
}
}
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
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:
}
#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
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);
if (!prog->data->LinkStatus)
goto done;
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)
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
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