diff options
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_buffer.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_buffer.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_context.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 8 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c | 46 |
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); |