drm/i915: Allow the application to choose the constant addressing mode
authorChris Wilson <chris@chris-wilson.co.uk>
Sun, 19 Dec 2010 11:42:05 +0000 (11:42 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 20 Dec 2010 09:41:36 +0000 (09:41 +0000)
The relative-to-general state default is useless as it means having to
rewrite the streaming kernels for each batch. Relative-to-surface is
more useful, as that stream usually needs to be rewritten for each
batch. And absolute addressing mode, vital if you start streaming
state, is also only available by adjusting the register...

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
include/drm/i915_drm.h

index 3f7b20392e26a5eb4a5c56dfe3cb32eeb0e4cada..18746e6cb1295ba067c9b2a4bb64ae7e9628e047 100644 (file)
@@ -778,6 +778,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_COHERENT_RINGS:
                value = 1;
                break;
+       case I915_PARAM_HAS_EXEC_CONSTANTS:
+               value = INTEL_INFO(dev)->gen >= 4;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
index 2a653cc803951eeb25e4bcc32be75a4867e4bf82..aac1bf332f75bc3dcf30b4955b8617ac1acfabc5 100644 (file)
@@ -258,6 +258,7 @@ typedef struct drm_i915_private {
        const struct intel_device_info *info;
 
        int has_gem;
+       int relative_constants_mode;
 
        void __iomem *regs;
 
index 5a0fbe59dd5b7850adf285c9ad1a73c79504897b..c79c0b62ef6057866d2622d8444532501b428ed9 100644 (file)
@@ -3735,6 +3735,8 @@ i915_gem_load(struct drm_device *dev)
                }
        }
 
+       dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
+
        /* Old X drivers will take 0-2 for front, back, depth buffers */
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                dev_priv->fence_reg_start = 3;
index fda0dc858a1fa933982abfb823744622d9befb26..61129e6759eb4a0afe81209825aa576c053f1cf2 100644 (file)
@@ -957,7 +957,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct intel_ring_buffer *ring;
        u32 exec_start, exec_len;
        u32 seqno;
-       int ret, i;
+       int ret, mode, i;
 
        if (!i915_gem_check_execbuffer(args)) {
                DRM_ERROR("execbuf with invalid offset/length\n");
@@ -997,6 +997,39 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
+       mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+       switch (mode) {
+       case I915_EXEC_CONSTANTS_REL_GENERAL:
+       case I915_EXEC_CONSTANTS_ABSOLUTE:
+       case I915_EXEC_CONSTANTS_REL_SURFACE:
+               if (ring == &dev_priv->ring[RCS] &&
+                   mode != dev_priv->relative_constants_mode) {
+                       if (INTEL_INFO(dev)->gen < 4)
+                               return -EINVAL;
+
+                       if (INTEL_INFO(dev)->gen > 5 &&
+                           mode == I915_EXEC_CONSTANTS_REL_SURFACE)
+                               return -EINVAL;
+
+                       ret = intel_ring_begin(ring, 4);
+                       if (ret)
+                               return ret;
+
+                       intel_ring_emit(ring, MI_NOOP);
+                       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+                       intel_ring_emit(ring, INSTPM);
+                       intel_ring_emit(ring,
+                                       I915_EXEC_CONSTANTS_MASK << 16 | mode);
+                       intel_ring_advance(ring);
+
+                       dev_priv->relative_constants_mode = mode;
+               }
+               break;
+       default:
+               DRM_ERROR("execbuf with unknown constants: %d\n", mode);
+               return -EINVAL;
+       }
+
        if (args->buffer_count < 1) {
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
index a2776e2807a4ce39051df02b7384da32d58c1545..0039f1f97ad86ff6587ab52b9b0cbd1c4342fc88 100644 (file)
@@ -289,6 +289,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_BLT              11
 #define I915_PARAM_HAS_RELAXED_FENCING  12
 #define I915_PARAM_HAS_COHERENT_RINGS   13
+#define I915_PARAM_HAS_EXEC_CONSTANTS   14
 
 typedef struct drm_i915_getparam {
        int param;
@@ -635,6 +636,17 @@ struct drm_i915_gem_execbuffer2 {
 #define I915_EXEC_RENDER                 (1<<0)
 #define I915_EXEC_BSD                    (2<<0)
 #define I915_EXEC_BLT                    (3<<0)
+
+/* Used for switching the constants addressing mode on gen4+ RENDER ring.
+ * Gen6+ only supports relative addressing to dynamic state (default) and
+ * absolute addressing.
+ *
+ * These flags are ignored for the BSD and BLT rings.
+ */
+#define I915_EXEC_CONSTANTS_MASK       (3<<6)
+#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
+#define I915_EXEC_CONSTANTS_ABSOLUTE   (1<<6)
+#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
        __u64 flags;
        __u64 rsvd1;
        __u64 rsvd2;