Subdiv: Use index instead of pointer for grid to face map

Switch from face pointers to indices, with the following benefits:
- Halve memory usage required for array (saves 16 MB with 1 million quads).
- Allow better code reuse with index-based utilities.
- Ease future replacement of `SubdivCCGFace` with mesh's face offsets.
- Allow future replacement of array with `Mesh::corner_to_face_map()`
- Potentially lower memory bandwidth required during multires evaluation
- Simplify retrieval of index in `BKE_subdiv_ccg_grid_to_face_index`.

For clarity, `gridfaces` was renamed to `grid_to_face_map`.

Pull Request: https://projects.blender.org/blender/blender/pulls/111078
This commit is contained in:
Hans Goudey
2023-08-31 19:40:39 +02:00
committed by Hans Goudey
parent 074dbf08cd
commit 2228006d5b
6 changed files with 23 additions and 26 deletions

View File

@@ -210,7 +210,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
Mesh *me,
@@ -445,7 +445,7 @@ void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
CCGKey *key);

View File

@@ -160,7 +160,7 @@ struct SubdivCCG {
int num_faces = -1;
SubdivCCGFace *faces = nullptr;
/* Indexed by grid index, points to corresponding face from `faces`. */
SubdivCCGFace **grid_faces = nullptr;
blender::Array<int> grid_to_face_map;
/* Edges which are adjacent to faces.
* Used for faster grid stitching, in the cost of extra memory.

View File

@@ -2215,7 +2215,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
subdiv_ccg->grids,
subdiv_ccg->num_grids,
&key,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_faces,
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden,
base_mesh,
@@ -2304,7 +2304,7 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
BKE_pbvh_grids_update(pbvh,
subdiv_ccg->grids,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_faces,
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden,
&key);

View File

@@ -914,7 +914,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
Mesh *me,
@@ -924,7 +924,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->header.type = PBVH_GRIDS;
pbvh->grids = grids;
pbvh->gridfaces = gridfaces;
pbvh->grid_to_face_map = grid_to_face_map;
pbvh->grid_flag_mats = flagmats;
pbvh->totgrid = totgrid;
pbvh->gridkey = *key;
@@ -1715,10 +1715,11 @@ void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int
pbvh_iter_begin(&iter, pbvh, {});
SubdivCCGFace *all_faces = pbvh->subdiv_ccg->faces;
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_UpdateNormals) {
for (const int grid : node->prim_indices) {
void *face = pbvh->gridfaces[grid];
void *face = &all_faces[pbvh->grid_to_face_map[grid]];
BLI_gset_add(face_set, face);
}
@@ -2944,14 +2945,14 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh,
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
CCGKey *key)
{
pbvh->gridkey = *key;
pbvh->grids = grids;
pbvh->gridfaces = gridfaces;
pbvh->grid_to_face_map = grid_to_face_map;
if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
pbvh->grid_flag_mats = flagmats;

View File

@@ -175,7 +175,7 @@ struct PBVH {
/* Grid Data */
CCGKey gridkey;
CCGElem **grids;
void **gridfaces;
blender::Span<int> grid_to_face_map;
const DMFlagMat *grid_flag_mats;
int totgrid;
BLI_bitmap **grid_hidden;

View File

@@ -155,8 +155,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv)
if (num_faces) {
subdiv_ccg->faces = static_cast<SubdivCCGFace *>(
MEM_calloc_arrayN(num_faces, sizeof(SubdivCCGFace), "Subdiv CCG faces"));
subdiv_ccg->grid_faces = static_cast<SubdivCCGFace **>(
MEM_calloc_arrayN(num_grids, sizeof(SubdivCCGFace *), "Subdiv CCG grid faces"));
subdiv_ccg->grid_to_face_map.reinitialize(num_grids);
}
}
@@ -235,7 +234,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
blender::MutableSpan<int> grid_to_face_map = subdiv_ccg->grid_to_face_map;
const SubdivCCGFace *face = &faces[face_index];
for (int corner = 0; corner < face->num_grids; corner++) {
const int grid_index = face->start_grid_index + corner;
@@ -252,7 +251,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
}
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
grid_to_face_map[grid_index] = face_index;
/* Assign material flags. */
subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags(
data->material_flags_evaluator, face_index);
@@ -266,7 +265,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
blender::MutableSpan<int> grid_to_face_map = subdiv_ccg->grid_to_face_map;
const SubdivCCGFace *face = &faces[face_index];
for (int corner = 0; corner < face->num_grids; corner++) {
const int grid_index = face->start_grid_index + corner;
@@ -282,7 +281,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
}
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
grid_to_face_map[grid_index] = face_index;
/* Assign material flags. */
subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags(
data->material_flags_evaluator, face_index);
@@ -596,7 +595,6 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
BKE_subdiv_free(subdiv_ccg->subdiv);
}
MEM_SAFE_FREE(subdiv_ccg->faces);
MEM_SAFE_FREE(subdiv_ccg->grid_faces);
/* Free map of adjacent edges. */
for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) {
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i];
@@ -1452,7 +1450,7 @@ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_cc
BLI_INLINE
int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index;
int next_face_grid_index = face_grid_index + 1 - face->start_grid_index;
if (next_face_grid_index == face->num_grids) {
@@ -1462,7 +1460,7 @@ int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord
}
BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index;
int prev_face_grid_index = face_grid_index - 1 - face->start_grid_index;
if (prev_face_grid_index < 0) {
@@ -1478,7 +1476,7 @@ static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg,
const bool include_duplicates,
SubdivCCGNeighbors *r_neighbors)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int num_adjacent_grids = face->num_grids;
subdiv_ccg_neighbors_init(
@@ -1506,7 +1504,7 @@ static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg,
Subdiv *subdiv = subdiv_ccg->subdiv;
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
const SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_index = face - subdiv_ccg->faces;
const int face_grid_index = coord->grid_index - face->start_grid_index;
const int num_face_grids = face->num_grids;
@@ -1583,7 +1581,7 @@ static int adjacent_edge_index_from_coord(const SubdivCCG *subdiv_ccg, const Sub
{
Subdiv *subdiv = subdiv_ccg->subdiv;
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index - face->start_grid_index;
const int face_index = face - subdiv_ccg->faces;
@@ -1876,9 +1874,7 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index)
{
const SubdivCCGFace *face = subdiv_ccg->grid_faces[grid_index];
const int face_index = face - subdiv_ccg->faces;
return face_index;
return subdiv_ccg->grid_to_face_map[grid_index];
}
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg)