ilo: add ilo_state_index_buffer
authorChia-I Wu <olvaffe@gmail.com>
Fri, 19 Jun 2015 07:10:02 +0000 (15:10 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Sat, 20 Jun 2015 03:18:07 +0000 (11:18 +0800)
It serves the same purpose as ilo_state_vertex_buffer does.

src/gallium/drivers/ilo/core/ilo_builder_3d_top.h
src/gallium/drivers/ilo/core/ilo_state_vf.c
src/gallium/drivers/ilo/core/ilo_state_vf.h
src/gallium/drivers/ilo/ilo_render_gen6.c
src/gallium/drivers/ilo/ilo_render_gen8.c
src/gallium/drivers/ilo/ilo_state.c
src/gallium/drivers/ilo/ilo_state.h

index bb20c7f..6a45d70 100644 (file)
@@ -437,102 +437,63 @@ gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_builder *builder,
 static inline void
 gen6_3DSTATE_INDEX_BUFFER(struct ilo_builder *builder,
                           const struct ilo_state_vf *vf,
-                          const struct ilo_ib_state *ib)
+                          const struct ilo_state_index_buffer *ib)
 {
    const uint8_t cmd_len = 3;
-   struct ilo_buffer *buf = ilo_buffer(ib->hw_resource);
-   uint32_t start_offset, end_offset;
-   enum gen_index_format format;
-   uint32_t *dw;
+   uint32_t dw0, *dw;
    unsigned pos;
 
    ILO_DEV_ASSERT(builder->dev, 6, 7.5);
 
-   if (!buf)
-      return;
-
-   switch (ib->hw_index_size) {
-   case 4:
-      format = GEN6_INDEX_DWORD;
-      break;
-   case 2:
-      format = GEN6_INDEX_WORD;
-      break;
-   case 1:
-      format = GEN6_INDEX_BYTE;
-      break;
-   default:
-      assert(!"unknown index size");
-      format = GEN6_INDEX_BYTE;
-      break;
-   }
+   dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2) |
+         builder->mocs << GEN6_IB_DW0_MOCS__SHIFT;
 
    /*
-    * set start_offset to 0 here and adjust pipe_draw_info::start with
-    * ib->draw_start_offset in 3DPRIMITIVE
+    * see index_buffer_set_gen8_3DSTATE_INDEX_BUFFER() and
+    * vf_params_set_gen6_3dstate_index_buffer()
     */
-   start_offset = 0;
-   end_offset = buf->bo_size;
-
-   /* end_offset must also be aligned and is inclusive */
-   end_offset -= (end_offset % ib->hw_index_size);
-   end_offset--;
+   dw0 |= ib->ib[0];
+   if (ilo_dev_gen(builder->dev) <= ILO_GEN(7))
+      dw0 |= vf->cut[0];
 
    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
 
-   dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2) |
-           builder->mocs << GEN6_IB_DW0_MOCS__SHIFT |
-           format << GEN6_IB_DW0_FORMAT__SHIFT;
-
-   /* see vf_params_set_gen6_3dstate_index_buffer() */
-   if (ilo_dev_gen(builder->dev) <= ILO_GEN(7))
-      dw[0] |= vf->cut[0];
-
-   ilo_builder_batch_reloc(builder, pos + 1, buf->bo, start_offset, 0);
-   ilo_builder_batch_reloc(builder, pos + 2, buf->bo, end_offset, 0);
+   dw[0] = dw0;
+   if (ib->need_bo) {
+      ilo_builder_batch_reloc(builder, pos + 1, ib->bo, ib->ib[1], 0);
+      ilo_builder_batch_reloc(builder, pos + 2, ib->bo, ib->ib[2], 0);
+   } else {
+      dw[1] = 0;
+      dw[2] = 0;
+   }
 }
 
 static inline void
 gen8_3DSTATE_INDEX_BUFFER(struct ilo_builder *builder,
                           const struct ilo_state_vf *vf,
-                          const struct ilo_ib_state *ib)
+                          const struct ilo_state_index_buffer *ib)
 {
    const uint8_t cmd_len = 5;
-   struct ilo_buffer *buf = ilo_buffer(ib->hw_resource);
-   int format;
    uint32_t *dw;
    unsigned pos;
 
    ILO_DEV_ASSERT(builder->dev, 8, 8);
 
-   if (!buf)
-      return;
-
-   switch (ib->hw_index_size) {
-   case 4:
-      format = GEN6_INDEX_DWORD;
-      break;
-   case 2:
-      format = GEN6_INDEX_WORD;
-      break;
-   case 1:
-      format = GEN6_INDEX_BYTE;
-      break;
-   default:
-      assert(!"unknown index size");
-      format = GEN6_INDEX_BYTE;
-      break;
-   }
-
    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
 
    dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2);
