[Mesa-dev] [PATCH] nv50: add edgeflag support when using inline vertex data submit

Samuel Pitoiset samuel.pitoiset at gmail.com
Mon Nov 23 12:36:00 PST 2015


Fixes the following piglit tests:
 - gl-1.0-edgeflag
 - gl-1.0-edgeflag-quads
 - gl-2.0-edgeflag
 - gl-2.0-edgeflag-immediate
 - point-vertex-id divisor
 - point-vertex-id gl_InstanceID
 - point-vertex-id gl_InstanceID divisor

I still need to figure out why point-vertex-id fails with gl_vertexID.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 src/gallium/drivers/nouveau/nv50/nv50_program.c |   5 +-
 src/gallium/drivers/nouveau/nv50/nv50_push.c    | 246 ++++++++++++++++++++----
 src/gallium/drivers/nouveau/nv50/nv50_surface.c |   2 +-
 src/gallium/drivers/nouveau/nv50/nv50_vbo.c     |   3 +-
 4 files changed, 210 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
index a4b8ddf..b904581 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
@@ -97,9 +97,6 @@ nv50_vertprog_assign_slots(struct nv50_ir_prog_info *info)
       case TGSI_SEMANTIC_CLIPDIST:
          prog->vp.clpd[info->out[i].si] = n;
          break;
-      case TGSI_SEMANTIC_EDGEFLAG:
-         prog->vp.edgeflag = i;
-         break;
       case TGSI_SEMANTIC_BCOLOR:
          prog->vp.bfc[info->out[i].si] = i;
          break;
@@ -349,7 +346,6 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset,
 
    prog->vp.bfc[0] = 0xff;
    prog->vp.bfc[1] = 0xff;
-   prog->vp.edgeflag = 0xff;
    prog->vp.clpd[0] = map_undef;
    prog->vp.clpd[1] = map_undef;
    prog->vp.psiz = map_undef;
@@ -383,6 +379,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset,
    prog->tls_space = info->bin.tlsSpace;
 
    prog->vp.need_vertex_id = info->io.vertexId < PIPE_MAX_SHADER_INPUTS;
