nv50: ensure enough room for state changes in current pushbuf
authorBen Skeggs <bskeggs@redhat.com>
Wed, 3 Mar 2010 04:43:21 +0000 (14:43 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 10 Mar 2010 06:29:58 +0000 (16:29 +1000)
Also allows the nv50_state_validate() caller to request a minimum amount
of space that itself requires, not all callers accurately use this yet
but the simple cases are now accounted for.

Rendering will also be dropped on the floor if validate fails now.

src/gallium/drivers/nv50/nv50_clear.c
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_state_validate.c
src/gallium/drivers/nv50/nv50_vbo.c

index e0b2d2880b00b1e42bfe7d02a3ba121ea06c208b..8afc95c9fc6b7942ce9e5bd974244f240861fffb 100644 (file)
@@ -36,7 +36,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,
        struct pipe_framebuffer_state *fb = &nv50->framebuffer;
        unsigned mode = 0, i;
 
-       if (!nv50_state_validate(nv50))
+       if (!nv50_state_validate(nv50, 64))
                return;
 
        if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
index 5fa39111148e7331736ac9c7c23f80faeb60f95d..ef0e99f0b126c361b7229d189214ff09b820087d 100644 (file)
@@ -229,7 +229,7 @@ extern void nv50_program_destroy(struct nv50_context *nv50,
                                 struct nv50_program *p);
 
 /* nv50_state_validate.c */
-extern boolean nv50_state_validate(struct nv50_context *nv50);
+extern boolean nv50_state_validate(struct nv50_context *nv50, unsigned dwords);
 extern void nv50_state_flush_notify(struct nouveau_channel *chan);
 
 extern void nv50_so_init_sifc(struct nv50_context *nv50,
index abdb9a55c859daca37351e131fc04f38e9f2d49b..b01a3d87de64b1a2c1550b276f923ff3bdc9afdf 100644 (file)
@@ -405,19 +405,11 @@ nv50_state_flush_notify(struct nouveau_channel *chan)
 }
 
 boolean
-nv50_state_validate(struct nv50_context *nv50)
+nv50_state_validate(struct nv50_context *nv50, unsigned nr_dwords)
 {
        struct nouveau_channel *chan = nv50->screen->base.channel;
-       int i;
-
-       if (nv50->screen->cur_ctx != nv50) {
-               for (i = 0; i < validate_list_len; i++) {
-                       if (nv50->state.hw[i])
-                               nv50->state.hw_dirty |= (1 << i);
-               }
-
-               nv50->screen->cur_ctx = nv50;
-       }
+       unsigned nr_relocs = 0;
+       int ret, i;
 
        for (i = 0; i < validate_list_len; i++) {
                struct state_validate *validate = &validate_list[i];
@@ -430,12 +422,37 @@ nv50_state_validate(struct nv50_context *nv50)
                if (!so)
                        continue;
 
+               nr_dwords += (so->total + so->cur);
+               nr_relocs += so->cur_reloc;
+
                so_ref(so, &nv50->state.hw[i]);
                so_ref(NULL, &so);
                nv50->state.hw_dirty |= (1 << i);
        }
        nv50->dirty = 0;
 
+       if (nv50->screen->cur_ctx != nv50) {
+               for (i = 0; i < validate_list_len; i++) {
+                       if (!nv50->state.hw[i] ||
+                           (nv50->state.hw_dirty & (1 << i)))
+                               continue;
+
+                       nr_dwords += (nv50->state.hw[i]->total +
+                                     nv50->state.hw[i]->cur);
+                       nr_relocs += nv50->state.hw[i]->cur_reloc;
+                       nv50->state.hw_dirty |= (1 << i);
+               }
+
+               nv50->screen->cur_ctx = nv50;
+       }
+
+       ret = MARK_RING(chan, nr_dwords, nr_relocs);
+       if (ret) {
+               debug_printf("MARK_RING(%d, %d) failed: %d\n",
+                            nr_dwords, nr_relocs, ret);
+               return FALSE;
+       }
+
        while (nv50->state.hw_dirty) {
                i = ffs(nv50->state.hw_dirty) - 1;
                nv50->state.hw_dirty &= ~(1 << i);
index 3e540013c4245656cf02d9dae3dbe5f9ad8844ab..ce2e479cfda551fa5df8280fa43ffb3f27e4e489 100644 (file)
@@ -425,7 +425,8 @@ nv50_draw_arrays_instanced(struct pipe_context *pipe,
        if (!NV50_USING_LOATHED_EDGEFLAG(nv50))
                nv50_upload_user_vbufs(nv50);
 
-       nv50_state_validate(nv50);
+       if (!nv50_state_validate(nv50, 0))
+               return;
 
        nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
 
@@ -477,7 +478,8 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
        struct nouveau_grobj *tesla = nv50->screen->tesla;
        boolean ret;
 
-       nv50_state_validate(nv50);
+       if (!nv50_state_validate(nv50, 11))
+               return;
 
        BEGIN_RING(chan, tesla, 0x142c, 1);
        OUT_RING  (chan, 0);
@@ -633,7 +635,8 @@ nv50_draw_elements_instanced(struct pipe_context *pipe,
        if (!NV50_USING_LOATHED_EDGEFLAG(nv50))
                nv50_upload_user_vbufs(nv50);
 
-       nv50_state_validate(nv50);
+       if (!nv50_state_validate(nv50, 0))
+               return;
 
        nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
 
@@ -677,7 +680,8 @@ nv50_draw_elements(struct pipe_context *pipe,
        struct pipe_screen *pscreen = pipe->screen;
        void *map;
        
-       nv50_state_validate(nv50);
+       if (!nv50_state_validate(nv50, 14))
+               return;
 
        BEGIN_RING(chan, tesla, 0x142c, 1);
        OUT_RING  (chan, 0);