From: Kenneth Graunke Date: Mon, 27 May 2013 00:53:14 +0000 (-0700) Subject: i965: Implement Pause/ResumeTransformfeedback driver hooks on Gen7+. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=684958d1e7415267e8276654390ea610eefaa95f;p=mesa.git i965: Implement Pause/ResumeTransformfeedback driver hooks on Gen7+. The ARB_transform_feedback2 extension introduces the ability to pause and resume transform feedback sessions. Although only one can be active at a time, it's possible to switch between multiple transform feedback objects while paused. In order to facilitate this, we need to save/restore the SO_WRITE_OFFSET registers so that after resuming, the GPU continues writing where it left off. This functionality also exists in ES 3.0, but somehow we completely forgot to implement it. v2: Reduce alignment from 4096 to 64 (it seemed excessive). v3: Use I915_GEM_DOMAIN_INSTRUCTION instead of RENDER, for consistency with other writes. It shouldn't matter on IVB+. Signed-off-by: Kenneth Graunke Reviewed-by: Ian Romanick Reviewed-by: Eric Anholt --- diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 2df12ed423d..90d9be449c1 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -255,6 +255,8 @@ brw_init_driver_functions(struct brw_context *brw, if (brw->gen >= 7) { functions->BeginTransformFeedback = gen7_begin_transform_feedback; functions->EndTransformFeedback = gen7_end_transform_feedback; + functions->PauseTransformFeedback = gen7_pause_transform_feedback; + functions->ResumeTransformFeedback = gen7_resume_transform_feedback; } else { functions->BeginTransformFeedback = brw_begin_transform_feedback; functions->EndTransformFeedback = brw_end_transform_feedback; diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 19d846de0a0..23c27d825bc 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -889,6 +889,9 @@ struct intel_batchbuffer { struct brw_transform_feedback_object { struct gl_transform_feedback_object base; + + /** A buffer to hold SO_WRITE_OFFSET(n) values while paused. */ + drm_intel_bo *offset_bo; }; /** @@ -1597,6 +1600,12 @@ gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode, void gen7_end_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj); +void +gen7_pause_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj); +void +gen7_resume_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj); /* brw_blorp_blit.cpp */ GLbitfield diff --git a/src/mesa/drivers/dri/i965/gen6_sol.c b/src/mesa/drivers/dri/i965/gen6_sol.c index 484be42b390..cbc95f4b51a 100644 --- a/src/mesa/drivers/dri/i965/gen6_sol.c +++ b/src/mesa/drivers/dri/i965/gen6_sol.c @@ -144,6 +144,9 @@ brw_new_transform_feedback(struct gl_context *ctx, GLuint name) _mesa_init_transform_feedback_object(&brw_obj->base, name); + brw_obj->offset_bo = + drm_intel_bo_alloc(brw->bufmgr, "transform feedback offsets", 16, 64); + return &brw_obj->base; } @@ -158,6 +161,8 @@ brw_delete_transform_feedback(struct gl_context *ctx, _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL); } + drm_intel_bo_unreference(brw_obj->offset_bo); + free(brw_obj); } diff --git a/src/mesa/drivers/dri/i965/gen7_sol_state.c b/src/mesa/drivers/dri/i965/gen7_sol_state.c index abfe0a0746d..bdb17e3b81d 100644 --- a/src/mesa/drivers/dri/i965/gen7_sol_state.c +++ b/src/mesa/drivers/dri/i965/gen7_sol_state.c @@ -273,3 +273,43 @@ gen7_end_transform_feedback(struct gl_context *ctx, intel_batchbuffer_emit_mi_flush(brw); } + +void +gen7_pause_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct brw_context *brw = brw_context(ctx); + struct brw_transform_feedback_object *brw_obj = + (struct brw_transform_feedback_object *) obj; + + /* Save the SOL buffer offset register values. */ + for (int i = 0; i < 4; i++) { + BEGIN_BATCH(3); + OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2)); + OUT_BATCH(GEN7_SO_WRITE_OFFSET(i)); + OUT_RELOC(brw_obj->offset_bo, + I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, + i * sizeof(uint32_t)); + ADVANCE_BATCH(); + } +} + +void +gen7_resume_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct brw_context *brw = brw_context(ctx); + struct brw_transform_feedback_object *brw_obj = + (struct brw_transform_feedback_object *) obj; + + /* Reload the SOL buffer offset registers. */ + for (int i = 0; i < 4; i++) { + BEGIN_BATCH(3); + OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2)); + OUT_BATCH(GEN7_SO_WRITE_OFFSET(i)); + OUT_RELOC(brw_obj->offset_bo, + I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, + i * sizeof(uint32_t)); + ADVANCE_BATCH(); + } +}