diff options
| author | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-09 12:08:25 +0100 | 
|---|---|---|
| committer | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-09 12:08:25 +0100 | 
| commit | 5655f8d42d919270791588162399ac7a2c718733 (patch) | |
| tree | b21c4ba42fc71f0654147b977e5b710f2db91557 /src | |
| parent | 548967f9faef8b4f3713e20c29b85cea3149e91d (diff) | |
nvc0: support primitive restart
Diffstat (limited to 'src')
| -rw-r--r-- | src/gallium/drivers/nvc0/nvc0_context.h | 1 | ||||
| -rw-r--r-- | src/gallium/drivers/nvc0/nvc0_push.c | 99 | ||||
| -rw-r--r-- | src/gallium/drivers/nvc0/nvc0_screen.c | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nvc0/nvc0_vbo.c | 49 | 
4 files changed, 123 insertions, 28 deletions
| diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index 0d884459f3..1b2f96429b 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -73,6 +73,7 @@ struct nvc0_context {     struct {        uint32_t instance_bits;        uint32_t instance_base; +      boolean prim_restart;        uint8_t num_vtxbufs;        uint8_t num_vtxelts;        uint8_t num_textures[5]; diff --git a/src/gallium/drivers/nvc0/nvc0_push.c b/src/gallium/drivers/nvc0/nvc0_push.c index d201f310cc..8b8fe610e2 100644 --- a/src/gallium/drivers/nvc0/nvc0_push.c +++ b/src/gallium/drivers/nvc0/nvc0_push.c @@ -14,17 +14,50 @@ struct push_context {     struct nouveau_channel *chan;     void *idxbuf; -   int32_t idxbias;     float edgeflag; -   int edgeflat_attr; +   int edgeflag_attr; -   uint32_t vertex_size; +   uint32_t vertex_words;     uint32_t packet_vertex_limit;     struct translate *translate; + +   boolean primitive_restart; +   uint32_t prim; +   uint32_t restart_index;  }; +static INLINE unsigned +prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index) +{ +   unsigned i; +   for (i = 0; i < push; ++i) +      if (elts[i] == index) +         break; +   return i; +} + +static INLINE unsigned +prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index) +{ +   unsigned i; +   for (i = 0; i < push; ++i) +      if (elts[i] == index) +         break; +   return i; +} + +static INLINE unsigned +prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index) +{ +   unsigned i; +   for (i = 0; i < push; ++i) +      if (elts[i] == index) +         break; +   return i; +} +  static void  emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)  { @@ -32,14 +65,27 @@ emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)     while (count) {        unsigned push = MIN2(count, ctx->packet_vertex_limit); -      unsigned size = ctx->vertex_size * push; +      unsigned size, nr; + +      nr = push; +      if (ctx->primitive_restart) +         nr = prim_restart_search_i08(elts, push, ctx->restart_index); + +      size = ctx->vertex_words * nr;        BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);        ctx->translate->run_elts8(ctx->translate, elts, push, 0, ctx->chan->cur); +        ctx->chan->cur += size;        count -= push;        elts += push; + +      if (nr != push) { +         BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); +         OUT_RING  (ctx->chan, 0); +         OUT_RING  (ctx->chan, ctx->prim); +      }     }  } @@ -50,14 +96,27 @@ emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)     while (count) {        unsigned push = MIN2(count, ctx->packet_vertex_limit); -      unsigned size = ctx->vertex_size * push; +      unsigned size, nr; + +      nr = push; +      if (ctx->primitive_restart) +         nr = prim_restart_search_i16(elts, push, ctx->restart_index); + +      size = ctx->vertex_words * nr;        BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);        ctx->translate->run_elts16(ctx->translate, elts, push, 0, ctx->chan->cur); +        ctx->chan->cur += size;        count -= push;        elts += push; + +      if (nr != push) { +         BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); +         OUT_RING  (ctx->chan, 0); +         OUT_RING  (ctx->chan, ctx->prim); +      }     }  } @@ -68,14 +127,27 @@ emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)     while (count) {        unsigned push = MIN2(count, ctx->packet_vertex_limit); -      unsigned size = ctx->vertex_size * push; +      unsigned size, nr; + +      nr = push; +      if (ctx->primitive_restart) +         nr = prim_restart_search_i32(elts, push, ctx->restart_index); + +      size = ctx->vertex_words * nr;        BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);        ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur); +        ctx->chan->cur += size;        count -= push;        elts += push; + +      if (nr != push) { +         BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); +         OUT_RING  (ctx->chan, 0); +         OUT_RING  (ctx->chan, ctx->prim); +      }     }  } @@ -84,7 +156,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_size * push; +      unsigned size = ctx->vertex_words * push;        BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size); @@ -131,13 +203,12 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)     struct push_context ctx;     struct pipe_transfer *transfer = NULL;     unsigned i, index_size; -   unsigned prim = nvc0_prim_gl(info->mode);     unsigned inst = info->instance_count;     ctx.chan = nvc0->screen->base.channel;     ctx.translate = nvc0->vertex->translate;     ctx.packet_vertex_limit = nvc0->vertex->vtx_per_packet_max; -   ctx.vertex_size = nvc0->vertex->vtx_size; +   ctx.vertex_words = nvc0->vertex->vtx_size;     for (i = 0; i < nvc0->num_vtxbufs; ++i) {        uint8_t *data; @@ -159,14 +230,20 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)        if (!ctx.idxbuf)           return;        index_size = nvc0->idxbuf.index_size; +      ctx.primitive_restart = info->primitive_restart; +      ctx.restart_index = info->restart_index;     } else {        ctx.idxbuf = NULL;        index_size = 0; +      ctx.primitive_restart = FALSE; +      ctx.restart_index = 0;     } +   ctx.prim = nvc0_prim_gl(info->mode); +     while (inst--) {        BEGIN_RING(ctx.chan, RING_3D(VERTEX_BEGIN_GL), 1); -      OUT_RING  (ctx.chan, prim); +      OUT_RING  (ctx.chan, ctx.prim);        switch (index_size) {        case 0:           emit_vertices_seq(&ctx, info->start, info->count); @@ -186,7 +263,7 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)        }        INLIN_RING(ctx.chan, RING_3D(VERTEX_END_GL), 0); -      prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; +      ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;     }     if (info->indexed) diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 9768de96f5..616a990337 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -110,7 +110,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)     case PIPE_CAP_SHADER_STENCIL_EXPORT:        return 0;     case PIPE_CAP_PRIMITIVE_RESTART: -      return 0; +      return 1;     default:        NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);        return 0; diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c index 1fc842238f..9fa1ad42ad 100644 --- a/src/gallium/drivers/nvc0/nvc0_vbo.c +++ b/src/gallium/drivers/nvc0/nvc0_vbo.c @@ -287,7 +287,7 @@ nvc0_tfb_setup(struct nvc0_context *nvc0)  static void  nvc0_draw_arrays(struct nvc0_context *nvc0,                   unsigned mode, unsigned start, unsigned count, -                 unsigned start_instance, unsigned instance_count) +                 unsigned instance_count)  {     struct nouveau_channel *chan = nvc0->screen->base.channel;     unsigned prim; @@ -297,12 +297,6 @@ nvc0_draw_arrays(struct nvc0_context *nvc0,     prim = nvc0_prim_gl(mode); -   if (nvc0->state.instance_base != start_instance) { -      nvc0->state.instance_base = start_instance; -      BEGIN_RING(chan, RING_3D(VB_INSTANCE_BASE), 1); -      OUT_RING  (chan, start_instance); -   } -     while (instance_count--) {        BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);        OUT_RING  (chan, prim); @@ -386,7 +380,7 @@ nvc0_draw_elements_inline_u32(struct nouveau_channel *chan, uint32_t *map,  static void  nvc0_draw_elements(struct nvc0_context *nvc0,                     unsigned mode, unsigned start, unsigned count, -                   unsigned start_instance, unsigned instance_count, +                   unsigned instance_count,                     unsigned index_size, int index_bias)  {     struct nouveau_channel *chan = nvc0->screen->base.channel; @@ -423,6 +417,8 @@ nvc0_draw_elements(struct nvc0_context *nvc0,        }        BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);        OUT_RING  (chan, 0); + +      prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;     }     chan->flush_notify = NULL; @@ -432,31 +428,52 @@ void  nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)  {     struct nvc0_context *nvc0 = nvc0_context(pipe); +   struct nouveau_channel *chan = nvc0->screen->base.channel;     nvc0_state_validate(nvc0); +   if (nvc0->state.instance_base != info->start_instance) { +      nvc0->state.instance_base = info->start_instance; +      BEGIN_RING(chan, RING_3D(VB_INSTANCE_BASE), 1); +      OUT_RING  (chan, info->start_instance); +   } +     if (nvc0->vbo_fifo) {        nvc0_push_vbo(nvc0, info);        return;     }     if (nvc0->vbo_dirty) { -      BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x142c), 1); -      OUT_RING  (nvc0->screen->base.channel, 0); +      BEGIN_RING(chan, RING_3D_(0x142c), 1); +      OUT_RING  (chan, 0);        nvc0->vbo_dirty = FALSE;     }     if (!info->indexed) {        nvc0_draw_arrays(nvc0,                         info->mode, info->start, info->count, -                       info->start_instance, info->instance_count); -   } else -   if (nvc0->idxbuf.buffer) { +                       info->instance_count); +   } else { +      assert(nvc0->idxbuf.buffer); + +      if (info->primitive_restart != nvc0->state.prim_restart) { +         if (info->primitive_restart) { +            BEGIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 2); +            OUT_RING  (chan, 1); +            OUT_RING  (chan, info->restart_index); +         } else { +            INLIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 0); +         } +         nvc0->state.prim_restart = info->primitive_restart; +      } else +      if (info->primitive_restart) { +         BEGIN_RING(chan, RING_3D(PRIM_RESTART_INDEX), 1); +         OUT_RING  (chan, info->restart_index); +      } +        nvc0_draw_elements(nvc0,                           info->mode, info->start, info->count, -                         info->start_instance, info->instance_count, +                         info->instance_count,                           nvc0->idxbuf.index_size, info->index_bias); -   } else { -      NOUVEAU_ERR("draw_indexed: no index buffer\n");     }  } | 
