[Mesa-dev] [PATCH 05/70] i965: Move the pipelined test for SO register access to the screen
Chris Wilson
chris at chris-wilson.co.uk
Fri Aug 7 13:13:09 PDT 2015
Moving the test to the screen places it alongside the other global HW
feature tesst that want to be shared between contexts.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Kenneth Graunke <kenneth at whitecape.org>
---
src/mesa/drivers/dri/i965/brw_context.c | 2 +
src/mesa/drivers/dri/i965/intel_extensions.c | 69 ---------------------
src/mesa/drivers/dri/i965/intel_screen.c | 92 ++++++++++++++++++++++++++++
src/mesa/drivers/dri/i965/intel_screen.h | 8 +++
4 files changed, 102 insertions(+), 69 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index ac744d7..e8d1396 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -728,6 +728,8 @@ brwCreateContext(gl_api api,
brw->must_use_separate_stencil = screen->hw_must_use_separate_stencil;
brw->has_swizzling = screen->hw_has_swizzling;
+ brw->has_pipelined_so =
+ screen->hw_has_pipelined_register & HW_HAS_PIPELINED_SOL_OFFSET;
brw->vs.base.stage = MESA_SHADER_VERTEX;
brw->gs.base.stage = MESA_SHADER_GEOMETRY;
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index bf8fdae..6346fbc 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -32,74 +32,6 @@
#include "intel_reg.h"
#include "utils.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)
-{
- /* Supposedly, Broadwell just works. */
- if (brw->gen >= 8)
- 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;
-}
-
static bool
can_write_oacontrol(struct brw_context *brw)
{
@@ -328,7 +260,6 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.ARB_texture_compression_bptc = true;
ctx->Extensions.ARB_texture_view = true;
- brw->has_pipelined_so = can_do_pipelined_register_writes(brw);
if (brw->has_pipelined_so) {
ctx->Extensions.ARB_draw_indirect = true;
ctx->Extensions.ARB_transform_feedback2 = true;
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index 61f1dbe..0a64d2b 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1186,6 +1186,96 @@ intel_detect_timestamp(struct intel_screen *screen)
}
/**
+ * 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.
*/
@@ -1444,6 +1534,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen);
intelScreen->hw_has_timestamp = intel_detect_timestamp(intelScreen);
+ if (intel_detect_pipelined_so(intelScreen))
+ intelScreen->hw_has_pipelined_register |= HW_HAS_PIPELINED_SOL_OFFSET;
const char *force_msaa = getenv("INTEL_FORCE_MSAA");
if (force_msaa) {
diff --git a/src/mesa/drivers/dri/i965/intel_screen.h b/src/mesa/drivers/dri/i965/intel_screen.h
index 76179fc..7890706 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.h
+++ b/src/mesa/drivers/dri/i965/intel_screen.h
@@ -64,6 +64,14 @@ struct intel_screen
*/
bool has_context_reset_notification : 1;
+ /**
+ * 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;
drm_intel_bo *workaround_bo;
--
2.5.0
More information about the mesa-dev
mailing list