r600g: initialize CMASK and HTILE with the GPU using streamout
authorMarek Olšák <maraeo@gmail.com>
Sun, 21 Apr 2013 21:26:52 +0000 (23:26 +0200)
committerMarek Olšák <maraeo@gmail.com>
Tue, 23 Apr 2013 18:26:20 +0000 (20:26 +0200)
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.

src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_texture.c

index 8fc83aaad2596c3ad0ba303dacc2fda2fa8da870..a0384bf366acf07554ebdb82fa47a919027cde94 100644 (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);
index 4948dddae741892dbe112b1baba4d352e0070ebe..008539d7c0cf0b290b9e92f8ccdad77f5d51183b 100644 (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;
 }
index 4a692e78302d80bbb8131d6f633b3f8f2526eaab..1dbed80ae402e4b4752830bdd3dd5f3cf525f337 100644 (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,
index 98cb11897635f4b63ef666308c164317d2a6aa8f..3a1f2fea831c65f07b059cc820d5901d3e7769d6 100644 (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) {