Blender V4.3
subdiv_modifier.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "MEM_guardedalloc.h"
8
9#include "DNA_mesh_types.h"
10#include "DNA_modifier_types.h"
11#include "DNA_object_types.h"
12#include "DNA_userdef_types.h"
13
14#include "BKE_customdata.hh"
15#include "BKE_mesh.hh"
16#include "BKE_modifier.hh"
17#include "BKE_subdiv.hh"
18
19#include "GPU_capabilities.hh"
20#include "GPU_context.hh"
21
22using namespace blender::bke;
23
25 const bool use_render_params)
26{
27 const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
28
29 subdiv::Settings settings{};
30 settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
31 settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
32 settings.level = settings.is_simple ? 1 :
33 (settings.is_adaptive ? smd->quality : requested_levels);
34 settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
35 settings.vtx_boundary_interpolation = subdiv::vtx_boundary_interpolation_from_subsurf(
36 smd->boundary_smooth);
37 settings.fvar_linear_interpolation = subdiv::fvar_interpolation_from_uv_smooth(smd->uv_smooth);
38
39 return settings;
40}
41
42bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params)
43{
44 subdiv::Settings settings = BKE_subsurf_modifier_settings_init(smd, use_render_params);
45
47 if (settings.level == 0) {
48 /* Modifier is effectively disabled, but still update settings if runtime data
49 * was already allocated. */
50 if (runtime_data) {
51 runtime_data->settings = settings;
52
53 runtime_data->used_cpu = runtime_data->used_gpu = 0;
54 }
55
56 return false;
57 }
58
59 /* Allocate runtime data if it did not exist yet. */
60 if (runtime_data == nullptr) {
61 runtime_data = MEM_cnew<SubsurfRuntimeData>(__func__);
62 smd->modifier.runtime = runtime_data;
63 }
64 runtime_data->settings = settings;
65 return true;
66}
67
69 const Object *ob,
70 int required_mode)
71{
72 ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
73
74 while (md) {
75 if (BKE_modifier_is_enabled(scene, md, required_mode)) {
76 break;
77 }
78
79 md = md->prev;
80 }
81
82 return md;
83}
84
90
92{
94 mesh->normals_domain() == MeshNormalDomain::Corner;
95}
96
98{
99 /* Only OpenGL is supported for OpenSubdiv evaluation for now. */
101 return false;
102 }
103
104 /* Now that we know it is OpenGL, check for Qualcomm GPUs,
105 * which GPU subdiv is broken on some of (#124515) */
107 return false;
108 }
109
111 return false;
112 }
113
114 return true;
115}
116
118 const Mesh *mesh)
119{
120 if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
121 /* GPU subdivision is explicitly disabled, so we don't force it. */
122 return false;
123 }
124
126 /* The GPU type is not compatible with the subdivision. */
127 return false;
128 }
129
131}
132
134 const Object *ob,
135 const Mesh *mesh,
136 const SubsurfModifierData *smd,
137 int required_mode)
138{
139 if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
140 return false;
141 }
142
143 /* Deactivate GPU subdivision if sharp edges or custom normals are used as those are
144 * complicated to support on GPU, and should really be separate workflows. */
146 return false;
147 }
148
149 ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
150 if (md != (const ModifierData *)smd) {
151 return false;
152 }
153
155}
156
158{
159 SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data;
160 return runtime_data && runtime_data->has_gpu_subdiv;
161}
162
164
166 const Mesh *mesh,
167 const bool for_draw_code)
168{
169 if (for_draw_code) {
170 runtime_data->used_gpu = 2; /* countdown in frames */
171
172 return runtime_data->subdiv_gpu = subdiv::update_from_mesh(
173 runtime_data->subdiv_gpu, &runtime_data->settings, mesh);
174 }
175 runtime_data->used_cpu = 2;
176 return runtime_data->subdiv_cpu = subdiv::update_from_mesh(
177 runtime_data->subdiv_cpu, &runtime_data->settings, mesh);
178}
179
180int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
181{
182 if (is_final_render) {
184 }
185
186 return eModifierMode_Realtime | (is_edit_mode ? int(eModifierMode_Editmode) : 0);
187}
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
#define MAX_GPU_SUBDIV_SSBOS
@ CD_CUSTOMLOOPNORMAL
@ eModifierMode_Render
@ eModifierMode_Editmode
@ eModifierMode_Realtime
@ SUBSURF_TYPE_SIMPLE
@ eSubsurfModifierFlag_UseRecursiveSubdivision
@ eSubsurfModifierFlag_UseCrease
@ eSubsurfModifierFlag_UseCustomNormals
Object is a sort of wrapper for general info.
@ USER_GPU_FLAG_SUBDIVISION_EVALUATION
int GPU_max_compute_shader_storage_blocks()
eGPUBackendType GPU_backend_get_type()
@ GPU_DRIVER_ANY
@ GPU_OS_WIN
@ GPU_DEVICE_QUALCOMM
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
Read Guarded memory(de)allocation.
unsigned int U
Definition btGjkEpa3.h:78
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
FVarLinearInterpolation fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition subdiv.cc:49
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition subdiv.cc:69
Subdiv * update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:181
void * last
struct ModifierData * prev
ListBase modifiers
blender::bke::subdiv::Settings settings
blender::bke::subdiv::Subdiv * subdiv_cpu
blender::bke::subdiv::Subdiv * subdiv_gpu
int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
void(* BKE_subsurf_modifier_free_gpu_cache_cb)(subdiv::Subdiv *subdiv)
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfModifierData *smd, const Mesh *mesh)
bool BKE_subsurf_modifier_has_split_normals(const SubsurfModifierData *smd, const Mesh *mesh)
bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params)
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, const Object *ob, const Mesh *mesh, const SubsurfModifierData *smd, int required_mode)
static ModifierData * modifier_get_last_enabled_for_mode(const Scene *scene, const Object *ob, int required_mode)
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
static bool is_subdivision_evaluation_possible_on_gpu()
subdiv::Settings BKE_subsurf_modifier_settings_init(const SubsurfModifierData *smd, const bool use_render_params)
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
subdiv::Subdiv * BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, const bool for_draw_code)