From: Marek Olšák Date: Sun, 23 Sep 2012 21:12:17 +0000 (+0200) Subject: r600g: don't modify pipe_resource in resource_copy_region, fixing race condition X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6db53ca490b22ba3f16b3ab0beef7a5fc071a074;p=mesa.git r600g: don't modify pipe_resource in resource_copy_region, fixing race condition pipe_resource can be shared between contexts, we shouldn't modify its description. Instead, let's use the resource "views" (sampler views and surfaces), where we can freely change almost any property of a resource. --- diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 169499bcee9..c126e7dfc3d 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -979,9 +979,11 @@ static void *evergreen_create_sampler_state(struct pipe_context *ctx, return ss; } -static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_context *ctx, - struct pipe_resource *texture, - const struct pipe_sampler_view *state) +struct pipe_sampler_view * +evergreen_create_sampler_view_custom(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_sampler_view *state, + unsigned width0, unsigned height0) { struct r600_screen *rscreen = (struct r600_screen*)ctx->screen; struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view); @@ -1027,8 +1029,8 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte endian = r600_colorformat_endian_swap(format); - width = tmp->surface.level[0].npix_x; - height = tmp->surface.level[0].npix_y; + width = width0; + height = height0; depth = tmp->surface.level[0].npix_z; pitch = tmp->surface.level[0].nblk_x * util_format_get_blockwidth(state->format); tile_type = tmp->tile_type; @@ -1116,6 +1118,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte return &view->base; } +static struct pipe_sampler_view * +evergreen_create_sampler_view(struct pipe_context *ctx, + struct pipe_resource *tex, + const struct pipe_sampler_view *state) +{ + return evergreen_create_sampler_view_custom(ctx, tex, state, + tex->width0, tex->height0); +} + static void evergreen_emit_clip_state(struct r600_context *rctx, struct r600_atom *atom) { struct radeon_winsys_cs *cs = rctx->cs; diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 090121cccf5..9bbbc454418 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -434,103 +434,6 @@ void r600_copy_buffer(struct pipe_context *ctx, struct } } -struct texture_orig_info { - unsigned format; - unsigned width0; - unsigned height0; - unsigned npix_x; - unsigned npix_y; - unsigned npix0_x; - unsigned npix0_y; -}; - -static void r600_compressed_to_blittable(struct pipe_resource *tex, - unsigned level, - struct texture_orig_info *orig) -{ - struct r600_texture *rtex = (struct r600_texture*)tex; - unsigned pixsize = util_format_get_blocksize(rtex->resource.b.b.format); - int new_format; - int new_height, new_width; - - orig->format = tex->format; - orig->width0 = tex->width0; - orig->height0 = tex->height0; - orig->npix0_x = rtex->surface.level[0].npix_x; - orig->npix0_y = rtex->surface.level[0].npix_y; - orig->npix_x = rtex->surface.level[level].npix_x; - orig->npix_y = rtex->surface.level[level].npix_y; - - if (pixsize == 8) - new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ - else - new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ - - new_width = util_format_get_nblocksx(tex->format, orig->width0); - new_height = util_format_get_nblocksy(tex->format, orig->height0); - - tex->width0 = new_width; - tex->height0 = new_height; - tex->format = new_format; - rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); - rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); - rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); - rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); -} - -static void r600_subsampled_2x1_32bpp_to_blittable(struct pipe_resource *tex, - unsigned level, - struct texture_orig_info *orig) -{ - struct r600_texture *rtex = (struct r600_texture*)tex; - - orig->format = tex->format; - orig->width0 = tex->width0; - orig->height0 = tex->height0; - orig->npix0_x = rtex->surface.level[0].npix_x; - orig->npix0_y = rtex->surface.level[0].npix_y; - orig->npix_x = rtex->surface.level[level].npix_x; - orig->npix_y = rtex->surface.level[level].npix_y; - - tex->width0 = util_format_get_nblocksx(orig->format, orig->width0); - tex->format = PIPE_FORMAT_R8G8B8A8_UINT; - rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); - rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); -} - -static void r600_change_format(struct pipe_resource *tex, - unsigned level, - struct texture_orig_info *orig, - enum pipe_format format) -{ - struct r600_texture *rtex = (struct r600_texture*)tex; - - orig->format = tex->format; - orig->width0 = tex->width0; - orig->height0 = tex->height0; - orig->npix0_x = rtex->surface.level[0].npix_x; - orig->npix0_y = rtex->surface.level[0].npix_y; - orig->npix_x = rtex->surface.level[level].npix_x; - orig->npix_y = rtex->surface.level[level].npix_y; - - tex->format = format; -} - -static void r600_reset_blittable_to_orig(struct pipe_resource *tex, - unsigned level, - struct texture_orig_info *orig) -{ - struct r600_texture *rtex = (struct r600_texture*)tex; - - tex->format = orig->format; - tex->width0 = orig->width0; - tex->height0 = orig->height0; - rtex->surface.level[0].npix_x = orig->npix0_x; - rtex->surface.level[0].npix_y = orig->npix0_y; - rtex->surface.level[level].npix_x = orig->npix_x; - rtex->surface.level[level].npix_y = orig->npix_y; -} - static bool util_format_is_subsampled_2x1_32bpp(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -550,12 +453,12 @@ static void r600_resource_copy_region(struct pipe_context *ctx, const struct pipe_box *src_box) { struct r600_context *rctx = (struct r600_context *)ctx; - struct texture_orig_info orig_info[2]; + struct r600_texture *rsrc = (struct r600_texture*)src; + struct r600_texture *rdst = (struct r600_texture*)dst; + struct pipe_surface *dst_view, dst_templ; + struct pipe_sampler_view src_templ, *src_view; + unsigned dst_width, dst_height, src_width0, src_height0, src_widthFL, src_heightFL; struct pipe_box sbox; - const struct pipe_box *psbox = src_box; - boolean restore_orig[2]; - - memset(orig_info, 0, sizeof(orig_info)); /* Handle buffers first. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { @@ -572,53 +475,70 @@ static void r600_resource_copy_region(struct pipe_context *ctx, return; /* error */ } - restore_orig[0] = restore_orig[1] = FALSE; - - if (util_format_is_compressed(src->format) && - util_format_is_compressed(dst->format)) { - r600_compressed_to_blittable(src, src_level, &orig_info[0]); - restore_orig[0] = TRUE; - sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); - sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); + dst_width = rdst->surface.level[dst_level].npix_x; + dst_height = rdst->surface.level[dst_level].npix_y; + src_width0 = src->width0; + src_height0 = src->height0; + src_widthFL = rsrc->surface.level[src_level].npix_x; + src_heightFL = rsrc->surface.level[src_level].npix_y; + + util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, src_box); + util_blitter_default_src_texture(&src_templ, src, src_level); + + if (util_format_is_compressed(src->format)) { + unsigned blocksize = util_format_get_blocksize(src->format); + + if (blocksize == 8) + src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ + else + src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ + dst_templ.format = src_templ.format; + + dst_width = util_format_get_nblocksx(dst->format, rdst->surface.level[dst_level].npix_x); + dst_height = util_format_get_nblocksy(dst->format, rdst->surface.level[dst_level].npix_y); + src_width0 = util_format_get_nblocksx(src->format, src->width0); + src_height0 = util_format_get_nblocksy(src->format, src->height0); + src_widthFL = util_format_get_nblocksx(src->format, rsrc->surface.level[src_level].npix_x); + src_heightFL = util_format_get_nblocksy(src->format, rsrc->surface.level[src_level].npix_y); + + dstx = util_format_get_nblocksx(dst->format, dstx); + dsty = util_format_get_nblocksy(dst->format, dsty); + + sbox.x = util_format_get_nblocksx(src->format, src_box->x); + sbox.y = util_format_get_nblocksy(src->format, src_box->y); sbox.z = src_box->z; - sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); - sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); + sbox.width = util_format_get_nblocksx(src->format, src_box->width); + sbox.height = util_format_get_nblocksy(src->format, src_box->height); sbox.depth = src_box->depth; - psbox = &sbox; - - r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); - restore_orig[1] = TRUE; - /* translate the dst box as well */ - dstx = util_format_get_nblocksx(orig_info[1].format, dstx); - dsty = util_format_get_nblocksy(orig_info[1].format, dsty); + src_box = &sbox; } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src, PIPE_MASK_RGBAZS)) { - if (util_format_is_subsampled_2x1_32bpp(src->format) && - util_format_is_subsampled_2x1_32bpp(dst->format)) { - r600_subsampled_2x1_32bpp_to_blittable(src, src_level, &orig_info[0]); - r600_subsampled_2x1_32bpp_to_blittable(dst, dst_level, &orig_info[1]); + if (util_format_is_subsampled_2x1_32bpp(src->format)) { - sbox = *src_box; - sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); - sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); - psbox = &sbox; + src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; + dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; - dstx = util_format_get_nblocksx(orig_info[1].format, dstx); + dst_width = util_format_get_nblocksx(dst->format, rdst->surface.level[dst_level].npix_x); + src_width0 = util_format_get_nblocksx(src->format, src->width0); + src_widthFL = util_format_get_nblocksx(src->format, rsrc->surface.level[src_level].npix_x); + + dstx = util_format_get_nblocksx(dst->format, dstx); + + sbox = *src_box; + sbox.x = util_format_get_nblocksx(src->format, src_box->x); + sbox.width = util_format_get_nblocksx(src->format, src_box->width); + src_box = &sbox; } else { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: - r600_change_format(src, src_level, &orig_info[0], - PIPE_FORMAT_R8_UNORM); - r600_change_format(dst, dst_level, &orig_info[1], - PIPE_FORMAT_R8_UNORM); + dst_templ.format = PIPE_FORMAT_R8_UNORM; + src_templ.format = PIPE_FORMAT_R8_UNORM; break; case 4: - r600_change_format(src, src_level, &orig_info[0], - PIPE_FORMAT_R8G8B8A8_UNORM); - r600_change_format(dst, dst_level, &orig_info[1], - PIPE_FORMAT_R8G8B8A8_UNORM); + dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; + src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", @@ -626,24 +546,32 @@ static void r600_resource_copy_region(struct pipe_context *ctx, assert(0); } } - restore_orig[0] = TRUE; - restore_orig[1] = TRUE; } + dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, dst_width, dst_height); + + if (rctx->chip_class >= EVERGREEN) { + src_view = evergreen_create_sampler_view_custom(ctx, src, &src_templ, + src_width0, src_height0); + } else { + src_view = r600_create_sampler_view_custom(ctx, src, &src_templ, + src_widthFL, src_heightFL); + } + + /* Copy. */ /* XXX Multisample texturing is unimplemented on Cayman. In the meantime, * copy only the first sample (which is the only one that is uncompressed * and therefore doesn't return garbage). */ r600_blitter_begin(ctx, R600_COPY_TEXTURE); - util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, - src, src_level, psbox, PIPE_MASK_RGBAZS, + util_blitter_blit_generic(rctx->blitter, dst_view, dstx, dsty, + abs(src_box->width), abs(src_box->height), + src_view, src_box, src_width0, src_height0, + PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, rctx->chip_class != CAYMAN); r600_blitter_end(ctx); - if (restore_orig[0]) - r600_reset_blittable_to_orig(src, src_level, &orig_info[0]); - - if (restore_orig[1]) - r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); + pipe_surface_reference(&dst_view, NULL); + pipe_sampler_view_reference(&src_view, NULL); } static void r600_msaa_color_resolve(struct pipe_context *ctx, diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 3430b89b74d..607116f7660 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -516,6 +516,11 @@ static INLINE void r600_atom_dirty(struct r600_context *rctx, struct r600_atom * } /* evergreen_state.c */ +struct pipe_sampler_view * +evergreen_create_sampler_view_custom(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_sampler_view *state, + unsigned width0, unsigned height0); void evergreen_init_common_regs(struct r600_command_buffer *cb, enum chip_class ctx_chip_class, enum radeon_family ctx_family, @@ -591,6 +596,11 @@ int r600_compute_shader_create(struct pipe_context * ctx, void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader); /* r600_state.c */ +struct pipe_sampler_view * +r600_create_sampler_view_custom(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_sampler_view *state, + unsigned width_first_level, unsigned height_first_level); void r600_set_scissor_state(struct r600_context *rctx, const struct pipe_scissor_state *state); void r600_init_state_functions(struct r600_context *rctx); @@ -619,6 +629,10 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, enum pipe_format f uint32_t *word4_p, uint32_t *yuv_format_p); unsigned r600_texture_get_offset(struct r600_texture *rtex, unsigned level, unsigned layer); +struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe, + struct pipe_resource *texture, + const struct pipe_surface *templ, + unsigned width, unsigned height); /* r600_translate.c */ void r600_translate_index_buffer(struct r600_context *r600, diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 3347e6d872f..1d6171debb5 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1007,9 +1007,11 @@ static void *r600_create_sampler_state(struct pipe_context *ctx, return ss; } -static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *ctx, - struct pipe_resource *texture, - const struct pipe_sampler_view *state) +struct pipe_sampler_view * +r600_create_sampler_view_custom(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_sampler_view *state, + unsigned width_first_level, unsigned height_first_level) { struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view); struct r600_texture *tmp = (struct r600_texture*)texture; @@ -1055,8 +1057,8 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c offset_level = state->u.tex.first_level; last_level = state->u.tex.last_level - offset_level; - width = tmp->surface.level[offset_level].npix_x; - height = tmp->surface.level[offset_level].npix_y; + width = width_first_level; + height = height_first_level; depth = tmp->surface.level[offset_level].npix_z; pitch = tmp->surface.level[offset_level].nblk_x * util_format_get_blockwidth(state->format); tile_type = tmp->tile_type; @@ -1116,6 +1118,18 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c return &view->base; } +static struct pipe_sampler_view * +r600_create_sampler_view(struct pipe_context *ctx, + struct pipe_resource *tex, + const struct pipe_sampler_view *state) +{ + struct r600_texture *rtex = (struct r600_texture*)tex; + + return r600_create_sampler_view_custom(ctx, tex, state, + rtex->surface.level[state->u.tex.first_level].npix_x, + rtex->surface.level[state->u.tex.first_level].npix_y); +} + static void r600_emit_clip_state(struct r600_context *rctx, struct r600_atom *atom) { struct radeon_winsys_cs *cs = rctx->cs; diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 1c52ff8c83b..4fb10ca031d 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -481,13 +481,12 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, 0, NULL, TRUE, &surface); } -static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, +struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe, struct pipe_resource *texture, - const struct pipe_surface *templ) + const struct pipe_surface *templ, + unsigned width, unsigned height) { - struct r600_texture *rtex = (struct r600_texture*)texture; struct r600_surface *surface = CALLOC_STRUCT(r600_surface); - unsigned level = templ->u.tex.level; assert(templ->u.tex.first_layer == templ->u.tex.last_layer); if (surface == NULL) @@ -496,13 +495,25 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, pipe_resource_reference(&surface->base.texture, texture); surface->base.context = pipe; surface->base.format = templ->format; - surface->base.width = rtex->surface.level[level].npix_x; - surface->base.height = rtex->surface.level[level].npix_y; + surface->base.width = width; + surface->base.height = height; surface->base.usage = templ->usage; surface->base.u = templ->u; return &surface->base; } +static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, + struct pipe_resource *texture, + const struct pipe_surface *templ) +{ + struct r600_texture *rtex = (struct r600_texture*)texture; + unsigned level = templ->u.tex.level; + + return r600_create_surface_custom(pipe, texture, templ, + rtex->surface.level[level].npix_x, + rtex->surface.level[level].npix_y); +} + static void r600_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surface) {