}
static void
-update_xfb_info(struct gl_transform_feedback_info *xfb_info)
+update_xfb_info(struct gl_transform_feedback_info *xfb_info,
+ struct shader_info *info)
{
if (!xfb_info)
return;
output->ComponentOffset = 3;
break;
}
+
+ info->outputs_written |= 1ull << output->OutputRegister;
}
}
prog->ShadowSamplers = shader->shadow_samplers;
_mesa_update_shader_textures_used(shProg, prog);
- update_xfb_info(prog->sh.LinkedTransformFeedback);
-
bool debug_enabled =
(INTEL_DEBUG & intel_debug_flag_for_shader_stage(shader->Stage));
prog->nir = brw_create_nir(brw, shProg, prog, (gl_shader_stage) stage,
compiler->scalar_stage[stage]);
+ }
+
+ /* Determine first and last stage. */
+ unsigned first = MESA_SHADER_STAGES;
+ unsigned last = 0;
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (!shProg->_LinkedShaders[i])
+ continue;
+ if (first == MESA_SHADER_STAGES)
+ first = i;
+ last = i;
+ }
+
+ /* Linking the stages in the opposite order (from fragment to vertex)
+ * ensures that inter-shader outputs written to in an earlier stage
+ * are eliminated if they are (transitively) not used in a later
+ * stage.
+ */
+ if (first != last) {
+ int next = last;
+ for (int i = next - 1; i >= 0; i--) {
+ if (shProg->_LinkedShaders[i] == NULL)
+ continue;
+
+ nir_shader *producer = shProg->_LinkedShaders[i]->Program->nir;
+ nir_shader *consumer = shProg->_LinkedShaders[next]->Program->nir;
+
+ nir_remove_dead_variables(producer, nir_var_shader_out);
+ nir_remove_dead_variables(consumer, nir_var_shader_in);
+
+ if (nir_remove_unused_varyings(producer, consumer)) {
+ nir_lower_global_vars_to_local(producer);
+ nir_lower_global_vars_to_local(consumer);
+
+ nir_variable_mode indirect_mask = (nir_variable_mode) 0;
+ if (compiler->glsl_compiler_options[i].EmitNoIndirectTemp)
+ indirect_mask = (nir_variable_mode) nir_var_local;
+
+ /* The backend might not be able to handle indirects on
+ * temporaries so we need to lower indirects on any of the
+ * varyings we have demoted here.
+ */
+ nir_lower_indirect_derefs(producer, indirect_mask);
+ nir_lower_indirect_derefs(consumer, indirect_mask);
+
+ const bool p_is_scalar = compiler->scalar_stage[producer->stage];
+ shProg->_LinkedShaders[i]->Program->nir =
+ brw_nir_optimize(producer, compiler, p_is_scalar);
+
+ const bool c_is_scalar = compiler->scalar_stage[producer->stage];
+ shProg->_LinkedShaders[next]->Program->nir =
+ brw_nir_optimize(consumer, compiler, c_is_scalar);
+ }
+
+ next = i;
+ }
+ }
+
+ for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) {
+ struct gl_linked_shader *shader = shProg->_LinkedShaders[stage];
+ if (!shader)
+ continue;
+
+ struct gl_program *prog = shader->Program;
+ nir_shader *nir = shader->Program->nir;
+ brw_shader_gather_info(nir, prog);
+
+ NIR_PASS_V(nir, nir_lower_samplers, shProg);
+ NIR_PASS_V(nir, nir_lower_atomics, shProg);
+
infos[stage] = &prog->nir->info;
+ update_xfb_info(prog->sh.LinkedTransformFeedback, infos[stage]);
+
/* Make a pass over the IR to add state references for any built-in
* uniforms that are used. This has to be done now (during linking).
* Code generation doesn't happen until the first time this shader is