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 <alexander.deucher@amd.com>

NOTE: This is a candidate for the 9.1 branch.
This commit is contained in:
Marek Olšák 2013-04-21 23:26:52 +02:00
parent 1ba46bbb4c
commit b692076420
4 changed files with 80 additions and 7 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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,

View file

@ -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) {