commit 88dbc993e651da91d66c4ca471d11ee5aa2b5085 Author: chr Date: Wed May 6 11:50:17 2009 +0200 Use multiple (3 for now: PVP, PFP, PMISC) constant buffers. diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 2ab7b57..6e279bd 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -426,7 +426,7 @@ set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e) static INLINE void set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) { - unsigned val = fui(pc->immd_buf[imm->hw - pc->param_nr * 4]); + unsigned val = fui(pc->immd_buf[imm->hw]); set_long(pc, e); /*XXX: can't be predicated - bits overlap.. catch cases where both @@ -478,22 +478,14 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, struct nv50_program_exec *e) { set_long(pc, e); -#if 1 - e->inst[1] |= (1 << 22); -#else - if (src->type == P_IMMD) { - e->inst[1] |= (NV50_CB_PMISC << 22); - } else { - if (pc->p->type == PIPE_SHADER_VERTEX) - e->inst[1] |= (NV50_CB_PVP << 22); - else - e->inst[1] |= (NV50_CB_PFP << 22); - } -#endif + /* XXX: param.bs can be extracted from inst[1] */ + e->param.bs = (src->type == P_IMMD) ? 0 : 1; e->param.index = src->hw; e->param.shift = s; e->param.mask = m << (s % 32); + + e->inst[1] |= (e->param.bs << 22); } static void @@ -1502,7 +1494,7 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_TEX: - case TGSI_OPCODE_TXP: + case TGSI_OPCODE_TXP: /* XXX: TXP should use w-component as iv on interp */ { struct nv50_reg *t[4]; struct nv50_program_exec *e; @@ -1977,7 +1969,7 @@ nv50_program_tx_prep(struct nv50_pc *pc) } if (pc->immd_nr) { - int rid = pc->param_nr * 4; + int rid = 0; pc->immd = CALLOC(pc->immd_nr * 4, sizeof(struct nv50_reg)); if (!pc->immd) @@ -2121,7 +2113,7 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p) static void nv50_program_upload_data(struct nv50_context *nv50, float *map, - unsigned start, unsigned count) + unsigned start, unsigned count, unsigned cbuf) { struct nouveau_channel *chan = nv50->screen->nvws->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -2130,7 +2122,7 @@ nv50_program_upload_data(struct nv50_context *nv50, float *map, unsigned nr = count > 2047 ? 2047 : count; BEGIN_RING(chan, tesla, 0x00000f00, 1); - OUT_RING (chan, (NV50_CB_PMISC << 0) | (start << 8)); + OUT_RING (chan, (cbuf << 0) | (start << 8)); BEGIN_RING(chan, tesla, 0x40000f04, nr); OUT_RINGp (chan, map, nr); @@ -2145,35 +2137,48 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) { struct nouveau_winsys *nvws = nv50->screen->nvws; struct pipe_winsys *ws = nv50->pipe.winsys; - unsigned nr = p->param_nr + p->immd_nr; - if (!p->data && nr) { - struct nouveau_resource *heap = nv50->screen->vp_data_heap; + if (!p->data[0] && p->immd_nr) { + struct nouveau_resource *heap = nv50->screen->immd_heap[0]; + + if (nvws->res_alloc(heap, p->immd_nr, p, &p->data[0])) { + while (heap->next && heap->size < p->immd_nr) { + struct nv50_program *evict = heap->next->priv; + nvws->res_free(&evict->data[0]); + } + + if (nvws->res_alloc(heap, p->immd_nr, p, &p->data[0])) + assert(0); + } + + /* immediates only need to be uploaded again when freed */ + nv50_program_upload_data(nv50, p->immd, p->data[0]->start, + p->immd_nr, NV50_CB_PMISC); + } + + if (!p->data[1] && p->param_nr) { + struct nouveau_resource *heap = nv50->screen->parm_heap[p->type]; - if (nvws->res_alloc(heap, nr, p, &p->data)) { - while (heap->next && heap->size < nr) { + if (nvws->res_alloc(heap, p->param_nr, p, &p->data[1])) { + while (heap->next && heap->size < p->param_nr) { struct nv50_program *evict = heap->next->priv; - nvws->res_free(&evict->data); + nvws->res_free(&evict->data[1]); } - if (nvws->res_alloc(heap, nr, p, &p->data)) + if (nvws->res_alloc(heap, p->param_nr, p, &p->data[1])) assert(0); } } if (p->param_nr) { + unsigned cbuf; float *map = ws->buffer_map(ws, nv50->constbuf[p->type], PIPE_BUFFER_USAGE_CPU_READ); - nv50_program_upload_data(nv50, map, p->data->start, - p->param_nr); + cbuf = (p->type == PIPE_SHADER_VERTEX) ? NV50_CB_PVP : NV50_CB_PFP; + nv50_program_upload_data(nv50, map, p->data[1]->start, + p->param_nr, cbuf); ws->buffer_unmap(ws, nv50->constbuf[p->type]); } - - if (p->immd_nr) { - nv50_program_upload_data(nv50, p->immd, - p->data->start + p->param_nr, - p->immd_nr); - } } static void @@ -2193,20 +2198,26 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) upload = TRUE; } - if (p->data && p->data->start != p->data_start) { + if ((p->data[0] && p->data[0]->start != p->data_start[0]) || + (p->data[1] && p->data[1]->start != p->data_start[1])) + { for (e = p->exec_head; e; e = e->next) { unsigned ei, ci; if (e->param.index < 0) continue; ei = e->param.shift >> 5; - ci = e->param.index + p->data->start; + ci = e->param.index + p->data[e->param.bs]->start; e->inst[ei] &= ~e->param.mask; e->inst[ei] |= (ci << e->param.shift); } - p->data_start = p->data->start; + if (p->data[0]) + p->data_start[0] = p->data[0]->start; + if (p->data[1]) + p->data_start[1] = p->data[1]->start; + upload = TRUE; } @@ -2364,7 +2375,8 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) if (p->buffer) pipe_buffer_reference(&p->buffer, NULL); - nv50->screen->nvws->res_free(&p->data); + nv50->screen->nvws->res_free(&p->data[0]); + nv50->screen->nvws->res_free(&p->data[1]); p->translated = 0; } diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index 3b3b6bb..9dd0f37 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -10,6 +10,7 @@ struct nv50_program_exec { unsigned inst[2]; struct { int index; + int bs; /* buffer selector */ unsigned mask; unsigned shift; } param; @@ -24,8 +25,8 @@ struct nv50_program { struct nv50_program_exec *exec_head; struct nv50_program_exec *exec_tail; unsigned exec_size; - struct nouveau_resource *data; - unsigned data_start; + struct nouveau_resource *data[2]; + unsigned data_start[2]; struct pipe_buffer *buffer; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 2980564..268eeeb 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -290,20 +290,61 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->tesla, 0x16b8, 1); so_data (so, 8); - /* Shared constant buffer */ - screen->constbuf = screen->pipe.buffer_create(&screen->pipe, 0, 0, 128 * 4 * 4); - if (nvws->res_init(&screen->vp_data_heap, 0, 128)) { - NOUVEAU_ERR("Error initialising constant buffer\n"); + /* constant buffers for immediates and VP/FP parameters */ + screen->constbuf_misc[0] = + screen->pipe.buffer_create(&screen->pipe, 0, 0, 128 * 4 * 4); + + screen->constbuf_parm[0] = + screen->pipe.buffer_create(&screen->pipe, 0, 0, 128 * 4 * 4); + + screen->constbuf_parm[1] = + screen->pipe.buffer_create(&screen->pipe, 0, 0, 128 * 4 * 4); + + if (nvws->res_init(&screen->immd_heap[0], 0, 128) || + nvws->res_init(&screen->parm_heap[0], 0, 128) || + nvws->res_init(&screen->parm_heap[1], 0, 128)) + { + NOUVEAU_ERR("Error initialising constant buffers.\n"); nv50_screen_destroy(&screen->pipe); return NULL; } so_method(so, screen->tesla, 0x1280, 3); - so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | + so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | + so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PMISC << 16) | 0x00001000); + so_data (so, (NV50_CB_PMISC << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); + + so_method(so, screen->tesla, 0x1280, 3); + so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_PVP << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); + + so_method(so, screen->tesla, 0x1280, 3); + so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_PMISC << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); + + /* + // map VP and FP CB index 0 to CB_PMISC + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x000BBNP1 = 0x00000001); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x000BBNP1 = 0x00000031); + */ /* Texture sampler/image unit setup - we abuse the constant buffer * upload mechanism for the moment to upload data to the tex config diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index db567aa..31b8ef2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -15,8 +15,11 @@ struct nv50_screen { struct nouveau_grobj *m2mf; struct nouveau_notifier *sync; - struct pipe_buffer *constbuf; - struct nouveau_resource *vp_data_heap; + struct pipe_buffer *constbuf_misc[1]; + struct pipe_buffer *constbuf_parm[2]; + + struct nouveau_resource *immd_heap[1]; + struct nouveau_resource *parm_heap[2]; struct pipe_buffer *tic; struct pipe_buffer *tsc;