nv50,nvc0: add invalidate_resource support for buffer resources
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 3 Apr 2016 19:11:39 +0000 (15:11 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sat, 9 Apr 2016 18:55:43 +0000 (14:55 -0400)
Provide a callback to reallocate the underlying storage of a resource so
that it is not bound to any existing fences.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nouveau_buffer.c
src/gallium/drivers/nouveau/nouveau_buffer.h
src/gallium/drivers/nouveau/nv50/nv50_resource.c
src/gallium/drivers/nouveau/nv50/nv50_resource.h
src/gallium/drivers/nouveau/nv50/nv50_screen.c
src/gallium/drivers/nouveau/nvc0/nvc0_resource.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c

index 1695553d793e9e451a5f8716ca076855215f746e..ba43a614b90fbd73338757913a6685b58866ab26 100644 (file)
@@ -843,6 +843,39 @@ nouveau_user_buffer_upload(struct nouveau_context *nv,
    return true;
 }
 
+/* Invalidate underlying buffer storage, reset fences, reallocate to non-busy
+ * buffer.
+ */
+void
+nouveau_buffer_invalidate(struct pipe_context *pipe,
+                          struct pipe_resource *resource)
+{
+   struct nouveau_context *nv = nouveau_context(pipe);
+   struct nv04_resource *buf = nv04_resource(resource);
+   int ref = buf->base.reference.count - 1;
+
+   /* Shared buffers shouldn't get reallocated */
+   if (unlikely(buf->base.bind & PIPE_BIND_SHARED))
+      return;
+
+   /* We can't touch persistent/coherent buffers */
+   if (buf->base.flags & (PIPE_RESOURCE_FLAG_MAP_PERSISTENT |
+                          PIPE_RESOURCE_FLAG_MAP_COHERENT))
+      return;
+
+   /* If the buffer is sub-allocated and not currently being written, just
+    * wipe the valid buffer range. Otherwise we have to create fresh
+    * storage. (We don't keep track of fences for non-sub-allocated BO's.)
+    */
+   if (buf->mm && !nouveau_buffer_busy(buf, PIPE_TRANSFER_WRITE)) {
+      util_range_set_empty(&buf->valid_buffer_range);
+   } else {
+      nouveau_buffer_reallocate(nv->screen, buf, buf->domain);
+      if (ref > 0) /* any references inside context possible ? */
+         nv->invalidate_resource_storage(nv, &buf->base, ref);
+   }
+}
+
 
 /* Scratch data allocation. */
 
index d45bf7aebcfbc397603b54a046407fd230414fb8..3a33fae9ce2fa3fd668d52f9010945aca4fef60a 100644 (file)
@@ -99,6 +99,10 @@ bool
 nouveau_user_buffer_upload(struct nouveau_context *, struct nv04_resource *,
                            unsigned base, unsigned size);
 
+void
+nouveau_buffer_invalidate(struct pipe_context *pipe,
+                          struct pipe_resource *resource);
+
 /* Copy data to a scratch buffer and return address & bo the data resides in.
  * Returns 0 on failure.
  */
index ad5f3b814db80d0a3c83dd5a001f38ef08c72e53..b090a30aed6bffb1d596c4cd55bd7bf3ca40ce33 100644 (file)
@@ -84,6 +84,13 @@ nv50_surface_destroy(struct pipe_context *pipe, struct pipe_surface *ps)
    FREE(s);
 }
 
+void
+nv50_invalidate_resource(struct pipe_context *pipe, struct pipe_resource *res)
+{
+   if (res->target == PIPE_BUFFER)
+      nouveau_buffer_invalidate(pipe, res);
+}
+
 void
 nv50_init_resource_functions(struct pipe_context *pcontext)
 {
@@ -93,6 +100,7 @@ nv50_init_resource_functions(struct pipe_context *pcontext)
    pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
    pcontext->create_surface = nv50_surface_create;
    pcontext->surface_destroy = nv50_surface_destroy;
+   pcontext->invalidate_resource = nv50_invalidate_resource;
 }
 
 void
index b40370a1d78212acf2ed1db1272c20d6910c008e..5d03925b0d05df9616716d792e26918bb3340b68 100644 (file)
@@ -151,6 +151,9 @@ nv50_surface_from_buffer(struct pipe_context *pipe,
 void
 nv50_surface_destroy(struct pipe_context *, struct pipe_surface *);
 
+void
+nv50_invalidate_resource(struct pipe_context *, struct pipe_resource *);
+
 void
 nv50_clear_texture(struct pipe_context *pipe,
                    struct pipe_resource *res,
index 20fb61b51f42cc7679e55e321a14cc75ff60a2bd..4968783b480f2138c31b2a4717c72b4036c5f489 100644 (file)
@@ -193,6 +193,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_CLEAR_TEXTURE:
    case PIPE_CAP_COMPUTE:
    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
+   case PIPE_CAP_INVALIDATE_BUFFER:
       return 1;
    case PIPE_CAP_SEAMLESS_CUBE_MAP:
       return 1; /* class_3d >= NVA0_3D_CLASS; */
@@ -234,7 +235,6 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
    case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
-   case PIPE_CAP_INVALIDATE_BUFFER:
    case PIPE_CAP_GENERATE_MIPMAP:
    case PIPE_CAP_STRING_MARKER:
    case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY:
index c034d0fd011c601c964a55d5b8b79cdf452f1016..0aee5890fd88b677c98cffb9ca6fb9491a5975a3 100644 (file)
@@ -52,6 +52,7 @@ nvc0_init_resource_functions(struct pipe_context *pcontext)
    pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
    pcontext->create_surface = nvc0_surface_create;
    pcontext->surface_destroy = nv50_surface_destroy;
+   pcontext->invalidate_resource = nv50_invalidate_resource;
 }
 
 void
index c41912a60374e87a4bfae9f7601cf079d02b9967..a2ea660fa131364f8f27d1c06a4c4466eca99e6e 100644 (file)
@@ -216,6 +216,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
    case PIPE_CAP_QUERY_BUFFER_OBJECT:
+   case PIPE_CAP_INVALIDATE_BUFFER:
       return 1;
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
@@ -241,7 +242,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
    case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
    case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
-   case PIPE_CAP_INVALIDATE_BUFFER:
    case PIPE_CAP_GENERATE_MIPMAP:
    case PIPE_CAP_STRING_MARKER:
    case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY: