diff options
author | Marek Olšák <[email protected]> | 2013-04-21 23:26:52 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2013-04-23 20:26:20 +0200 |
commit | b69207642079fe8ba33c594750415e8d9c66a06f (patch) | |
tree | f71b6cfd90363297b7f15c0acd55508267fc7a5a | |
parent | 1ba46bbb4c99caa7e297f2ec6717e962765275cb (diff) |
r600g: initialize CMASK and HTILE with the GPU using streamout
This fixes a crash when a resource cannot be mapped to the CPU's address space
because it's too big.
This puts a global pipe_context in r600_screen, which is guarded by a mutex,
so that we can use pipe_context when there isn't one around.
Hopefully our multi-context support is solid.
Reviewed-by: Alex Deucher <[email protected]>
NOTE: This is a candidate for the 9.1 branch.
-rw-r--r-- | src/gallium/drivers/r600/r600_blit.c | 31 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 39 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_texture.c | 10 |
4 files changed, 80 insertions, 7 deletions
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 8fc83aaad25..a0384bf366a 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -522,6 +522,37 @@ void r600_copy_buffer(struct pipe_context *ctx, struct pipe_resource *dst, unsig } } +static void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, + unsigned offset, unsigned size, unsigned char value) +{ + struct r600_context *rctx = (struct r600_context*)ctx; + + if (rctx->screen->has_streamout && offset % 4 == 0 && size % 4 == 0) { + union pipe_color_union clear_value; + uint32_t v = value; + + clear_value.ui[0] = v | (v << 8) | (v << 16) | (v << 24); + + r600_blitter_begin(ctx, R600_DISABLE_RENDER_COND); + util_blitter_clear_buffer(rctx->blitter, dst, offset, size, + 1, &clear_value); + r600_blitter_end(ctx); + } else { + char *map = r600_buffer_mmap_sync_with_rings(rctx, r600_resource(dst), + PIPE_TRANSFER_WRITE); + memset(map + offset, value, size); + } +} + +void r600_screen_clear_buffer(struct r600_screen *rscreen, struct pipe_resource *dst, + unsigned offset, unsigned size, unsigned char value) +{ + pipe_mutex_lock(rscreen->aux_context_lock); + r600_clear_buffer(rscreen->aux_context, dst, offset, size, value); + rscreen->aux_context->flush(rscreen->aux_context, NULL, 0); + pipe_mutex_unlock(rscreen->aux_context_lock); +} + static bool util_format_is_subsampled_2x1_32bpp(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 4948dddae74..008539d7c0c 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -940,6 +940,9 @@ static void r600_destroy_screen(struct pipe_screen* pscreen) if (rscreen == NULL) return; + pipe_mutex_destroy(rscreen->aux_context_lock); + rscreen->aux_context->destroy(rscreen->aux_context); + if (rscreen->global_pool) { compute_memory_pool_delete(rscreen->global_pool); } @@ -1319,5 +1322,41 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws) } #endif + /* Create the auxiliary context. */ + pipe_mutex_init(rscreen->aux_context_lock); + rscreen->aux_context = rscreen->screen.context_create(&rscreen->screen, NULL); + +#if 0 /* This is for testing whether aux_context and buffer clearing work correctly. */ + struct pipe_resource templ = {}; + + templ.width0 = 4; + templ.height0 = 2048; + templ.depth0 = 1; + templ.array_size = 1; + templ.target = PIPE_TEXTURE_2D; + templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; + templ.usage = PIPE_USAGE_STATIC; + + struct r600_resource *res = r600_resource(rscreen->screen.resource_create(&rscreen->screen, &templ)); + unsigned char *map = ws->buffer_map(res->cs_buf, NULL, PIPE_TRANSFER_WRITE); + + memset(map, 0, 256); + + r600_screen_clear_buffer(rscreen, &res->b.b, 4, 4, 0xCC); + r600_screen_clear_buffer(rscreen, &res->b.b, 8, 4, 0xDD); + r600_screen_clear_buffer(rscreen, &res->b.b, 12, 4, 0xEE); + r600_screen_clear_buffer(rscreen, &res->b.b, 20, 4, 0xFF); + r600_screen_clear_buffer(rscreen, &res->b.b, 32, 20, 0x87); + + ws->buffer_wait(res->buf, RADEON_USAGE_WRITE); + + int i; + for (i = 0; i < 256; i++) { + printf("%02X", map[i]); + if (i % 16 == 15) + printf("\n"); + } +#endif + return &rscreen->screen; } diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 4a692e78302..1dbed80ae40 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -290,6 +290,11 @@ struct r600_screen { unsigned cs_count; #endif r600g_dma_blit_t dma_blit; + + /* Auxiliary context. Mainly used to initialize resources. + * It must be locked prior to using and flushed before unlocking. */ + struct pipe_context *aux_context; + pipe_mutex aux_context_lock; }; struct r600_pipe_sampler_view { @@ -721,6 +726,8 @@ void evergreen_update_db_shader_control(struct r600_context * rctx); /* r600_blit.c */ void r600_copy_buffer(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dstx, struct pipe_resource *src, const struct pipe_box *src_box); +void r600_screen_clear_buffer(struct r600_screen *rscreen, struct pipe_resource *dst, + unsigned offset, unsigned size, unsigned char value); void r600_init_blit_functions(struct r600_context *rctx); void r600_blit_decompress_depth(struct pipe_context *ctx, struct r600_texture *texture, diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 98cb1189763..3a1f2fea831 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -480,10 +480,7 @@ r600_texture_create_object(struct pipe_screen *screen, */ R600_ERR("r600: failed to create bo for htile buffers\n"); } else { - void *ptr; - ptr = rscreen->ws->buffer_map(rtex->htile->cs_buf, NULL, PIPE_TRANSFER_WRITE); - memset(ptr, 0x0, htile_size); - rscreen->ws->buffer_unmap(rtex->htile->cs_buf); + r600_screen_clear_buffer(rscreen, &rtex->htile->b.b, 0, htile_size, 0); } } @@ -505,9 +502,8 @@ r600_texture_create_object(struct pipe_screen *screen, if (rtex->cmask_size) { /* Initialize the cmask to 0xCC (= compressed state). */ - char *ptr = rscreen->ws->buffer_map(resource->cs_buf, NULL, PIPE_TRANSFER_WRITE); - memset(ptr + rtex->cmask_offset, 0xCC, rtex->cmask_size); - rscreen->ws->buffer_unmap(resource->cs_buf); + r600_screen_clear_buffer(rscreen, &rtex->resource.b.b, + rtex->cmask_offset, rtex->cmask_size, 0xCC); } if (rscreen->debug_flags & DBG_VM) { |