ilo: support PIPE_CAP_USER_INDEX_BUFFERS
authorChia-I Wu <olvaffe@gmail.com>
Wed, 26 Jun 2013 05:44:27 +0000 (13:44 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 26 Jun 2013 08:42:46 +0000 (16:42 +0800)
We want to access the user buffer, if available, when primitive restart is
enabled and the restart index/primitive type is not natively supported.

And since we are handling index buffer uploads in the driver with this change,
we can also work around misalignment of index buffer offsets.

src/gallium/drivers/ilo/ilo_3d.c
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
src/gallium/drivers/ilo/ilo_context.c
src/gallium/drivers/ilo/ilo_gpe.h
src/gallium/drivers/ilo/ilo_gpe_gen6.c
src/gallium/drivers/ilo/ilo_gpe_gen6.h
src/gallium/drivers/ilo/ilo_gpe_gen7.c
src/gallium/drivers/ilo/ilo_screen.c
src/gallium/drivers/ilo/ilo_state.c

index 69808d90751741af72dec417b3275056d2c4c8ed..ef3aeced340b3e6ec9a8c75df9a01a954acb0393 100644 (file)
@@ -605,15 +605,22 @@ ilo_draw_vbo_with_sw_restart(struct pipe_context *pipe,
       return;
    }
 
-   struct pipe_transfer *transfer = NULL;
-   const void *map = NULL;
-   map = pipe_buffer_map(pipe, ilo->ib.state.buffer,
-         PIPE_TRANSFER_READ, &transfer);
+   if (ilo->ib.state.buffer) {
+      struct pipe_transfer *transfer;
+      const void *map;
 
-   sub_prim_count = ilo_find_sub_primitives(map + ilo->ib.state.offset,
-           ilo->ib.state.index_size, info, restart_info);
+      map = pipe_buffer_map(pipe, ilo->ib.state.buffer,
+            PIPE_TRANSFER_READ, &transfer);
 
-   pipe_buffer_unmap(pipe, transfer);
+      sub_prim_count = ilo_find_sub_primitives(map + ilo->ib.state.offset,
+            ilo->ib.state.index_size, info, restart_info);
+
+      pipe_buffer_unmap(pipe, transfer);
+   }
+   else {
+      sub_prim_count = ilo_find_sub_primitives(ilo->ib.state.user_buffer,
+            ilo->ib.state.index_size, info, restart_info);
+   }
 
    info = restart_info;
 
index 00da47f3bb2c7dcfbe333cecea392ac6c569cc2c..190f6a9d9fbe4803ec07a2f6cd706d864ef96cd2 100644 (file)
@@ -401,7 +401,7 @@ gen6_pipeline_vf(struct ilo_3d_pipeline *p,
    /* 3DSTATE_INDEX_BUFFER */
    if (DIRTY(INDEX_BUFFER) || session->batch_bo_changed) {
       p->gen6_3DSTATE_INDEX_BUFFER(p->dev,
-            &ilo->ib.state, ilo->draw->primitive_restart, p->cp);
+            &ilo->ib, ilo->draw->primitive_restart, p->cp);
    }
 
    /* 3DSTATE_VERTEX_BUFFERS */
@@ -455,7 +455,7 @@ gen6_pipeline_vf_draw(struct ilo_3d_pipeline *p,
                       struct gen6_pipeline_session *session)
 {
    /* 3DPRIMITIVE */
-   p->gen6_3DPRIMITIVE(p->dev, ilo->draw, false, p->cp);
+   p->gen6_3DPRIMITIVE(p->dev, ilo->draw, &ilo->ib, false, p->cp);
    p->state.has_gen6_wa_pipe_control = false;
 }
 
index e355a9c3089fb6f7630237f86f27ced8130e83c4..7fd5ab6b524d4db9adf255d2c20174222200a1a9 100644 (file)
@@ -145,7 +145,7 @@ ilo_context_create(struct pipe_screen *screen, void *priv)
    }
 
    ilo->uploader = u_upload_create(&ilo->base, 1024 * 1024, 16,
-         PIPE_BIND_CONSTANT_BUFFER);
+         PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_INDEX_BUFFER);
    if (!ilo->uploader) {
       ilo_context_destroy(&ilo->base);
       return NULL;
index 7825e58a40fe5c997fc8445ebd70ea57a714ebee..aa979f31a09a28a0c4c9ff88fd0f4afb9146b716 100644 (file)
@@ -64,6 +64,9 @@ struct ilo_vb_state {
 
 struct ilo_ib_state {
    struct pipe_index_buffer state;
+
+   struct pipe_resource *resource;
+   int64_t draw_start_offset;
 };
 
 struct ilo_ve_cso {
index 75721f160ab04d35cb32d4626c78bd63f7b32070..9c88b0a5b319263e27e410ff9b2a74a2d7d44ca2 100644 (file)
@@ -1027,13 +1027,13 @@ gen6_emit_3DSTATE_VERTEX_ELEMENTS(const struct ilo_dev_info *dev,
 
 static void
 gen6_emit_3DSTATE_INDEX_BUFFER(const struct ilo_dev_info *dev,
-                               const struct pipe_index_buffer *ib,
+                               const struct ilo_ib_state *ib,
                                bool enable_cut_index,
                                struct ilo_cp *cp)
 {
    const uint32_t cmd = ILO_GPE_CMD(0x3, 0x0, 0x0a);
    const uint8_t cmd_len = 3;
-   const struct ilo_buffer *buf = ilo_buffer(ib->buffer);
+   const struct ilo_buffer *buf = ilo_buffer(ib->resource);
    uint32_t start_offset, end_offset;
    int format;
 
@@ -1042,21 +1042,18 @@ gen6_emit_3DSTATE_INDEX_BUFFER(const struct ilo_dev_info *dev,
    if (!buf)
       return;
 
-   format = gen6_translate_index_size(ib->index_size);
+   format = gen6_translate_index_size(ib->state.index_size);
 
-   start_offset = ib->offset;
-   /* start_offset must be aligned to index size */
-   if (start_offset % ib->index_size) {
-      /* TODO need a u_upload_mgr to upload the IB to an aligned address */
-      assert(!"unaligned index buffer offset");
-      start_offset -= start_offset % ib->index_size;
-   }
-
-   /* end_offset must also be aligned */
+   /*
+    * set start_offset to 0 here and adjust pipe_draw_info::start with
+    * ib->draw_start_offset in 3DPRIMITIVE
+    */
+   start_offset = 0;
    end_offset = buf->bo_size;
-   end_offset -= (end_offset % ib->index_size);
-   /* it is inclusive */
-   end_offset -= 1;
+
+   /* end_offset must also be aligned and is inclusive */
+   end_offset -= (end_offset % ib->state.index_size);
+   end_offset--;
 
    ilo_cp_begin(cp, cmd_len);
    ilo_cp_write(cp, cmd | (cmd_len - 2) |
@@ -3086,6 +3083,7 @@ gen6_emit_PIPE_CONTROL(const struct ilo_dev_info *dev,
 static void
 gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
                       const struct pipe_draw_info *info,
+                      const struct ilo_ib_state *ib,
                       bool rectlist,
                       struct ilo_cp *cp)
 {
@@ -3096,6 +3094,8 @@ gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
    const int vb_access = (info->indexed) ?
       GEN4_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM :
       GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL;
+   const uint32_t vb_start = info->start +
+      ((info->indexed) ? ib->draw_start_offset : 0);
 
    ILO_GPE_VALID_GEN(dev, 6, 6);
 
@@ -3104,7 +3104,7 @@ gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
                     prim << GEN4_3DPRIM_TOPOLOGY_TYPE_SHIFT |
                     vb_access);
    ilo_cp_write(cp, info->count);
-   ilo_cp_write(cp, info->start);
+   ilo_cp_write(cp, vb_start);
    ilo_cp_write(cp, info->instance_count);
    ilo_cp_write(cp, info->start_instance);
    ilo_cp_write(cp, info->index_bias);
index 489371c27cef7a6b157cabdde9c927b001c25d38..7e24f97b8ca12b5d6a36a2586057e87cb572f4b2 100644 (file)
@@ -209,7 +209,7 @@ typedef void
 
 typedef void
 (*ilo_gpe_gen6_3DSTATE_INDEX_BUFFER)(const struct ilo_dev_info *dev,
-                                     const struct pipe_index_buffer *ib,
+                                     const struct ilo_ib_state *ib,
                                      bool enable_cut_index,
                                      struct ilo_cp *cp);
 
@@ -362,6 +362,7 @@ typedef void
 typedef void
 (*ilo_gpe_gen6_3DPRIMITIVE)(const struct ilo_dev_info *dev,
                             const struct pipe_draw_info *info,
+                            const struct ilo_ib_state *ib,
                             bool rectlist,
                             struct ilo_cp *cp);
 
index 21764c9ff3c6937745593441d40f60de363c77ee..2a590be2ddcf01fa25ab008bf7aa944ebdbf5832 100644 (file)
@@ -1182,6 +1182,7 @@ gen7_emit_3DSTATE_SO_BUFFER(const struct ilo_dev_info *dev,
 static void
 gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
                       const struct pipe_draw_info *info,
+                      const struct ilo_ib_state *ib,
                       bool rectlist,
                       struct ilo_cp *cp)
 {
@@ -1192,6 +1193,8 @@ gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
    const int vb_access = (info->indexed) ?
       GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM :
       GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL;
+   const uint32_t vb_start = info->start +
+      ((info->indexed) ? ib->draw_start_offset : 0);
 
    ILO_GPE_VALID_GEN(dev, 7, 7);
 
@@ -1199,7 +1202,7 @@ gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev,
    ilo_cp_write(cp, cmd | (cmd_len - 2));
    ilo_cp_write(cp, vb_access | prim);
    ilo_cp_write(cp, info->count);
-   ilo_cp_write(cp, info->start);
+   ilo_cp_write(cp, vb_start);
    ilo_cp_write(cp, info->instance_count);
    ilo_cp_write(cp, info->start_instance);
    ilo_cp_write(cp, info->index_bias);
index aaceb7a6494162fc3d425229c877b5f2e7d327c6..3f7c8cfab551287a967f1d967746ae167b5e4d82 100644 (file)
@@ -391,7 +391,6 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_COMPUTE:
       return false; /* TODO */
    case PIPE_CAP_USER_INDEX_BUFFERS:
-      return false;
    case PIPE_CAP_USER_CONSTANT_BUFFERS:
       return true;
    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
index 0e4e937879ffd3ab67f5d479b2bb04f2f45f5133..ede72623f1774d0cc05c0514fd100d9f7d3d58bc 100644 (file)
@@ -126,6 +126,44 @@ finalize_constant_buffers(struct ilo_context *ilo)
    }
 }
 
+static void
+finalize_index_buffer(struct ilo_context *ilo)
+{
+   struct pipe_resource *res;
+   unsigned offset, size;
+   bool uploaded = false;
+
+   if (!ilo->draw->indexed)
+      return;
+
+   res = ilo->ib.resource;
+   offset = ilo->ib.state.index_size * ilo->draw->start;
+   size = ilo->ib.state.index_size * ilo->draw->count;
+
+   if (ilo->ib.state.user_buffer) {
+      u_upload_data(ilo->uploader, 0, size,
+            ilo->ib.state.user_buffer + offset, &offset, &res);
+      uploaded = true;
+   }
+   else if (unlikely(ilo->ib.state.offset % ilo->ib.state.index_size)) {
+      u_upload_buffer(ilo->uploader, 0, ilo->ib.state.offset + offset, size,
+            ilo->ib.state.buffer, &offset, &res);
+      uploaded = true;
+   }
+
+   if (uploaded) {
+      ilo->ib.resource = res;
+
+      assert(offset % ilo->ib.state.index_size == 0);
+      ilo->ib.draw_start_offset = offset / ilo->ib.state.index_size;
+
+      /* could be negative */
+      ilo->ib.draw_start_offset -= ilo->draw->start;
+
+      ilo->dirty |= ILO_DIRTY_INDEX_BUFFER;
+   }
+}
+
 /**
  * Finalize states.  Some states depend on other states and are
  * incomplete/invalid until finalized.
@@ -138,6 +176,7 @@ ilo_finalize_3d_states(struct ilo_context *ilo,
 
    finalize_shader_states(ilo);
    finalize_constant_buffers(ilo);
+   finalize_index_buffer(ilo);
 
    u_upload_unmap(ilo->uploader);
 }
@@ -818,19 +857,28 @@ ilo_set_index_buffer(struct pipe_context *pipe,
    struct ilo_context *ilo = ilo_context(pipe);
 
    if (state) {
-      /* no PIPE_CAP_USER_INDEX_BUFFERS */
-      assert(!state->user_buffer);
-
-      ilo->ib.state.index_size = state->index_size;
-      ilo->ib.state.offset = state->offset;
       pipe_resource_reference(&ilo->ib.state.buffer, state->buffer);
+      ilo->ib.state.offset = state->offset;
+      ilo->ib.state.index_size = state->index_size;
+
+      /* state->offset does not apply for user buffer */
       ilo->ib.state.user_buffer = state->user_buffer;
+
+      /*
+       * when there is no state->buffer or state->offset is misaligned,
+       * ilo_finalize_3d_states() will set these to the valid values
+       */
+      pipe_resource_reference(&ilo->ib.resource, state->buffer);
+      ilo->ib.draw_start_offset = state->offset / state->index_size;
    }
    else {
-      ilo->ib.state.index_size = 0;
-      ilo->ib.state.offset = 0;
       pipe_resource_reference(&ilo->ib.state.buffer, NULL);
+      ilo->ib.state.offset = 0;
+      ilo->ib.state.index_size = 0;
       ilo->ib.state.user_buffer = NULL;
+
+      pipe_resource_reference(&ilo->ib.resource, NULL);
+      ilo->ib.draw_start_offset = 0;
    }
 
    ilo->dirty |= ILO_DIRTY_INDEX_BUFFER;