From 1dcf377a76cc4fa3e1c5312b0e10c4754532b512 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Mon, 27 Aug 2018 12:07:42 -0700 Subject: [PATCH] svga: fix texture array layer index in transfer map 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 --- .../drivers/svga/svga_resource_texture.c | 107 +++++++----------- .../drivers/svga/svga_resource_texture.h | 1 + 2 files changed, 42 insertions(+), 66 deletions(-) diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 53cdb93c914..c0921525465 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -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__, diff --git a/src/gallium/drivers/svga/svga_resource_texture.h b/src/gallium/drivers/svga/svga_resource_texture.h index fe52738b4f1..20db1c03957 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.h +++ b/src/gallium/drivers/svga/svga_resource_texture.h @@ -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; -- 2.30.2