nv50: get rid of the static_init stateobj

Relocations of per-screen buffers are now emitted directly,
and include the necessary method to get changes in constbuf
addresses committed to the hw.

It should also be a bit cheaper than the way stateobjs emit
relocation markers, use a little less pushbuf space.
This commit is contained in:
Christoph Bumiller
2010-03-21 13:17:02 +01:00
parent f87a5f6499
commit 272bbbffb0
3 changed files with 141 additions and 139 deletions
+138 -136
View File
@@ -190,8 +190,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
nouveau_bo_ref(NULL, &screen->tic);
if (screen->tsc)
nouveau_bo_ref(NULL, &screen->tsc);
if (screen->static_init)
so_ref(NULL, &screen->static_init);
nouveau_notifier_free(&screen->sync);
nouveau_grobj_free(&screen->tesla);
@@ -204,16 +202,65 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
FREE(screen);
}
#define BGN_RELOC(ch, bo, gr, m, n, fl) \
OUT_RELOC(ch, bo, (n << 18) | (gr->subc << 13) | m, fl, 0, 0)
void
nv50_screen_relocs(struct nv50_screen *screen)
{
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *tesla = screen->tesla;
unsigned i;
const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
MARK_RING (chan, 28, 26);
/* cause grobj autobind */
BEGIN_RING(chan, tesla, 0x0100, 1);
OUT_RING (chan, 0);
BGN_RELOC (chan, screen->tic, tesla, NV50TCL_TIC_ADDRESS_HIGH, 2, rl);
OUT_RELOCh(chan, screen->tic, 0, rl);
OUT_RELOCl(chan, screen->tic, 0, rl);
BGN_RELOC (chan, screen->tsc, tesla, NV50TCL_TSC_ADDRESS_HIGH, 2, rl);
OUT_RELOCh(chan, screen->tsc, 0, rl);
OUT_RELOCl(chan, screen->tsc, 0, rl);
BGN_RELOC (chan, screen->constbuf_misc[0],
tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
OUT_RELOC (chan, screen->constbuf_misc[0],
(NV50_CB_PMISC << 16) | 0x0200, rl, 0, 0);
BGN_RELOC (chan, screen->constbuf_misc[0],
tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
OUT_RELOC (chan, screen->constbuf_misc[0],
(NV50_CB_AUX << 16) | 0x0200, rl, 0, 0);
for (i = 0; i < 3; ++i) {
BGN_RELOC (chan, screen->constbuf_parm[i],
tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
OUT_RELOC (chan, screen->constbuf_parm[i],
((NV50_CB_PVP + i) << 16) | 0x0800, rl, 0, 0);
}
}
struct pipe_screen *
nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
{
struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
struct nouveau_channel *chan;
struct pipe_screen *pscreen;
struct nouveau_stateobj *so;
unsigned chipset = dev->chipset;
unsigned tesla_class = 0;
int ret, i;
const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
if (!screen)
return NULL;
@@ -296,64 +343,58 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
}
/* Static M2MF init */
so = so_new(1, 3, 0);
so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
so_data (so, screen->sync->handle);
so_data (so, chan->vram->handle);
so_data (so, chan->vram->handle);
so_emit(chan, so);
so_ref (NULL, &so);
BEGIN_RING(chan, screen->m2mf,
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
OUT_RING (chan, screen->sync->handle);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
/* Static 2D init */
so = so_new(4, 7, 0);
so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
so_data (so, screen->sync->handle);
so_data (so, chan->vram->handle);
so_data (so, chan->vram->handle);
so_data (so, chan->vram->handle);
so_method(so, screen->eng2d, NV50_2D_OPERATION, 1);
so_data (so, NV50_2D_OPERATION_SRCCOPY);
so_method(so, screen->eng2d, NV50_2D_CLIP_ENABLE, 1);
so_data (so, 0);
so_method(so, screen->eng2d, 0x0888, 1);
so_data (so, 1);
so_emit(chan, so);
so_ref(NULL, &so);
BEGIN_RING(chan, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
OUT_RING (chan, screen->sync->handle);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
BEGIN_RING(chan, screen->eng2d, NV50_2D_OPERATION, 1);
OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
BEGIN_RING(chan, screen->eng2d, NV50_2D_CLIP_ENABLE, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, screen->eng2d, 0x0888, 1);
OUT_RING (chan, 1);
/* Static tesla init */
so = so_new(47, 95, 24);
so_method(so, screen->tesla, NV50TCL_COND_MODE, 1);
so_data (so, NV50TCL_COND_MODE_ALWAYS);
so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
so_data (so, screen->sync->handle);
so_method(so, screen->tesla, NV50TCL_DMA_ZETA, 11);
BEGIN_RING(chan, screen->tesla, NV50TCL_COND_MODE, 1);
OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS);
BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
OUT_RING (chan, screen->sync->handle);
BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_ZETA, 11);
for (i = 0; i < 11; i++)
so_data(so, chan->vram->handle);
so_method(so, screen->tesla, NV50TCL_DMA_COLOR(0),
NV50TCL_DMA_COLOR__SIZE);
OUT_RING (chan, chan->vram->handle);
BEGIN_RING(chan, screen->tesla,
NV50TCL_DMA_COLOR(0), NV50TCL_DMA_COLOR__SIZE);
for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
so_data(so, chan->vram->handle);
so_method(so, screen->tesla, NV50TCL_RT_CONTROL, 1);
so_data (so, 1);
OUT_RING (chan, chan->vram->handle);
BEGIN_RING(chan, screen->tesla, NV50TCL_RT_CONTROL, 1);
OUT_RING (chan, 1);
/* activate all 32 lanes (threads) in a warp */
so_method(so, screen->tesla, NV50TCL_WARP_HALVES, 1);
so_data (so, 0x2);
so_method(so, screen->tesla, 0x1400, 1);
so_data (so, 0xf);
BEGIN_RING(chan, screen->tesla, NV50TCL_WARP_HALVES, 1);
OUT_RING (chan, 2);
BEGIN_RING(chan, screen->tesla, 0x1400, 1);
OUT_RING (chan, 0xf);
/* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
for (i = 0; i < 3; ++i) {
so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
so_data (so, 0x54);
BEGIN_RING(chan, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
OUT_RING (chan, 0x54);
}
/* origin is top left (set to 1 for bottom left) */
so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
so_data (so, 0);
so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
so_data (so, 8);
BEGIN_RING(chan, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
OUT_RING (chan, 8);
/* constant buffers for immediates and VP/FP parameters */
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4,
@@ -362,6 +403,14 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
nv50_screen_destroy(pscreen);
return NULL;
}
BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
OUT_RING (chan, (NV50_CB_PMISC << 16) | 0x0200);
BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
OUT_RING (chan, (NV50_CB_AUX << 16) | 0x0200);
for (i = 0; i < 3; i++) {
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4,
@@ -370,6 +419,10 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
nv50_screen_destroy(pscreen);
return NULL;
}
BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
OUT_RING (chan, ((NV50_CB_PVP + i) << 16) | 0x0800);
}
if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) ||
@@ -381,80 +434,16 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
return NULL;
}
/*
// map constant buffers:
// B = buffer ID (maybe more than 1 byte)
// N = CB index used in shader instruction
// P = program type (0 = VP, 2 = GP, 3 = FP)
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x000BBNP1);
*/
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
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) | 0x00000200);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000001 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000021 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000031 | (NV50_CB_PMISC << 12));
/* bind auxiliary constbuf to immediate data bo */
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_AUX << 16) | 0x00000200);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000201 | (NV50_CB_AUX << 12));
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000221 | (NV50_CB_AUX << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 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, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000101 | (NV50_CB_PVP << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PGP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000121 | (NV50_CB_PGP << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PFP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
&screen->tic);
if (ret) {
nv50_screen_destroy(pscreen);
return NULL;
}
so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, 3 * 32 - 1);
BEGIN_RING(chan, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
OUT_RELOCh(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RING (chan, 3 * 32 - 1);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
&screen->tsc);
@@ -462,37 +451,50 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
nv50_screen_destroy(pscreen);
return NULL;
}
BEGIN_RING(chan, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
OUT_RELOCh(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RING (chan, 0); /* ignored if TSC_LINKED (0x1234) == 1 */
so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, 0x00000000); /* ignored if TSC_LINKED (0x1234) = 1 */
/* map constant buffers:
* B = buffer ID (maybe more than 1 byte)
* N = CB index used in shader instruction
* P = program type (0 = VP, 2 = GP, 3 = FP)
* SET_PROGRAM_CB = 0x000BBNP1
*/
BEGIN_RING_NI(chan, screen->tesla, NV50TCL_SET_PROGRAM_CB, 8);
/* bind immediate buffer */
OUT_RING (chan, 0x001 | (NV50_CB_PMISC << 12));
OUT_RING (chan, 0x021 | (NV50_CB_PMISC << 12));
OUT_RING (chan, 0x031 | (NV50_CB_PMISC << 12));
/* bind auxiliary constbuf to immediate data bo */
OUT_RING (chan, 0x201 | (NV50_CB_AUX << 12));
OUT_RING (chan, 0x221 | (NV50_CB_AUX << 12));
/* bind parameter buffers */
OUT_RING (chan, 0x101 | (NV50_CB_PVP << 12));
OUT_RING (chan, 0x121 | (NV50_CB_PGP << 12));
OUT_RING (chan, 0x131 | (NV50_CB_PFP << 12));
/* Vertex array limits - max them out */
for (i = 0; i < 16; i++) {
so_method(so, screen->tesla, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2);
so_data (so, 0x000000ff);
so_data (so, 0xffffffff);
BEGIN_RING(chan, screen->tesla,
NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2);
OUT_RING (chan, 0x000000ff);
OUT_RING (chan, 0xffffffff);
}
so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2);
so_data (so, fui(0.0));
so_data (so, fui(1.0));
BEGIN_RING(chan, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2);
OUT_RINGf (chan, 0.0f);
OUT_RINGf (chan, 1.0f);
/* no dynamic combination of TIC & TSC entries => only BIND_TIC used */
so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1);
so_data (so, 1);
BEGIN_RING(chan, screen->tesla, NV50TCL_LINKED_TSC, 1);
OUT_RING (chan, 1);
so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
so_data (so, 1); /* default edgeflag to TRUE */
BEGIN_RING(chan, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
OUT_RING (chan, 1); /* default edgeflag to TRUE */
so_emit(chan, so);
so_ref (so, &screen->static_init);
so_ref (NULL, &so);
nouveau_pushbuf_flush(chan, 0);
FIRE_RING (chan);
screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE);
return pscreen;
+2 -2
View File
@@ -27,8 +27,6 @@ struct nv50_screen {
struct nouveau_bo *tic;
struct nouveau_bo *tsc;
struct nouveau_stateobj *static_init;
boolean force_push;
};
@@ -38,4 +36,6 @@ nv50_screen(struct pipe_screen *screen)
return (struct nv50_screen *)screen;
}
extern void nv50_screen_relocs(struct nv50_screen *);
#endif
@@ -435,7 +435,7 @@ nv50_state_validate(struct nv50_context *nv50, unsigned wait_dwords)
so_emit_reloc_markers(chan, nv50->state.hw[3]); /* vp */
so_emit_reloc_markers(chan, nv50->state.hw[4]); /* fp */
so_emit_reloc_markers(chan, nv50->state.hw[17]); /* vb */
so_emit_reloc_markers(chan, nv50->screen->static_init);
nv50_screen_relocs(nv50->screen);
/* No idea.. */
BEGIN_RING(chan, tesla, 0x142c, 1);