mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-08 15:00:11 +01:00
nouveau: avoid running out of relocs
- Added flush notify functions for NV30 and NV40. - Flushing mid frame will call flush notify, which will resubmit all relocs. - We don't try to recover from reloc failure yet.
This commit is contained in:
parent
2677f199a5
commit
41b52aa336
11 changed files with 76 additions and 18 deletions
|
|
@ -112,20 +112,30 @@ so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
|
|||
{
|
||||
struct nouveau_pushbuf *pb = chan->pushbuf;
|
||||
unsigned nr, i;
|
||||
int ret = 0;
|
||||
|
||||
nr = so->cur - so->push;
|
||||
if (pb->remaining < nr)
|
||||
nouveau_pushbuf_flush(chan, nr);
|
||||
/* This will flush if we need space.
|
||||
* We don't actually need the marker.
|
||||
*/
|
||||
if ((ret = nouveau_pushbuf_marker_emit(chan, nr, so->cur_reloc))) {
|
||||
debug_printf("so_emit failed marker emit with error %d\n", ret);
|
||||
return;
|
||||
}
|
||||
pb->remaining -= nr;
|
||||
|
||||
memcpy(pb->cur, so->push, nr * 4);
|
||||
for (i = 0; i < so->cur_reloc; i++) {
|
||||
struct nouveau_stateobj_reloc *r = &so->reloc[i];
|
||||
|
||||
nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
|
||||
if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
|
||||
r->bo, r->data, 0, r->flags,
|
||||
r->vor, r->tor);
|
||||
r->vor, r->tor))) {
|
||||
debug_printf("so_emit failed reloc with error %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
pb->cur += nr;
|
||||
}
|
||||
|
||||
|
|
@ -134,26 +144,45 @@ so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
|
|||
{
|
||||
struct nouveau_pushbuf *pb = chan->pushbuf;
|
||||
unsigned i;
|
||||
int ret = 0;
|
||||
|
||||
if (!so)
|
||||
return;
|
||||
|
||||
i = so->cur_reloc << 1;
|
||||
if (pb->remaining < i)
|
||||
nouveau_pushbuf_flush(chan, i);
|
||||
/* This will flush if we need space.
|
||||
* We don't actually need the marker.
|
||||
*/
|
||||
if ((ret = nouveau_pushbuf_marker_emit(chan, i, i))) {
|
||||
debug_printf("so_emit_reloc_markers failed marker emit with" \
|
||||
"error %d\n", ret);
|
||||
return;
|
||||
}
|
||||
pb->remaining -= i;
|
||||
|
||||
for (i = 0; i < so->cur_reloc; i++) {
|
||||
struct nouveau_stateobj_reloc *r = &so->reloc[i];
|
||||
|
||||
nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet, 0,
|
||||
if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
|
||||
r->packet, 0,
|
||||
(r->flags & (NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_GART |
|
||||
NOUVEAU_BO_RDWR)) |
|
||||
NOUVEAU_BO_DUMMY, 0, 0);
|
||||
nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data, 0,
|
||||
NOUVEAU_BO_DUMMY, 0, 0))) {
|
||||
debug_printf("so_emit_reloc_markers failed reloc" \
|
||||
"with error %d\n", ret);
|
||||
pb->remaining += ((so->cur_reloc - i) << 1);
|
||||
return;
|
||||
}
|
||||
if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
|
||||
r->data, 0,
|
||||
r->flags | NOUVEAU_BO_DUMMY,
|
||||
r->vor, r->tor);
|
||||
r->vor, r->tor))) {
|
||||
debug_printf("so_emit_reloc_markers failed reloc" \
|
||||
"with error %d\n", ret);
|
||||
pb->remaining += ((so->cur_reloc - i) << 1) - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
|
|||
assert(sub_w == w || util_is_pot(sub_w));
|
||||
assert(sub_h == h || util_is_pot(sub_h));
|
||||
|
||||
MARK_RING (chan, 8 + ((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*17, 2 +
|
||||
((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*2);
|
||||
|
||||
BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
|
||||
OUT_RELOCo(chan, dst_bo,
|
||||
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
|
|
@ -202,7 +205,7 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx,
|
|||
unsigned src_offset = src->offset + sy * src_pitch +
|
||||
sx * pf_get_blocksize(src->texture->format);
|
||||
|
||||
WAIT_RING (chan, 3 + ((h / 2047) + 1) * 9);
|
||||
MARK_RING (chan, 3 + ((h / 2047) + 1) * 9, 2 + ((h / 2047) + 1) * 2);
|
||||
BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
|
||||
OUT_RELOCo(chan, src_bo,
|
||||
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
|
||||
|
|
@ -250,7 +253,7 @@ nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
|
|||
if (format < 0)
|
||||
return 1;
|
||||
|
||||
WAIT_RING (chan, 12);
|
||||
MARK_RING (chan, 12, 4);
|
||||
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
|
||||
OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
|
||||
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
|
|
@ -315,7 +318,7 @@ nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
|
|||
gdirect_format = nv04_rect_format(dst->format);
|
||||
assert(gdirect_format >= 0);
|
||||
|
||||
WAIT_RING (chan, 16);
|
||||
MARK_RING (chan, 16, 4);
|
||||
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
|
||||
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ nv30_create(struct pipe_screen *pscreen, unsigned pctx_id)
|
|||
nv30->pipe.is_texture_referenced = nouveau_is_texture_referenced;
|
||||
nv30->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;
|
||||
|
||||
screen->base.channel->user_private = nv30;
|
||||
screen->base.channel->flush_notify = nv30_state_flush_notify;
|
||||
|
||||
nv30_init_query_functions(nv30);
|
||||
nv30_init_surface_functions(nv30);
|
||||
nv30_init_state_functions(nv30);
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ extern void nv30_fragtex_bind(struct nv30_context *);
|
|||
/* nv30_state.c and friends */
|
||||
extern boolean nv30_state_validate(struct nv30_context *nv30);
|
||||
extern void nv30_state_emit(struct nv30_context *nv30);
|
||||
extern void nv30_state_flush_notify(struct nouveau_channel *chan);
|
||||
extern struct nv30_state_entry nv30_state_rasterizer;
|
||||
extern struct nv30_state_entry nv30_state_scissor;
|
||||
extern struct nv30_state_entry nv30_state_stipple;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ nv30_state_emit(struct nv30_context *nv30)
|
|||
struct nouveau_channel *chan = nv30->screen->base.channel;
|
||||
struct nv30_state *state = &nv30->state;
|
||||
struct nv30_screen *screen = nv30->screen;
|
||||
unsigned i, samplers;
|
||||
unsigned i;
|
||||
uint64_t states;
|
||||
|
||||
if (nv30->pctx_id != screen->cur_pctx) {
|
||||
|
|
@ -63,6 +63,14 @@ nv30_state_emit(struct nv30_context *nv30)
|
|||
}
|
||||
|
||||
state->dirty = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv30_state_flush_notify(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv30_context *nv30 = chan->user_private;
|
||||
struct nv30_state *state = &nv30->state;
|
||||
unsigned i, samplers;
|
||||
|
||||
so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]);
|
||||
for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ nv40_create(struct pipe_screen *pscreen, unsigned pctx_id)
|
|||
nv40->pipe.is_texture_referenced = nouveau_is_texture_referenced;
|
||||
nv40->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;
|
||||
|
||||
screen->base.channel->user_private = nv40;
|
||||
screen->base.channel->flush_notify = nv40_state_flush_notify;
|
||||
|
||||
nv40_init_query_functions(nv40);
|
||||
nv40_init_surface_functions(nv40);
|
||||
nv40_init_state_functions(nv40);
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ extern void nv40_fragtex_bind(struct nv40_context *);
|
|||
extern boolean nv40_state_validate(struct nv40_context *nv40);
|
||||
extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40);
|
||||
extern void nv40_state_emit(struct nv40_context *nv40);
|
||||
extern void nv40_state_flush_notify(struct nouveau_channel *chan);
|
||||
extern struct nv40_state_entry nv40_state_rasterizer;
|
||||
extern struct nv40_state_entry nv40_state_scissor;
|
||||
extern struct nv40_state_entry nv40_state_stipple;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ nv40_state_emit(struct nv40_context *nv40)
|
|||
struct nouveau_channel *chan = nv40->screen->base.channel;
|
||||
struct nv40_state *state = &nv40->state;
|
||||
struct nv40_screen *screen = nv40->screen;
|
||||
unsigned i, samplers;
|
||||
unsigned i;
|
||||
uint64_t states;
|
||||
|
||||
if (nv40->pctx_id != screen->cur_pctx) {
|
||||
|
|
@ -87,6 +87,14 @@ nv40_state_emit(struct nv40_context *nv40)
|
|||
}
|
||||
|
||||
state->dirty = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv40_state_flush_notify(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv40_context *nv40 = chan->user_private;
|
||||
struct nv40_state *state = &nv40->state;
|
||||
unsigned i, samplers;
|
||||
|
||||
so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]);
|
||||
for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
|
|||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
|
||||
WAIT_RING (chan, 5);
|
||||
MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4);
|
||||
OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
|
|||
return 1;
|
||||
|
||||
if (!bo->tile_flags) {
|
||||
MARK_RING (chan, 9, 2); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, eng2d, mthd, 2);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 1);
|
||||
|
|
@ -72,6 +73,7 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
|
|||
OUT_RELOCh(chan, bo, ps->offset, flags);
|
||||
OUT_RELOCl(chan, bo, ps->offset, flags);
|
||||
} else {
|
||||
MARK_RING (chan, 11, 2); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, eng2d, mthd, 5);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 0);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
|
|||
while (height) {
|
||||
int line_count = height > 2047 ? 2047 : height;
|
||||
|
||||
WAIT_RING (chan, 15);
|
||||
MARK_RING (chan, 15, 4); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
|
||||
OUT_RELOCh(chan, src_bo, src_offset, src_reloc);
|
||||
|
|
@ -265,7 +265,7 @@ nv50_upload_sifc(struct nv50_context *nv50,
|
|||
|
||||
reloc |= NOUVEAU_BO_WR;
|
||||
|
||||
WAIT_RING (chan, 32);
|
||||
MARK_RING (chan, 32, 2); /* flush on lack of space or relocs */
|
||||
|
||||
if (bo->tile_flags) {
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue