ilo: rename ilo_3d_pipeline*.[ch] to ilo_render*.[ch]
authorChia-I Wu <olvaffe@gmail.com>
Wed, 24 Sep 2014 04:27:23 +0000 (12:27 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 26 Sep 2014 13:15:55 +0000 (21:15 +0800)
They are used to build render engine commands, which can be more than 3D.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
14 files changed:
src/gallium/drivers/ilo/Makefile.sources
src/gallium/drivers/ilo/ilo_3d_pipeline.c [deleted file]
src/gallium/drivers/ilo/ilo_3d_pipeline.h [deleted file]
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c [deleted file]
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h [deleted file]
src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c [deleted file]
src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.h [deleted file]
src/gallium/drivers/ilo/ilo_draw.c
src/gallium/drivers/ilo/ilo_render.c [new file with mode: 0644]
src/gallium/drivers/ilo/ilo_render.h [new file with mode: 0644]
src/gallium/drivers/ilo/ilo_render_gen.h [new file with mode: 0644]
src/gallium/drivers/ilo/ilo_render_gen6.c [new file with mode: 0644]
src/gallium/drivers/ilo/ilo_render_gen7.c [new file with mode: 0644]
src/gallium/drivers/ilo/ilo_render_gen7.h [new file with mode: 0644]

index a6477e76b394c40058a3d9c092602a95d8dccaff..845b0231e0ee1e86380736891f6fdb76e1428ceb 100644 (file)
@@ -1,10 +1,4 @@
 C_SOURCES := \
-       ilo_3d_pipeline.c \
-       ilo_3d_pipeline_gen6.c \
-       ilo_3d_pipeline_gen6.h \
-       ilo_3d_pipeline_gen7.c \
-       ilo_3d_pipeline_gen7.h \
-       ilo_3d_pipeline.h \
        ilo_blit.c \
        ilo_blit.h \
        ilo_blitter.c \
@@ -40,6 +34,12 @@ C_SOURCES := \
        ilo_query.h \
        ilo_resource.c \
        ilo_resource.h \
+       ilo_render.c \
+       ilo_render.h \
+       ilo_render_gen.h \
+       ilo_render_gen6.c \
+       ilo_render_gen7.c \
+       ilo_render_gen7.h \
        ilo_screen.c \
        ilo_screen.h \
        ilo_shader.c \
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline.c b/src/gallium/drivers/ilo/ilo_3d_pipeline.c
deleted file mode 100644 (file)
index 74553dc..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#include "intel_winsys.h"
-
-#include "ilo_builder.h"
-#include "ilo_3d_pipeline_gen6.h"
-#include "ilo_3d_pipeline_gen7.h"
-#include "ilo_3d_pipeline.h"
-
-/* in U0.4 */
-struct sample_position {
-   uint8_t x, y;
-};
-
-/* \see gen6_get_sample_position() */
-static const struct sample_position sample_position_1x[1] = {
-   {  8,  8 },
-};
-
-static const struct sample_position sample_position_4x[4] = {
-   {  6,  2 }, /* distance from the center is sqrt(40) */
-   { 14,  6 }, /* distance from the center is sqrt(40) */
-   {  2, 10 }, /* distance from the center is sqrt(40) */
-   { 10, 14 }, /* distance from the center is sqrt(40) */
-};
-
-static const struct sample_position sample_position_8x[8] = {
-   {  7,  9 }, /* distance from the center is sqrt(2) */
-   {  9, 13 }, /* distance from the center is sqrt(26) */
-   { 11,  3 }, /* distance from the center is sqrt(34) */
-   { 13, 11 }, /* distance from the center is sqrt(34) */
-   {  1,  7 }, /* distance from the center is sqrt(50) */
-   {  5,  1 }, /* distance from the center is sqrt(58) */
-   { 15,  5 }, /* distance from the center is sqrt(58) */
-   {  3, 15 }, /* distance from the center is sqrt(74) */
-};
-
-struct ilo_3d_pipeline *
-ilo_3d_pipeline_create(struct ilo_builder *builder)
-{
-   struct ilo_3d_pipeline *p;
-   int i;
-
-   p = CALLOC_STRUCT(ilo_3d_pipeline);
-   if (!p)
-      return NULL;
-
-   p->dev = builder->dev;
-   p->builder = builder;
-
-   switch (ilo_dev_gen(p->dev)) {
-   case ILO_GEN(6):
-      ilo_3d_pipeline_init_gen6(p);
-      break;
-   case ILO_GEN(7):
-   case ILO_GEN(7.5):
-      ilo_3d_pipeline_init_gen7(p);
-      break;
-   default:
-      assert(!"unsupported GEN");
-      FREE(p);
-      return NULL;
-      break;
-   }
-
-   p->invalidate_flags = ILO_3D_PIPELINE_INVALIDATE_ALL;
-
-   p->workaround_bo = intel_winsys_alloc_buffer(builder->winsys,
-         "PIPE_CONTROL workaround", 4096, false);
-   if (!p->workaround_bo) {
-      ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
-      FREE(p);
-      return NULL;
-   }
-
-   p->packed_sample_position_1x =
-      sample_position_1x[0].x << 4 |
-      sample_position_1x[0].y;
-
-   /* pack into dwords */
-   for (i = 0; i < 4; i++) {
-      p->packed_sample_position_4x |=
-         sample_position_4x[i].x << (8 * i + 4) |
-         sample_position_4x[i].y << (8 * i);
-
-      p->packed_sample_position_8x[0] |=
-         sample_position_8x[i].x << (8 * i + 4) |
-         sample_position_8x[i].y << (8 * i);
-
-      p->packed_sample_position_8x[1] |=
-         sample_position_8x[4 + i].x << (8 * i + 4) |
-         sample_position_8x[4 + i].y << (8 * i);
-   }
-
-   return p;
-}
-
-void
-ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *p)
-{
-   if (p->workaround_bo)
-      intel_bo_unreference(p->workaround_bo);
-
-   FREE(p);
-}
-
-void
-ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
-                                    unsigned sample_count,
-                                    unsigned sample_index,
-                                    float *x, float *y)
-{
-   const struct sample_position *pos;
-
-   switch (sample_count) {
-   case 1:
-      assert(sample_index < Elements(sample_position_1x));
-      pos = sample_position_1x;
-      break;
-   case 4:
-      assert(sample_index < Elements(sample_position_4x));
-      pos = sample_position_4x;
-      break;
-   case 8:
-      assert(sample_index < Elements(sample_position_8x));
-      pos = sample_position_8x;
-      break;
-   default:
-      assert(!"unknown sample count");
-      *x = 0.5f;
-      *y = 0.5f;
-      return;
-      break;
-   }
-
-   *x = (float) pos[sample_index].x / 16.0f;
-   *y = (float) pos[sample_index].y / 16.0f;
-}
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline.h b/src/gallium/drivers/ilo/ilo_3d_pipeline.h
deleted file mode 100644 (file)
index e85bb8a..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#ifndef ILO_3D_PIPELINE_H
-#define ILO_3D_PIPELINE_H
-
-#include "ilo_common.h"
-#include "ilo_state.h"
-
-struct intel_bo;
-struct ilo_blitter;
-struct ilo_cp;
-struct ilo_query;
-struct ilo_state_vector;
-
-enum ilo_3d_pipeline_invalidate_flags {
-   ILO_3D_PIPELINE_INVALIDATE_HW         = 1 << 0,
-   ILO_3D_PIPELINE_INVALIDATE_BATCH_BO   = 1 << 1,
-   ILO_3D_PIPELINE_INVALIDATE_STATE_BO   = 1 << 2,
-   ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO  = 1 << 3,
-
-   ILO_3D_PIPELINE_INVALIDATE_ALL        = 0xffffffff,
-};
-
-enum ilo_3d_pipeline_action {
-   ILO_3D_PIPELINE_DRAW,
-   ILO_3D_PIPELINE_FLUSH,
-   ILO_3D_PIPELINE_QUERY,
-   ILO_3D_PIPELINE_RECTLIST,
-};
-
-/**
- * 3D pipeline.
- */
-struct ilo_3d_pipeline {
-   const struct ilo_dev_info *dev;
-   struct ilo_builder *builder;
-
-   uint32_t invalidate_flags;
-
-   struct intel_bo *workaround_bo;
-
-   uint32_t packed_sample_position_1x;
-   uint32_t packed_sample_position_4x;
-   uint32_t packed_sample_position_8x[2];
-
-   int (*estimate_size)(struct ilo_3d_pipeline *pipeline,
-                        enum ilo_3d_pipeline_action action,
-                        const void *arg);
-
-   void (*emit_draw)(struct ilo_3d_pipeline *pipeline,
-                     const struct ilo_state_vector *vec);
-
-   void (*emit_flush)(struct ilo_3d_pipeline *pipeline);
-
-   void (*emit_query)(struct ilo_3d_pipeline *pipeline,
-                      struct ilo_query *q, uint32_t offset);
-
-   void (*emit_rectlist)(struct ilo_3d_pipeline *pipeline,
-                         const struct ilo_blitter *blitter);
-
-   /**
-    * HW states.
-    */
-   struct ilo_3d_pipeline_state {
-      /*
-       * When a WA is needed before some command, we always emit the WA right
-       * before the command.  Knowing what have already been done since last
-       * 3DPRIMITIVE allows us to skip some WAs.
-       */
-      uint32_t current_pipe_control_dw1;
-
-      /*
-       * When a WA is needed after some command, we may have the WA follow the
-       * command immediately or defer it.  If this is non-zero, a PIPE_CONTROL
-       * will be emitted before 3DPRIMITIVE.
-       */
-      uint32_t deferred_pipe_control_dw1;
-
-      bool primitive_restart;
-      int reduced_prim;
-      int so_max_vertices;
-
-      uint32_t SF_VIEWPORT;
-      uint32_t CLIP_VIEWPORT;
-      uint32_t SF_CLIP_VIEWPORT; /* GEN7+ */
-      uint32_t CC_VIEWPORT;
-
-      uint32_t COLOR_CALC_STATE;
-      uint32_t BLEND_STATE;
-      uint32_t DEPTH_STENCIL_STATE;
-
-      uint32_t SCISSOR_RECT;
-
-      struct {
-         uint32_t BINDING_TABLE_STATE;
-         int BINDING_TABLE_STATE_size;
-         uint32_t SURFACE_STATE[ILO_MAX_VS_SURFACES];
-         uint32_t SAMPLER_STATE;
-         uint32_t SAMPLER_BORDER_COLOR_STATE[ILO_MAX_SAMPLERS];
-         uint32_t PUSH_CONSTANT_BUFFER;
-         int PUSH_CONSTANT_BUFFER_size;
-      } vs;
-
-      struct {
-         uint32_t BINDING_TABLE_STATE;
-         int BINDING_TABLE_STATE_size;
-         uint32_t SURFACE_STATE[ILO_MAX_GS_SURFACES];
-         bool active;
-      } gs;
-
-      struct {
-         uint32_t BINDING_TABLE_STATE;
-         int BINDING_TABLE_STATE_size;
-         uint32_t SURFACE_STATE[ILO_MAX_WM_SURFACES];
-         uint32_t SAMPLER_STATE;
-         uint32_t SAMPLER_BORDER_COLOR_STATE[ILO_MAX_SAMPLERS];
-         uint32_t PUSH_CONSTANT_BUFFER;
-         int PUSH_CONSTANT_BUFFER_size;
-      } wm;
-   } state;
-};
-
-struct ilo_3d_pipeline *
-ilo_3d_pipeline_create(struct ilo_builder *builder);
-
-void
-ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *pipeline);
-
-
-static inline void
-ilo_3d_pipeline_invalidate(struct ilo_3d_pipeline *p, uint32_t flags)
-{
-   p->invalidate_flags |= flags;
-
-   /* Kernel flushes everything.  Shouldn't we set all bits here? */
-   p->state.current_pipe_control_dw1 = 0;
-}
-
-/**
- * Estimate the size of an action.
- */
-static inline int
-ilo_3d_pipeline_estimate_size(struct ilo_3d_pipeline *pipeline,
-                              enum ilo_3d_pipeline_action action,
-                              const void *arg)
-{
-   return pipeline->estimate_size(pipeline, action, arg);
-}
-
-/**
- * Emit context states and 3DPRIMITIVE.
- */
-static inline void
-ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline *p,
-                          const struct ilo_state_vector *vec)
-{
-   p->emit_draw(p, vec);
-}
-
-/**
- * Emit PIPE_CONTROL to flush all caches.
- */
-static inline void
-ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
-{
-   p->emit_flush(p);
-}
-
-/**
- * Emit PIPE_CONTROL or MI_STORE_REGISTER_MEM to save register values.
- */
-static inline void
-ilo_3d_pipeline_emit_query(struct ilo_3d_pipeline *p,
-                           struct ilo_query *q, uint32_t offset)
-{
-   p->emit_query(p, q, offset);
-}
-
-static inline void
-ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p,
-                              const struct ilo_blitter *blitter)
-{
-   p->emit_rectlist(p, blitter);
-}
-
-void
-ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
-                                    unsigned sample_count,
-                                    unsigned sample_index,
-                                    float *x, float *y);
-
-#endif /* ILO_3D_PIPELINE_H */
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
deleted file mode 100644 (file)
index e5cd937..0000000
+++ /dev/null
@@ -1,2010 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#include "genhw/genhw.h"
-#include "util/u_dual_blend.h"
-#include "util/u_prim.h"
-
-#include "ilo_blitter.h"
-#include "ilo_builder_3d.h"
-#include "ilo_builder_mi.h"
-#include "ilo_builder_render.h"
-#include "ilo_query.h"
-#include "ilo_shader.h"
-#include "ilo_state.h"
-#include "ilo_3d_pipeline.h"
-#include "ilo_3d_pipeline_gen6.h"
-
-/**
- * A wrapper for gen6_PIPE_CONTROL().
- */
-static inline void
-gen6_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
-{
-   struct intel_bo *bo = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) ?
-      p->workaround_bo : NULL;
-
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   gen6_PIPE_CONTROL(p->builder, dw1, bo, 0, false);
-
-   p->state.current_pipe_control_dw1 |= dw1;
-
-   assert(!p->state.deferred_pipe_control_dw1);
-}
-
-/**
- * This should be called before PIPE_CONTROL.
- */
-static void
-gen6_wa_pre_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
-{
-   /*
-    * From the Sandy Bridge PRM, volume 2 part 1, page 60:
-    *
-    *     "Pipe-control with CS-stall bit set must be sent BEFORE the
-    *      pipe-control with a post-sync op and no write-cache flushes."
-    *
-    * This WA may also be triggered indirectly by the other two WAs on the
-    * same page:
-    *
-    *     "Before any depth stall flush (including those produced by
-    *      non-pipelined state commands), software needs to first send a
-    *      PIPE_CONTROL with no bits set except Post-Sync Operation != 0."
-    *
-    *     "Before a PIPE_CONTROL with Write Cache Flush Enable =1, a
-    *      PIPE_CONTROL with any non-zero post-sync-op is required."
-    */
-   const bool direct_wa_cond = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) &&
-                               !(dw1 & GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH);
-   const bool indirect_wa_cond = (dw1 & GEN6_PIPE_CONTROL_DEPTH_STALL) |
-                                 (dw1 & GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH);
-
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   if (!direct_wa_cond && !indirect_wa_cond)
-      return;
-
-   if (!(p->state.current_pipe_control_dw1 & GEN6_PIPE_CONTROL_CS_STALL)) {
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 73:
-       *
-       *     "1 of the following must also be set (when CS stall is set):
-       *
-       *       - Depth Cache Flush Enable ([0] of DW1)
-       *       - Stall at Pixel Scoreboard ([1] of DW1)
-       *       - Depth Stall ([13] of DW1)
-       *       - Post-Sync Operation ([13] of DW1)
-       *       - Render Target Cache Flush Enable ([12] of DW1)
-       *       - Notify Enable ([8] of DW1)"
-       *
-       * Because of the WAs above, we have to pick Stall at Pixel Scoreboard.
-       */
-      const uint32_t direct_wa = GEN6_PIPE_CONTROL_CS_STALL |
-                                 GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
-
-      gen6_pipe_control(p, direct_wa);
-   }
-
-   if (indirect_wa_cond &&
-       !(p->state.current_pipe_control_dw1 & GEN6_PIPE_CONTROL_WRITE__MASK)) {
-      const uint32_t indirect_wa = GEN6_PIPE_CONTROL_WRITE_IMM;
-
-      gen6_pipe_control(p, indirect_wa);
-   }
-}
-
-/**
- * This should be called before any non-pipelined state command.
- */
-static void
-gen6_wa_pre_non_pipelined(struct ilo_3d_pipeline *p)
-{
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   /* non-pipelined state commands produce depth stall */
-   gen6_wa_pre_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
-}
-
-static void
-gen6_wa_post_3dstate_constant_vs(struct ilo_3d_pipeline *p)
-{
-   /*
-    * According to upload_vs_state() of the classic driver, we need to emit a
-    * PIPE_CONTROL after 3DSTATE_CONSTANT_VS, otherwise the command is kept
-    * being buffered by VS FF, to the point that the FF dies.
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
-                        GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
-                        GEN6_PIPE_CONTROL_STATE_CACHE_INVALIDATE;
-
-   gen6_wa_pre_pipe_control(p, dw1);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen6_pipe_control(p, dw1);
-}
-
-static void
-gen6_wa_pre_3dstate_wm_max_threads(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Sandy Bridge PRM, volume 2 part 1, page 274:
-    *
-    *     "A PIPE_CONTROL command, with only the Stall At Pixel Scoreboard
-    *      field set (DW1 Bit 1), must be issued prior to any change to the
-    *      value in this field (Maximum Number of Threads in 3DSTATE_WM)"
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   gen6_wa_pre_pipe_control(p, dw1);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen6_pipe_control(p, dw1);
-}
-
-static void
-gen6_wa_pre_3dstate_multisample(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Sandy Bridge PRM, volume 2 part 1, page 305:
-    *
-    *     "Driver must guarentee that all the caches in the depth pipe are
-    *      flushed before this command (3DSTATE_MULTISAMPLE) is parsed. This
-    *      requires driver to send a PIPE_CONTROL with a CS stall along with a
-    *      Depth Flush prior to this command."
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
-                        GEN6_PIPE_CONTROL_CS_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   gen6_wa_pre_pipe_control(p, dw1);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen6_pipe_control(p, dw1);
-}
-
-static void
-gen6_wa_pre_depth(struct ilo_3d_pipeline *p)
-{
-   ILO_DEV_ASSERT(p->dev, 6, 6);
-
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
-    *
-    *     "Restriction: Prior to changing Depth/Stencil Buffer state (i.e.,
-    *      any combination of 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
-    *      3DSTATE_STENCIL_BUFFER, 3DSTATE_HIER_DEPTH_BUFFER) SW must first
-    *      issue a pipelined depth stall (PIPE_CONTROL with Depth Stall bit
-    *      set), followed by a pipelined depth cache flush (PIPE_CONTROL with
-    *      Depth Flush Bit set, followed by another pipelined depth stall
-    *      (PIPE_CONTROL with Depth Stall Bit set), unless SW can otherwise
-    *      guarantee that the pipeline from WM onwards is already flushed
-    *      (e.g., via a preceding MI_FLUSH)."
-    *
-    * According to the classic driver, it also applies for GEN6.
-    */
-   gen6_wa_pre_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL |
-                               GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
-
-   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
-   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
-   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
-}
-
-#define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
-
-void
-gen6_pipeline_common_select(struct ilo_3d_pipeline *p,
-                            const struct ilo_state_vector *vec,
-                            struct gen6_pipeline_session *session)
-{
-   /* PIPELINE_SELECT */
-   if (session->hw_ctx_changed) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_PIPELINE_SELECT(p->builder, 0x0);
-   }
-}
-
-void
-gen6_pipeline_common_sip(struct ilo_3d_pipeline *p,
-                         const struct ilo_state_vector *vec,
-                         struct gen6_pipeline_session *session)
-{
-   /* STATE_SIP */
-   if (session->hw_ctx_changed) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_STATE_SIP(p->builder, 0);
-   }
-}
-
-void
-gen6_pipeline_common_base_address(struct ilo_3d_pipeline *p,
-                                  const struct ilo_state_vector *vec,
-                                  struct gen6_pipeline_session *session)
-{
-   /* STATE_BASE_ADDRESS */
-   if (session->state_bo_changed || session->kernel_bo_changed ||
-       session->batch_bo_changed) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_state_base_address(p->builder, session->hw_ctx_changed);
-
-      /*
-       * From the Sandy Bridge PRM, volume 1 part 1, page 28:
-       *
-       *     "The following commands must be reissued following any change to
-       *      the base addresses:
-       *
-       *       * 3DSTATE_BINDING_TABLE_POINTERS
-       *       * 3DSTATE_SAMPLER_STATE_POINTERS
-       *       * 3DSTATE_VIEWPORT_STATE_POINTERS
-       *       * 3DSTATE_CC_POINTERS
-       *       * MEDIA_STATE_POINTERS"
-       *
-       * 3DSTATE_SCISSOR_STATE_POINTERS is not on the list, but it is
-       * reasonable to also reissue the command.  Same to PCB.
-       */
-      session->viewport_state_changed = true;
-
-      session->cc_state_blend_changed = true;
-      session->cc_state_dsa_changed = true;
-      session->cc_state_cc_changed = true;
-
-      session->scissor_state_changed = true;
-
-      session->binding_table_vs_changed = true;
-      session->binding_table_gs_changed = true;
-      session->binding_table_fs_changed = true;
-
-      session->sampler_state_vs_changed = true;
-      session->sampler_state_gs_changed = true;
-      session->sampler_state_fs_changed = true;
-
-      session->pcb_state_vs_changed = true;
-      session->pcb_state_gs_changed = true;
-      session->pcb_state_fs_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_common_urb(struct ilo_3d_pipeline *p,
-                         const struct ilo_state_vector *vec,
-                         struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_URB */
-   if (DIRTY(VE) || DIRTY(VS) || DIRTY(GS)) {
-      const bool gs_active = (vec->gs || (vec->vs &&
-               ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO)));
-      int vs_entry_size, gs_entry_size;
-      int vs_total_size, gs_total_size;
-
-      vs_entry_size = (vec->vs) ?
-         ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT) : 0;
-
-      /*
-       * As indicated by 2e712e41db0c0676e9f30fc73172c0e8de8d84d4, VF and VS
-       * share VUE handles.  The VUE allocation size must be large enough to
-       * store either VF outputs (number of VERTEX_ELEMENTs) and VS outputs.
-       *
-       * I am not sure if the PRM explicitly states that VF and VS share VUE
-       * handles.  But here is a citation that implies so:
-       *
-       * From the Sandy Bridge PRM, volume 2 part 1, page 44:
-       *
-       *     "Once a FF stage that spawn threads has sufficient input to
-       *      initiate a thread, it must guarantee that it is safe to request
-       *      the thread initiation. For all these FF stages, this check is
-       *      based on :
-       *
-       *      - The availability of output URB entries:
-       *        - VS: As the input URB entries are overwritten with the
-       *          VS-generated output data, output URB availability isn't a
-       *          factor."
-       */
-      if (vs_entry_size < vec->ve->count)
-         vs_entry_size = vec->ve->count;
-
-      gs_entry_size = (vec->gs) ?
-         ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_OUTPUT_COUNT) :
-         (gs_active) ? vs_entry_size : 0;
-
-      /* in bytes */
-      vs_entry_size *= sizeof(float) * 4;
-      gs_entry_size *= sizeof(float) * 4;
-      vs_total_size = p->dev->urb_size;
-
-      if (gs_active) {
-         vs_total_size /= 2;
-         gs_total_size = vs_total_size;
-      }
-      else {
-         gs_total_size = 0;
-      }
-
-      gen6_3DSTATE_URB(p->builder, vs_total_size, gs_total_size,
-            vs_entry_size, gs_entry_size);
-
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 27:
-       *
-       *     "Because of a urb corruption caused by allocating a previous
-       *      gsunit's urb entry to vsunit software is required to send a
-       *      "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB
-       *      size == 0) plus a dummy DRAW call before any case where VS will
-       *      be taking over GS URB space."
-       */
-      if (p->state.gs.active && !gs_active)
-         ilo_3d_pipeline_emit_flush_gen6(p);
-
-      p->state.gs.active = gs_active;
-   }
-}
-
-static void
-gen6_pipeline_common_pointers_1(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_VIEWPORT_STATE_POINTERS */
-   if (session->viewport_state_changed) {
-      gen6_3DSTATE_VIEWPORT_STATE_POINTERS(p->builder,
-            p->state.CLIP_VIEWPORT,
-            p->state.SF_VIEWPORT,
-            p->state.CC_VIEWPORT);
-   }
-}
-
-static void
-gen6_pipeline_common_pointers_2(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CC_STATE_POINTERS */
-   if (session->cc_state_blend_changed ||
-       session->cc_state_dsa_changed ||
-       session->cc_state_cc_changed) {
-      gen6_3DSTATE_CC_STATE_POINTERS(p->builder,
-            p->state.BLEND_STATE,
-            p->state.DEPTH_STENCIL_STATE,
-            p->state.COLOR_CALC_STATE);
-   }
-
-   /* 3DSTATE_SAMPLER_STATE_POINTERS */
-   if (session->sampler_state_vs_changed ||
-       session->sampler_state_gs_changed ||
-       session->sampler_state_fs_changed) {
-      gen6_3DSTATE_SAMPLER_STATE_POINTERS(p->builder,
-            p->state.vs.SAMPLER_STATE,
-            0,
-            p->state.wm.SAMPLER_STATE);
-   }
-}
-
-static void
-gen6_pipeline_common_pointers_3(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_SCISSOR_STATE_POINTERS */
-   if (session->scissor_state_changed) {
-      gen6_3DSTATE_SCISSOR_STATE_POINTERS(p->builder,
-            p->state.SCISSOR_RECT);
-   }
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS */
-   if (session->binding_table_vs_changed ||
-       session->binding_table_gs_changed ||
-       session->binding_table_fs_changed) {
-      gen6_3DSTATE_BINDING_TABLE_POINTERS(p->builder,
-            p->state.vs.BINDING_TABLE_STATE,
-            p->state.gs.BINDING_TABLE_STATE,
-            p->state.wm.BINDING_TABLE_STATE);
-   }
-}
-
-void
-gen6_pipeline_vf(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   if (ilo_dev_gen(p->dev) >= ILO_GEN(7.5)) {
-      /* 3DSTATE_INDEX_BUFFER */
-      if (DIRTY(IB) || session->batch_bo_changed) {
-         gen6_3DSTATE_INDEX_BUFFER(p->builder,
-               &vec->ib, false);
-      }
-
-      /* 3DSTATE_VF */
-      if (session->primitive_restart_changed) {
-         gen7_3DSTATE_VF(p->builder, vec->draw->primitive_restart,
-               vec->draw->restart_index);
-      }
-   }
-   else {
-      /* 3DSTATE_INDEX_BUFFER */
-      if (DIRTY(IB) || session->primitive_restart_changed ||
-          session->batch_bo_changed) {
-         gen6_3DSTATE_INDEX_BUFFER(p->builder,
-               &vec->ib, vec->draw->primitive_restart);
-      }
-   }
-
-   /* 3DSTATE_VERTEX_BUFFERS */
-   if (DIRTY(VB) || DIRTY(VE) || session->batch_bo_changed)
-      gen6_3DSTATE_VERTEX_BUFFERS(p->builder, vec->ve, &vec->vb);
-
-   /* 3DSTATE_VERTEX_ELEMENTS */
-   if (DIRTY(VE) || DIRTY(VS)) {
-      const struct ilo_ve_state *ve = vec->ve;
-      bool last_velement_edgeflag = false;
-      bool prepend_generate_ids = false;
-
-      if (vec->vs) {
-         if (ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_VS_INPUT_EDGEFLAG)) {
-            /* we rely on the state tracker here */
-            assert(ilo_shader_get_kernel_param(vec->vs,
-                     ILO_KERNEL_INPUT_COUNT) == ve->count);
-
-            last_velement_edgeflag = true;
-         }
-
-         if (ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_VS_INPUT_INSTANCEID) ||
-             ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_VS_INPUT_VERTEXID))
-            prepend_generate_ids = true;
-      }
-
-      gen6_3DSTATE_VERTEX_ELEMENTS(p->builder, ve,
-            last_velement_edgeflag, prepend_generate_ids);
-   }
-}
-
-void
-gen6_pipeline_vf_statistics(struct ilo_3d_pipeline *p,
-                            const struct ilo_state_vector *vec,
-                            struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_VF_STATISTICS */
-   if (session->hw_ctx_changed)
-      gen6_3DSTATE_VF_STATISTICS(p->builder, false);
-}
-
-static void
-gen6_pipeline_vf_draw(struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *vec,
-                      struct gen6_pipeline_session *session)
-{
-   /* 3DPRIMITIVE */
-   gen6_3DPRIMITIVE(p->builder, vec->draw, &vec->ib);
-
-   p->state.current_pipe_control_dw1 = 0;
-   assert(!p->state.deferred_pipe_control_dw1);
-}
-
-void
-gen6_pipeline_vs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   const bool emit_3dstate_vs = (DIRTY(VS) || DIRTY(SAMPLER_VS) ||
-                                 session->kernel_bo_changed);
-   const bool emit_3dstate_constant_vs = session->pcb_state_vs_changed;
-
-   /*
-    * the classic i965 does this in upload_vs_state(), citing a spec that I
-    * cannot find
-    */
-   if (emit_3dstate_vs && ilo_dev_gen(p->dev) == ILO_GEN(6))
-      gen6_wa_pre_non_pipelined(p);
-
-   /* 3DSTATE_CONSTANT_VS */
-   if (emit_3dstate_constant_vs) {
-      gen6_3DSTATE_CONSTANT_VS(p->builder,
-            &p->state.vs.PUSH_CONSTANT_BUFFER,
-            &p->state.vs.PUSH_CONSTANT_BUFFER_size,
-            1);
-   }
-
-   /* 3DSTATE_VS */
-   if (emit_3dstate_vs) {
-      const int num_samplers = vec->sampler[PIPE_SHADER_VERTEX].count;
-
-      gen6_3DSTATE_VS(p->builder, vec->vs, num_samplers);
-   }
-
-   if (emit_3dstate_constant_vs && ilo_dev_gen(p->dev) == ILO_GEN(6))
-      gen6_wa_post_3dstate_constant_vs(p);
-}
-
-static void
-gen6_pipeline_gs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CONSTANT_GS */
-   if (session->pcb_state_gs_changed)
-      gen6_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
-
-   /* 3DSTATE_GS */
-   if (DIRTY(GS) || DIRTY(VS) ||
-       session->prim_changed || session->kernel_bo_changed) {
-      const int verts_per_prim = u_vertices_per_prim(session->reduced_prim);
-
-      gen6_3DSTATE_GS(p->builder, vec->gs, vec->vs, verts_per_prim);
-   }
-}
-
-static bool
-gen6_pipeline_update_max_svbi(struct ilo_3d_pipeline *p,
-                              const struct ilo_state_vector *vec,
-                              struct gen6_pipeline_session *session)
-{
-   if (DIRTY(VS) || DIRTY(GS) || DIRTY(SO)) {
-      const struct pipe_stream_output_info *so_info =
-         (vec->gs) ? ilo_shader_get_kernel_so_info(vec->gs) :
-         (vec->vs) ? ilo_shader_get_kernel_so_info(vec->vs) : NULL;
-      unsigned max_svbi = 0xffffffff;
-      int i;
-
-      for (i = 0; i < so_info->num_outputs; i++) {
-         const int output_buffer = so_info->output[i].output_buffer;
-         const struct pipe_stream_output_target *so =
-            vec->so.states[output_buffer];
-         const int struct_size = so_info->stride[output_buffer] * 4;
-         const int elem_size = so_info->output[i].num_components * 4;
-         int buf_size, count;
-
-         if (!so) {
-            max_svbi = 0;
-            break;
-         }
-
-         buf_size = so->buffer_size - so_info->output[i].dst_offset * 4;
-
-         count = buf_size / struct_size;
-         if (buf_size % struct_size >= elem_size)
-            count++;
-
-         if (count < max_svbi)
-            max_svbi = count;
-      }
-
-      if (p->state.so_max_vertices != max_svbi) {
-         p->state.so_max_vertices = max_svbi;
-         return true;
-      }
-   }
-
-   return false;
-}
-
-static void
-gen6_pipeline_gs_svbi(struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *vec,
-                      struct gen6_pipeline_session *session)
-{
-   const bool emit = gen6_pipeline_update_max_svbi(p, vec, session);
-
-   /* 3DSTATE_GS_SVB_INDEX */
-   if (emit) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_3DSTATE_GS_SVB_INDEX(p->builder,
-            0, 0, p->state.so_max_vertices,
-            false);
-
-      if (session->hw_ctx_changed) {
-         int i;
-
-         /*
-          * From the Sandy Bridge PRM, volume 2 part 1, page 148:
-          *
-          *     "If a buffer is not enabled then the SVBI must be set to 0x0
-          *      in order to not cause overflow in that SVBI."
-          *
-          *     "If a buffer is not enabled then the MaxSVBI must be set to
-          *      0xFFFFFFFF in order to not cause overflow in that SVBI."
-          */
-         for (i = 1; i < 4; i++) {
-            gen6_3DSTATE_GS_SVB_INDEX(p->builder,
-                  i, 0, 0xffffffff, false);
-         }
-      }
-   }
-}
-
-void
-gen6_pipeline_clip(struct ilo_3d_pipeline *p,
-                   const struct ilo_state_vector *vec,
-                   struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CLIP */
-   if (DIRTY(RASTERIZER) || DIRTY(FS) || DIRTY(VIEWPORT) || DIRTY(FB)) {
-      bool enable_guardband = true;
-      unsigned i;
-
-      /*
-       * We do not do 2D clipping yet.  Guard band test should only be enabled
-       * when the viewport is larger than the framebuffer.
-       */
-      for (i = 0; i < vec->viewport.count; i++) {
-         const struct ilo_viewport_cso *vp = &vec->viewport.cso[i];
-
-         if (vp->min_x > 0.0f || vp->max_x < vec->fb.state.width ||
-             vp->min_y > 0.0f || vp->max_y < vec->fb.state.height) {
-            enable_guardband = false;
-            break;
-         }
-      }
-
-      gen6_3DSTATE_CLIP(p->builder, vec->rasterizer,
-            vec->fs, enable_guardband, 1);
-   }
-}
-
-static void
-gen6_pipeline_sf(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_SF */
-   if (DIRTY(RASTERIZER) || DIRTY(FS))
-      gen6_3DSTATE_SF(p->builder, vec->rasterizer, vec->fs);
-}
-
-void
-gen6_pipeline_sf_rect(struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *vec,
-                      struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_DRAWING_RECTANGLE */
-   if (DIRTY(FB)) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
-            vec->fb.state.width, vec->fb.state.height);
-   }
-}
-
-static void
-gen6_pipeline_wm(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CONSTANT_PS */
-   if (session->pcb_state_fs_changed) {
-      gen6_3DSTATE_CONSTANT_PS(p->builder,
-            &p->state.wm.PUSH_CONSTANT_BUFFER,
-            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
-            1);
-   }
-
-   /* 3DSTATE_WM */
-   if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) || DIRTY(DSA) ||
-       DIRTY(RASTERIZER) || session->kernel_bo_changed) {
-      const int num_samplers = vec->sampler[PIPE_SHADER_FRAGMENT].count;
-      const bool dual_blend = vec->blend->dual_blend;
-      const bool cc_may_kill = (vec->dsa->dw_alpha ||
-                                vec->blend->alpha_to_coverage);
-
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6) && session->hw_ctx_changed)
-         gen6_wa_pre_3dstate_wm_max_threads(p);
-
-      gen6_3DSTATE_WM(p->builder, vec->fs, num_samplers,
-            vec->rasterizer, dual_blend, cc_may_kill, 0);
-   }
-}
-
-static void
-gen6_pipeline_wm_multisample(struct ilo_3d_pipeline *p,
-                             const struct ilo_state_vector *vec,
-                             struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_MULTISAMPLE and 3DSTATE_SAMPLE_MASK */
-   if (DIRTY(SAMPLE_MASK) || DIRTY(FB)) {
-      const uint32_t *packed_sample_pos;
-
-      packed_sample_pos = (vec->fb.num_samples > 1) ?
-         &p->packed_sample_position_4x : &p->packed_sample_position_1x;
-
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
-         gen6_wa_pre_non_pipelined(p);
-         gen6_wa_pre_3dstate_multisample(p);
-      }
-
-      gen6_3DSTATE_MULTISAMPLE(p->builder,
-            vec->fb.num_samples, packed_sample_pos,
-            vec->rasterizer->state.half_pixel_center);
-
-      gen6_3DSTATE_SAMPLE_MASK(p->builder,
-            (vec->fb.num_samples > 1) ? vec->sample_mask : 0x1);
-   }
-}
-
-static void
-gen6_pipeline_wm_depth(struct ilo_3d_pipeline *p,
-                       const struct ilo_state_vector *vec,
-                       struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
-   if (DIRTY(FB) || session->batch_bo_changed) {
-      const struct ilo_zs_surface *zs;
-      uint32_t clear_params;
-
-      if (vec->fb.state.zsbuf) {
-         const struct ilo_surface_cso *surface =
-            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
-         const struct ilo_texture_slice *slice =
-            ilo_texture_get_slice(ilo_texture(surface->base.texture),
-                  surface->base.u.tex.level, surface->base.u.tex.first_layer);
-
-         assert(!surface->is_rt);
-
-         zs = &surface->u.zs;
-         clear_params = slice->clear_value;
-      }
-      else {
-         zs = &vec->fb.null_zs;
-         clear_params = 0;
-      }
-
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
-         gen6_wa_pre_non_pipelined(p);
-         gen6_wa_pre_depth(p);
-      }
-
-      gen6_3DSTATE_DEPTH_BUFFER(p->builder, zs);
-      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder, zs);
-      gen6_3DSTATE_STENCIL_BUFFER(p->builder, zs);
-      gen6_3DSTATE_CLEAR_PARAMS(p->builder, clear_params);
-   }
-}
-
-void
-gen6_pipeline_wm_raster(struct ilo_3d_pipeline *p,
-                        const struct ilo_state_vector *vec,
-                        struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_POLY_STIPPLE_PATTERN and 3DSTATE_POLY_STIPPLE_OFFSET */
-   if ((DIRTY(RASTERIZER) || DIRTY(POLY_STIPPLE)) &&
-       vec->rasterizer->state.poly_stipple_enable) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_3DSTATE_POLY_STIPPLE_PATTERN(p->builder,
-            &vec->poly_stipple);
-
-      gen6_3DSTATE_POLY_STIPPLE_OFFSET(p->builder, 0, 0);
-   }
-
-   /* 3DSTATE_LINE_STIPPLE */
-   if (DIRTY(RASTERIZER) && vec->rasterizer->state.line_stipple_enable) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_3DSTATE_LINE_STIPPLE(p->builder,
-            vec->rasterizer->state.line_stipple_pattern,
-            vec->rasterizer->state.line_stipple_factor + 1);
-   }
-
-   /* 3DSTATE_AA_LINE_PARAMETERS */
-   if (DIRTY(RASTERIZER) && vec->rasterizer->state.line_smooth) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_non_pipelined(p);
-
-      gen6_3DSTATE_AA_LINE_PARAMETERS(p->builder);
-   }
-}
-
-static void
-gen6_pipeline_state_viewports(struct ilo_3d_pipeline *p,
-                              const struct ilo_state_vector *vec,
-                              struct gen6_pipeline_session *session)
-{
-   /* SF_CLIP_VIEWPORT and CC_VIEWPORT */
-   if (ilo_dev_gen(p->dev) >= ILO_GEN(7) && DIRTY(VIEWPORT)) {
-      p->state.SF_CLIP_VIEWPORT = gen7_SF_CLIP_VIEWPORT(p->builder,
-            vec->viewport.cso, vec->viewport.count);
-
-      p->state.CC_VIEWPORT = gen6_CC_VIEWPORT(p->builder,
-            vec->viewport.cso, vec->viewport.count);
-
-      session->viewport_state_changed = true;
-   }
-   /* SF_VIEWPORT, CLIP_VIEWPORT, and CC_VIEWPORT */
-   else if (DIRTY(VIEWPORT)) {
-      p->state.CLIP_VIEWPORT = gen6_CLIP_VIEWPORT(p->builder,
-            vec->viewport.cso, vec->viewport.count);
-
-      p->state.SF_VIEWPORT = gen6_SF_VIEWPORT(p->builder,
-            vec->viewport.cso, vec->viewport.count);
-
-      p->state.CC_VIEWPORT = gen6_CC_VIEWPORT(p->builder,
-            vec->viewport.cso, vec->viewport.count);
-
-      session->viewport_state_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_state_cc(struct ilo_3d_pipeline *p,
-                       const struct ilo_state_vector *vec,
-                       struct gen6_pipeline_session *session)
-{
-   /* BLEND_STATE */
-   if (DIRTY(BLEND) || DIRTY(FB) || DIRTY(DSA)) {
-      p->state.BLEND_STATE = gen6_BLEND_STATE(p->builder,
-            vec->blend, &vec->fb, vec->dsa);
-
-      session->cc_state_blend_changed = true;
-   }
-
-   /* COLOR_CALC_STATE */
-   if (DIRTY(DSA) || DIRTY(STENCIL_REF) || DIRTY(BLEND_COLOR)) {
-      p->state.COLOR_CALC_STATE =
-         gen6_COLOR_CALC_STATE(p->builder, &vec->stencil_ref,
-               vec->dsa->alpha_ref, &vec->blend_color);
-
-      session->cc_state_cc_changed = true;
-   }
-
-   /* DEPTH_STENCIL_STATE */
-   if (DIRTY(DSA)) {
-      p->state.DEPTH_STENCIL_STATE =
-         gen6_DEPTH_STENCIL_STATE(p->builder, vec->dsa);
-
-      session->cc_state_dsa_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_state_scissors(struct ilo_3d_pipeline *p,
-                             const struct ilo_state_vector *vec,
-                             struct gen6_pipeline_session *session)
-{
-   /* SCISSOR_RECT */
-   if (DIRTY(SCISSOR) || DIRTY(VIEWPORT)) {
-      /* there should be as many scissors as there are viewports */
-      p->state.SCISSOR_RECT = gen6_SCISSOR_RECT(p->builder,
-            &vec->scissor, vec->viewport.count);
-
-      session->scissor_state_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_state_surfaces_rt(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* SURFACE_STATEs for render targets */
-   if (DIRTY(FB)) {
-      const struct ilo_fb_state *fb = &vec->fb;
-      const int offset = ILO_WM_DRAW_SURFACE(0);
-      uint32_t *surface_state = &p->state.wm.SURFACE_STATE[offset];
-      int i;
-
-      for (i = 0; i < fb->state.nr_cbufs; i++) {
-         const struct ilo_surface_cso *surface =
-            (const struct ilo_surface_cso *) fb->state.cbufs[i];
-
-         if (!surface) {
-            surface_state[i] =
-               gen6_SURFACE_STATE(p->builder, &fb->null_rt, true);
-         }
-         else {
-            assert(surface && surface->is_rt);
-            surface_state[i] =
-               gen6_SURFACE_STATE(p->builder, &surface->u.rt, true);
-         }
-      }
-
-      /*
-       * Upload at least one render target, as
-       * brw_update_renderbuffer_surfaces() does.  I don't know why.
-       */
-      if (i == 0) {
-         surface_state[i] =
-            gen6_SURFACE_STATE(p->builder, &fb->null_rt, true);
-
-         i++;
-      }
-
-      memset(&surface_state[i], 0, (ILO_MAX_DRAW_BUFFERS - i) * 4);
-
-      if (i && session->num_surfaces[PIPE_SHADER_FRAGMENT] < offset + i)
-         session->num_surfaces[PIPE_SHADER_FRAGMENT] = offset + i;
-
-      session->binding_table_fs_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_state_surfaces_so(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   const struct ilo_so_state *so = &vec->so;
-
-   if (ilo_dev_gen(p->dev) != ILO_GEN(6))
-      return;
-
-   /* SURFACE_STATEs for stream output targets */
-   if (DIRTY(VS) || DIRTY(GS) || DIRTY(SO)) {
-      const struct pipe_stream_output_info *so_info =
-         (vec->gs) ? ilo_shader_get_kernel_so_info(vec->gs) :
-         (vec->vs) ? ilo_shader_get_kernel_so_info(vec->vs) : NULL;
-      const int offset = ILO_GS_SO_SURFACE(0);
-      uint32_t *surface_state = &p->state.gs.SURFACE_STATE[offset];
-      int i;
-
-      for (i = 0; so_info && i < so_info->num_outputs; i++) {
-         const int target = so_info->output[i].output_buffer;
-         const struct pipe_stream_output_target *so_target =
-            (target < so->count) ? so->states[target] : NULL;
-
-         if (so_target) {
-            surface_state[i] = gen6_so_SURFACE_STATE(p->builder,
-                  so_target, so_info, i);
-         }
-         else {
-            surface_state[i] = 0;
-         }
-      }
-
-      memset(&surface_state[i], 0, (ILO_MAX_SO_BINDINGS - i) * 4);
-
-      if (i && session->num_surfaces[PIPE_SHADER_GEOMETRY] < offset + i)
-         session->num_surfaces[PIPE_SHADER_GEOMETRY] = offset + i;
-
-      session->binding_table_gs_changed = true;
-   }
-}
-
-static void
-gen6_pipeline_state_surfaces_view(struct ilo_3d_pipeline *p,
-                                  const struct ilo_state_vector *vec,
-                                  int shader_type,
-                                  struct gen6_pipeline_session *session)
-{
-   const struct ilo_view_state *view = &vec->view[shader_type];
-   uint32_t *surface_state;
-   int offset, i;
-   bool skip = false;
-
-   /* SURFACE_STATEs for sampler views */
-   switch (shader_type) {
-   case PIPE_SHADER_VERTEX:
-      if (DIRTY(VIEW_VS)) {
-         offset = ILO_VS_TEXTURE_SURFACE(0);
-         surface_state = &p->state.vs.SURFACE_STATE[offset];
-
-         session->binding_table_vs_changed = true;
-      }
-      else {
-         skip = true;
-      }
-      break;
-   case PIPE_SHADER_FRAGMENT:
-      if (DIRTY(VIEW_FS)) {
-         offset = ILO_WM_TEXTURE_SURFACE(0);
-         surface_state = &p->state.wm.SURFACE_STATE[offset];
-
-         session->binding_table_fs_changed = true;
-      }
-      else {
-         skip = true;
-      }
-      break;
-   default:
-      skip = true;
-      break;
-   }
-
-   if (skip)
-      return;
-
-   for (i = 0; i < view->count; i++) {
-      if (view->states[i]) {
-         const struct ilo_view_cso *cso =
-            (const struct ilo_view_cso *) view->states[i];
-
-         surface_state[i] =
-            gen6_SURFACE_STATE(p->builder, &cso->surface, false);
-      }
-      else {
-         surface_state[i] = 0;
-      }
-   }
-
-   memset(&surface_state[i], 0, (ILO_MAX_SAMPLER_VIEWS - i) * 4);
-
-   if (i && session->num_surfaces[shader_type] < offset + i)
-      session->num_surfaces[shader_type] = offset + i;
-}
-
-static void
-gen6_pipeline_state_surfaces_const(struct ilo_3d_pipeline *p,
-                                   const struct ilo_state_vector *vec,
-                                   int shader_type,
-                                   struct gen6_pipeline_session *session)
-{
-   const struct ilo_cbuf_state *cbuf = &vec->cbuf[shader_type];
-   uint32_t *surface_state;
-   bool *binding_table_changed;
-   int offset, count, i;
-
-   if (!DIRTY(CBUF))
-      return;
-
-   /* SURFACE_STATEs for constant buffers */
-   switch (shader_type) {
-   case PIPE_SHADER_VERTEX:
-      offset = ILO_VS_CONST_SURFACE(0);
-      surface_state = &p->state.vs.SURFACE_STATE[offset];
-      binding_table_changed = &session->binding_table_vs_changed;
-      break;
-   case PIPE_SHADER_FRAGMENT:
-      offset = ILO_WM_CONST_SURFACE(0);
-      surface_state = &p->state.wm.SURFACE_STATE[offset];
-      binding_table_changed = &session->binding_table_fs_changed;
-      break;
-   default:
-      return;
-      break;
-   }
-
-   /* constants are pushed via PCB */
-   if (cbuf->enabled_mask == 0x1 && !cbuf->cso[0].resource) {
-      memset(surface_state, 0, ILO_MAX_CONST_BUFFERS * 4);
-      return;
-   }
-
-   count = util_last_bit(cbuf->enabled_mask);
-   for (i = 0; i < count; i++) {
-      if (cbuf->cso[i].resource) {
-         surface_state[i] = gen6_SURFACE_STATE(p->builder,
-               &cbuf->cso[i].surface, false);
-      }
-      else {
-         surface_state[i] = 0;
-      }
-   }
-
-   memset(&surface_state[count], 0, (ILO_MAX_CONST_BUFFERS - count) * 4);
-
-   if (count && session->num_surfaces[shader_type] < offset + count)
-      session->num_surfaces[shader_type] = offset + count;
-
-   *binding_table_changed = true;
-}
-
-static void
-gen6_pipeline_state_binding_tables(struct ilo_3d_pipeline *p,
-                                   const struct ilo_state_vector *vec,
-                                   int shader_type,
-                                   struct gen6_pipeline_session *session)
-{
-   uint32_t *binding_table_state, *surface_state;
-   int *binding_table_state_size, size;
-   bool skip = false;
-
-   /* BINDING_TABLE_STATE */
-   switch (shader_type) {
-   case PIPE_SHADER_VERTEX:
-      surface_state = p->state.vs.SURFACE_STATE;
-      binding_table_state = &p->state.vs.BINDING_TABLE_STATE;
-      binding_table_state_size = &p->state.vs.BINDING_TABLE_STATE_size;
-
-      skip = !session->binding_table_vs_changed;
-      break;
-   case PIPE_SHADER_GEOMETRY:
-      surface_state = p->state.gs.SURFACE_STATE;
-      binding_table_state = &p->state.gs.BINDING_TABLE_STATE;
-      binding_table_state_size = &p->state.gs.BINDING_TABLE_STATE_size;
-
-      skip = !session->binding_table_gs_changed;
-      break;
-   case PIPE_SHADER_FRAGMENT:
-      surface_state = p->state.wm.SURFACE_STATE;
-      binding_table_state = &p->state.wm.BINDING_TABLE_STATE;
-      binding_table_state_size = &p->state.wm.BINDING_TABLE_STATE_size;
-
-      skip = !session->binding_table_fs_changed;
-      break;
-   default:
-      skip = true;
-      break;
-   }
-
-   if (skip)
-      return;
-
-   /*
-    * If we have seemingly less SURFACE_STATEs than before, it could be that
-    * we did not touch those reside at the tail in this upload.  Loop over
-    * them to figure out the real number of SURFACE_STATEs.
-    */
-   for (size = *binding_table_state_size;
-         size > session->num_surfaces[shader_type]; size--) {
-      if (surface_state[size - 1])
-         break;
-   }
-   if (size < session->num_surfaces[shader_type])
-      size = session->num_surfaces[shader_type];
-
-   *binding_table_state = gen6_BINDING_TABLE_STATE(p->builder,
-         surface_state, size);
-   *binding_table_state_size = size;
-}
-
-static void
-gen6_pipeline_state_samplers(struct ilo_3d_pipeline *p,
-                             const struct ilo_state_vector *vec,
-                             int shader_type,
-                             struct gen6_pipeline_session *session)
-{
-   const struct ilo_sampler_cso * const *samplers =
-      vec->sampler[shader_type].cso;
-   const struct pipe_sampler_view * const *views =
-      (const struct pipe_sampler_view **) vec->view[shader_type].states;
-   const int num_samplers = vec->sampler[shader_type].count;
-   const int num_views = vec->view[shader_type].count;
-   uint32_t *sampler_state, *border_color_state;
-   bool emit_border_color = false;
-   bool skip = false;
-
-   /* SAMPLER_BORDER_COLOR_STATE and SAMPLER_STATE */
-   switch (shader_type) {
-   case PIPE_SHADER_VERTEX:
-      if (DIRTY(SAMPLER_VS) || DIRTY(VIEW_VS)) {
-         sampler_state = &p->state.vs.SAMPLER_STATE;
-         border_color_state = p->state.vs.SAMPLER_BORDER_COLOR_STATE;
-
-         if (DIRTY(SAMPLER_VS))
-            emit_border_color = true;
-
-         session->sampler_state_vs_changed = true;
-      }
-      else {
-         skip = true;
-      }
-      break;
-   case PIPE_SHADER_FRAGMENT:
-      if (DIRTY(SAMPLER_FS) || DIRTY(VIEW_FS)) {
-         sampler_state = &p->state.wm.SAMPLER_STATE;
-         border_color_state = p->state.wm.SAMPLER_BORDER_COLOR_STATE;
-
-         if (DIRTY(SAMPLER_FS))
-            emit_border_color = true;
-
-         session->sampler_state_fs_changed = true;
-      }
-      else {
-         skip = true;
-      }
-      break;
-   default:
-      skip = true;
-      break;
-   }
-
-   if (skip)
-      return;
-
-   if (emit_border_color) {
-      int i;
-
-      for (i = 0; i < num_samplers; i++) {
-         border_color_state[i] = (samplers[i]) ?
-            gen6_SAMPLER_BORDER_COLOR_STATE(p->builder, samplers[i]) : 0;
-      }
-   }
-
-   /* should we take the minimum of num_samplers and num_views? */
-   *sampler_state = gen6_SAMPLER_STATE(p->builder,
-         samplers, views,
-         border_color_state,
-         MIN2(num_samplers, num_views));
-}
-
-static void
-gen6_pipeline_state_pcb(struct ilo_3d_pipeline *p,
-                        const struct ilo_state_vector *vec,
-                        struct gen6_pipeline_session *session)
-{
-   /* push constant buffer for VS */
-   if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) {
-      const int cbuf0_size = (vec->vs) ?
-            ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
-      const int clip_state_size = (vec->vs) ?
-            ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_VS_PCB_UCP_SIZE) : 0;
-      const int total_size = cbuf0_size + clip_state_size;
-
-      if (total_size) {
-         void *pcb;
-
-         p->state.vs.PUSH_CONSTANT_BUFFER =
-            gen6_push_constant_buffer(p->builder, total_size, &pcb);
-         p->state.vs.PUSH_CONSTANT_BUFFER_size = total_size;
-
-         if (cbuf0_size) {
-            const struct ilo_cbuf_state *cbuf =
-               &vec->cbuf[PIPE_SHADER_VERTEX];
-
-            if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
-               memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
-            }
-            else {
-               memcpy(pcb, cbuf->cso[0].user_buffer,
-                     cbuf->cso[0].user_buffer_size);
-               memset(pcb + cbuf->cso[0].user_buffer_size, 0,
-                     cbuf0_size - cbuf->cso[0].user_buffer_size);
-            }
-
-            pcb += cbuf0_size;
-         }
-
-         if (clip_state_size)
-            memcpy(pcb, &vec->clip, clip_state_size);
-
-         session->pcb_state_vs_changed = true;
-      }
-      else if (p->state.vs.PUSH_CONSTANT_BUFFER_size) {
-         p->state.vs.PUSH_CONSTANT_BUFFER = 0;
-         p->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
-
-         session->pcb_state_vs_changed = true;
-      }
-   }
-
-   /* push constant buffer for FS */
-   if (DIRTY(FS) || DIRTY(CBUF)) {
-      const int cbuf0_size = (vec->fs) ?
-         ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
-
-      if (cbuf0_size) {
-         const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_FRAGMENT];
-         void *pcb;
-
-         p->state.wm.PUSH_CONSTANT_BUFFER =
-            gen6_push_constant_buffer(p->builder, cbuf0_size, &pcb);
-         p->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size;
-
-         if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
-            memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
-         }
-         else {
-            memcpy(pcb, cbuf->cso[0].user_buffer,
-                  cbuf->cso[0].user_buffer_size);
-            memset(pcb + cbuf->cso[0].user_buffer_size, 0,
-                  cbuf0_size - cbuf->cso[0].user_buffer_size);
-         }
-
-         session->pcb_state_fs_changed = true;
-      }
-      else if (p->state.wm.PUSH_CONSTANT_BUFFER_size) {
-         p->state.wm.PUSH_CONSTANT_BUFFER = 0;
-         p->state.wm.PUSH_CONSTANT_BUFFER_size = 0;
-
-         session->pcb_state_fs_changed = true;
-      }
-   }
-}
-
-#undef DIRTY
-
-static void
-gen6_pipeline_commands(struct ilo_3d_pipeline *p,
-                       const struct ilo_state_vector *vec,
-                       struct gen6_pipeline_session *session)
-{
-   /*
-    * We try to keep the order of the commands match, as closely as possible,
-    * that of the classic i965 driver.  It allows us to compare the command
-    * streams easily.
-    */
-   gen6_pipeline_common_select(p, vec, session);
-   gen6_pipeline_gs_svbi(p, vec, session);
-   gen6_pipeline_common_sip(p, vec, session);
-   gen6_pipeline_vf_statistics(p, vec, session);
-   gen6_pipeline_common_base_address(p, vec, session);
-   gen6_pipeline_common_pointers_1(p, vec, session);
-   gen6_pipeline_common_urb(p, vec, session);
-   gen6_pipeline_common_pointers_2(p, vec, session);
-   gen6_pipeline_wm_multisample(p, vec, session);
-   gen6_pipeline_vs(p, vec, session);
-   gen6_pipeline_gs(p, vec, session);
-   gen6_pipeline_clip(p, vec, session);
-   gen6_pipeline_sf(p, vec, session);
-   gen6_pipeline_wm(p, vec, session);
-   gen6_pipeline_common_pointers_3(p, vec, session);
-   gen6_pipeline_wm_depth(p, vec, session);
-   gen6_pipeline_wm_raster(p, vec, session);
-   gen6_pipeline_sf_rect(p, vec, session);
-   gen6_pipeline_vf(p, vec, session);
-   gen6_pipeline_vf_draw(p, vec, session);
-}
-
-void
-gen6_pipeline_states(struct ilo_3d_pipeline *p,
-                     const struct ilo_state_vector *vec,
-                     struct gen6_pipeline_session *session)
-{
-   int shader_type;
-
-   gen6_pipeline_state_viewports(p, vec, session);
-   gen6_pipeline_state_cc(p, vec, session);
-   gen6_pipeline_state_scissors(p, vec, session);
-   gen6_pipeline_state_pcb(p, vec, session);
-
-   /*
-    * upload all SURAFCE_STATEs together so that we know there are minimal
-    * paddings
-    */
-   gen6_pipeline_state_surfaces_rt(p, vec, session);
-   gen6_pipeline_state_surfaces_so(p, vec, session);
-   for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
-      gen6_pipeline_state_surfaces_view(p, vec, shader_type, session);
-      gen6_pipeline_state_surfaces_const(p, vec, shader_type, session);
-   }
-
-   for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
-      gen6_pipeline_state_samplers(p, vec, shader_type, session);
-      /* this must be called after all SURFACE_STATEs are uploaded */
-      gen6_pipeline_state_binding_tables(p, vec, shader_type, session);
-   }
-}
-
-void
-gen6_pipeline_prepare(const struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *vec,
-                      struct gen6_pipeline_session *session)
-{
-   memset(session, 0, sizeof(*session));
-   session->pipe_dirty = vec->dirty;
-   session->reduced_prim = u_reduced_prim(vec->draw->mode);
-
-   session->hw_ctx_changed =
-      (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_HW);
-
-   if (session->hw_ctx_changed) {
-      /* these should be enough to make everything uploaded */
-      session->batch_bo_changed = true;
-      session->state_bo_changed = true;
-      session->kernel_bo_changed = true;
-      session->prim_changed = true;
-      session->primitive_restart_changed = true;
-   } else {
-      /*
-       * Any state that involves resources needs to be re-emitted when the
-       * batch bo changed.  This is because we do not pin the resources and
-       * their offsets (or existence) may change between batch buffers.
-       */
-      session->batch_bo_changed =
-         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_BATCH_BO);
-
-      session->state_bo_changed =
-         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_STATE_BO);
-      session->kernel_bo_changed =
-         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO);
-      session->prim_changed = (p->state.reduced_prim != session->reduced_prim);
-      session->primitive_restart_changed =
-         (p->state.primitive_restart != vec->draw->primitive_restart);
-   }
-}
-
-void
-gen6_pipeline_draw(struct ilo_3d_pipeline *p,
-                   const struct ilo_state_vector *vec,
-                   struct gen6_pipeline_session *session)
-{
-   /* force all states to be uploaded if the state bo changed */
-   if (session->state_bo_changed)
-      session->pipe_dirty = ILO_DIRTY_ALL;
-   else
-      session->pipe_dirty = vec->dirty;
-
-   session->emit_draw_states(p, vec, session);
-
-   /* force all commands to be uploaded if the HW context changed */
-   if (session->hw_ctx_changed)
-      session->pipe_dirty = ILO_DIRTY_ALL;
-   else
-      session->pipe_dirty = vec->dirty;
-
-   session->emit_draw_commands(p, vec, session);
-}
-
-void
-gen6_pipeline_end(struct ilo_3d_pipeline *p,
-                  const struct ilo_state_vector *vec,
-                  struct gen6_pipeline_session *session)
-{
-   p->state.reduced_prim = session->reduced_prim;
-   p->state.primitive_restart = vec->draw->primitive_restart;
-}
-
-static void
-ilo_3d_pipeline_emit_draw_gen6(struct ilo_3d_pipeline *p,
-                               const struct ilo_state_vector *vec)
-{
-   struct gen6_pipeline_session session;
-
-   gen6_pipeline_prepare(p, vec, &session);
-
-   session.emit_draw_states = gen6_pipeline_states;
-   session.emit_draw_commands = gen6_pipeline_commands;
-
-   gen6_pipeline_draw(p, vec, &session);
-   gen6_pipeline_end(p, vec, &session);
-}
-
-void
-ilo_3d_pipeline_emit_flush_gen6(struct ilo_3d_pipeline *p)
-{
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
-                        GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
-                        GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
-                        GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE |
-                        GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
-                        GEN6_PIPE_CONTROL_CS_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 6, 7.5);
-
-   if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-      gen6_wa_pre_pipe_control(p, dw1);
-
-   gen6_PIPE_CONTROL(p->builder, dw1, NULL, 0, false);
-
-   p->state.current_pipe_control_dw1 |= dw1;
-   p->state.deferred_pipe_control_dw1 &= ~dw1;
-}
-
-void
-ilo_3d_pipeline_emit_query_gen6(struct ilo_3d_pipeline *p,
-                                struct ilo_query *q, uint32_t offset)
-{
-   const uint32_t pipeline_statistics_regs[] = {
-      GEN6_REG_IA_VERTICES_COUNT,
-      GEN6_REG_IA_PRIMITIVES_COUNT,
-      GEN6_REG_VS_INVOCATION_COUNT,
-      GEN6_REG_GS_INVOCATION_COUNT,
-      GEN6_REG_GS_PRIMITIVES_COUNT,
-      GEN6_REG_CL_INVOCATION_COUNT,
-      GEN6_REG_CL_PRIMITIVES_COUNT,
-      GEN6_REG_PS_INVOCATION_COUNT,
-      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ? GEN7_REG_HS_INVOCATION_COUNT : 0,
-      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ? GEN7_REG_DS_INVOCATION_COUNT : 0,
-      0,
-   };
-   const uint32_t primitives_generated_reg =
-      (ilo_dev_gen(p->dev) >= ILO_GEN(7) && q->index > 0) ?
-      GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
-      GEN6_REG_CL_INVOCATION_COUNT;
-   const uint32_t primitives_emitted_reg =
-      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ?
-      GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
-      GEN6_REG_SO_NUM_PRIMS_WRITTEN;
-   const uint32_t *regs;
-   int reg_count = 0, i;
-   uint32_t pipe_control_dw1 = 0;
-
-   ILO_DEV_ASSERT(p->dev, 6, 7.5);
-
-   switch (q->type) {
-   case PIPE_QUERY_OCCLUSION_COUNTER:
-      pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
-                         GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
-      break;
-   case PIPE_QUERY_TIMESTAMP:
-   case PIPE_QUERY_TIME_ELAPSED:
-      pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
-      break;
-   case PIPE_QUERY_PRIMITIVES_GENERATED:
-      regs = &primitives_generated_reg;
-      reg_count = 1;
-      break;
-   case PIPE_QUERY_PRIMITIVES_EMITTED:
-      regs = &primitives_emitted_reg;
-      reg_count = 1;
-      break;
-   case PIPE_QUERY_PIPELINE_STATISTICS:
-      regs = pipeline_statistics_regs;
-      reg_count = Elements(pipeline_statistics_regs);
-      break;
-   default:
-      break;
-   }
-
-   if (pipe_control_dw1) {
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         gen6_wa_pre_pipe_control(p, pipe_control_dw1);
-
-      gen6_PIPE_CONTROL(p->builder, pipe_control_dw1, q->bo, offset, true);
-
-      p->state.current_pipe_control_dw1 |= pipe_control_dw1;
-      p->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
-   }
-
-   if (!reg_count)
-      return;
-
-   p->emit_flush(p);
-
-   for (i = 0; i < reg_count; i++) {
-      if (regs[i]) {
-         /* store lower 32 bits */
-         gen6_MI_STORE_REGISTER_MEM(p->builder, q->bo, offset, regs[i]);
-         /* store higher 32 bits */
-         gen6_MI_STORE_REGISTER_MEM(p->builder, q->bo,
-               offset + 4, regs[i] + 4);
-      } else {
-         gen6_MI_STORE_DATA_IMM(p->builder, q->bo, offset, 0, true);
-      }
-
-      offset += 8;
-   }
-}
-
-static void
-gen6_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen6_3DSTATE_CONSTANT_VS(p->builder, NULL, NULL, 0);
-   gen6_3DSTATE_VS(p->builder, NULL, 0);
-
-   gen6_wa_post_3dstate_constant_vs(p);
-
-   gen6_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
-   gen6_3DSTATE_GS(p->builder, NULL, NULL, 0);
-
-   gen6_3DSTATE_CLIP(p->builder, NULL, NULL, false, 0);
-   gen6_3DSTATE_SF(p->builder, NULL, NULL);
-}
-
-static void
-gen6_rectlist_wm(struct ilo_3d_pipeline *p,
-                 const struct ilo_blitter *blitter,
-                 struct gen6_rectlist_session *session)
-{
-   uint32_t hiz_op;
-
-   switch (blitter->op) {
-   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
-      hiz_op = GEN6_WM_DW4_DEPTH_CLEAR;
-      break;
-   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
-      hiz_op = GEN6_WM_DW4_DEPTH_RESOLVE;
-      break;
-   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
-      hiz_op = GEN6_WM_DW4_HIZ_RESOLVE;
-      break;
-   default:
-      hiz_op = 0;
-      break;
-   }
-
-   gen6_3DSTATE_CONSTANT_PS(p->builder, NULL, NULL, 0);
-
-   gen6_wa_pre_3dstate_wm_max_threads(p);
-   gen6_3DSTATE_WM(p->builder, NULL, 0, NULL, false, false, hiz_op);
-}
-
-static void
-gen6_rectlist_wm_depth(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen6_wa_pre_depth(p);
-
-   if (blitter->uses & (ILO_BLITTER_USE_FB_DEPTH |
-                        ILO_BLITTER_USE_FB_STENCIL)) {
-      gen6_3DSTATE_DEPTH_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
-      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
-      gen6_3DSTATE_STENCIL_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   gen6_3DSTATE_CLEAR_PARAMS(p->builder,
-         blitter->depth_clear_value);
-}
-
-static void
-gen6_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
-                             const struct ilo_blitter *blitter,
-                             struct gen6_rectlist_session *session)
-{
-   const uint32_t *packed_sample_pos = (blitter->fb.num_samples > 1) ?
-      &p->packed_sample_position_4x : &p->packed_sample_position_1x;
-
-   gen6_wa_pre_3dstate_multisample(p);
-
-   gen6_3DSTATE_MULTISAMPLE(p->builder, blitter->fb.num_samples,
-         packed_sample_pos, true);
-
-   gen6_3DSTATE_SAMPLE_MASK(p->builder,
-         (1 << blitter->fb.num_samples) - 1);
-}
-
-static void
-gen6_rectlist_commands(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen6_wa_pre_non_pipelined(p);
-
-   gen6_rectlist_wm_multisample(p, blitter, session);
-
-   gen6_state_base_address(p->builder, true);
-
-   gen6_3DSTATE_VERTEX_BUFFERS(p->builder,
-         &blitter->ve, &blitter->vb);
-
-   gen6_3DSTATE_VERTEX_ELEMENTS(p->builder,
-         &blitter->ve, false, false);
-
-   gen6_3DSTATE_URB(p->builder,
-         p->dev->urb_size, 0, blitter->ve.count * 4 * sizeof(float), 0);
-   /* 3DSTATE_URB workaround */
-   if (p->state.gs.active) {
-      ilo_3d_pipeline_emit_flush_gen6(p);
-      p->state.gs.active = false;
-   }
-
-   if (blitter->uses &
-       (ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_CC)) {
-      gen6_3DSTATE_CC_STATE_POINTERS(p->builder, 0,
-            session->DEPTH_STENCIL_STATE, session->COLOR_CALC_STATE);
-   }
-
-   gen6_rectlist_vs_to_sf(p, blitter, session);
-   gen6_rectlist_wm(p, blitter, session);
-
-   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
-      gen6_3DSTATE_VIEWPORT_STATE_POINTERS(p->builder,
-            0, 0, session->CC_VIEWPORT);
-   }
-
-   gen6_rectlist_wm_depth(p, blitter, session);
-
-   gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
-         blitter->fb.width, blitter->fb.height);
-
-   gen6_3DPRIMITIVE(p->builder, &blitter->draw, NULL);
-}
-
-static void
-gen6_rectlist_states(struct ilo_3d_pipeline *p,
-                     const struct ilo_blitter *blitter,
-                     struct gen6_rectlist_session *session)
-{
-   if (blitter->uses & ILO_BLITTER_USE_DSA) {
-      session->DEPTH_STENCIL_STATE =
-         gen6_DEPTH_STENCIL_STATE(p->builder, &blitter->dsa);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_CC) {
-      session->COLOR_CALC_STATE =
-         gen6_COLOR_CALC_STATE(p->builder, &blitter->cc.stencil_ref,
-               blitter->cc.alpha_ref, &blitter->cc.blend_color);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
-      session->CC_VIEWPORT =
-         gen6_CC_VIEWPORT(p->builder, &blitter->viewport, 1);
-   }
-}
-
-static void
-ilo_3d_pipeline_emit_rectlist_gen6(struct ilo_3d_pipeline *p,
-                                   const struct ilo_blitter *blitter)
-{
-   struct gen6_rectlist_session session;
-
-   memset(&session, 0, sizeof(session));
-   gen6_rectlist_states(p, blitter, &session);
-   gen6_rectlist_commands(p, blitter, &session);
-}
-
-static int
-gen6_pipeline_max_command_size(const struct ilo_3d_pipeline *p)
-{
-   static int size;
-
-   if (!size) {
-      size += GEN6_3DSTATE_CONSTANT_ANY__SIZE * 3;
-      size += GEN6_3DSTATE_GS_SVB_INDEX__SIZE * 4;
-      size += GEN6_PIPE_CONTROL__SIZE * 5;
-
-      size +=
-         GEN6_STATE_BASE_ADDRESS__SIZE +
-         GEN6_STATE_SIP__SIZE +
-         GEN6_3DSTATE_VF_STATISTICS__SIZE +
-         GEN6_PIPELINE_SELECT__SIZE +
-         GEN6_3DSTATE_BINDING_TABLE_POINTERS__SIZE +
-         GEN6_3DSTATE_SAMPLER_STATE_POINTERS__SIZE +
-         GEN6_3DSTATE_URB__SIZE +
-         GEN6_3DSTATE_VERTEX_BUFFERS__SIZE +
-         GEN6_3DSTATE_VERTEX_ELEMENTS__SIZE +
-         GEN6_3DSTATE_INDEX_BUFFER__SIZE +
-         GEN6_3DSTATE_VIEWPORT_STATE_POINTERS__SIZE +
-         GEN6_3DSTATE_CC_STATE_POINTERS__SIZE +
-         GEN6_3DSTATE_SCISSOR_STATE_POINTERS__SIZE +
-         GEN6_3DSTATE_VS__SIZE +
-         GEN6_3DSTATE_GS__SIZE +
-         GEN6_3DSTATE_CLIP__SIZE +
-         GEN6_3DSTATE_SF__SIZE +
-         GEN6_3DSTATE_WM__SIZE +
-         GEN6_3DSTATE_SAMPLE_MASK__SIZE +
-         GEN6_3DSTATE_DRAWING_RECTANGLE__SIZE +
-         GEN6_3DSTATE_DEPTH_BUFFER__SIZE +
-         GEN6_3DSTATE_POLY_STIPPLE_OFFSET__SIZE +
-         GEN6_3DSTATE_POLY_STIPPLE_PATTERN__SIZE +
-         GEN6_3DSTATE_LINE_STIPPLE__SIZE +
-         GEN6_3DSTATE_AA_LINE_PARAMETERS__SIZE +
-         GEN6_3DSTATE_MULTISAMPLE__SIZE +
-         GEN6_3DSTATE_STENCIL_BUFFER__SIZE +
-         GEN6_3DSTATE_HIER_DEPTH_BUFFER__SIZE +
-         GEN6_3DSTATE_CLEAR_PARAMS__SIZE +
-         GEN6_3DPRIMITIVE__SIZE;
-   }
-
-   return size;
-}
-
-int
-gen6_pipeline_estimate_state_size(const struct ilo_3d_pipeline *p,
-                                  const struct ilo_state_vector *vec)
-{
-   static int static_size;
-   int sh_type, size;
-
-   if (!static_size) {
-      /* 64 bytes, or 16 dwords */
-      const int alignment = 64 / 4;
-
-      /* pad first */
-      size = alignment - 1;
-
-      /* CC states */
-      size += align(GEN6_BLEND_STATE__SIZE * ILO_MAX_DRAW_BUFFERS, alignment);
-      size += align(GEN6_DEPTH_STENCIL_STATE__SIZE, alignment);
-      size += align(GEN6_COLOR_CALC_STATE__SIZE, alignment);
-
-      /* viewport arrays */
-      if (ilo_dev_gen(p->dev) >= ILO_GEN(7)) {
-         size +=
-            align(GEN7_SF_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 16) +
-            align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
-            align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
-      }
-      else {
-         size +=
-            align(GEN6_SF_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
-            align(GEN6_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
-            align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
-            align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
-      }
-
-      static_size = size;
-   }
-
-   size = static_size;
-
-   for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) {
-      const int alignment = 32 / 4;
-      int num_samplers, num_surfaces, pcb_size;
-
-      /* samplers */
-      num_samplers = vec->sampler[sh_type].count;
-
-      /* sampler views and constant buffers */
-      num_surfaces = vec->view[sh_type].count +
-         util_bitcount(vec->cbuf[sh_type].enabled_mask);
-
-      pcb_size = 0;
-
-      switch (sh_type) {
-      case PIPE_SHADER_VERTEX:
-         if (vec->vs) {
-            if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
-               const struct pipe_stream_output_info *so_info =
-                  ilo_shader_get_kernel_so_info(vec->vs);
-
-               /* stream outputs */
-               num_surfaces += so_info->num_outputs;
-            }
-
-            pcb_size = ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_PCB_CBUF0_SIZE);
-            pcb_size += ilo_shader_get_kernel_param(vec->vs,
-                  ILO_KERNEL_VS_PCB_UCP_SIZE);
-         }
-         break;
-      case PIPE_SHADER_GEOMETRY:
-         if (vec->gs && ilo_dev_gen(p->dev) == ILO_GEN(6)) {
-            const struct pipe_stream_output_info *so_info =
-               ilo_shader_get_kernel_so_info(vec->gs);
-
-            /* stream outputs */
-            num_surfaces += so_info->num_outputs;
-         }
-         break;
-      case PIPE_SHADER_FRAGMENT:
-         /* render targets */
-         num_surfaces += vec->fb.state.nr_cbufs;
-
-         if (vec->fs) {
-            pcb_size = ilo_shader_get_kernel_param(vec->fs,
-                  ILO_KERNEL_PCB_CBUF0_SIZE);
-         }
-         break;
-      default:
-         break;
-      }
-
-      /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
-      if (num_samplers) {
-         size += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) +
-            align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers;
-      }
-
-      /* BINDING_TABLE_STATE and SURFACE_STATEs */
-      if (num_surfaces) {
-         size += align(num_surfaces, alignment) +
-            align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces;
-      }
-
-      /* PCB */
-      if (pcb_size)
-         size += align(pcb_size, alignment);
-   }
-
-   return size;
-}
-
-int
-gen6_pipeline_estimate_query_size(const struct ilo_3d_pipeline *p,
-                                  const struct ilo_query *q)
-{
-   int size;
-
-   ILO_DEV_ASSERT(p->dev, 6, 7.5);
-
-   switch (q->type) {
-   case PIPE_QUERY_OCCLUSION_COUNTER:
-      size = GEN6_PIPE_CONTROL__SIZE;
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         size *= 3;
-      break;
-   case PIPE_QUERY_TIMESTAMP:
-   case PIPE_QUERY_TIME_ELAPSED:
-      size = GEN6_PIPE_CONTROL__SIZE;
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         size *= 2;
-      break;
-   case PIPE_QUERY_PRIMITIVES_GENERATED:
-   case PIPE_QUERY_PRIMITIVES_EMITTED:
-      size = GEN6_PIPE_CONTROL__SIZE;
-      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
-         size *= 3;
-
-      size += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2;
-      break;
-   case PIPE_QUERY_PIPELINE_STATISTICS:
-      if (ilo_dev_gen(p->dev) >= ILO_GEN(7)) {
-         const int num_regs = 10;
-         const int num_pads = 1;
-
-         size = GEN6_PIPE_CONTROL__SIZE +
-            GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
-            GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
-      } else {
-         const int num_regs = 8;
-         const int num_pads = 3;
-
-         size = GEN6_PIPE_CONTROL__SIZE * 3 +
-            GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
-            GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
-      }
-      break;
-   default:
-      size = 0;
-      break;
-   }
-
-   return size;
-}
-
-static int
-ilo_3d_pipeline_estimate_size_gen6(struct ilo_3d_pipeline *p,
-                                   enum ilo_3d_pipeline_action action,
-                                   const void *arg)
-{
-   int size;
-
-   switch (action) {
-   case ILO_3D_PIPELINE_DRAW:
-      {
-         const struct ilo_state_vector *ilo = arg;
-
-         size = gen6_pipeline_max_command_size(p) +
-            gen6_pipeline_estimate_state_size(p, ilo);
-      }
-      break;
-   case ILO_3D_PIPELINE_FLUSH:
-      size = GEN6_PIPE_CONTROL__SIZE * 3;
-      break;
-   case ILO_3D_PIPELINE_QUERY:
-      size = gen6_pipeline_estimate_query_size(p,
-            (const struct ilo_query *) arg);
-      break;
-   case ILO_3D_PIPELINE_RECTLIST:
-      size = 64 + 256; /* states + commands */
-      break;
-   default:
-      assert(!"unknown 3D pipeline action");
-      size = 0;
-      break;
-   }
-
-   return size;
-}
-
-void
-ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p)
-{
-   p->estimate_size = ilo_3d_pipeline_estimate_size_gen6;
-   p->emit_draw = ilo_3d_pipeline_emit_draw_gen6;
-   p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
-   p->emit_query = ilo_3d_pipeline_emit_query_gen6;
-   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen6;
-}
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h
deleted file mode 100644 (file)
index 85a8985..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2012-2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#ifndef ILO_3D_PIPELINE_GEN6_H
-#define ILO_3D_PIPELINE_GEN6_H
-
-#include "ilo_common.h"
-
-struct ilo_3d_pipeline;
-struct ilo_query;
-struct ilo_state_vector;
-
-struct gen6_pipeline_session {
-   uint32_t pipe_dirty;
-
-   int reduced_prim;
-
-   bool hw_ctx_changed;
-   bool batch_bo_changed;
-   bool state_bo_changed;
-   bool kernel_bo_changed;
-   bool prim_changed;
-   bool primitive_restart_changed;
-
-   void (*emit_draw_states)(struct ilo_3d_pipeline *p,
-                            const struct ilo_state_vector *ilo,
-                            struct gen6_pipeline_session *session);
-
-   void (*emit_draw_commands)(struct ilo_3d_pipeline *p,
-                              const struct ilo_state_vector *ilo,
-                              struct gen6_pipeline_session *session);
-
-   /* indirect states */
-   bool viewport_state_changed;
-   bool cc_state_blend_changed;
-   bool cc_state_dsa_changed;
-   bool cc_state_cc_changed;
-   bool scissor_state_changed;
-   bool binding_table_vs_changed;
-   bool binding_table_gs_changed;
-   bool binding_table_fs_changed;
-   bool sampler_state_vs_changed;
-   bool sampler_state_gs_changed;
-   bool sampler_state_fs_changed;
-   bool pcb_state_vs_changed;
-   bool pcb_state_gs_changed;
-   bool pcb_state_fs_changed;
-
-   int num_surfaces[PIPE_SHADER_TYPES];
-};
-
-struct gen6_rectlist_session {
-   uint32_t DEPTH_STENCIL_STATE;
-   uint32_t COLOR_CALC_STATE;
-   uint32_t CC_VIEWPORT;
-};
-
-void
-gen6_pipeline_prepare(const struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *ilo,
-                      struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_draw(struct ilo_3d_pipeline *p,
-                   const struct ilo_state_vector *ilo,
-                   struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_end(struct ilo_3d_pipeline *p,
-                  const struct ilo_state_vector *ilo,
-                  struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_common_select(struct ilo_3d_pipeline *p,
-                            const struct ilo_state_vector *ilo,
-                            struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_common_sip(struct ilo_3d_pipeline *p,
-                         const struct ilo_state_vector *ilo,
-                         struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_common_base_address(struct ilo_3d_pipeline *p,
-                                  const struct ilo_state_vector *ilo,
-                                  struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_vf(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *ilo,
-                 struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_vf_statistics(struct ilo_3d_pipeline *p,
-                            const struct ilo_state_vector *ilo,
-                            struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_vs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *ilo,
-                 struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_clip(struct ilo_3d_pipeline *p,
-                   const struct ilo_state_vector *ilo,
-                   struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_sf_rect(struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *ilo,
-                      struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_wm_raster(struct ilo_3d_pipeline *p,
-                        const struct ilo_state_vector *ilo,
-                        struct gen6_pipeline_session *session);
-
-void
-gen6_pipeline_states(struct ilo_3d_pipeline *p,
-                     const struct ilo_state_vector *ilo,
-                     struct gen6_pipeline_session *session);
-
-int
-gen6_pipeline_estimate_state_size(const struct ilo_3d_pipeline *p,
-                                  const struct ilo_state_vector *ilo);
-
-int
-gen6_pipeline_estimate_query_size(const struct ilo_3d_pipeline *p,
-                                  const struct ilo_query *q);
-
-void
-ilo_3d_pipeline_emit_flush_gen6(struct ilo_3d_pipeline *p);
-
-void
-ilo_3d_pipeline_emit_query_gen6(struct ilo_3d_pipeline *p,
-                                struct ilo_query *q, uint32_t offset);
-
-void
-ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p);
-
-#endif /* ILO_3D_PIPELINE_GEN6_H */
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
deleted file mode 100644 (file)
index 51f663b..0000000
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#include "genhw/genhw.h"
-#include "util/u_dual_blend.h"
-
-#include "ilo_blitter.h"
-#include "ilo_builder_3d.h"
-#include "ilo_builder_render.h"
-#include "ilo_shader.h"
-#include "ilo_state.h"
-#include "ilo_3d_pipeline.h"
-#include "ilo_3d_pipeline_gen6.h"
-#include "ilo_3d_pipeline_gen7.h"
-
-/**
- * A wrapper for gen6_PIPE_CONTROL().
- */
-static inline void
-gen7_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
-{
-   struct intel_bo *bo = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) ?
-      p->workaround_bo : NULL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if (dw1 & GEN6_PIPE_CONTROL_CS_STALL) {
-      /* CS stall cannot be set alone */
-      const uint32_t mask = GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
-                            GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
-                            GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL |
-                            GEN6_PIPE_CONTROL_DEPTH_STALL |
-                            GEN6_PIPE_CONTROL_WRITE__MASK;
-      if (!(dw1 & mask))
-         dw1 |= GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
-   }
-
-   gen6_PIPE_CONTROL(p->builder, dw1, bo, 0, false);
-
-
-   p->state.current_pipe_control_dw1 |= dw1;
-   p->state.deferred_pipe_control_dw1 &= ~dw1;
-}
-
-static void
-gen7_wa_post_3dstate_push_constant_alloc_ps(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 292:
-    *
-    *     "A PIPE_CONTOL command with the CS Stall bit set must be programmed
-    *      in the ring after this instruction
-    *      (3DSTATE_PUSH_CONSTANT_ALLOC_PS)."
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   p->state.deferred_pipe_control_dw1 |= dw1;
-}
-
-static void
-gen7_wa_pre_vs(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 106:
-    *
-    *     "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth stall
-    *      needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS,
-    *      3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS,
-    *      3DSTATE_SAMPLER_STATE_POINTER_VS command.  Only one PIPE_CONTROL
-    *      needs to be sent before any combination of VS associated 3DSTATE."
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
-                        GEN6_PIPE_CONTROL_WRITE_IMM;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen7_pipe_control(p, dw1);
-}
-
-static void
-gen7_wa_pre_3dstate_sf_depth_bias(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 258:
-    *
-    *     "Due to an HW issue driver needs to send a pipe control with stall
-    *      when ever there is state change in depth bias related state (in
-    *      3DSTATE_SF)"
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen7_pipe_control(p, dw1);
-}
-
-static void
-gen7_wa_pre_3dstate_multisample(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 304:
-    *
-    *     "Driver must ierarchi that all the caches in the depth pipe are
-    *      flushed before this command (3DSTATE_MULTISAMPLE) is parsed. This
-    *      requires driver to send a PIPE_CONTROL with a CS stall along with a
-    *      Depth Flush prior to this command.
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
-                        GEN6_PIPE_CONTROL_CS_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen7_pipe_control(p, dw1);
-}
-
-static void
-gen7_wa_pre_depth(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
-    *
-    *     "Driver must send a least one PIPE_CONTROL command with CS Stall and
-    *      a post sync operation prior to the group of depth
-    *      commands(3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
-    *      3DSTATE_STENCIL_BUFFER, and 3DSTATE_HIER_DEPTH_BUFFER)."
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL |
-                        GEN6_PIPE_CONTROL_WRITE_IMM;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen7_pipe_control(p, dw1);
-
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
-    *
-    *     "Restriction: Prior to changing Depth/Stencil Buffer state (i.e.,
-    *      any combination of 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
-    *      3DSTATE_STENCIL_BUFFER, 3DSTATE_HIER_DEPTH_BUFFER) SW must first
-    *      issue a pipelined depth stall (PIPE_CONTROL with Depth Stall bit
-    *      set), followed by a pipelined depth cache flush (PIPE_CONTROL with
-    *      Depth Flush Bit set, followed by another pipelined depth stall
-    *      (PIPE_CONTROL with Depth Stall Bit set), unless SW can otherwise
-    *      guarantee that the pipeline from WM onwards is already flushed
-    *      (e.g., via a preceding MI_FLUSH)."
-    */
-   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
-   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
-   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
-}
-
-static void
-gen7_wa_pre_3dstate_ps_max_threads(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 286:
-    *
-    *     "If this field (Maximum Number of Threads in 3DSTATE_PS) is changed
-    *      between 3DPRIMITIVE commands, a PIPE_CONTROL command with Stall at
-    *      Pixel Scoreboard set is required to be issued."
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
-      gen7_pipe_control(p, dw1);
-}
-
-static void
-gen7_wa_post_ps_and_later(struct ilo_3d_pipeline *p)
-{
-   /*
-    * From the Ivy Bridge PRM, volume 2 part 1, page 276:
-    *
-    *     "The driver must make sure a PIPE_CONTROL with the Depth Stall
-    *      Enable bit set after all the following states are programmed:
-    *
-    *       - 3DSTATE_PS
-    *       - 3DSTATE_VIEWPORT_STATE_POINTERS_CC
-    *       - 3DSTATE_CONSTANT_PS
-    *       - 3DSTATE_BINDING_TABLE_POINTERS_PS
-    *       - 3DSTATE_SAMPLER_STATE_POINTERS_PS
-    *       - 3DSTATE_CC_STATE_POINTERS
-    *       - 3DSTATE_BLEND_STATE_POINTERS
-    *       - 3DSTATE_DEPTH_STENCIL_STATE_POINTERS"
-    */
-   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL;
-
-   ILO_DEV_ASSERT(p->dev, 7, 7.5);
-
-   p->state.deferred_pipe_control_dw1 |= dw1;
-}
-
-#define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
-
-static void
-gen7_pipeline_common_urb(struct ilo_3d_pipeline *p,
-                         const struct ilo_state_vector *vec,
-                         struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_URB_{VS,GS,HS,DS} */
-   if (DIRTY(VE) || DIRTY(VS)) {
-      /* the first 16KB are reserved for VS and PS PCBs */
-      const int offset = (ilo_dev_gen(p->dev) == ILO_GEN(7.5) &&
-            p->dev->gt == 3) ? 32768 : 16384;
-      int vs_entry_size, vs_total_size;
-
-      vs_entry_size = (vec->vs) ?
-         ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT) : 0;
-
-      /*
-       * From the Ivy Bridge PRM, volume 2 part 1, page 35:
-       *
-       *     "Programming Restriction: As the VS URB entry serves as both the
-       *      per-vertex input and output of the VS shader, the VS URB
-       *      Allocation Size must be sized to the maximum of the vertex input
-       *      and output structures."
-       */
-      if (vs_entry_size < vec->ve->count)
-         vs_entry_size = vec->ve->count;
-
-      vs_entry_size *= sizeof(float) * 4;
-      vs_total_size = p->dev->urb_size - offset;
-
-      gen7_wa_pre_vs(p);
-
-      gen7_3DSTATE_URB_VS(p->builder,
-            offset, vs_total_size, vs_entry_size);
-
-      gen7_3DSTATE_URB_GS(p->builder, offset, 0, 0);
-      gen7_3DSTATE_URB_HS(p->builder, offset, 0, 0);
-      gen7_3DSTATE_URB_DS(p->builder, offset, 0, 0);
-   }
-}
-
-static void
-gen7_pipeline_common_pcb_alloc(struct ilo_3d_pipeline *p,
-                               const struct ilo_state_vector *vec,
-                               struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_PUSH_CONSTANT_ALLOC_{VS,PS} */
-   if (session->hw_ctx_changed) {
-      /*
-       * Push constant buffers are only allowed to take up at most the first
-       * 16KB of the URB.  Split the space evenly for VS and FS.
-       */
-      const int max_size = (ilo_dev_gen(p->dev) == ILO_GEN(7.5) &&
-            p->dev->gt == 3) ? 32768 : 16384;
-      const int size = max_size / 2;
-      int offset = 0;
-
-      gen7_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->builder, offset, size);
-      offset += size;
-
-      gen7_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->builder, offset, size);
-
-      if (ilo_dev_gen(p->dev) == ILO_GEN(7))
-         gen7_wa_post_3dstate_push_constant_alloc_ps(p);
-   }
-}
-
-static void
-gen7_pipeline_common_pointers_1(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_VIEWPORT_STATE_POINTERS_{CC,SF_CLIP} */
-   if (session->viewport_state_changed) {
-      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->builder,
-            p->state.CC_VIEWPORT);
-
-      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP(p->builder,
-            p->state.SF_CLIP_VIEWPORT);
-   }
-}
-
-static void
-gen7_pipeline_common_pointers_2(struct ilo_3d_pipeline *p,
-                                const struct ilo_state_vector *vec,
-                                struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_BLEND_STATE_POINTERS */
-   if (session->cc_state_blend_changed) {
-      gen7_3DSTATE_BLEND_STATE_POINTERS(p->builder,
-            p->state.BLEND_STATE);
-   }
-
-   /* 3DSTATE_CC_STATE_POINTERS */
-   if (session->cc_state_cc_changed) {
-      gen7_3DSTATE_CC_STATE_POINTERS(p->builder,
-            p->state.COLOR_CALC_STATE);
-   }
-
-   /* 3DSTATE_DEPTH_STENCIL_STATE_POINTERS */
-   if (session->cc_state_dsa_changed) {
-      gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->builder,
-            p->state.DEPTH_STENCIL_STATE);
-   }
-}
-
-static void
-gen7_pipeline_vs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   const bool emit_3dstate_binding_table = session->binding_table_vs_changed;
-   const bool emit_3dstate_sampler_state = session->sampler_state_vs_changed;
-   /* see gen6_pipeline_vs() */
-   const bool emit_3dstate_constant_vs = session->pcb_state_vs_changed;
-   const bool emit_3dstate_vs = (DIRTY(VS) || DIRTY(SAMPLER_VS) ||
-           session->kernel_bo_changed);
-
-   /* emit depth stall before any of the VS commands */
-   if (emit_3dstate_binding_table || emit_3dstate_sampler_state ||
-           emit_3dstate_constant_vs || emit_3dstate_vs)
-      gen7_wa_pre_vs(p);
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS_VS */
-   if (emit_3dstate_binding_table) {
-      gen7_3DSTATE_BINDING_TABLE_POINTERS_VS(p->builder,
-              p->state.vs.BINDING_TABLE_STATE);
-   }
-
-   /* 3DSTATE_SAMPLER_STATE_POINTERS_VS */
-   if (emit_3dstate_sampler_state) {
-      gen7_3DSTATE_SAMPLER_STATE_POINTERS_VS(p->builder,
-              p->state.vs.SAMPLER_STATE);
-   }
-
-   /* 3DSTATE_CONSTANT_VS */
-   if (emit_3dstate_constant_vs) {
-      gen7_3DSTATE_CONSTANT_VS(p->builder,
-              &p->state.vs.PUSH_CONSTANT_BUFFER,
-              &p->state.vs.PUSH_CONSTANT_BUFFER_size,
-              1);
-   }
-
-   /* 3DSTATE_VS */
-   if (emit_3dstate_vs) {
-      const int num_samplers = vec->sampler[PIPE_SHADER_VERTEX].count;
-
-      gen6_3DSTATE_VS(p->builder, vec->vs, num_samplers);
-   }
-}
-
-static void
-gen7_pipeline_hs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CONSTANT_HS and 3DSTATE_HS */
-   if (session->hw_ctx_changed) {
-      gen7_3DSTATE_CONSTANT_HS(p->builder, 0, 0, 0);
-      gen7_3DSTATE_HS(p->builder, NULL, 0);
-   }
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS_HS */
-   if (session->hw_ctx_changed)
-      gen7_3DSTATE_BINDING_TABLE_POINTERS_HS(p->builder, 0);
-}
-
-static void
-gen7_pipeline_te(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_TE */
-   if (session->hw_ctx_changed)
-      gen7_3DSTATE_TE(p->builder);
-}
-
-static void
-gen7_pipeline_ds(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CONSTANT_DS and 3DSTATE_DS */
-   if (session->hw_ctx_changed) {
-      gen7_3DSTATE_CONSTANT_DS(p->builder, 0, 0, 0);
-      gen7_3DSTATE_DS(p->builder, NULL, 0);
-   }
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS_DS */
-   if (session->hw_ctx_changed)
-      gen7_3DSTATE_BINDING_TABLE_POINTERS_DS(p->builder, 0);
-
-}
-
-static void
-gen7_pipeline_gs(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_CONSTANT_GS and 3DSTATE_GS */
-   if (session->hw_ctx_changed) {
-      gen7_3DSTATE_CONSTANT_GS(p->builder, 0, 0, 0);
-      gen7_3DSTATE_GS(p->builder, NULL, 0);
-   }
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS_GS */
-   if (session->binding_table_gs_changed) {
-      gen7_3DSTATE_BINDING_TABLE_POINTERS_GS(p->builder,
-            p->state.gs.BINDING_TABLE_STATE);
-   }
-}
-
-static void
-gen7_pipeline_sol(struct ilo_3d_pipeline *p,
-                  const struct ilo_state_vector *vec,
-                  struct gen6_pipeline_session *session)
-{
-   const struct pipe_stream_output_info *so_info;
-   const struct ilo_shader_state *shader;
-   bool dirty_sh = false;
-
-   if (vec->gs) {
-      shader = vec->gs;
-      dirty_sh = DIRTY(GS);
-   }
-   else {
-      shader = vec->vs;
-      dirty_sh = DIRTY(VS);
-   }
-
-   so_info = ilo_shader_get_kernel_so_info(shader);
-
-   /* 3DSTATE_SO_BUFFER */
-   if ((DIRTY(SO) || dirty_sh || session->batch_bo_changed) &&
-       vec->so.enabled) {
-      int i;
-
-      for (i = 0; i < vec->so.count; i++) {
-         const int stride = so_info->stride[i] * 4; /* in bytes */
-         int base = 0;
-
-         gen7_3DSTATE_SO_BUFFER(p->builder, i, base, stride,
-               vec->so.states[i]);
-      }
-
-      for (; i < 4; i++)
-         gen7_3DSTATE_SO_BUFFER(p->builder, i, 0, 0, NULL);
-   }
-
-   /* 3DSTATE_SO_DECL_LIST */
-   if (dirty_sh && vec->so.enabled)
-      gen7_3DSTATE_SO_DECL_LIST(p->builder, so_info);
-
-   /* 3DSTATE_STREAMOUT */
-   if (DIRTY(SO) || DIRTY(RASTERIZER) || dirty_sh) {
-      const unsigned buffer_mask = (1 << vec->so.count) - 1;
-      const int output_count = ilo_shader_get_kernel_param(shader,
-            ILO_KERNEL_OUTPUT_COUNT);
-
-      gen7_3DSTATE_STREAMOUT(p->builder, buffer_mask, output_count,
-            vec->rasterizer->state.rasterizer_discard);
-   }
-}
-
-static void
-gen7_pipeline_sf(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_SBE */
-   if (DIRTY(RASTERIZER) || DIRTY(FS))
-      gen7_3DSTATE_SBE(p->builder, vec->rasterizer, vec->fs);
-
-   /* 3DSTATE_SF */
-   if (DIRTY(RASTERIZER) || DIRTY(FB)) {
-      struct pipe_surface *zs = vec->fb.state.zsbuf;
-
-      gen7_wa_pre_3dstate_sf_depth_bias(p);
-      gen7_3DSTATE_SF(p->builder, vec->rasterizer,
-            (zs) ? zs->format : PIPE_FORMAT_NONE);
-   }
-}
-
-static void
-gen7_pipeline_wm(struct ilo_3d_pipeline *p,
-                 const struct ilo_state_vector *vec,
-                 struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_WM */
-   if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) || DIRTY(RASTERIZER)) {
-      const bool cc_may_kill = (vec->dsa->dw_alpha ||
-                                vec->blend->alpha_to_coverage);
-
-      gen7_3DSTATE_WM(p->builder, vec->fs,
-            vec->rasterizer, cc_may_kill, 0);
-   }
-
-   /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
-   if (session->binding_table_fs_changed) {
-      gen7_3DSTATE_BINDING_TABLE_POINTERS_PS(p->builder,
-            p->state.wm.BINDING_TABLE_STATE);
-   }
-
-   /* 3DSTATE_SAMPLER_STATE_POINTERS_PS */
-   if (session->sampler_state_fs_changed) {
-      gen7_3DSTATE_SAMPLER_STATE_POINTERS_PS(p->builder,
-            p->state.wm.SAMPLER_STATE);
-   }
-
-   /* 3DSTATE_CONSTANT_PS */
-   if (session->pcb_state_fs_changed) {
-      gen7_3DSTATE_CONSTANT_PS(p->builder,
-            &p->state.wm.PUSH_CONSTANT_BUFFER,
-            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
-            1);
-   }
-
-   /* 3DSTATE_PS */
-   if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) ||
-       session->kernel_bo_changed) {
-      const int num_samplers = vec->sampler[PIPE_SHADER_FRAGMENT].count;
-      const bool dual_blend = vec->blend->dual_blend;
-
-      if ((ilo_dev_gen(p->dev) == ILO_GEN(7) ||
-           ilo_dev_gen(p->dev) == ILO_GEN(7.5)) &&
-          session->hw_ctx_changed)
-         gen7_wa_pre_3dstate_ps_max_threads(p);
-
-      gen7_3DSTATE_PS(p->builder, vec->fs, num_samplers, dual_blend);
-   }
-
-   /* 3DSTATE_SCISSOR_STATE_POINTERS */
-   if (session->scissor_state_changed) {
-      gen6_3DSTATE_SCISSOR_STATE_POINTERS(p->builder,
-            p->state.SCISSOR_RECT);
-   }
-
-   /* XXX what is the best way to know if this workaround is needed? */
-   {
-      const bool emit_3dstate_ps =
-         (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND));
-      const bool emit_3dstate_depth_buffer =
-         (DIRTY(FB) || DIRTY(DSA) || session->state_bo_changed);
-
-      if (emit_3dstate_ps ||
-          session->pcb_state_fs_changed ||
-          session->viewport_state_changed ||
-          session->binding_table_fs_changed ||
-          session->sampler_state_fs_changed ||
-          session->cc_state_cc_changed ||
-          session->cc_state_blend_changed ||
-          session->cc_state_dsa_changed)
-         gen7_wa_post_ps_and_later(p);
-
-      if (emit_3dstate_depth_buffer)
-         gen7_wa_pre_depth(p);
-   }
-
-   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
-   if (DIRTY(FB) || session->batch_bo_changed) {
-      const struct ilo_zs_surface *zs;
-      uint32_t clear_params;
-
-      if (vec->fb.state.zsbuf) {
-         const struct ilo_surface_cso *surface =
-            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
-         const struct ilo_texture_slice *slice =
-            ilo_texture_get_slice(ilo_texture(surface->base.texture),
-                  surface->base.u.tex.level, surface->base.u.tex.first_layer);
-
-         assert(!surface->is_rt);
-         zs = &surface->u.zs;
-         clear_params = slice->clear_value;
-      }
-      else {
-         zs = &vec->fb.null_zs;
-         clear_params = 0;
-      }
-
-      gen6_3DSTATE_DEPTH_BUFFER(p->builder, zs);
-      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder, zs);
-      gen6_3DSTATE_STENCIL_BUFFER(p->builder, zs);
-      gen7_3DSTATE_CLEAR_PARAMS(p->builder, clear_params);
-   }
-}
-
-static void
-gen7_pipeline_wm_multisample(struct ilo_3d_pipeline *p,
-                             const struct ilo_state_vector *vec,
-                             struct gen6_pipeline_session *session)
-{
-   /* 3DSTATE_MULTISAMPLE and 3DSTATE_SAMPLE_MASK */
-   if (DIRTY(SAMPLE_MASK) || DIRTY(FB)) {
-      const uint32_t *packed_sample_pos;
-
-      gen7_wa_pre_3dstate_multisample(p);
-
-      packed_sample_pos =
-         (vec->fb.num_samples > 4) ? p->packed_sample_position_8x :
-         (vec->fb.num_samples > 1) ? &p->packed_sample_position_4x :
-         &p->packed_sample_position_1x;
-
-      gen6_3DSTATE_MULTISAMPLE(p->builder,
-            vec->fb.num_samples, packed_sample_pos,
-            vec->rasterizer->state.half_pixel_center);
-
-      gen7_3DSTATE_SAMPLE_MASK(p->builder,
-            (vec->fb.num_samples > 1) ? vec->sample_mask : 0x1,
-            vec->fb.num_samples);
-   }
-}
-
-static void
-gen7_pipeline_vf_draw(struct ilo_3d_pipeline *p,
-                      const struct ilo_state_vector *vec,
-                      struct gen6_pipeline_session *session)
-{
-   if (p->state.deferred_pipe_control_dw1)
-      gen7_pipe_control(p, p->state.deferred_pipe_control_dw1);
-
-   /* 3DPRIMITIVE */
-   gen7_3DPRIMITIVE(p->builder, vec->draw, &vec->ib);
-
-   p->state.current_pipe_control_dw1 = 0;
-   p->state.deferred_pipe_control_dw1 = 0;
-}
-
-static void
-gen7_pipeline_commands(struct ilo_3d_pipeline *p,
-                       const struct ilo_state_vector *vec,
-                       struct gen6_pipeline_session *session)
-{
-   /*
-    * We try to keep the order of the commands match, as closely as possible,
-    * that of the classic i965 driver.  It allows us to compare the command
-    * streams easily.
-    */
-   gen6_pipeline_common_select(p, vec, session);
-   gen6_pipeline_common_sip(p, vec, session);
-   gen6_pipeline_vf_statistics(p, vec, session);
-   gen7_pipeline_common_pcb_alloc(p, vec, session);
-   gen6_pipeline_common_base_address(p, vec, session);
-   gen7_pipeline_common_pointers_1(p, vec, session);
-   gen7_pipeline_common_urb(p, vec, session);
-   gen7_pipeline_common_pointers_2(p, vec, session);
-   gen7_pipeline_wm_multisample(p, vec, session);
-   gen7_pipeline_gs(p, vec, session);
-   gen7_pipeline_hs(p, vec, session);
-   gen7_pipeline_te(p, vec, session);
-   gen7_pipeline_ds(p, vec, session);
-   gen7_pipeline_vs(p, vec, session);
-   gen7_pipeline_sol(p, vec, session);
-   gen6_pipeline_clip(p, vec, session);
-   gen7_pipeline_sf(p, vec, session);
-   gen7_pipeline_wm(p, vec, session);
-   gen6_pipeline_wm_raster(p, vec, session);
-   gen6_pipeline_sf_rect(p, vec, session);
-   gen6_pipeline_vf(p, vec, session);
-   gen7_pipeline_vf_draw(p, vec, session);
-}
-
-static void
-ilo_3d_pipeline_emit_draw_gen7(struct ilo_3d_pipeline *p,
-                               const struct ilo_state_vector *vec)
-{
-   struct gen6_pipeline_session session;
-
-   gen6_pipeline_prepare(p, vec, &session);
-
-   session.emit_draw_states = gen6_pipeline_states;
-   session.emit_draw_commands = gen7_pipeline_commands;
-
-   gen6_pipeline_draw(p, vec, &session);
-   gen6_pipeline_end(p, vec, &session);
-}
-
-static void
-gen7_rectlist_pcb_alloc(struct ilo_3d_pipeline *p,
-                        const struct ilo_blitter *blitter,
-                        struct gen6_rectlist_session *session)
-{
-   /*
-    * Push constant buffers are only allowed to take up at most the first
-    * 16KB of the URB.  Split the space evenly for VS and FS.
-    */
-   const int max_size =
-      (ilo_dev_gen(p->dev) == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
-   const int size = max_size / 2;
-   int offset = 0;
-
-   gen7_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->builder, offset, size);
-   offset += size;
-
-   gen7_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->builder, offset, size);
-
-   gen7_wa_post_3dstate_push_constant_alloc_ps(p);
-}
-
-static void
-gen7_rectlist_urb(struct ilo_3d_pipeline *p,
-                  const struct ilo_blitter *blitter,
-                  struct gen6_rectlist_session *session)
-{
-   /* the first 16KB are reserved for VS and PS PCBs */
-   const int offset =
-      (ilo_dev_gen(p->dev) == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
-
-   gen7_3DSTATE_URB_VS(p->builder, offset, p->dev->urb_size - offset,
-         blitter->ve.count * 4 * sizeof(float));
-
-   gen7_3DSTATE_URB_GS(p->builder, offset, 0, 0);
-   gen7_3DSTATE_URB_HS(p->builder, offset, 0, 0);
-   gen7_3DSTATE_URB_DS(p->builder, offset, 0, 0);
-}
-
-static void
-gen7_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen7_3DSTATE_CONSTANT_VS(p->builder, NULL, NULL, 0);
-   gen6_3DSTATE_VS(p->builder, NULL, 0);
-
-   gen7_3DSTATE_CONSTANT_HS(p->builder, NULL, NULL, 0);
-   gen7_3DSTATE_HS(p->builder, NULL, 0);
-
-   gen7_3DSTATE_TE(p->builder);
-
-   gen7_3DSTATE_CONSTANT_DS(p->builder, NULL, NULL, 0);
-   gen7_3DSTATE_DS(p->builder, NULL, 0);
-
-   gen7_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
-   gen7_3DSTATE_GS(p->builder, NULL, 0);
-
-   gen7_3DSTATE_STREAMOUT(p->builder, 0x0, 0, false);
-
-   gen6_3DSTATE_CLIP(p->builder, NULL, NULL, false, 0);
-
-   gen7_wa_pre_3dstate_sf_depth_bias(p);
-
-   gen7_3DSTATE_SF(p->builder, NULL, blitter->fb.dst.base.format);
-   gen7_3DSTATE_SBE(p->builder, NULL, NULL);
-}
-
-static void
-gen7_rectlist_wm(struct ilo_3d_pipeline *p,
-                 const struct ilo_blitter *blitter,
-                 struct gen6_rectlist_session *session)
-{
-   uint32_t hiz_op;
-
-   switch (blitter->op) {
-   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
-      hiz_op = GEN7_WM_DW1_DEPTH_CLEAR;
-      break;
-   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
-      hiz_op = GEN7_WM_DW1_DEPTH_RESOLVE;
-      break;
-   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
-      hiz_op = GEN7_WM_DW1_HIZ_RESOLVE;
-      break;
-   default:
-      hiz_op = 0;
-      break;
-   }
-
-   gen7_3DSTATE_WM(p->builder, NULL, NULL, false, hiz_op);
-
-   gen7_3DSTATE_CONSTANT_PS(p->builder, NULL, NULL, 0);
-
-   gen7_wa_pre_3dstate_ps_max_threads(p);
-   gen7_3DSTATE_PS(p->builder, NULL, 0, false);
-}
-
-static void
-gen7_rectlist_wm_depth(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen7_wa_pre_depth(p);
-
-   if (blitter->uses & (ILO_BLITTER_USE_FB_DEPTH |
-                        ILO_BLITTER_USE_FB_STENCIL)) {
-      gen6_3DSTATE_DEPTH_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
-      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
-      gen6_3DSTATE_STENCIL_BUFFER(p->builder,
-            &blitter->fb.dst.u.zs);
-   }
-
-   gen7_3DSTATE_CLEAR_PARAMS(p->builder,
-         blitter->depth_clear_value);
-}
-
-static void
-gen7_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
-                             const struct ilo_blitter *blitter,
-                             struct gen6_rectlist_session *session)
-{
-   const uint32_t *packed_sample_pos =
-      (blitter->fb.num_samples > 4) ? p->packed_sample_position_8x :
-      (blitter->fb.num_samples > 1) ? &p->packed_sample_position_4x :
-      &p->packed_sample_position_1x;
-
-   gen7_wa_pre_3dstate_multisample(p);
-
-   gen6_3DSTATE_MULTISAMPLE(p->builder, blitter->fb.num_samples,
-         packed_sample_pos, true);
-
-   gen7_3DSTATE_SAMPLE_MASK(p->builder,
-         (1 << blitter->fb.num_samples) - 1, blitter->fb.num_samples);
-}
-
-static void
-gen7_rectlist_commands(struct ilo_3d_pipeline *p,
-                       const struct ilo_blitter *blitter,
-                       struct gen6_rectlist_session *session)
-{
-   gen7_rectlist_wm_multisample(p, blitter, session);
-
-   gen6_state_base_address(p->builder, true);
-
-   gen6_3DSTATE_VERTEX_BUFFERS(p->builder,
-         &blitter->ve, &blitter->vb);
-
-   gen6_3DSTATE_VERTEX_ELEMENTS(p->builder,
-         &blitter->ve, false, false);
-
-   gen7_rectlist_pcb_alloc(p, blitter, session);
-
-   /* needed for any VS-related commands */
-   gen7_wa_pre_vs(p);
-
-   gen7_rectlist_urb(p, blitter, session);
-
-   if (blitter->uses & ILO_BLITTER_USE_DSA) {
-      gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->builder,
-            session->DEPTH_STENCIL_STATE);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_CC) {
-      gen7_3DSTATE_CC_STATE_POINTERS(p->builder,
-            session->COLOR_CALC_STATE);
-   }
-
-   gen7_rectlist_vs_to_sf(p, blitter, session);
-   gen7_rectlist_wm(p, blitter, session);
-
-   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
-      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->builder,
-            session->CC_VIEWPORT);
-   }
-
-   gen7_rectlist_wm_depth(p, blitter, session);
-
-   gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
-         blitter->fb.width, blitter->fb.height);
-
-   gen7_3DPRIMITIVE(p->builder, &blitter->draw, NULL);
-}
-
-static void
-gen7_rectlist_states(struct ilo_3d_pipeline *p,
-                     const struct ilo_blitter *blitter,
-                     struct gen6_rectlist_session *session)
-{
-   if (blitter->uses & ILO_BLITTER_USE_DSA) {
-      session->DEPTH_STENCIL_STATE =
-         gen6_DEPTH_STENCIL_STATE(p->builder, &blitter->dsa);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_CC) {
-      session->COLOR_CALC_STATE =
-         gen6_COLOR_CALC_STATE(p->builder, &blitter->cc.stencil_ref,
-               blitter->cc.alpha_ref, &blitter->cc.blend_color);
-   }
-
-   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
-      session->CC_VIEWPORT =
-         gen6_CC_VIEWPORT(p->builder, &blitter->viewport, 1);
-   }
-}
-
-static void
-ilo_3d_pipeline_emit_rectlist_gen7(struct ilo_3d_pipeline *p,
-                                   const struct ilo_blitter *blitter)
-{
-   struct gen6_rectlist_session session;
-
-   memset(&session, 0, sizeof(session));
-   gen7_rectlist_states(p, blitter, &session);
-   gen7_rectlist_commands(p, blitter, &session);
-}
-
-static int
-gen7_pipeline_max_command_size(const struct ilo_3d_pipeline *p)
-{
-   static int size;
-
-   if (!size) {
-      size += GEN7_3DSTATE_URB_ANY__SIZE * 4;
-      size += GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_ANY__SIZE * 5;
-      size += GEN6_3DSTATE_CONSTANT_ANY__SIZE * 5;
-      size += GEN7_3DSTATE_POINTERS_ANY__SIZE * (5 + 5 + 4);
-      size += GEN7_3DSTATE_SO_BUFFER__SIZE * 4;
-      size += GEN6_PIPE_CONTROL__SIZE * 5;
-
-      size +=
-         GEN6_STATE_BASE_ADDRESS__SIZE +
-         GEN6_STATE_SIP__SIZE +
-         GEN6_3DSTATE_VF_STATISTICS__SIZE +
-         GEN6_PIPELINE_SELECT__SIZE +
-         GEN6_3DSTATE_CLEAR_PARAMS__SIZE +
-         GEN6_3DSTATE_DEPTH_BUFFER__SIZE +
-         GEN6_3DSTATE_STENCIL_BUFFER__SIZE +
-         GEN6_3DSTATE_HIER_DEPTH_BUFFER__SIZE +
-         GEN6_3DSTATE_VERTEX_BUFFERS__SIZE +
-         GEN6_3DSTATE_VERTEX_ELEMENTS__SIZE +
-         GEN6_3DSTATE_INDEX_BUFFER__SIZE +
-         GEN75_3DSTATE_VF__SIZE +
-         GEN6_3DSTATE_VS__SIZE +
-         GEN6_3DSTATE_GS__SIZE +
-         GEN6_3DSTATE_CLIP__SIZE +
-         GEN6_3DSTATE_SF__SIZE +
-         GEN6_3DSTATE_WM__SIZE +
-         GEN6_3DSTATE_SAMPLE_MASK__SIZE +
-         GEN7_3DSTATE_HS__SIZE +
-         GEN7_3DSTATE_TE__SIZE +
-         GEN7_3DSTATE_DS__SIZE +
-         GEN7_3DSTATE_STREAMOUT__SIZE +
-         GEN7_3DSTATE_SBE__SIZE +
-         GEN7_3DSTATE_PS__SIZE +
-         GEN6_3DSTATE_DRAWING_RECTANGLE__SIZE +
-         GEN6_3DSTATE_POLY_STIPPLE_OFFSET__SIZE +
-         GEN6_3DSTATE_POLY_STIPPLE_PATTERN__SIZE +
-         GEN6_3DSTATE_LINE_STIPPLE__SIZE +
-         GEN6_3DSTATE_AA_LINE_PARAMETERS__SIZE +
-         GEN6_3DSTATE_MULTISAMPLE__SIZE +
-         GEN7_3DSTATE_SO_DECL_LIST__SIZE +
-         GEN6_3DPRIMITIVE__SIZE;
-   }
-
-   return size;
-}
-
-static int
-ilo_3d_pipeline_estimate_size_gen7(struct ilo_3d_pipeline *p,
-                                   enum ilo_3d_pipeline_action action,
-                                   const void *arg)
-{
-   int size;
-
-   switch (action) {
-   case ILO_3D_PIPELINE_DRAW:
-      {
-         const struct ilo_state_vector *ilo = arg;
-
-         size = gen7_pipeline_max_command_size(p) +
-            gen6_pipeline_estimate_state_size(p, ilo);
-      }
-      break;
-   case ILO_3D_PIPELINE_FLUSH:
-      size = GEN6_PIPE_CONTROL__SIZE;
-      break;
-   case ILO_3D_PIPELINE_QUERY:
-      size = gen6_pipeline_estimate_query_size(p,
-            (const struct ilo_query *) arg);
-      break;
-   case ILO_3D_PIPELINE_RECTLIST:
-      size = 64 + 256; /* states + commands */
-      break;
-   default:
-      assert(!"unknown 3D pipeline action");
-      size = 0;
-      break;
-   }
-
-   return size;
-}
-
-void
-ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p)
-{
-   p->estimate_size = ilo_3d_pipeline_estimate_size_gen7;
-   p->emit_draw = ilo_3d_pipeline_emit_draw_gen7;
-   p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
-   p->emit_query = ilo_3d_pipeline_emit_query_gen6;
-   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen7;
-}
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.h b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.h
deleted file mode 100644 (file)
index a59f966..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2013 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Chia-I Wu <olv@lunarg.com>
- */
-
-#ifndef ILO_3D_PIPELINE_GEN7_H
-#define ILO_3D_PIPELINE_GEN7_H
-
-#include "ilo_common.h"
-
-struct ilo_3d_pipeline;
-
-void
-ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p);
-
-#endif /* ILO_3D_PIPELINE_GEN7_H */
index a155a41ac1b97dc1bbda6b51f74f579169dcf42b..19ea6a7d080f52b8841fd9fbedc86b34dc48950c 100644 (file)
@@ -28,7 +28,7 @@
 #include "util/u_prim.h"
 #include "intel_winsys.h"
 
