r300g/swtcl: handle large index count properly
authorMarek Olšák <maraeo@gmail.com>
Wed, 26 May 2010 20:21:21 +0000 (22:21 +0200)
committerMarek Olšák <maraeo@gmail.com>
Wed, 26 May 2010 20:39:19 +0000 (22:39 +0200)
This fixes piglit/draw-elements.

src/gallium/drivers/r300/r300_render.c

index a5d129449e61efd925748219b449d1aea8a1065e..c289c3d0e5ddaf068a3dfa2830e31c505e2ce9dc 100644 (file)
@@ -148,12 +148,14 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
                                        struct pipe_resource *index_buffer,
                                        unsigned cs_dwords,
                                        unsigned aos_offset,
-                                       int index_bias)
+                                       int index_bias,
+                                       unsigned *end_cs_dwords)
 {
     boolean flushed = FALSE;
     boolean first_draw = flags & PREP_FIRST_DRAW;
     boolean emit_aos = flags & PREP_EMIT_AOS;
     boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL;
+    unsigned end_dwords = 0;
 
     /* Stencil ref fallback. */
     if (r300->stencil_ref_bf_fallback) {
@@ -175,7 +177,9 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
     }
 
     /* Emitted in flush. */
-    cs_dwords += 26; /* emit_query_end */
+    end_dwords += 26; /* emit_query_end */
+
+    cs_dwords += end_dwords;
 
     /* Reserve requested CS space. */
     if (!r300_check_cs(r300, cs_dwords)) {
@@ -193,6 +197,9 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
         if (emit_aos_swtcl)
             r300_emit_aos_swtcl(r300, flags & PREP_INDEXED);
     }
+
+    if (end_cs_dwords)
+        *end_cs_dwords = end_dwords;
 }
 
 static boolean immd_is_good_idea(struct r300_context *r300,
@@ -294,7 +301,7 @@ static void r500_emit_draw_arrays_immediate(struct r300_context *r300,
 
     dwords = 9 + count * vertex_size;
 
-    r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
+    r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
 
     BEGIN_CS(dwords);
     OUT_CS_REG(R300_GA_COLOR_CONTROL,
@@ -626,7 +633,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
     /* 15 dwords for emit_draw_elements */
     r300_prepare_for_rendering(r300,
         PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
-        indexBuffer, 15, 0, indexBias);
+        indexBuffer, 15, 0, indexBias, NULL);
 
     u_upload_flush(r300->upload_vb);
     u_upload_flush(r300->upload_ib);
@@ -647,7 +654,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
             if (count) {
                 r300_prepare_for_rendering(r300,
                     PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
-                    indexBuffer, 15, 0, indexBias);
+                    indexBuffer, 15, 0, indexBias, NULL);
             }
         } while (count);
     }
@@ -694,7 +701,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
     } else {
         /* 9 spare dwords for emit_draw_arrays. */
         r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
-                               NULL, 9, start, 0);
+                               NULL, 9, start, 0, NULL);
 
         if (alt_num_verts || count <= 65535) {
             r300->emit_draw_arrays(r300, mode, count);
@@ -710,7 +717,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
                 if (count) {
                     r300_prepare_for_rendering(r300,
                         PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
-                        start, 0);
+                        start, 0, NULL);
                 }
             } while (count);
         }
@@ -953,7 +960,7 @@ static void r500_render_draw_arrays(struct vbuf_render* render,
     (void) i; (void) ptr;
 
     r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
-                               NULL, dwords, 0, 0);
+                               NULL, dwords, 0, 0, NULL);
 
     DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
 
@@ -991,30 +998,53 @@ static void r500_render_draw_elements(struct vbuf_render* render,
     struct r300_render* r300render = r300_render(render);
     struct r300_context* r300 = r300render->r300;
     int i;
-    unsigned dwords = 6 + (count+1)/2;
+    unsigned end_cs_dwords;
     unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) /
                          (r300render->r300->vertex_info.size * 4) - 1;
+    unsigned short_count;
+    struct r300_cs_info cs_info;
 
     CS_LOCALS(r300);
 
+    /* Reserve at least 256 dwords.
+     *
+     * Below we manage the CS space manually because there may be more
+     * indices than it can fit in CS. */
     r300_prepare_for_rendering(r300,
         PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
-        NULL, dwords, 0, 0);
+        NULL, 256, 0, 0, &end_cs_dwords);
+
+    while (count) {
+        r300->rws->get_cs_info(r300->rws, &cs_info);
+
+        short_count = MIN2(count, (cs_info.free - end_cs_dwords - 6) * 2);
+
+        BEGIN_CS(6 + (short_count+1)/2);
+        OUT_CS_REG(R300_GA_COLOR_CONTROL,
+                r300_provoking_vertex_fixes(r300, r300render->prim));
+        OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index);
+        OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (short_count+1)/2);
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (short_count << 16) |
+               r300render->hwprim);
+        for (i = 0; i < short_count-1; i += 2) {
+            OUT_CS(indices[i+1] << 16 | indices[i]);
+        }
+        if (short_count % 2) {
+            OUT_CS(indices[short_count-1]);
+        }
+        END_CS;
 
-    BEGIN_CS(dwords);
-    OUT_CS_REG(R300_GA_COLOR_CONTROL,
-            r300_provoking_vertex_fixes(r300, r300render->prim));
-    OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index);
-    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2);
-    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
-           r300render->hwprim);
-    for (i = 0; i < count-1; i += 2) {
-        OUT_CS(indices[i+1] << 16 | indices[i]);
-    }
-    if (count % 2) {
-        OUT_CS(indices[count-1]);
+        /* OK now subtract the emitted indices and see if we need to emit
+         * another draw packet. */
+        indices += short_count;
+        count -= short_count;
+
+        if (count) {
+            r300_prepare_for_rendering(r300,
+                PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
+                NULL, 256, 0, 0, &end_cs_dwords);
+        }
     }
-    END_CS;
 }
 
 static void r300_render_draw_arrays(struct vbuf_render* render,