summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-03-13 06:07:33 +0100
committerMarek Olšák <maraeo@gmail.com>2010-03-13 18:23:27 +0100
commitbcec6d851ce6ec2d948f03e5a1adfb5871e4e627 (patch)
tree9c989e991db8886d7c39e982be108d837ef45f33 /src
parente31bca139f720396d1a1639b46d37aee4fd9736e (diff)
r300g: refrain from using immediate mode if it causes slowdown
E.g. when mapping buffers could flush CS or cause waiting for a busy buffer. The side effect of this is it also fixes progs/demos/arbocclude however a separate fix should be proposed to address this issue in other cases it might occur.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r300/r300_render.c33
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_buffer.c14
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_winsys.h3
3 files changed, 48 insertions, 2 deletions
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index ccf39876a5..971e7f3521 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -131,9 +131,38 @@ static boolean r300_reserve_cs_space(struct r300_context *r300,
}
static boolean immd_is_good_idea(struct r300_context *r300,
- unsigned count)
+ unsigned count)
{
- return count <= 4;
+ struct pipe_vertex_element* velem;
+ struct pipe_vertex_buffer* vbuf;
+ boolean checked[PIPE_MAX_ATTRIBS] = {0};
+ unsigned vertex_element_count = r300->velems->count;
+ unsigned i, vbi;
+
+ if (count > 4) {
+ return FALSE;
+ }
+
+ /* We shouldn't map buffers referenced by CS, busy buffers,
+ * and ones placed in VRAM. */
+ /* XXX Check for VRAM buffers. */
+ for (i = 0; i < vertex_element_count; i++) {
+ velem = &r300->velems->velem[i];
+ vbi = velem->vertex_buffer_index;
+
+ if (!checked[vbi]) {
+ vbuf = &r300->vertex_buffer[vbi];
+
+ if (r300->winsys->is_buffer_referenced(r300->winsys,
+ vbuf->buffer)) {
+ /* It's a very bad idea to map it... */
+ return FALSE;
+ }
+ checked[vbi] = TRUE;
+ }
+ }
+
+ return TRUE;
}
static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
index daa032af6f..25b58b2926 100644
--- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
+++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
@@ -213,6 +213,18 @@ static void radeon_buffer_unmap(struct pipe_winsys *ws,
}
}
+static boolean radeon_is_buffer_referenced(struct radeon_winsys *ws,
+ struct pipe_buffer *buffer)
+{
+ struct radeon_pipe_buffer *radeon_buffer =
+ (struct radeon_pipe_buffer*)buffer;
+ uint32_t domain;
+
+ /* Referenced by CS or HW. */
+ return radeon_bo_is_referenced_by_cs(radeon_buffer->bo, ws->priv->cs) ||
+ radeon_bo_is_busy(radeon_buffer->bo, &domain);
+}
+
static void radeon_buffer_set_tiling(struct radeon_winsys *ws,
struct pipe_buffer *buffer,
uint32_t pitch,
@@ -370,5 +382,7 @@ struct radeon_winsys* radeon_pipe_winsys(int fd)
radeon_ws->buffer_from_handle = radeon_buffer_from_handle;
radeon_ws->buffer_get_handle = radeon_buffer_get_handle;
+ radeon_ws->is_buffer_referenced = radeon_is_buffer_referenced;
+
return radeon_ws;
}
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h
index 37eeb45979..887a381cc4 100644
--- a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h
+++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h
@@ -118,6 +118,9 @@ struct radeon_winsys {
uint32_t pitch,
boolean microtiled,
boolean macrotiled);
+
+ boolean (*is_buffer_referenced)(struct radeon_winsys *winsys,
+ struct pipe_buffer *buffer);
};
#endif