[Mesa-dev] [PATCH 3/5] i965: Move the pipelined test for SO register access to the screen

Chris Wilson chris at chris-wilson.co.uk
Wed Jul 8 06:48:40 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      |  1 +
 src/mesa/drivers/dri/i965/intel_extensions.c | 69 -------------------
 src/mesa/drivers/dri/i965/intel_screen.c     | 99 ++++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/intel_screen.h     |  7 ++
 4 files changed, 107 insertions(+), 69 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 3dac01b..705f042 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -728,6 +728,7 @@ 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_so;
 
    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 489a00f..1414015 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)
 {
@@ -327,7 +259,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 71f2957..9067399 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1157,6 +1157,104 @@ 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)
+{
+   const int offset = 100;
+
+   drm_intel_bo *bo;
+   uint32_t buf[100];
+   uint32_t *batch = buf;
+
+   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.
+    */
+   if (drm_intel_bo_map(screen->workaround_bo, true))
+      return false;
+
+   data = screen->workaround_bo->virtual;
+   data[offset] = 0xffffffff;
+   drm_intel_bo_unmap(screen->workaround_bo);
+
+   bo = drm_intel_bo_alloc(screen->bufmgr, "batchbuffer", 4096, 0);
+   if (bo == NULL)
+      return false;
+
+   /* Write the register. */
+   *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+   *batch++ = reg;
+   *batch++ = expected_value;
+
+   /* Force a command barrier between the write then read */
+   *batch++ = _3DSTATE_PIPE_CONTROL | (5 - 2);
+   *batch++ = PIPE_CONTROL_NO_WRITE | PIPE_CONTROL_CS_STALL;
+   *batch++ = 0;
+   *batch++ = 0;
+   *batch++ = 0;
+
+   /* 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 *)buf,
+                           screen->workaround_bo, offset*sizeof(uint32_t),
+                           I915_GEM_DOMAIN_INSTRUCTION,
+                           I915_GEM_DOMAIN_INSTRUCTION);
+   *batch++ = screen->workaround_bo->offset + offset*sizeof(uint32_t);
+
+   /* And afterwards clear the register */
+   *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+   *batch++ = reg;
+   *batch++ = 0;
+
+   *batch++ = MI_BATCH_BUFFER_END;
+   if ((batch - buf) & 1)
+      *batch++ = 0;
+
+   if (drm_intel_bo_subdata(bo, 0, (char *)batch - (char *)buf, buf) == 0)
+      drm_intel_bo_mrb_exec(bo, (char *)batch - (char *)buf,
+                            NULL, 0, 0,
+                            I915_EXEC_RENDER);
+
+   drm_intel_bo_unreference(bo);
+
+   /* Check whether the value got written. */
+   bool success = false;
+   if (drm_intel_bo_map(screen->workaround_bo, false) == 0) {
+      data = screen->workaround_bo->virtual;
+      success = data[offset] == expected_value;
+      drm_intel_bo_unmap(screen->workaround_bo);
+   }
+
+   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);
+}
+
+/**
  * Return array of MSAA modes supported by the hardware. The array is
  * zero-terminated and sorted in decreasing order.
  */
@@ -1415,6 +1513,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
 
    intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen);
    intelScreen->hw_has_timestamp = intel_detect_timestamp(intelScreen);
+   intelScreen->hw_has_pipelined_so = intel_detect_pipelined_so(intelScreen);
 
    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 e55fddb..e0577f7 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.h
+++ b/src/mesa/drivers/dri/i965/intel_screen.h
@@ -55,6 +55,13 @@ struct intel_screen
    bool hw_has_timestamp;
 
    /**
+    * Does the kernel support pipelined register access?
+    * Due to whitelisting we need to do seperate checks
+    * for each register.
+    */
+   bool hw_has_pipelined_so;
+
+   /**
     * Does the kernel support context reset notifications?
     */
    bool has_context_reset_notification;
-- 
2.1.4



More information about the mesa-dev mailing list