nir: add support for user defined select control
This will allow us to make use of the selection control support in spirv and the GL support provided by EXT_control_flow_attributes. Note this only supports if-statements as we dont support switches in NIR. Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108841
This commit is contained in:
@@ -365,6 +365,8 @@ nir_if_create(nir_shader *shader)
|
||||
{
|
||||
nir_if *if_stmt = ralloc(shader, nir_if);
|
||||
|
||||
if_stmt->control = nir_selection_control_none;
|
||||
|
||||
cf_init(&if_stmt->cf_node, nir_cf_node_if);
|
||||
src_init(&if_stmt->condition);
|
||||
|
||||
|
@@ -1902,9 +1902,16 @@ nir_block_ends_in_jump(nir_block *block)
|
||||
#define nir_foreach_instr_reverse_safe(instr, block) \
|
||||
foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
|
||||
|
||||
typedef enum {
|
||||
nir_selection_control_none = 0x0,
|
||||
nir_selection_control_flatten = 0x1,
|
||||
nir_selection_control_dont_flatten = 0x2,
|
||||
} nir_selection_control;
|
||||
|
||||
typedef struct nir_if {
|
||||
nir_cf_node cf_node;
|
||||
nir_src condition;
|
||||
nir_selection_control control;
|
||||
|
||||
struct exec_list then_list; /** < list of nir_cf_node */
|
||||
struct exec_list else_list; /** < list of nir_cf_node */
|
||||
|
@@ -537,6 +537,7 @@ static nir_if *
|
||||
clone_if(clone_state *state, struct exec_list *cf_list, const nir_if *i)
|
||||
{
|
||||
nir_if *ni = nir_if_create(state->ns);
|
||||
ni->control = i->control;
|
||||
|
||||
__clone_src(state, ni, &ni->condition, &i->condition);
|
||||
|
||||
|
@@ -191,6 +191,10 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
|
||||
return false;
|
||||
|
||||
nir_if *if_stmt = nir_cf_node_as_if(prev_node);
|
||||
|
||||
if (if_stmt->control == nir_selection_control_dont_flatten)
|
||||
return false;
|
||||
|
||||
nir_block *then_block = nir_if_first_then_block(if_stmt);
|
||||
nir_block *else_block = nir_if_first_else_block(if_stmt);
|
||||
|
||||
@@ -199,6 +203,12 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
|
||||
nir_if_last_else_block(if_stmt) != else_block)
|
||||
return false;
|
||||
|
||||
if (if_stmt->control == nir_selection_control_flatten) {
|
||||
/* Override driver defaults */
|
||||
indirect_load_ok = true;
|
||||
expensive_alu_ok = true;
|
||||
}
|
||||
|
||||
/* ... and those blocks must only contain "allowed" instructions. */
|
||||
unsigned count = 0;
|
||||
if (!block_check_for_allowed_instrs(then_block, &count, limit != 0,
|
||||
@@ -207,7 +217,7 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
|
||||
indirect_load_ok, expensive_alu_ok))
|
||||
return false;
|
||||
|
||||
if (count > limit)
|
||||
if (count > limit && if_stmt->control != nir_selection_control_flatten)
|
||||
return false;
|
||||
|
||||
/* At this point, we know that the previous CFG node is an if-then
|
||||
|
Reference in New Issue
Block a user