nouveau,nvc0: fix/improve handling of multiple constant buffers
This commit is contained in:
parent
28271fd00d
commit
d988361ead
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue