[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