From 129da5b1c87e4fd45b117a092e5d022ad7041e66 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 27 May 2013 20:09:56 -0700 Subject: [PATCH] i965: Enable ARB_transform_feedback2 on Gen7+ if register writes work. 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. v2: Use I915_GEM_DOMAIN_INSTRUCTION for the register read, and also correctly set the writeable flag when mapping (caught by Eric). Signed-off-by: Kenneth Graunke Reviewed-by: Eric Anholt --- src/mesa/drivers/dri/i965/intel_extensions.c | 62 +++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c index 22e4aa2c5ad..337e7e87c4f 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, true); + 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_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->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,9 @@ 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) -- 2.11.0