r600g: fix texture offset computation for mapped MSAA depth buffers
authorMarek Olšák <maraeo@gmail.com>
Sun, 30 Jun 2013 12:34:23 +0000 (14:34 +0200)
committerMarek Olšák <maraeo@gmail.com>
Mon, 8 Jul 2013 18:25:18 +0000 (20:25 +0200)
It was wrong, because the offset shouldn't be applied to MSAA depth buffers.
This small cleanup should prevent such issues in the future.

This fixes a lockup in "piglit/fbo-depthstencil default_fb -samples=n".

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_texture.c

index 8485cce732c975050e266345ee64ee0f1130abbb..64a90c3b3e96c6dfab90e11d6c58630cb900e4b3 100644 (file)
@@ -787,8 +787,6 @@ void r600_init_surface_functions(struct r600_context *r600);
 uint32_t r600_translate_texformat(struct pipe_screen *screen, enum pipe_format format,
                                  const unsigned char *swizzle_view,
                                  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,
index 60d8c3610d6059119b6fd8b0f6188676927f155b..c2feb521be380939dfad35d1875be4722674f0d2 100644 (file)
@@ -116,11 +116,15 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600
        }
 }
 
-unsigned r600_texture_get_offset(struct r600_texture *rtex,
-                                       unsigned level, unsigned layer)
+static unsigned r600_texture_get_offset(struct r600_texture *rtex, unsigned level,
+                                       const struct pipe_box *box)
 {
+       enum pipe_format format = rtex->resource.b.b.format;
+
        return rtex->surface.level[level].offset +
-              layer * rtex->surface.level[level].slice_size;
+              box->z * rtex->surface.level[level].slice_size +
+              box->y / util_format_get_blockheight(format) * rtex->surface.level[level].pitch_bytes +
+              box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
 }
 
 static int r600_init_surface(struct r600_screen *rscreen,
@@ -805,7 +809,6 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
        struct r600_texture *rtex = (struct r600_texture*)texture;
        struct r600_transfer *trans;
        boolean use_staging_texture = FALSE;
-       enum pipe_format format = texture->format;
        struct r600_resource *buf;
        unsigned offset = 0;
        char *map;
@@ -849,8 +852,6 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
        trans->transfer.box = *box;
 
        if (rtex->is_depth) {
-               /* XXX: only readback the rectangle which is being mapped? */
-               /* XXX: when discard is true, no need to read back from depth texture */
                struct r600_texture *staging_depth;
 
                if (rtex->resource.b.b.nr_samples > 1) {
@@ -861,6 +862,8 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                         *
                         * First downsample the depth buffer to a temporary texture,
                         * then decompress the temporary one to staging.
+                        *
+                        * Only the region being mapped is transfered.
                         */
                        struct pipe_resource *temp;
                        struct pipe_resource resource;
@@ -880,9 +883,10 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                                                   0, 0, 0, box->depth, 0, 0);
 
                        pipe_resource_reference((struct pipe_resource**)&temp, NULL);
-                       trans->offset = 0;
                }
                else {
+                       /* XXX: only readback the rectangle which is being mapped? */
+                       /* XXX: when discard is true, no need to read back from depth texture */
                        if (!r600_init_flushed_depth_texture(ctx, texture, &staging_depth)) {
                                R600_ERR("failed to create temporary texture to hold untiled copy\n");
                                FREE(trans);
@@ -894,7 +898,7 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                                                   box->z, box->z + box->depth - 1,
                                                   0, 0);
 
-                       trans->offset = r600_texture_get_offset(staging_depth, level, box->z);
+                       offset = r600_texture_get_offset(staging_depth, level, box);
                }
 
                trans->transfer.stride = staging_depth->surface.level[level].pitch_bytes;
@@ -926,9 +930,10 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                        rctx->rings.gfx.flush(rctx, 0);
                }
        } else {
+               /* the resource is mapped directly */
                trans->transfer.stride = rtex->surface.level[level].pitch_bytes;
                trans->transfer.layer_stride = rtex->surface.level[level].slice_size;
-               trans->offset = r600_texture_get_offset(rtex, level, box->z);
+               offset = r600_texture_get_offset(rtex, level, box);
        }
 
        if (trans->staging) {
@@ -937,11 +942,6 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                buf = &rtex->resource;
        }
 
-       if (rtex->is_depth || !trans->staging)
-               offset = trans->offset +
-                       box->y / util_format_get_blockheight(format) * trans->transfer.stride +
-                       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
-
        if (!(map = r600_buffer_mmap_sync_with_rings(rctx, buf, usage))) {
                pipe_resource_reference((struct pipe_resource**)&trans->staging, NULL);
                FREE(trans);