[Nouveau] [PATCH] nv50/nvc0: make transfers aware of PIPE_TRANSFER_MAP_DIRECTLY

Marcin Slusarz marcin.slusarz at gmail.com
Sun May 8 15:39:00 PDT 2011


If state tracker asked us to map resource directly and we can't
do it (because of tiling), return NULL instead of doing full transfer
- state tracker should handle it and fallback to some other method
or repeat transfer without PIPE_TRANSFER_MAP_DIRECTLY.

It greatly improves performance of xorg state tracker on nv50+,
because fallback (DFS/UTS) is much faster than full transfer.
---
 src/gallium/drivers/nv50/nv50_transfer.c |   31 +++++++++++++++++++---------
 src/gallium/drivers/nvc0/nvc0_transfer.c |   32 ++++++++++++++++++++---------
 2 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index 7486977..13ac372 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -209,6 +209,10 @@ nv50_miptree_transfer_new(struct pipe_context *pctx,
    uint32_t w, h, d, z, layer;
    int ret;
 
+   if ((usage & PIPE_TRANSFER_MAP_DIRECTLY) &&
+         nouveau_bo_tile_layout(mt->base.bo))
+      return NULL;
+
    if (mt->layout_3d) {
       z = box->z;
       d = u_minify(res->depth0, level);
@@ -252,6 +256,11 @@ nv50_miptree_transfer_new(struct pipe_context *pctx,
    tx->rect[0].pitch = lvl->pitch;
    tx->rect[0].domain = NOUVEAU_BO_VRAM;
 
+   if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
+      tx->rect[1] = tx->rect[0];
+      return &tx->base;
+   }
+
    size = tx->base.layer_stride;
 
    ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
@@ -296,19 +305,21 @@ nv50_miptree_transfer_del(struct pipe_context *pctx,
    struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
    unsigned i;
 
-   if (tx->base.usage & PIPE_TRANSFER_WRITE) {
-      for (i = 0; i < tx->base.box.depth; ++i) {
-         nv50_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
-                                 tx->nblocksx, tx->nblocksy);
-         if (mt->layout_3d)
-            tx->rect[0].z++;
-         else
-            tx->rect[0].base += mt->layer_stride;
-         tx->rect[1].base += tx->nblocksy * tx->base.stride;
+   if (!(tx->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
+      if (tx->base.usage & PIPE_TRANSFER_WRITE) {
+         for (i = 0; i < tx->base.box.depth; ++i) {
+            nv50_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
+                                    tx->nblocksx, tx->nblocksy);
+            if (mt->layout_3d)
+               tx->rect[0].z++;
+            else
+               tx->rect[0].base += mt->layer_stride;
+            tx->rect[1].base += tx->nblocksy * tx->base.stride;
+         }
       }
+      nouveau_bo_ref(NULL, &tx->rect[1].bo);
    }
 
-   nouveau_bo_ref(NULL, &tx->rect[1].bo);
    pipe_resource_reference(&transfer->resource, NULL);
 
    FREE(tx);
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
index 7bbfe05..6a2721c 100644
--- a/src/gallium/drivers/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
@@ -246,6 +246,10 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    uint32_t w, h, d, z, layer;
    int ret;
 
+   if ((usage & PIPE_TRANSFER_MAP_DIRECTLY) &&
+         nouveau_bo_tile_layout(mt->base.bo))
+      return NULL;
+
    tx = CALLOC_STRUCT(nvc0_transfer);
    if (!tx)
       return NULL;
@@ -290,6 +294,11 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    tx->rect[0].pitch = lvl->pitch;
    tx->rect[0].domain = NOUVEAU_BO_VRAM;
 
+   if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
+      tx->rect[1] = tx->rect[0];
+      return &tx->base;
+   }
+
    size = tx->base.layer_stride;
 
    ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
@@ -334,19 +343,22 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx,
    struct nvc0_miptree *mt = nvc0_miptree(tx->base.resource);
    unsigned i;
 
-   if (tx->base.usage & PIPE_TRANSFER_WRITE) {
-      for (i = 0; i < tx->nlayers; ++i) {
-         nvc0_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
-                                 tx->nblocksx, tx->nblocksy);
-         if (mt->layout_3d)
-            tx->rect[0].z++;
-         else
-            tx->rect[0].base += mt->layer_stride;
-         tx->rect[1].base += tx->nblocksy * tx->base.stride;
+   if (!(tx->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
+      if (tx->base.usage & PIPE_TRANSFER_WRITE) {
+         for (i = 0; i < tx->nlayers; ++i) {
+            nvc0_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
+                                    tx->nblocksx, tx->nblocksy);
+            if (mt->layout_3d)
+               tx->rect[0].z++;
+            else
+               tx->rect[0].base += mt->layer_stride;
+            tx->rect[1].base += tx->nblocksy * tx->base.stride;
+         }
       }
+
+      nouveau_bo_ref(NULL, &tx->rect[1].bo);
    }
 
-   nouveau_bo_ref(NULL, &tx->rect[1].bo);
    pipe_resource_reference(&transfer->resource, NULL);
 
    FREE(tx);
-- 
1.7.4.1



More information about the Nouveau mailing list