i965: Enable the AMD_performance_monitor extension on Gen5+.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 13 Nov 2013 23:42:57 +0000 (15:42 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Nov 2013 23:01:14 +0000 (15:01 -0800)
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/intel_extensions.c

index 62c0b15..065cd00 100644 (file)
@@ -89,6 +89,64 @@ can_do_pipelined_register_writes(struct brw_context *brw)
    return success;
 }
 
+static bool
+can_write_oacontrol(struct brw_context *brw)
+{
+   if (brw->gen < 6 || brw->gen >= 8)
+      return false;
+
+   /* Set "Select Context ID" to a particular address (which is likely not a
+    * context), but leave all counting disabled.  This should be harmless.
+    */
+   const int expected_value = 0x31337000;
+   const int offset = 110;
+
+   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, true);
+   data = brw->batch.workaround_bo->virtual;
+   data[offset] = 0xffffffff;
+   drm_intel_bo_unmap(brw->batch.workaround_bo);
+
+   /* Write OACONTROL. */
+   BEGIN_BATCH(3);
+   OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
+   OUT_BATCH(OACONTROL);
+   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(OACONTROL);
+   OUT_RELOC(brw->batch.workaround_bo,
+             I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+             offset * sizeof(uint32_t));
+   ADVANCE_BATCH();
+
+   intel_batchbuffer_emit_mi_flush(brw);
+
+   /* Set OACONTROL back to zero (everything off). */
+   BEGIN_BATCH(3);
+   OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
+   OUT_BATCH(OACONTROL);
+   OUT_BATCH(0);
+   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.
@@ -234,6 +292,9 @@ intelInitExtensions(struct gl_context *ctx)
       }
    }
 
+   if (brw->gen == 5 || can_write_oacontrol(brw))
+      ctx->Extensions.AMD_performance_monitor = true;
+
    if (ctx->API == API_OPENGL_CORE)
       ctx->Extensions.ARB_base_instance = true;
    if (ctx->API != API_OPENGL_CORE)