[Mesa-dev] [PATCH v2 9/8+1] i965: Enable ARB_transform_feedback2 on Gen7+ if register writes work.

Kenneth Graunke kenneth at whitecape.org
Sat Oct 26 08:59:29 CEST 2013


With Linux 3.12, register writes work on Ivybridge and Baytrail, but not
Haswell.  That will be fixed in a future kernel revision, at which point
this extension will automatically be enabled.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/mesa/drivers/dri/i965/intel_extensions.c | 61 +++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

Tested on Ivybridge (extension is on) and Haswell (extension is off).
So the register write testing is working as expected.

diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index 22e4aa2..0c6ed02 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -28,11 +28,68 @@
 #include "main/version.h"
 
 #include "brw_context.h"
-#include "intel_chipset.h"
+#include "intel_batchbuffer.h"
 #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)
+{
+   /* 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->batch.workaround_bo, false);
+   data = brw->batch.workaround_bo->virtual;
+   data[offset] = 0xffffffff;
+   drm_intel_bo_unmap(brw->batch.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();
+
+   intel_batchbuffer_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->batch.workaround_bo,
+             I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
+             offset * sizeof(uint32_t));
+   ADVANCE_BATCH();
+
+   intel_batchbuffer_flush(brw);
+
+   /* Check whether the value got written. */
+   drm_intel_bo_map(brw->batch.workaround_bo, false);
+   bool success = data[offset] == expected_value;
+   drm_intel_bo_unmap(brw->batch.workaround_bo);
+
+   return success;
+}
+
+/**
  * Initializes potential list of extensions if ctx == NULL, or actually enables
  * extensions for a context.
  */
@@ -171,6 +228,8 @@ intelInitExtensions(struct gl_context *ctx)
    if (brw->gen >= 7) {
       ctx->Extensions.ARB_texture_gather = true;
       ctx->Extensions.ARB_conservative_depth = true;
+      if (can_do_pipelined_register_writes(brw))
+         ctx->Extensions.ARB_transform_feedback2 = true;
    }
 
    if (ctx->API == API_OPENGL_CORE)
-- 
1.8.3.2



More information about the mesa-dev mailing list