svga: fix texture array layer index in transfer map
authorCharmaine Lee <charmainel@vmware.com>
Mon, 27 Aug 2018 19:07:42 +0000 (12:07 -0700)
committerBrian Paul <brianp@vmware.com>
Thu, 20 Sep 2018 19:20:10 +0000 (13:20 -0600)
In gallium, the layer index of a texture array to be mapped
is specified in the z component, whereas in svga device, the
index is specified in a separate argument.
Currently in svga_texture_transfer_map(), we explicitly modify
the z value in the base transfer map to 0 so the layer offset will not be
applied twice, but this causes problem when state tracker later
refers to the base transfer map and expects the slice index to be
specified in z (commit 463b0ea1f6762b7e0536cfadc4e384840af3e8e0).

To fix the problem, this patch makes a local copy of the box in
svga_transfer and modifies the z value in this copy instead.

Fixes spec@khr_texture_compression-astc piglit test crashes.
Fixes regression in the dma path with commit 1fdd3dd94a.

Tested with mtt glretrace, piglit on Windows VM and Linux VM.

Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_resource_texture.h

index 53cdb93c91480b2536cbc987a3535c5c354755d7..c09215254654f92acd915209040bb8fa82e5cd6a 100644 (file)
@@ -121,8 +121,8 @@ svga_transfer_dma(struct svga_context *svga,
    if (!st->swbuf) {
       /* Do the DMA transfer in a single go */
       svga_transfer_dma_band(svga, st, transfer,
-                             st->base.box.x, st->base.box.y, st->base.box.z,
-                             st->base.box.width, st->base.box.height, st->base.box.depth,
+                             st->box.x, st->box.y, st->box.z,
+                             st->box.w, st->box.h, st->box.d,
                              0, 0, 0,
                              flags);
 
@@ -140,12 +140,12 @@ svga_transfer_dma(struct svga_context *svga,
       h = st->hw_nblocksy * blockheight;
       srcy = 0;
 
-      for (y = 0; y < st->base.box.height; y += h) {
+      for (y = 0; y < st->box.h; y += h) {
          unsigned offset, length;
          void *hw, *sw;
 
-         if (y + h > st->base.box.height)
-            h = st->base.box.height - y;
+         if (y + h > st->box.h)
+            h = st->box.h - y;
 
          /* Transfer band must be aligned to pixel block boundaries */
          assert(y % blockheight == 0);
@@ -175,8 +175,8 @@ svga_transfer_dma(struct svga_context *svga,
          }
 
          svga_transfer_dma_band(svga, st, transfer,
-                                st->base.box.x, y, st->base.box.z,
-                                st->base.box.width, h, st->base.box.depth,
+                                st->box.x, y, st->box.z,
+                                st->box.w, h, st->box.d,
                                 0, srcy, 0, flags);
 
          /*
@@ -255,44 +255,19 @@ svga_texture_destroy(struct pipe_screen *screen,
 }
 
 
-/**
- * Determine if the resource was rendered to
- */
-static inline boolean
-was_tex_rendered_to(struct pipe_resource *resource,
-                    const struct pipe_transfer *transfer)
-{
-   unsigned layer_face;
-
-   switch (resource->target) {
-   case PIPE_TEXTURE_CUBE:
-      assert(transfer->box.depth == 1);
-   case PIPE_TEXTURE_1D_ARRAY:
-   case PIPE_TEXTURE_2D_ARRAY:
-   case PIPE_TEXTURE_CUBE_ARRAY:
-      layer_face = transfer->box.z;
-      break;
-   default:
-      layer_face = 0;
-   }
-
-   return svga_was_texture_rendered_to(svga_texture(resource),
-                                       layer_face, transfer->level);
-}
-
-
 /**
  * Determine if we need to read back a texture image before mapping it.
  */
 static inline boolean
-need_tex_readback(struct pipe_transfer *transfer)
+need_tex_readback(struct svga_transfer *st)
 {
-   if (transfer->usage & PIPE_TRANSFER_READ)
+   if (st->base.usage & PIPE_TRANSFER_READ)
       return TRUE;
 
-   if ((transfer->usage & PIPE_TRANSFER_WRITE) &&
-       ((transfer->usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) == 0)) {
-      return was_tex_rendered_to(transfer->resource, transfer);
+   if ((st->base.usage & PIPE_TRANSFER_WRITE) &&
+       ((st->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) == 0)) {
+      return svga_was_texture_rendered_to(svga_texture(st->base.resource),
+                                          st->slice, st->base.level);
    }
 
    return FALSE;
@@ -350,9 +325,9 @@ svga_texture_transfer_map_dma(struct svga_context *svga,
    unsigned usage = st->base.usage;
 
    /* we'll put the data into a tightly packed buffer */
-   nblocksx = util_format_get_nblocksx(texture->format, st->base.box.width);
-   nblocksy = util_format_get_nblocksy(texture->format, st->base.box.height);
-   d = st->base.box.depth;
+   nblocksx = util_format_get_nblocksx(texture->format, st->box.w);
+   nblocksy = util_format_get_nblocksy(texture->format, st->box.h);
+   d = st->box.d;
 
    st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
    st->base.layer_stride = st->base.stride * nblocksy;
@@ -421,12 +396,12 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
    unsigned w, h, nblocksx, nblocksy, i;
    unsigned usage = st->base.usage;
 
-   if (need_tex_readback(transfer)) {
+   if (need_tex_readback(st)) {
       enum pipe_error ret;
 
       svga_surfaces_flush(svga);
 
-      for (i = 0; i < st->base.box.depth; i++) {
+      for (i = 0; i < st->box.d; i++) {
          if (svga_have_vgpu10(svga)) {
             ret = readback_image_vgpu10(svga, surf, st->slice + i, level,
                                         tex->b.b.last_level + 1);
@@ -528,9 +503,9 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
 
       offset += svga3dsurface_get_pixel_offset(tex->key.format,
                                                mip_width, mip_height,
-                                               st->base.box.x,
-                                               st->base.box.y,
-                                               st->base.box.z);
+                                               st->box.x,
+                                               st->box.y,
+                                               st->box.z);
 
       return (void *) (map + offset);
    }
@@ -579,16 +554,26 @@ svga_texture_transfer_map(struct pipe_context *pipe,
    st->base.usage = usage;
    st->base.box = *box;
 
+   /* The modified transfer map box with the array index removed from z.
+    * The array index is specified in slice.
+    */
+   st->box.x = box->x;
+   st->box.y = box->y;
+   st->box.z = box->z;
+   st->box.w = box->width;
+   st->box.h = box->height;
+   st->box.d = box->depth;
+
    switch (tex->b.b.target) {
    case PIPE_TEXTURE_CUBE:
       st->slice = st->base.box.z;
-      st->base.box.z = 0;   /* so we don't apply double offsets below */
+      st->box.z = 0;   /* so we don't apply double offsets below */
       break;
    case PIPE_TEXTURE_1D_ARRAY:
    case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_CUBE_ARRAY:
       st->slice = st->base.box.z;
-      st->base.box.z = 0;   /* so we don't apply double offsets below */
+      st->box.z = 0;   /* so we don't apply double offsets below */
 
       /* Force direct map for transfering multiple slices */
       if (st->base.box.depth > 1)
@@ -624,7 +609,9 @@ svga_texture_transfer_map(struct pipe_context *pipe,
    else {
       boolean can_use_upload = tex->can_use_upload &&
                                !(st->base.usage & PIPE_TRANSFER_READ);
-      boolean was_rendered_to = was_tex_rendered_to(texture, &st->base);
+      boolean was_rendered_to =
+         svga_was_texture_rendered_to(svga_texture(texture),
+                                      st->slice, st->base.level);
 
       /* If the texture was already rendered to and upload buffer
        * is supported, then we will use upload buffer to
@@ -669,7 +656,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       if (usage & PIPE_TRANSFER_WRITE) {
          /* record texture upload for HUD */
          svga->hud.num_bytes_uploaded +=
-            st->base.layer_stride * st->base.box.depth;
+            st->base.layer_stride * st->box.d;
 
          /* mark this texture level as dirty */
          svga_set_texture_dirty(tex, st->slice, level);
@@ -798,39 +785,27 @@ svga_texture_transfer_unmap_direct(struct svga_context *svga,
    /* Now send an update command to update the content in the backend. */
    if (st->base.usage & PIPE_TRANSFER_WRITE) {
       struct svga_winsys_surface *surf = tex->handle;
-      SVGA3dBox box;
       enum pipe_error ret;
-      unsigned nlayers = 1;
 
       assert(svga_have_gb_objects(svga));
 
       /* update the effected region */
-      box.x = transfer->box.x;
-      box.y = transfer->box.y;
-      box.w = transfer->box.width;
-      box.h = transfer->box.height;
-      box.d = transfer->box.depth;
+      SVGA3dBox box = st->box;
+      unsigned nlayers;
 
       switch (tex->b.b.target) {
-      case PIPE_TEXTURE_CUBE:
-         box.z = 0;
-         break;
       case PIPE_TEXTURE_2D_ARRAY:
       case PIPE_TEXTURE_CUBE_ARRAY:
-         nlayers = box.d;
-         box.z = 0;
-         box.d = 1;
-         break;
       case PIPE_TEXTURE_1D_ARRAY:
          nlayers = box.d;
-         box.y = box.z = 0;
          box.d = 1;
          break;
       default:
-         box.z = transfer->box.z;
+         nlayers = 1;
          break;
       }
 
+
       if (0)
          debug_printf("%s %d, %d, %d  %d x %d x %d\n",
                       __FUNCTION__,
index fe52738b4f18b45b46e84ad11be0d26f07b3c87c..20db1c03957539eb88749d2cc9f247065dfa83ea 100644 (file)
@@ -125,6 +125,7 @@ struct svga_transfer
    struct pipe_transfer base;
 
    unsigned slice;  /**< array slice or cube face */
+   SVGA3dBox box;   /* The adjusted box with slice index removed from z */
 
    struct svga_winsys_buffer *hwbuf;