[Bf-blender-cvs] [f68493f5bee] temp-trimesh-sculpt: Little design study for new API to replace various pbvh/sculpt iterators (uncomment PROXY_ADVANCED in BKE_pbvh to enable): + Same idea as existing pbvh proxies. + Based on "struct of arrays" approach. + New ProxyVeryArray structure holds all the coordinates, normals, indices, neighbor references, color, mask, etc data--basically everything in PBVHVertIter and SculptNeightborIter. + Only the desired data is stored. Client code can pass a mask stating which data layers it wants; e.g. normals, coordiantes, etc.
Joseph Eagar
noreply at git.blender.org
Mon Oct 19 13:25:59 CEST 2020
Commit: f68493f5bee352d4a7feb90c2488a264607c84ac
Author: Joseph Eagar
Date: Mon Oct 19 04:10:34 2020 -0700
Branches: temp-trimesh-sculpt
https://developer.blender.org/rBf68493f5bee352d4a7feb90c2488a264607c84ac
Little design study for new API to replace various pbvh/sculpt
iterators (uncomment PROXY_ADVANCED in BKE_pbvh to enable):
+ Same idea as existing pbvh proxies.
+ Based on "struct of arrays" approach.
+ New ProxyVeryArray structure holds all the coordinates,
normals, indices, neighbor references, color, mask, etc
data--basically everything in PBVHVertIter and SculptNeightborIter.
+ Only the desired data is stored. Client code can pass a mask
stating which data layers it wants; e.g. normals, coordiantes, etc.
There's a lot of advantages to this approach: simpler and more
maintainable code, possibility of SSE/opencl/cuda vectorization down
the line, etc.
More importantly for this branch, it should be a great profiling tool.
No more trying to figure out which bit of API cruft is causing the CPU
cache to go haywire. I can eliminate a lot of performance bugs and
concentrate on the ones related to DynTopo.
===================================================================
M source/blender/blenkernel/BKE_pbvh.h
M source/blender/blenkernel/intern/pbvh.c
M source/blender/blenkernel/intern/pbvh_intern.h
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/sculpt_paint/sculpt_intern.h
M source/blender/editors/sculpt_paint/sculpt_smooth.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 73718ba33bf..3cdbad8885e 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -58,6 +58,77 @@ struct TaskParallelTLS;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
+#define PROXY_ADVANCED
+
+// experimental performance test of "data-based programming" approach
+#ifdef PROXY_ADVANCED
+typedef struct ProxyKey {
+ int node;
+ int pindex;
+} ProxyKey;
+
+# define MAX_PROXY_NEIGHBORS 12
+
+typedef struct ProxyVertArray {
+ float **ownerco;
+ short **ownerno;
+ float (*co)[3];
+ float (*fno)[3];
+ short (*no)[3];
+ float *mask, **ownermask;
+ int *index;
+ float **ownercolor, (*color)[4];
+
+ ProxyKey (*neighbors)[MAX_PROXY_NEIGHBORS];
+
+ int size;
+ int datamask;
+
+ GHash *indexmap;
+} ProxyVertArray;
+
+typedef enum {
+ PV_OWNERCO = 1,
+ PV_OWNERNO = 2,
+ PV_CO = 4,
+ PV_NO = 8,
+ PV_MASK = 16,
+ PV_OWNERMASK = 32,
+ PV_INDEX = 64,
+ PV_OWNERCOLOR = 128,
+ PV_COLOR = 256,
+ PV_NEIGHBORS = 512
+} ProxyVertField;
+
+typedef struct ProxyVertUpdateRec {
+ float *co, *no, *mask, *color;
+ int index, newindex;
+} ProxyVertUpdateRec;
+
+# define PBVH_PROXY_DEFAULT CO | INDEX | MASK
+
+struct SculptSession;
+
+void BKE_pbvh_ensure_proxyarrays(struct SculptSession *ss, PBVH *pbvh, int mask);
+void BKE_pbvh_load_proxyarrays(PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
+
+void BKE_pbvh_ensure_proxyarray(
+ struct SculptSession *ss,
+ struct PBVH *pbvh,
+ struct PBVHNode *node,
+ int mask,
+ struct GHash
+ *vert_node_map, // vert_node_map maps vertex SculptIdxs to PBVHNode indices; optional
+ bool check_indexmap,
+ bool force_update);
+void BKE_pbvh_gather_proxyarray(PBVH *pbvh, PBVHNode **nodes, int totnode);
+
+void BKE_pbvh_free_proxyarray(struct PBVH *pbvh, struct PBVHNode *node);
+void BKE_pbvh_update_proxyvert(struct PBVH *pbvh, struct PBVHNode *node, ProxyVertUpdateRec *rec);
+ProxyVertArray *BKE_pbvh_get_proxyarrays(struct PBVH *pbvh, struct PBVHNode *node);
+
+#endif
+
typedef struct {
float (*co)[3];
} PBVHProxyNode;
@@ -107,12 +178,16 @@ void TMElemSet_remove(TMElemSet *ts, void *elem, bool ignoreExist);
bool TMElemSet_has(TMElemSet *ts, void *elem);
#define TMS_ITER(v, ts) \
-{int _i1; for (_i1=0; _i1<ts->cur; _i1++) {\
- if (!ts->elems[_i1])\
- continue;\
- v = ts->elems[_i1];
-
-#define TMS_ITER_END }}
+ { \
+ int _i1; \
+ for (_i1 = 0; _i1 < ts->cur; _i1++) { \
+ if (!ts->elems[_i1]) \
+ continue; \
+ v = ts->elems[_i1];
+
+#define TMS_ITER_END \
+ } \
+ }
void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
@@ -155,14 +230,14 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset);
void BKE_pbvh_build_trimesh(PBVH *bvh,
- struct TM_TriMesh *bm,
- bool smooth_shading,
- struct TriMeshLog *log,
- const int cd_vert_node_offset,
- const int cd_face_node_offset);
+ struct TM_TriMesh *bm,
+ bool smooth_shading,
+ struct TriMeshLog *log,
+ const int cd_vert_node_offset,
+ const int cd_face_node_offset);
void BKE_pbvh_free(PBVH *bvh);
-//void BKE_pbvh_free_layer_disp(PBVH *bvh);
+// void BKE_pbvh_free_layer_disp(PBVH *bvh);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
@@ -207,10 +282,10 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
float *depth,
float *r_edge_length);
bool BKE_pbvh_trimesh_node_raycast_detail(PBVHNode *node,
- const float ray_start[3],
- struct IsectRayPrecalc *isect_precalc,
- float *depth,
- float *r_edge_length);
+ const float ray_start[3],
+ struct IsectRayPrecalc *isect_precalc,
+ float *depth,
+ float *r_edge_length);
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
@@ -248,12 +323,7 @@ void BKE_pbvh_draw_debug_cb(
void *user_data);
/* PBVH Access */
-typedef enum {
- PBVH_FACES,
- PBVH_GRIDS,
- PBVH_BMESH,
- PBVH_TRIMESH
-} PBVHType;
+typedef enum { PBVH_FACES, PBVH_GRIDS, PBVH_BMESH, PBVH_TRIMESH } PBVHType;
PBVHType BKE_pbvh_type(const PBVH *pbvh);
bool BKE_pbvh_has_faces(const PBVH *pbvh);
@@ -297,12 +367,13 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
const bool use_projected);
bool BKE_pbvh_trimesh_update_topology(PBVH *bvh,
- PBVHTopologyUpdateMode mode,
- const float center[3],
- const float view_normal[3],
- float radius,
- const bool use_frontface,
- const bool use_projected, int sym_axis);
+ PBVHTopologyUpdateMode mode,
+ const float center[3],
+ const float view_normal[3],
+ float radius,
+ const bool use_frontface,
+ const bool use_projected,
+ int sym_axis);
/* Node Access */
void BKE_pbvh_node_mark_update(PBVHNode *node);
@@ -503,30 +574,32 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
} \
else if (vi.tm_vdata) { \
- TMVert *tv = NULL;\
- while (!tv) {\
- if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_cur_set->cur) {\
- if (vi.tm_cur_set != vi.tm_other_verts) {\
- vi.tm_cur_set = vi.tm_other_verts;\
- vi.ti = 0;\
- if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_other_verts->cur) {\
- break;\
- }\
- } else {\
- break;\
- }\
- } else {\
- tv = vi.tm_cur_set->elems[vi.ti++];\
- if (tv && BLI_safepool_elem_is_dead(tv)) {\
- printf("dead vert: %p\n", tv);\
- tv = NULL;\
- }\
- }\
- }\
- if (!tv) {\
- continue;\
- }\
- vi.tm_vert = tv;\
+ TMVert *tv = NULL; \
+ while (!tv) { \
+ if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_cur_set->cur) { \
+ if (vi.tm_cur_set != vi.tm_other_verts) { \
+ vi.tm_cur_set = vi.tm_other_verts; \
+ vi.ti = 0; \
+ if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_other_verts->cur) { \
+ break; \
+ } \
+ } \
+ else { \
+ break; \
+ } \
+ } \
+ else { \
+ tv = vi.tm_cur_set->elems[vi.ti++]; \
+ if (tv && BLI_safepool_elem_is_dead(tv)) { \
+ printf("dead vert: %p\n", tv); \
+ tv = NULL; \
+ } \
+ } \
+ } \
+ if (!tv) { \
+ continue; \
+ } \
+ vi.tm_vert = tv; \
vi.visible = !TM_elem_flag_test_bool(vi.tm_vert, TM_ELEM_HIDDEN); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
@@ -535,7 +608,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi.fno = vi.tm_vert->no; \
vi.index = (SculptIdx)vi.tm_vert; \
vi.mask = TM_ELEM_CD_GET_VOID_P(vi.tm_vert, vi.cd_vert_mask_offset); \
- }\
+ } \
else { \
if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 59320ca0d49..773565b4b24 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -2451,7 +2451,7 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
face_normal);
break;
case PBVH_TRIMESH:
- //TM_mesh_elem_index_ensure(pbvh->tm, TM_VERTEX);
+ // TM_mesh_elem_index_ensure(pbvh->tm, TM_VERTEX);
hit = pbvh_trimesh_node_raycast(node,
ray_start,
ray_normal,
@@ -3003,16 +3003,18 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
return node->proxies + index;
}
-void BKE_pbvh_node_free_proxies(PBVHNode *node)
+void BKE_pbvh_node_free_proxies(PBVH *pbvh, PBVHNode *node)
{
for (int p = 0; p < node->proxy_count; p++) {
MEM_freeN(node->proxies[p].co);
node->proxies[p].co = NULL;
}
- MEM_freeN(node->proxies);
- node->proxies = NULL;
+ if (node->proxies) {
+ MEM_freeN(node->proxies);
+ }
+ node->proxies = NULL;
node->proxy_count = 0;
}
@@ -3218,3 +3220,378 @@ void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
{
pbvh->respect_hide = respect_hide;
}
+
+#ifdef PROXY_ADVANCED
+// TODO: if this really works, make sure to pull the neighbor iterator out of sculpt.c and put it
+// here
+/* clang-format off */
+# include "BKE_context.h"
+# include "DNA_object_types.h"
+# include "DNA_scene_types.h"
+# include "../../editors/sculpt_paint/sculpt_intern.h"
+/* clang-format on */
+
+int checkalloc(void **data, int esize, int oldsize, int newsize, int emask, int umask)
+{
+ if (!*data && (emask & umask)) {
+ *data = MEM_callocN(newsize * esize, "pbvh proxy vert arrays");
+ return emask;
+ }
+ // update channel if it already was allocated once, or is requested by umask
+ else if (newsize != oldsize && (*data || (emask & umask))) {
+ *data = MEM_reallocN(data, newsize * esize);
+ return emask;
+ }
+
+ return 0;
+}
+
+void BKE_pbvh_e
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list