summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-02-22 15:11:29 +0100
committerCorbin Simpson <[email protected]>2010-02-24 17:11:47 -0800
commite6632b4bf7cba5fe8a77d54635a3b617fa67185f (patch)
treec51f40deebfe74d2006082b6d956ff95b3373d1a /src/gallium/drivers
parentb7041db8f8af07d3eec68fb259e2f17ceb8bd421 (diff)
r300g: prevent CS overflow when emitting the draw packets
Signed-off-by: Corbin Simpson <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/r300/r300_emit.c29
-rw-r--r--src/gallium/drivers/r300/r300_emit.h2
-rw-r--r--src/gallium/drivers/r300/r300_render.c42
3 files changed, 55 insertions, 18 deletions
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index f7dcd8dc52f..2d8801c08ad 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -1076,16 +1076,10 @@ validate:
}
}
-/* Emit all dirty state. */
-void r300_emit_dirty_state(struct r300_context* r300)
+unsigned r300_get_num_dirty_dwords(struct r300_context *r300)
{
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_atom* atom;
- unsigned i, dwords = 1024;
- int dirty_tex = 0;
-
- /* Check the required number of dwords against the space remaining in the
- * current CS object. If we need more, then flush. */
+ unsigned dwords = 0;
foreach(atom, &r300->atom_list) {
if (atom->dirty || atom->always_dirty) {
@@ -1093,12 +1087,19 @@ void r300_emit_dirty_state(struct r300_context* r300)
}
}
- /* Make sure we have at least 2*1024 spare dwords. */
- /* XXX It would be nice to know the number of dwords we really need to
- * XXX emit. */
- while (!r300->winsys->check_cs(r300->winsys, dwords)) {
- r300->context.flush(&r300->context, 0, NULL);
- }
+ /* XXX This is the compensation for the non-atomized states. */
+ dwords += 2048;
+
+ return dwords;
+}
+
+/* Emit all dirty state. */
+void r300_emit_dirty_state(struct r300_context* r300)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_atom* atom;
+ unsigned i;
+ int dirty_tex = 0;
if (r300->dirty_state & R300_NEW_QUERY) {
r300_emit_query_start(r300);
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 6b96d9b57c0..ff709a05957 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -90,6 +90,8 @@ void r300_emit_ztop_state(struct r300_context* r300, void* state);
void r300_flush_textures(struct r300_context* r300);
+unsigned r300_get_num_dirty_dwords(struct r300_context *r300);
+
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 648d884654f..ec72d6c3b52 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -118,6 +118,18 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
return color_control;
}
+/* Check if the requested number of dwords is available in the CS and
+ * if not, flush. Return TRUE if the flush occured. */
+static boolean r300_reserve_cs_space(struct r300_context *r300,
+ unsigned dwords)
+{
+ while (!r300->winsys->check_cs(r300->winsys, dwords)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ return TRUE;
+ }
+ return FALSE;
+}
+
static boolean immd_is_good_idea(struct r300_context *r300,
unsigned count)
{
@@ -132,7 +144,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
struct pipe_vertex_element* velem;
struct pipe_vertex_buffer* vbuf;
unsigned vertex_element_count = r300->vertex_element_count;
- unsigned i, v, vbi, dw, elem_offset;
+ unsigned i, v, vbi, dw, elem_offset, dwords;
/* Size of the vertex, in dwords. */
unsigned vertex_size = 0;
@@ -171,9 +183,12 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
}
}
+ dwords = 10 + count * vertex_size;
+
+ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords);
r300_emit_dirty_state(r300);
- BEGIN_CS(10 + count * vertex_size);
+ BEGIN_CS(dwords);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
@@ -400,8 +415,9 @@ void r300_draw_range_elements(struct pipe_context* pipe,
goto cleanup;
}
+ /* 128 dwords for emit_aos and emit_draw_elements */
+ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
r300_emit_dirty_state(r300);
-
r300_emit_aos(r300, 0);
if (alt_num_verts || count <= 65535) {
@@ -415,6 +431,12 @@ void r300_draw_range_elements(struct pipe_context* pipe,
start += short_count;
count -= short_count;
+
+ /* 16 spare dwords are enough for emit_draw_elements. */
+ if (count && r300_reserve_cs_space(r300, 16)) {
+ r300_emit_dirty_state(r300);
+ r300_emit_aos(r300, 0);
+ }
} while (count);
}
@@ -461,6 +483,9 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
return;
}
+ /* Make sure there are at least 128 spare dwords in the command buffer.
+ * (most of it being consumed by emit_aos) */
+ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
r300_emit_dirty_state(r300);
if (alt_num_verts || count <= 65535) {
@@ -474,6 +499,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
start += short_count;
count -= short_count;
+
+ /* Again, we emit both AOS and draw_arrays so there should be
+ * at least 128 spare dwords. */
+ if (count && r300_reserve_cs_space(r300, 128)) {
+ r300_emit_dirty_state(r300);
+ }
} while (count);
}
}
@@ -690,6 +721,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
CS_LOCALS(r300);
+ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2);
r300_emit_dirty_state(r300);
DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
@@ -708,12 +740,14 @@ static void r300_render_draw(struct vbuf_render* render,
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
int i;
+ unsigned dwords = 2 + (count+1)/2;
CS_LOCALS(r300);
+ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords);
r300_emit_dirty_state(r300);
- BEGIN_CS(2 + (count+1)/2);
+ BEGIN_CS(dwords);
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);