summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0/nvc0_vbo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_vbo.c')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_vbo.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c
index a14e9557382..a51a887ed89 100644
--- a/src/gallium/drivers/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nvc0/nvc0_vbo.c
@@ -58,7 +58,8 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
if (!so)
return NULL;
so->num_elements = num_elements;
- so->instance_bits = 0;
+ so->instance_elts = 0;
+ so->instance_bufs = 0;
transkey.nr_elements = 0;
transkey.output_stride = 0;
@@ -85,7 +86,7 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
}
so->element[i].state |= i;
- if (likely(!ve->instance_divisor)) {
+ if (1) {
unsigned j = transkey.nr_elements++;
transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
@@ -97,8 +98,11 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
transkey.element[j].output_format = fmt;
transkey.element[j].output_offset = transkey.output_stride;
transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
- } else {
- so->instance_bits |= 1 << i;
+
+ if (unlikely(ve->instance_divisor)) {
+ so->instance_elts |= 1 << i;
+ so->instance_bufs |= 1 << vbi;
+ }
}
}
@@ -141,6 +145,22 @@ nvc0_emit_vtxattr(struct nvc0_context *nvc0, struct pipe_vertex_buffer *vb,
OUT_RINGf(chan, v[i]);
}
+static INLINE void
+nvc0_vbuf_range(struct nvc0_context *nvc0, int vbi,
+ uint32_t *base, uint32_t *size)
+{
+ if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) {
+ /* TODO: use min and max instance divisor to get a proper range */
+ *base = 0;
+ *size = (nvc0->vtxbuf[vbi].max_index + 1) * nvc0->vtxbuf[vbi].stride;
+ } else {
+ assert(nvc0->vbo_max_index != ~0);
+ *base = nvc0->vbo_min_index * nvc0->vtxbuf[vbi].stride;
+ *size = (nvc0->vbo_max_index -
+ nvc0->vbo_min_index + 1) * nvc0->vtxbuf[vbi].stride;
+ }
+}
+
static void
nvc0_prevalidate_vbufs(struct nvc0_context *nvc0)
{
@@ -165,9 +185,7 @@ nvc0_prevalidate_vbufs(struct nvc0_context *nvc0)
if (buf->status & NVC0_BUFFER_STATUS_USER_MEMORY) {
nvc0->vbo_user |= 1 << i;
assert(vb->stride > vb->buffer_offset);
- size = vb->stride * (nvc0->vbo_max_index -
- nvc0->vbo_min_index + 1);
- base = vb->stride * nvc0->vbo_min_index;
+ nvc0_vbuf_range(nvc0, i, &base, &size);
nvc0_user_buffer_upload(buf, base, size);
} else {
nvc0_buffer_migrate(nvc0, buf, NOUVEAU_BO_GART);
@@ -184,7 +202,6 @@ static void
nvc0_update_user_vbufs(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
- const uint32_t vertex_count = nvc0->vbo_max_index - nvc0->vbo_min_index + 1;
uint32_t base, offset, size;
int i;
uint32_t written = 0;
@@ -202,8 +219,7 @@ nvc0_update_user_vbufs(struct nvc0_context *nvc0)
nvc0_emit_vtxattr(nvc0, vb, ve, i);
continue;
}
- size = vb->stride * vertex_count;
- base = vb->stride * nvc0->vbo_min_index;
+ nvc0_vbuf_range(nvc0, b, &base, &size);
if (!(written & (1 << b))) {
written |= 1 << b;
@@ -253,13 +269,13 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
vb = &nvc0->vtxbuf[ve->pipe.vertex_buffer_index];
if (unlikely(ve->pipe.instance_divisor)) {
- if (!(nvc0->state.instance_bits & (1 << i))) {
+ if (!(nvc0->state.instance_elts & (1 << i))) {
IMMED_RING(chan, RING_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 1);
}
BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_DIVISOR(i)), 1);
OUT_RING (chan, ve->pipe.instance_divisor);
} else
- if (unlikely(nvc0->state.instance_bits & (1 << i))) {
+ if (unlikely(nvc0->state.instance_elts & (1 << i))) {
IMMED_RING(chan, RING_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 0);
}
@@ -293,7 +309,7 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
}
nvc0->state.num_vtxelts = vertex->num_elements;
- nvc0->state.instance_bits = vertex->instance_bits;
+ nvc0->state.instance_elts = vertex->instance_elts;
}
#define NVC0_PRIM_GL_CASE(n) \
@@ -600,17 +616,18 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
nvc0_state_validate(nvc0);
+ if (nvc0->vbo_fifo) {
+ nvc0_push_vbo(nvc0, info);
+ return;
+ }
+
if (nvc0->state.instance_base != info->start_instance) {
nvc0->state.instance_base = info->start_instance;
+ /* NOTE: this does not affect the shader input, should it ? */
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(chan, RING_3D(VERTEX_ARRAY_FLUSH), 1);
OUT_RING (chan, 0);