r600g: implement 3D transfers
authorMarek Olšák <maraeo@gmail.com>
Thu, 20 Dec 2012 02:45:49 +0000 (03:45 +0100)
committerMarek Olšák <maraeo@gmail.com>
Fri, 4 Jan 2013 13:06:54 +0000 (14:06 +0100)
That means we can map and read multiple slices with one transfer_map call.

src/gallium/drivers/r600/r600_texture.c

index 0f6773962b99da3ed6e50ddeab84ebb5c81eb9ed..85da0930242f4e75ec1fc4029c63e676a3daec18 100644 (file)
@@ -70,7 +70,7 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600
        struct pipe_resource *texture = transfer->resource;
        struct pipe_box sbox;
 
-       u_box_origin_2d(transfer->box.width, transfer->box.height, &sbox);
+       u_box_3d(0, 0, 0, transfer->box.width, transfer->box.height, transfer->box.depth, &sbox);
 
        ctx->resource_copy_region(ctx, texture, transfer->level,
                                  transfer->box.x, transfer->box.y, transfer->box.z,
@@ -722,7 +722,6 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
 {
        struct r600_context *rctx = (struct r600_context*)ctx;
        struct r600_texture *rtex = (struct r600_texture*)texture;
-       struct pipe_resource resource;
        struct r600_transfer *trans;
        boolean use_staging_texture = FALSE;
        enum pipe_format format = texture->format;
@@ -793,40 +792,51 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
                                           0, 0);
 
                trans->transfer.stride = staging_depth->surface.level[level].pitch_bytes;
+                trans->transfer.layer_stride = staging_depth->surface.level[level].slice_size;
                trans->offset = r600_texture_get_offset(staging_depth, level, box->z);
                trans->staging = (struct r600_resource*)staging_depth;
        } else if (use_staging_texture) {
-               resource.target = PIPE_TEXTURE_2D;
+               struct pipe_resource resource;
+               struct r600_texture *staging;
+
+               memset(&resource, 0, sizeof(resource));
                resource.format = texture->format;
                resource.width0 = box->width;
                resource.height0 = box->height;
                resource.depth0 = 1;
                resource.array_size = 1;
-               resource.last_level = 0;
-               resource.nr_samples = 0;
                resource.usage = PIPE_USAGE_STAGING;
-               resource.bind = 0;
                resource.flags = R600_RESOURCE_FLAG_TRANSFER;
-               /* For texture reading, the temporary (detiled) texture is used as
-                * a render target when blitting from a tiled texture. */
-               if (usage & PIPE_TRANSFER_READ) {
-                       resource.bind |= PIPE_BIND_RENDER_TARGET;
-               }
-               /* For texture writing, the temporary texture is used as a sampler
-                * when blitting into a tiled texture. */
-               if (usage & PIPE_TRANSFER_WRITE) {
-                       resource.bind |= PIPE_BIND_SAMPLER_VIEW;
+
+               /* We must set the correct texture target and dimensions if needed for a 3D transfer. */
+               if (box->depth > 1 && u_max_layer(texture, level) > 0)
+                       resource.target = texture->target;
+               else
+                       resource.target = PIPE_TEXTURE_2D;
+
+               switch (resource.target) {
+               case PIPE_TEXTURE_1D_ARRAY:
+               case PIPE_TEXTURE_2D_ARRAY:
+               case PIPE_TEXTURE_CUBE_ARRAY:
+                       resource.array_size = box->depth;
+                       break;
+               case PIPE_TEXTURE_3D:
+                       resource.depth0 = box->depth;
+                       break;
+               default:;
                }
+
+
                /* Create the temporary texture. */
-               trans->staging = (struct r600_resource*)ctx->screen->resource_create(ctx->screen, &resource);
-               if (trans->staging == NULL) {
+               staging = (struct r600_texture*)ctx->screen->resource_create(ctx->screen, &resource);
+               if (staging == NULL) {
                        R600_ERR("failed to create temporary texture to hold untiled copy\n");
                        FREE(trans);
                        return NULL;
                }
-
-               trans->transfer.stride =
-                       ((struct r600_texture *)trans->staging)->surface.level[0].pitch_bytes;
+               trans->staging = &staging->resource;
+               trans->transfer.stride = staging->surface.level[0].pitch_bytes;
+               trans->transfer.layer_stride = staging->surface.level[0].slice_size;
                if (usage & PIPE_TRANSFER_READ) {
                        r600_copy_to_staging_texture(ctx, trans);
                        /* Always referenced in the blit. */
@@ -839,9 +849,9 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx,
        }
 
        if (trans->staging) {
-               buf = ((struct r600_resource *)trans->staging)->cs_buf;
+               buf = trans->staging->cs_buf;
        } else {
-               buf = ((struct r600_resource *)texture)->cs_buf;
+               buf = rtex->resource.cs_buf;
        }
 
        if (rtex->is_depth || !trans->staging)