-   dw[1] = format << GEN8_IB_DW1_FORMAT__SHIFT |
+   /* see index_buffer_set_gen8_3DSTATE_INDEX_BUFFER() */
+   dw[1] = ib->ib[0] |
            builder->mocs << GEN8_IB_DW1_MOCS__SHIFT;
-   dw[4] = buf->bo_size;
 
-   /* ignore ib->offset here in favor of adjusting 3DPRIMITIVE */
-   ilo_builder_batch_reloc64(builder, pos + 2, buf->bo, 0, 0);
+   if (ib->need_bo) {
+      ilo_builder_batch_reloc64(builder, pos + 2, ib->bo, ib->ib[1], 0);
+   } else {
+      dw[2] = 0;
+      dw[3] = 0;
+   }
+
+   dw[4] = ib->ib[2];
 }
 
 static inline void
index 92e0380..09e0f7f 100644 (file)
@@ -555,6 +555,93 @@ vertex_buffer_set_gen8_vertex_buffer_state(struct ilo_state_vertex_buffer *vb,
    return true;
 }
 
+static uint32_t
+get_index_format_size(enum gen_index_format format)
+{
+   switch (format) {
+   case GEN6_INDEX_BYTE:   return 1;
+   case GEN6_INDEX_WORD:   return 2;
+   case GEN6_INDEX_DWORD:  return 4;
+   default:
+      assert(!"unknown index format");
+      return 1;
+   }
+}
+
+static bool
+index_buffer_validate_gen6(const struct ilo_dev *dev,
+                           const struct ilo_state_index_buffer_info *info)
+{
+   const uint32_t format_size = get_index_format_size(info->format);
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 79:
+    *
+    *     "This field (Buffer Starting Address) contains the size-aligned (as
+    *      specified by Index Format) Graphics Address of the first element of
+    *      interest within the index buffer."
+    */
+   assert(info->offset % format_size == 0);
+
+   if (info->buf)
+      assert(info->offset < info->buf->bo_size && info->size);
+
+   return true;
+}
+
+static uint32_t
+index_buffer_get_gen6_size(const struct ilo_dev *dev,
+                           const struct ilo_state_index_buffer_info *info)
+{
+   uint32_t size;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   if (!info->buf)
+      return 0;
+
+   size = (info->offset + info->size <= info->buf->bo_size) ? info->size :
+      info->buf->bo_size - info->offset;
+
+   if (ilo_dev_gen(dev) < ILO_GEN(8)) {
+      const uint32_t format_size = get_index_format_size(info->format);
+      size -= (size % format_size);
+   }
+
+   return size;
+}
+
+static bool
+index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(struct ilo_state_index_buffer *ib,
+                                           const struct ilo_dev *dev,
+                                           const struct ilo_state_index_buffer_info *info)
+{
+   const uint32_t size = index_buffer_get_gen6_size(dev, info);
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   if (!index_buffer_validate_gen6(dev, info))
+      return false;
+
+   STATIC_ASSERT(ARRAY_SIZE(ib->ib) >= 3);
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      ib->ib[0] = info->format << GEN8_IB_DW1_FORMAT__SHIFT;
+      ib->ib[1] = info->offset;
+      ib->ib[2] = size;
+   } else {
+      ib->ib[0] = info->format << GEN6_IB_DW0_FORMAT__SHIFT;
+      ib->ib[1] = info->offset;
+      /* address of the last valid byte, or 0 */
+      ib->ib[2] = (size) ? info->offset + size - 1 : 0;
+   }
+
+   ib->need_bo = (info->buf != NULL);
+
+   return true;
+}
+
 bool
 ilo_state_vf_init(struct ilo_state_vf *vf,
                   const struct ilo_dev *dev,
@@ -752,3 +839,20 @@ ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer *vb,
 
    return ret;
 }
