nouveau: avoid running out of relocs
authorMaarten Maathuis <madman2003@gmail.com>
Fri, 4 Dec 2009 21:58:22 +0000 (22:58 +0100)
committerMaarten Maathuis <madman2003@gmail.com>
Mon, 14 Dec 2009 18:31:54 +0000 (19:31 +0100)
- 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.

src/gallium/drivers/nouveau/nouveau_stateobj.h
src/gallium/drivers/nv04/nv04_surface_2d.c
src/gallium/drivers/nv30/nv30_context.c
src/gallium/drivers/nv30/nv30_context.h
src/gallium/drivers/nv30/nv30_state_emit.c
src/gallium/drivers/nv40/nv40_context.c
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_state_emit.c
src/gallium/drivers/nv50/nv50_query.c
src/gallium/drivers/nv50/nv50_surface.c
src/gallium/drivers/nv50/nv50_transfer.c

index 62990f9b6a607333921dc4ecf16850f391095685..9aee9e495664e3c8b3caf97669106e2b729ff256 100644 (file)
@@ -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;
+               }
        }
 }
 
index 932893eef597bfc58ce0ad96338cc885e794670b..3020806c5d65735f8d6afab1d7faef720c99b597 100644 (file)
@@ -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);
index d8300fd69f647a95ed00ce0581deed5012707a3b..46a821a48b1f03b22e071120083e425d946918f8 100644 (file)
@@ -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);
index 8d49366dfcb813dd91e54812593e52caeb760466..6f44b1c7fe1a42cc07c73c459411f58325c0cfff 100644 (file)
@@ -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;
index 621b8846c8ed3835c97fd809ddfbe0dcba208e26..ac52d946f021232356e8912b47041080fe19d049 100644 (file)
@@ -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++) {
index 7f008274a4e301d5621234853afbfb036e51bb3e..eb9cce4c786718b45708de45a47eb83e2d8538a3 100644 (file)
@@ -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);
index a3d594167aad1c668c93ff74a85996220397a658..cf33b64a86dbb91b058bafce61522e0ffcbbbe54 100644 (file)
@@ -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;
index 198692965dc4ad3d482c2826161af03c04457524..ba0fbcb26a995585914ea7dafd4679e823f1a1e1 100644 (file)
@@ -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++) {
index 5305c93d59ab15de76094c8a14e667d8d2b335a2..268c9823f7d8887ceab9b3022662d61a6c372da8 100644 (file)
@@ -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);
index 6bf6f773b0c26b075282175c1d3292a1e3ddd753..79655fc08d5a6b782b33eadb5916d0a6697fed19 100644 (file)
@@ -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);
index 104d29a003ff1a01999e198528bc27174c413606..6240a0c757ad2ffff87646dcc5b558b9efbc4a3e 100644 (file)
@@ -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);