summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0/nvc0_vbo.c
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2012-03-16 17:37:32 +0100
committerChristoph Bumiller <[email protected]>2012-04-14 06:14:21 +0200
commitedbfeed56f1ebd8517840ef48f8c87e24bb98157 (patch)
tree091d7e779b814713c0201813e9a3fed3153a9c6f /src/gallium/drivers/nvc0/nvc0_vbo.c
parent784f49e69624cba07616fd5a22ccb80ad3b5111b (diff)
nvc0: improve vertex state validation
Now updating vertex attribute format only when necessary.
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_vbo.c')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_vbo.c189
1 files changed, 103 insertions, 86 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c
index 9c13adff807..7cb1e0a43b7 100644
--- a/src/gallium/drivers/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nvc0/nvc0_vbo.c
@@ -126,26 +126,44 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
((c) << NVC0_3D_VTX_ATTR_DEFINE_COMP__SHIFT))
static void
-nvc0_emit_vtxattr(struct nvc0_context *nvc0, struct pipe_vertex_buffer *vb,
- struct pipe_vertex_element *ve, unsigned attr)
+nvc0_update_constant_vertex_attribs(struct nvc0_context *nvc0)
{
- const void *data;
- struct nouveau_pushbuf *push = nvc0->base.pushbuf;
- struct nv04_resource *res = nv04_resource(vb->buffer);
- float v[4];
- int i;
- const unsigned nc = util_format_get_nr_components(ve->src_format);
+ uint32_t mask = nvc0->state.constant_elts;
- data = nouveau_resource_map_offset(&nvc0->base, res, vb->buffer_offset +
- ve->src_offset, NOUVEAU_BO_RD);
+ while (unlikely(mask)) {
+ const int i = ffs(mask) - 1;
+ uint32_t mode;
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct pipe_vertex_element *ve = &nvc0->vertex->element[i].pipe;
+ struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index];
+ const struct util_format_description *desc;
+ void *dst;
+ const void *src = nouveau_resource_map_offset(&nvc0->base,
+ nv04_resource(vb->buffer),
+ vb->buffer_offset + ve->src_offset, NOUVEAU_BO_RD);
- util_format_read_4f(ve->src_format, v, 0, data, 0, 0, 0, 1, 1);
+ mask &= ~(1 << i);
- PUSH_SPACE(push, 6);
- BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), nc + 1);
- PUSH_DATA (push, VTX_ATTR(attr, nc, FLOAT, 32));
- for (i = 0; i < nc; ++i)
- PUSH_DATAf(push, v[i]);
+ desc = util_format_description(ve->src_format);
+
+ PUSH_SPACE(push, 6);
+ BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 5);
+ dst = push->cur + 1;
+ if (desc->channel[0].pure_integer) {
+ if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
+ mode = VTX_ATTR(i, 4, SINT, 32);
+ desc->unpack_rgba_sint(dst, 0, src, 0, 1, 1);
+ } else {
+ mode = VTX_ATTR(i, 4, UINT, 32);
+ desc->unpack_rgba_uint(dst, 0, src, 0, 1, 1);
+ }
+ } else {
+ mode = VTX_ATTR(i, 4, FLOAT, 32);
+ desc->unpack_rgba_float(dst, 0, src, 0, 1, 1);
+ }
+ *push->cur = mode;
+ push->cur += 5;
+ }
}
static INLINE void
@@ -225,13 +243,8 @@ nvc0_update_user_vbufs(struct nvc0_context *nvc0)
struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b];
struct nv04_resource *buf = nv04_resource(vb->buffer);
- if (!(nvc0->vbo_user & (1 << b)))
- continue;
-
- if (!vb->stride) {
- nvc0_emit_vtxattr(nvc0, vb, ve, i);
+ if (!(nvc0->vbo_user & (1 << b)) || !vb->stride)
continue;
- }
nvc0_vbuf_range(nvc0, b, &base, &size);
if (!(written & (1 << b))) {
@@ -268,83 +281,88 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
struct nvc0_vertex_stateobj *vertex = nvc0->vertex;
struct pipe_vertex_buffer *vb;
struct nvc0_vertex_element *ve;
+ uint32_t const_vbos;
unsigned i;
+ boolean update_vertex;
if (unlikely(vertex->need_conversion) ||
unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) {
- nvc0->vbo_fifo = ~0;
nvc0->vbo_user = 0;
+ nvc0->vbo_fifo = ~nvc0->constant_vbos;
} else {
nvc0_prevalidate_vbufs(nvc0);
+ nvc0->vbo_fifo &= ~nvc0->constant_vbos;
}
+ const_vbos = nvc0->vbo_fifo ? 0 : nvc0->constant_vbos;
+
+ update_vertex = (nvc0->dirty & NVC0_NEW_VERTEX) ||
+ (const_vbos != nvc0->state.constant_vbos);
+ if (update_vertex) {
+ uint32_t *restrict data;
+ const unsigned n = MAX2(vertex->num_elements, nvc0->state.num_vtxelts);
+
+ if (unlikely(vertex->instance_elts != nvc0->state.instance_elts)) {
+ nvc0->state.instance_elts = vertex->instance_elts;
+ assert(n); /* if (n == 0), both masks should be 0 */
+ PUSH_SPACE(push, 3);
+ BEGIN_NVC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_PER_INSTANCE), 2);
+ PUSH_DATA (push, n);
+ PUSH_DATA (push, vertex->instance_elts);
+ }
- PUSH_SPACE(push, vertex->num_elements + 1);
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), vertex->num_elements);
- for (i = 0; i < vertex->num_elements; ++i) {
- ve = &vertex->element[i];
- vb = &nvc0->vtxbuf[ve->pipe.vertex_buffer_index];
-
- if (likely(vb->stride) || nvc0->vbo_fifo) {
- PUSH_DATA(push, ve->state);
- } else {
- PUSH_DATA(push, ve->state | NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST);
- nvc0->vbo_fifo &= ~(1 << i);
+ nvc0->state.num_vtxelts = vertex->num_elements;
+ nvc0->state.constant_vbos = const_vbos;
+ nvc0->state.constant_elts = 0;
+
+ PUSH_SPACE(push, n * 2 + 1);
+ BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n);
+ data = push->cur;
+ push->cur += n;
+ for (i = 0; i < vertex->num_elements; ++data, ++i) {
+ ve = &vertex->element[i];
+ *data = ve->state;
+ if (unlikely(const_vbos & (1 << ve->pipe.vertex_buffer_index))) {
+ *data |= NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST;
+ nvc0->state.constant_elts |= 1 << i;
+ IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0);
+ }
+ }
+ for (; i < n; ++data, ++i) {
+ IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0);
+ *data = NVC0_3D_VERTEX_ATTRIB_INACTIVE;
}
}
- PUSH_SPACE(push, vertex->num_elements * 16);
+ PUSH_SPACE(push, vertex->num_elements * 8);
for (i = 0; i < vertex->num_elements; ++i) {
struct nv04_resource *res;
unsigned size, offset;
-
+
+ if (nvc0->state.constant_elts & (1 << i))
+ continue;
ve = &vertex->element[i];
vb = &nvc0->vtxbuf[ve->pipe.vertex_buffer_index];
- if (unlikely(ve->pipe.instance_divisor)) {
- if (!(nvc0->state.instance_elts & (1 << i))) {
- IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 1);
- }
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_DIVISOR(i)), 1);
- PUSH_DATA (push, ve->pipe.instance_divisor);
- } else
- if (unlikely(nvc0->state.instance_elts & (1 << i))) {
- IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 0);
- }
-
res = nv04_resource(vb->buffer);
-
- if (nvc0->vbo_fifo || unlikely(vb->stride == 0)) {
- if (!nvc0->vbo_fifo)
- nvc0_emit_vtxattr(nvc0, vb, &ve->pipe, i);
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1);
- PUSH_DATA (push, 0);
- continue;
- }
-
- size = vb->buffer->width0;
offset = ve->pipe.src_offset + vb->buffer_offset;
+ size = vb->buffer->width0;
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1);
- PUSH_DATA (push, (1 << 12) | vb->stride);
- BEGIN_1IC0(push, NVC0_3D(VERTEX_ARRAY_SELECT), 5);
- PUSH_DATA (push, i);
+ if (unlikely(ve->pipe.instance_divisor)) {
+ BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 4);
+ PUSH_DATA (push, (1 << 12) | vb->stride);
+ PUSH_DATAh(push, res->address + offset);
+ PUSH_DATA (push, res->address + offset);
+ PUSH_DATA (push, ve->pipe.instance_divisor);
+ } else {
+ BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 3);
+ PUSH_DATA (push, (1 << 12) | vb->stride);
+ PUSH_DATAh(push, res->address + offset);
+ PUSH_DATA (push, res->address + offset);
+ }
+ BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2);
PUSH_DATAh(push, res->address + size - 1);
PUSH_DATA (push, res->address + size - 1);
- PUSH_DATAh(push, res->address + offset);
- PUSH_DATA (push, res->address + offset);
}
- for (; i < nvc0->state.num_vtxelts; ++i) {
- PUSH_SPACE(push, 5);
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(i)), 1);
- PUSH_DATA (push, NVC0_3D_VERTEX_ATTRIB_INACTIVE);
- if (unlikely(nvc0->state.instance_elts & (1 << i)))
- IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 0);
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1);
- PUSH_DATA (push, 0);
- }
-
- nvc0->state.num_vtxelts = vertex->num_elements;
- nvc0->state.instance_elts = vertex->instance_elts;
}
void
@@ -393,7 +411,6 @@ nvc0_prim_gl(unsigned prim)
NVC0_PRIM_GL_CASE(PATCHES); */
default:
return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
- break;
}
}
@@ -666,6 +683,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
push->kick_notify = nvc0_default_kick_notify;
return;
}
+ nvc0_update_constant_vertex_attribs(nvc0);
/* space for base instance, flush, and prim restart */
PUSH_SPACE(push, 8);
@@ -678,19 +696,11 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
}
if (nvc0->base.vbo_dirty) {
- BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 1);
- PUSH_DATA (push, 0);
+ IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0);
nvc0->base.vbo_dirty = FALSE;
}
- if (unlikely(info->count_from_stream_output)) {
- nvc0_draw_stream_output(nvc0, info);
- } else
- if (!info->indexed) {
- nvc0_draw_arrays(nvc0,
- info->mode, info->start, info->count,
- info->instance_count);
- } else {
+ if (info->indexed) {
boolean shorten = info->max_index <= 65535;
assert(nvc0->idxbuf.buffer);
@@ -719,6 +729,13 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
nvc0_draw_elements(nvc0, shorten,
info->mode, info->start, info->count,
info->instance_count, info->index_bias);
+ } else
+ if (unlikely(info->count_from_stream_output)) {
+ nvc0_draw_stream_output(nvc0, info);
+ } else {
+ nvc0_draw_arrays(nvc0,
+ info->mode, info->start, info->count,
+ info->instance_count);
}
push->kick_notify = nvc0_default_kick_notify;