return false;
}
- const unsigned slots = var->type->count_attribute_slots();
+ const unsigned slots = var->type->count_attribute_slots(target_index == MESA_SHADER_VERTEX ? true : false);
/* If the variable is not a built-in and has a location statically
* assigned in the shader (presumably via a layout qualifier), make sure
* issue (3) of the GL_ARB_vertex_attrib_64bit behavior, this
* is optional behavior, but it seems preferable.
*/
- const glsl_type *type = var->type->without_array();
- if (type == glsl_type::dvec3_type ||
- type == glsl_type::dvec4_type ||
- type == glsl_type::dmat2x3_type ||
- type == glsl_type::dmat2x4_type ||
- type == glsl_type::dmat3_type ||
- type == glsl_type::dmat3x4_type ||
- type == glsl_type::dmat4x3_type ||
- type == glsl_type::dmat4_type) {
+ if (var->type->without_array()->is_dual_slot_double())
double_storage_locations |= (use_mask << attr);
- }
}
continue;
* Match explicit locations of outputs to inputs and deactivate the
* unmatch flag if found so we don't optimise them away.
*/
-void
+static void
match_explicit_outputs_to_inputs(struct gl_shader_program *prog,
gl_shader *producer,
gl_shader *consumer)
if ((var == NULL) || (var->data.mode != ir_var_shader_out))
continue;
- /* Mark output as matched if separate shader with no linked consumer */
- if (consumer == NULL)
- var->data.is_unmatched_generic_inout = 0;
-
if (var->data.explicit_location &&
var->data.location >= VARYING_SLOT_VAR0) {
const unsigned idx = var->data.location - VARYING_SLOT_VAR0;
if ((input == NULL) || (input->data.mode != ir_var_shader_in))
continue;
- /* Mark input as matched if separate shader with no linked producer */
- if (producer == NULL)
- input->data.is_unmatched_generic_inout = 0;
-
ir_variable *output = NULL;
if (input->data.explicit_location
&& input->data.location >= VARYING_SLOT_VAR0) {
foreach_in_list(ir_instruction, node, sh->ir) {
ir_variable *var = node->as_variable();
if (var && var->data.mode == ir_var_shader_out)
- fragment_outputs += var->type->count_attribute_slots();
+ /* since there are no double fs outputs - pass false */
+ fragment_outputs += var->type->count_attribute_slots(false);
}
}
}
assert(*num_ubos + *num_ssbos == num_blocks);
}
+static void
+set_always_active_io(exec_list *ir, ir_variable_mode io_mode)
+{
+ assert(io_mode == ir_var_shader_in || io_mode == ir_var_shader_out);
+
+ foreach_in_list(ir_instruction, node, ir) {
+ ir_variable *const var = node->as_variable();
+
+ if (var == NULL || var->data.mode != io_mode)
+ continue;
+
+ /* Don't set always active on builtins that haven't been redeclared */
+ if (var->data.how_declared == ir_var_declared_implicitly)
+ continue;
+
+ var->data.always_active_io = true;
+ }
+}
+
+/**
+ * When separate shader programs are enabled, only input/outputs between
+ * the stages of a multi-stage separate program can be safely removed
+ * from the shader interface. Other inputs/outputs must remain active.
+ */
+static void
+disable_varying_optimizations_for_sso(struct gl_shader_program *prog)
+{
+ unsigned first, last;
+ assert(prog->SeparateShader);
+
+ first = MESA_SHADER_STAGES;
+ last = 0;
+
+ /* Determine first and last stage. Excluding the compute stage */
+ for (unsigned i = 0; i < MESA_SHADER_COMPUTE; i++) {
+ if (!prog->_LinkedShaders[i])
+ continue;
+ if (first == MESA_SHADER_STAGES)
+ first = i;
+ last = i;
+ }
+
+ if (first == MESA_SHADER_STAGES)
+ return;
+
+ for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+ gl_shader *sh = prog->_LinkedShaders[stage];
+ 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);
+ }
+ }
+}
+
void
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
{
}
}
+ if (prog->SeparateShader)
+ disable_varying_optimizations_for_sso(prog);
+
if (!interstage_cross_validate_uniform_blocks(prog))
goto done;
if (first < MESA_SHADER_FRAGMENT) {
gl_shader *const sh = prog->_LinkedShaders[last];
- if (first == MESA_SHADER_GEOMETRY) {
+ if (first != MESA_SHADER_VERTEX) {
/* There was no vertex shader, but we still have to assign varying
- * locations for use by geometry shader inputs in SSO.
+ * locations for use by tessellation/geometry shader inputs in SSO.
*
* If the shader is not separable (i.e., prog->SeparateShader is
- * false), linking will have already failed when first is
- * MESA_SHADER_GEOMETRY.
+ * false), linking will have already failed when first is not
+ * MESA_SHADER_VERTEX.
*/
if (!assign_varying_locations(ctx, mem_ctx, prog,
NULL, prog->_LinkedShaders[first],
if (ctx->Const.ShaderCompilerOptions[i].LowerBufferInterfaceBlocks)
lower_ubo_reference(prog->_LinkedShaders[i]);
+ if (ctx->Const.ShaderCompilerOptions[i].LowerShaderSharedVariables)
+ lower_shared_reference(prog->_LinkedShaders[i],
+ &prog->Comp.SharedSize);
+
lower_vector_derefs(prog->_LinkedShaders[i]);
}