[Mesa-dev] [PATCH v2 1/4] i965: Move the pipelined test for SO register access to the screen
Iago Toral Quiroga
itoral at igalia.com
Wed Jan 4 12:26:20 UTC 2017
From: Chris Wilson <chris at chris-wilson.co.uk>
Moving the test to the screen places it alongside the other global HW
feature tests that want to be shared between contexts.
Also, we need to know if we support pipelined register writes at
screen creation time so that we can tell if we can expose OpenGL 4.0
in gen7.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
src/mesa/drivers/dri/i965/brw_context.c | 2 +
src/mesa/drivers/dri/i965/intel_extensions.c | 73 ----------------------
src/mesa/drivers/dri/i965/intel_screen.c | 93 ++++++++++++++++++++++++++++
src/mesa/drivers/dri/i965/intel_screen.h | 8 +++
4 files changed, 103 insertions(+), 73 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 3f3da7d..6b390b7 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -983,6 +983,8 @@ brwCreateContext(gl_api api,
brw->must_use_separate_stencil = devinfo->must_use_separate_stencil;
brw->has_swizzling = screen->hw_has_swizzling;
+ brw->can_do_pipelined_register_writes =
+ screen->hw_has_pipelined_register & HW_HAS_PIPELINED_SOL_OFFSET;
isl_device_init(&brw->isl_dev, devinfo, screen->hw_has_swizzling);
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index 1ecefc1..17fbc37 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -30,77 +30,6 @@
#include "intel_batchbuffer.h"
/**
- * Test if we can use MI_LOAD_REGISTER_MEM from an untrusted batchbuffer.
- *
- * Some combinations of hardware and kernel versions allow this feature,
- * while others don't. Instead of trying to enumerate every case, just
- * try and write a register and see if works.
- */
-static bool
-can_do_pipelined_register_writes(struct brw_context *brw)
-{
- /**
- * gen >= 8 specifically allows these writes. gen <= 6 also
- * doesn't block them.
- */
- if (brw->gen != 7)
- return true;
-
- static int result = -1;
- if (result != -1)
- return result;
-
- /* We use SO_WRITE_OFFSET0 since you're supposed to write it (unlike the
- * statistics registers), and we already reset it to zero before using it.
- */
- const int reg = GEN7_SO_WRITE_OFFSET(0);
- const int expected_value = 0x1337d0d0;
- const int offset = 100;
-
- /* The register we picked only exists on Gen7+. */
- assert(brw->gen == 7);
-
- uint32_t *data;
- /* Set a value in a BO to a known quantity. The workaround BO already
- * exists and doesn't contain anything important, so we may as well use it.
- */
- drm_intel_bo_map(brw->workaround_bo, true);
- data = brw->workaround_bo->virtual;
- data[offset] = 0xffffffff;
- drm_intel_bo_unmap(brw->workaround_bo);
-
- /* Write the register. */
- BEGIN_BATCH(3);
- OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
- OUT_BATCH(reg);
- OUT_BATCH(expected_value);
- ADVANCE_BATCH();
-
- brw_emit_mi_flush(brw);
-
- /* Save the register's value back to the buffer. */
- BEGIN_BATCH(3);
- OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2));
- OUT_BATCH(reg);
- OUT_RELOC(brw->workaround_bo,
- I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
- offset * sizeof(uint32_t));
- ADVANCE_BATCH();
-
- intel_batchbuffer_flush(brw);
-
- /* Check whether the value got written. */
- drm_intel_bo_map(brw->workaround_bo, false);
- data = brw->workaround_bo->virtual;
- bool success = data[offset] == expected_value;
- drm_intel_bo_unmap(brw->workaround_bo);
-
- result = success;
-
- return success;
-}
-
-/**
* Initializes potential list of extensions if ctx == NULL, or actually enables
* extensions for a context.
*/
@@ -267,8 +196,6 @@ intelInitExtensions(struct gl_context *ctx)
}
brw->predicate.supported = false;
- brw->can_do_pipelined_register_writes =
- can_do_pipelined_register_writes(brw);
if (brw->gen >= 7) {
ctx->Extensions.ARB_conservative_depth = true;
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index d0e3ac6..758a328 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1271,6 +1271,96 @@ intel_detect_timestamp(struct intel_screen *screen)
return 0;
}
+ /**
+ * Test if we can use MI_LOAD_REGISTER_MEM from an untrusted batchbuffer.
+ *
+ * Some combinations of hardware and kernel versions allow this feature,
+ * while others don't. Instead of trying to enumerate every case, just
+ * try and write a register and see if works.
+ */
+static bool
+intel_detect_pipelined_register(struct intel_screen *screen,
+ int reg, uint32_t expected_value, bool reset)
+{
+ drm_intel_bo *results, *bo;
+ uint32_t *batch;
+ uint32_t offset = 0;
+ bool success = false;
+
+ /* Create a zero'ed temporary buffer for reading our results */
+ results = drm_intel_bo_alloc(screen->bufmgr, "registers", 4096, 0);
+ if (results == NULL)
+ goto err;
+
+ bo = drm_intel_bo_alloc(screen->bufmgr, "batchbuffer", 4096, 0);
+ if (bo == NULL)
+ goto err_results;
+
+ if (drm_intel_bo_map(bo, 1))
+ goto err_batch;
+
+ batch = bo->virtual;
+
+ /* Write the register. */
+ *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+ *batch++ = reg;
+ *batch++ = expected_value;
+
+ /* Save the register's value back to the buffer. */
+ *batch++ = MI_STORE_REGISTER_MEM | (3 - 2);
+ *batch++ = reg;
+ drm_intel_bo_emit_reloc(bo, (char *)batch -(char *)bo->virtual,
+ results, offset*sizeof(uint32_t),
+ I915_GEM_DOMAIN_INSTRUCTION,
+ I915_GEM_DOMAIN_INSTRUCTION);
+ *batch++ = results->offset + offset*sizeof(uint32_t);
+
+ /* And afterwards clear the register */
+ if (reset) {
+ *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+ *batch++ = reg;
+ *batch++ = 0;
+ }
+
+ *batch++ = MI_BATCH_BUFFER_END;
+
+ drm_intel_bo_mrb_exec(bo, ALIGN((char *)batch - (char *)bo->virtual, 8),
+ NULL, 0, 0,
+ I915_EXEC_RENDER);
+
+ /* Check whether the value got written. */
+ if (drm_intel_bo_map(results, false) == 0) {
+ success = *((uint32_t *)results->virtual + offset) == expected_value;
+ drm_intel_bo_unmap(results);
+ }
+
+err_batch:
+ drm_intel_bo_unreference(bo);
+err_results:
+ drm_intel_bo_unreference(results);
+err:
+ return success;
+}
+
+static bool
+intel_detect_pipelined_so(struct intel_screen *screen)
+{
+ /* Supposedly, Broadwell just works. */
+ if (screen->devinfo.gen >= 8)
+ return true;
+
+ if (screen->devinfo.gen <= 6)
+ return false;
+
+ /* We use SO_WRITE_OFFSET0 since you're supposed to write it (unlike the
+ * statistics registers), and we already reset it to zero before using it.
+ */
+ return intel_detect_pipelined_register(screen,
+ GEN7_SO_WRITE_OFFSET(0),
+ 0x1337d0d0,
+ false);
+}
+
/**
* Return array of MSAA modes supported by the hardware. The array is
* zero-terminated and sorted in decreasing order.
@@ -1643,6 +1733,9 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
screen->subslice_total = 1 << (screen->devinfo.gt - 1);
}
+ if (intel_detect_pipelined_so(screen))
+ screen->hw_has_pipelined_register |= HW_HAS_PIPELINED_SOL_OFFSET;
+
const char *force_msaa = getenv("INTEL_FORCE_MSAA");
if (force_msaa) {
screen->winsys_msaa_samples_override =
diff --git a/src/mesa/drivers/dri/i965/intel_screen.h b/src/mesa/drivers/dri/i965/intel_screen.h
index 51c1d4e..62fde03 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.h
+++ b/src/mesa/drivers/dri/i965/intel_screen.h
@@ -68,6 +68,14 @@ struct intel_screen
*/
bool has_context_reset_notification;
+ /**
+ * Does the kernel support pipelined register access?
+ * Due to whitelisting we need to do seperate checks
+ * for each register.
+ */
+ unsigned hw_has_pipelined_register;
+#define HW_HAS_PIPELINED_SOL_OFFSET (1<<0)
+
dri_bufmgr *bufmgr;
/**
--
2.7.4
More information about the mesa-dev
mailing list