mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 20:38:06 +02:00
nv50: use SIFC for TIC, TSC upload
Add proper flushes for TIC and TSC and remove the costly 2D.0110 flush in nv50_flush. Correct TIC and TSC bo sizes.
This commit is contained in:
parent
6ab2fcca9d
commit
fba2eabe13
6 changed files with 77 additions and 52 deletions
|
|
@ -33,13 +33,6 @@ nv50_flush(struct pipe_context *pipe, unsigned flags,
|
|||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
|
||||
/* We need this in the ddx for reliable composite, not sure what we're
|
||||
* actually flushing. We generate all our own flushes with flags = 0. */
|
||||
WAIT_RING(chan, 2);
|
||||
BEGIN_RING(chan, eng2d, 0x0110, 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
if (flags & PIPE_FLUSH_FRAME)
|
||||
FIRE_RING(chan);
|
||||
|
|
|
|||
|
|
@ -199,6 +199,11 @@ extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program
|
|||
extern boolean nv50_state_validate(struct nv50_context *nv50);
|
||||
extern void nv50_state_flush_notify(struct nouveau_channel *chan);
|
||||
|
||||
extern void nv50_so_init_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_stateobj *so,
|
||||
struct nouveau_bo *bo, unsigned reloc,
|
||||
unsigned size);
|
||||
|
||||
/* nv50_tex.c */
|
||||
extern void nv50_tex_validate(struct nv50_context *);
|
||||
|
||||
|
|
|
|||
|
|
@ -364,48 +364,31 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
|||
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
|
||||
so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
|
||||
|
||||
/* Texture sampler/image unit setup - we abuse the constant buffer
|
||||
* upload mechanism for the moment to upload data to the tex config
|
||||
* blocks. At some point we *may* want to go the NVIDIA way of doing
|
||||
* things?
|
||||
*/
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tic);
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 64*8*4, &screen->tic);
|
||||
if (ret) {
|
||||
nv50_screen_destroy(pscreen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
so_method(so, screen->tesla, NV50TCL_CB_DEF_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, (NV50_CB_TIC << 16) | 0x0800);
|
||||
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, 0x00000800);
|
||||
so_data (so, 0x000007ff);
|
||||
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tsc);
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 64*8*4, &screen->tsc);
|
||||
if (ret) {
|
||||
nv50_screen_destroy(pscreen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
so_method(so, screen->tesla, NV50TCL_CB_DEF_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, (NV50_CB_TSC << 16) | 0x0800);
|
||||
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, 0x00000800);
|
||||
so_data (so, 0x00000000);
|
||||
|
||||
|
||||
/* Vertex array limits - max them out */
|
||||
|
|
|
|||
|
|
@ -222,6 +222,9 @@ nv50_state_flush_notify(struct nouveau_channel *chan)
|
|||
{
|
||||
struct nv50_context *nv50 = chan->user_private;
|
||||
|
||||
if (nv50->state.tic_upload && !(nv50->dirty & NV50_NEW_TEXTURE))
|
||||
so_emit(chan, nv50->state.tic_upload);
|
||||
|
||||
so_emit_reloc_markers(chan, nv50->state.fb);
|
||||
so_emit_reloc_markers(chan, nv50->state.vertprog);
|
||||
so_emit_reloc_markers(chan, nv50->state.fragprog);
|
||||
|
|
@ -233,6 +236,7 @@ boolean
|
|||
nv50_state_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
struct nouveau_stateobj *so;
|
||||
unsigned i;
|
||||
|
||||
|
|
@ -354,19 +358,25 @@ scissor_uptodate:
|
|||
viewport_uptodate:
|
||||
|
||||
if (nv50->dirty & NV50_NEW_SAMPLER) {
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
so = so_new(nv50->sampler_nr * 9 + 23 + 4, 2);
|
||||
|
||||
nv50_so_init_sifc(nv50, so, nv50->screen->tsc, NOUVEAU_BO_VRAM,
|
||||
nv50->sampler_nr * 8 * 4);
|
||||
|
||||
so = so_new(nv50->sampler_nr * 11, 0);
|
||||
for (i = 0; i < nv50->sampler_nr; i++) {
|
||||
if (!nv50->sampler[i])
|
||||
continue;
|
||||
|
||||
so_method(so, tesla, NV50TCL_CB_ADDR, 1);
|
||||
so_data (so, ((i * 8) << NV50TCL_CB_ADDR_ID_SHIFT) |
|
||||
NV50_CB_TSC);
|
||||
so_method(so, tesla, NV50TCL_CB_DATA(0) | (2<<29), 8);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
|
||||
so_datap (so, nv50->sampler[i]->tsc, 8);
|
||||
}
|
||||
|
||||
so_method(so, tesla, 0x1440, 1); /* sync SIFC */
|
||||
so_data (so, 0);
|
||||
so_method(so, tesla, 0x1334, 1); /* flush TSC */
|
||||
so_data (so, 0);
|
||||
|
||||
so_ref(so, &nv50->state.tsc_upload);
|
||||
so_ref(NULL, &so);
|
||||
}
|
||||
|
|
@ -384,3 +394,33 @@ viewport_uptodate:
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void nv50_so_init_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_stateobj *so,
|
||||
struct nouveau_bo *bo, unsigned reloc, unsigned size)
|
||||
{
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
|
||||
so_method(so, eng2d, NV50_2D_DST_FORMAT, 2);
|
||||
so_data (so, NV50_2D_DST_FORMAT_R8_UNORM);
|
||||
so_data (so, 1);
|
||||
so_method(so, eng2d, NV50_2D_DST_PITCH, 5);
|
||||
so_data (so, 262144);
|
||||
so_data (so, 65536);
|
||||
so_data (so, 1);
|
||||
so_reloc (so, bo, 0, reloc | NOUVEAU_BO_WR | NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, bo, 0, reloc | NOUVEAU_BO_WR | NOUVEAU_BO_LOW, 0, 0);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_UNK0800, 2);
|
||||
so_data (so, 0);
|
||||
so_data (so, NV50_2D_SIFC_FORMAT_R8_UNORM);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_WIDTH, 10);
|
||||
so_data (so, size);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,24 +98,24 @@ nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so,
|
|||
void
|
||||
nv50_tex_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so;
|
||||
int unit, push;
|
||||
unsigned i, unit, push;
|
||||
|
||||
push = nv50->miptree_nr * 11;
|
||||
push += MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2;
|
||||
push = MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2 + 23 + 6;
|
||||
so = so_new(nv50->miptree_nr * 9 + push, nv50->miptree_nr + 2);
|
||||
|
||||
so = so_new(push, nv50->miptree_nr * 2);
|
||||
for (unit = 0; unit < nv50->miptree_nr; unit++) {
|
||||
nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM,
|
||||
nv50->miptree_nr * 8 * 4);
|
||||
|
||||
for (i = 0, unit = 0; unit < nv50->miptree_nr; ++unit) {
|
||||
struct nv50_miptree *mt = nv50->miptree[unit];
|
||||
|
||||
if (!mt)
|
||||
continue;
|
||||
|
||||
so_method(so, tesla, NV50TCL_CB_ADDR, 1);
|
||||
so_data (so, ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT) |
|
||||
NV50_CB_TIC);
|
||||
so_method(so, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
|
||||
if (nv50_tex_construct(nv50, so, mt, unit)) {
|
||||
NOUVEAU_ERR("failed tex validate\n");
|
||||
so_ref(NULL, &so);
|
||||
|
|
@ -123,17 +123,25 @@ nv50_tex_validate(struct nv50_context *nv50)
|
|||
}
|
||||
|
||||
so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
|
||||
so_data (so, (unit << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
|
||||
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
|
||||
NV50TCL_SET_SAMPLER_TEX_VALID);
|
||||
so_data (so, (i++ << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
|
||||
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
|
||||
NV50TCL_SET_SAMPLER_TEX_VALID);
|
||||
}
|
||||
|
||||
for (; unit < nv50->state.miptree_nr; unit++) {
|
||||
so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
|
||||
so_data (so,
|
||||
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
|
||||
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
|
||||
}
|
||||
|
||||
/* not sure if the following really do what I think: */
|
||||
so_method(so, tesla, 0x1440, 1); /* sync SIFC */
|
||||
so_data (so, 0);
|
||||
so_method(so, tesla, 0x1330, 1); /* flush TIC */
|
||||
so_data (so, 0);
|
||||
so_method(so, tesla, 0x1338, 1); /* flush texture caches */
|
||||
so_data (so, 0x20);
|
||||
|
||||
so_ref(so, &nv50->state.tic_upload);
|
||||
so_ref(NULL, &so);
|
||||
nv50->state.miptree_nr = nv50->miptree_nr;
|
||||
|
|
|
|||
|
|
@ -139,10 +139,6 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
|
|||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, 0x142c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, 0x1440, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, 0x1334, 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue