summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2011-10-20 22:42:59 +0200
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2011-10-21 23:00:40 +0200
commitd988361ead27ce61615669bd428b04d2aac7af4f (patch)
treecf038c67142bf4352489fd0a80bb89df76c58c97
parent28271fd00dc5dd83f95b5cb890e0ab2c0ff6159d (diff)
nouveau,nvc0: fix/improve handling of multiple constant buffers
-rw-r--r--src/gallium/drivers/nouveau/nouveau_buffer.c17
-rw-r--r--src/gallium/drivers/nouveau/nouveau_context.h6
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h6
-rw-r--r--src/gallium/drivers/nv50/nv50_transfer.c33
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.c1
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.h5
-rw-r--r--src/gallium/drivers/nvc0/nvc0_state_validate.c42
-rw-r--r--src/gallium/drivers/nvc0/nvc0_transfer.c36
8 files changed, 111 insertions, 35 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c
index 60d8e37a554..f822625af90 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.c
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.c
@@ -24,14 +24,19 @@ static INLINE boolean
nouveau_buffer_allocate(struct nouveau_screen *screen,
struct nv04_resource *buf, unsigned domain)
{
+ uint32_t size = buf->base.width0;
+
+ if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+ size = align(size, 0x100);
+
if (domain == NOUVEAU_BO_VRAM) {
- buf->mm = nouveau_mm_allocate(screen->mm_VRAM, buf->base.width0,
+ buf->mm = nouveau_mm_allocate(screen->mm_VRAM, size,
&buf->bo, &buf->offset);
if (!buf->bo)
return nouveau_buffer_allocate(screen, buf, NOUVEAU_BO_GART);
} else
if (domain == NOUVEAU_BO_GART) {
- buf->mm = nouveau_mm_allocate(screen->mm_GART, buf->base.width0,
+ buf->mm = nouveau_mm_allocate(screen->mm_GART, size,
&buf->bo, &buf->offset);
if (!buf->bo)
return FALSE;
@@ -129,8 +134,12 @@ nouveau_buffer_upload(struct nouveau_context *nv, struct nv04_resource *buf,
uint32_t offset;
if (size <= 192) {
- nv->push_data(nv, buf->bo, buf->offset + start, buf->domain,
- size, buf->data + start);
+ if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+ nv->push_cb(nv, buf->bo, buf->domain, buf->offset, buf->base.width0,
+ start, size / 4, (const uint32_t *)(buf->data + start));
+ else
+ nv->push_data(nv, buf->bo, buf->offset + start, buf->domain,
+ size, buf->data + start);
return TRUE;
}
diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h
index 7b5f3f1ec39..92aea76b424 100644
--- a/src/gallium/drivers/nouveau/nouveau_context.h
+++ b/src/gallium/drivers/nouveau/nouveau_context.h
@@ -8,6 +8,7 @@ struct nouveau_context {
struct nouveau_screen *screen;
boolean vbo_dirty;
+ boolean cb_dirty;
void (*copy_data)(struct nouveau_context *,
struct nouveau_bo *dst, unsigned, unsigned,
@@ -15,6 +16,11 @@ struct nouveau_context {
void (*push_data)(struct nouveau_context *,
struct nouveau_bo *dst, unsigned, unsigned,
unsigned, const void *);
+ /* base, size refer to the whole constant buffer */
+ void (*push_cb)(struct nouveau_context *,
+ struct nouveau_bo *, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *);
};
static INLINE struct nouveau_context *
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index edd79159e72..2bf634a8237 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -53,6 +53,7 @@
#define NV50_BUFCTX_TEXTURES 3
#define NV50_BUFCTX_COUNT 4
+#define NV50_CB_TMP 123
/* fixed constant buffer binding points - low indices for user's constbufs */
#define NV50_CB_PVP 124
#define NV50_CB_PGP 126
@@ -206,6 +207,11 @@ nv50_m2mf_copy_linear(struct nouveau_context *pipe,
struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
unsigned size);
+void
+nv50_cb_push(struct nouveau_context *nv,
+ struct nouveau_bo *bo, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *data);
/* nv50_vbo.c */
void nv50_draw_vbo(struct pipe_context *, const struct pipe_draw_info *);
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index c86c417c071..6f860e73348 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -364,3 +364,36 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx,
nouveau_bo_unmap(tx->rect[1].bo);
}
+void
+nv50_cb_push(struct nouveau_context *nv,
+ struct nouveau_bo *bo, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *data)
+{
+ struct nouveau_channel *chan = nv->screen->channel;
+
+ assert(!(offset & 3));
+ size = align(size, 0x100);
+
+ while (words) {
+ unsigned nr;
+
+ MARK_RING(chan, 24, 2);
+ nr = AVAIL_RING(chan);
+ nr = MIN2(nr - 7, words);
+ nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
+
+ BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3);
+ OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR);
+ OUT_RING (chan, (NV50_CB_TMP << 16) | (size & 0xffff));
+ BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
+ OUT_RING (chan, (offset << 6) | NV50_CB_TMP);
+ BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr);
+ OUT_RINGp (chan, data, nr);
+
+ words -= nr;
+ data += nr;
+ offset += nr * 4;
+ }
+}
diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c
index d493d4b2a92..2927a0905bd 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nvc0/nvc0_context.c
@@ -124,6 +124,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
nvc0->base.screen = &screen->base;
nvc0->base.copy_data = nvc0_m2mf_copy_linear;
nvc0->base.push_data = nvc0_m2mf_push_linear;
+ nvc0->base.push_cb = nvc0_cb_push;
pipe->winsys = pipe_winsys;
pipe->screen = pscreen;
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h
index c46e7430f85..4435c1b4f3c 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nvc0/nvc0_context.h
@@ -221,6 +221,11 @@ nvc0_m2mf_copy_linear(struct nouveau_context *nv,
struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
unsigned size);
+void
+nvc0_cb_push(struct nouveau_context *,
+ struct nouveau_bo *bo, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *data);
/* nvc0_vbo.c */
void nvc0_draw_vbo(struct pipe_context *, const struct pipe_draw_info *);
diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c
index e60ed972455..1ec95b7f8b5 100644
--- a/src/gallium/drivers/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c
@@ -340,7 +340,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
while (nvc0->constbuf_dirty[s]) {
unsigned base = 0;
- unsigned offset = 0, words = 0;
+ unsigned words = 0;
boolean rebind = TRUE;
i = ffs(nvc0->constbuf_dirty[s]) - 1;
@@ -356,7 +356,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
}
if (!nouveau_resource_mapped_by_gpu(&res->base)) {
- if (i == 0) {
+ if (i == 0 && (res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) {
base = s << 16;
bo = nvc0->screen->uniforms;
@@ -365,19 +365,16 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
else
nvc0->state.uniform_buffer_bound[s] =
align(res->base.width0, 0x100);
+
+ words = res->base.width0 / 4;
} else {
+ nouveau_buffer_migrate(&nvc0->base, res, NOUVEAU_BO_VRAM);
bo = res->bo;
+ base = res->offset;
}
-#if 0
- nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
- base, res->base.width0, res->data);
- BEGIN_RING(chan, RING_3D_(0x021c), 1);
- OUT_RING (chan, 0x1111);
-#else
- words = res->base.width0 / 4;
-#endif
} else {
bo = res->bo;
+ base = res->offset;
if (i == 0)
nvc0->state.uniform_buffer_bound[s] = 0;
}
@@ -396,27 +393,10 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
OUT_RING (chan, (i << 4) | 1);
}
- while (words) {
- unsigned nr = AVAIL_RING(chan);
-
- if (nr < 16) {
- FIRE_RING(chan);
- continue;
- }
- nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
-
- MARK_RING (chan, nr + 5, 2);
- BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
- OUT_RING (chan, align(res->base.width0, 0x100));
- OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
- OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
- BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
- OUT_RING (chan, offset);
- OUT_RINGp (chan, &res->data[offset], nr);
-
- offset += nr * 4;
- words -= nr;
- }
+ if (words)
+ nvc0_cb_push(&nvc0->base,
+ bo, NOUVEAU_BO_VRAM, base, res->base.width0,
+ 0, words, (const uint32_t *)res->data);
}
}
}
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
index 6404c8cc4ae..f16863733b7 100644
--- a/src/gallium/drivers/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
@@ -365,3 +365,39 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
nouveau_bo_unmap(tx->rect[1].bo);
}
+void
+nvc0_cb_push(struct nouveau_context *nv,
+ struct nouveau_bo *bo, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *data)
+{
+ struct nouveau_channel *chan = nv->screen->channel;
+
+ assert(!(offset & 3));
+ size = align(size, 0x100);
+
+ MARK_RING (chan, 16, 2);
+ BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
+ OUT_RING (chan, size);
+ OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR);
+
+ while (words) {
+ unsigned nr = AVAIL_RING(chan);
+ nr = MIN2(nr, words);
+ nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
+
+ BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
+ OUT_RING (chan, offset);
+ OUT_RINGp (chan, data, nr);
+
+ words -= nr;
+ data += nr;
+ offset += nr * 4;
+
+ if (words) {
+ MARK_RING(chan, 6, 1);
+ nouveau_bo_validate(chan, bo, domain | NOUVEAU_BO_WR);
+ }
+ }
+}