summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2013-04-21 23:26:52 +0200
committerMarek Olšák <maraeo@gmail.com>2013-04-23 20:26:20 +0200
commitb69207642079fe8ba33c594750415e8d9c66a06f (patch)
treef71b6cfd90363297b7f15c0acd55508267fc7a5a
parent1ba46bbb4c99caa7e297f2ec6717e962765275cb (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 <alexander.deucher@amd.com> NOTE: This is a candidate for the 9.1 branch.
-rw-r--r--src/gallium/drivers/r600/r600_blit.c31
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c39
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h7
-rw-r--r--src/gallium/drivers/r600/r600_texture.c10
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) {