summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2018-12-27 10:24:56 -0500
committerIlia Mirkin <[email protected]>2018-12-30 23:32:21 -0500
commitb04c1907c8c9f4fd66ce4e069665f4c40e3d40e0 (patch)
tree6af1861e4ff533cc0d5752e727aa70ee21cbd9b0 /src
parentb34cfd474961bef6cb245e02a6dba7db0cf12ce6 (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')
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_miptree.c39
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,