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 463b0ea1f6).

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>
This commit is contained in:
Charmaine Lee 2018-08-27 12:07:42 -07:00 committed by Brian Paul
parent 18a6e426f3
commit 1dcf377a76
2 changed files with 42 additions and 66 deletions

View 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__,

View 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;