diff options
author | Ilia Mirkin <[email protected]> | 2018-12-27 10:24:56 -0500 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2018-12-30 23:32:21 -0500 |
commit | b04c1907c8c9f4fd66ce4e069665f4c40e3d40e0 (patch) | |
tree | 6af1861e4ff533cc0d5752e727aa70ee21cbd9b0 /src/gallium | |
parent | b34cfd474961bef6cb245e02a6dba7db0cf12ce6 (diff) |
nv30: add support for multi-layer transfers
This logic mirrors what we do on nv50. The relatively new
texture_subdata callback can cause this to happen with 3D textures,
which is triggered at least by xonotic, and probably many piglits.
Signed-off-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/nouveau/nv30/nv30_miptree.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c index 4f991776323..a75072b7eea 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c @@ -265,6 +265,7 @@ nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_device *dev = nv30->screen->base.device; + struct nv30_miptree *mt = nv30_miptree(pt); struct nv30_transfer *tx; unsigned access = 0; int ret; @@ -288,7 +289,8 @@ nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, tx->nblocksx, tx->nblocksy, &tx->img); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, - tx->base.layer_stride, NULL, &tx->tmp.bo); + tx->base.layer_stride * tx->base.box.depth, NULL, + &tx->tmp.bo); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); FREE(tx); @@ -308,8 +310,25 @@ nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, tx->tmp.y1 = tx->tmp.h; tx->tmp.z = 0; - if (usage & PIPE_TRANSFER_READ) - nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); + if (usage & PIPE_TRANSFER_READ) { + bool is_3d = mt->base.base.target == PIPE_TEXTURE_3D; + unsigned offset = tx->img.offset; + unsigned z = tx->img.z; + unsigned i; + for (i = 0; i < box->depth; ++i) { + nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); + if (is_3d && mt->swizzled) + tx->img.z++; + else if (is_3d) + tx->img.offset += mt->level[level].zslice_size; + else + tx->img.offset += mt->layer_size; + tx->tmp.offset += tx->base.layer_stride; + } + tx->img.z = z; + tx->img.offset = offset; + tx->tmp.offset = 0; + } if (tx->tmp.bo->map) { *ptransfer = &tx->base; @@ -338,9 +357,21 @@ nv30_miptree_transfer_unmap(struct pipe_context *pipe, { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_transfer *tx = nv30_transfer(ptx); + struct nv30_miptree *mt = nv30_miptree(tx->base.resource); + unsigned i; if (ptx->usage & PIPE_TRANSFER_WRITE) { - nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img); + bool is_3d = mt->base.base.target == PIPE_TEXTURE_3D; + for (i = 0; i < tx->base.box.depth; ++i) { + nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img); + if (is_3d && mt->swizzled) + tx->img.z++; + else if (is_3d) + tx->img.offset += mt->level[tx->base.level].zslice_size; + else + tx->img.offset += mt->layer_size; + tx->tmp.offset += tx->base.layer_stride; + } /* Allow the copies above to finish executing before freeing the source */ nouveau_fence_work(nv30->screen->base.fence.current, |