[Mesa-dev] [PATCH 57/84] st/nine: Implement Fast path for dynamic buffers and csmt

Axel Davy axel.davy at ens.fr
Wed Dec 7 22:55:30 UTC 2016


Use the secondary pipe for DISCARD/NOOVERWRITE, which
avoids stalling to get the pipe from the worker thread.

Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
 src/gallium/state_trackers/nine/buffer9.c      | 62 ++++++++++++++++++++++----
 src/gallium/state_trackers/nine/buffer9.h      |  7 ++-
 src/gallium/state_trackers/nine/indexbuffer9.c |  2 +
 3 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/src/gallium/state_trackers/nine/buffer9.c b/src/gallium/state_trackers/nine/buffer9.c
index 726408a..7a2145d 100644
--- a/src/gallium/state_trackers/nine/buffer9.c
+++ b/src/gallium/state_trackers/nine/buffer9.c
@@ -32,6 +32,7 @@
 #include "pipe/p_defines.h"
 #include "pipe/p_format.h"
 #include "util/u_box.h"
+#include "util/u_inlines.h"
 
 #define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER)
 
@@ -50,7 +51,7 @@ NineBuffer9_ctor( struct NineBuffer9 *This,
 
     user_assert(Pool != D3DPOOL_SCRATCH, D3DERR_INVALIDCALL);
 
-    This->maps = MALLOC(sizeof(struct pipe_transfer *));
+    This->maps = MALLOC(sizeof(struct NineTransfer));
     if (!This->maps)
         return E_OUTOFMEMORY;
     This->nmaps = 0;
@@ -169,6 +170,25 @@ NineBuffer9_GetResource( struct NineBuffer9 *This )
     return NineResource9_GetResource(&This->base);
 }
 
+static void
+NineBuffer9_RebindIfRequired( struct NineBuffer9 *This,
+                              struct NineDevice9 *device )
+{
+    int i;
+
+    if (!This->bind_count)
+        return;
+    for (i = 0; i < device->caps.MaxStreams; i++) {
+        if (device->state.stream[i] == (struct NineVertexBuffer9 *)This)
+            nine_context_set_stream_source(device, i,
+                                           (struct NineVertexBuffer9 *)This,
+                                           device->state.vtxbuf[i].buffer_offset,
+                                           device->state.vtxbuf[i].stride);
+    }
+    if (device->state.idxbuf == (struct NineIndexBuffer9 *)This)
+        nine_context_set_indices(device, (struct NineIndexBuffer9 *)This);
+}
+
 HRESULT NINE_WINAPI
 NineBuffer9_Lock( struct NineBuffer9 *This,
                         UINT OffsetToLock,
@@ -176,6 +196,7 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
                         void **ppbData,
                         DWORD Flags )
 {
+    struct NineDevice9 *device = This->base.base.device;
     struct pipe_box box;
     struct pipe_context *pipe;
     void *data;
@@ -237,9 +258,9 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
         usage |= PIPE_TRANSFER_DONTBLOCK;
 
     if (This->nmaps == This->maxmaps) {
-        struct pipe_transfer **newmaps =
-            REALLOC(This->maps, sizeof(struct pipe_transfer *)*This->maxmaps,
-                    sizeof(struct pipe_transfer *)*(This->maxmaps << 1));
+        struct NineTransfer *newmaps =
+            REALLOC(This->maps, sizeof(struct NineTransfer)*This->maxmaps,
+                    sizeof(struct NineTransfer)*(This->maxmaps << 1));
         if (newmaps == NULL)
             return E_OUTOFMEMORY;
 
@@ -247,9 +268,29 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
         This->maps = newmaps;
     }
 
-    pipe = NineDevice9_GetPipe(This->base.base.device);
+    This->maps[This->nmaps].is_pipe_secondary = FALSE;
+
+    if (Flags & D3DLOCK_DISCARD && device->csmt_active) {
+        struct pipe_screen *screen = NineDevice9_GetScreen(device);
+        struct pipe_resource *new_res = screen->resource_create(screen, &This->base.info);
+        if (new_res) {
+            /* Use the new resource */
+            pipe_resource_reference(&This->base.resource, new_res);
+            pipe_resource_reference(&new_res, NULL);
+            usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED;
+            NineBuffer9_RebindIfRequired(This, device);
+            This->maps[This->nmaps].is_pipe_secondary = TRUE;
+        }
+    } else if (Flags & D3DLOCK_NOOVERWRITE && device->csmt_active)
+        This->maps[This->nmaps].is_pipe_secondary = TRUE;
+
+    if (This->maps[This->nmaps].is_pipe_secondary)
+        pipe = device->pipe_secondary;
+    else
+        pipe = NineDevice9_GetPipe(device);
+
     data = pipe->transfer_map(pipe, This->base.resource, 0,
-                              usage, &box, &This->maps[This->nmaps]);
+                              usage, &box, &This->maps[This->nmaps].transfer);
 
     if (!data) {
         DBG("pipe::transfer_map failed\n"
@@ -273,15 +314,18 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
 HRESULT NINE_WINAPI
 NineBuffer9_Unlock( struct NineBuffer9 *This )
 {
+    struct NineDevice9 *device = This->base.base.device;
     struct pipe_context *pipe;
     DBG("This=%p\n", This);
 
     user_assert(This->nmaps > 0, D3DERR_INVALIDCALL);
+    This->nmaps--;
     if (This->base.pool != D3DPOOL_MANAGED) {
-        pipe = NineDevice9_GetPipe(This->base.base.device);
-        pipe->transfer_unmap(pipe, This->maps[--(This->nmaps)]);
+        pipe = This->maps[This->nmaps].is_pipe_secondary ?
+            device->pipe_secondary :
+            NineDevice9_GetPipe(device);
+        pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer);
     } else {
-        This->nmaps--;
         BASEBUF_REGISTER_UPDATE(This);
     }
     return D3D_OK;
diff --git a/src/gallium/state_trackers/nine/buffer9.h b/src/gallium/state_trackers/nine/buffer9.h
index 49b67a9..d8024e4 100644
--- a/src/gallium/state_trackers/nine/buffer9.h
+++ b/src/gallium/state_trackers/nine/buffer9.h
@@ -34,12 +34,17 @@ struct pipe_screen;
 struct pipe_context;
 struct pipe_transfer;
 
+struct NineTransfer {
+    struct pipe_transfer *transfer;
+    bool is_pipe_secondary;
+};
+
 struct NineBuffer9
 {
     struct NineResource9 base;
 
     /* G3D */
-    struct pipe_transfer **maps;
+    struct NineTransfer *maps;
     int nmaps, maxmaps;
     UINT size;
 
diff --git a/src/gallium/state_trackers/nine/indexbuffer9.c b/src/gallium/state_trackers/nine/indexbuffer9.c
index 4e65ed7..4029a8d 100644
--- a/src/gallium/state_trackers/nine/indexbuffer9.c
+++ b/src/gallium/state_trackers/nine/indexbuffer9.c
@@ -76,6 +76,8 @@ NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This )
 const struct pipe_index_buffer *
 NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This )
 {
+    /* The resource may change */
+    This->buffer.buffer = NineIndexBuffer9_GetResource(This);
     return &This->buffer;
 }
 
-- 
2.10.2



More information about the mesa-dev mailing list