ilo: add ilo_view_surface for SURFACE_STATE
authorChia-I Wu <olvaffe@gmail.com>
Thu, 6 Jun 2013 03:16:13 +0000 (11:16 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 7 Jun 2013 03:13:15 +0000 (11:13 +0800)
Define struct ilo_view_surface for SURFACE_STATE construction and emission.

src/gallium/drivers/ilo/ilo_gpe.h
src/gallium/drivers/ilo/ilo_gpe_gen6.c
src/gallium/drivers/ilo/ilo_gpe_gen7.c

index a84140b4876e88754fe7cc84075e9ad08f04c540..ccb4ebc1f0e2f5f1966010bef4e9ea518eb32cf3 100644 (file)
@@ -53,6 +53,9 @@
 #define ILO_WM_CONST_SURFACE(i)    (ILO_MAX_DRAW_BUFFERS + i)
 #define ILO_WM_TEXTURE_SURFACE(i)  (ILO_MAX_DRAW_BUFFERS + ILO_MAX_CONST_BUFFERS  + i)
 
+struct ilo_buffer;
+struct ilo_texture;
+
 struct ilo_vb_state {
    struct pipe_vertex_buffer states[PIPE_MAX_ATTRIBS];
    uint32_t enabled_mask;
@@ -159,6 +162,12 @@ struct ilo_sampler_state {
    unsigned count;
 };
 
+struct ilo_view_surface {
+   /* SURFACE_STATE */
+   uint32_t payload[8];
+   struct intel_bo *bo;
+};
+
 struct ilo_view_state {
    struct pipe_sampler_view *states[ILO_MAX_SAMPLER_VIEWS];
    unsigned count;
@@ -239,4 +248,114 @@ ilo_gpe_init_sampler_cso(const struct ilo_dev_info *dev,
                          const struct pipe_sampler_state *state,
                          struct ilo_sampler_cso *sampler);
 
+void
+ilo_gpe_init_view_surface_null_gen6(const struct ilo_dev_info *dev,
+                                    unsigned width, unsigned height,
+                                    unsigned depth, unsigned level,
+                                    struct ilo_view_surface *surf);
+
+void
+ilo_gpe_init_view_surface_for_buffer_gen6(const struct ilo_dev_info *dev,
+                                          const struct ilo_buffer *buf,
+                                          unsigned offset, unsigned size,
+                                          unsigned struct_size,
+                                          enum pipe_format elem_format,
+                                          bool is_rt, bool render_cache_rw,
+                                          struct ilo_view_surface *surf);
+
+void
+ilo_gpe_init_view_surface_for_texture_gen6(const struct ilo_dev_info *dev,
+                                           const struct ilo_texture *tex,
+                                           enum pipe_format format,
+                                           unsigned first_level,
+                                           unsigned num_levels,
+                                           unsigned first_layer,
+                                           unsigned num_layers,
+                                           bool is_rt, bool render_cache_rw,
+                                           struct ilo_view_surface *surf);
+
+void
+ilo_gpe_init_view_surface_null_gen7(const struct ilo_dev_info *dev,
+                                    unsigned width, unsigned height,
+                                    unsigned depth, unsigned level,
+                                    struct ilo_view_surface *surf);
+
+void
+ilo_gpe_init_view_surface_for_buffer_gen7(const struct ilo_dev_info *dev,
+                                          const struct ilo_buffer *buf,
+                                          unsigned offset, unsigned size,
+                                          unsigned struct_size,
+                                          enum pipe_format elem_format,
+                                          bool is_rt, bool render_cache_rw,
+                                          struct ilo_view_surface *surf);
+
+void
+ilo_gpe_init_view_surface_for_texture_gen7(const struct ilo_dev_info *dev,
+                                           const struct ilo_texture *tex,
+                                           enum pipe_format format,
+                                           unsigned first_level,
+                                           unsigned num_levels,
+                                           unsigned first_layer,
+                                           unsigned num_layers,
+                                           bool is_rt, bool render_cache_rw,
+                                           struct ilo_view_surface *surf);
+
+static inline void
+ilo_gpe_init_view_surface_null(const struct ilo_dev_info *dev,
+                               unsigned width, unsigned height,
+                               unsigned depth, unsigned level,
+                               struct ilo_view_surface *surf)
+{
+   if (dev->gen >= ILO_GEN(7)) {
+      ilo_gpe_init_view_surface_null_gen7(dev,
+            width, height, depth, level, surf);
+   }
+   else {
+      ilo_gpe_init_view_surface_null_gen6(dev,
+            width, height, depth, level, surf);
+   }
+}
+
+static inline void
+ilo_gpe_init_view_surface_for_buffer(const struct ilo_dev_info *dev,
+                                     const struct ilo_buffer *buf,
+                                     unsigned offset, unsigned size,
+                                     unsigned struct_size,
+                                     enum pipe_format elem_format,
+                                     bool is_rt, bool render_cache_rw,
+                                     struct ilo_view_surface *surf)
+{
+   if (dev->gen >= ILO_GEN(7)) {
+      ilo_gpe_init_view_surface_for_buffer_gen7(dev, buf, offset, size,
+            struct_size, elem_format, is_rt, render_cache_rw, surf);
+   }
+   else {
+      ilo_gpe_init_view_surface_for_buffer_gen6(dev, buf, offset, size,
+            struct_size, elem_format, is_rt, render_cache_rw, surf);
+   }
+}
+
+static inline void
+ilo_gpe_init_view_surface_for_texture(const struct ilo_dev_info *dev,
+                                      const struct ilo_texture *tex,
+                                      enum pipe_format format,
+                                      unsigned first_level,
+                                      unsigned num_levels,
+                                      unsigned first_layer,
+                                      unsigned num_layers,
+                                      bool is_rt, bool render_cache_rw,
+                                      struct ilo_view_surface *surf)
+{
+   if (dev->gen >= ILO_GEN(7)) {
+      ilo_gpe_init_view_surface_for_texture_gen7(dev, tex, format,
+            first_level, num_levels, first_layer, num_layers,
+            is_rt, render_cache_rw, surf);
+   }
+   else {
+      ilo_gpe_init_view_surface_for_texture_gen6(dev, tex, format,
+            first_level, num_levels, first_layer, num_layers,
+            is_rt, render_cache_rw, surf);
+   }
+}
+
 #endif /* ILO_GPE_H */
index 82818e78aa3ee9d78de32055bd08938e06c6484b..f6d2fab27864fda25ea8fe53dfd8360ef531f8f5 100644 (file)
@@ -3784,14 +3784,15 @@ gen6_emit_BINDING_TABLE_STATE(const struct ilo_dev_info *dev,
    return state_offset;
 }
 
-static void
-gen6_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
-                             unsigned width, unsigned height,
-                             unsigned depth, unsigned lod,
-                             uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_null_gen6(const struct ilo_dev_info *dev,
+                                    unsigned width, unsigned height,
+                                    unsigned depth, unsigned level,
+                                    struct ilo_view_surface *surf)
 {
+   uint32_t *dw;
+
    ILO_GPE_VALID_GEN(dev, 6, 6);
-   assert(num_dwords == 6);
 
    /*
     * From the Sandy Bridge PRM, volume 4 part 1, page 71:
@@ -3816,6 +3817,9 @@ gen6_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
     *      true"
     */
 
+   STATIC_ASSERT(Elements(surf->payload) >= 6);
+   dw = surf->payload;
+
    dw[0] = BRW_SURFACE_NULL << BRW_SURFACE_TYPE_SHIFT |
            BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT;
 
@@ -3823,30 +3827,32 @@ gen6_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    dw[2] = (height - 1) << BRW_SURFACE_HEIGHT_SHIFT |
            (width  - 1) << BRW_SURFACE_WIDTH_SHIFT |
-           lod << BRW_SURFACE_LOD_SHIFT;
+           level << BRW_SURFACE_LOD_SHIFT;
 
    dw[3] = (depth - 1) << BRW_SURFACE_DEPTH_SHIFT |
            BRW_SURFACE_TILED;
 
    dw[4] = 0;
    dw[5] = 0;
+
+   surf->bo = NULL;
 }
 
-static void
-gen6_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
-                               const struct ilo_buffer *buf,
-                               unsigned offset, unsigned size,
-                               unsigned struct_size,
-                               enum pipe_format elem_format,
-                               bool is_rt, bool render_cache_rw,
-                               uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_for_buffer_gen6(const struct ilo_dev_info *dev,
+                                          const struct ilo_buffer *buf,
+                                          unsigned offset, unsigned size,
+                                          unsigned struct_size,
+                                          enum pipe_format elem_format,
+                                          bool is_rt, bool render_cache_rw,
+                                          struct ilo_view_surface *surf)
 {
    const int elem_size = util_format_get_blocksize(elem_format);
    int width, height, depth, pitch;
    int surface_format, num_entries;
+   uint32_t *dw;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
-   assert(num_dwords == 6);
 
    /*
     * For SURFTYPE_BUFFER, a SURFACE_STATE specifies an element of a
@@ -3903,6 +3909,9 @@ gen6_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
    /* bits [26:20] */
    depth  = (num_entries & 0x07f00000) >> 20;
 
+   STATIC_ASSERT(Elements(surf->payload) >= 6);
+   dw = surf->payload;
+
    dw[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT |
            surface_format << BRW_SURFACE_FORMAT_SHIFT;
    if (render_cache_rw)
@@ -3918,23 +3927,28 @@ gen6_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    dw[4] = 0;
    dw[5] = 0;
+
+   /* do not increment reference count */
+   surf->bo = buf->bo;
 }
 
-static void
-gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
-                               struct ilo_texture *tex,
-                               enum pipe_format format,
-                               unsigned first_level, unsigned num_levels,
-                               unsigned first_layer, unsigned num_layers,
-                               bool is_rt, bool render_cache_rw,
-                               uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_for_texture_gen6(const struct ilo_dev_info *dev,
+                                           const struct ilo_texture *tex,
+                                           enum pipe_format format,
+                                           unsigned first_level,
+                                           unsigned num_levels,
+                                           unsigned first_layer,
+                                           unsigned num_layers,
+                                           bool is_rt, bool render_cache_rw,
+                                           struct ilo_view_surface *surf)
 {
    int surface_type, surface_format;
    int width, height, depth, pitch, lod;
    unsigned layer_offset, x_offset, y_offset;
+   uint32_t *dw;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
-   assert(num_dwords == 6);
 
    surface_type = ilo_gpe_gen6_translate_texture(tex->base.target);
    assert(surface_type != BRW_SURFACE_BUFFER);
@@ -4088,6 +4102,9 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
       assert(!x_offset);
    }
 
+   STATIC_ASSERT(Elements(surf->payload) >= 6);
+   dw = surf->payload;
+
    dw[0] = surface_type << BRW_SURFACE_TYPE_SHIFT |
            surface_format << BRW_SURFACE_FORMAT_SHIFT |
            BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT;
@@ -4120,12 +4137,15 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
            y_offset << BRW_SURFACE_Y_OFFSET_SHIFT;
    if (tex->valign_4)
       dw[5] |= BRW_SURFACE_VERTICAL_ALIGN_ENABLE;
+
+   /* do not increment reference count */
+   surf->bo = tex->bo;
 }
 
 static uint32_t
 gen6_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
-                        struct intel_bo *bo, bool for_render,
-                        const uint32_t *dw, int num_dwords,
+                        const struct ilo_view_surface *surf,
+                        bool for_render,
                         struct ilo_cp *cp)
 {
    const int state_align = 32 / 4;
@@ -4134,7 +4154,6 @@ gen6_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
    uint32_t read_domains, write_domain;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
-   assert(num_dwords == state_len);
 
    if (for_render) {
       read_domains = INTEL_DOMAIN_RENDER;
@@ -4146,12 +4165,15 @@ gen6_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
    }
 
    ilo_cp_steal(cp, "SURFACE_STATE", state_len, state_align, &state_offset);
-   ilo_cp_write(cp, dw[0]);
-   ilo_cp_write_bo(cp, dw[1], bo, read_domains, write_domain);
-   ilo_cp_write(cp, dw[2]);
-   ilo_cp_write(cp, dw[3]);
-   ilo_cp_write(cp, dw[4]);
-   ilo_cp_write(cp, dw[5]);
+
+   ilo_cp_write(cp, surf->payload[0]);
+   ilo_cp_write_bo(cp, surf->payload[1],
+         surf->bo, read_domains, write_domain);
+   ilo_cp_write(cp, surf->payload[2]);
+   ilo_cp_write(cp, surf->payload[3]);
+   ilo_cp_write(cp, surf->payload[4]);
+   ilo_cp_write(cp, surf->payload[5]);
+
    ilo_cp_end(cp);
 
    return state_offset;
@@ -4162,33 +4184,29 @@ gen6_emit_surf_SURFACE_STATE(const struct ilo_dev_info *dev,
                              const struct pipe_surface *surface,
                              struct ilo_cp *cp)
 {
-   struct intel_bo *bo;
-   uint32_t dw[6];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
 
    if (surface && surface->texture) {
       struct ilo_texture *tex = ilo_texture(surface->texture);
 
-      bo = tex->bo;
-
       /*
        * classic i965 sets render_cache_rw for constant buffers and sol
        * surfaces but not render buffers.  Why?
        */
-      gen6_fill_normal_SURFACE_STATE(dev, tex, surface->format,
+      ilo_gpe_init_view_surface_for_texture_gen6(dev, tex, surface->format,
             surface->u.tex.level, 1,
             surface->u.tex.first_layer,
             surface->u.tex.last_layer - surface->u.tex.first_layer + 1,
-            true, true, dw, Elements(dw));
+            true, true, &surf);
    }
    else {
-      bo = NULL;
-      gen6_fill_null_SURFACE_STATE(dev,
-            surface->width, surface->height, 1, 0, dw, Elements(dw));
+      ilo_gpe_init_view_surface_null_gen6(dev,
+            surface->width, surface->height, 1, 0, &surf);
    }
 
-   return gen6_emit_SURFACE_STATE(dev, bo, true, dw, Elements(dw), cp);
+   return gen6_emit_SURFACE_STATE(dev, &surf, true, cp);
 }
 
 static uint32_t
@@ -4196,8 +4214,7 @@ gen6_emit_view_SURFACE_STATE(const struct ilo_dev_info *dev,
                              const struct pipe_sampler_view *view,
                              struct ilo_cp *cp)
 {
-   struct intel_bo *bo;
-   uint32_t dw[6];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
 
@@ -4207,26 +4224,22 @@ gen6_emit_view_SURFACE_STATE(const struct ilo_dev_info *dev,
       const unsigned num_elems = view->u.buf.last_element - first_elem + 1;
       struct ilo_buffer *buf = ilo_buffer(view->texture);
 
-      gen6_fill_buffer_SURFACE_STATE(dev, buf,
+      ilo_gpe_init_view_surface_for_buffer_gen6(dev, buf,
             first_elem * elem_size, num_elems * elem_size,
-            elem_size, view->format, false, false, dw, Elements(dw));
-
-      bo = buf->bo;
+            elem_size, view->format, false, false, &surf);
    }
    else {
       struct ilo_texture *tex = ilo_texture(view->texture);
 
-      gen6_fill_normal_SURFACE_STATE(dev, tex, view->format,
+      ilo_gpe_init_view_surface_for_texture_gen6(dev, tex, view->format,
             view->u.tex.first_level,
             view->u.tex.last_level - view->u.tex.first_level + 1,
             view->u.tex.first_layer,
             view->u.tex.last_layer - view->u.tex.first_layer + 1,
-            false, false, dw, Elements(dw));
-
-      bo = tex->bo;
+            false, false, &surf);
    }
 
-   return gen6_emit_SURFACE_STATE(dev, bo, false, dw, Elements(dw), cp);
+   return gen6_emit_SURFACE_STATE(dev, &surf, false, cp);
 }
 
 static uint32_t
@@ -4236,16 +4249,16 @@ gen6_emit_cbuf_SURFACE_STATE(const struct ilo_dev_info *dev,
 {
    const enum pipe_format elem_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    struct ilo_buffer *buf = ilo_buffer(cbuf->buffer);
-   uint32_t dw[6];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
 
-   gen6_fill_buffer_SURFACE_STATE(dev, buf,
+   ilo_gpe_init_view_surface_for_buffer_gen6(dev, buf,
          cbuf->buffer_offset, cbuf->buffer_size,
          util_format_get_blocksize(elem_format), elem_format,
-         false, false, dw, Elements(dw));
+         false, false, &surf);
 
-   return gen6_emit_SURFACE_STATE(dev, buf->bo, false, dw, Elements(dw), cp);
+   return gen6_emit_SURFACE_STATE(dev, &surf, false, cp);
 }
 
 static uint32_t
@@ -4258,7 +4271,7 @@ gen6_emit_so_SURFACE_STATE(const struct ilo_dev_info *dev,
    struct ilo_buffer *buf = ilo_buffer(so->buffer);
    unsigned bo_offset, struct_size;
    enum pipe_format elem_format;
-   uint32_t dw[6];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
 
@@ -4284,10 +4297,10 @@ gen6_emit_so_SURFACE_STATE(const struct ilo_dev_info *dev,
       break;
    }
 
-   gen6_fill_buffer_SURFACE_STATE(dev, buf, bo_offset, so->buffer_size,
-         struct_size, elem_format, false, true, dw, Elements(dw));
+   ilo_gpe_init_view_surface_for_buffer_gen6(dev, buf, bo_offset, so->buffer_size,
+         struct_size, elem_format, false, true, &surf);
 
-   return gen6_emit_SURFACE_STATE(dev, buf->bo, false, dw, Elements(dw), cp);
+   return gen6_emit_SURFACE_STATE(dev, &surf, false, cp);
 }
 
 static void
index 4ec0e8608b9a9e92214dca168fb69f6fc9692035..43b76628d66c459b3b7d8ad5609c88daf26543ff 100644 (file)
@@ -1235,14 +1235,15 @@ gen7_emit_SF_CLIP_VIEWPORT(const struct ilo_dev_info *dev,
    return state_offset;
 }
 
-static void
-gen7_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
-                             unsigned width, unsigned height,
-                             unsigned depth, unsigned lod,
-                             uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_null_gen7(const struct ilo_dev_info *dev,
+                                    unsigned width, unsigned height,
+                                    unsigned depth, unsigned level,
+                                    struct ilo_view_surface *surf)
 {
+   uint32_t *dw;
+
    ILO_GPE_VALID_GEN(dev, 7, 7);
-   assert(num_dwords == 8);
 
    /*
     * From the Ivy Bridge PRM, volume 4 part 1, page 62:
@@ -1275,6 +1276,9 @@ gen7_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
     *      true"
     */
 
+   STATIC_ASSERT(Elements(surf->payload) >= 8);
+   dw = surf->payload;
+
    dw[0] = BRW_SURFACE_NULL << BRW_SURFACE_TYPE_SHIFT |
            BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT |
            BRW_SURFACE_TILED << 13;
@@ -1287,19 +1291,22 @@ gen7_fill_null_SURFACE_STATE(const struct ilo_dev_info *dev,
    dw[3] = SET_FIELD(depth - 1, BRW_SURFACE_DEPTH);
 
    dw[4] = 0;
-   dw[5] = lod;
+   dw[5] = level;
+
    dw[6] = 0;
    dw[7] = 0;
+
+   surf->bo = NULL;
 }
 
-static void
-gen7_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
-                               const struct ilo_buffer *buf,
-                               unsigned offset, unsigned size,
-                               unsigned struct_size,
-                               enum pipe_format elem_format,
-                               bool is_rt, bool render_cache_rw,
-                               uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_for_buffer_gen7(const struct ilo_dev_info *dev,
+                                          const struct ilo_buffer *buf,
+                                          unsigned offset, unsigned size,
+                                          unsigned struct_size,
+                                          enum pipe_format elem_format,
+                                          bool is_rt, bool render_cache_rw,
+                                          struct ilo_view_surface *surf)
 {
    const bool typed = (elem_format != PIPE_FORMAT_NONE);
    const bool structured = (!typed && struct_size > 1);
@@ -1307,9 +1314,9 @@ gen7_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
       util_format_get_blocksize(elem_format) : 1;
    int width, height, depth, pitch;
    int surface_type, surface_format, num_entries;
+   uint32_t *dw;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
-   assert(num_dwords == 8);
 
    surface_type = (structured) ? 5 : BRW_SURFACE_BUFFER;
 
@@ -1384,6 +1391,9 @@ gen7_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
    if (typed || structured)
       depth &= 0x3f;
 
+   STATIC_ASSERT(Elements(surf->payload) >= 8);
+   dw = surf->payload;
+
    dw[0] = surface_type << BRW_SURFACE_TYPE_SHIFT |
            surface_format << BRW_SURFACE_FORMAT_SHIFT;
    if (render_cache_rw)
@@ -1399,25 +1409,31 @@ gen7_fill_buffer_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    dw[4] = 0;
    dw[5] = 0;
+
    dw[6] = 0;
    dw[7] = 0;
+
+   /* do not increment reference count */
+   surf->bo = buf->bo;
 }
 
-static void
-gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
-                               struct ilo_texture *tex,
-                               enum pipe_format format,
-                               unsigned first_level, unsigned num_levels,
-                               unsigned first_layer, unsigned num_layers,
-                               bool is_rt, bool render_cache_rw,
-                               uint32_t *dw, int num_dwords)
+void
+ilo_gpe_init_view_surface_for_texture_gen7(const struct ilo_dev_info *dev,
+                                           const struct ilo_texture *tex,
+                                           enum pipe_format format,
+                                           unsigned first_level,
+                                           unsigned num_levels,
+                                           unsigned first_layer,
+                                           unsigned num_layers,
+                                           bool is_rt, bool render_cache_rw,
+                                           struct ilo_view_surface *surf)
 {
    int surface_type, surface_format;
    int width, height, depth, pitch, lod;
    unsigned layer_offset, x_offset, y_offset;
+   uint32_t *dw;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
-   assert(num_dwords == 8);
 
    surface_type = ilo_gpe_gen6_translate_texture(tex->base.target);
    assert(surface_type != BRW_SURFACE_BUFFER);
@@ -1566,6 +1582,9 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
       assert(!x_offset);
    }
 
+   STATIC_ASSERT(Elements(surf->payload) >= 8);
+   dw = surf->payload;
+
    dw[0] = surface_type << BRW_SURFACE_TYPE_SHIFT |
            surface_format << BRW_SURFACE_FORMAT_SHIFT |
            ilo_gpe_gen6_translate_winsys_tiling(tex->tiling) << 13;
@@ -1628,13 +1647,15 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    dw[6] = 0;
    dw[7] = 0;
+
+   /* do not increment reference count */
+   surf->bo = tex->bo;
 }
 
 static uint32_t
 gen7_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
-                        struct intel_bo *bo, bool for_render,
-                        const uint32_t *dw, int num_dwords,
-                        struct ilo_cp *cp)
+                        const struct ilo_view_surface *surf,
+                        bool for_render, struct ilo_cp *cp)
 {
    const int state_align = 32 / 4;
    const int state_len = 8;
@@ -1642,7 +1663,6 @@ gen7_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
    uint32_t read_domains, write_domain;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
-   assert(num_dwords == state_len);
 
    if (for_render) {
       read_domains = INTEL_DOMAIN_RENDER;
@@ -1654,14 +1674,14 @@ gen7_emit_SURFACE_STATE(const struct ilo_dev_info *dev,
    }
 
    ilo_cp_steal(cp, "SURFACE_STATE", state_len, state_align, &state_offset);
-   ilo_cp_write(cp, dw[0]);
-   ilo_cp_write_bo(cp, dw[1], bo, read_domains, write_domain);
-   ilo_cp_write(cp, dw[2]);
-   ilo_cp_write(cp, dw[3]);
-   ilo_cp_write(cp, dw[4]);
-   ilo_cp_write(cp, dw[5]);
-   ilo_cp_write(cp, dw[6]);
-   ilo_cp_write(cp, dw[7]);
+   ilo_cp_write(cp, surf->payload[0]);
+   ilo_cp_write_bo(cp, surf->payload[1], surf->bo, read_domains, write_domain);
+   ilo_cp_write(cp, surf->payload[2]);
+   ilo_cp_write(cp, surf->payload[3]);
+   ilo_cp_write(cp, surf->payload[4]);
+   ilo_cp_write(cp, surf->payload[5]);
+   ilo_cp_write(cp, surf->payload[6]);
+   ilo_cp_write(cp, surf->payload[7]);
    ilo_cp_end(cp);
 
    return state_offset;
@@ -1672,33 +1692,29 @@ gen7_emit_surf_SURFACE_STATE(const struct ilo_dev_info *dev,
                              const struct pipe_surface *surface,
                              struct ilo_cp *cp)
 {
-   struct intel_bo *bo;
-   uint32_t dw[8];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
 
    if (surface && surface->texture) {
       struct ilo_texture *tex = ilo_texture(surface->texture);
 
-      bo = tex->bo;
-
       /*
        * classic i965 sets render_cache_rw for constant buffers and sol
        * surfaces but not render buffers.  Why?
        */
-      gen7_fill_normal_SURFACE_STATE(dev, tex, surface->format,
+      ilo_gpe_init_view_surface_for_texture_gen7(dev, tex, surface->format,
             surface->u.tex.level, 1,
             surface->u.tex.first_layer,
             surface->u.tex.last_layer - surface->u.tex.first_layer + 1,
-            true, true, dw, Elements(dw));
+            true, true, &surf);
    }
    else {
-      bo = NULL;
-      gen7_fill_null_SURFACE_STATE(dev,
-            surface->width, surface->height, 1, 0, dw, Elements(dw));
+      ilo_gpe_init_view_surface_null_gen7(dev,
+            surface->width, surface->height, 1, 0, &surf);
    }
 
-   return gen7_emit_SURFACE_STATE(dev, bo, true, dw, Elements(dw), cp);
+   return gen7_emit_SURFACE_STATE(dev, &surf, true, cp);
 }
 
 static uint32_t
@@ -1706,8 +1722,7 @@ gen7_emit_view_SURFACE_STATE(const struct ilo_dev_info *dev,
                              const struct pipe_sampler_view *view,
                              struct ilo_cp *cp)
 {
-   struct intel_bo *bo;
-   uint32_t dw[8];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
 
@@ -1717,26 +1732,22 @@ gen7_emit_view_SURFACE_STATE(const struct ilo_dev_info *dev,
       const unsigned num_elems = view->u.buf.last_element - first_elem + 1;
       struct ilo_buffer *buf = ilo_buffer(view->texture);
 
-      gen7_fill_buffer_SURFACE_STATE(dev, buf,
+      ilo_gpe_init_view_surface_for_buffer_gen7(dev, buf,
             first_elem * elem_size, num_elems * elem_size,
-            elem_size, view->format, false, false, dw, Elements(dw));
-
-      bo = buf->bo;
+            elem_size, view->format, false, false, &surf);
    }
    else {
       struct ilo_texture *tex = ilo_texture(view->texture);
 
-      gen7_fill_normal_SURFACE_STATE(dev, tex, view->format,
+      ilo_gpe_init_view_surface_for_texture_gen7(dev, tex, view->format,
             view->u.tex.first_level,
             view->u.tex.last_level - view->u.tex.first_level + 1,
             view->u.tex.first_layer,
             view->u.tex.last_layer - view->u.tex.first_layer + 1,
-            false, false, dw, Elements(dw));
-
-      bo = tex->bo;
+            false, false, &surf);
    }
 
-   return gen7_emit_SURFACE_STATE(dev, bo, false, dw, Elements(dw), cp);
+   return gen7_emit_SURFACE_STATE(dev, &surf, false, cp);
 }
 
 static uint32_t
@@ -1746,16 +1757,16 @@ gen7_emit_cbuf_SURFACE_STATE(const struct ilo_dev_info *dev,
 {
    const enum pipe_format elem_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    struct ilo_buffer *buf = ilo_buffer(cbuf->buffer);
-   uint32_t dw[8];
+   struct ilo_view_surface surf;
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
 
-   gen7_fill_buffer_SURFACE_STATE(dev, buf,
+   ilo_gpe_init_view_surface_for_buffer_gen7(dev, buf,
          cbuf->buffer_offset, cbuf->buffer_size,
          util_format_get_blocksize(elem_format), elem_format,
-         false, false, dw, Elements(dw));
+         false, false, &surf);
 
-   return gen7_emit_SURFACE_STATE(dev, buf->bo, false, dw, Elements(dw), cp);
+   return gen7_emit_SURFACE_STATE(dev, &surf, false, cp);
 }
 
 static int