Browse Source

nvc0: support primitive restart

tags/android-x86-2.2-r2
Christoph Bumiller 15 years ago
parent
commit
5655f8d42d

+ 1
- 0
src/gallium/drivers/nvc0/nvc0_context.h View File

@@ -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];

+ 88
- 11
src/gallium/drivers/nvc0/nvc0_push.c View File

@@ -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)

+ 1
- 1
src/gallium/drivers/nvc0/nvc0_screen.c View File

@@ -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;

+ 33
- 16
src/gallium/drivers/nvc0/nvc0_vbo.c View File

@@ -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");
}
}

Loading…
Cancel
Save