aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2020-03-22 14:45:14 -0400
committerMarge Bot <[email protected]>2020-04-30 22:01:55 +0000
commitbefbd54864d2959b83e3d2d46d0825f19cb4fc46 (patch)
tree5bad3284c34e2dbe214caa63ee305382a1b05782
parent7f22e0fd29369f478da1d36520049f001cd698d1 (diff)
glthread: don't use atomics for refcounting to decrease overhead on AMD Zen
Reviewed-by: Pierre-Eric Pelloux-Prayer <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4314>
-rw-r--r--src/mesa/main/glthread.h1
-rw-r--r--src/mesa/main/glthread_bufferobj.c33
2 files changed, 33 insertions, 1 deletions
diff --git a/src/mesa/main/glthread.h b/src/mesa/main/glthread.h
index 4a8ce5abce6..64b82ac1317 100644
--- a/src/mesa/main/glthread.h
+++ b/src/mesa/main/glthread.h
@@ -114,6 +114,7 @@ struct glthread_state
struct gl_buffer_object *upload_buffer;
uint8_t *upload_ptr;
unsigned upload_offset;
+ int upload_buffer_private_refcount;
/** Caps. */
GLboolean SupportsBufferUploads;
diff --git a/src/mesa/main/glthread_bufferobj.c b/src/mesa/main/glthread_bufferobj.c
index 3d393af075b..52828308052 100644
--- a/src/mesa/main/glthread_bufferobj.c
+++ b/src/mesa/main/glthread_bufferobj.c
@@ -97,11 +97,39 @@ _mesa_glthread_upload(struct gl_context *ctx, const void *data,
return;
}
+ if (glthread->upload_buffer_private_refcount > 0) {
+ p_atomic_add(&glthread->upload_buffer->RefCount,
+ -glthread->upload_buffer_private_refcount);
+ glthread->upload_buffer_private_refcount = 0;
+ }
_mesa_reference_buffer_object(ctx, &glthread->upload_buffer, NULL);
glthread->upload_buffer =
new_upload_buffer(ctx, default_size, &glthread->upload_ptr);
glthread->upload_offset = 0;
offset = 0;
+
+ /* Since atomic operations are very very slow when 2 threads are not
+ * sharing one L3 cache (which can happen on AMD Zen), prevent using
+ * atomics as follows:
+ *
+ * This function has to return a buffer reference to the caller.
+ * Instead of atomic_inc for every call, it does all possible future
+ * increments in advance when the upload buffer is allocated.
+ * The maximum number of times the function can be called per upload
+ * buffer is default_size, because the minimum allocation size is 1.
+ * Therefore the function can only return default_size number of
+ * references at most, so we will never need more. This is the number
+ * that is added to RefCount at allocation.
+ *
+ * upload_buffer_private_refcount tracks how many buffer references
+ * are left to return to callers. If the buffer is full and there are
+ * still references left, they are atomically subtracted from RefCount
+ * before the buffer is unreferenced.
+ *
+ * This can increase performance by 20%.
+ */
+ glthread->upload_buffer->RefCount += default_size;
+ glthread->upload_buffer_private_refcount = default_size;
}
/* Upload data. */
@@ -112,8 +140,11 @@ _mesa_glthread_upload(struct gl_context *ctx, const void *data,
glthread->upload_offset = offset + size;
*out_offset = offset;
+
assert(*out_buffer == NULL);
- _mesa_reference_buffer_object(ctx, out_buffer, glthread->upload_buffer);
+ assert(glthread->upload_buffer_private_refcount > 0);
+ *out_buffer = glthread->upload_buffer;
+ glthread->upload_buffer_private_refcount--;
}
/** Tracks the current bindings for the vertex array and index array buffers.