+
+/**
+ * No need to initialize first.
+ */
+bool
+ilo_state_index_buffer_set_info(struct ilo_state_index_buffer *ib,
+                                const struct ilo_dev *dev,
+                                const struct ilo_state_index_buffer_info *info)
+{
+   bool ret = true;
+
+   ret &= index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(ib, dev, info);
+
+   assert(ret);
+
+   return ret;
+}
index 488f92f..39750d8 100644 (file)
@@ -149,6 +149,23 @@ struct ilo_state_vertex_buffer {
    struct intel_bo *bo;
 };
 
+struct ilo_state_index_buffer_info {
+   const struct ilo_buffer *buf;
+   uint32_t offset;
+   uint32_t size;
+
+   enum gen_index_format format;
+};
+
+struct ilo_state_index_buffer {
+   uint32_t ib[3];
+
+   bool need_bo;
+
+   /* managed by users */
+   struct intel_bo *bo;
+};
+
 static inline size_t
 ilo_state_vf_data_size(const struct ilo_dev *dev, uint8_t element_count)
 {
@@ -199,4 +216,9 @@ ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer *vb,
                                  const struct ilo_dev *dev,
                                  const struct ilo_state_vertex_buffer_info *info);
 
+bool
+ilo_state_index_buffer_set_info(struct ilo_state_index_buffer *ib,
+                                const struct ilo_dev *dev,
+                                const struct ilo_state_index_buffer_info *info);
+
 #endif /* ILO_STATE_VF_H */
index 8415b13..0623714 100644 (file)
@@ -415,7 +415,7 @@ gen6_draw_vf(struct ilo_render *r,
       /* 3DSTATE_INDEX_BUFFER */
       if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) ||
           DIRTY(IB) || r->batch_bo_changed)
-         gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib);
+         gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib);
 
       /* 3DSTATE_VF */
       if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF)
@@ -424,7 +424,7 @@ gen6_draw_vf(struct ilo_render *r,
       /* 3DSTATE_INDEX_BUFFER */
       if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) ||
           DIRTY(IB) || r->batch_bo_changed)
-         gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib);
+         gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib);
    }
 
    /* 3DSTATE_VERTEX_BUFFERS */
index 4c1c08b..8956e5f 100644 (file)
@@ -202,7 +202,7 @@ gen8_draw_vf(struct ilo_render *r,
    /* 3DSTATE_INDEX_BUFFER */
    if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) ||
        DIRTY(IB) || r->batch_bo_changed)
-      gen8_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib);
+      gen8_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib);
 
    /* 3DSTATE_VF */
    if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF)
index e24f8fa..966a6e0 100644 (file)
@@ -379,11 +379,13 @@ finalize_constant_buffers(struct ilo_context *ilo)
 static void
 finalize_index_buffer(struct ilo_context *ilo)
 {
+   const struct ilo_dev *dev = ilo->dev;
    struct ilo_state_vector *vec = &ilo->state_vector;
    const bool need_upload = (vec->draw->indexed &&
          (vec->ib.state.user_buffer ||
           vec->ib.state.offset % vec->ib.state.index_size));
    struct pipe_resource *current_hw_res = NULL;
+   struct ilo_state_index_buffer_info info;
 
    if (!(vec->dirty & ILO_DIRTY_IB) && !need_upload)
       return;
@@ -435,6 +437,17 @@ finalize_index_buffer(struct ilo_context *ilo)
       vec->ib.hw_index_size = vec->ib.state.index_size;
 
    pipe_resource_reference(&current_hw_res, NULL);
+
+   memset(&info, 0, sizeof(info));
+   if (vec->ib.hw_resource) {
+      info.buf = ilo_buffer(vec->ib.hw_resource);
+      info.size = info.buf->bo_size;
+      info.format = ilo_translate_index_size(vec->ib.hw_index_size);
+
+      vec->ib.ib.bo = info.buf->bo;
+   }
+
+   ilo_state_index_buffer_set_info(&vec->ib.ib, dev, &info);
 }
 
 static void
index 2b3147f..d990269 100644 (file)
@@ -167,6 +167,7 @@ struct ilo_ib_state {
    /* these are not valid until the state is finalized */
    struct pipe_resource *hw_resource;
    unsigned hw_index_size;
+   struct ilo_state_index_buffer ib;
    /* an offset to be added to pipe_draw_info::start */
    int64_t draw_start_offset;
 };