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 <ch...@chris-wilson.co.uk> Cc: Kenneth Graunke <kenn...@whitecape.org> --- src/mesa/drivers/dri/i965/brw_context.c | 2 + src/mesa/drivers/dri/i965/intel_extensions.c | 69 --------------------- src/mesa/drivers/dri/i965/intel_screen.c | 92 ++++++++++++++++++++++++++++ src/mesa/drivers/dri/i965/intel_screen.h | 8 +++ 4 files changed, 102 insertions(+), 69 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index ac744d7..e8d1396 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -728,6 +728,8 @@ 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_register & HW_HAS_PIPELINED_SOL_OFFSET; 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 bf8fdae..6346fbc 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) { @@ -328,7 +260,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 61f1dbe..0a64d2b 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -1186,6 +1186,96 @@ 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, bool reset) +{ + drm_intel_bo *results, *bo; + uint32_t *batch; + uint32_t offset = 0; + bool success = false; + + /* Create a zero'ed temporary buffer for reading our results */ + results = drm_intel_bo_alloc(screen->bufmgr, "registers", 4096, 0); + if (results == NULL) + goto err; + + bo = drm_intel_bo_alloc(screen->bufmgr, "batchbuffer", 4096, 0); + if (bo == NULL) + goto err_results; + + if (drm_intel_bo_map(bo, 1)) + goto err_batch; + + batch = bo->virtual; + + /* Write the register. */ + *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2); + *batch++ = reg; + *batch++ = expected_value; + + /* 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 *)bo->virtual, + results, offset*sizeof(uint32_t), + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION); + *batch++ = results->offset + offset*sizeof(uint32_t); + + /* And afterwards clear the register */ + if (reset) { + *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2); + *batch++ = reg; + *batch++ = 0; + } + + *batch++ = MI_BATCH_BUFFER_END; + + drm_intel_bo_mrb_exec(bo, ALIGN((char *)batch - (char *)bo->virtual, 8), + NULL, 0, 0, + I915_EXEC_RENDER); + + /* Check whether the value got written. */ + if (drm_intel_bo_map(results, false) == 0) { + success = *((uint32_t *)results->virtual + offset) == expected_value; + drm_intel_bo_unmap(results); + } + +err_batch: + drm_intel_bo_unreference(bo); +err_results: + drm_intel_bo_unreference(results); +err: + 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, + false); +} + +/** * Return array of MSAA modes supported by the hardware. The array is * zero-terminated and sorted in decreasing order. */ @@ -1444,6 +1534,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen); intelScreen->hw_has_timestamp = intel_detect_timestamp(intelScreen); + if (intel_detect_pipelined_so(intelScreen)) + intelScreen->hw_has_pipelined_register |= HW_HAS_PIPELINED_SOL_OFFSET; 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 76179fc..7890706 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.h +++ b/src/mesa/drivers/dri/i965/intel_screen.h @@ -64,6 +64,14 @@ struct intel_screen */ bool has_context_reset_notification : 1; + /** + * Does the kernel support pipelined register access? + * Due to whitelisting we need to do seperate checks + * for each register. + */ + unsigned hw_has_pipelined_register; +#define HW_HAS_PIPELINED_SOL_OFFSET (1<<0) + dri_bufmgr *bufmgr; drm_intel_bo *workaround_bo; -- 2.5.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev