summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2016-07-26 13:19:46 -0700
committerKenneth Graunke <[email protected]>2016-07-29 16:05:24 -0700
commitebdc82d06532f992aea592265c29a11330e698fa (patch)
tree16e53a0aa2fc2d1abda460704dffc39faeb9e584 /src
parent591eeb7d1c98d85142453d6ba2b8128c9a5a554e (diff)
i965: Fix move_interpolation_to_top() pass.
The pass I introduced in commit a2dc11a7818c04d8dc0324e8fcba98d60bae was entirely broken. A missing "break" made the load_interpolated_input case always fall through to "default" and hit a "continue", making it not actually move any load_interpolated_input intrinsics at all. It would only move the simple load_barycentric_* intrinsics, which don't emit any code anyway, making it basically useless. The initial version I sent of the pass worked, but I apparently failed to verify that the simplified version in v2 actually worked. With the obvious fix applied (so we actually tried to move load_interpolated_input intrinsics), I discovered a second bug: we weren't moving the offset SSA def to the top, breaking SSA validation. The new version of the pass actually moves load_interpolated_input intrinsics and all their dependencies, as intended. Papers over GPU hangs on Ivybridge and Baytrail caused by the recent NIR FS input rework by restoring the old behavior. (I'm not honestly sure why they hang with PLN not at the top.) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97083 Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp50
1 files changed, 29 insertions, 21 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index f9af525875e..3309f61a06c 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -6353,38 +6353,46 @@ move_interpolation_to_top(nir_shader *nir)
continue;
nir_block *top = nir_start_block(f->impl);
+ exec_node *cursor_node = NULL;
nir_foreach_block(block, f->impl) {
if (block == top)
continue;
- nir_foreach_instr_reverse_safe(instr, block) {
+ nir_foreach_instr_safe(instr, block) {
if (instr->type != nir_instr_type_intrinsic)
continue;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_barycentric_pixel:
- case nir_intrinsic_load_barycentric_centroid:
- case nir_intrinsic_load_barycentric_sample:
- break;
- case nir_intrinsic_load_interpolated_input: {
- nir_intrinsic_instr *bary_intrinsic =
- nir_instr_as_intrinsic(intrin->src[0].ssa->parent_instr);
- nir_intrinsic_op op = bary_intrinsic->intrinsic;
-
- /* Leave interpolateAtSample/Offset() where it is. */
- if (op == nir_intrinsic_load_barycentric_at_sample ||
- op == nir_intrinsic_load_barycentric_at_offset)
- continue;
- }
- default:
+ if (intrin->intrinsic != nir_intrinsic_load_interpolated_input)
continue;
- }
+ nir_intrinsic_instr *bary_intrinsic =
+ nir_instr_as_intrinsic(intrin->src[0].ssa->parent_instr);
+ nir_intrinsic_op op = bary_intrinsic->intrinsic;
- exec_node_remove(&instr->node);
- exec_list_push_head(&top->instr_list, &instr->node);
- instr->block = top;
+ /* Leave interpolateAtSample/Offset() where they are. */
+ if (op == nir_intrinsic_load_barycentric_at_sample ||
+ op == nir_intrinsic_load_barycentric_at_offset)
+ continue;
+
+ nir_instr *move[3] = {
+ &bary_intrinsic->instr,
+ intrin->src[1].ssa->parent_instr,
+ instr
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(move); i++) {
+ if (move[i]->block != top) {
+ move[i]->block = top;
+ exec_node_remove(&move[i]->node);
+ if (cursor_node) {
+ exec_node_insert_after(cursor_node, &move[i]->node);
+ } else {
+ exec_list_push_head(&top->instr_list, &move[i]->node);
+ }
+ cursor_node = &move[i]->node;
+ }
+ }
}
}
nir_metadata_preserve(f->impl, (nir_metadata)