summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_buffer.c4
-rw-r--r--src/gallium/drivers/nouveau/nouveau_buffer.h2
-rw-r--r--src/gallium/drivers/nouveau/nouveau_context.h5
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_context.h8
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state.c2
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c3
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c46
7 files changed, 58 insertions, 12 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c
index 912b7789006..4937dae8b06 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.c
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.c
@@ -206,8 +206,8 @@ nouveau_transfer_write(struct nouveau_context *nv, struct nouveau_transfer *tx,
nv->copy_data(nv, buf->bo, buf->offset + base, buf->domain,
tx->bo, tx->offset + offset, NOUVEAU_BO_GART, size);
else
- if ((buf->base.bind & PIPE_BIND_CONSTANT_BUFFER) && nv->push_cb && can_cb)
- nv->push_cb(nv, buf->bo, buf->domain, buf->offset, buf->base.width0,
+ if (nv->push_cb && can_cb)
+ nv->push_cb(nv, buf,
base, size / 4, (const uint32_t *)data);
else
nv->push_data(nv, buf->bo, buf->offset + base, buf->domain, size, data);
diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.h b/src/gallium/drivers/nouveau/nouveau_buffer.h
index 7e6a6cc804b..d45bf7aebcf 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.h
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.h
@@ -41,6 +41,8 @@ struct nv04_resource {
uint8_t status;
uint8_t domain;
+ uint16_t cb_bindings[6]; /* per-shader per-slot bindings */
+
struct nouveau_fence *fence;
struct nouveau_fence *fence_wr;
diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h
index 24deb7ee4c0..decb2714ede 100644
--- a/src/gallium/drivers/nouveau/nouveau_context.h
+++ b/src/gallium/drivers/nouveau/nouveau_context.h
@@ -6,6 +6,8 @@
#define NOUVEAU_MAX_SCRATCH_BUFS 4
+struct nv04_resource;
+
struct nouveau_context {
struct pipe_context pipe;
struct nouveau_screen *screen;
@@ -23,8 +25,7 @@ struct nouveau_context {
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,
+ struct nv04_resource *,
unsigned offset, unsigned words, const uint32_t *);
/* @return: @ref reduced by nr of references found in context */
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
index 6ed79cf9553..30bee3a0f8c 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
@@ -299,10 +299,10 @@ nve4_p2mf_push_linear(struct nouveau_context *nv,
struct nouveau_bo *dst, unsigned offset, unsigned domain,
unsigned size, const void *data);
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_cb_bo_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/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index ee29912eb40..c5bfd03956d 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -831,6 +831,8 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
}
nvc0->constbuf_dirty[s] |= 1 << i;
+ if (nvc0->constbuf[s][i].u.buf)
+ nv04_resource(nvc0->constbuf[s][i].u.buf)->cb_bindings[s] &= ~(1 << i);
pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, res);
nvc0->constbuf[s][i].user = (cb && cb->user_buffer) ? true : false;
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
index 47bd66d1e35..aec06097bbd 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
@@ -440,7 +440,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (0 << 4) | 1);
}
- nvc0_cb_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base),
+ nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base),
base, nvc0->state.uniform_buffer_bound[s],
0, (size + 3) / 4,
nvc0->constbuf[s][0].u.data);
@@ -458,6 +458,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);
nvc0->cb_dirty = 1; /* Force cache flush for UBO. */
+ res->cb_bindings[s] |= 1 << i;
} else {
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (i << 4) | 0);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
index 7cc5b4b1f48..d4831bfd9d4 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
@@ -506,12 +506,49 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
}
/* This happens rather often with DTD9/st. */
-void
+static void
nvc0_cb_push(struct nouveau_context *nv,
- struct nouveau_bo *bo, unsigned domain,
- unsigned base, unsigned size,
+ struct nv04_resource *res,
unsigned offset, unsigned words, const uint32_t *data)
{
+ struct nvc0_context *nvc0 = nvc0_context(&nv->pipe);
+ struct nvc0_constbuf *cb = NULL;
+ int s;
+
+ /* Go through all the constbuf binding points of this buffer and try to
+ * find one which contains the region to be updated.
+ */
+ for (s = 0; s < 6 && !cb; s++) {
+ uint16_t bindings = res->cb_bindings[s];
+ while (bindings) {
+ int i = ffs(bindings) - 1;
+ uint32_t cb_offset = nvc0->constbuf[s][i].offset;
+
+ bindings &= ~(1 << i);
+ if (cb_offset <= offset &&
+ cb_offset + nvc0->constbuf[s][i].size >= offset + words * 4) {
+ cb = &nvc0->constbuf[s][i];
+ break;
+ }
+ }
+ }
+
+ if (cb) {
+ nvc0_cb_bo_push(nv, res->bo, res->domain,
+ res->offset + cb->offset, cb->size,
+ offset - cb->offset, words, data);
+ } else {
+ nv->push_data(nv, res->bo, res->offset + offset, res->domain,
+ words * 4, data);
+ }
+}
+
+void
+nvc0_cb_bo_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_pushbuf *push = nv->pushbuf;
NOUVEAU_DRV_STAT(nv->screen, constbuf_upload_count, 1);
@@ -520,6 +557,9 @@ nvc0_cb_push(struct nouveau_context *nv,
assert(!(offset & 3));
size = align(size, 0x100);
+ assert(offset < size);
+ assert(offset + words * 4 <= size);
+
BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, size);
PUSH_DATAh(push, bo->offset + base);