-#include "ilo_3d_pipeline.h"
+#include "ilo_render.h"
 #include "ilo_blit.h"
 #include "ilo_context.h"
 #include "ilo_cp.h"
diff --git a/src/gallium/drivers/ilo/ilo_render.c b/src/gallium/drivers/ilo/ilo_render.c
new file mode 100644 (file)
index 0000000..2893a4f
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "intel_winsys.h"
+
+#include "ilo_builder.h"
+#include "ilo_render_gen.h"
+#include "ilo_render_gen7.h"
+#include "ilo_render.h"
+
+/* in U0.4 */
+struct sample_position {
+   uint8_t x, y;
+};
+
+/* \see gen6_get_sample_position() */
+static const struct sample_position sample_position_1x[1] = {
+   {  8,  8 },
+};
+
+static const struct sample_position sample_position_4x[4] = {
+   {  6,  2 }, /* distance from the center is sqrt(40) */
+   { 14,  6 }, /* distance from the center is sqrt(40) */
+   {  2, 10 }, /* distance from the center is sqrt(40) */
+   { 10, 14 }, /* distance from the center is sqrt(40) */
+};
+
+static const struct sample_position sample_position_8x[8] = {
+   {  7,  9 }, /* distance from the center is sqrt(2) */
+   {  9, 13 }, /* distance from the center is sqrt(26) */
+   { 11,  3 }, /* distance from the center is sqrt(34) */
+   { 13, 11 }, /* distance from the center is sqrt(34) */
+   {  1,  7 }, /* distance from the center is sqrt(50) */
+   {  5,  1 }, /* distance from the center is sqrt(58) */
+   { 15,  5 }, /* distance from the center is sqrt(58) */
+   {  3, 15 }, /* distance from the center is sqrt(74) */
+};
+
+struct ilo_3d_pipeline *
+ilo_3d_pipeline_create(struct ilo_builder *builder)
+{
+   struct ilo_3d_pipeline *p;
+   int i;
+
+   p = CALLOC_STRUCT(ilo_3d_pipeline);
+   if (!p)
+      return NULL;
+
+   p->dev = builder->dev;
+   p->builder = builder;
+
+   switch (ilo_dev_gen(p->dev)) {
+   case ILO_GEN(6):
+      ilo_3d_pipeline_init_gen6(p);
+      break;
+   case ILO_GEN(7):
+   case ILO_GEN(7.5):
+      ilo_3d_pipeline_init_gen7(p);
+      break;
+   default:
+      assert(!"unsupported GEN");
+      FREE(p);
+      return NULL;
+      break;
+   }
+
+   p->invalidate_flags = ILO_3D_PIPELINE_INVALIDATE_ALL;
+
+   p->workaround_bo = intel_winsys_alloc_buffer(builder->winsys,
+         "PIPE_CONTROL workaround", 4096, false);
+   if (!p->workaround_bo) {
+      ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
+      FREE(p);
+      return NULL;
+   }
+
+   p->packed_sample_position_1x =
+      sample_position_1x[0].x << 4 |
+      sample_position_1x[0].y;
+
+   /* pack into dwords */
+   for (i = 0; i < 4; i++) {
+      p->packed_sample_position_4x |=
+         sample_position_4x[i].x << (8 * i + 4) |
+         sample_position_4x[i].y << (8 * i);
+
+      p->packed_sample_position_8x[0] |=
+         sample_position_8x[i].x << (8 * i + 4) |
+         sample_position_8x[i].y << (8 * i);
+
+      p->packed_sample_position_8x[1] |=
+         sample_position_8x[4 + i].x << (8 * i + 4) |
+         sample_position_8x[4 + i].y << (8 * i);
+   }
+
+   return p;
+}
+
+void
+ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *p)
+{
+   if (p->workaround_bo)
+      intel_bo_unreference(p->workaround_bo);
+
+   FREE(p);
+}
+
+void
+ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
+                                    unsigned sample_count,
+                                    unsigned sample_index,
+                                    float *x, float *y)
+{
+   const struct sample_position *pos;
+
+   switch (sample_count) {
+   case 1:
+      assert(sample_index < Elements(sample_position_1x));
+      pos = sample_position_1x;
+      break;
+   case 4:
+      assert(sample_index < Elements(sample_position_4x));
+      pos = sample_position_4x;
+      break;
+   case 8:
+      assert(sample_index < Elements(sample_position_8x));
+      pos = sample_position_8x;
+      break;
+   default:
+      assert(!"unknown sample count");
+      *x = 0.5f;
+      *y = 0.5f;
+      return;
+      break;
+   }
+
+   *x = (float) pos[sample_index].x / 16.0f;
+   *y = (float) pos[sample_index].y / 16.0f;
+}
diff --git a/src/gallium/drivers/ilo/ilo_render.h b/src/gallium/drivers/ilo/ilo_render.h
new file mode 100644 (file)
index 0000000..eccf727
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef ILO_RENDER_H
+#define ILO_RENDER_H
+
+#include "ilo_common.h"
+#include "ilo_state.h"
+
+struct intel_bo;
+struct ilo_blitter;
+struct ilo_cp;
+struct ilo_query;
+struct ilo_state_vector;
+
+enum ilo_3d_pipeline_invalidate_flags {
+   ILO_3D_PIPELINE_INVALIDATE_HW         = 1 << 0,
+   ILO_3D_PIPELINE_INVALIDATE_BATCH_BO   = 1 << 1,
+   ILO_3D_PIPELINE_INVALIDATE_STATE_BO   = 1 << 2,
+   ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO  = 1 << 3,
+
+   ILO_3D_PIPELINE_INVALIDATE_ALL        = 0xffffffff,
+};
+
+enum ilo_3d_pipeline_action {
+   ILO_3D_PIPELINE_DRAW,
+   ILO_3D_PIPELINE_FLUSH,
+   ILO_3D_PIPELINE_QUERY,
+   ILO_3D_PIPELINE_RECTLIST,
+};
+
+/**
+ * 3D pipeline.
+ */
+struct ilo_3d_pipeline {
+   const struct ilo_dev_info *dev;
+   struct ilo_builder *builder;
+
+   uint32_t invalidate_flags;
+
+   struct intel_bo *workaround_bo;
+
+   uint32_t packed_sample_position_1x;
+   uint32_t packed_sample_position_4x;
+   uint32_t packed_sample_position_8x[2];
+
+   int (*estimate_size)(struct ilo_3d_pipeline *pipeline,
+                        enum ilo_3d_pipeline_action action,
+                        const void *arg);
+
+   void (*emit_draw)(struct ilo_3d_pipeline *pipeline,
+                     const struct ilo_state_vector *vec);
+
+   void (*emit_flush)(struct ilo_3d_pipeline *pipeline);
+
+   void (*emit_query)(struct ilo_3d_pipeline *pipeline,
+                      struct ilo_query *q, uint32_t offset);
+
+   void (*emit_rectlist)(struct ilo_3d_pipeline *pipeline,
+                         const struct ilo_blitter *blitter);
+
+   /**
+    * HW states.
+    */
+   struct ilo_3d_pipeline_state {
+      /*
+       * When a WA is needed before some command, we always emit the WA right
+       * before the command.  Knowing what have already been done since last
+       * 3DPRIMITIVE allows us to skip some WAs.
+       */
+      uint32_t current_pipe_control_dw1;
+
+      /*
+       * When a WA is needed after some command, we may have the WA follow the
+       * command immediately or defer it.  If this is non-zero, a PIPE_CONTROL
+       * will be emitted before 3DPRIMITIVE.
+       */
+      uint32_t deferred_pipe_control_dw1;
+
+      bool primitive_restart;
+      int reduced_prim;
+      int so_max_vertices;
+
+      uint32_t SF_VIEWPORT;
+      uint32_t CLIP_VIEWPORT;
+      uint32_t SF_CLIP_VIEWPORT; /* GEN7+ */
+      uint32_t CC_VIEWPORT;
+
+      uint32_t COLOR_CALC_STATE;
+      uint32_t BLEND_STATE;
+      uint32_t DEPTH_STENCIL_STATE;
+
+      uint32_t SCISSOR_RECT;
+
+      struct {
+         uint32_t BINDING_TABLE_STATE;
+         int BINDING_TABLE_STATE_size;
+         uint32_t SURFACE_STATE[ILO_MAX_VS_SURFACES];
+         uint32_t SAMPLER_STATE;
+         uint32_t SAMPLER_BORDER_COLOR_STATE[ILO_MAX_SAMPLERS];
+         uint32_t PUSH_CONSTANT_BUFFER;
+         int PUSH_CONSTANT_BUFFER_size;
+      } vs;
+
+      struct {
+         uint32_t BINDING_TABLE_STATE;
+         int BINDING_TABLE_STATE_size;
+         uint32_t SURFACE_STATE[ILO_MAX_GS_SURFACES];
+         bool active;
+      } gs;
+
+      struct {
+         uint32_t BINDING_TABLE_STATE;
+         int BINDING_TABLE_STATE_size;
+         uint32_t SURFACE_STATE[ILO_MAX_WM_SURFACES];
+         uint32_t SAMPLER_STATE;
+         uint32_t SAMPLER_BORDER_COLOR_STATE[ILO_MAX_SAMPLERS];
+         uint32_t PUSH_CONSTANT_BUFFER;
+         int PUSH_CONSTANT_BUFFER_size;
+      } wm;
+   } state;
+};
+
+struct ilo_3d_pipeline *
+ilo_3d_pipeline_create(struct ilo_builder *builder);
+
+void
+ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *pipeline);
+
+
+static inline void
+ilo_3d_pipeline_invalidate(struct ilo_3d_pipeline *p, uint32_t flags)
+{
+   p->invalidate_flags |= flags;
+
+   /* Kernel flushes everything.  Shouldn't we set all bits here? */
+   p->state.current_pipe_control_dw1 = 0;
+}
+
+/**
+ * Estimate the size of an action.
+ */
+static inline int
+ilo_3d_pipeline_estimate_size(struct ilo_3d_pipeline *pipeline,
+                              enum ilo_3d_pipeline_action action,
+                              const void *arg)
+{
+   return pipeline->estimate_size(pipeline, action, arg);
+}
+
+/**
+ * Emit context states and 3DPRIMITIVE.
+ */
+static inline void
+ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline *p,
+                          const struct ilo_state_vector *vec)
+{
+   p->emit_draw(p, vec);
+}
+
+/**
+ * Emit PIPE_CONTROL to flush all caches.
+ */
+static inline void
+ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
+{
+   p->emit_flush(p);
+}
+
+/**
+ * Emit PIPE_CONTROL or MI_STORE_REGISTER_MEM to save register values.
+ */
+static inline void
+ilo_3d_pipeline_emit_query(struct ilo_3d_pipeline *p,
+                           struct ilo_query *q, uint32_t offset)
+{
+   p->emit_query(p, q, offset);
+}
+
+static inline void
+ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p,
+                              const struct ilo_blitter *blitter)
+{
+   p->emit_rectlist(p, blitter);
+}
+
+void
+ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
+                                    unsigned sample_count,
+                                    unsigned sample_index,
+                                    float *x, float *y);
+
+#endif /* ILO_RENDER_H */
diff --git a/src/gallium/drivers/ilo/ilo_render_gen.h b/src/gallium/drivers/ilo/ilo_render_gen.h
new file mode 100644 (file)
index 0000000..a622633
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2012-2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef ILO_RENDER_GEN_H
+#define ILO_RENDER_GEN_H
+
+#include "ilo_common.h"
+
+struct ilo_3d_pipeline;
+struct ilo_query;
+struct ilo_state_vector;
+
+struct gen6_pipeline_session {
+   uint32_t pipe_dirty;
+
+   int reduced_prim;
+
+   bool hw_ctx_changed;
+   bool batch_bo_changed;
+   bool state_bo_changed;
+   bool kernel_bo_changed;
+   bool prim_changed;
+   bool primitive_restart_changed;
+
+   void (*emit_draw_states)(struct ilo_3d_pipeline *p,
+                            const struct ilo_state_vector *ilo,
+                            struct gen6_pipeline_session *session);
+
+   void (*emit_draw_commands)(struct ilo_3d_pipeline *p,
+                              const struct ilo_state_vector *ilo,
+                              struct gen6_pipeline_session *session);
+
+   /* indirect states */
+   bool viewport_state_changed;
+   bool cc_state_blend_changed;
+   bool cc_state_dsa_changed;
+   bool cc_state_cc_changed;
+   bool scissor_state_changed;
+   bool binding_table_vs_changed;
+   bool binding_table_gs_changed;
+   bool binding_table_fs_changed;
+   bool sampler_state_vs_changed;
+   bool sampler_state_gs_changed;
+   bool sampler_state_fs_changed;
+   bool pcb_state_vs_changed;
+   bool pcb_state_gs_changed;
+   bool pcb_state_fs_changed;
+
+   int num_surfaces[PIPE_SHADER_TYPES];
+};
+
+struct gen6_rectlist_session {
+   uint32_t DEPTH_STENCIL_STATE;
+   uint32_t COLOR_CALC_STATE;
+   uint32_t CC_VIEWPORT;
+};
+
+void
+gen6_pipeline_prepare(const struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *ilo,
+                      struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_draw(struct ilo_3d_pipeline *p,
+                   const struct ilo_state_vector *ilo,
+                   struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_end(struct ilo_3d_pipeline *p,
+                  const struct ilo_state_vector *ilo,
+                  struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_common_select(struct ilo_3d_pipeline *p,
+                            const struct ilo_state_vector *ilo,
+                            struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_common_sip(struct ilo_3d_pipeline *p,
+                         const struct ilo_state_vector *ilo,
+                         struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_common_base_address(struct ilo_3d_pipeline *p,
+                                  const struct ilo_state_vector *ilo,
+                                  struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_vf(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *ilo,
+                 struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_vf_statistics(struct ilo_3d_pipeline *p,
+                            const struct ilo_state_vector *ilo,
+                            struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_vs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *ilo,
+                 struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_clip(struct ilo_3d_pipeline *p,
+                   const struct ilo_state_vector *ilo,
+                   struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_sf_rect(struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *ilo,
+                      struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_wm_raster(struct ilo_3d_pipeline *p,
+                        const struct ilo_state_vector *ilo,
+                        struct gen6_pipeline_session *session);
+
+void
+gen6_pipeline_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_state_vector *ilo,
+                     struct gen6_pipeline_session *session);
+
+int
+gen6_pipeline_estimate_state_size(const struct ilo_3d_pipeline *p,
+                                  const struct ilo_state_vector *ilo);
+
+int
+gen6_pipeline_estimate_query_size(const struct ilo_3d_pipeline *p,
+                                  const struct ilo_query *q);
+
+void
+ilo_3d_pipeline_emit_flush_gen6(struct ilo_3d_pipeline *p);
+
+void
+ilo_3d_pipeline_emit_query_gen6(struct ilo_3d_pipeline *p,
+                                struct ilo_query *q, uint32_t offset);
+
+void
+ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p);
+
+#endif /* ILO_RENDER_GEN_H */
diff --git a/src/gallium/drivers/ilo/ilo_render_gen6.c b/src/gallium/drivers/ilo/ilo_render_gen6.c
new file mode 100644 (file)
index 0000000..e706533
--- /dev/null
@@ -0,0 +1,2010 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "genhw/genhw.h"
+#include "util/u_dual_blend.h"
+#include "util/u_prim.h"
+
+#include "ilo_blitter.h"
+#include "ilo_builder_3d.h"
+#include "ilo_builder_mi.h"
+#include "ilo_builder_render.h"
+#include "ilo_query.h"
+#include "ilo_shader.h"
+#include "ilo_state.h"
+#include "ilo_render.h"
+#include "ilo_render_gen.h"
+
+/**
+ * A wrapper for gen6_PIPE_CONTROL().
+ */
+static inline void
+gen6_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
+{
+   struct intel_bo *bo = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) ?
+      p->workaround_bo : NULL;
+
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   gen6_PIPE_CONTROL(p->builder, dw1, bo, 0, false);
+
+   p->state.current_pipe_control_dw1 |= dw1;
+
+   assert(!p->state.deferred_pipe_control_dw1);
+}
+
+/**
+ * This should be called before PIPE_CONTROL.
+ */
+static void
+gen6_wa_pre_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
+{
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 60:
+    *
+    *     "Pipe-control with CS-stall bit set must be sent BEFORE the
+    *      pipe-control with a post-sync op and no write-cache flushes."
+    *
+    * This WA may also be triggered indirectly by the other two WAs on the
+    * same page:
+    *
+    *     "Before any depth stall flush (including those produced by
+    *      non-pipelined state commands), software needs to first send a
+    *      PIPE_CONTROL with no bits set except Post-Sync Operation != 0."
+    *
+    *     "Before a PIPE_CONTROL with Write Cache Flush Enable =1, a
+    *      PIPE_CONTROL with any non-zero post-sync-op is required."
+    */
+   const bool direct_wa_cond = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) &&
+                               !(dw1 & GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH);
+   const bool indirect_wa_cond = (dw1 & GEN6_PIPE_CONTROL_DEPTH_STALL) |
+                                 (dw1 & GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH);
+
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   if (!direct_wa_cond && !indirect_wa_cond)
+      return;
+
+   if (!(p->state.current_pipe_control_dw1 & GEN6_PIPE_CONTROL_CS_STALL)) {
+      /*
+       * From the Sandy Bridge PRM, volume 2 part 1, page 73:
+       *
+       *     "1 of the following must also be set (when CS stall is set):
+       *
+       *       - Depth Cache Flush Enable ([0] of DW1)
+       *       - Stall at Pixel Scoreboard ([1] of DW1)
+       *       - Depth Stall ([13] of DW1)
+       *       - Post-Sync Operation ([13] of DW1)
+       *       - Render Target Cache Flush Enable ([12] of DW1)
+       *       - Notify Enable ([8] of DW1)"
+       *
+       * Because of the WAs above, we have to pick Stall at Pixel Scoreboard.
+       */
+      const uint32_t direct_wa = GEN6_PIPE_CONTROL_CS_STALL |
+                                 GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
+
+      gen6_pipe_control(p, direct_wa);
+   }
+
+   if (indirect_wa_cond &&
+       !(p->state.current_pipe_control_dw1 & GEN6_PIPE_CONTROL_WRITE__MASK)) {
+      const uint32_t indirect_wa = GEN6_PIPE_CONTROL_WRITE_IMM;
+
+      gen6_pipe_control(p, indirect_wa);
+   }
+}
+
+/**
+ * This should be called before any non-pipelined state command.
+ */
+static void
+gen6_wa_pre_non_pipelined(struct ilo_3d_pipeline *p)
+{
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   /* non-pipelined state commands produce depth stall */
+   gen6_wa_pre_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
+}
+
+static void
+gen6_wa_post_3dstate_constant_vs(struct ilo_3d_pipeline *p)
+{
+   /*
+    * According to upload_vs_state() of the classic driver, we need to emit a
+    * PIPE_CONTROL after 3DSTATE_CONSTANT_VS, otherwise the command is kept
+    * being buffered by VS FF, to the point that the FF dies.
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
+                        GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
+                        GEN6_PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+
+   gen6_wa_pre_pipe_control(p, dw1);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_pipe_control(p, dw1);
+}
+
+static void
+gen6_wa_pre_3dstate_wm_max_threads(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 274:
+    *
+    *     "A PIPE_CONTROL command, with only the Stall At Pixel Scoreboard
+    *      field set (DW1 Bit 1), must be issued prior to any change to the
+    *      value in this field (Maximum Number of Threads in 3DSTATE_WM)"
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   gen6_wa_pre_pipe_control(p, dw1);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_pipe_control(p, dw1);
+}
+
+static void
+gen6_wa_pre_3dstate_multisample(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 305:
+    *
+    *     "Driver must guarentee that all the caches in the depth pipe are
+    *      flushed before this command (3DSTATE_MULTISAMPLE) is parsed. This
+    *      requires driver to send a PIPE_CONTROL with a CS stall along with a
+    *      Depth Flush prior to this command."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                        GEN6_PIPE_CONTROL_CS_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   gen6_wa_pre_pipe_control(p, dw1);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_pipe_control(p, dw1);
+}
+
+static void
+gen6_wa_pre_depth(struct ilo_3d_pipeline *p)
+{
+   ILO_DEV_ASSERT(p->dev, 6, 6);
+
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
+    *
+    *     "Restriction: Prior to changing Depth/Stencil Buffer state (i.e.,
+    *      any combination of 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
+    *      3DSTATE_STENCIL_BUFFER, 3DSTATE_HIER_DEPTH_BUFFER) SW must first
+    *      issue a pipelined depth stall (PIPE_CONTROL with Depth Stall bit
+    *      set), followed by a pipelined depth cache flush (PIPE_CONTROL with
+    *      Depth Flush Bit set, followed by another pipelined depth stall
+    *      (PIPE_CONTROL with Depth Stall Bit set), unless SW can otherwise
+    *      guarantee that the pipeline from WM onwards is already flushed
+    *      (e.g., via a preceding MI_FLUSH)."
+    *
+    * According to the classic driver, it also applies for GEN6.
+    */
+   gen6_wa_pre_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL |
+                               GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
+
+   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
+   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
+   gen6_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
+}
+
+#define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
+
+void
+gen6_pipeline_common_select(struct ilo_3d_pipeline *p,
+                            const struct ilo_state_vector *vec,
+                            struct gen6_pipeline_session *session)
+{
+   /* PIPELINE_SELECT */
+   if (session->hw_ctx_changed) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_PIPELINE_SELECT(p->builder, 0x0);
+   }
+}
+
+void
+gen6_pipeline_common_sip(struct ilo_3d_pipeline *p,
+                         const struct ilo_state_vector *vec,
+                         struct gen6_pipeline_session *session)
+{
+   /* STATE_SIP */
+   if (session->hw_ctx_changed) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_STATE_SIP(p->builder, 0);
+   }
+}
+
+void
+gen6_pipeline_common_base_address(struct ilo_3d_pipeline *p,
+                                  const struct ilo_state_vector *vec,
+                                  struct gen6_pipeline_session *session)
+{
+   /* STATE_BASE_ADDRESS */
+   if (session->state_bo_changed || session->kernel_bo_changed ||
+       session->batch_bo_changed) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_state_base_address(p->builder, session->hw_ctx_changed);
+
+      /*
+       * From the Sandy Bridge PRM, volume 1 part 1, page 28:
+       *
+       *     "The following commands must be reissued following any change to
+       *      the base addresses:
+       *
+       *       * 3DSTATE_BINDING_TABLE_POINTERS
+       *       * 3DSTATE_SAMPLER_STATE_POINTERS
+       *       * 3DSTATE_VIEWPORT_STATE_POINTERS
+       *       * 3DSTATE_CC_POINTERS
+       *       * MEDIA_STATE_POINTERS"
+       *
+       * 3DSTATE_SCISSOR_STATE_POINTERS is not on the list, but it is
+       * reasonable to also reissue the command.  Same to PCB.
+       */
+      session->viewport_state_changed = true;
+
+      session->cc_state_blend_changed = true;
+      session->cc_state_dsa_changed = true;
+      session->cc_state_cc_changed = true;
+
+      session->scissor_state_changed = true;
+
+      session->binding_table_vs_changed = true;
+      session->binding_table_gs_changed = true;
+      session->binding_table_fs_changed = true;
+
+      session->sampler_state_vs_changed = true;
+      session->sampler_state_gs_changed = true;
+      session->sampler_state_fs_changed = true;
+
+      session->pcb_state_vs_changed = true;
+      session->pcb_state_gs_changed = true;
+      session->pcb_state_fs_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_common_urb(struct ilo_3d_pipeline *p,
+                         const struct ilo_state_vector *vec,
+                         struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_URB */
+   if (DIRTY(VE) || DIRTY(VS) || DIRTY(GS)) {
+      const bool gs_active = (vec->gs || (vec->vs &&
+               ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO)));
+      int vs_entry_size, gs_entry_size;
+      int vs_total_size, gs_total_size;
+
+      vs_entry_size = (vec->vs) ?
+         ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT) : 0;
+
+      /*
+       * As indicated by 2e712e41db0c0676e9f30fc73172c0e8de8d84d4, VF and VS
+       * share VUE handles.  The VUE allocation size must be large enough to
+       * store either VF outputs (number of VERTEX_ELEMENTs) and VS outputs.
+       *
+       * I am not sure if the PRM explicitly states that VF and VS share VUE
+       * handles.  But here is a citation that implies so:
+       *
+       * From the Sandy Bridge PRM, volume 2 part 1, page 44:
+       *
+       *     "Once a FF stage that spawn threads has sufficient input to
+       *      initiate a thread, it must guarantee that it is safe to request
+       *      the thread initiation. For all these FF stages, this check is
+       *      based on :
+       *
+       *      - The availability of output URB entries:
+       *        - VS: As the input URB entries are overwritten with the
+       *          VS-generated output data, output URB availability isn't a
+       *          factor."
+       */
+      if (vs_entry_size < vec->ve->count)
+         vs_entry_size = vec->ve->count;
+
+      gs_entry_size = (vec->gs) ?
+         ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_OUTPUT_COUNT) :
+         (gs_active) ? vs_entry_size : 0;
+
+      /* in bytes */
+      vs_entry_size *= sizeof(float) * 4;
+      gs_entry_size *= sizeof(float) * 4;
+      vs_total_size = p->dev->urb_size;
+
+      if (gs_active) {
+         vs_total_size /= 2;
+         gs_total_size = vs_total_size;
+      }
+      else {
+         gs_total_size = 0;
+      }
+
+      gen6_3DSTATE_URB(p->builder, vs_total_size, gs_total_size,
+            vs_entry_size, gs_entry_size);
+
+      /*
+       * From the Sandy Bridge PRM, volume 2 part 1, page 27:
+       *
+       *     "Because of a urb corruption caused by allocating a previous
+       *      gsunit's urb entry to vsunit software is required to send a
+       *      "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB
+       *      size == 0) plus a dummy DRAW call before any case where VS will
+       *      be taking over GS URB space."
+       */
+      if (p->state.gs.active && !gs_active)
+         ilo_3d_pipeline_emit_flush_gen6(p);
+
+      p->state.gs.active = gs_active;
+   }
+}
+
+static void
+gen6_pipeline_common_pointers_1(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_VIEWPORT_STATE_POINTERS */
+   if (session->viewport_state_changed) {
+      gen6_3DSTATE_VIEWPORT_STATE_POINTERS(p->builder,
+            p->state.CLIP_VIEWPORT,
+            p->state.SF_VIEWPORT,
+            p->state.CC_VIEWPORT);
+   }
+}
+
+static void
+gen6_pipeline_common_pointers_2(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CC_STATE_POINTERS */
+   if (session->cc_state_blend_changed ||
+       session->cc_state_dsa_changed ||
+       session->cc_state_cc_changed) {
+      gen6_3DSTATE_CC_STATE_POINTERS(p->builder,
+            p->state.BLEND_STATE,
+            p->state.DEPTH_STENCIL_STATE,
+            p->state.COLOR_CALC_STATE);
+   }
+
+   /* 3DSTATE_SAMPLER_STATE_POINTERS */
+   if (session->sampler_state_vs_changed ||
+       session->sampler_state_gs_changed ||
+       session->sampler_state_fs_changed) {
+      gen6_3DSTATE_SAMPLER_STATE_POINTERS(p->builder,
+            p->state.vs.SAMPLER_STATE,
+            0,
+            p->state.wm.SAMPLER_STATE);
+   }
+}
+
+static void
+gen6_pipeline_common_pointers_3(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_SCISSOR_STATE_POINTERS */
+   if (session->scissor_state_changed) {
+      gen6_3DSTATE_SCISSOR_STATE_POINTERS(p->builder,
+            p->state.SCISSOR_RECT);
+   }
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS */
+   if (session->binding_table_vs_changed ||
+       session->binding_table_gs_changed ||
+       session->binding_table_fs_changed) {
+      gen6_3DSTATE_BINDING_TABLE_POINTERS(p->builder,
+            p->state.vs.BINDING_TABLE_STATE,
+            p->state.gs.BINDING_TABLE_STATE,
+            p->state.wm.BINDING_TABLE_STATE);
+   }
+}
+
+void
+gen6_pipeline_vf(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   if (ilo_dev_gen(p->dev) >= ILO_GEN(7.5)) {
+      /* 3DSTATE_INDEX_BUFFER */
+      if (DIRTY(IB) || session->batch_bo_changed) {
+         gen6_3DSTATE_INDEX_BUFFER(p->builder,
+               &vec->ib, false);
+      }
+
+      /* 3DSTATE_VF */
+      if (session->primitive_restart_changed) {
+         gen7_3DSTATE_VF(p->builder, vec->draw->primitive_restart,
+               vec->draw->restart_index);
+      }
+   }
+   else {
+      /* 3DSTATE_INDEX_BUFFER */
+      if (DIRTY(IB) || session->primitive_restart_changed ||
+          session->batch_bo_changed) {
+         gen6_3DSTATE_INDEX_BUFFER(p->builder,
+               &vec->ib, vec->draw->primitive_restart);
+      }
+   }
+
+   /* 3DSTATE_VERTEX_BUFFERS */
+   if (DIRTY(VB) || DIRTY(VE) || session->batch_bo_changed)
+      gen6_3DSTATE_VERTEX_BUFFERS(p->builder, vec->ve, &vec->vb);
+
+   /* 3DSTATE_VERTEX_ELEMENTS */
+   if (DIRTY(VE) || DIRTY(VS)) {
+      const struct ilo_ve_state *ve = vec->ve;
+      bool last_velement_edgeflag = false;
+      bool prepend_generate_ids = false;
+
+      if (vec->vs) {
+         if (ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_VS_INPUT_EDGEFLAG)) {
+            /* we rely on the state tracker here */
+            assert(ilo_shader_get_kernel_param(vec->vs,
+                     ILO_KERNEL_INPUT_COUNT) == ve->count);
+
+            last_velement_edgeflag = true;
+         }
+
+         if (ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_VS_INPUT_INSTANCEID) ||
+             ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_VS_INPUT_VERTEXID))
+            prepend_generate_ids = true;
+      }
+
+      gen6_3DSTATE_VERTEX_ELEMENTS(p->builder, ve,
+            last_velement_edgeflag, prepend_generate_ids);
+   }
+}
+
+void
+gen6_pipeline_vf_statistics(struct ilo_3d_pipeline *p,
+                            const struct ilo_state_vector *vec,
+                            struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_VF_STATISTICS */
+   if (session->hw_ctx_changed)
+      gen6_3DSTATE_VF_STATISTICS(p->builder, false);
+}
+
+static void
+gen6_pipeline_vf_draw(struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *vec,
+                      struct gen6_pipeline_session *session)
+{
+   /* 3DPRIMITIVE */
+   gen6_3DPRIMITIVE(p->builder, vec->draw, &vec->ib);
+
+   p->state.current_pipe_control_dw1 = 0;
+   assert(!p->state.deferred_pipe_control_dw1);
+}
+
+void
+gen6_pipeline_vs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   const bool emit_3dstate_vs = (DIRTY(VS) || DIRTY(SAMPLER_VS) ||
+                                 session->kernel_bo_changed);
+   const bool emit_3dstate_constant_vs = session->pcb_state_vs_changed;
+
+   /*
+    * the classic i965 does this in upload_vs_state(), citing a spec that I
+    * cannot find
+    */
+   if (emit_3dstate_vs && ilo_dev_gen(p->dev) == ILO_GEN(6))
+      gen6_wa_pre_non_pipelined(p);
+
+   /* 3DSTATE_CONSTANT_VS */
+   if (emit_3dstate_constant_vs) {
+      gen6_3DSTATE_CONSTANT_VS(p->builder,
+            &p->state.vs.PUSH_CONSTANT_BUFFER,
+            &p->state.vs.PUSH_CONSTANT_BUFFER_size,
+            1);
+   }
+
+   /* 3DSTATE_VS */
+   if (emit_3dstate_vs) {
+      const int num_samplers = vec->sampler[PIPE_SHADER_VERTEX].count;
+
+      gen6_3DSTATE_VS(p->builder, vec->vs, num_samplers);
+   }
+
+   if (emit_3dstate_constant_vs && ilo_dev_gen(p->dev) == ILO_GEN(6))
+      gen6_wa_post_3dstate_constant_vs(p);
+}
+
+static void
+gen6_pipeline_gs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CONSTANT_GS */
+   if (session->pcb_state_gs_changed)
+      gen6_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
+
+   /* 3DSTATE_GS */
+   if (DIRTY(GS) || DIRTY(VS) ||
+       session->prim_changed || session->kernel_bo_changed) {
+      const int verts_per_prim = u_vertices_per_prim(session->reduced_prim);
+
+      gen6_3DSTATE_GS(p->builder, vec->gs, vec->vs, verts_per_prim);
+   }
+}
+
+static bool
+gen6_pipeline_update_max_svbi(struct ilo_3d_pipeline *p,
+                              const struct ilo_state_vector *vec,
+                              struct gen6_pipeline_session *session)
+{
+   if (DIRTY(VS) || DIRTY(GS) || DIRTY(SO)) {
+      const struct pipe_stream_output_info *so_info =
+         (vec->gs) ? ilo_shader_get_kernel_so_info(vec->gs) :
+         (vec->vs) ? ilo_shader_get_kernel_so_info(vec->vs) : NULL;
+      unsigned max_svbi = 0xffffffff;
+      int i;
+
+      for (i = 0; i < so_info->num_outputs; i++) {
+         const int output_buffer = so_info->output[i].output_buffer;
+         const struct pipe_stream_output_target *so =
+            vec->so.states[output_buffer];
+         const int struct_size = so_info->stride[output_buffer] * 4;
+         const int elem_size = so_info->output[i].num_components * 4;
+         int buf_size, count;
+
+         if (!so) {
+            max_svbi = 0;
+            break;
+         }
+
+         buf_size = so->buffer_size - so_info->output[i].dst_offset * 4;
+
+         count = buf_size / struct_size;
+         if (buf_size % struct_size >= elem_size)
+            count++;
+
+         if (count < max_svbi)
+            max_svbi = count;
+      }
+
+      if (p->state.so_max_vertices != max_svbi) {
+         p->state.so_max_vertices = max_svbi;
+         return true;
+      }
+   }
+
+   return false;
+}
+
+static void
+gen6_pipeline_gs_svbi(struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *vec,
+                      struct gen6_pipeline_session *session)
+{
+   const bool emit = gen6_pipeline_update_max_svbi(p, vec, session);
+
+   /* 3DSTATE_GS_SVB_INDEX */
+   if (emit) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_3DSTATE_GS_SVB_INDEX(p->builder,
+            0, 0, p->state.so_max_vertices,
+            false);
+
+      if (session->hw_ctx_changed) {
+         int i;
+
+         /*
+          * From the Sandy Bridge PRM, volume 2 part 1, page 148:
+          *
+          *     "If a buffer is not enabled then the SVBI must be set to 0x0
+          *      in order to not cause overflow in that SVBI."
+          *
+          *     "If a buffer is not enabled then the MaxSVBI must be set to
+          *      0xFFFFFFFF in order to not cause overflow in that SVBI."
+          */
+         for (i = 1; i < 4; i++) {
+            gen6_3DSTATE_GS_SVB_INDEX(p->builder,
+                  i, 0, 0xffffffff, false);
+         }
+      }
+   }
+}
+
+void
+gen6_pipeline_clip(struct ilo_3d_pipeline *p,
+                   const struct ilo_state_vector *vec,
+                   struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CLIP */
+   if (DIRTY(RASTERIZER) || DIRTY(FS) || DIRTY(VIEWPORT) || DIRTY(FB)) {
+      bool enable_guardband = true;
+      unsigned i;
+
+      /*
+       * We do not do 2D clipping yet.  Guard band test should only be enabled
+       * when the viewport is larger than the framebuffer.
+       */
+      for (i = 0; i < vec->viewport.count; i++) {
+         const struct ilo_viewport_cso *vp = &vec->viewport.cso[i];
+
+         if (vp->min_x > 0.0f || vp->max_x < vec->fb.state.width ||
+             vp->min_y > 0.0f || vp->max_y < vec->fb.state.height) {
+            enable_guardband = false;
+            break;
+         }
+      }
+
+      gen6_3DSTATE_CLIP(p->builder, vec->rasterizer,
+            vec->fs, enable_guardband, 1);
+   }
+}
+
+static void
+gen6_pipeline_sf(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_SF */
+   if (DIRTY(RASTERIZER) || DIRTY(FS))
+      gen6_3DSTATE_SF(p->builder, vec->rasterizer, vec->fs);
+}
+
+void
+gen6_pipeline_sf_rect(struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *vec,
+                      struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_DRAWING_RECTANGLE */
+   if (DIRTY(FB)) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
+            vec->fb.state.width, vec->fb.state.height);
+   }
+}
+
+static void
+gen6_pipeline_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CONSTANT_PS */
+   if (session->pcb_state_fs_changed) {
+      gen6_3DSTATE_CONSTANT_PS(p->builder,
+            &p->state.wm.PUSH_CONSTANT_BUFFER,
+            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
+            1);
+   }
+
+   /* 3DSTATE_WM */
+   if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) || DIRTY(DSA) ||
+       DIRTY(RASTERIZER) || session->kernel_bo_changed) {
+      const int num_samplers = vec->sampler[PIPE_SHADER_FRAGMENT].count;
+      const bool dual_blend = vec->blend->dual_blend;
+      const bool cc_may_kill = (vec->dsa->dw_alpha ||
+                                vec->blend->alpha_to_coverage);
+
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6) && session->hw_ctx_changed)
+         gen6_wa_pre_3dstate_wm_max_threads(p);
+
+      gen6_3DSTATE_WM(p->builder, vec->fs, num_samplers,
+            vec->rasterizer, dual_blend, cc_may_kill, 0);
+   }
+}
+
+static void
+gen6_pipeline_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_state_vector *vec,
+                             struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_MULTISAMPLE and 3DSTATE_SAMPLE_MASK */
+   if (DIRTY(SAMPLE_MASK) || DIRTY(FB)) {
+      const uint32_t *packed_sample_pos;
+
+      packed_sample_pos = (vec->fb.num_samples > 1) ?
+         &p->packed_sample_position_4x : &p->packed_sample_position_1x;
+
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
+         gen6_wa_pre_non_pipelined(p);
+         gen6_wa_pre_3dstate_multisample(p);
+      }
+
+      gen6_3DSTATE_MULTISAMPLE(p->builder,
+            vec->fb.num_samples, packed_sample_pos,
+            vec->rasterizer->state.half_pixel_center);
+
+      gen6_3DSTATE_SAMPLE_MASK(p->builder,
+            (vec->fb.num_samples > 1) ? vec->sample_mask : 0x1);
+   }
+}
+
+static void
+gen6_pipeline_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_state_vector *vec,
+                       struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
+   if (DIRTY(FB) || session->batch_bo_changed) {
+      const struct ilo_zs_surface *zs;
+      uint32_t clear_params;
+
+      if (vec->fb.state.zsbuf) {
+         const struct ilo_surface_cso *surface =
+            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
+         const struct ilo_texture_slice *slice =
+            ilo_texture_get_slice(ilo_texture(surface->base.texture),
+                  surface->base.u.tex.level, surface->base.u.tex.first_layer);
+
+         assert(!surface->is_rt);
+
+         zs = &surface->u.zs;
+         clear_params = slice->clear_value;
+      }
+      else {
+         zs = &vec->fb.null_zs;
+         clear_params = 0;
+      }
+
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
+         gen6_wa_pre_non_pipelined(p);
+         gen6_wa_pre_depth(p);
+      }
+
+      gen6_3DSTATE_DEPTH_BUFFER(p->builder, zs);
+      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder, zs);
+      gen6_3DSTATE_STENCIL_BUFFER(p->builder, zs);
+      gen6_3DSTATE_CLEAR_PARAMS(p->builder, clear_params);
+   }
+}
+
+void
+gen6_pipeline_wm_raster(struct ilo_3d_pipeline *p,
+                        const struct ilo_state_vector *vec,
+                        struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_POLY_STIPPLE_PATTERN and 3DSTATE_POLY_STIPPLE_OFFSET */
+   if ((DIRTY(RASTERIZER) || DIRTY(POLY_STIPPLE)) &&
+       vec->rasterizer->state.poly_stipple_enable) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_3DSTATE_POLY_STIPPLE_PATTERN(p->builder,
+            &vec->poly_stipple);
+
+      gen6_3DSTATE_POLY_STIPPLE_OFFSET(p->builder, 0, 0);
+   }
+
+   /* 3DSTATE_LINE_STIPPLE */
+   if (DIRTY(RASTERIZER) && vec->rasterizer->state.line_stipple_enable) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_3DSTATE_LINE_STIPPLE(p->builder,
+            vec->rasterizer->state.line_stipple_pattern,
+            vec->rasterizer->state.line_stipple_factor + 1);
+   }
+
+   /* 3DSTATE_AA_LINE_PARAMETERS */
+   if (DIRTY(RASTERIZER) && vec->rasterizer->state.line_smooth) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_non_pipelined(p);
+
+      gen6_3DSTATE_AA_LINE_PARAMETERS(p->builder);
+   }
+}
+
+static void
+gen6_pipeline_state_viewports(struct ilo_3d_pipeline *p,
+                              const struct ilo_state_vector *vec,
+                              struct gen6_pipeline_session *session)
+{
+   /* SF_CLIP_VIEWPORT and CC_VIEWPORT */
+   if (ilo_dev_gen(p->dev) >= ILO_GEN(7) && DIRTY(VIEWPORT)) {
+      p->state.SF_CLIP_VIEWPORT = gen7_SF_CLIP_VIEWPORT(p->builder,
+            vec->viewport.cso, vec->viewport.count);
+
+      p->state.CC_VIEWPORT = gen6_CC_VIEWPORT(p->builder,
+            vec->viewport.cso, vec->viewport.count);
+
+      session->viewport_state_changed = true;
+   }
+   /* SF_VIEWPORT, CLIP_VIEWPORT, and CC_VIEWPORT */
+   else if (DIRTY(VIEWPORT)) {
+      p->state.CLIP_VIEWPORT = gen6_CLIP_VIEWPORT(p->builder,
+            vec->viewport.cso, vec->viewport.count);
+
+      p->state.SF_VIEWPORT = gen6_SF_VIEWPORT(p->builder,
+            vec->viewport.cso, vec->viewport.count);
+
+      p->state.CC_VIEWPORT = gen6_CC_VIEWPORT(p->builder,
+            vec->viewport.cso, vec->viewport.count);
+
+      session->viewport_state_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_state_cc(struct ilo_3d_pipeline *p,
+                       const struct ilo_state_vector *vec,
+                       struct gen6_pipeline_session *session)
+{
+   /* BLEND_STATE */
+   if (DIRTY(BLEND) || DIRTY(FB) || DIRTY(DSA)) {
+      p->state.BLEND_STATE = gen6_BLEND_STATE(p->builder,
+            vec->blend, &vec->fb, vec->dsa);
+
+      session->cc_state_blend_changed = true;
+   }
+
+   /* COLOR_CALC_STATE */
+   if (DIRTY(DSA) || DIRTY(STENCIL_REF) || DIRTY(BLEND_COLOR)) {
+      p->state.COLOR_CALC_STATE =
+         gen6_COLOR_CALC_STATE(p->builder, &vec->stencil_ref,
+               vec->dsa->alpha_ref, &vec->blend_color);
+
+      session->cc_state_cc_changed = true;
+   }
+
+   /* DEPTH_STENCIL_STATE */
+   if (DIRTY(DSA)) {
+      p->state.DEPTH_STENCIL_STATE =
+         gen6_DEPTH_STENCIL_STATE(p->builder, vec->dsa);
+
+      session->cc_state_dsa_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_state_scissors(struct ilo_3d_pipeline *p,
+                             const struct ilo_state_vector *vec,
+                             struct gen6_pipeline_session *session)
+{
+   /* SCISSOR_RECT */
+   if (DIRTY(SCISSOR) || DIRTY(VIEWPORT)) {
+      /* there should be as many scissors as there are viewports */
+      p->state.SCISSOR_RECT = gen6_SCISSOR_RECT(p->builder,
+            &vec->scissor, vec->viewport.count);
+
+      session->scissor_state_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_state_surfaces_rt(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* SURFACE_STATEs for render targets */
+   if (DIRTY(FB)) {
+      const struct ilo_fb_state *fb = &vec->fb;
+      const int offset = ILO_WM_DRAW_SURFACE(0);
+      uint32_t *surface_state = &p->state.wm.SURFACE_STATE[offset];
+      int i;
+
+      for (i = 0; i < fb->state.nr_cbufs; i++) {
+         const struct ilo_surface_cso *surface =
+            (const struct ilo_surface_cso *) fb->state.cbufs[i];
+
+         if (!surface) {
+            surface_state[i] =
+               gen6_SURFACE_STATE(p->builder, &fb->null_rt, true);
+         }
+         else {
+            assert(surface && surface->is_rt);
+            surface_state[i] =
+               gen6_SURFACE_STATE(p->builder, &surface->u.rt, true);
+         }
+      }
+
+      /*
+       * Upload at least one render target, as
+       * brw_update_renderbuffer_surfaces() does.  I don't know why.
+       */
+      if (i == 0) {
+         surface_state[i] =
+            gen6_SURFACE_STATE(p->builder, &fb->null_rt, true);
+
+         i++;
+      }
+
+      memset(&surface_state[i], 0, (ILO_MAX_DRAW_BUFFERS - i) * 4);
+
+      if (i && session->num_surfaces[PIPE_SHADER_FRAGMENT] < offset + i)
+         session->num_surfaces[PIPE_SHADER_FRAGMENT] = offset + i;
+
+      session->binding_table_fs_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_state_surfaces_so(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   const struct ilo_so_state *so = &vec->so;
+
+   if (ilo_dev_gen(p->dev) != ILO_GEN(6))
+      return;
+
+   /* SURFACE_STATEs for stream output targets */
+   if (DIRTY(VS) || DIRTY(GS) || DIRTY(SO)) {
+      const struct pipe_stream_output_info *so_info =
+         (vec->gs) ? ilo_shader_get_kernel_so_info(vec->gs) :
+         (vec->vs) ? ilo_shader_get_kernel_so_info(vec->vs) : NULL;
+      const int offset = ILO_GS_SO_SURFACE(0);
+      uint32_t *surface_state = &p->state.gs.SURFACE_STATE[offset];
+      int i;
+
+      for (i = 0; so_info && i < so_info->num_outputs; i++) {
+         const int target = so_info->output[i].output_buffer;
+         const struct pipe_stream_output_target *so_target =
+            (target < so->count) ? so->states[target] : NULL;
+
+         if (so_target) {
+            surface_state[i] = gen6_so_SURFACE_STATE(p->builder,
+                  so_target, so_info, i);
+         }
+         else {
+            surface_state[i] = 0;
+         }
+      }
+
+      memset(&surface_state[i], 0, (ILO_MAX_SO_BINDINGS - i) * 4);
+
+      if (i && session->num_surfaces[PIPE_SHADER_GEOMETRY] < offset + i)
+         session->num_surfaces[PIPE_SHADER_GEOMETRY] = offset + i;
+
+      session->binding_table_gs_changed = true;
+   }
+}
+
+static void
+gen6_pipeline_state_surfaces_view(struct ilo_3d_pipeline *p,
+                                  const struct ilo_state_vector *vec,
+                                  int shader_type,
+                                  struct gen6_pipeline_session *session)
+{
+   const struct ilo_view_state *view = &vec->view[shader_type];
+   uint32_t *surface_state;
+   int offset, i;
+   bool skip = false;
+
+   /* SURFACE_STATEs for sampler views */
+   switch (shader_type) {
+   case PIPE_SHADER_VERTEX:
+      if (DIRTY(VIEW_VS)) {
+         offset = ILO_VS_TEXTURE_SURFACE(0);
+         surface_state = &p->state.vs.SURFACE_STATE[offset];
+
+         session->binding_table_vs_changed = true;
+      }
+      else {
+         skip = true;
+      }
+      break;
+   case PIPE_SHADER_FRAGMENT:
+      if (DIRTY(VIEW_FS)) {
+         offset = ILO_WM_TEXTURE_SURFACE(0);
+         surface_state = &p->state.wm.SURFACE_STATE[offset];
+
+         session->binding_table_fs_changed = true;
+      }
+      else {
+         skip = true;
+      }
+      break;
+   default:
+      skip = true;
+      break;
+   }
+
+   if (skip)
+      return;
+
+   for (i = 0; i < view->count; i++) {
+      if (view->states[i]) {
+         const struct ilo_view_cso *cso =
+            (const struct ilo_view_cso *) view->states[i];
+
+         surface_state[i] =
+            gen6_SURFACE_STATE(p->builder, &cso->surface, false);
+      }
+      else {
+         surface_state[i] = 0;
+      }
+   }
+
+   memset(&surface_state[i], 0, (ILO_MAX_SAMPLER_VIEWS - i) * 4);
+
+   if (i && session->num_surfaces[shader_type] < offset + i)
+      session->num_surfaces[shader_type] = offset + i;
+}
+
+static void
+gen6_pipeline_state_surfaces_const(struct ilo_3d_pipeline *p,
+                                   const struct ilo_state_vector *vec,
+                                   int shader_type,
+                                   struct gen6_pipeline_session *session)
+{
+   const struct ilo_cbuf_state *cbuf = &vec->cbuf[shader_type];
+   uint32_t *surface_state;
+   bool *binding_table_changed;
+   int offset, count, i;
+
+   if (!DIRTY(CBUF))
+      return;
+
+   /* SURFACE_STATEs for constant buffers */
+   switch (shader_type) {
+   case PIPE_SHADER_VERTEX:
+      offset = ILO_VS_CONST_SURFACE(0);
+      surface_state = &p->state.vs.SURFACE_STATE[offset];
+      binding_table_changed = &session->binding_table_vs_changed;
+      break;
+   case PIPE_SHADER_FRAGMENT:
+      offset = ILO_WM_CONST_SURFACE(0);
+      surface_state = &p->state.wm.SURFACE_STATE[offset];
+      binding_table_changed = &session->binding_table_fs_changed;
+      break;
+   default:
+      return;
+      break;
+   }
+
+   /* constants are pushed via PCB */
+   if (cbuf->enabled_mask == 0x1 && !cbuf->cso[0].resource) {
+      memset(surface_state, 0, ILO_MAX_CONST_BUFFERS * 4);
+      return;
+   }
+
+   count = util_last_bit(cbuf->enabled_mask);
+   for (i = 0; i < count; i++) {
+      if (cbuf->cso[i].resource) {
+         surface_state[i] = gen6_SURFACE_STATE(p->builder,
+               &cbuf->cso[i].surface, false);
+      }
+      else {
+         surface_state[i] = 0;
+      }
+   }
+
+   memset(&surface_state[count], 0, (ILO_MAX_CONST_BUFFERS - count) * 4);
+
+   if (count && session->num_surfaces[shader_type] < offset + count)
+      session->num_surfaces[shader_type] = offset + count;
+
+   *binding_table_changed = true;
+}
+
+static void
+gen6_pipeline_state_binding_tables(struct ilo_3d_pipeline *p,
+                                   const struct ilo_state_vector *vec,
+                                   int shader_type,
+                                   struct gen6_pipeline_session *session)
+{
+   uint32_t *binding_table_state, *surface_state;
+   int *binding_table_state_size, size;
+   bool skip = false;
+
+   /* BINDING_TABLE_STATE */
+   switch (shader_type) {
+   case PIPE_SHADER_VERTEX:
+      surface_state = p->state.vs.SURFACE_STATE;
+      binding_table_state = &p->state.vs.BINDING_TABLE_STATE;
+      binding_table_state_size = &p->state.vs.BINDING_TABLE_STATE_size;
+
+      skip = !session->binding_table_vs_changed;
+      break;
+   case PIPE_SHADER_GEOMETRY:
+      surface_state = p->state.gs.SURFACE_STATE;
+      binding_table_state = &p->state.gs.BINDING_TABLE_STATE;
+      binding_table_state_size = &p->state.gs.BINDING_TABLE_STATE_size;
+
+      skip = !session->binding_table_gs_changed;
+      break;
+   case PIPE_SHADER_FRAGMENT:
+      surface_state = p->state.wm.SURFACE_STATE;
+      binding_table_state = &p->state.wm.BINDING_TABLE_STATE;
+      binding_table_state_size = &p->state.wm.BINDING_TABLE_STATE_size;
+
+      skip = !session->binding_table_fs_changed;
+      break;
+   default:
+      skip = true;
+      break;
+   }
+
+   if (skip)
+      return;
+
+   /*
+    * If we have seemingly less SURFACE_STATEs than before, it could be that
+    * we did not touch those reside at the tail in this upload.  Loop over
+    * them to figure out the real number of SURFACE_STATEs.
+    */
+   for (size = *binding_table_state_size;
+         size > session->num_surfaces[shader_type]; size--) {
+      if (surface_state[size - 1])
+         break;
+   }
+   if (size < session->num_surfaces[shader_type])
+      size = session->num_surfaces[shader_type];
+
+   *binding_table_state = gen6_BINDING_TABLE_STATE(p->builder,
+         surface_state, size);
+   *binding_table_state_size = size;
+}
+
+static void
+gen6_pipeline_state_samplers(struct ilo_3d_pipeline *p,
+                             const struct ilo_state_vector *vec,
+                             int shader_type,
+                             struct gen6_pipeline_session *session)
+{
+   const struct ilo_sampler_cso * const *samplers =
+      vec->sampler[shader_type].cso;
+   const struct pipe_sampler_view * const *views =
+      (const struct pipe_sampler_view **) vec->view[shader_type].states;
+   const int num_samplers = vec->sampler[shader_type].count;
+   const int num_views = vec->view[shader_type].count;
+   uint32_t *sampler_state, *border_color_state;
+   bool emit_border_color = false;
+   bool skip = false;
+
+   /* SAMPLER_BORDER_COLOR_STATE and SAMPLER_STATE */
+   switch (shader_type) {
+   case PIPE_SHADER_VERTEX:
+      if (DIRTY(SAMPLER_VS) || DIRTY(VIEW_VS)) {
+         sampler_state = &p->state.vs.SAMPLER_STATE;
+         border_color_state = p->state.vs.SAMPLER_BORDER_COLOR_STATE;
+
+         if (DIRTY(SAMPLER_VS))
+            emit_border_color = true;
+
+         session->sampler_state_vs_changed = true;
+      }
+      else {
+         skip = true;
+      }
+      break;
+   case PIPE_SHADER_FRAGMENT:
+      if (DIRTY(SAMPLER_FS) || DIRTY(VIEW_FS)) {
+         sampler_state = &p->state.wm.SAMPLER_STATE;
+         border_color_state = p->state.wm.SAMPLER_BORDER_COLOR_STATE;
+
+         if (DIRTY(SAMPLER_FS))
+            emit_border_color = true;
+
+         session->sampler_state_fs_changed = true;
+      }
+      else {
+         skip = true;
+      }
+      break;
+   default:
+      skip = true;
+      break;
+   }
+
+   if (skip)
+      return;
+
+   if (emit_border_color) {
+      int i;
+
+      for (i = 0; i < num_samplers; i++) {
+         border_color_state[i] = (samplers[i]) ?
+            gen6_SAMPLER_BORDER_COLOR_STATE(p->builder, samplers[i]) : 0;
+      }
+   }
+
+   /* should we take the minimum of num_samplers and num_views? */
+   *sampler_state = gen6_SAMPLER_STATE(p->builder,
+         samplers, views,
+         border_color_state,
+         MIN2(num_samplers, num_views));
+}
+
+static void
+gen6_pipeline_state_pcb(struct ilo_3d_pipeline *p,
+                        const struct ilo_state_vector *vec,
+                        struct gen6_pipeline_session *session)
+{
+   /* push constant buffer for VS */
+   if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) {
+      const int cbuf0_size = (vec->vs) ?
+            ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
+      const int clip_state_size = (vec->vs) ?
+            ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_VS_PCB_UCP_SIZE) : 0;
+      const int total_size = cbuf0_size + clip_state_size;
+
+      if (total_size) {
+         void *pcb;
+
+         p->state.vs.PUSH_CONSTANT_BUFFER =
+            gen6_push_constant_buffer(p->builder, total_size, &pcb);
+         p->state.vs.PUSH_CONSTANT_BUFFER_size = total_size;
+
+         if (cbuf0_size) {
+            const struct ilo_cbuf_state *cbuf =
+               &vec->cbuf[PIPE_SHADER_VERTEX];
+
+            if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
+               memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
+            }
+            else {
+               memcpy(pcb, cbuf->cso[0].user_buffer,
+                     cbuf->cso[0].user_buffer_size);
+               memset(pcb + cbuf->cso[0].user_buffer_size, 0,
+                     cbuf0_size - cbuf->cso[0].user_buffer_size);
+            }
+
+            pcb += cbuf0_size;
+         }
+
+         if (clip_state_size)
+            memcpy(pcb, &vec->clip, clip_state_size);
+
+         session->pcb_state_vs_changed = true;
+      }
+      else if (p->state.vs.PUSH_CONSTANT_BUFFER_size) {
+         p->state.vs.PUSH_CONSTANT_BUFFER = 0;
+         p->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
+
+         session->pcb_state_vs_changed = true;
+      }
+   }
+
+   /* push constant buffer for FS */
+   if (DIRTY(FS) || DIRTY(CBUF)) {
+      const int cbuf0_size = (vec->fs) ?
+         ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
+
+      if (cbuf0_size) {
+         const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_FRAGMENT];
+         void *pcb;
+
+         p->state.wm.PUSH_CONSTANT_BUFFER =
+            gen6_push_constant_buffer(p->builder, cbuf0_size, &pcb);
+         p->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size;
+
+         if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
+            memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
+         }
+         else {
+            memcpy(pcb, cbuf->cso[0].user_buffer,
+                  cbuf->cso[0].user_buffer_size);
+            memset(pcb + cbuf->cso[0].user_buffer_size, 0,
+                  cbuf0_size - cbuf->cso[0].user_buffer_size);
+         }
+
+         session->pcb_state_fs_changed = true;
+      }
+      else if (p->state.wm.PUSH_CONSTANT_BUFFER_size) {
+         p->state.wm.PUSH_CONSTANT_BUFFER = 0;
+         p->state.wm.PUSH_CONSTANT_BUFFER_size = 0;
+
+         session->pcb_state_fs_changed = true;
+      }
+   }
+}
+
+#undef DIRTY
+
+static void
+gen6_pipeline_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_state_vector *vec,
+                       struct gen6_pipeline_session *session)
+{
+   /*
+    * We try to keep the order of the commands match, as closely as possible,
+    * that of the classic i965 driver.  It allows us to compare the command
+    * streams easily.
+    */
+   gen6_pipeline_common_select(p, vec, session);
+   gen6_pipeline_gs_svbi(p, vec, session);
+   gen6_pipeline_common_sip(p, vec, session);
+   gen6_pipeline_vf_statistics(p, vec, session);
+   gen6_pipeline_common_base_address(p, vec, session);
+   gen6_pipeline_common_pointers_1(p, vec, session);
+   gen6_pipeline_common_urb(p, vec, session);
+   gen6_pipeline_common_pointers_2(p, vec, session);
+   gen6_pipeline_wm_multisample(p, vec, session);
+   gen6_pipeline_vs(p, vec, session);
+   gen6_pipeline_gs(p, vec, session);
+   gen6_pipeline_clip(p, vec, session);
+   gen6_pipeline_sf(p, vec, session);
+   gen6_pipeline_wm(p, vec, session);
+   gen6_pipeline_common_pointers_3(p, vec, session);
+   gen6_pipeline_wm_depth(p, vec, session);
+   gen6_pipeline_wm_raster(p, vec, session);
+   gen6_pipeline_sf_rect(p, vec, session);
+   gen6_pipeline_vf(p, vec, session);
+   gen6_pipeline_vf_draw(p, vec, session);
+}
+
+void
+gen6_pipeline_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_state_vector *vec,
+                     struct gen6_pipeline_session *session)
+{
+   int shader_type;
+
+   gen6_pipeline_state_viewports(p, vec, session);
+   gen6_pipeline_state_cc(p, vec, session);
+   gen6_pipeline_state_scissors(p, vec, session);
+   gen6_pipeline_state_pcb(p, vec, session);
+
+   /*
+    * upload all SURAFCE_STATEs together so that we know there are minimal
+    * paddings
+    */
+   gen6_pipeline_state_surfaces_rt(p, vec, session);
+   gen6_pipeline_state_surfaces_so(p, vec, session);
+   for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
+      gen6_pipeline_state_surfaces_view(p, vec, shader_type, session);
+      gen6_pipeline_state_surfaces_const(p, vec, shader_type, session);
+   }
+
+   for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
+      gen6_pipeline_state_samplers(p, vec, shader_type, session);
+      /* this must be called after all SURFACE_STATEs are uploaded */
+      gen6_pipeline_state_binding_tables(p, vec, shader_type, session);
+   }
+}
+
+void
+gen6_pipeline_prepare(const struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *vec,
+                      struct gen6_pipeline_session *session)
+{
+   memset(session, 0, sizeof(*session));
+   session->pipe_dirty = vec->dirty;
+   session->reduced_prim = u_reduced_prim(vec->draw->mode);
+
+   session->hw_ctx_changed =
+      (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_HW);
+
+   if (session->hw_ctx_changed) {
+      /* these should be enough to make everything uploaded */
+      session->batch_bo_changed = true;
+      session->state_bo_changed = true;
+      session->kernel_bo_changed = true;
+      session->prim_changed = true;
+      session->primitive_restart_changed = true;
+   } else {
+      /*
+       * Any state that involves resources needs to be re-emitted when the
+       * batch bo changed.  This is because we do not pin the resources and
+       * their offsets (or existence) may change between batch buffers.
+       */
+      session->batch_bo_changed =
+         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_BATCH_BO);
+
+      session->state_bo_changed =
+         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_STATE_BO);
+      session->kernel_bo_changed =
+         (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO);
+      session->prim_changed = (p->state.reduced_prim != session->reduced_prim);
+      session->primitive_restart_changed =
+         (p->state.primitive_restart != vec->draw->primitive_restart);
+   }
+}
+
+void
+gen6_pipeline_draw(struct ilo_3d_pipeline *p,
+                   const struct ilo_state_vector *vec,
+                   struct gen6_pipeline_session *session)
+{
+   /* force all states to be uploaded if the state bo changed */
+   if (session->state_bo_changed)
+      session->pipe_dirty = ILO_DIRTY_ALL;
+   else
+      session->pipe_dirty = vec->dirty;
+
+   session->emit_draw_states(p, vec, session);
+
+   /* force all commands to be uploaded if the HW context changed */
+   if (session->hw_ctx_changed)
+      session->pipe_dirty = ILO_DIRTY_ALL;
+   else
+      session->pipe_dirty = vec->dirty;
+
+   session->emit_draw_commands(p, vec, session);
+}
+
+void
+gen6_pipeline_end(struct ilo_3d_pipeline *p,
+                  const struct ilo_state_vector *vec,
+                  struct gen6_pipeline_session *session)
+{
+   p->state.reduced_prim = session->reduced_prim;
+   p->state.primitive_restart = vec->draw->primitive_restart;
+}
+
+static void
+ilo_3d_pipeline_emit_draw_gen6(struct ilo_3d_pipeline *p,
+                               const struct ilo_state_vector *vec)
+{
+   struct gen6_pipeline_session session;
+
+   gen6_pipeline_prepare(p, vec, &session);
+
+   session.emit_draw_states = gen6_pipeline_states;
+   session.emit_draw_commands = gen6_pipeline_commands;
+
+   gen6_pipeline_draw(p, vec, &session);
+   gen6_pipeline_end(p, vec, &session);
+}
+
+void
+ilo_3d_pipeline_emit_flush_gen6(struct ilo_3d_pipeline *p)
+{
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
+                        GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
+                        GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                        GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE |
+                        GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
+                        GEN6_PIPE_CONTROL_CS_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 6, 7.5);
+
+   if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+      gen6_wa_pre_pipe_control(p, dw1);
+
+   gen6_PIPE_CONTROL(p->builder, dw1, NULL, 0, false);
+
+   p->state.current_pipe_control_dw1 |= dw1;
+   p->state.deferred_pipe_control_dw1 &= ~dw1;
+}
+
+void
+ilo_3d_pipeline_emit_query_gen6(struct ilo_3d_pipeline *p,
+                                struct ilo_query *q, uint32_t offset)
+{
+   const uint32_t pipeline_statistics_regs[] = {
+      GEN6_REG_IA_VERTICES_COUNT,
+      GEN6_REG_IA_PRIMITIVES_COUNT,
+      GEN6_REG_VS_INVOCATION_COUNT,
+      GEN6_REG_GS_INVOCATION_COUNT,
+      GEN6_REG_GS_PRIMITIVES_COUNT,
+      GEN6_REG_CL_INVOCATION_COUNT,
+      GEN6_REG_CL_PRIMITIVES_COUNT,
+      GEN6_REG_PS_INVOCATION_COUNT,
+      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ? GEN7_REG_HS_INVOCATION_COUNT : 0,
+      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ? GEN7_REG_DS_INVOCATION_COUNT : 0,
+      0,
+   };
+   const uint32_t primitives_generated_reg =
+      (ilo_dev_gen(p->dev) >= ILO_GEN(7) && q->index > 0) ?
+      GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
+      GEN6_REG_CL_INVOCATION_COUNT;
+   const uint32_t primitives_emitted_reg =
+      (ilo_dev_gen(p->dev) >= ILO_GEN(7)) ?
+      GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
+      GEN6_REG_SO_NUM_PRIMS_WRITTEN;
+   const uint32_t *regs;
+   int reg_count = 0, i;
+   uint32_t pipe_control_dw1 = 0;
+
+   ILO_DEV_ASSERT(p->dev, 6, 7.5);
+
+   switch (q->type) {
+   case PIPE_QUERY_OCCLUSION_COUNTER:
+      pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
+                         GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
+      break;
+   case PIPE_QUERY_TIMESTAMP:
+   case PIPE_QUERY_TIME_ELAPSED:
+      pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+      regs = &primitives_generated_reg;
+      reg_count = 1;
+      break;
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+      regs = &primitives_emitted_reg;
+      reg_count = 1;
+      break;
+   case PIPE_QUERY_PIPELINE_STATISTICS:
+      regs = pipeline_statistics_regs;
+      reg_count = Elements(pipeline_statistics_regs);
+      break;
+   default:
+      break;
+   }
+
+   if (pipe_control_dw1) {
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         gen6_wa_pre_pipe_control(p, pipe_control_dw1);
+
+      gen6_PIPE_CONTROL(p->builder, pipe_control_dw1, q->bo, offset, true);
+
+      p->state.current_pipe_control_dw1 |= pipe_control_dw1;
+      p->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
+   }
+
+   if (!reg_count)
+      return;
+
+   p->emit_flush(p);
+
+   for (i = 0; i < reg_count; i++) {
+      if (regs[i]) {
+         /* store lower 32 bits */
+         gen6_MI_STORE_REGISTER_MEM(p->builder, q->bo, offset, regs[i]);
+         /* store higher 32 bits */
+         gen6_MI_STORE_REGISTER_MEM(p->builder, q->bo,
+               offset + 4, regs[i] + 4);
+      } else {
+         gen6_MI_STORE_DATA_IMM(p->builder, q->bo, offset, 0, true);
+      }
+
+      offset += 8;
+   }
+}
+
+static void
+gen6_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_3DSTATE_CONSTANT_VS(p->builder, NULL, NULL, 0);
+   gen6_3DSTATE_VS(p->builder, NULL, 0);
+
+   gen6_wa_post_3dstate_constant_vs(p);
+
+   gen6_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
+   gen6_3DSTATE_GS(p->builder, NULL, NULL, 0);
+
+   gen6_3DSTATE_CLIP(p->builder, NULL, NULL, false, 0);
+   gen6_3DSTATE_SF(p->builder, NULL, NULL);
+}
+
+static void
+gen6_rectlist_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_blitter *blitter,
+                 struct gen6_rectlist_session *session)
+{
+   uint32_t hiz_op;
+
+   switch (blitter->op) {
+   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
+      hiz_op = GEN6_WM_DW4_DEPTH_CLEAR;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
+      hiz_op = GEN6_WM_DW4_DEPTH_RESOLVE;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
+      hiz_op = GEN6_WM_DW4_HIZ_RESOLVE;
+      break;
+   default:
+      hiz_op = 0;
+      break;
+   }
+
+   gen6_3DSTATE_CONSTANT_PS(p->builder, NULL, NULL, 0);
+
+   gen6_wa_pre_3dstate_wm_max_threads(p);
+   gen6_3DSTATE_WM(p->builder, NULL, 0, NULL, false, false, hiz_op);
+}
+
+static void
+gen6_rectlist_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_wa_pre_depth(p);
+
+   if (blitter->uses & (ILO_BLITTER_USE_FB_DEPTH |
+                        ILO_BLITTER_USE_FB_STENCIL)) {
+      gen6_3DSTATE_DEPTH_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
+      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
+      gen6_3DSTATE_STENCIL_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   gen6_3DSTATE_CLEAR_PARAMS(p->builder,
+         blitter->depth_clear_value);
+}
+
+static void
+gen6_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_blitter *blitter,
+                             struct gen6_rectlist_session *session)
+{
+   const uint32_t *packed_sample_pos = (blitter->fb.num_samples > 1) ?
+      &p->packed_sample_position_4x : &p->packed_sample_position_1x;
+
+   gen6_wa_pre_3dstate_multisample(p);
+
+   gen6_3DSTATE_MULTISAMPLE(p->builder, blitter->fb.num_samples,
+         packed_sample_pos, true);
+
+   gen6_3DSTATE_SAMPLE_MASK(p->builder,
+         (1 << blitter->fb.num_samples) - 1);
+}
+
+static void
+gen6_rectlist_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_wa_pre_non_pipelined(p);
+
+   gen6_rectlist_wm_multisample(p, blitter, session);
+
+   gen6_state_base_address(p->builder, true);
+
+   gen6_3DSTATE_VERTEX_BUFFERS(p->builder,
+         &blitter->ve, &blitter->vb);
+
+   gen6_3DSTATE_VERTEX_ELEMENTS(p->builder,
+         &blitter->ve, false, false);
+
+   gen6_3DSTATE_URB(p->builder,
+         p->dev->urb_size, 0, blitter->ve.count * 4 * sizeof(float), 0);
+   /* 3DSTATE_URB workaround */
+   if (p->state.gs.active) {
+      ilo_3d_pipeline_emit_flush_gen6(p);
+      p->state.gs.active = false;
+   }
+
+   if (blitter->uses &
+       (ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_CC)) {
+      gen6_3DSTATE_CC_STATE_POINTERS(p->builder, 0,
+            session->DEPTH_STENCIL_STATE, session->COLOR_CALC_STATE);
+   }
+
+   gen6_rectlist_vs_to_sf(p, blitter, session);
+   gen6_rectlist_wm(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      gen6_3DSTATE_VIEWPORT_STATE_POINTERS(p->builder,
+            0, 0, session->CC_VIEWPORT);
+   }
+
+   gen6_rectlist_wm_depth(p, blitter, session);
+
+   gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
+         blitter->fb.width, blitter->fb.height);
+
+   gen6_3DPRIMITIVE(p->builder, &blitter->draw, NULL);
+}
+
+static void
+gen6_rectlist_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_blitter *blitter,
+                     struct gen6_rectlist_session *session)
+{
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      session->DEPTH_STENCIL_STATE =
+         gen6_DEPTH_STENCIL_STATE(p->builder, &blitter->dsa);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      session->COLOR_CALC_STATE =
+         gen6_COLOR_CALC_STATE(p->builder, &blitter->cc.stencil_ref,
+               blitter->cc.alpha_ref, &blitter->cc.blend_color);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      session->CC_VIEWPORT =
+         gen6_CC_VIEWPORT(p->builder, &blitter->viewport, 1);
+   }
+}
+
+static void
+ilo_3d_pipeline_emit_rectlist_gen6(struct ilo_3d_pipeline *p,
+                                   const struct ilo_blitter *blitter)
+{
+   struct gen6_rectlist_session session;
+
+   memset(&session, 0, sizeof(session));
+   gen6_rectlist_states(p, blitter, &session);
+   gen6_rectlist_commands(p, blitter, &session);
+}
+
+static int
+gen6_pipeline_max_command_size(const struct ilo_3d_pipeline *p)
+{
+   static int size;
+
+   if (!size) {
+      size += GEN6_3DSTATE_CONSTANT_ANY__SIZE * 3;
+      size += GEN6_3DSTATE_GS_SVB_INDEX__SIZE * 4;
+      size += GEN6_PIPE_CONTROL__SIZE * 5;
+
+      size +=
+         GEN6_STATE_BASE_ADDRESS__SIZE +
+         GEN6_STATE_SIP__SIZE +
+         GEN6_3DSTATE_VF_STATISTICS__SIZE +
+         GEN6_PIPELINE_SELECT__SIZE +
+         GEN6_3DSTATE_BINDING_TABLE_POINTERS__SIZE +
+         GEN6_3DSTATE_SAMPLER_STATE_POINTERS__SIZE +
+         GEN6_3DSTATE_URB__SIZE +
+         GEN6_3DSTATE_VERTEX_BUFFERS__SIZE +
+         GEN6_3DSTATE_VERTEX_ELEMENTS__SIZE +
+         GEN6_3DSTATE_INDEX_BUFFER__SIZE +
+         GEN6_3DSTATE_VIEWPORT_STATE_POINTERS__SIZE +
+         GEN6_3DSTATE_CC_STATE_POINTERS__SIZE +
+         GEN6_3DSTATE_SCISSOR_STATE_POINTERS__SIZE +
+         GEN6_3DSTATE_VS__SIZE +
+         GEN6_3DSTATE_GS__SIZE +
+         GEN6_3DSTATE_CLIP__SIZE +
+         GEN6_3DSTATE_SF__SIZE +
+         GEN6_3DSTATE_WM__SIZE +
+         GEN6_3DSTATE_SAMPLE_MASK__SIZE +
+         GEN6_3DSTATE_DRAWING_RECTANGLE__SIZE +
+         GEN6_3DSTATE_DEPTH_BUFFER__SIZE +
+         GEN6_3DSTATE_POLY_STIPPLE_OFFSET__SIZE +
+         GEN6_3DSTATE_POLY_STIPPLE_PATTERN__SIZE +
+         GEN6_3DSTATE_LINE_STIPPLE__SIZE +
+         GEN6_3DSTATE_AA_LINE_PARAMETERS__SIZE +
+         GEN6_3DSTATE_MULTISAMPLE__SIZE +
+         GEN6_3DSTATE_STENCIL_BUFFER__SIZE +
+         GEN6_3DSTATE_HIER_DEPTH_BUFFER__SIZE +
+         GEN6_3DSTATE_CLEAR_PARAMS__SIZE +
+         GEN6_3DPRIMITIVE__SIZE;
+   }
+
+   return size;
+}
+
+int
+gen6_pipeline_estimate_state_size(const struct ilo_3d_pipeline *p,
+                                  const struct ilo_state_vector *vec)
+{
+   static int static_size;
+   int sh_type, size;
+
+   if (!static_size) {
+      /* 64 bytes, or 16 dwords */
+      const int alignment = 64 / 4;
+
+      /* pad first */
+      size = alignment - 1;
+
+      /* CC states */
+      size += align(GEN6_BLEND_STATE__SIZE * ILO_MAX_DRAW_BUFFERS, alignment);
+      size += align(GEN6_DEPTH_STENCIL_STATE__SIZE, alignment);
+      size += align(GEN6_COLOR_CALC_STATE__SIZE, alignment);
+
+      /* viewport arrays */
+      if (ilo_dev_gen(p->dev) >= ILO_GEN(7)) {
+         size +=
+            align(GEN7_SF_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 16) +
+            align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
+            align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
+      }
+      else {
+         size +=
+            align(GEN6_SF_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
+            align(GEN6_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
+            align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
+            align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
+      }
+
+      static_size = size;
+   }
+
+   size = static_size;
+
+   for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) {
+      const int alignment = 32 / 4;
+      int num_samplers, num_surfaces, pcb_size;
+
+      /* samplers */
+      num_samplers = vec->sampler[sh_type].count;
+
+      /* sampler views and constant buffers */
+      num_surfaces = vec->view[sh_type].count +
+         util_bitcount(vec->cbuf[sh_type].enabled_mask);
+
+      pcb_size = 0;
+
+      switch (sh_type) {
+      case PIPE_SHADER_VERTEX:
+         if (vec->vs) {
+            if (ilo_dev_gen(p->dev) == ILO_GEN(6)) {
+               const struct pipe_stream_output_info *so_info =
+                  ilo_shader_get_kernel_so_info(vec->vs);
+
+               /* stream outputs */
+               num_surfaces += so_info->num_outputs;
+            }
+
+            pcb_size = ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_PCB_CBUF0_SIZE);
+            pcb_size += ilo_shader_get_kernel_param(vec->vs,
+                  ILO_KERNEL_VS_PCB_UCP_SIZE);
+         }
+         break;
+      case PIPE_SHADER_GEOMETRY:
+         if (vec->gs && ilo_dev_gen(p->dev) == ILO_GEN(6)) {
+            const struct pipe_stream_output_info *so_info =
+               ilo_shader_get_kernel_so_info(vec->gs);
+
+            /* stream outputs */
+            num_surfaces += so_info->num_outputs;
+         }
+         break;
+      case PIPE_SHADER_FRAGMENT:
+         /* render targets */
+         num_surfaces += vec->fb.state.nr_cbufs;
+
+         if (vec->fs) {
+            pcb_size = ilo_shader_get_kernel_param(vec->fs,
+                  ILO_KERNEL_PCB_CBUF0_SIZE);
+         }
+         break;
+      default:
+         break;
+      }
+
+      /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
+      if (num_samplers) {
+         size += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) +
+            align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers;
+      }
+
+      /* BINDING_TABLE_STATE and SURFACE_STATEs */
+      if (num_surfaces) {
+         size += align(num_surfaces, alignment) +
+            align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces;
+      }
+
+      /* PCB */
+      if (pcb_size)
+         size += align(pcb_size, alignment);
+   }
+
+   return size;
+}
+
+int
+gen6_pipeline_estimate_query_size(const struct ilo_3d_pipeline *p,
+                                  const struct ilo_query *q)
+{
+   int size;
+
+   ILO_DEV_ASSERT(p->dev, 6, 7.5);
+
+   switch (q->type) {
+   case PIPE_QUERY_OCCLUSION_COUNTER:
+      size = GEN6_PIPE_CONTROL__SIZE;
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         size *= 3;
+      break;
+   case PIPE_QUERY_TIMESTAMP:
+   case PIPE_QUERY_TIME_ELAPSED:
+      size = GEN6_PIPE_CONTROL__SIZE;
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         size *= 2;
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+      size = GEN6_PIPE_CONTROL__SIZE;
+      if (ilo_dev_gen(p->dev) == ILO_GEN(6))
+         size *= 3;
+
+      size += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2;
+      break;
+   case PIPE_QUERY_PIPELINE_STATISTICS:
+      if (ilo_dev_gen(p->dev) >= ILO_GEN(7)) {
+         const int num_regs = 10;
+         const int num_pads = 1;
+
+         size = GEN6_PIPE_CONTROL__SIZE +
+            GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
+            GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
+      } else {
+         const int num_regs = 8;
+         const int num_pads = 3;
+
+         size = GEN6_PIPE_CONTROL__SIZE * 3 +
+            GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
+            GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
+      }
+      break;
+   default:
+      size = 0;
+      break;
+   }
+
+   return size;
+}
+
+static int
+ilo_3d_pipeline_estimate_size_gen6(struct ilo_3d_pipeline *p,
+                                   enum ilo_3d_pipeline_action action,
+                                   const void *arg)
+{
+   int size;
+
+   switch (action) {
+   case ILO_3D_PIPELINE_DRAW:
+      {
+         const struct ilo_state_vector *ilo = arg;
+
+         size = gen6_pipeline_max_command_size(p) +
+            gen6_pipeline_estimate_state_size(p, ilo);
+      }
+      break;
+   case ILO_3D_PIPELINE_FLUSH:
+      size = GEN6_PIPE_CONTROL__SIZE * 3;
+      break;
+   case ILO_3D_PIPELINE_QUERY:
+      size = gen6_pipeline_estimate_query_size(p,
+            (const struct ilo_query *) arg);
+      break;
+   case ILO_3D_PIPELINE_RECTLIST:
+      size = 64 + 256; /* states + commands */
+      break;
+   default:
+      assert(!"unknown 3D pipeline action");
+      size = 0;
+      break;
+   }
+
+   return size;
+}
+
+void
+ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p)
+{
+   p->estimate_size = ilo_3d_pipeline_estimate_size_gen6;
+   p->emit_draw = ilo_3d_pipeline_emit_draw_gen6;
+   p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
+   p->emit_query = ilo_3d_pipeline_emit_query_gen6;
+   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen6;
+}
diff --git a/src/gallium/drivers/ilo/ilo_render_gen7.c b/src/gallium/drivers/ilo/ilo_render_gen7.c
new file mode 100644 (file)
index 0000000..7ecea1e
--- /dev/null
@@ -0,0 +1,1021 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "genhw/genhw.h"
+#include "util/u_dual_blend.h"
+
+#include "ilo_blitter.h"
+#include "ilo_builder_3d.h"
+#include "ilo_builder_render.h"
+#include "ilo_shader.h"
+#include "ilo_state.h"
+#include "ilo_render.h"
+#include "ilo_render_gen.h"
+#include "ilo_render_gen7.h"
+
+/**
+ * A wrapper for gen6_PIPE_CONTROL().
+ */
+static inline void
+gen7_pipe_control(struct ilo_3d_pipeline *p, uint32_t dw1)
+{
+   struct intel_bo *bo = (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) ?
+      p->workaround_bo : NULL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if (dw1 & GEN6_PIPE_CONTROL_CS_STALL) {
+      /* CS stall cannot be set alone */
+      const uint32_t mask = GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
+                            GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                            GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL |
+                            GEN6_PIPE_CONTROL_DEPTH_STALL |
+                            GEN6_PIPE_CONTROL_WRITE__MASK;
+      if (!(dw1 & mask))
+         dw1 |= GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
+   }
+
+   gen6_PIPE_CONTROL(p->builder, dw1, bo, 0, false);
+
+
+   p->state.current_pipe_control_dw1 |= dw1;
+   p->state.deferred_pipe_control_dw1 &= ~dw1;
+}
+
+static void
+gen7_wa_post_3dstate_push_constant_alloc_ps(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 292:
+    *
+    *     "A PIPE_CONTOL command with the CS Stall bit set must be programmed
+    *      in the ring after this instruction
+    *      (3DSTATE_PUSH_CONSTANT_ALLOC_PS)."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   p->state.deferred_pipe_control_dw1 |= dw1;
+}
+
+static void
+gen7_wa_pre_vs(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 106:
+    *
+    *     "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth stall
+    *      needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS,
+    *      3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS,
+    *      3DSTATE_SAMPLER_STATE_POINTER_VS command.  Only one PIPE_CONTROL
+    *      needs to be sent before any combination of VS associated 3DSTATE."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
+                        GEN6_PIPE_CONTROL_WRITE_IMM;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen7_pipe_control(p, dw1);
+}
+
+static void
+gen7_wa_pre_3dstate_sf_depth_bias(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 258:
+    *
+    *     "Due to an HW issue driver needs to send a pipe control with stall
+    *      when ever there is state change in depth bias related state (in
+    *      3DSTATE_SF)"
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen7_pipe_control(p, dw1);
+}
+
+static void
+gen7_wa_pre_3dstate_multisample(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 304:
+    *
+    *     "Driver must ierarchi that all the caches in the depth pipe are
+    *      flushed before this command (3DSTATE_MULTISAMPLE) is parsed. This
+    *      requires driver to send a PIPE_CONTROL with a CS stall along with a
+    *      Depth Flush prior to this command.
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                        GEN6_PIPE_CONTROL_CS_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen7_pipe_control(p, dw1);
+}
+
+static void
+gen7_wa_pre_depth(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
+    *
+    *     "Driver must send a least one PIPE_CONTROL command with CS Stall and
+    *      a post sync operation prior to the group of depth
+    *      commands(3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
+    *      3DSTATE_STENCIL_BUFFER, and 3DSTATE_HIER_DEPTH_BUFFER)."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL |
+                        GEN6_PIPE_CONTROL_WRITE_IMM;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen7_pipe_control(p, dw1);
+
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
+    *
+    *     "Restriction: Prior to changing Depth/Stencil Buffer state (i.e.,
+    *      any combination of 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
+    *      3DSTATE_STENCIL_BUFFER, 3DSTATE_HIER_DEPTH_BUFFER) SW must first
+    *      issue a pipelined depth stall (PIPE_CONTROL with Depth Stall bit
+    *      set), followed by a pipelined depth cache flush (PIPE_CONTROL with
+    *      Depth Flush Bit set, followed by another pipelined depth stall
+    *      (PIPE_CONTROL with Depth Stall Bit set), unless SW can otherwise
+    *      guarantee that the pipeline from WM onwards is already flushed
+    *      (e.g., via a preceding MI_FLUSH)."
+    */
+   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
+   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
+   gen7_pipe_control(p, GEN6_PIPE_CONTROL_DEPTH_STALL);
+}
+
+static void
+gen7_wa_pre_3dstate_ps_max_threads(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 286:
+    *
+    *     "If this field (Maximum Number of Threads in 3DSTATE_PS) is changed
+    *      between 3DPRIMITIVE commands, a PIPE_CONTROL command with Stall at
+    *      Pixel Scoreboard set is required to be issued."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   if ((p->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen7_pipe_control(p, dw1);
+}
+
+static void
+gen7_wa_post_ps_and_later(struct ilo_3d_pipeline *p)
+{
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 276:
+    *
+    *     "The driver must make sure a PIPE_CONTROL with the Depth Stall
+    *      Enable bit set after all the following states are programmed:
+    *
+    *       - 3DSTATE_PS
+    *       - 3DSTATE_VIEWPORT_STATE_POINTERS_CC
+    *       - 3DSTATE_CONSTANT_PS
+    *       - 3DSTATE_BINDING_TABLE_POINTERS_PS
+    *       - 3DSTATE_SAMPLER_STATE_POINTERS_PS
+    *       - 3DSTATE_CC_STATE_POINTERS
+    *       - 3DSTATE_BLEND_STATE_POINTERS
+    *       - 3DSTATE_DEPTH_STENCIL_STATE_POINTERS"
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL;
+
+   ILO_DEV_ASSERT(p->dev, 7, 7.5);
+
+   p->state.deferred_pipe_control_dw1 |= dw1;
+}
+
+#define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
+
+static void
+gen7_pipeline_common_urb(struct ilo_3d_pipeline *p,
+                         const struct ilo_state_vector *vec,
+                         struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_URB_{VS,GS,HS,DS} */
+   if (DIRTY(VE) || DIRTY(VS)) {
+      /* the first 16KB are reserved for VS and PS PCBs */
+      const int offset = (ilo_dev_gen(p->dev) == ILO_GEN(7.5) &&
+            p->dev->gt == 3) ? 32768 : 16384;
+      int vs_entry_size, vs_total_size;
+
+      vs_entry_size = (vec->vs) ?
+         ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT) : 0;
+
+      /*
+       * From the Ivy Bridge PRM, volume 2 part 1, page 35:
+       *
+       *     "Programming Restriction: As the VS URB entry serves as both the
+       *      per-vertex input and output of the VS shader, the VS URB
+       *      Allocation Size must be sized to the maximum of the vertex input
+       *      and output structures."
+       */
+      if (vs_entry_size < vec->ve->count)
+         vs_entry_size = vec->ve->count;
+
+      vs_entry_size *= sizeof(float) * 4;
+      vs_total_size = p->dev->urb_size - offset;
+
+      gen7_wa_pre_vs(p);
+
+      gen7_3DSTATE_URB_VS(p->builder,
+            offset, vs_total_size, vs_entry_size);
+
+      gen7_3DSTATE_URB_GS(p->builder, offset, 0, 0);
+      gen7_3DSTATE_URB_HS(p->builder, offset, 0, 0);
+      gen7_3DSTATE_URB_DS(p->builder, offset, 0, 0);
+   }
+}
+
+static void
+gen7_pipeline_common_pcb_alloc(struct ilo_3d_pipeline *p,
+                               const struct ilo_state_vector *vec,
+                               struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_PUSH_CONSTANT_ALLOC_{VS,PS} */
+   if (session->hw_ctx_changed) {
+      /*
+       * Push constant buffers are only allowed to take up at most the first
+       * 16KB of the URB.  Split the space evenly for VS and FS.
+       */
+      const int max_size = (ilo_dev_gen(p->dev) == ILO_GEN(7.5) &&
+            p->dev->gt == 3) ? 32768 : 16384;
+      const int size = max_size / 2;
+      int offset = 0;
+
+      gen7_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->builder, offset, size);
+      offset += size;
+
+      gen7_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->builder, offset, size);
+
+      if (ilo_dev_gen(p->dev) == ILO_GEN(7))
+         gen7_wa_post_3dstate_push_constant_alloc_ps(p);
+   }
+}
+
+static void
+gen7_pipeline_common_pointers_1(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_VIEWPORT_STATE_POINTERS_{CC,SF_CLIP} */
+   if (session->viewport_state_changed) {
+      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->builder,
+            p->state.CC_VIEWPORT);
+
+      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP(p->builder,
+            p->state.SF_CLIP_VIEWPORT);
+   }
+}
+
+static void
+gen7_pipeline_common_pointers_2(struct ilo_3d_pipeline *p,
+                                const struct ilo_state_vector *vec,
+                                struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_BLEND_STATE_POINTERS */
+   if (session->cc_state_blend_changed) {
+      gen7_3DSTATE_BLEND_STATE_POINTERS(p->builder,
+            p->state.BLEND_STATE);
+   }
+
+   /* 3DSTATE_CC_STATE_POINTERS */
+   if (session->cc_state_cc_changed) {
+      gen7_3DSTATE_CC_STATE_POINTERS(p->builder,
+            p->state.COLOR_CALC_STATE);
+   }
+
+   /* 3DSTATE_DEPTH_STENCIL_STATE_POINTERS */
+   if (session->cc_state_dsa_changed) {
+      gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->builder,
+            p->state.DEPTH_STENCIL_STATE);
+   }
+}
+
+static void
+gen7_pipeline_vs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   const bool emit_3dstate_binding_table = session->binding_table_vs_changed;
+   const bool emit_3dstate_sampler_state = session->sampler_state_vs_changed;
+   /* see gen6_pipeline_vs() */
+   const bool emit_3dstate_constant_vs = session->pcb_state_vs_changed;
+   const bool emit_3dstate_vs = (DIRTY(VS) || DIRTY(SAMPLER_VS) ||
+           session->kernel_bo_changed);
+
+   /* emit depth stall before any of the VS commands */
+   if (emit_3dstate_binding_table || emit_3dstate_sampler_state ||
+           emit_3dstate_constant_vs || emit_3dstate_vs)
+      gen7_wa_pre_vs(p);
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS_VS */
+   if (emit_3dstate_binding_table) {
+      gen7_3DSTATE_BINDING_TABLE_POINTERS_VS(p->builder,
+              p->state.vs.BINDING_TABLE_STATE);
+   }
+
+   /* 3DSTATE_SAMPLER_STATE_POINTERS_VS */
+   if (emit_3dstate_sampler_state) {
+      gen7_3DSTATE_SAMPLER_STATE_POINTERS_VS(p->builder,
+              p->state.vs.SAMPLER_STATE);
+   }
+
+   /* 3DSTATE_CONSTANT_VS */
+   if (emit_3dstate_constant_vs) {
+      gen7_3DSTATE_CONSTANT_VS(p->builder,
+              &p->state.vs.PUSH_CONSTANT_BUFFER,
+              &p->state.vs.PUSH_CONSTANT_BUFFER_size,
+              1);
+   }
+
+   /* 3DSTATE_VS */
+   if (emit_3dstate_vs) {
+      const int num_samplers = vec->sampler[PIPE_SHADER_VERTEX].count;
+
+      gen6_3DSTATE_VS(p->builder, vec->vs, num_samplers);
+   }
+}
+
+static void
+gen7_pipeline_hs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CONSTANT_HS and 3DSTATE_HS */
+   if (session->hw_ctx_changed) {
+      gen7_3DSTATE_CONSTANT_HS(p->builder, 0, 0, 0);
+      gen7_3DSTATE_HS(p->builder, NULL, 0);
+   }
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS_HS */
+   if (session->hw_ctx_changed)
+      gen7_3DSTATE_BINDING_TABLE_POINTERS_HS(p->builder, 0);
+}
+
+static void
+gen7_pipeline_te(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_TE */
+   if (session->hw_ctx_changed)
+      gen7_3DSTATE_TE(p->builder);
+}
+
+static void
+gen7_pipeline_ds(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CONSTANT_DS and 3DSTATE_DS */
+   if (session->hw_ctx_changed) {
+      gen7_3DSTATE_CONSTANT_DS(p->builder, 0, 0, 0);
+      gen7_3DSTATE_DS(p->builder, NULL, 0);
+   }
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS_DS */
+   if (session->hw_ctx_changed)
+      gen7_3DSTATE_BINDING_TABLE_POINTERS_DS(p->builder, 0);
+
+}
+
+static void
+gen7_pipeline_gs(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_CONSTANT_GS and 3DSTATE_GS */
+   if (session->hw_ctx_changed) {
+      gen7_3DSTATE_CONSTANT_GS(p->builder, 0, 0, 0);
+      gen7_3DSTATE_GS(p->builder, NULL, 0);
+   }
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS_GS */
+   if (session->binding_table_gs_changed) {
+      gen7_3DSTATE_BINDING_TABLE_POINTERS_GS(p->builder,
+            p->state.gs.BINDING_TABLE_STATE);
+   }
+}
+
+static void
+gen7_pipeline_sol(struct ilo_3d_pipeline *p,
+                  const struct ilo_state_vector *vec,
+                  struct gen6_pipeline_session *session)
+{
+   const struct pipe_stream_output_info *so_info;
+   const struct ilo_shader_state *shader;
+   bool dirty_sh = false;
+
+   if (vec->gs) {
+      shader = vec->gs;
+      dirty_sh = DIRTY(GS);
+   }
+   else {
+      shader = vec->vs;
+      dirty_sh = DIRTY(VS);
+   }
+
+   so_info = ilo_shader_get_kernel_so_info(shader);
+
+   /* 3DSTATE_SO_BUFFER */
+   if ((DIRTY(SO) || dirty_sh || session->batch_bo_changed) &&
+       vec->so.enabled) {
+      int i;
+
+      for (i = 0; i < vec->so.count; i++) {
+         const int stride = so_info->stride[i] * 4; /* in bytes */
+         int base = 0;
+
+         gen7_3DSTATE_SO_BUFFER(p->builder, i, base, stride,
+               vec->so.states[i]);
+      }
+
+      for (; i < 4; i++)
+         gen7_3DSTATE_SO_BUFFER(p->builder, i, 0, 0, NULL);
+   }
+
+   /* 3DSTATE_SO_DECL_LIST */
+   if (dirty_sh && vec->so.enabled)
+      gen7_3DSTATE_SO_DECL_LIST(p->builder, so_info);
+
+   /* 3DSTATE_STREAMOUT */
+   if (DIRTY(SO) || DIRTY(RASTERIZER) || dirty_sh) {
+      const unsigned buffer_mask = (1 << vec->so.count) - 1;
+      const int output_count = ilo_shader_get_kernel_param(shader,
+            ILO_KERNEL_OUTPUT_COUNT);
+
+      gen7_3DSTATE_STREAMOUT(p->builder, buffer_mask, output_count,
+            vec->rasterizer->state.rasterizer_discard);
+   }
+}
+
+static void
+gen7_pipeline_sf(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_SBE */
+   if (DIRTY(RASTERIZER) || DIRTY(FS))
+      gen7_3DSTATE_SBE(p->builder, vec->rasterizer, vec->fs);
+
+   /* 3DSTATE_SF */
+   if (DIRTY(RASTERIZER) || DIRTY(FB)) {
+      struct pipe_surface *zs = vec->fb.state.zsbuf;
+
+      gen7_wa_pre_3dstate_sf_depth_bias(p);
+      gen7_3DSTATE_SF(p->builder, vec->rasterizer,
+            (zs) ? zs->format : PIPE_FORMAT_NONE);
+   }
+}
+
+static void
+gen7_pipeline_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_state_vector *vec,
+                 struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_WM */
+   if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) || DIRTY(RASTERIZER)) {
+      const bool cc_may_kill = (vec->dsa->dw_alpha ||
+                                vec->blend->alpha_to_coverage);
+
+      gen7_3DSTATE_WM(p->builder, vec->fs,
+            vec->rasterizer, cc_may_kill, 0);
+   }
+
+   /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
+   if (session->binding_table_fs_changed) {
+      gen7_3DSTATE_BINDING_TABLE_POINTERS_PS(p->builder,
+            p->state.wm.BINDING_TABLE_STATE);
+   }
+
+   /* 3DSTATE_SAMPLER_STATE_POINTERS_PS */
+   if (session->sampler_state_fs_changed) {
+      gen7_3DSTATE_SAMPLER_STATE_POINTERS_PS(p->builder,
+            p->state.wm.SAMPLER_STATE);
+   }
+
+   /* 3DSTATE_CONSTANT_PS */
+   if (session->pcb_state_fs_changed) {
+      gen7_3DSTATE_CONSTANT_PS(p->builder,
+            &p->state.wm.PUSH_CONSTANT_BUFFER,
+            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
+            1);
+   }
+
+   /* 3DSTATE_PS */
+   if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) ||
+       session->kernel_bo_changed) {
+      const int num_samplers = vec->sampler[PIPE_SHADER_FRAGMENT].count;
+      const bool dual_blend = vec->blend->dual_blend;
+
+      if ((ilo_dev_gen(p->dev) == ILO_GEN(7) ||
+           ilo_dev_gen(p->dev) == ILO_GEN(7.5)) &&
+          session->hw_ctx_changed)
+         gen7_wa_pre_3dstate_ps_max_threads(p);
+
+      gen7_3DSTATE_PS(p->builder, vec->fs, num_samplers, dual_blend);
+   }
+
+   /* 3DSTATE_SCISSOR_STATE_POINTERS */
+   if (session->scissor_state_changed) {
+      gen6_3DSTATE_SCISSOR_STATE_POINTERS(p->builder,
+            p->state.SCISSOR_RECT);
+   }
+
+   /* XXX what is the best way to know if this workaround is needed? */
+   {
+      const bool emit_3dstate_ps =
+         (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND));
+      const bool emit_3dstate_depth_buffer =
+         (DIRTY(FB) || DIRTY(DSA) || session->state_bo_changed);
+
+      if (emit_3dstate_ps ||
+          session->pcb_state_fs_changed ||
+          session->viewport_state_changed ||
+          session->binding_table_fs_changed ||
+          session->sampler_state_fs_changed ||
+          session->cc_state_cc_changed ||
+          session->cc_state_blend_changed ||
+          session->cc_state_dsa_changed)
+         gen7_wa_post_ps_and_later(p);
+
+      if (emit_3dstate_depth_buffer)
+         gen7_wa_pre_depth(p);
+   }
+
+   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
+   if (DIRTY(FB) || session->batch_bo_changed) {
+      const struct ilo_zs_surface *zs;
+      uint32_t clear_params;
+
+      if (vec->fb.state.zsbuf) {
+         const struct ilo_surface_cso *surface =
+            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
+         const struct ilo_texture_slice *slice =
+            ilo_texture_get_slice(ilo_texture(surface->base.texture),
+                  surface->base.u.tex.level, surface->base.u.tex.first_layer);
+
+         assert(!surface->is_rt);
+         zs = &surface->u.zs;
+         clear_params = slice->clear_value;
+      }
+      else {
+         zs = &vec->fb.null_zs;
+         clear_params = 0;
+      }
+
+      gen6_3DSTATE_DEPTH_BUFFER(p->builder, zs);
+      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder, zs);
+      gen6_3DSTATE_STENCIL_BUFFER(p->builder, zs);
+      gen7_3DSTATE_CLEAR_PARAMS(p->builder, clear_params);
+   }
+}
+
+static void
+gen7_pipeline_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_state_vector *vec,
+                             struct gen6_pipeline_session *session)
+{
+   /* 3DSTATE_MULTISAMPLE and 3DSTATE_SAMPLE_MASK */
+   if (DIRTY(SAMPLE_MASK) || DIRTY(FB)) {
+      const uint32_t *packed_sample_pos;
+
+      gen7_wa_pre_3dstate_multisample(p);
+
+      packed_sample_pos =
+         (vec->fb.num_samples > 4) ? p->packed_sample_position_8x :
+         (vec->fb.num_samples > 1) ? &p->packed_sample_position_4x :
+         &p->packed_sample_position_1x;
+
+      gen6_3DSTATE_MULTISAMPLE(p->builder,
+            vec->fb.num_samples, packed_sample_pos,
+            vec->rasterizer->state.half_pixel_center);
+
+      gen7_3DSTATE_SAMPLE_MASK(p->builder,
+            (vec->fb.num_samples > 1) ? vec->sample_mask : 0x1,
+            vec->fb.num_samples);
+   }
+}
+
+static void
+gen7_pipeline_vf_draw(struct ilo_3d_pipeline *p,
+                      const struct ilo_state_vector *vec,
+                      struct gen6_pipeline_session *session)
+{
+   if (p->state.deferred_pipe_control_dw1)
+      gen7_pipe_control(p, p->state.deferred_pipe_control_dw1);
+
+   /* 3DPRIMITIVE */
+   gen7_3DPRIMITIVE(p->builder, vec->draw, &vec->ib);
+
+   p->state.current_pipe_control_dw1 = 0;
+   p->state.deferred_pipe_control_dw1 = 0;
+}
+
+static void
+gen7_pipeline_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_state_vector *vec,
+                       struct gen6_pipeline_session *session)
+{
+   /*
+    * We try to keep the order of the commands match, as closely as possible,
+    * that of the classic i965 driver.  It allows us to compare the command
+    * streams easily.
+    */
+   gen6_pipeline_common_select(p, vec, session);
+   gen6_pipeline_common_sip(p, vec, session);
+   gen6_pipeline_vf_statistics(p, vec, session);
+   gen7_pipeline_common_pcb_alloc(p, vec, session);
+   gen6_pipeline_common_base_address(p, vec, session);
+   gen7_pipeline_common_pointers_1(p, vec, session);
+   gen7_pipeline_common_urb(p, vec, session);
+   gen7_pipeline_common_pointers_2(p, vec, session);
+   gen7_pipeline_wm_multisample(p, vec, session);
+   gen7_pipeline_gs(p, vec, session);
+   gen7_pipeline_hs(p, vec, session);
+   gen7_pipeline_te(p, vec, session);
+   gen7_pipeline_ds(p, vec, session);
+   gen7_pipeline_vs(p, vec, session);
+   gen7_pipeline_sol(p, vec, session);
+   gen6_pipeline_clip(p, vec, session);
+   gen7_pipeline_sf(p, vec, session);
+   gen7_pipeline_wm(p, vec, session);
+   gen6_pipeline_wm_raster(p, vec, session);
+   gen6_pipeline_sf_rect(p, vec, session);
+   gen6_pipeline_vf(p, vec, session);
+   gen7_pipeline_vf_draw(p, vec, session);
+}
+
+static void
+ilo_3d_pipeline_emit_draw_gen7(struct ilo_3d_pipeline *p,
+                               const struct ilo_state_vector *vec)
+{
+   struct gen6_pipeline_session session;
+
+   gen6_pipeline_prepare(p, vec, &session);
+
+   session.emit_draw_states = gen6_pipeline_states;
+   session.emit_draw_commands = gen7_pipeline_commands;
+
+   gen6_pipeline_draw(p, vec, &session);
+   gen6_pipeline_end(p, vec, &session);
+}
+
+static void
+gen7_rectlist_pcb_alloc(struct ilo_3d_pipeline *p,
+                        const struct ilo_blitter *blitter,
+                        struct gen6_rectlist_session *session)
+{
+   /*
+    * Push constant buffers are only allowed to take up at most the first
+    * 16KB of the URB.  Split the space evenly for VS and FS.
+    */
+   const int max_size =
+      (ilo_dev_gen(p->dev) == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+   const int size = max_size / 2;
+   int offset = 0;
+
+   gen7_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->builder, offset, size);
+   offset += size;
+
+   gen7_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->builder, offset, size);
+
+   gen7_wa_post_3dstate_push_constant_alloc_ps(p);
+}
+
+static void
+gen7_rectlist_urb(struct ilo_3d_pipeline *p,
+                  const struct ilo_blitter *blitter,
+                  struct gen6_rectlist_session *session)
+{
+   /* the first 16KB are reserved for VS and PS PCBs */
+   const int offset =
+      (ilo_dev_gen(p->dev) == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+
+   gen7_3DSTATE_URB_VS(p->builder, offset, p->dev->urb_size - offset,
+         blitter->ve.count * 4 * sizeof(float));
+
+   gen7_3DSTATE_URB_GS(p->builder, offset, 0, 0);
+   gen7_3DSTATE_URB_HS(p->builder, offset, 0, 0);
+   gen7_3DSTATE_URB_DS(p->builder, offset, 0, 0);
+}
+
+static void
+gen7_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_3DSTATE_CONSTANT_VS(p->builder, NULL, NULL, 0);
+   gen6_3DSTATE_VS(p->builder, NULL, 0);
+
+   gen7_3DSTATE_CONSTANT_HS(p->builder, NULL, NULL, 0);
+   gen7_3DSTATE_HS(p->builder, NULL, 0);
+
+   gen7_3DSTATE_TE(p->builder);
+
+   gen7_3DSTATE_CONSTANT_DS(p->builder, NULL, NULL, 0);
+   gen7_3DSTATE_DS(p->builder, NULL, 0);
+
+   gen7_3DSTATE_CONSTANT_GS(p->builder, NULL, NULL, 0);
+   gen7_3DSTATE_GS(p->builder, NULL, 0);
+
+   gen7_3DSTATE_STREAMOUT(p->builder, 0x0, 0, false);
+
+   gen6_3DSTATE_CLIP(p->builder, NULL, NULL, false, 0);
+
+   gen7_wa_pre_3dstate_sf_depth_bias(p);
+
+   gen7_3DSTATE_SF(p->builder, NULL, blitter->fb.dst.base.format);
+   gen7_3DSTATE_SBE(p->builder, NULL, NULL);
+}
+
+static void
+gen7_rectlist_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_blitter *blitter,
+                 struct gen6_rectlist_session *session)
+{
+   uint32_t hiz_op;
+
+   switch (blitter->op) {
+   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
+      hiz_op = GEN7_WM_DW1_DEPTH_CLEAR;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
+      hiz_op = GEN7_WM_DW1_DEPTH_RESOLVE;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
+      hiz_op = GEN7_WM_DW1_HIZ_RESOLVE;
+      break;
+   default:
+      hiz_op = 0;
+      break;
+   }
+
+   gen7_3DSTATE_WM(p->builder, NULL, NULL, false, hiz_op);
+
+   gen7_3DSTATE_CONSTANT_PS(p->builder, NULL, NULL, 0);
+
+   gen7_wa_pre_3dstate_ps_max_threads(p);
+   gen7_3DSTATE_PS(p->builder, NULL, 0, false);
+}
+
+static void
+gen7_rectlist_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_wa_pre_depth(p);
+
+   if (blitter->uses & (ILO_BLITTER_USE_FB_DEPTH |
+                        ILO_BLITTER_USE_FB_STENCIL)) {
+      gen6_3DSTATE_DEPTH_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
+      gen6_3DSTATE_HIER_DEPTH_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
+      gen6_3DSTATE_STENCIL_BUFFER(p->builder,
+            &blitter->fb.dst.u.zs);
+   }
+
+   gen7_3DSTATE_CLEAR_PARAMS(p->builder,
+         blitter->depth_clear_value);
+}
+
+static void
+gen7_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_blitter *blitter,
+                             struct gen6_rectlist_session *session)
+{
+   const uint32_t *packed_sample_pos =
+      (blitter->fb.num_samples > 4) ? p->packed_sample_position_8x :
+      (blitter->fb.num_samples > 1) ? &p->packed_sample_position_4x :
+      &p->packed_sample_position_1x;
+
+   gen7_wa_pre_3dstate_multisample(p);
+
+   gen6_3DSTATE_MULTISAMPLE(p->builder, blitter->fb.num_samples,
+         packed_sample_pos, true);
+
+   gen7_3DSTATE_SAMPLE_MASK(p->builder,
+         (1 << blitter->fb.num_samples) - 1, blitter->fb.num_samples);
+}
+
+static void
+gen7_rectlist_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_rectlist_wm_multisample(p, blitter, session);
+
+   gen6_state_base_address(p->builder, true);
+
+   gen6_3DSTATE_VERTEX_BUFFERS(p->builder,
+         &blitter->ve, &blitter->vb);
+
+   gen6_3DSTATE_VERTEX_ELEMENTS(p->builder,
+         &blitter->ve, false, false);
+
+   gen7_rectlist_pcb_alloc(p, blitter, session);
+
+   /* needed for any VS-related commands */
+   gen7_wa_pre_vs(p);
+
+   gen7_rectlist_urb(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->builder,
+            session->DEPTH_STENCIL_STATE);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      gen7_3DSTATE_CC_STATE_POINTERS(p->builder,
+            session->COLOR_CALC_STATE);
+   }
+
+   gen7_rectlist_vs_to_sf(p, blitter, session);
+   gen7_rectlist_wm(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->builder,
+            session->CC_VIEWPORT);
+   }
+
+   gen7_rectlist_wm_depth(p, blitter, session);
+
+   gen6_3DSTATE_DRAWING_RECTANGLE(p->builder, 0, 0,
+         blitter->fb.width, blitter->fb.height);
+
+   gen7_3DPRIMITIVE(p->builder, &blitter->draw, NULL);
+}
+
+static void
+gen7_rectlist_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_blitter *blitter,
+                     struct gen6_rectlist_session *session)
+{
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      session->DEPTH_STENCIL_STATE =
+         gen6_DEPTH_STENCIL_STATE(p->builder, &blitter->dsa);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      session->COLOR_CALC_STATE =
+         gen6_COLOR_CALC_STATE(p->builder, &blitter->cc.stencil_ref,
+               blitter->cc.alpha_ref, &blitter->cc.blend_color);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      session->CC_VIEWPORT =
+         gen6_CC_VIEWPORT(p->builder, &blitter->viewport, 1);
+   }
+}
+
+static void
+ilo_3d_pipeline_emit_rectlist_gen7(struct ilo_3d_pipeline *p,
+                                   const struct ilo_blitter *blitter)
+{
+   struct gen6_rectlist_session session;
+
+   memset(&session, 0, sizeof(session));
+   gen7_rectlist_states(p, blitter, &session);
+   gen7_rectlist_commands(p, blitter, &session);
+}
+
+static int
+gen7_pipeline_max_command_size(const struct ilo_3d_pipeline *p)
+{
+   static int size;
+
+   if (!size) {
+      size += GEN7_3DSTATE_URB_ANY__SIZE * 4;
+      size += GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_ANY__SIZE * 5;
+      size += GEN6_3DSTATE_CONSTANT_ANY__SIZE * 5;
+      size += GEN7_3DSTATE_POINTERS_ANY__SIZE * (5 + 5 + 4);
+      size += GEN7_3DSTATE_SO_BUFFER__SIZE * 4;
+      size += GEN6_PIPE_CONTROL__SIZE * 5;
+
+      size +=
+         GEN6_STATE_BASE_ADDRESS__SIZE +
+         GEN6_STATE_SIP__SIZE +
+         GEN6_3DSTATE_VF_STATISTICS__SIZE +
+         GEN6_PIPELINE_SELECT__SIZE +
+         GEN6_3DSTATE_CLEAR_PARAMS__SIZE +
+         GEN6_3DSTATE_DEPTH_BUFFER__SIZE +
+         GEN6_3DSTATE_STENCIL_BUFFER__SIZE +
+         GEN6_3DSTATE_HIER_DEPTH_BUFFER__SIZE +
+         GEN6_3DSTATE_VERTEX_BUFFERS__SIZE +
+         GEN6_3DSTATE_VERTEX_ELEMENTS__SIZE +
+         GEN6_3DSTATE_INDEX_BUFFER__SIZE +
+         GEN75_3DSTATE_VF__SIZE +
+         GEN6_3DSTATE_VS__SIZE +
+         GEN6_3DSTATE_GS__SIZE +
+         GEN6_3DSTATE_CLIP__SIZE +
+         GEN6_3DSTATE_SF__SIZE +
+         GEN6_3DSTATE_WM__SIZE +
+         GEN6_3DSTATE_SAMPLE_MASK__SIZE +
+         GEN7_3DSTATE_HS__SIZE +
+         GEN7_3DSTATE_TE__SIZE +
+         GEN7_3DSTATE_DS__SIZE +
+         GEN7_3DSTATE_STREAMOUT__SIZE +
+         GEN7_3DSTATE_SBE__SIZE +
+         GEN7_3DSTATE_PS__SIZE +
+         GEN6_3DSTATE_DRAWING_RECTANGLE__SIZE +
+         GEN6_3DSTATE_POLY_STIPPLE_OFFSET__SIZE +
+         GEN6_3DSTATE_POLY_STIPPLE_PATTERN__SIZE +
+         GEN6_3DSTATE_LINE_STIPPLE__SIZE +
+         GEN6_3DSTATE_AA_LINE_PARAMETERS__SIZE +
+         GEN6_3DSTATE_MULTISAMPLE__SIZE +
+         GEN7_3DSTATE_SO_DECL_LIST__SIZE +
+         GEN6_3DPRIMITIVE__SIZE;
+   }
+
+   return size;
+}
+
+static int
+ilo_3d_pipeline_estimate_size_gen7(struct ilo_3d_pipeline *p,
+                                   enum ilo_3d_pipeline_action action,
+                                   const void *arg)
+{
+   int size;
+
+   switch (action) {
+   case ILO_3D_PIPELINE_DRAW:
+      {
+         const struct ilo_state_vector *ilo = arg;
+
+         size = gen7_pipeline_max_command_size(p) +
+            gen6_pipeline_estimate_state_size(p, ilo);
+      }
+      break;
+   case ILO_3D_PIPELINE_FLUSH:
+      size = GEN6_PIPE_CONTROL__SIZE;
+      break;
+   case ILO_3D_PIPELINE_QUERY:
+      size = gen6_pipeline_estimate_query_size(p,
+            (const struct ilo_query *) arg);
+      break;
+   case ILO_3D_PIPELINE_RECTLIST:
+      size = 64 + 256; /* states + commands */
+      break;
+   default:
+      assert(!"unknown 3D pipeline action");
+      size = 0;
+      break;
+   }
+
+   return size;
+}
+
+void
+ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p)
+{
+   p->estimate_size = ilo_3d_pipeline_estimate_size_gen7;
+   p->emit_draw = ilo_3d_pipeline_emit_draw_gen7;
+   p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
+   p->emit_query = ilo_3d_pipeline_emit_query_gen6;
+   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen7;
+}
diff --git a/src/gallium/drivers/ilo/ilo_render_gen7.h b/src/gallium/drivers/ilo/ilo_render_gen7.h
new file mode 100644 (file)
index 0000000..cceb48a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef ILO_RENDER_GEN7_H
+#define ILO_RENDER_GEN7_H
+
+#include "ilo_common.h"
+
+struct ilo_3d_pipeline;
+
+void
+ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p);
+
+#endif /* ILO_RENDER_GEN7_H */