ac/nir/nggc: Refactor save_reusable_variables.
This makes the code more elegant and also fixes the mistake of
skipping the blocks that come before loops.
Fossil DB changes on Sienna Cichlid with NGGC on:
Totals from 1026 (0.80% of 128647) affected shaders:
SpillSGPRs: 3817 -> 4035 (+5.71%)
CodeSize: 5582856 -> 5538732 (-0.79%); split: -0.89%, +0.10%
Instrs: 1106907 -> 1100180 (-0.61%); split: -0.68%, +0.07%
Latency: 10084948 -> 10052197 (-0.32%); split: -0.37%, +0.05%
InvThroughput: 1567012 -> 1564949 (-0.13%); split: -0.16%, +0.03%
SClause: 39789 -> 39075 (-1.79%); split: -2.33%, +0.54%
Copies: 95184 -> 96456 (+1.34%); split: -0.19%, +1.53%
Branches: 44087 -> 44093 (+0.01%); split: -0.01%, +0.02%
PreSGPRs: 47584 -> 51009 (+7.20%); split: -0.61%, +7.80%
Fixes: 0bb543bb60
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13001>
This commit is contained in:
parent
70842e2206
commit
cb19ebe7ba
|
@ -850,31 +850,24 @@ save_reusable_variables(nir_builder *b, lower_ngg_nogs_state *nogs_state)
|
||||||
ASSERTED int vec_ok = u_vector_init(&nogs_state->saved_uniforms, sizeof(saved_uniform), 4 * sizeof(saved_uniform));
|
ASSERTED int vec_ok = u_vector_init(&nogs_state->saved_uniforms, sizeof(saved_uniform), 4 * sizeof(saved_uniform));
|
||||||
assert(vec_ok);
|
assert(vec_ok);
|
||||||
|
|
||||||
unsigned loop_depth = 0;
|
nir_block *block = nir_start_block(b->impl);
|
||||||
|
while (block) {
|
||||||
nir_foreach_block_safe(block, b->impl) {
|
/* Process the instructions in the current block. */
|
||||||
/* Check whether we're in a loop. */
|
|
||||||
nir_cf_node *next_cf_node = nir_cf_node_next(&block->cf_node);
|
|
||||||
nir_cf_node *prev_cf_node = nir_cf_node_prev(&block->cf_node);
|
|
||||||
if (next_cf_node && next_cf_node->type == nir_cf_node_loop)
|
|
||||||
loop_depth++;
|
|
||||||
if (prev_cf_node && prev_cf_node->type == nir_cf_node_loop)
|
|
||||||
loop_depth--;
|
|
||||||
|
|
||||||
/* The following code doesn't make sense in loops, so just skip it then. */
|
|
||||||
if (loop_depth)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
nir_foreach_instr_safe(instr, block) {
|
nir_foreach_instr_safe(instr, block) {
|
||||||
/* Find instructions whose SSA definitions are used by both
|
/* Find instructions whose SSA definitions are used by both
|
||||||
* the top and bottom parts of the shader. In this case, it
|
* the top and bottom parts of the shader (before and after culling).
|
||||||
* makes sense to try to reuse these from the top part.
|
* Only in this case, it makes sense for the bottom part
|
||||||
|
* to try to reuse these from the top part.
|
||||||
*/
|
*/
|
||||||
if ((instr->pass_flags & nggc_passflag_used_by_both) != nggc_passflag_used_by_both)
|
if ((instr->pass_flags & nggc_passflag_used_by_both) != nggc_passflag_used_by_both)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Determine if we can reuse the current SSA value.
|
||||||
|
* When vertex compaction is used, it is possible that the same shader invocation
|
||||||
|
* processes a different vertex in the top and bottom part of the shader.
|
||||||
|
* Therefore, we only reuse uniform values.
|
||||||
|
*/
|
||||||
nir_ssa_def *ssa = NULL;
|
nir_ssa_def *ssa = NULL;
|
||||||
|
|
||||||
switch (instr->type) {
|
switch (instr->type) {
|
||||||
case nir_instr_type_alu: {
|
case nir_instr_type_alu: {
|
||||||
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
||||||
|
@ -908,6 +901,7 @@ save_reusable_variables(nir_builder *b, lower_ngg_nogs_state *nogs_state)
|
||||||
|
|
||||||
assert(ssa);
|
assert(ssa);
|
||||||
|
|
||||||
|
/* Determine a suitable type for the SSA value. */
|
||||||
enum glsl_base_type base_type = GLSL_TYPE_UINT;
|
enum glsl_base_type base_type = GLSL_TYPE_UINT;
|
||||||
switch (ssa->bit_size) {
|
switch (ssa->bit_size) {
|
||||||
case 8: base_type = GLSL_TYPE_UINT8; break;
|
case 8: base_type = GLSL_TYPE_UINT8; break;
|
||||||
|
@ -924,6 +918,10 @@ save_reusable_variables(nir_builder *b, lower_ngg_nogs_state *nogs_state)
|
||||||
saved_uniform *saved = (saved_uniform *) u_vector_add(&nogs_state->saved_uniforms);
|
saved_uniform *saved = (saved_uniform *) u_vector_add(&nogs_state->saved_uniforms);
|
||||||
assert(saved);
|
assert(saved);
|
||||||
|
|
||||||
|
/* Create a new NIR variable where we store the reusable value.
|
||||||
|
* Then, we reload the variable and replace the uses of the value
|
||||||
|
* with the reloaded variable.
|
||||||
|
*/
|
||||||
saved->var = nir_local_variable_create(b->impl, t, NULL);
|
saved->var = nir_local_variable_create(b->impl, t, NULL);
|
||||||
saved->ssa = ssa;
|
saved->ssa = ssa;
|
||||||
|
|
||||||
|
@ -934,6 +932,19 @@ save_reusable_variables(nir_builder *b, lower_ngg_nogs_state *nogs_state)
|
||||||
nir_ssa_def *reloaded = nir_load_var(b, saved->var);
|
nir_ssa_def *reloaded = nir_load_var(b, saved->var);
|
||||||
nir_ssa_def_rewrite_uses_after(ssa, reloaded, reloaded->parent_instr);
|
nir_ssa_def_rewrite_uses_after(ssa, reloaded, reloaded->parent_instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look at the next CF node. */
|
||||||
|
nir_cf_node *next_cf_node = nir_cf_node_next(&block->cf_node);
|
||||||
|
if (next_cf_node) {
|
||||||
|
/* It makes no sense to try to reuse things from within loops. */
|
||||||
|
if (next_cf_node->type == nir_cf_node_loop) {
|
||||||
|
block = nir_cf_node_cf_tree_next(next_cf_node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go to the next block. */
|
||||||
|
block = nir_block_cf_tree_next(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue