diff options
-rw-r--r-- | source/blender/blenkernel/BKE_subdiv_modifier.h | 36 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.cc | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_wrapper.cc | 23 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_modifier.c | 62 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.cc | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_subdivision.cc | 50 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_subdivision.h | 3 | ||||
-rw-r--r-- | source/blender/editors/space_info/info_stats.cc | 18 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_mesh_types.h | 19 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 7 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_subsurf.c | 42 |
11 files changed, 146 insertions, 150 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_modifier.h b/source/blender/blenkernel/BKE_subdiv_modifier.h index 4ad17610207..271026d4253 100644 --- a/source/blender/blenkernel/BKE_subdiv_modifier.h +++ b/source/blender/blenkernel/BKE_subdiv_modifier.h @@ -7,6 +7,8 @@ #pragma once +#include "BKE_subdiv.h" + #include "BLI_sys_types.h" #ifdef __cplusplus @@ -24,9 +26,30 @@ struct Subdiv; struct SubdivSettings; struct SubsurfModifierData; -void BKE_subsurf_modifier_subdiv_settings_init(struct SubdivSettings *settings, - const struct SubsurfModifierData *smd, - bool use_render_params); +/* Runtime subsurf modifier data, cached in modifier on evaluated meshes. */ +typedef struct SubsurfRuntimeData { + /* Subdivision settings, exists before descriptor or mesh wrapper is created. */ + SubdivSettings settings; + + /* Cached subdivision surface descriptor, with topology and settings. */ + struct Subdiv *subdiv; + bool set_by_draw_code; + + /* Cached mesh wrapper data, to be used for GPU subdiv or lazy evaluation on CPU. */ + bool has_gpu_subdiv; + int resolution; + bool use_optimal_display; + bool calc_loop_normals; + bool use_loop_normals; + + /* Cached from the draw code for stats display. */ + int stats_totvert; + int stats_totedge; + int stats_totpoly; + int stats_totloop; +} SubsurfRuntimeData; + +bool BKE_subsurf_modifier_runtime_init(struct SubsurfModifierData *smd, bool use_render_params); bool BKE_subsurf_modifier_use_custom_loop_normals(const struct SubsurfModifierData *smd, const struct Mesh *mesh); @@ -57,12 +80,7 @@ extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(struct Subdiv *subdiv); * which matches settings and topology. */ struct Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure( - const struct SubsurfModifierData *smd, - const struct SubdivSettings *subdiv_settings, - const struct Mesh *mesh, - bool for_draw_code); - -struct SubsurfRuntimeData *BKE_subsurf_modifier_ensure_runtime(struct SubsurfModifierData *smd); + struct SubsurfRuntimeData *runtime_data, const struct Mesh *mesh, bool for_draw_code); /** * Return the #ModifierMode required for the evaluation of the subsurf modifier, diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 8496692ceb3..b3a9d894944 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -52,6 +52,7 @@ #include "BKE_object.h" #include "BKE_object_deform.h" #include "BKE_paint.h" +#include "BKE_subdiv_modifier.h" #include "BLI_sys_types.h" /* for intptr_t support */ @@ -598,10 +599,10 @@ static bool mesh_has_modifier_final_normals(const Mesh *mesh_input, /* Test if mesh has the required loop normals, in case an additional modifier * evaluation from another instance or from an operator requests it but the * initial normals were not loop normals. */ - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); - return (!do_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)); + return (!calc_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)); } static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, @@ -610,16 +611,19 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, Mesh *mesh_final) { /* Compute normals. */ - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ - mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals; + SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data; + if (subsurf_runtime_data) { + subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + } - if (do_loop_normals) { + if (calc_loop_normals) { /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ - if (mesh_final->runtime.subsurf_resolution == 0) { + if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { BKE_mesh_calc_normals_split(mesh_final); } } @@ -1266,15 +1270,18 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, return; } - const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); - mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals; + SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data; + if (subsurf_runtime_data) { + subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + } - if (do_loop_normals) { + if (calc_loop_normals) { /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the * wrapper is generated. */ - if (mesh_final->runtime.subsurf_resolution == 0) { + if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { BKE_mesh_calc_normals_split(mesh_final); } } diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index c505a74724b..fdebf1d6a26 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -314,28 +314,23 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me) return me; } + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; + if (runtime_data == nullptr || runtime_data->settings.level == 0) { + return me; + } + /* Initialize the settings before ensuring the descriptor as this is checked to decide whether * subdivision is needed at all, and checking the descriptor status might involve checking if the * data is out-of-date, which is a very expensive operation. */ SubdivToMeshSettings mesh_settings; - mesh_settings.resolution = me->runtime.subsurf_resolution; - mesh_settings.use_optimal_display = me->runtime.subsurf_use_optimal_display; + mesh_settings.resolution = runtime_data->resolution; + mesh_settings.use_optimal_display = runtime_data->use_optimal_display; if (mesh_settings.resolution < 3) { return me; } - const bool apply_render = me->runtime.subsurf_apply_render; - - SubdivSettings subdiv_settings; - BKE_subsurf_modifier_subdiv_settings_init(&subdiv_settings, smd, apply_render); - if (subdiv_settings.level == 0) { - return me; - } - - SubsurfRuntimeData *runtime_data = BKE_subsurf_modifier_ensure_runtime(smd); - - Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(smd, &subdiv_settings, me, false); + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, me, false); if (subdiv == nullptr) { /* Happens on bad topology, but also on empty input mesh. */ return me; @@ -358,7 +353,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me) CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } - else if (me->runtime.subsurf_do_loop_normals) { + else if (runtime_data->calc_loop_normals) { BKE_mesh_calc_normals_split(subdiv_mesh); } diff --git a/source/blender/blenkernel/intern/subdiv_modifier.c b/source/blender/blenkernel/intern/subdiv_modifier.c index e43da956ce5..f5423dccc0f 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.c +++ b/source/blender/blenkernel/intern/subdiv_modifier.c @@ -3,8 +3,6 @@ #include "BKE_subdiv_modifier.h" -#include "BLI_session_uuid.h" - #include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" @@ -21,22 +19,40 @@ #include "opensubdiv_capi.h" -void BKE_subsurf_modifier_subdiv_settings_init(SubdivSettings *settings, - const SubsurfModifierData *smd, - const bool use_render_params) +bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params) { const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels; - settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE); - settings->is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision); - settings->level = settings->is_simple ? - 1 : - (settings->is_adaptive ? smd->quality : requested_levels); - settings->use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease); - settings->vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( + SubdivSettings settings; + settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE); + settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision); + settings.level = settings.is_simple ? 1 : + (settings.is_adaptive ? smd->quality : requested_levels); + settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease); + settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( smd->boundary_smooth); - settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( + settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( smd->uv_smooth); + + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; + if (settings.level == 0) { + /* Modifier is effectively disabled, but still update settings if runtime data + * was already allocated. */ + if (runtime_data) { + runtime_data->settings = settings; + } + + return false; + } + else { + /* Allocate runtime data if it did not exist yet. */ + if (runtime_data == NULL) { + runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime"); + smd->modifier.runtime = runtime_data; + } + runtime_data->settings = settings; + return true; + } } static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene, @@ -133,37 +149,27 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh) { - return BLI_session_uuid_is_generated(&mesh->runtime.subsurf_session_uuid); + SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data; + return runtime_data && runtime_data->has_gpu_subdiv; } void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = NULL; -Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(const SubsurfModifierData *smd, - const SubdivSettings *subdiv_settings, +Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, const bool for_draw_code) { - SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; if (runtime_data->subdiv && runtime_data->set_by_draw_code != for_draw_code) { BKE_subdiv_free(runtime_data->subdiv); runtime_data->subdiv = NULL; } - Subdiv *subdiv = BKE_subdiv_update_from_mesh(runtime_data->subdiv, subdiv_settings, mesh); + Subdiv *subdiv = BKE_subdiv_update_from_mesh( + runtime_data->subdiv, &runtime_data->settings, mesh); runtime_data->subdiv = subdiv; runtime_data->set_by_draw_code = for_draw_code; return subdiv; } -SubsurfRuntimeData *BKE_subsurf_modifier_ensure_runtime(SubsurfModifierData *smd) -{ - SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; - if (runtime_data == NULL) { - runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime"); - smd->modifier.runtime = runtime_data; - } - return runtime_data; -} - int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode) { if (is_final_render) { diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 96b5910072b..7c02ee2c033 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -2068,8 +2068,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, } if (do_subdivision) { - DRW_create_subdivision(scene, - ob, + DRW_create_subdivision(ob, me, cache, &cache->final, diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 2b0953b0b9b..b37a420b555 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1052,14 +1052,10 @@ static void build_vertex_face_adjacency_maps(DRWSubdivCache *cache) static bool draw_subdiv_build_cache(DRWSubdivCache *cache, Subdiv *subdiv, Mesh *mesh_eval, - const Scene *scene, - const SubsurfModifierData *smd, - const bool is_final_render) + const SubsurfRuntimeData *runtime_data) { - const int requested_levels = (is_final_render) ? smd->renderLevels : smd->levels; - const int level = get_render_subsurf_level(&scene->r, requested_levels, is_final_render); SubdivToMeshSettings to_mesh_settings; - to_mesh_settings.resolution = (1 << level) + 1; + to_mesh_settings.resolution = runtime_data->resolution; to_mesh_settings.use_optimal_display = false; if (cache->resolution != to_mesh_settings.resolution) { @@ -2006,8 +2002,7 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache, MEM_freeN(per_polygon_mat_offset); } -static bool draw_subdiv_create_requested_buffers(const Scene *scene, - Object *ob, +static bool draw_subdiv_create_requested_buffers(Object *ob, Mesh *mesh, struct MeshBatchCache *batch_cache, MeshBufferCache *mbc, @@ -2021,16 +2016,10 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, const bool use_hide, OpenSubdiv_EvaluatorCache *evaluator_cache) { - SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData *>( - BKE_modifiers_findby_session_uuid(ob, &mesh->runtime.subsurf_session_uuid)); - BLI_assert(smd); + SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data; + BLI_assert(runtime_data && runtime_data->has_gpu_subdiv); - const bool is_final_render = DRW_state_is_scene_render(); - - SubdivSettings settings; - BKE_subsurf_modifier_subdiv_settings_init(&settings, smd, is_final_render); - - if (settings.level == 0) { + if (runtime_data->settings.level == 0) { return false; } @@ -2041,9 +2030,7 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, bm = mesh->edit_mesh->bm; } - BKE_subsurf_modifier_ensure_runtime(smd); - - Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(smd, &settings, mesh_eval, true); + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh_eval, true); if (!subdiv) { return false; } @@ -2064,13 +2051,13 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, } DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache); - if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, scene, smd, is_final_render)) { + if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, runtime_data)) { return false; } /* Edges which do not come from coarse edges should not be drawn in edit mode, only in object * mode when optimal display in turned off. */ - const bool optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges) || is_editmode; + const bool optimal_display = runtime_data->use_optimal_display || is_editmode; draw_cache->bm = bm; draw_cache->mesh = mesh_eval; @@ -2078,14 +2065,13 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, draw_cache->optimal_display = optimal_display; draw_cache->num_subdiv_triangles = tris_count_from_number_of_loops(draw_cache->num_subdiv_loops); - /* Copy topology information for stats display. Use `mesh` directly, as `mesh_eval` could be the - * edit mesh. */ - mesh->runtime.subsurf_totvert = draw_cache->num_subdiv_verts; - mesh->runtime.subsurf_totedge = draw_cache->num_subdiv_edges; - mesh->runtime.subsurf_totpoly = draw_cache->num_subdiv_quads; - mesh->runtime.subsurf_totloop = draw_cache->num_subdiv_loops; + /* Copy topology information for stats display. */ + runtime_data->stats_totvert = draw_cache->num_subdiv_verts; + runtime_data->stats_totedge = draw_cache->num_subdiv_edges; + runtime_data->stats_totpoly = draw_cache->num_subdiv_quads; + runtime_data->stats_totloop = draw_cache->num_subdiv_loops; - draw_cache->use_custom_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) && + draw_cache->use_custom_loop_normals = (runtime_data->use_loop_normals) && (mesh_eval->flag & ME_AUTOSMOOTH) && CustomData_has_layer(&mesh_eval->ldata, CD_CUSTOMLOOPNORMAL); @@ -2207,8 +2193,7 @@ blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWS static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr; -void DRW_create_subdivision(const Scene *scene, - Object *ob, +void DRW_create_subdivision(Object *ob, Mesh *mesh, struct MeshBatchCache *batch_cache, MeshBufferCache *mbc, @@ -2231,8 +2216,7 @@ void DRW_create_subdivision(const Scene *scene, const double begin_time = PIL_check_seconds_timer(); #endif - if (!draw_subdiv_create_requested_buffers(scene, - ob, + if (!draw_subdiv_create_requested_buffers(ob, mesh, batch_cache, mbc, diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h index 8920a2dcd51..2d9f4713feb 100644 --- a/source/blender/draw/intern/draw_subdivision.h +++ b/source/blender/draw/intern/draw_subdivision.h @@ -185,8 +185,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache); /** \} */ -void DRW_create_subdivision(const struct Scene *scene, - struct Object *ob, +void DRW_create_subdivision(struct Object *ob, struct Mesh *mesh, struct MeshBatchCache *batch_cache, struct MeshBufferCache *mbc, diff --git a/source/blender/editors/space_info/info_stats.cc b/source/blender/editors/space_info/info_stats.cc index b817ff887ce..29a7eb150a1 100644 --- a/source/blender/editors/space_info/info_stats.cc +++ b/source/blender/editors/space_info/info_stats.cc @@ -46,6 +46,7 @@ #include "BKE_pbvh.h" #include "BKE_scene.h" #include "BKE_subdiv_ccg.h" +#include "BKE_subdiv_modifier.h" #include "DEG_depsgraph_query.h" @@ -92,15 +93,18 @@ static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *st } int totvert, totedge, totface, totloop; - if (me_eval->runtime.subdiv_ccg != nullptr) { - const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg; + + const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg; + const SubsurfRuntimeData *subsurf_runtime_data = me_eval->runtime.subsurf_runtime_data; + + if (subdiv_ccg != nullptr) { BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop); } - else if (me_eval->runtime.subsurf_resolution != 0) { - totvert = me_eval->runtime.subsurf_totvert; - totedge = me_eval->runtime.subsurf_totedge; - totface = me_eval->runtime.subsurf_totpoly; - totloop = me_eval->runtime.subsurf_totloop; + else if (subsurf_runtime_data && subsurf_runtime_data->resolution != 0) { + totvert = subsurf_runtime_data->stats_totvert; + totedge = subsurf_runtime_data->stats_totedge; + totface = subsurf_runtime_data->stats_totpoly; + totloop = subsurf_runtime_data->stats_totloop; } else { totvert = me_eval->totvert; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index a66badb4a68..2eca84959b8 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -32,6 +32,7 @@ struct MVert; struct Material; struct Mesh; struct SubdivCCG; +struct SubsurfRuntimeData; # # @@ -123,26 +124,18 @@ typedef struct Mesh_Runtime { /** * Settings for lazily evaluating the subdivision on the CPU if needed. These are - * set in the modifier when GPU subdivision can be performed. + * set in the modifier when GPU subdivision can be performed, and owned by the by + * the modifier in the object. */ - SessionUUID subsurf_session_uuid; - char subsurf_resolution; - char subsurf_do_loop_normals; - char subsurf_apply_render; - char subsurf_use_optimal_display; - - /* Cached from the draw code for stats display. */ - int subsurf_totvert; - int subsurf_totedge; - int subsurf_totpoly; - int subsurf_totloop; - char _pad2[2]; + struct SubsurfRuntimeData *subsurf_runtime_data; + void *_pad1; /** * Caches for lazily computed vertex and polygon normals. These are stored here rather than in * #CustomData because they can be calculated on a const mesh, and adding custom data layers on a * const mesh is not thread-safe. */ + char _pad2[6]; char vert_normals_dirty; char poly_normals_dirty; float (*vert_normals)[3]; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 6e3ce7e98a8..f148116eba8 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -178,13 +178,6 @@ typedef enum { SUBSURF_BOUNDARY_SMOOTH_PRESERVE_CORNERS = 1, } eSubsurfBoundarySmooth; -typedef struct SubsurfRuntimeData { - /* Cached subdivision surface descriptor, with topology and settings. */ - struct Subdiv *subdiv; - char set_by_draw_code; - char _pad[7]; -} SubsurfRuntimeData; - typedef struct SubsurfModifierData { ModifierData modifier; diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 4201bab0326..23f447f2469 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -196,16 +196,21 @@ static Mesh *subdiv_as_ccg(SubsurfModifierData *smd, /* Cache settings for lazy CPU evaluation. */ -static void subdiv_cache_cpu_evaluation_settings(const ModifierEvalContext *ctx, - Mesh *me, - SubsurfModifierData *smd) +static void subdiv_cache_mesh_wrapper_settings(const ModifierEvalContext *ctx, + Mesh *mesh, + SubsurfModifierData *smd, + SubsurfRuntimeData *runtime_data) { SubdivToMeshSettings mesh_settings; subdiv_mesh_settings_init(&mesh_settings, smd, ctx); - me->runtime.subsurf_apply_render = (ctx->flag & MOD_APPLY_RENDER) != 0; - me->runtime.subsurf_resolution = mesh_settings.resolution; - me->runtime.subsurf_use_optimal_display = mesh_settings.use_optimal_display; - me->runtime.subsurf_session_uuid = smd->modifier.session_uuid; + + runtime_data->has_gpu_subdiv = true; + runtime_data->resolution = mesh_settings.resolution; + runtime_data->use_optimal_display = mesh_settings.use_optimal_display; + runtime_data->calc_loop_normals = false; /* Set at the end of modifier stack evaluation. */ + runtime_data->use_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals); + + mesh->runtime.subsurf_runtime_data = runtime_data; } /* Modifier itself. */ @@ -218,13 +223,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return result; #endif SubsurfModifierData *smd = (SubsurfModifierData *)md; - SubdivSettings subdiv_settings; - BKE_subsurf_modifier_subdiv_settings_init( - &subdiv_settings, smd, (ctx->flag & MOD_APPLY_RENDER) != 0); - if (subdiv_settings.level == 0) { + if (!BKE_subsurf_modifier_runtime_init(smd, (ctx->flag & MOD_APPLY_RENDER) != 0)) { return result; } - SubsurfRuntimeData *runtime_data = BKE_subsurf_modifier_ensure_runtime(smd); + + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; /* Delay evaluation to the draw code if possible, provided we do not have to apply the modifier. */ @@ -237,13 +240,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const bool is_editmode = (mesh->edit_mesh != NULL); const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode); if (BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ctx->object, mesh, smd, required_mode)) { - subdiv_cache_cpu_evaluation_settings(ctx, mesh, smd); + subdiv_cache_mesh_wrapper_settings(ctx, mesh, smd, runtime_data); return result; } } - Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure( - smd, &subdiv_settings, mesh, false); + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh, false); if (subdiv == NULL) { /* Happens on bad topology, but also on empty input mesh. */ return result; @@ -294,15 +296,11 @@ static void deformMatrices(ModifierData *md, (void)deform_matrices; SubsurfModifierData *smd = (SubsurfModifierData *)md; - SubdivSettings subdiv_settings; - BKE_subsurf_modifier_subdiv_settings_init( - &subdiv_settings, smd, (ctx->flag & MOD_APPLY_RENDER) != 0); - if (subdiv_settings.level == 0) { + if (!BKE_subsurf_modifier_runtime_init(smd, (ctx->flag & MOD_APPLY_RENDER) != 0)) { return; } - SubsurfRuntimeData *runtime_data = BKE_subsurf_modifier_ensure_runtime(smd); - Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure( - smd, &subdiv_settings, mesh, false); + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh, false); if (subdiv == NULL) { /* Happens on bad topology, but also on empty input mesh. */ return; |