tests/gem_pipe_control_store_loop: Add subtest for reused buffers

This exercises the slightly faulty kernel w/a that Eric fixed in

commit e844b990b1df9242bb91b7d490552f3198946838
Author: Eric Anholt <eric@anholt.net>
Date:   Tue Jul 31 15:35:01 2012 -0700

    drm/i915: Don't forget to apply SNB PIPE_CONTROL GTT workaround.

    If a buffer that was the target of a PIPE_CONTROL from userland was a
    reused one that hadn't been evicted which had not previously had this
    workaround applied, then the early return for a correct
    presumed_offset in this function meant we would not bind it into the
    GTT and the write would land somewhere else.

    Fixes reproducible failures with GL_EXT_timer_query usage in apitrace,
    and I also expect it to fix the intermittent OQ issues on snb that
    danvet's been working on.

    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=48019
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=52932
    Signed-off-by: Eric Anholt <eric@anholt.net>
    Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
    Reviewed-by: Carl Worth <cworth@cworth.org>
    Tested-by: Carl Worth <cworth@cworth.org>
    Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Daniel Vetter 2013-09-04 14:08:10 +02:00
parent 0550092c9a
commit 52221651ab

View File

@ -63,7 +63,7 @@ uint32_t devid;
/* Like the store dword test, but we create new command buffers each time */ /* Like the store dword test, but we create new command buffers each time */
static void static void
store_pipe_control_loop(void) store_pipe_control_loop(bool preuse_buffer)
{ {
int i, val = 0; int i, val = 0;
uint32_t *buf; uint32_t *buf;
@ -78,6 +78,29 @@ store_pipe_control_loop(void)
igt_fail(-1); igt_fail(-1);
} }
if (preuse_buffer) {
BEGIN_BATCH(6);
OUT_BATCH(XY_COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
OUT_BATCH((3 << 24) | (0xf0 << 16) | 64);
OUT_BATCH(0);
OUT_BATCH(1 << 16 | 1);
/*
* IMPORTANT: We need to preuse the buffer in a
* different domain than what the pipe control write
* (and kernel wa) uses!
*/
OUT_RELOC(target_bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
OUT_BATCH(0xdeadbeef);
ADVANCE_BATCH();
intel_batchbuffer_flush(batch);
igt_assert(target_bo->offset != 0);
} else
igt_assert(target_bo->offset == 0);
/* gem_storedw_batches_loop.c is a bit overenthusiastic with /* gem_storedw_batches_loop.c is a bit overenthusiastic with
* creating new batchbuffers - with buffer reuse disabled, the * creating new batchbuffers - with buffer reuse disabled, the
* support code will do that for us. */ * support code will do that for us. */
@ -118,66 +141,54 @@ store_pipe_control_loop(void)
drm_intel_bo_map(target_bo, 1); drm_intel_bo_map(target_bo, 1);
buf = target_bo->virtual; buf = target_bo->virtual;
if (buf[0] != val) { igt_assert(buf[0] == val);
fprintf(stderr,
"value mismatch: cur 0x%08x, stored 0x%08x\n",
buf[0], val);
igt_fail(-1);
}
buf[0] = 0; /* let batch write it again */
drm_intel_bo_unmap(target_bo);
drm_intel_bo_unmap(target_bo);
/* Make doublesure that this buffer won't get reused. */
drm_intel_bo_disable_reuse(target_bo);
drm_intel_bo_unreference(target_bo); drm_intel_bo_unreference(target_bo);
val++; val++;
} }
printf("completed %d writes successfully\n", i);
} }
int fd;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int fd; igt_subtest_init(argc, argv);
if (argc != 1) {
fprintf(stderr, "usage: %s\n", argv[0]);
igt_fail(-1);
}
igt_fixture {
fd = drm_open_any(); fd = drm_open_any();
devid = intel_get_drm_devid(fd); devid = intel_get_drm_devid(fd);
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
if (!bufmgr) { igt_assert(bufmgr);
fprintf(stderr, "failed to init libdrm\n");
igt_fail(-1); igt_skip_on(IS_GEN2(devid) || IS_GEN3(devid));
} igt_skip_on(devid == PCI_CHIP_I965_G); /* has totally broken pipe control */
if (IS_GEN2(devid) || IS_GEN3(devid)) {
fprintf(stderr, "no pipe_control on gen2/3\n");
return 77;
}
if (devid == PCI_CHIP_I965_G) {
fprintf(stderr, "pipe_control totally broken on i965\n");
return 77;
}
/* IMPORTANT: No call to /* IMPORTANT: No call to
* drm_intel_bufmgr_gem_enable_reuse(bufmgr); * drm_intel_bufmgr_gem_enable_reuse(bufmgr);
* here because we wan't to have fresh buffers (to trash the tlb) * here because we wan't to have fresh buffers (to trash the tlb)
* every time! */ * every time! */
batch = intel_batchbuffer_alloc(bufmgr, devid); batch = intel_batchbuffer_alloc(bufmgr, devid);
if (!batch) { igt_assert(batch);
fprintf(stderr, "failed to create batch buffer\n");
igt_fail(-1);
} }
store_pipe_control_loop(); igt_subtest("fresh-buffer")
store_pipe_control_loop(false);
igt_subtest("reused-buffer")
store_pipe_control_loop(true);
igt_fixture {
intel_batchbuffer_free(batch); intel_batchbuffer_free(batch);
drm_intel_bufmgr_destroy(bufmgr); drm_intel_bufmgr_destroy(bufmgr);
close(fd); close(fd);
}
return 0;
igt_exit();
} }