mesa: Use atomics for shared VAO reference counts.
authorMathias Fröhlich <mathias.froehlich@web.de>
Sat, 3 Feb 2018 14:22:33 +0000 (15:22 +0100)
committerMathias Fröhlich <mathias.froehlich@web.de>
Fri, 23 Feb 2018 04:34:11 +0000 (05:34 +0100)
VAOs will be used in the next change as immutable object across multiple
contexts. Only reference counting may write concurrently on the VAO. So,
make the reference count thread safe for those and only those VAO objects.

v3: Use bool/true/false for gl_vertex_array_object::SharedAndImmutable.

Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/main/arrayobj.c
src/mesa/main/arrayobj.h
src/mesa/main/mtypes.h

index cf9c5d7ecc7e7e47e41cf76c06df5acf18de8ad0..2526404fda31b214a184e257faa9d8a04ec92a1f 100644 (file)
@@ -53,6 +53,7 @@
 #include "varray.h"
 #include "main/dispatch.h"
 #include "util/bitscan.h"
+#include "util/u_atomic.h"
 
 
 const GLubyte
@@ -331,10 +332,16 @@ _mesa_reference_vao_(struct gl_context *ctx,
       /* Unreference the old array object */
       struct gl_vertex_array_object *oldObj = *ptr;
 
-      assert(oldObj->RefCount > 0);
-      oldObj->RefCount--;
+      bool deleteFlag;
+      if (oldObj->SharedAndImmutable) {
+         deleteFlag = p_atomic_dec_zero(&oldObj->RefCount);
+      } else {
+         assert(oldObj->RefCount > 0);
+         oldObj->RefCount--;
+         deleteFlag = (oldObj->RefCount == 0);
+      }
 
-      if (oldObj->RefCount == 0)
+      if (deleteFlag)
          _mesa_delete_vao(ctx, oldObj);
 
       *ptr = NULL;
@@ -343,9 +350,13 @@ _mesa_reference_vao_(struct gl_context *ctx,
 
    if (vao) {
       /* reference new array object */
-      assert(vao->RefCount > 0);
+      if (vao->SharedAndImmutable) {
+         p_atomic_inc(&vao->RefCount);
+      } else {
+         assert(vao->RefCount > 0);
+         vao->RefCount++;
+      }
 
-      vao->RefCount++;
       *ptr = vao;
    }
 }
@@ -407,6 +418,7 @@ _mesa_initialize_vao(struct gl_context *ctx,
    vao->Name = name;
 
    vao->RefCount = 1;
+   vao->SharedAndImmutable = false;
 
    /* Init the individual arrays */
    for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) {
@@ -452,6 +464,9 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
 {
    GLbitfield arrays = vao->NewArrays;
 
+   /* Make sure we do not run into problems with shared objects */
+   assert(!vao->SharedAndImmutable || vao->NewArrays == 0);
+
    while (arrays) {
       const int attrib = u_bit_scan(&arrays);
       struct gl_vertex_array *array = &vao->_VertexArray[attrib];
@@ -465,6 +480,16 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
 }
 
 
+void
+_mesa_set_vao_immutable(struct gl_context *ctx,
+                        struct gl_vertex_array_object *vao)
+{
+   _mesa_update_vao_derived_arrays(ctx, vao);
+   vao->NewArrays = 0;
+   vao->SharedAndImmutable = true;
+}
+
+
 bool
 _mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao)
 {
index 5de74505bb80285d360a66e6c2a93b1c51858f29..8da5c9ffe017b6781258ca324e06540366281112 100644 (file)
@@ -81,6 +81,15 @@ extern void
 _mesa_update_vao_derived_arrays(struct gl_context *ctx,
                                 struct gl_vertex_array_object *vao);
 
+
+/**
+ * Mark the vao as shared and immutable, do remaining updates.
+ */
+extern void
+_mesa_set_vao_immutable(struct gl_context *ctx,
+                        struct gl_vertex_array_object *vao);
+
+
 /* Returns true if all varying arrays reside in vbos */
 extern bool
 _mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao);
index bdecd422a9af888e94f687904f92b3f77a6cbf74..15f39cbacc33c876d14ab9c559cc982ff3f3c924 100644 (file)
@@ -1607,6 +1607,13 @@ struct gl_vertex_array_object
     */
    GLboolean EverBound;
 
+   /**
+    * Marked to true if the object is shared between contexts and immutable.
+    * Then reference counting is done using atomics and thread safe.
+    * Is used for dlist VAOs.
+    */
+   bool SharedAndImmutable;
+
    /**
     * Derived vertex attribute arrays
     *