summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-09-08 21:12:11 -0700
committerJason Ekstrand <[email protected]>2016-11-28 16:45:08 -0800
commitd6cef320477354f1c139c0bb7fb9b68731aa15cd (patch)
tree61376d62aaffb5d3201edeab45d0d7f306849177
parent0a5e1b02cf6103037b488db5daa3097fbcfcf670 (diff)
intel/aubinator: Properly handle batch buffer chaining
The original aubinator that Kristian wrote had a bug in the handling of MI_BATCH_BUFFER_START that propagated into the version in upstream mesa. In particular, it ignored the "2nd level" bit which tells you whether this MI_BATCH_BUFFER_START is a subroutine call (2nd level) or a goto. Since the Vulkan driver uses batch chaining, this can lead to a very confusing interpretation of the batches. In some cases, depending on how things are laid out in the virtual GTT, you can even end up with infinite loops in batch processing. Reviewed-by: Kristian H. Kristensen <[email protected]>
-rw-r--r--src/intel/tools/aubinator.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c
index 0d4b3f944f4..78682c571c7 100644
--- a/src/intel/tools/aubinator.c
+++ b/src/intel/tools/aubinator.c
@@ -790,7 +790,25 @@ parse_commands(struct gen_spec *spec, uint32_t *cmds, int size, int engine)
else
start = p[1];
- parse_commands(spec, gtt + start, 1 << 20, engine);
+ if (p[0] & (1 << 22)) {
+ /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts
+ * like a subroutine call. Commands that come afterwards get
+ * processed once the 2nd level batch buffer returns with
+ * MI_BATCH_BUFFER_END.
+ */
+ parse_commands(spec, gtt + start, gtt_end - start, engine);
+ } else {
+ /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts
+ * like a goto. Nothing after it will ever get processed. In
+ * order to prevent the recursion from growing, we just reset the
+ * loop and continue;
+ */
+ p = gtt + start;
+ /* We don't know where secondaries end so use the GTT end */
+ end = gtt + gtt_end;
+ length = 0;
+ continue;
+ }
} else if ((p[0] & 0xffff0000) == AUB_MI_BATCH_BUFFER_END) {
break;
}