diff options
author | Marek Olšák <[email protected]> | 2010-03-13 06:07:33 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2010-03-13 18:23:27 +0100 |
commit | bcec6d851ce6ec2d948f03e5a1adfb5871e4e627 (patch) | |
tree | 9c989e991db8886d7c39e982be108d837ef45f33 /src | |
parent | e31bca139f720396d1a1639b46d37aee4fd9736e (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.c | 33 | ||||
-rw-r--r-- | src/gallium/winsys/drm/radeon/core/radeon_buffer.c | 14 | ||||
-rw-r--r-- | src/gallium/winsys/drm/radeon/core/radeon_winsys.h | 3 |
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 ccf39876a59..971e7f35212 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 daa032af6f2..25b58b2926c 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 37eeb459791..887a381cc49 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 |