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:
authorJoseph Eagar <joeedh@gmail.com>2021-08-17 06:50:02 +0300
committerJoseph Eagar <joeedh@gmail.com>2021-08-17 06:50:02 +0300
commit9503751c83345b2941a4fc41dcc979ef456b0c5f (patch)
tree3fadb7567304a58ba233c32e017fb2f8f5f41bca /source/blender
parentdcaba4c5e3494240464ed6cc6330f40c30ba0e0e (diff)
Sculpt dyntopo
* Added a limited "fast draw" mode to pbvh drawing that tries to limit data sent to the GPU. - Facesets and mask data are disabled. - Indexed mode is forced. - Does not work (at all) for multires. * Finally fixed some outstanding bmesh sculpt undo bugs: - Forgot to mark pbvh nodes to update their bounds, which produced a bug I had thought was caused by something else. - Hopefully fixed a long-standing occasional memory corruption bug.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h15
-rw-r--r--source/blender/blenkernel/intern/paint.c10
-rw-r--r--source/blender/blenkernel/intern/pbvh.c59
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c49
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h1
-rw-r--r--source/blender/draw/engines/overlay/overlay_sculpt.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c9
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c68
-rw-r--r--source/blender/gpu/GPU_buffers.h8
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c266
-rw-r--r--source/blender/makesdna/DNA_scene_types.h19
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c12
13 files changed, 346 insertions, 174 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 7314a2dc8ff..db091a8b878 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -655,6 +655,8 @@ typedef struct SculptSession {
// id of current stroke, used to detect
// if vertex original data needs to be updated
int stroke_id;
+
+ bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth
} SculptSession;
void BKE_sculptsession_free(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 97d3c77fb50..2f87895b262 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -240,21 +240,24 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
struct CustomData *ldata,
struct CustomData *pdata,
const struct MLoopTri *looptri,
- int looptri_num);
+ int looptri_num,
+ bool fast_draw);
void BKE_pbvh_build_grids(PBVH *pbvh,
struct CCGElem **grids,
int totgrid,
struct CCGKey *key,
void **gridfaces,
struct DMFlagMat *flagmats,
- unsigned int **grid_hidden);
+ unsigned int **grid_hidden,
+ bool fast_draw);
void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset,
- const int cd_dyn_vert);
+ const int cd_dyn_vert,
+ bool fast_draw);
void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset,
@@ -682,10 +685,10 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
-bool pbvh_has_mask(const PBVH *pbvh);
+bool BKE_pbvh_draw_mask(const PBVH *pbvh);
void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
-bool pbvh_has_face_sets(PBVH *pbvh);
+bool BKE_pbvh_draw_face_sets(PBVH *pbvh);
void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
/* Parallelization */
@@ -740,6 +743,8 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, struc
#define DYNTOPO_DYNAMIC_TESS
+PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 6463fcf8780..2cc5561000b 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1701,6 +1701,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
}
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
+ ss->fast_draw = (scene->toolsettings->sculpt->flags & SCULPT_FAST_DRAW) != 0;
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh);
@@ -2137,7 +2138,8 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
ob->sculpt->bm_log,
ob->sculpt->cd_vert_node_offset,
ob->sculpt->cd_face_node_offset,
- ob->sculpt->cd_dyn_vert);
+ ob->sculpt->cd_dyn_vert,
+ ob->sculpt->fast_draw);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, false);
@@ -2167,7 +2169,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
&me->ldata,
&me->pdata,
looptri,
- looptris_num);
+ looptris_num,
+ ob->sculpt->fast_draw);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
@@ -2199,7 +2202,8 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
&key,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_flag_mats,
- subdiv_ccg->grid_hidden);
+ subdiv_ccg->grid_hidden,
+ ob->sculpt->fast_draw);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
return pbvh;
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index abadab127a8..52058661da6 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -591,7 +591,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
struct CustomData *ldata,
struct CustomData *pdata,
const MLoopTri *looptri,
- int looptri_num)
+ int looptri_num,
+ bool fast_draw)
{
BBC *prim_bbc = NULL;
BB cb;
@@ -639,6 +640,10 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
}
+ if (fast_draw) {
+ pbvh->flags |= PBVH_FAST_DRAW;
+ }
+
MEM_freeN(prim_bbc);
MEM_freeN(pbvh->vert_bitmap);
}
@@ -650,7 +655,8 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
CCGKey *key,
void **gridfaces,
DMFlagMat *flagmats,
- BLI_bitmap **grid_hidden)
+ BLI_bitmap **grid_hidden,
+ bool fast_draw)
{
const int gridsize = key->grid_size;
@@ -689,6 +695,10 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh_build(pbvh, &cb, prim_bbc, totgrid);
}
+ if (fast_draw) {
+ pbvh->flags |= PBVH_FAST_DRAW;
+ }
+
MEM_freeN(prim_bbc);
}
@@ -1454,20 +1464,11 @@ void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node)
}
}
-static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
+ATTR_NO_OPT static void pbvh_update_draw_buffers(PBVH *pbvh,
+ PBVHNode **nodes,
+ int totnode,
+ int update_flag)
{
- if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
- /* Free buffers uses OpenGL, so not in parallel. */
- for (int n = 0; n < totnode; n++) {
- PBVHNode *node = nodes[n];
- if (node->flag & PBVH_RebuildDrawBuffers) {
- pbvh_free_all_draw_buffers(node);
- }
- else if ((node->flag & PBVH_UpdateDrawBuffers)) {
- pbvh_update_free_all_draw_buffers(pbvh, node);
- }
- }
- }
CustomData *vdata;
CustomData *ldata;
@@ -1486,7 +1487,21 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
ldata = pbvh->ldata;
}
- GPU_pbvh_update_attribute_names(vdata, ldata, GPU_pbvh_need_full_render_get());
+ GPU_pbvh_update_attribute_names(
+ vdata, ldata, GPU_pbvh_need_full_render_get(), pbvh->flags & PBVH_FAST_DRAW);
+
+ if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
+ /* Free buffers uses OpenGL, so not in parallel. */
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ if (node->flag & PBVH_RebuildDrawBuffers) {
+ pbvh_free_all_draw_buffers(node);
+ }
+ else if ((node->flag & PBVH_UpdateDrawBuffers)) {
+ pbvh_update_free_all_draw_buffers(pbvh, node);
+ }
+ }
+ }
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data = {
@@ -3252,8 +3267,12 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
}
}
-bool pbvh_has_mask(const PBVH *pbvh)
+bool BKE_pbvh_draw_mask(const PBVH *pbvh)
{
+ if (pbvh->flags & PBVH_FAST_DRAW) {
+ return false;
+ }
+
switch (pbvh->type) {
case PBVH_GRIDS:
return (pbvh->gridkey.has_mask != 0);
@@ -3286,8 +3305,12 @@ SculptFaceRef BKE_pbvh_table_index_to_face(PBVH *pbvh, int idx)
return BKE_pbvh_make_fref(idx);
}
-bool pbvh_has_face_sets(PBVH *pbvh)
+bool BKE_pbvh_draw_face_sets(PBVH *pbvh)
{
+ if (pbvh->flags & PBVH_FAST_DRAW) {
+ return false;
+ }
+
switch (pbvh->type) {
case PBVH_GRIDS:
return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index e2f926fa2f8..f8f3beaccaa 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -545,11 +545,13 @@ void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f)
static void pbvh_bmesh_regen_node_verts(PBVH *pbvh, PBVHNode *node)
{
- int usize = BLI_table_gset_len(node->bm_other_verts);
+ node->flag &= ~PBVH_RebuildNodeVerts;
+
+ int usize = BLI_table_gset_len(node->bm_unique_verts);
int osize = BLI_table_gset_len(node->bm_other_verts);
- BLI_table_gset_free(node->bm_other_verts, NULL);
BLI_table_gset_free(node->bm_unique_verts, NULL);
+ BLI_table_gset_free(node->bm_other_verts, NULL);
node->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
node->bm_other_verts = BLI_table_gset_new("bm_other_verts");
@@ -557,11 +559,20 @@ static void pbvh_bmesh_regen_node_verts(PBVH *pbvh, PBVHNode *node)
const int cd_vert_node = pbvh->cd_vert_node_offset;
const int ni = (int)(node - pbvh->nodes);
+ bool update = false;
+
BMFace *f;
TGSET_ITER (f, node->bm_faces) {
BMLoop *l = f->l_first;
do {
int ni2 = BM_ELEM_CD_GET_INT(l->v, cd_vert_node);
+
+ if (ni2 == DYNTOPO_NODE_NONE) {
+ BM_ELEM_CD_SET_INT(l->v, cd_vert_node, ni);
+ ni2 = ni;
+ update = true;
+ }
+
if (ni2 == ni) {
BLI_table_gset_add(node->bm_unique_verts, l->v);
}
@@ -573,16 +584,25 @@ static void pbvh_bmesh_regen_node_verts(PBVH *pbvh, PBVHNode *node)
TGSET_ITER_END;
if (usize != BLI_table_gset_len(node->bm_unique_verts)) {
+ update = true;
printf("possible pbvh error: bm_unique_verts might have had bad data. old: %d, new: %d\n",
usize,
BLI_table_gset_len(node->bm_unique_verts));
}
if (osize != BLI_table_gset_len(node->bm_other_verts)) {
+ update = true;
printf("possible pbvh error: bm_other_verts might have had bad data. old: %d, new: %d\n",
osize,
BLI_table_gset_len(node->bm_other_verts));
}
+
+ if (update) {
+ node->flag |= PBVH_UpdateNormals | PBVH_UpdateDrawBuffers | PBVH_RebuildDrawBuffers |
+ PBVH_UpdateBB;
+ node->flag |= PBVH_UpdateOriginalBB | PBVH_UpdateRedraw | PBVH_UpdateColor | PBVH_UpdateTris |
+ PBVH_UpdateVisibility;
+ }
}
void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node)
@@ -590,6 +610,18 @@ void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node)
node->flag |= PBVH_RebuildNodeVerts;
}
+PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i)
+{
+ if (i >= 0 && i < pbvh->totnode) {
+ PBVHNode *node = pbvh->nodes + i;
+ if ((node->flag & PBVH_Leaf) && !(node->flag & PBVH_Delete)) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh)
{
for (int i = 0; i < pbvh->totnode; i++) {
@@ -1226,13 +1258,16 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset,
- const int cd_dyn_vert)
+ const int cd_dyn_vert,
+ bool fast_draw)
{
pbvh->cd_vert_node_offset = cd_vert_node_offset;
pbvh->cd_face_node_offset = cd_face_node_offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
pbvh->cd_dyn_vert = cd_dyn_vert;
+ smooth_shading |= fast_draw;
+
pbvh->bm = bm;
BKE_pbvh_bmesh_detail_size_set(pbvh, 0.75f, 0.4f);
@@ -1270,10 +1305,15 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
zero_v4(mv->origcolor);
}
}
+
if (smooth_shading) {
pbvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
}
+ if (fast_draw) {
+ pbvh->flags |= PBVH_FAST_DRAW;
+ }
+
/* bounding box array of all faces, no need to recalculate every time */
BBC *bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC");
BMFace **nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo");
@@ -1384,13 +1424,16 @@ static void pbvh_free_tribuf(PBVHTriBuf *tribuf)
MEM_SAFE_FREE(tribuf->verts);
MEM_SAFE_FREE(tribuf->tris);
MEM_SAFE_FREE(tribuf->loops);
+ MEM_SAFE_FREE(tribuf->edges);
tribuf->verts = NULL;
tribuf->tris = NULL;
tribuf->loops = NULL;
+ tribuf->edges = NULL;
tribuf->verts_size = 0;
tribuf->tris_size = 0;
+ tribuf->edges_size = 0;
}
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node)
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index f06c95b1755..efe5c426e91 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -129,6 +129,7 @@ struct PBVHNode {
typedef enum {
PBVH_DYNTOPO_SMOOTH_SHADING = 1,
+ PBVH_FAST_DRAW = 2 // hides facesets/masks and forces smooth to save GPU bandwidth
} PBVHFlags;
typedef struct PBVHBMeshLog PBVHBMeshLog;
diff --git a/source/blender/draw/engines/overlay/overlay_sculpt.c b/source/blender/draw/engines/overlay/overlay_sculpt.c
index 24c52ec427d..24ff807bba8 100644
--- a/source/blender/draw/engines/overlay/overlay_sculpt.c
+++ b/source/blender/draw/engines/overlay/overlay_sculpt.c
@@ -60,7 +60,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
return;
}
- if (!pbvh_has_mask(pbvh) && !pbvh_has_face_sets(pbvh)) {
+ if (!BKE_pbvh_draw_mask(pbvh) && !BKE_pbvh_draw_face_sets(pbvh)) {
/* The SculptSession and the PBVH can be created without a Mask data-layer or Face Set
* data-layer. (masks data-layers are created after using a mask tool), so in these cases there
* is nothing to draw. */
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index b3fcb9155f3..04db16d4516 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -1305,19 +1305,20 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
MEM_freeN(looptris);
- if (sgcontext->ss && sgcontext->ss->bm) { //rebuild pbvh
+ if (sgcontext->ss && sgcontext->ss->bm) { // rebuild pbvh
BKE_pbvh_free(sgcontext->ss->pbvh);
sgcontext->ss->pbvh = BKE_pbvh_new();
BKE_pbvh_build_bmesh(sgcontext->ss->pbvh,
sgcontext->ss->bm,
- false,
+ sgcontext->ss->bm_smooth_shading,
sgcontext->ss->bm_log,
sgcontext->ss->cd_vert_node_offset,
sgcontext->ss->cd_face_node_offset,
- sgcontext->ss->cd_dyn_vert);
+ sgcontext->ss->cd_dyn_vert,
+ sgcontext->ss->fast_draw);
}
- else { //save result to mesh
+ else { // save result to mesh
Mesh *result = BKE_mesh_from_bmesh_nomain(bm,
(&(struct BMeshToMeshParams){
.calc_object_remap = false,
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 3e5aa90a6ba..1cc928525ec 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -435,6 +435,8 @@ typedef struct BmeshUndoData {
bool balance_pbvh;
int cd_face_node_offset, cd_vert_node_offset;
int cd_dyn_vert;
+ bool regen_all_unique_verts;
+ bool is_redo;
} BmeshUndoData;
static void bmesh_undo_on_vert_kill(BMVert *v, void *userdata)
@@ -448,29 +450,17 @@ static void bmesh_undo_on_vert_kill(BMVert *v, void *userdata)
data->do_full_recalc = true;
return;
}
- else {
- int ni = BM_ELEM_CD_GET_INT(v, data->cd_vert_node_offset);
-
- /*
- regenerate bm_unique_verts, which can end up with
- freed verts for some reason. I've run this through
- ASAN and fixed one likely cause, but it still happens.
- - joeedh
- */
- if (ni >= 0) {
- PBVHNode *node = BKE_pbvh_get_node(data->pbvh, ni);
- BKE_pbvh_bmesh_mark_node_regen(data->pbvh, node);
- }
- }
BKE_pbvh_bmesh_remove_vertex(data->pbvh, v, false);
data->balance_pbvh = true;
}
+
static void bmesh_undo_on_vert_add(BMVert *v, void *userdata)
{
BmeshUndoData *data = (BmeshUndoData *)userdata;
BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
// data->do_full_recalc = true;
+
data->balance_pbvh = true;
MDynTopoVert *mv = BKE_PBVH_DYNVERT(data->cd_dyn_vert, v);
@@ -482,19 +472,13 @@ static void bmesh_undo_on_face_kill(BMFace *f, void *userdata)
BmeshUndoData *data = (BmeshUndoData *)userdata;
int ni = BM_ELEM_CD_GET_INT(f, data->cd_face_node_offset);
- /*
- regenerate bm_unique_verts, which can end up with
- freed verts for some reason. I've run this through
- ASAN and fixed one likely cause, but it still happens.
- - joeedh
- */
+ BKE_pbvh_bmesh_remove_face(data->pbvh, f, false);
+
if (ni >= 0) {
PBVHNode *node = BKE_pbvh_get_node(data->pbvh, ni);
BKE_pbvh_bmesh_mark_node_regen(data->pbvh, node);
}
- BKE_pbvh_bmesh_remove_face(data->pbvh, f, false);
-
// data->do_full_recalc = true;
data->balance_pbvh = true;
}
@@ -521,22 +505,36 @@ static void bmesh_undo_full_mesh(void *userdata)
data->do_full_recalc = true;
}
-static void bmesh_undo_on_vert_change(BMVert *v, void *userdata, void *old_customdata)
+ATTR_NO_OPT static void bmesh_undo_on_vert_change(BMVert *v, void *userdata, void *old_customdata)
{
BmeshUndoData *data = (BmeshUndoData *)userdata;
if (!old_customdata) {
BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
+ data->regen_all_unique_verts = true;
return;
}
- BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
+ BMElem h;
+ h.head.data = old_customdata;
+
+ int ni = BM_ELEM_CD_GET_INT(&h, data->cd_vert_node_offset);
+
+ // attempt to find old node
+ PBVHNode *node = BKE_pbvh_get_node_leaf_safe(data->pbvh, ni);
+ if (node) {
+ // BKE_pbvh_bmesh_mark_node_regen(data->pbvh, node);
+ BKE_pbvh_node_mark_update(node);
+ // BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
+ }
+ else {
+ BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
+ data->regen_all_unique_verts = true;
+ }
+
return;
// preserve pbvh node references
- BMVert h;
- h.head.data = old_customdata;
-
int oldnode_i = BM_ELEM_CD_GET_INT(&h, data->cd_vert_node_offset);
BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, oldnode_i);
@@ -563,7 +561,9 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
false,
ss->cd_face_node_offset,
ss->cd_vert_node_offset,
- ss->cd_dyn_vert};
+ ss->cd_dyn_vert,
+ false,
+ !unode->applied};
BMLogCallbacks callbacks = {bmesh_undo_on_vert_add,
bmesh_undo_on_vert_kill,
@@ -589,11 +589,17 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
int totnode;
PBVHNode **nodes;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ if (data.regen_all_unique_verts) {
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_bmesh_mark_node_regen(ss->pbvh, nodes[i]);
+ }
+ }
+
BKE_pbvh_bmesh_regen_node_verts(ss->pbvh);
pbvh_bmesh_check_nodes(ss->pbvh);
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(
@@ -608,6 +614,8 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
if (data.balance_pbvh) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
}
+
+ BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw);
}
else {
SCULPT_pbvh_clear(ob);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index cf0ba4b16bf..e2ccf8fe941 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -87,9 +87,11 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const struct MPropCol *vtcol,
const int update_flags);
-void GPU_pbvh_update_attribute_names(struct CustomData *vdata,
- struct CustomData *ldata,
- bool need_full_render);
+void GPU_pbvh_update_attribute_names(
+ struct CustomData *vdata,
+ struct CustomData *ldata,
+ bool need_full_render,
+ bool fast_mode); // fast mode renders without vcol, uv, facesets, even mask, etc
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
struct BMesh *bm,
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index d6968dbc158..67e52b6c964 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -61,6 +61,8 @@
#include "bmesh.h"
+//#define GPU_PERF_TEST // will disable vcol, uvs, mask, fset colors, etc
+
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
@@ -116,6 +118,8 @@ struct GPU_PBVH_Buffers {
* smooth-shaded or all faces are flat-shaded */
bool smooth;
+ void *last_tribuf_tris; // used to detect if we can reuse index buffers
+
bool show_overlay;
#ifdef QUANTIZED_PERF_TEST
float matrix[4][4];
@@ -157,6 +161,7 @@ static struct {
bool active_vcol_only;
bool need_full_render;
+ bool fast_mode;
} g_vbo_id = {{0}};
#ifdef NEW_ATTR_SYSTEM
@@ -355,7 +360,7 @@ static void free_cd_layers(CDAttrLayers *cdattr)
void gpu_pbvh_init()
{
- GPU_pbvh_update_attribute_names(NULL, NULL, false);
+ GPU_pbvh_update_attribute_names(NULL, NULL, false, false);
}
void gpu_pbvh_exit()
@@ -462,9 +467,11 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MPropCol *vtcol,
const int update_flags)
{
- const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+ const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 &&
+ !g_vbo_id.fast_mode;
const bool show_face_sets = sculpt_face_sets &&
- (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
+ (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0 &&
+ !g_vbo_id.fast_mode;
const bool show_vcol = (vcol || (vtcol && U.experimental.use_sculpt_vertex_colors)) &&
(update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
bool empty_mask = true;
@@ -566,8 +573,11 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
}
}
- /* Face Sets. */
- memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3]));
+
+ if (!g_vbo_id.fast_mode) {
+ /* Face Sets. */
+ memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3]));
+ }
}
}
}
@@ -580,7 +590,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MPoly *mp = &buffers->mpoly[lt->poly];
buffers->material_index = mp->mat_nr;
- buffers->show_overlay = !empty_mask || !default_face_set;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
buffers->mvert = mvert;
}
@@ -601,7 +611,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const MPoly *mpoly,
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
/* smooth or flat for all */
- buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
+ buffers->smooth = (mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH) || g_vbo_id.fast_mode;
buffers->show_overlay = false;
@@ -679,13 +689,13 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const MPoly *mpoly,
/** \name Grid PBVH
* \{ */
-static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers,
- SubdivCCG *UNUSED(subdiv_ccg),
- const int *UNUSED(face_sets),
- const int *grid_indices,
- uint visible_quad_len,
- int totgrid,
- int gridsize)
+ATTR_NO_OPT static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers,
+ SubdivCCG *UNUSED(subdiv_ccg),
+ const int *UNUSED(face_sets),
+ const int *grid_indices,
+ uint visible_quad_len,
+ int totgrid,
+ int gridsize)
{
GPUIndexBufBuilder elb, elb_lines;
GPUIndexBufBuilder elb_fast, elb_lines_fast;
@@ -695,7 +705,7 @@ static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers,
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX);
GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX);
- if (buffers->smooth) {
+ if (buffers->smooth || g_vbo_id.fast_mode) {
uint offset = 0;
const uint grid_vert_len = gridsize * gridsize;
for (int i = 0; i < totgrid; i++, offset += grid_vert_len) {
@@ -815,7 +825,7 @@ void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
const struct DMFlagMat *grid_flag_mats,
const int *grid_indices)
{
- const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
+ const bool smooth = (grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH) || g_vbo_id.fast_mode;
if (buffers->smooth != smooth) {
buffers->smooth = smooth;
@@ -832,22 +842,23 @@ void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
}
/* Threaded - do not call any functions that use OpenGL calls! */
-void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
- SubdivCCG *subdiv_ccg,
- CCGElem **grids,
- const struct DMFlagMat *grid_flag_mats,
- int *grid_indices,
- int totgrid,
- const int *sculpt_face_sets,
- const int face_sets_color_seed,
- const int face_sets_color_default,
- const struct CCGKey *key,
- const int update_flags)
+ATTR_NO_OPT void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
+ SubdivCCG *subdiv_ccg,
+ CCGElem **grids,
+ const struct DMFlagMat *grid_flag_mats,
+ int *grid_indices,
+ int totgrid,
+ const int *sculpt_face_sets,
+ const int face_sets_color_seed,
+ const int face_sets_color_default,
+ const struct CCGKey *key,
+ const int update_flags)
{
- const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+ const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 && !g_vbo_id.fast_mode;
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
const bool show_face_sets = sculpt_face_sets &&
- (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
+ (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0 &&
+ !g_vbo_id.fast_mode;
bool empty_mask = true;
bool default_face_set = true;
@@ -856,7 +867,13 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
/* Build VBO */
const int has_mask = key->has_mask;
- buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
+ bool smooth = (grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH) || g_vbo_id.fast_mode;
+ ;
+ if (smooth != buffers->smooth) {
+ GPU_pbvh_grid_buffers_update_free(buffers, grid_flag_mats, grid_indices);
+ }
+
+ buffers->smooth = smooth;
uint vert_per_grid = (buffers->smooth) ? key->grid_area : (square_i(key->grid_size - 1) * 4);
uint vert_count = totgrid * vert_per_grid;
@@ -906,7 +923,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
}
}
- if (buffers->smooth) {
+ if (buffers->smooth || g_vbo_id.fast_mode) {
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
@@ -929,7 +946,9 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index, &vcol);
}
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index, &face_set_color);
+ if (!g_vbo_id.fast_mode) {
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index, &face_set_color);
+ }
vbo_index += 1;
}
@@ -980,15 +999,23 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
}
const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 0, &vcol);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 1, &vcol);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 2, &vcol);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 3, &vcol);
+ if (1) { // g_vbo_id.totcol > 0 || !g_vbo_id.fast_mode) {
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 0, &vcol);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 1, &vcol);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 2, &vcol);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], vbo_index + 3, &vcol);
+ }
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 0, &face_set_color);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 1, &face_set_color);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 2, &face_set_color);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 3, &face_set_color);
+ if (!g_vbo_id.fast_mode) {
+ GPU_vertbuf_attr_set(
+ buffers->vert_buf, g_vbo_id.fset, vbo_index + 0, &face_set_color);
+ GPU_vertbuf_attr_set(
+ buffers->vert_buf, g_vbo_id.fset, vbo_index + 1, &face_set_color);
+ GPU_vertbuf_attr_set(
+ buffers->vert_buf, g_vbo_id.fset, vbo_index + 2, &face_set_color);
+ GPU_vertbuf_attr_set(
+ buffers->vert_buf, g_vbo_id.fset, vbo_index + 3, &face_set_color);
+ }
vbo_index += 4;
}
@@ -1008,7 +1035,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->totgrid = totgrid;
buffers->grid_flag_mats = grid_flag_mats;
buffers->gridkey = *key;
- buffers->show_overlay = !empty_mask || !default_face_set;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
}
/* Threaded - do not call any functions that use OpenGL calls! */
@@ -1061,9 +1088,11 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
short no_short[3];
+
normal_float_to_short_v3(no_short, fno ? fno : v->no);
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, v_index, no_short);
+#ifndef GPU_PERF_TEST
if (show_mask) {
float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
@@ -1078,7 +1107,7 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
*empty_mask = *empty_mask && (cmask == 0);
}
-#ifndef NEW_ATTR_SYSTEM
+# ifndef NEW_ATTR_SYSTEM
if (show_vcol && totvcol > 0) {
for (int i = 0; i < totvcol; i++) {
ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
@@ -1094,20 +1123,23 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col[i], v_index, vcol);
}
}
- else if (show_vcol) { // ensure first vcol attribute is not zero
+ else if (show_vcol && !g_vbo_id.fast_mode) { // ensure first vcol attribute is not zero
const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col[0], v_index, vcol);
}
-#else
+# else
if (show_vcol && totvcol == 0) { // ensure first vcol attribute is not zero
const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col[0], v_index, vcol);
}
-#endif
+# endif
- /* Add default face sets color to avoid artifacts. */
- const uchar face_set[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.fset, v_index, &face_set);
+ if (!g_vbo_id.fast_mode) {
+ /* Add default face sets color to avoid artifacts. */
+ const uchar face_set[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.fset, v_index, &face_set);
+ }
+#endif
}
/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
@@ -1151,17 +1183,13 @@ static int gpu_bmesh_face_visible_count(TableGSet *bm_faces, int mat_nr)
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);
+ if (buffers->last_tribuf_tris) {
+ // bmesh indexed drawing frees buffers by itself
+ return;
}
+
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
}
static int gpu_pbvh_bmesh_make_vcol_offs(CustomData *vdata,
@@ -1232,12 +1260,17 @@ bool GPU_pbvh_need_full_render_get()
return g_vbo_id.need_full_render;
}
-void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool need_full_render)
+void GPU_pbvh_update_attribute_names(CustomData *vdata,
+ CustomData *ldata,
+ bool need_full_render,
+ bool fast_mode)
{
const bool active_only = !need_full_render;
GPU_vertformat_clear(&g_vbo_id.format);
+ g_vbo_id.fast_mode = fast_mode;
+
// g_vbo_id.loop_attrs = build_cd_layers(vdata, )
/* Initialize vertex buffer (match 'VertexBufferFormat'). */
if (g_vbo_id.format.attr_len == 0) {
@@ -1259,8 +1292,12 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool
return;
#endif
- g_vbo_id.msk = GPU_vertformat_attr_add(
- &g_vbo_id.format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+#ifndef GPU_PERF_TEST
+ if (!fast_mode) {
+ g_vbo_id.msk = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+#endif
g_vbo_id.totcol = 0;
@@ -1302,7 +1339,7 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool
g_vbo_id.loop_attrs_len = BLI_array_len(lattr);
#endif
-#ifndef NEW_ATTR_SYSTEM
+#if !defined(NEW_ATTR_SYSTEM) && !defined(GPU_PERF_TEST)
if (vdata && CustomData_has_layer(vdata, CD_PROP_COLOR)) {
const int act = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
int ci = 0;
@@ -1331,14 +1368,14 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool
}
// ensure at least one vertex color layer
- if (g_vbo_id.totcol == 0) {
+ if (!fast_mode && g_vbo_id.totcol == 0) {
g_vbo_id.col[0] = GPU_vertformat_attr_add(
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.totcol = 1;
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
}
-#else
+#elif !defined(GPU_PERF_TEST)
// ensure at least one vertex color layer
if (!vdata || !CustomData_has_layer(vdata, CD_PROP_COLOR)) {
g_vbo_id.col[0] = GPU_vertformat_attr_add(
@@ -1349,20 +1386,25 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool
}
#endif
- g_vbo_id.fset = GPU_vertformat_attr_add(
- &g_vbo_id.format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- g_vbo_id.uv = GPU_vertformat_attr_add(
- &g_vbo_id.format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_vertformat_alias_add(&g_vbo_id.format, "u");
+#ifndef GPU_PERF_TEST
+ if (!fast_mode) {
+ g_vbo_id.fset = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
if (ldata && CustomData_has_layer(ldata, CD_MLOOPUV)) {
+ g_vbo_id.uv = GPU_vertformat_attr_add(
+ &g_vbo_id.format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&g_vbo_id.format, "u");
+
const int cd_uv_index = CustomData_get_layer_index(ldata, CD_MLOOPUV);
CustomDataLayer *cl = ldata->layers + cd_uv_index;
cl += cl->active;
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "u", ldata, cl);
}
+#endif
}
}
@@ -1568,29 +1610,37 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
/* Get material index from the last face we iterated on. */
buffers->material_index = mat_nr;
- buffers->show_overlay = !empty_mask || !default_face_set;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
}
-static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
- BMesh *bm,
- TableGSet *bm_faces,
- TableGSet *bm_unique_verts,
- TableGSet *bm_other_verts,
- PBVHTriBuf *tribuf,
- const int update_flags,
- const int cd_vert_node_offset,
- int face_sets_color_seed,
- int face_sets_color_default,
- bool flat_vcol,
- short mat_nr)
+ATTR_NO_OPT static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
+ BMesh *bm,
+ TableGSet *bm_faces,
+ TableGSet *bm_unique_verts,
+ TableGSet *bm_other_verts,
+ PBVHTriBuf *tribuf,
+ const int update_flags,
+ const int cd_vert_node_offset,
+ int face_sets_color_seed,
+ int face_sets_color_default,
+ bool flat_vcol,
+ short mat_nr)
{
bool active_vcol_only = g_vbo_id.active_vcol_only;
- const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
- const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
+ const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 && !g_vbo_id.fast_mode;
+ bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
+
+ if (g_vbo_id.totcol == 0 && g_vbo_id.fast_mode) {
+ show_vcol = false;
+ }
+
+ bool need_indexed = buffers->last_tribuf_tris != tribuf->tris;
+
+ buffers->last_tribuf_tris = tribuf->tris;
int tottri, totvert;
bool empty_mask = true;
@@ -1629,11 +1679,6 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
return;
}
- /* Fill the vertex and triangle buffer in one pass over faces. */
- GPUIndexBufBuilder elb, elb_lines;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert);
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
-
#ifdef QUANTIZED_PERF_TEST
GPUVertBuf *vert_buf = buffers->vert_buf;
@@ -1712,6 +1757,24 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
#endif
}
+ if (!need_indexed) {
+ buffers->material_index = mat_nr;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
+
+ gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
+ return;
+ }
+
+ 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);
+
+ /* Fill the vertex and triangle buffer in one pass over faces. */
+ GPUIndexBufBuilder elb, elb_lines;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert);
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
+
for (int i = 0; i < tribuf->tottri; i++) {
PBVHTri *tri = tribuf->tris + i;
@@ -1735,7 +1798,7 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
buffers->material_index = mat_nr;
- buffers->show_overlay = !empty_mask || !default_face_set;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
@@ -1779,9 +1842,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
}
const bool have_uv = CustomData_has_layer(&bm->ldata, CD_MLOOPUV);
- const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+ const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 && !g_vbo_id.fast_mode;
const bool show_face_sets = CustomData_has_layer(&bm->pdata, CD_SCULPT_FACE_SETS) &&
- (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
+ (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0 &&
+ !g_vbo_id.fast_mode;
int tottri, totvert;
bool empty_mask = true;
@@ -1810,6 +1874,8 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
return;
}
+ buffers->last_tribuf_tris = NULL;
+
/* TODO, make mask layer optional for bmesh buffer */
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
const int cd_mcol_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
@@ -1903,7 +1969,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
&empty_mask,
NULL,
0);
-
+# ifndef GPU_PERF_TEST
if (cd_vcol_count >= 0) {
for (int k = 0; k < cd_vcol_count; k++) {
MPropCol *mp = BM_ELEM_CD_GET_VOID_P(l[j]->v, cd_vcols[k]);
@@ -1938,8 +2004,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.uv, v_index, mu->uv);
}
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, v_index, face_set_color);
-
+ if (show_face_sets) {
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, v_index, face_set_color);
+ }
+# endif
v_index++;
}
}
@@ -2068,7 +2136,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
/* Get material index from the last face we iterated on. */
buffers->material_index = mat_nr;
- buffers->show_overlay = !empty_mask || !default_face_set;
+ buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
}
@@ -2084,8 +2152,8 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
buffers->use_bmesh = true;
- buffers->smooth = smooth_shading;
- buffers->show_overlay = true;
+ buffers->smooth = smooth_shading || g_vbo_id.fast_mode;
+ buffers->show_overlay = (!g_vbo_id.fast_mode) && !g_vbo_id.fast_mode;
return buffers;
}
@@ -2101,7 +2169,7 @@ GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool
bool GPU_pbvh_buffers_has_overlays(GPU_PBVH_Buffers *buffers)
{
- return buffers->show_overlay;
+ return buffers->show_overlay && !g_vbo_id.fast_mode;
}
short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers)
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 05a40f46977..3f3bc876126 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -484,7 +484,7 @@ typedef struct ImageFormatData {
#define R_IMF_IMTYPE_INVALID 255
/** #ImageFormatData.flag */
-#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */
+#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */
#define R_IMF_FLAG_PREVIEW_JPG (1 << 1) /* was R_PREVIEW_JPG */
/* Return values from #BKE_imtype_valid_depths, note this is depths per channel. */
@@ -526,8 +526,8 @@ typedef enum eImageFormatDepth {
/** #ImageFormatData.jp2_flag */
#define R_IMF_JP2_FLAG_YCC (1 << 0) /* when disabled use RGB */ /* was R_JPEG2K_YCC */
-#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */
-#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */
+#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */
+#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */
/** #ImageFormatData.jp2_codec */
#define R_IMF_JP2_CODEC_JP2 0
@@ -1842,12 +1842,12 @@ typedef struct Scene {
#define R_MODE_UNUSED_20 (1 << 20) /* cleared */
#define R_MODE_UNUSED_21 (1 << 21) /* cleared */
-#define R_NO_OVERWRITE (1 << 22) /* skip existing files */
-#define R_TOUCH (1 << 23) /* touch files before rendering */
+#define R_NO_OVERWRITE (1 << 22) /* skip existing files */
+#define R_TOUCH (1 << 23) /* touch files before rendering */
#define R_SIMPLIFY (1 << 24)
-#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */
+#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */
#define R_PERSISTENT_DATA (1 << 26) /* keep data around for re-render */
-#define R_MODE_UNUSED_27 (1 << 27) /* cleared */
+#define R_MODE_UNUSED_27 (1 << 27) /* cleared */
/** #RenderData.seq_flag */
enum {
@@ -2237,8 +2237,11 @@ typedef enum eSculptFlags {
/* Don't display face sets in viewport. */
SCULPT_HIDE_FACE_SETS = (1 << 17),
- SCULPT_DYNTOPO_FLAT_VCOL_SHADING = (1<<18),
+ SCULPT_DYNTOPO_FLAT_VCOL_SHADING = (1 << 18),
SCULPT_DYNTOPO_CLEANUP = (1 << 19),
+
+ // hides facesets/masks and forces indexed mode to save GPU bandwidth
+ SCULPT_FAST_DRAW = (1 << 20),
} eSculptFlags;
/** #ImagePaintSettings.mode */
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 579dcf6aeb8..3d5e5ed8896 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -382,6 +382,7 @@ static void rna_Sculpt_update(bContext *C, PointerRNA *UNUSED(ptr))
ob->sculpt->bm_smooth_shading = ((scene->toolsettings->sculpt->flags &
SCULPT_DYNTOPO_SMOOTH_SHADING) != 0);
+ ob->sculpt->fast_draw = ((scene->toolsettings->sculpt->flags & SCULPT_FAST_DRAW) != 0);
}
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -831,6 +832,17 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
+ prop = RNA_def_property(srna, "use_fast_draw", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_FAST_DRAW);
+ RNA_def_property_ui_text(prop,
+ "Fast Draw Mode",
+ "Forces smooth shading"
+ "and disables drawing of masks and face sets"
+ "to speed up drawing. Useful for posing"
+ "high-poly meshes.");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
+
prop = RNA_def_property(srna, "use_dyntopo_cleanup", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_CLEANUP);
RNA_def_property_ui_text(prop, "Cleanup", "Removes verts surrounded by only 3 or 4 edges");