nir: Flatten ifs with discards in nir_opt_peephole_select for HW without CF.
i915g and r300-r400 don't have if statements, and discards are all nir_intrinsic_discard_if. We can flatten those discards here, saving a separate GLSL pass to try to do so. i915g: GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS rv370: GAINED: shaders/closed/xcom-enemy-unknown/12.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/122.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/132.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/145.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/146.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/19.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS GAINED: shaders/closed/xcom-enemy-unknown/415.shader_test FS Closes: #9918 Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24763>
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "nir/nir_builder.h"
|
||||
#include "nir.h"
|
||||
#include "nir_builder.h"
|
||||
#include "nir_control_flow.h"
|
||||
#include "nir_search_helpers.h"
|
||||
|
||||
@@ -74,10 +75,21 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count,
|
||||
case nir_instr_type_tex:
|
||||
break;
|
||||
|
||||
case nir_instr_type_intrinsic:
|
||||
if (!nir_intrinsic_can_reorder(nir_instr_as_intrinsic(instr)))
|
||||
return false;
|
||||
case nir_instr_type_intrinsic: {
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
switch (intr->intrinsic) {
|
||||
case nir_intrinsic_discard:
|
||||
case nir_intrinsic_discard_if:
|
||||
/* For non-CF hardware, we need to be able to move discards up
|
||||
* and flatten, so let them pass.
|
||||
*/
|
||||
continue;
|
||||
default:
|
||||
if (!nir_intrinsic_can_reorder(intr))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
@@ -362,6 +374,32 @@ nir_opt_collapse_if(nir_if *if_stmt, nir_shader *shader, unsigned limit,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we're moving discards out of the if for non-CF hardware, we need to add
|
||||
* the if's condition to it
|
||||
*/
|
||||
static void
|
||||
rewrite_discard_conds(nir_instr *instr, nir_def *if_cond, bool is_else)
|
||||
{
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
return;
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
|
||||
if (intr->intrinsic != nir_intrinsic_discard_if && intr->intrinsic != nir_intrinsic_discard)
|
||||
return;
|
||||
|
||||
nir_builder b = nir_builder_at(nir_before_instr(instr));
|
||||
|
||||
if (is_else)
|
||||
if_cond = nir_inot(&b, if_cond);
|
||||
|
||||
if (intr->intrinsic == nir_intrinsic_discard_if) {
|
||||
nir_src_rewrite(&intr->src[0], nir_iand(&b, intr->src[0].ssa, if_cond));
|
||||
} else {
|
||||
nir_discard_if(&b, if_cond);
|
||||
nir_instr_remove(instr);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
|
||||
unsigned limit, bool indirect_load_ok,
|
||||
@@ -434,12 +472,14 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
|
||||
exec_node_remove(&instr->node);
|
||||
instr->block = prev_block;
|
||||
exec_list_push_tail(&prev_block->instr_list, &instr->node);
|
||||
rewrite_discard_conds(instr, if_stmt->condition.ssa, false);
|
||||
}
|
||||
|
||||
nir_foreach_instr_safe(instr, else_block) {
|
||||
exec_node_remove(&instr->node);
|
||||
instr->block = prev_block;
|
||||
exec_list_push_tail(&prev_block->instr_list, &instr->node);
|
||||
rewrite_discard_conds(instr, if_stmt->condition.ssa, true);
|
||||
}
|
||||
|
||||
nir_foreach_phi_safe(phi, block) {
|
||||
|
Reference in New Issue
Block a user