diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 77dace6a01f62751dec6c94b5a5cbe91b94d590a..5f4d5893e98356ff8b657a3a3048858d8ba15fab 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -781,6 +781,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_RELAXED_DELTA: value = 1; break; + case I915_PARAM_HAS_GEN7_SOL_RESET: + value = 1; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 11545ff90db646b16a42f6cdc382733229f5d2e2..c01cb20184970e16e85f2ed3d4738deac7d5eff2 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -970,6 +970,31 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, } } +static int +i915_reset_gen7_sol_offsets(struct drm_device *dev, + struct intel_ring_buffer *ring) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int ret, i; + + if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) + return 0; + + ret = intel_ring_begin(ring, 4 * 3); + if (ret) + return ret; + + for (i = 0; i < 4; i++) { + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i)); + intel_ring_emit(ring, 0); + } + + intel_ring_advance(ring); + + return 0; +} + static int i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_file *file, @@ -1184,6 +1209,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, dev_priv->relative_constants_mode = mode; } + if (args->flags & I915_EXEC_GEN7_SOL_RESET) { + ret = i915_reset_gen7_sol_offsets(dev, ring); + if (ret) + goto err; + } + trace_i915_gem_ring_dispatch(ring, seqno); exec_start = batch_obj->gtt_offset + args->batch_start_offset; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index edced95aa75f9c1efb62860b42b687a6a328547b..c3afb783cb9d93bf7c79dd32a18d8627ed6bfd0d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3736,4 +3736,10 @@ #define CPT_AUD_CNTL_ST_A 0xE50B4 #define CPT_AUD_CNTRL_ST2 0xE50C0 +/* These are the 4 32-bit write offset registers for each stream + * output buffer. It determines the offset from the + * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. + */ +#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4) + #endif /* _I915_REG_H_ */ diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 1b4da1a9ec0f6d653cd8e4500e124e418ed78b46..924f6a454fed97d9b84dbbbbdfc32751b82759db 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -295,6 +295,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_COHERENT_RINGS 13 #define I915_PARAM_HAS_EXEC_CONSTANTS 14 #define I915_PARAM_HAS_RELAXED_DELTA 15 +#define I915_PARAM_HAS_GEN7_SOL_RESET 16 typedef struct drm_i915_getparam { int param; @@ -657,6 +658,9 @@ struct drm_i915_gem_execbuffer2 { __u64 rsvd2; }; +/** Resets the SO write offset registers for transform feedback on gen7. */ +#define I915_EXEC_GEN7_SOL_RESET (1<<8) + struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ __u32 handle;