summaryrefslogtreecommitdiffstats
path: root/src/glsl/nir/nir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/nir/nir.c')
-rw-r--r--src/glsl/nir/nir.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c
index 3157ff82d99..79df6d3df94 100644
--- a/src/glsl/nir/nir.c
+++ b/src/glsl/nir/nir.c
@@ -107,6 +107,10 @@ void
nir_shader_add_variable(nir_shader *shader, nir_variable *var)
{
switch (var->data.mode) {
+ case nir_var_all:
+ assert(!"invalid mode");
+ break;
+
case nir_var_local:
assert(!"nir_shader_add_variable cannot be used for local variables");
break;
@@ -312,6 +316,14 @@ nir_block_create(nir_shader *shader)
block->predecessors = _mesa_set_create(block, _mesa_hash_pointer,
_mesa_key_pointer_equal);
block->imm_dom = NULL;
+ /* XXX maybe it would be worth it to defer allocation? This
+ * way it doesn't get allocated for shader ref's that never run
+ * nir_calc_dominance? For example, state-tracker creates an
+ * initial IR, clones that, runs appropriate lowering pass, passes
+ * to driver which does common lowering/opt, and then stores ref
+ * which is later used to do state specific lowering and futher
+ * opt. Do any of the references not need dominance metadata?
+ */
block->dom_frontier = _mesa_set_create(block, _mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -1306,21 +1318,62 @@ nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src)
{
assert(!new_src.is_ssa || def != new_src.ssa);
- nir_foreach_use_safe(def, use_src) {
- nir_instr *src_parent_instr = use_src->parent_instr;
- list_del(&use_src->use_link);
- nir_src_copy(use_src, &new_src, src_parent_instr);
- src_add_all_uses(use_src, src_parent_instr, NULL);
- }
+ nir_foreach_use_safe(def, use_src)
+ nir_instr_rewrite_src(use_src->parent_instr, use_src, new_src);
+
+ nir_foreach_if_use_safe(def, use_src)
+ nir_if_rewrite_condition(use_src->parent_if, new_src);
+}
+
+static bool
+is_instr_between(nir_instr *start, nir_instr *end, nir_instr *between)
+{
+ assert(start->block == end->block);
+
+ if (between->block != start->block)
+ return false;
+
+ /* Search backwards looking for "between" */
+ while (start != end) {
+ if (between == end)
+ return true;
- nir_foreach_if_use_safe(def, use_src) {
- nir_if *src_parent_if = use_src->parent_if;
- list_del(&use_src->use_link);
- nir_src_copy(use_src, &new_src, src_parent_if);
- src_add_all_uses(use_src, NULL, src_parent_if);
+ end = nir_instr_prev(end);
+ assert(end);
}
+
+ return false;
}
+/* Replaces all uses of the given SSA def with the given source but only if
+ * the use comes after the after_me instruction. This can be useful if you
+ * are emitting code to fix up the result of some instruction: you can freely
+ * use the result in that code and then call rewrite_uses_after and pass the
+ * last fixup instruction as after_me and it will replace all of the uses you
+ * want without touching the fixup code.
+ *
+ * This function assumes that after_me is in the same block as
+ * def->parent_instr and that after_me comes after def->parent_instr.
+ */
+void
+nir_ssa_def_rewrite_uses_after(nir_ssa_def *def, nir_src new_src,
+ nir_instr *after_me)
+{
+ assert(!new_src.is_ssa || def != new_src.ssa);
+
+ nir_foreach_use_safe(def, use_src) {
+ assert(use_src->parent_instr != def->parent_instr);
+ /* Since def already dominates all of its uses, the only way a use can
+ * not be dominated by after_me is if it is between def and after_me in
+ * the instruction list.
+ */
+ if (!is_instr_between(def->parent_instr, after_me, use_src->parent_instr))
+ nir_instr_rewrite_src(use_src->parent_instr, use_src, new_src);
+ }
+
+ nir_foreach_if_use_safe(def, use_src)
+ nir_if_rewrite_condition(use_src->parent_if, new_src);
+}
static bool foreach_cf_node(nir_cf_node *node, nir_foreach_block_cb cb,
bool reverse, void *state);
@@ -1571,6 +1624,8 @@ nir_intrinsic_from_system_value(gl_system_value val)
return nir_intrinsic_load_tess_level_inner;
case SYSTEM_VALUE_VERTICES_IN:
return nir_intrinsic_load_patch_vertices_in;
+ case SYSTEM_VALUE_HELPER_INVOCATION:
+ return nir_intrinsic_load_helper_invocation;
default:
unreachable("system value does not directly correspond to intrinsic");
}
@@ -1614,6 +1669,8 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin)
return SYSTEM_VALUE_TESS_LEVEL_INNER;
case nir_intrinsic_load_patch_vertices_in:
return SYSTEM_VALUE_VERTICES_IN;
+ case nir_intrinsic_load_helper_invocation:
+ return SYSTEM_VALUE_HELPER_INVOCATION;
default:
unreachable("intrinsic doesn't produce a system value");
}