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 <[email protected]> Cc: Kenneth Graunke <[email protected]> --- 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 _______________________________________________ mesa-dev mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-dev
