aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-09-13 12:58:19 +0200
committerMarek Olšák <[email protected]>2010-09-13 13:26:35 +0200
commit0392e48867c27f2aa445c5c9b35f4a52ecef2f2d (patch)
tree22e037ba8ae68b7b0e869a04db0b40a4009cbe66 /src
parent501d43028e8e551dd36ede00fb85095183c32037 (diff)
r300g: fix SWTCL
https://bugs.freedesktop.org/show_bug.cgi?id=29901
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r300/r300_context.h12
-rw-r--r--src/gallium/drivers/r300/r300_emit.c2
-rw-r--r--src/gallium/drivers/r300/r300_flush.c2
-rw-r--r--src/gallium/drivers/r300/r300_render.c124
4 files changed, 99 insertions, 41 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 8f0e86fd378..8eddf72b704 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -447,9 +447,17 @@ struct r300_context {
struct r300_winsys_cs *cs;
/* Screen. */
struct r300_screen *screen;
+
/* Draw module. Used mostly for SW TCL. */
struct draw_context* draw;
+ /* Vertex buffer for SW TCL. */
+ struct pipe_resource* vbo;
+ /* Offset and size into the SW TCL VBO. */
+ size_t draw_vbo_offset;
size_t draw_vbo_size;
+ /* Whether the VBO must not be flushed. */
+ boolean draw_vbo_locked;
+
/* Accelerated blit support. */
struct blitter_context* blitter;
/* Stencil two-sided reference value fallback. */
@@ -457,14 +465,10 @@ struct r300_context {
/* For translating vertex buffers having incompatible vertex layout. */
struct r300_translate_context tran;
- /* Vertex buffer for rendering. */
- struct pipe_resource* vbo;
/* The KIL opcode needs the first texture unit to be enabled
* on r3xx-r4xx. In order to calm down the CS checker, we bind this
* dummy texture there. */
struct r300_sampler_view *texkill_sampler;
- /* Offset into the VBO. */
- size_t vbo_offset;
/* The currently active query. */
struct r300_query *query_current;
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 3eebd2a9be6..b2b34c3efcb 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -847,7 +847,7 @@ void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed)
OUT_CS(1 | (!indexed ? R300_VC_FORCE_PREFETCH : 0));
OUT_CS(r300->vertex_info.size |
(r300->vertex_info.size << 8));
- OUT_CS(r300->vbo_offset);
+ OUT_CS(r300->draw_vbo_offset);
OUT_CS_BUF_RELOC(r300->vbo, 0, r300_buffer(r300->vbo)->domain, 0);
END_CS;
}
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 2b5d2e42ba5..1afd27f0938 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -43,7 +43,7 @@ static void r300_flush(struct pipe_context* pipe,
u_upload_flush(r300->upload_vb);
u_upload_flush(r300->upload_ib);
- if (r300->draw)
+ if (r300->draw && !r300->draw_vbo_locked)
r300_draw_flush_vbuf(r300);
if (r300->dirty_hw) {
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index aa45ee3abfd..6c4cd6c59bd 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -179,26 +179,20 @@ enum r300_prepare_flags {
/**
* Check if the requested number of dwords is available in the CS and
- * if not, flush. Then validate buffers and emit dirty state.
+ * if not, flush.
* \param r300 The context.
* \param flags See r300_prepare_flags.
- * \param index_buffer The index buffer to validate. The parameter may be NULL.
* \param cs_dwords The number of dwords to reserve in CS.
- * \param aos_offset The offset passed to emit_aos.
- * \param index_bias The index bias to emit.
+ * \return TRUE if the CS was flushed
*/
-static boolean r300_prepare_for_rendering(struct r300_context *r300,
- enum r300_prepare_flags flags,
- struct pipe_resource *index_buffer,
- unsigned cs_dwords,
- int aos_offset,
- int index_bias)
+static boolean r300_reserve_cs_dwords(struct r300_context *r300,
+ enum r300_prepare_flags flags,
+ unsigned 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;
- boolean indexed = flags & PREP_INDEXED;
boolean hw_index_bias = r500_index_bias_supported(r300);
/* Add dirty state, index offset, and AOS. */
@@ -223,8 +217,32 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300,
flushed = TRUE;
}
+ return flushed;
+}
+
+/**
+ * Validate buffers and emit dirty state.
+ * \param r300 The context.
+ * \param flags See r300_prepare_flags.
+ * \param index_buffer The index buffer to validate. The parameter may be NULL.
+ * \param aos_offset The offset passed to emit_aos.
+ * \param index_bias The index bias to emit.
+ * \return TRUE if rendering should be skipped
+ */
+static boolean r300_emit_states(struct r300_context *r300,
+ enum r300_prepare_flags flags,
+ struct pipe_resource *index_buffer,
+ int aos_offset,
+ int index_bias)
+{
+ boolean first_draw = flags & PREP_FIRST_DRAW;
+ boolean emit_aos = flags & PREP_EMIT_AOS;
+ boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL;
+ boolean indexed = flags & PREP_INDEXED;
+ boolean hw_index_bias = r500_index_bias_supported(r300);
+
/* Validate buffers and emit dirty state if needed. */
- if (first_draw || flushed) {
+ if (first_draw) {
if (!r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS,
index_buffer)) {
fprintf(stderr, "r300: CS space validation failed. "
@@ -250,6 +268,30 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300,
return TRUE;
}
+/**
+ * Check if the requested number of dwords is available in the CS and
+ * if not, flush. Then validate buffers and emit dirty state.
+ * \param r300 The context.
+ * \param flags See r300_prepare_flags.
+ * \param index_buffer The index buffer to validate. The parameter may be NULL.
+ * \param cs_dwords The number of dwords to reserve in CS.
+ * \param aos_offset The offset passed to emit_aos.
+ * \param index_bias The index bias to emit.
+ * \return TRUE if rendering should be skipped
+ */
+static boolean r300_prepare_for_rendering(struct r300_context *r300,
+ enum r300_prepare_flags flags,
+ struct pipe_resource *index_buffer,
+ unsigned cs_dwords,
+ int aos_offset,
+ int index_bias)
+{
+ if (r300_reserve_cs_dwords(r300, flags, cs_dwords))
+ flags |= PREP_FIRST_DRAW;
+
+ return r300_emit_states(r300, flags, index_buffer, aos_offset, index_bias);
+}
+
static boolean immd_is_good_idea(struct r300_context *r300,
unsigned count)
{
@@ -675,7 +717,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
struct pipe_transfer *ib_transfer = NULL;
unsigned count = info->count;
int i;
- void* indices = NULL;
+ void *indices = NULL;
+ boolean indexed = info->indexed && r300->index_buffer.buffer;
if (r300->skip_rendering) {
return;
@@ -687,6 +730,11 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
r300_update_derived_state(r300);
+ r300_reserve_cs_dwords(r300,
+ PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL |
+ (indexed ? PREP_INDEXED : 0),
+ indexed ? 256 : 6);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
if (r300->vertex_buffer[i].buffer) {
void *buf = pipe_buffer_map(pipe,
@@ -697,14 +745,16 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
}
}
- if (info->indexed && r300->index_buffer.buffer) {
+ if (indexed) {
indices = pipe_buffer_map(pipe, r300->index_buffer.buffer,
PIPE_TRANSFER_READ, &ib_transfer);
}
draw_set_mapped_index_buffer(r300->draw, indices);
+ r300->draw_vbo_locked = TRUE;
draw_vbo(r300->draw, info);
+ r300->draw_vbo_locked = FALSE;
/* XXX Not sure whether this is the best fix.
* It prevents CS from being rejected and weird assertion failures. */
@@ -718,7 +768,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
}
}
- if (ib_transfer) {
+ if (indexed) {
pipe_buffer_unmap(pipe, r300->index_buffer.buffer, ib_transfer);
draw_set_mapped_index_buffer(r300->draw, NULL);
}
@@ -738,7 +788,6 @@ struct r300_render {
unsigned hwprim;
/* VBO */
- size_t vbo_offset;
size_t vbo_max_used;
void * vbo_ptr;
@@ -769,18 +818,19 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render,
struct pipe_screen* screen = r300->context.screen;
size_t size = (size_t)vertex_size * (size_t)count;
- if (size + r300render->vbo_offset > r300->draw_vbo_size)
+ DBG(r300, DBG_DRAW, "r300: render_allocate_vertices (size: %d)\n", size);
+
+ if (size + r300->draw_vbo_offset > r300->draw_vbo_size)
{
pipe_resource_reference(&r300->vbo, NULL);
r300->vbo = pipe_buffer_create(screen,
PIPE_BIND_VERTEX_BUFFER,
R300_MAX_DRAW_VBO_SIZE);
- r300render->vbo_offset = 0;
+ r300->draw_vbo_offset = 0;
r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE;
}
r300render->vertex_size = vertex_size;
- r300->vbo_offset = r300render->vbo_offset;
return (r300->vbo) ? TRUE : FALSE;
}
@@ -792,6 +842,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render)
assert(!r300render->vbo_transfer);
+ DBG(r300, DBG_DRAW, "r300: render_map_vertices\n");
+
r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context,
r300->vbo,
PIPE_TRANSFER_WRITE,
@@ -799,7 +851,7 @@ static void* r300_render_map_vertices(struct vbuf_render* render)
assert(r300render->vbo_ptr);
- return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset);
+ return ((uint8_t*)r300render->vbo_ptr + r300->draw_vbo_offset);
}
static void r300_render_unmap_vertices(struct vbuf_render* render,
@@ -812,6 +864,8 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
assert(r300render->vbo_transfer);
+ DBG(r300, DBG_DRAW, "r300: render_unmap_vertices\n");
+
r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
r300render->vertex_size * (max + 1));
pipe_buffer_unmap(context, r300->vbo, r300render->vbo_transfer);
@@ -822,8 +876,11 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
static void r300_render_release_vertices(struct vbuf_render* render)
{
struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
- r300render->vbo_offset += r300render->vbo_max_used;
+ DBG(r300, DBG_DRAW, "r300: render_release_vertices\n");
+
+ r300->draw_vbo_offset += r300render->vbo_max_used;
r300render->vbo_max_used = 0;
}
@@ -851,13 +908,13 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
CS_LOCALS(r300);
(void) i; (void) ptr;
- if (!r300_prepare_for_rendering(r300,
- PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
- NULL, dwords, 0, 0))
- return;
-
DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count);
+ if (!r300_emit_states(r300,
+ PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
+ NULL, 0, 0))
+ return;
+
/* Uncomment to dump all VBOs rendered through this interface.
* Slow and noisy!
ptr = pipe_buffer_map(&r300render->r300->context,
@@ -893,7 +950,7 @@ static void r300_render_draw_elements(struct vbuf_render* render,
struct r300_context* r300 = r300render->r300;
int i;
unsigned end_cs_dwords;
- unsigned max_index = (r300->draw_vbo_size - r300render->vbo_offset) /
+ unsigned max_index = (r300->draw_vbo_size - r300->draw_vbo_offset) /
(r300render->r300->vertex_info.size * 4) - 1;
unsigned short_count;
unsigned free_dwords;
@@ -901,15 +958,14 @@ static void r300_render_draw_elements(struct vbuf_render* render,
CS_LOCALS(r300);
DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count);
- /* Reserve at least 256 dwords.
- *
- * Below we manage the CS space manually because there may be more
- * indices than it can fit in CS. */
- if (!r300_prepare_for_rendering(r300,
+ if (!r300_emit_states(r300,
PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
- NULL, 256, 0, 0))
+ NULL, 0, 0))
return;
+ /* Below we manage the CS space manually because there may be more
+ * indices than it can fit in CS. */
+
end_cs_dwords = r300_get_num_cs_end_dwords(r300);
while (count) {
@@ -973,8 +1029,6 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300)
r300render->base.release_vertices = r300_render_release_vertices;
r300render->base.destroy = r300_render_destroy;
- r300render->vbo_offset = 0;
-
return &r300render->base;
}