+   prog->vp.edgeflag = info->io.edgeFlagIn;
 
    if (prog->type == PIPE_SHADER_FRAGMENT) {
       if (info->prop.fp.writesDepth) {
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_push.c b/src/gallium/drivers/nouveau/nv50/nv50_push.c
index cbef95d..dae1e34 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_push.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_push.c
@@ -15,9 +15,6 @@ struct push_context {
 
    const void *idxbuf;
 
-   float edgeflag;
-   int edgeflag_attr;
-
    uint32_t vertex_words;
    uint32_t packet_vertex_limit;
 
@@ -31,8 +28,40 @@ struct push_context {
    uint32_t prim;
    uint32_t restart_index;
    uint32_t instance_id;
+
+   struct {
+      bool enabled;
+      bool value;
+      uint8_t width;
+      unsigned stride;
+      const uint8_t *data;
+   } edgeflag;
 };
 
+static inline void
+nv50_push_map_edgeflag(struct push_context *ctx, struct nv50_context *nv50,
+                       int32_t index_bias)
+{
+
+   unsigned attr = nv50->vertprog->vp.edgeflag;
+   struct pipe_vertex_element *ve = &nv50->vertex->element[attr].pipe;
+   struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index];
+   struct nv04_resource *buf = nv04_resource(vb->buffer);
+
+   ctx->edgeflag.stride = vb->stride;
+   ctx->edgeflag.width = util_format_get_blocksize(ve->src_format);
+   if (buf) {
+      unsigned offset = vb->buffer_offset + ve->src_offset;
+      ctx->edgeflag.data =
+         nouveau_resource_map_offset(&nv50->base, buf, offset, NOUVEAU_BO_RD);
+   } else {
+      ctx->edgeflag.data = (const uint8_t *)vb->user_buffer + ve->src_offset;
+   }
+
+   if (index_bias)
+      ctx->edgeflag.data += (intptr_t)index_bias * vb->stride;
+}
+
 static inline unsigned
 prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
 {
@@ -63,6 +92,75 @@ prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
    return i;
 }
 
+static inline bool
+ef_value_8(const struct push_context *ctx, uint32_t index)
+{
+   uint8_t *pf = (uint8_t *)&ctx->edgeflag.data[index * ctx->edgeflag.stride];
+   return !!*pf;
+}
+
+static inline bool
+ef_value_32(const struct push_context *ctx, uint32_t index)
+{
+   uint32_t *pf = (uint32_t *)&ctx->edgeflag.data[index * ctx->edgeflag.stride];
+   return !!*pf;
+}
+
+static inline bool
+ef_toggle(struct push_context *ctx)
+{
+   ctx->edgeflag.value = !ctx->edgeflag.value;
+   return ctx->edgeflag.value;
+}
+
+static inline unsigned
+ef_toggle_search_i08(struct push_context *ctx, const uint8_t *elts, unsigned n)
+{
+   unsigned i;
+   bool ef = ctx->edgeflag.value;
+   if (ctx->edgeflag.width == 1)
+      for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);
+   else
+      for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);
+   return i;
+}
+
+static inline unsigned
+ef_toggle_search_i16(struct push_context *ctx, const uint16_t *elts, unsigned n)
+{
+   unsigned i;
+   bool ef = ctx->edgeflag.value;
+   if (ctx->edgeflag.width == 1)
+      for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);
+   else
+      for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);
+   return i;
+}
+
+static inline unsigned
+ef_toggle_search_i32(struct push_context *ctx, const uint32_t *elts, unsigned n)
+{
+   unsigned i;
+   bool ef = ctx->edgeflag.value;
+   if (ctx->edgeflag.width == 1)
+      for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);
+   else
+      for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);
+   return i;
+}
+
+static inline unsigned
+ef_toggle_search_seq(struct push_context *ctx, unsigned start, unsigned n)
+{
+   unsigned i;
+   bool ef = ctx->edgeflag.value;
+   if (ctx->edgeflag.width == 1)
+      for (i = 0; i < n && ef_value_8(ctx, start++) == ef; ++i);
+   else
+      for (i = 0; i < n && ef_value_32(ctx, start++) == ef; ++i);
+   return i;
+}
+
 static void
 emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
 {
@@ -70,29 +168,43 @@ emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
 
    while (count) {
       unsigned push = MIN2(count, ctx->packet_vertex_limit);
+      bool need_restart_idx = false;
       unsigned size, nr;
 
       nr = push;
       if (ctx->primitive_restart)
          nr = prim_restart_search_i08(elts, push, ctx->restart_index);
+      need_restart_idx = nr != push;
 
-      size = ctx->vertex_words * nr;
+      while (nr) {
+         unsigned ne = nr;
 
-      if (unlikely(ctx->need_vertex_id)) {
-         BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
-         PUSH_DATA (ctx->push, *elts + ctx->index_bias);
-      }
+         if (unlikely(ctx->edgeflag.enabled))
+             ne = ef_toggle_search_i08(ctx, elts, nr);
+         size = ctx->vertex_words * ne;
 
-      BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
+         if (unlikely(ctx->need_vertex_id)) {
+            BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
+            PUSH_DATA (ctx->push, *elts + ctx->index_bias);
+         }
 
-      ctx->translate->run_elts8(ctx->translate, elts, nr, 0, ctx->instance_id,
-                                ctx->push->cur);
+         BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
 
-      ctx->push->cur += size;
-      count -= nr;
-      elts += nr;
+         ctx->translate->run_elts8(ctx->translate, elts, ne, 0, ctx->instance_id,
+                                   ctx->push->cur);
+         ctx->push->cur += size;
+
+         if (unlikely(ne != nr)) {
+             BEGIN_NV04(ctx->push, NV50_3D(EDGEFLAG), 1);
+             PUSH_DATA (ctx->push, ef_toggle(ctx));
+         }
+
+         count -= ne;
+         elts += ne;
+         nr -= ne;
+      }
 
-      if (nr != push) {
+      if (need_restart_idx) {
          count--;
          elts++;
          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
@@ -108,29 +220,44 @@ emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
 
    while (count) {
       unsigned push = MIN2(count, ctx->packet_vertex_limit);
+      bool need_restart_idx = false;
       unsigned size, nr;
 
       nr = push;
       if (ctx->primitive_restart)
          nr = prim_restart_search_i16(elts, push, ctx->restart_index);
+      need_restart_idx = nr != push;
 
-      size = ctx->vertex_words * nr;
+      while (nr) {
+         unsigned ne= nr;
 
-      if (unlikely(ctx->need_vertex_id)) {
-         BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
-         PUSH_DATA (ctx->push, *elts + ctx->index_bias);
-      }
+         if (unlikely(ctx->edgeflag.enabled))
+             ne = ef_toggle_search_i16(ctx, elts, nr);
+         size = ctx->vertex_words * ne;
 
-      BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
 
-      ctx->translate->run_elts16(ctx->translate, elts, nr, 0, ctx->instance_id,
-                                 ctx->push->cur);
+         if (unlikely(ctx->need_vertex_id)) {
+            BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
+            PUSH_DATA (ctx->push, *elts + ctx->index_bias);
+         }
+
+         BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
 
-      ctx->push->cur += size;
-      count -= nr;
-      elts += nr;
+         ctx->translate->run_elts16(ctx->translate, elts, ne, 0, ctx->instance_id,
+                                    ctx->push->cur);
+         ctx->push->cur += size;
 
-      if (nr != push) {
+         if (unlikely(ne != nr)) {
+             BEGIN_NV04(ctx->push, NV50_3D(EDGEFLAG), 1);
+             PUSH_DATA (ctx->push, ef_toggle(ctx));
+         }
+
+         count -= ne;
+         elts += ne;
+         nr -= ne;
+      }
+
+      if (need_restart_idx) {
          count--;
          elts++;
          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
@@ -146,29 +273,43 @@ emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
 
    while (count) {
       unsigned push = MIN2(count, ctx->packet_vertex_limit);
+      bool need_restart_idx = false;
       unsigned size, nr;
 
       nr = push;
       if (ctx->primitive_restart)
          nr = prim_restart_search_i32(elts, push, ctx->restart_index);
+      need_restart_idx = nr != push;
 
-      size = ctx->vertex_words * nr;
+      while (nr) {
+         unsigned ne = nr;
 
-      if (unlikely(ctx->need_vertex_id)) {
-         BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
-         PUSH_DATA (ctx->push, *elts + ctx->index_bias);
-      }
+         if (unlikely(ctx->edgeflag.enabled))
+             ne = ef_toggle_search_i32(ctx, elts, nr);
+         size = ctx->vertex_words * ne;
 
-      BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
+         if (unlikely(ctx->need_vertex_id)) {
+            BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);
+            PUSH_DATA (ctx->push, *elts + ctx->index_bias);
+         }
 
-      ctx->translate->run_elts(ctx->translate, elts, nr, 0, ctx->instance_id,
-                               ctx->push->cur);
+         BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
 
-      ctx->push->cur += size;
-      count -= nr;
-      elts += nr;
+         ctx->translate->run_elts(ctx->translate, elts, ne, 0, ctx->instance_id,
+                                  ctx->push->cur);
+         ctx->push->cur += size;
+
+         if (unlikely(ne != nr)) {
+             BEGIN_NV04(ctx->push, NV50_3D(EDGEFLAG), 1);
+             PUSH_DATA (ctx->push, ef_toggle(ctx));
+         }
+
+         count -= ne;
+         elts += ne;
+         nr -= ne;
+      }
 
-      if (nr != push) {
+      if (need_restart_idx) {
          count--;
          elts++;
          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
@@ -184,7 +325,7 @@ emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
 
    while (count) {
       unsigned push = MIN2(count, ctx->packet_vertex_limit);
-      unsigned size = ctx->vertex_words * push;
+      unsigned size;
 
       if (unlikely(ctx->need_vertex_id)) {
          /* For non-indexed draws, gl_VertexID goes up after each vertex. */
@@ -192,11 +333,22 @@ emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
          PUSH_DATA (ctx->push, elts++);
       }
 
+      if (unlikely(ctx->edgeflag.enabled))
+         push = ef_toggle_search_seq(ctx, start, push);
+      size = ctx->vertex_words * push;
+
       BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
 
       ctx->translate->run(ctx->translate, start, push, 0, ctx->instance_id,
                           ctx->push->cur);
       ctx->push->cur += size;
+
+      if (unlikely(push != count)) {
+         PUSH_SPACE(ctx->push, 2);
+         BEGIN_NV04(ctx->push, NV50_3D(EDGEFLAG), 1);
+         PUSH_DATA (ctx->push, ef_toggle(ctx));
+      }
+
       count -= push;
       start += push;
    }
@@ -253,6 +405,12 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
       ctx.need_vertex_id ? 1 : nv50->vertex->packet_vertex_limit;
    ctx.vertex_words = nv50->vertex->vertex_size;
 
+   ctx.edgeflag.value = true;
+   ctx.edgeflag.enabled = nv50->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS;
+   ctx.edgeflag.data = NULL;
+   ctx.edgeflag.stride = 0;
+   ctx.edgeflag.width = 0;
+
    assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
    for (i = 0; i < nv50->num_vtxbufs; ++i) {
       const struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i];
@@ -270,6 +428,9 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
       ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
    }
 
+   if (unlikely(ctx.edgeflag.enabled))
+      nv50_push_map_edgeflag(&ctx, nv50, info->index_bias);
+
    if (info->indexed) {
       if (nv50->idxbuf.buffer) {
          ctx.idxbuf = nouveau_resource_map_offset(&nv50->base,
@@ -347,4 +508,9 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
       BEGIN_NV04(ctx.push, NV84_3D(VERTEX_ID_BASE), 1);
       PUSH_DATA (ctx.push, nv50->state.index_bias);
    }
+
+   if (unlikely(!ctx.edgeflag.value)) {
+      BEGIN_NV04(ctx.push, NV50_3D(EDGEFLAG), 1);
+      PUSH_DATA (ctx.push, 0);
+   }
 }
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
index 8ba19d2..a854669 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
@@ -779,7 +779,7 @@ nv50_blitter_make_vp(struct nv50_blitter *blit)
    blit->vp.out[1].si = 0;
    blit->vp.vp.attrs[0] = 0x73;
    blit->vp.vp.psiz = 0x40;
-   blit->vp.vp.edgeflag = 0x40;
+   blit->vp.vp.edgeflag = PIPE_MAX_ATTRIBS;
 }
 
 void *
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
index 85878d5..ad131d5 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
@@ -302,7 +302,8 @@ nv50_vertex_arrays_validate(struct nv50_context *nv50)
    unsigned i;
    const unsigned n = MAX2(vertex->num_elements, nv50->state.num_vtxelts);
 
-   if (unlikely(vertex->need_conversion))
+   if (unlikely(vertex->need_conversion) ||
+       unlikely(nv50->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS))
       nv50->vbo_fifo = ~0;
    else
    if (nv50->vbo_user & ~nv50->vbo_constant)
-- 
2.6.2



More information about the mesa-dev mailing list