summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-09-15 21:12:34 -0700
committerEmil Velikov <[email protected]>2016-11-08 16:23:14 +0000
commit4e1298be040a7a25441ba108a697736143135160 (patch)
tree23158aa227c8fd839d59d63b330be2c427d90a5e /src/compiler
parent17429a22a6026dc6601fc8e9ae4f0daecb30079a (diff)
nir/spirv/cfg: Use a nop intrinsic for tagging the ends of blocks
Previously, we were saving off the last nir_block in a vtn_block before moving on so that we could find the nir_block again when it came time to handle phi sources. Unfortunately, NIR's control flow modification code is inconsistent when it comes to how it splits blocks so the block pointer we saved off may point to a block somewhere else in the shader by the time we get around to handling phi sources. In order to get around this, we insert a nop instruction and use that as the logical end of our block. Since the control flow manipulation code respects instructions, the nop will keeps its place like any other instruction and we can easily find the end of our block when we need it. This fixes a bug triggered by a couple of vkQuake shaders. Signed-off-by: Jason Ekstrand <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97233 Cc: "12.0" <[email protected]> Tested-by: Dave Airlie <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> (cherry picked from commit 6ffbfc760da14fc710a05438b9fd9eff034128da)
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/spirv/vtn_cfg.c6
-rw-r--r--src/compiler/spirv/vtn_private.h4
2 files changed, 6 insertions, 4 deletions
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index 1c8c4f8e108..62b9056990e 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -531,7 +531,7 @@ vtn_handle_phi_second_pass(struct vtn_builder *b, SpvOp opcode,
struct vtn_block *pred =
vtn_value(b, w[i + 1], vtn_value_type_block)->block;
- b->nb.cursor = nir_after_block_before_jump(pred->end_block);
+ b->nb.cursor = nir_after_instr(&pred->end_nop->instr);
vtn_local_store(b, src, nir_deref_var_create(b, phi_var));
}
@@ -589,7 +589,9 @@ vtn_emit_cf_list(struct vtn_builder *b, struct list_head *cf_list,
vtn_foreach_instruction(b, block_start, block_end, handler);
- block->end_block = nir_cursor_current_block(b->nb.cursor);
+ block->end_nop = nir_intrinsic_instr_create(b->nb.shader,
+ nir_intrinsic_nop);
+ nir_builder_instr_insert(&b->nb, &block->end_nop->instr);
if ((*block->branch & SpvOpCodeMask) == SpvOpReturnValue) {
struct vtn_ssa_value *src = vtn_ssa_value(b, block->branch[1]);
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index 7f5444ee875..6f34f09ebd2 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -149,8 +149,8 @@ struct vtn_block {
/** Points to the switch case started by this block (if any) */
struct vtn_case *switch_case;
- /** The last block in this SPIR-V block. */
- nir_block *end_block;
+ /** Every block ends in a nop intrinsic so that we can find it again */
+ nir_intrinsic_instr *end_nop;
};
struct vtn_function {