Module: Mesa
Branch: master
Commit: 95c21f12f321bb33ae8e1f1b255680ac8eeffade
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=95c21f12f321bb33ae8e1f1b255680ac8eeffade

Author: Chia-I Wu <[email protected]>
Date:   Wed Jun 26 13:44:27 2013 +0800

ilo: support PIPE_CAP_USER_INDEX_BUFFERS

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               |   21 +++++---
 src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c |    4 +-
 src/gallium/drivers/ilo/ilo_context.c          |    2 +-
 src/gallium/drivers/ilo/ilo_gpe.h              |    3 +
 src/gallium/drivers/ilo/ilo_gpe_gen6.c         |   32 ++++++------
 src/gallium/drivers/ilo/ilo_gpe_gen6.h         |    3 +-
 src/gallium/drivers/ilo/ilo_gpe_gen7.c         |    5 ++-
 src/gallium/drivers/ilo/ilo_screen.c           |    1 -
 src/gallium/drivers/ilo/ilo_state.c            |   62 +++++++++++++++++++++---
 9 files changed, 97 insertions(+), 36 deletions(-)

diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c
index 69808d9..ef3aece 100644
--- a/src/gallium/drivers/ilo/ilo_3d.c
+++ b/src/gallium/drivers/ilo/ilo_3d.c
@@ -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;
 
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c 
b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
index 00da47f..190f6a9 100644
--- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
@@ -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;
 }
 
diff --git a/src/gallium/drivers/ilo/ilo_context.c 
b/src/gallium/drivers/ilo/ilo_context.c
index e355a9c..7fd5ab6 100644
--- a/src/gallium/drivers/ilo/ilo_context.c
+++ b/src/gallium/drivers/ilo/ilo_context.c
@@ -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;
diff --git a/src/gallium/drivers/ilo/ilo_gpe.h 
b/src/gallium/drivers/ilo/ilo_gpe.h
index 7825e58..aa979f3 100644
--- a/src/gallium/drivers/ilo/ilo_gpe.h
+++ b/src/gallium/drivers/ilo/ilo_gpe.h
@@ -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 {
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c 
b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
index 75721f1..9c88b0a 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
@@ -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);
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.h 
b/src/gallium/drivers/ilo/ilo_gpe_gen6.h
index 489371c..7e24f97 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen6.h
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.h
@@ -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);
 
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen7.c 
b/src/gallium/drivers/ilo/ilo_gpe_gen7.c
index 21764c9..2a590be 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen7.c
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen7.c
@@ -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);
diff --git a/src/gallium/drivers/ilo/ilo_screen.c 
b/src/gallium/drivers/ilo/ilo_screen.c
index aaceb7a..3f7c8cf 100644
--- a/src/gallium/drivers/ilo/ilo_screen.c
+++ b/src/gallium/drivers/ilo/ilo_screen.c
@@ -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:
diff --git a/src/gallium/drivers/ilo/ilo_state.c 
b/src/gallium/drivers/ilo/ilo_state.c
index 0e4e937..ede7262 100644
--- a/src/gallium/drivers/ilo/ilo_state.c
+++ b/src/gallium/drivers/ilo/ilo_state.c
@@ -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;

_______________________________________________
mesa-commit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to