Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-09-27 23:42:57 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-09-29 16:28:15 +0300
commitf6fc863acd7c24874026202d4c2aec50c60b40d2 (patch)
tree541dab504b4a4132869d4ba982c42aeca049f661 /source/blender/gpu
parentc931a0057ffea26175a2dc111718e5f3590b00f8 (diff)
Sculpt: multithread GPU draw buffer filling for workbench
This improves performance of some sculpt tools, particularly those that modify many vertices like filter and mask tools, or use brushes with large radius. For mask expand it can make updates up to 2x faster on heavy meshes, but for most tools it's more on the order of 1-1.1x. There are bigger bottlenecks to solve, like normal updates. Ref T70295 Differential Revision: https://developer.blender.org/D5926
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_buffers.h20
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c151
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c4
-rw-r--r--source/blender/gpu/intern/gpu_private.h4
4 files changed, 111 insertions, 68 deletions
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 9009c134837..552bad2b0d6 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -41,7 +41,8 @@ struct PBVH;
/* Buffers for drawing from PBVH grids. */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
-/* build */
+/* Build must be called once before using the other functions, used every time
+ * mesh topology changes. Threaded. */
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
const struct MPoly *mpoly,
const struct MLoop *mloop,
@@ -54,8 +55,13 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, unsigned int **grid_h
GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading);
-/* update */
+/* Free part of data for update. Not thread safe, must run in OpenGL main thread. */
+void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers);
+void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
+ const struct DMFlagMat *grid_flag_mats,
+ int *grid_indices);
+/* Update mesh buffers without topology changes. Threaded. */
enum {
GPU_PBVH_BUFFERS_SHOW_MASK = (1 << 1),
GPU_PBVH_BUFFERS_SHOW_VCOL = (1 << 1),
@@ -85,6 +91,12 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
const struct CCGKey *key,
const int update_flags);
+/* Finish update. Not thread safe, must run in OpenGL main thread. */
+void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers);
+
+/* Free buffers. Not thread safe, must run in OpenGL main thread. */
+void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers);
+
/* draw */
struct GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires);
@@ -92,8 +104,4 @@ short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers);
bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers);
-void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers);
-
-void GPU_pbvh_fix_linking(void);
-
#endif
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 3511c7438cb..cf9a8142530 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -45,6 +45,8 @@
#include "GPU_buffers.h"
#include "GPU_batch.h"
+#include "gpu_private.h"
+
#include "bmesh.h"
/* XXX: the rest of the code in this file is used for optimized PBVH
@@ -78,6 +80,7 @@ struct GPU_PBVH_Buffers {
int totgrid;
bool use_bmesh;
+ bool clear_bmesh_on_flush;
uint tot_tri, tot_quad;
@@ -91,8 +94,9 @@ struct GPU_PBVH_Buffers {
};
static struct {
+ GPUVertFormat format;
uint pos, nor, msk, col;
-} g_vbo_id = {0};
+} g_vbo_id = {{0}};
/** \} */
@@ -100,6 +104,27 @@ static struct {
/** \name PBVH Utils
* \{ */
+void gpu_pbvh_init()
+{
+ /* Initialize vertex buffer (match 'VertexBufferFormat'). */
+ if (g_vbo_id.format.attr_len == 0) {
+ g_vbo_id.pos = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ g_vbo_id.nor = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */
+ g_vbo_id.msk = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ g_vbo_id.col = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "ac", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+}
+
+void gpu_pbvh_exit()
+{
+ /* Nothing to do. */
+}
+
/* Allocates a non-initialized buffer to be sent to GPU.
* Return is false it indicates that the memory map failed. */
static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
@@ -110,14 +135,7 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
#if 0
if (buffers->vert_buf == NULL) {
/* Initialize vertex buffer (match 'VertexBufferFormat'). */
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- g_vbo_id.nor = GPU_vertformat_attr_add(
- &format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- g_vbo_id.msk = GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
- buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DYNAMIC);
+ buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&g_vbo_id.format, GPU_USAGE_DYNAMIC);
GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
}
else if (vert_len != buffers->vert_buf->vertex_len) {
@@ -126,30 +144,16 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
#else
if (buffers->vert_buf == NULL) {
/* Initialize vertex buffer (match 'VertexBufferFormat'). */
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- g_vbo_id.nor = GPU_vertformat_attr_add(
- &format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */
- g_vbo_id.msk = GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- g_vbo_id.col = GPU_vertformat_attr_add(
- &format, "ac", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
- buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
+ buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&g_vbo_id.format, GPU_USAGE_STATIC);
}
GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
#endif
+
return buffers->vert_buf->data != NULL;
}
static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
{
- /* force flushing to the GPU */
- if (buffers->vert_buf->data) {
- GPU_vertbuf_use(buffers->vert_buf);
- }
-
if (buffers->triangles == NULL) {
buffers->triangles = GPU_batch_create(prim,
buffers->vert_buf,
@@ -180,6 +184,7 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
/** \name Mesh PBVH
* \{ */
+/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MVert *mvert,
const int *vert_indices,
@@ -298,6 +303,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->mvert = mvert;
}
+/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
const MPoly *mpoly,
const MLoop *mloop,
@@ -336,11 +342,6 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
return buffers;
}
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_BATCH_DISCARD_SAFE(buffers->lines);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
-
/* An element index buffer is used for smooth shading, but flat
* shading requires separate vertex normals so an index buffer
* can't be used there. */
@@ -537,6 +538,27 @@ static void gpu_pbvh_grid_fill_index_buffers(
buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast);
}
+void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
+ const struct DMFlagMat *grid_flag_mats,
+ int *grid_indices)
+{
+ const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
+
+ if (buffers->smooth != smooth) {
+ buffers->smooth = smooth;
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_BATCH_DISCARD_SAFE(buffers->lines_fast);
+
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast);
+ }
+}
+
+/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
CCGElem **grids,
const DMFlagMat *grid_flag_mats,
@@ -550,26 +572,13 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
bool empty_mask = true;
int i, j, k, x, y;
- const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
-
/* Build VBO */
const int has_mask = key->has_mask;
- uint vert_per_grid = (smooth) ? key->grid_area : (SQUARE(key->grid_size - 1) * 4);
- uint vert_count = totgrid * vert_per_grid;
-
- if (buffers->smooth != smooth) {
- buffers->smooth = smooth;
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast);
- GPU_BATCH_DISCARD_SAFE(buffers->lines);
- GPU_BATCH_DISCARD_SAFE(buffers->lines_fast);
+ buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast);
- }
+ uint vert_per_grid = (buffers->smooth) ? key->grid_area : (SQUARE(key->grid_size - 1) * 4);
+ uint vert_count = totgrid * vert_per_grid;
if (buffers->index_buf == NULL) {
uint visible_quad_len = BKE_pbvh_count_grid_quads(
@@ -692,6 +701,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->show_mask = !empty_mask;
}
+/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden)
{
GPU_PBVH_Buffers *buffers;
@@ -796,8 +806,24 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces)
return totface;
}
+void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
+{
+ if (buffers->smooth) {
+ /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ }
+ else {
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ }
+}
+
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
- * shading, an element index buffer. */
+ * shading, an element index buffer.
+ * Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
BMesh *bm,
GSet *bm_faces,
@@ -815,17 +841,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
tottri = gpu_bmesh_face_visible_count(bm_faces);
if (buffers->smooth) {
- /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_BATCH_DISCARD_SAFE(buffers->lines);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
/* Count visible vertices */
totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
}
else {
- GPU_BATCH_DISCARD_SAFE(buffers->lines);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
totvert = tottri * 3;
}
@@ -834,9 +853,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
/* Node is just hidden. */
}
else {
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
- GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ buffers->clear_bmesh_on_flush = true;
}
buffers->tot_tri = 0;
return;
@@ -991,6 +1008,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
/** \name Generic
* \{ */
+/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
{
GPU_PBVH_Buffers *buffers;
@@ -1023,6 +1041,21 @@ short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers)
return buffers->material_index;
}
+void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers)
+{
+ /* Free empty bmesh node buffers. */
+ if (buffers->clear_bmesh_on_flush) {
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ }
+
+ /* Force flushing to the GPU. */
+ if (buffers->vert_buf && buffers->vert_buf->data) {
+ GPU_vertbuf_use(buffers->vert_buf);
+ }
+}
+
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
@@ -1041,7 +1074,3 @@ void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
}
/** \} */
-
-void GPU_pbvh_fix_linking()
-{
-}
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 2f84a1cbd27..0009e7d8c47 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -62,11 +62,13 @@ void GPU_init(void)
immInit();
}
- GPU_pbvh_fix_linking();
+ gpu_pbvh_init();
}
void GPU_exit(void)
{
+ gpu_pbvh_exit();
+
if (!G.background) {
immDestroy();
}
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index 43b2da13e28..b9af8f1b38c 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -33,4 +33,8 @@ void gpu_debug_exit(void);
void gpu_framebuffer_module_init(void);
void gpu_framebuffer_module_exit(void);
+/* gpu_pbvh.c */
+void gpu_pbvh_init(void);
+void gpu_pbvh_exit(void);
+
#endif /* __GPU_PRIVATE_H__ */