From 8e1dd58a7e76834c1fb6d117b6ea5755e05cfb77 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Wed, 3 Apr 2013 00:18:55 +0200 Subject: [PATCH] nvc0: place staging textures in GART and map them directly --- src/gallium/drivers/nv50/nv50_miptree.c | 6 +-- src/gallium/drivers/nv50/nv50_resource.h | 2 +- src/gallium/drivers/nvc0/nvc0_2d.xml.h | 2 +- src/gallium/drivers/nvc0/nvc0_miptree.c | 25 ++++++++++--- src/gallium/drivers/nvc0/nvc0_screen.c | 2 + src/gallium/drivers/nvc0/nvc0_surface.c | 3 +- src/gallium/drivers/nvc0/nvc0_transfer.c | 47 ++++++++++++++++++++++++ 7 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index ed0f8c2b2f1..fe481887570 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -213,7 +213,7 @@ nv50_miptree_init_ms_mode(struct nv50_miptree *mt) } boolean -nv50_miptree_init_layout_linear(struct nv50_miptree *mt) +nv50_miptree_init_layout_linear(struct nv50_miptree *mt, unsigned pitch_align) { struct pipe_resource *pt = &mt->base.base; const unsigned blocksize = util_format_get_blocksize(pt->format); @@ -227,7 +227,7 @@ nv50_miptree_init_layout_linear(struct nv50_miptree *mt) if (mt->ms_x | mt->ms_y) return FALSE; - mt->level[0].pitch = align(pt->width0 * blocksize, 64); + mt->level[0].pitch = align(pt->width0 * blocksize, pitch_align); /* Account for very generous prefetch (allocate size as if tiled). */ h = MAX2(h, 8); @@ -314,7 +314,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, if (bo_config.nv50.memtype != 0) { nv50_miptree_init_layout_tiled(mt); } else - if (!nv50_miptree_init_layout_linear(mt)) { + if (!nv50_miptree_init_layout_linear(mt, 64)) { FREE(mt); return NULL; } diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index a2bc9803fbe..469d812098f 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -67,7 +67,7 @@ nv50_miptree(struct pipe_resource *pt) /* Internal functions: */ boolean -nv50_miptree_init_layout_linear(struct nv50_miptree *mt); +nv50_miptree_init_layout_linear(struct nv50_miptree *mt, unsigned pitch_align); struct pipe_resource * nv50_miptree_create(struct pipe_screen *pscreen, diff --git a/src/gallium/drivers/nvc0/nvc0_2d.xml.h b/src/gallium/drivers/nvc0/nvc0_2d.xml.h index 93dba340899..9a488c17be1 100644 --- a/src/gallium/drivers/nvc0/nvc0_2d.xml.h +++ b/src/gallium/drivers/nvc0/nvc0_2d.xml.h @@ -122,7 +122,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_2D_UNK258 0x00000258 -#define NVC0_2D_UNK260 0x00000260 +#define NVC0_2D_SINGLE_GPC 0x00000260 #define NVC0_2D_COND_ADDRESS_HIGH 0x00000264 diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index 9fcd7886323..2913363bf99 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -158,9 +158,6 @@ nvc0_miptree_init_ms_mode(struct nv50_miptree *mt) return TRUE; } -boolean -nv50_miptree_init_layout_linear(struct nv50_miptree *); - static void nvc0_miptree_init_layout_video(struct nv50_miptree *mt) { @@ -260,6 +257,21 @@ nvc0_miptree_create(struct pipe_screen *pscreen, pipe_reference_init(&pt->reference, 1); pt->screen = pscreen; + if (pt->usage == PIPE_USAGE_STAGING) { + switch (pt->target) { + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + if (pt->last_level == 0 && + !util_format_is_depth_or_stencil(pt->format) && + pt->nr_samples <= 1) + pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR; + break; + default: + break; + } + } + bo_config.nvc0.memtype = nvc0_mt_choose_storage_type(mt, compressed); if (!nvc0_miptree_init_ms_mode(mt)) { @@ -273,13 +285,16 @@ nvc0_miptree_create(struct pipe_screen *pscreen, if (likely(bo_config.nvc0.memtype)) { nvc0_miptree_init_layout_tiled(mt); } else - if (!nv50_miptree_init_layout_linear(mt)) { + if (!nv50_miptree_init_layout_linear(mt, 128)) { FREE(mt); return NULL; } bo_config.nvc0.tile_mode = mt->level[0].tile_mode; - mt->base.domain = NOUVEAU_BO_VRAM; + if (!bo_config.nvc0.memtype && pt->usage == PIPE_USAGE_STAGING) + mt->base.domain = NOUVEAU_BO_GART; + else + mt->base.domain = NOUVEAU_BO_VRAM; bo_flags = mt->base.domain | NOUVEAU_BO_NOSNOOP; diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 3a32539d053..a46fb388e64 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -629,6 +629,8 @@ nvc0_screen_create(struct nouveau_device *dev) BEGIN_NVC0(push, SUBC_2D(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push, screen->eng2d->oclass); + BEGIN_NVC0(push, NVC0_2D(SINGLE_GPC), 1); + PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_2D(OPERATION), 1); PUSH_DATA (push, NVC0_2D_OPERATION_SRCCOPY); BEGIN_NVC0(push, NVC0_2D(CLIP_ENABLE), 1); diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c index 481b4518a67..3abf717a6ee 100644 --- a/src/gallium/drivers/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nvc0/nvc0_surface.c @@ -1108,7 +1108,8 @@ nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) PUSH_DATA (push, srcy >> 32); } } - nvc0_bufctx_fence(nvc0, nvc0->bufctx, FALSE); + nvc0_resource_validate(&dst->base, NOUVEAU_BO_WR); + nvc0_resource_validate(&src->base, NOUVEAU_BO_RD); nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D); diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index bdba83d90fb..3f876622353 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c @@ -328,6 +328,30 @@ nve4_m2mf_copy_linear(struct nouveau_context *nv, nouveau_bufctx_reset(bctx, 0); } + +static INLINE boolean +nvc0_mt_transfer_can_map_directly(struct nv50_miptree *mt) +{ + if (mt->base.domain == NOUVEAU_BO_VRAM) + return FALSE; + if (mt->base.base.usage != PIPE_USAGE_STAGING) + return FALSE; + return !nouveau_bo_memtype(mt->base.bo); +} + +static INLINE boolean +nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage) +{ + if (!mt->base.mm) { + uint32_t access = (usage & PIPE_TRANSFER_WRITE) ? + NOUVEAU_BO_WR : NOUVEAU_BO_RD; + return !nouveau_bo_wait(mt->base.bo, access, nvc0->base.client); + } + if (usage & PIPE_TRANSFER_WRITE) + return !mt->base.fence || nouveau_fence_wait(mt->base.fence); + return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr); +} + void * nvc0_miptree_transfer_map(struct pipe_context *pctx, struct pipe_resource *res, @@ -344,6 +368,16 @@ nvc0_miptree_transfer_map(struct pipe_context *pctx, int ret; unsigned flags = 0; + if (nvc0_mt_transfer_can_map_directly(mt)) { + ret = !nvc0_mt_sync(nvc0, mt, usage); + if (!ret) + ret = nouveau_bo_map(mt->base.bo, 0, NULL); + if (ret && + (usage & PIPE_TRANSFER_MAP_DIRECTLY)) + return NULL; + if (!ret) + usage |= PIPE_TRANSFER_MAP_DIRECTLY; + } else if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; @@ -369,6 +403,12 @@ nvc0_miptree_transfer_map(struct pipe_context *pctx, tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); tx->base.layer_stride = tx->nblocksy * tx->base.stride; + if (usage & PIPE_TRANSFER_MAP_DIRECTLY) { + tx->base.stride = align(tx->base.stride, 128); + *ptransfer = &tx->base; + return mt->base.bo->map + mt->base.offset; + } + nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z); size = tx->base.layer_stride; @@ -437,6 +477,13 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx, struct nv50_miptree *mt = nv50_miptree(tx->base.resource); unsigned i; + if (tx->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) { + pipe_resource_reference(&transfer->resource, NULL); + + FREE(tx); + return; + } + if (tx->base.usage & PIPE_TRANSFER_WRITE) { for (i = 0; i < tx->nlayers; ++i) { nvc0->m2mf_copy_rect(nvc0, &tx->rect[0], &tx->rect[1], -- 2.30.2