Blender  V3.3
subdiv_modifier.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
4 #include "BKE_subdiv_modifier.h"
5 
6 #include "MEM_guardedalloc.h"
7 
8 #include "DNA_mesh_types.h"
9 #include "DNA_modifier_types.h"
10 #include "DNA_object_types.h"
11 #include "DNA_scene_types.h"
12 #include "DNA_userdef_types.h"
13 
14 #include "BKE_modifier.h"
15 #include "BKE_subdiv.h"
16 
17 #include "GPU_capabilities.h"
18 #include "GPU_context.h"
19 
20 #include "opensubdiv_capi.h"
21 
22 bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params)
23 {
24  const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
25 
26  SubdivSettings settings;
27  settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
28  settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
29  settings.level = settings.is_simple ? 1 :
30  (settings.is_adaptive ? smd->quality : requested_levels);
31  settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
32  settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
33  smd->boundary_smooth);
34  settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
35  smd->uv_smooth);
36 
37  SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
38  if (settings.level == 0) {
39  /* Modifier is effectively disabled, but still update settings if runtime data
40  * was already allocated. */
41  if (runtime_data) {
42  runtime_data->settings = settings;
43  }
44 
45  return false;
46  }
47 
48  /* Allocate runtime data if it did not exist yet. */
49  if (runtime_data == NULL) {
50  runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
51  smd->modifier.runtime = runtime_data;
52  }
53  runtime_data->settings = settings;
54  return true;
55 }
56 
58  const Object *ob,
59  int required_mode)
60 {
61  ModifierData *md = ob->modifiers.last;
62 
63  while (md) {
64  if (BKE_modifier_is_enabled(scene, md, required_mode)) {
65  break;
66  }
67 
68  md = md->prev;
69  }
70 
71  return md;
72 }
73 
75 {
78 }
79 
81  const Mesh *mesh)
82 {
84 }
85 
87 {
88  /* Only OpenGL is supported for OpenSubdiv evaluation for now. */
90  return false;
91  }
92 
94  return false;
95  }
96 
98  return false;
99  }
100 
101  return true;
102 }
103 
105  const Mesh *mesh)
106 {
107  if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
108  /* GPU subdivision is explicitly disabled, so we don't force it. */
109  return false;
110  }
111 
113  /* The GPU type is not compatible with the subdivision. */
114  return false;
115  }
116 
118 }
119 
121  const Object *ob,
122  const Mesh *mesh,
123  const SubsurfModifierData *smd,
124  int required_mode)
125 {
126  if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
127  return false;
128  }
129 
130  /* Deactivate GPU subdivision if autosmooth or custom split normals are used as those are
131  * complicated to support on GPU, and should really be separate workflows. */
133  return false;
134  }
135 
136  ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
137  if (md != (const ModifierData *)smd) {
138  return false;
139  }
140 
142 }
143 
145 {
147  return runtime_data && runtime_data->has_gpu_subdiv;
148 }
149 
151 
153  const Mesh *mesh,
154  const bool for_draw_code)
155 {
156  if (runtime_data->subdiv && runtime_data->set_by_draw_code != for_draw_code) {
157  BKE_subdiv_free(runtime_data->subdiv);
158  runtime_data->subdiv = NULL;
159  }
161  runtime_data->subdiv, &runtime_data->settings, mesh);
162  runtime_data->subdiv = subdiv;
163  runtime_data->set_by_draw_code = for_draw_code;
164  return subdiv;
165 }
166 
167 int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
168 {
169  if (is_final_render) {
170  return eModifierMode_Render;
171  }
172 
173  return eModifierMode_Realtime | (is_edit_mode ? eModifierMode_Editmode : 0);
174 }
bool CustomData_has_layer(const struct CustomData *data, int type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition: subdiv.c:66
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:184
Subdiv * BKE_subdiv_update_from_mesh(Subdiv *subdiv, const SubdivSettings *settings, const struct Mesh *mesh)
eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition: subdiv.c:46
#define MAX_GPU_SUBDIV_SSBOS
@ CD_CUSTOMLOOPNORMAL
@ ME_AUTOSMOOTH
@ 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
bool GPU_compute_shader_support(void)
int GPU_max_compute_shader_storage_blocks(void)
bool GPU_shader_storage_buffer_objects_support(void)
eGPUBackendType GPU_backend_get_type(void)
Definition: gpu_context.cc:274
@ GPU_BACKEND_OPENGL
Definition: GPU_platform.h:17
Read Guarded memory(de)allocation.
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
SyclQueue void void size_t num_bytes void
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void * last
Definition: DNA_listBase.h:31
struct SubsurfRuntimeData * subsurf_runtime_data
uint16_t flag
Mesh_Runtime runtime
CustomData ldata
struct ModifierData * prev
ListBase modifiers
struct Subdiv * subdiv
SubdivSettings settings
static bool is_subdivision_evaluation_possible_on_gpu(void)
int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(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)
Subdiv * BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, const bool for_draw_code)
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
void(* BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv)
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
static bool subsurf_modifier_use_autosmooth_or_split_normals(const SubsurfModifierData *smd, const Mesh *mesh)
static ModifierData * modifier_get_last_enabled_for_mode(const Scene *scene, const Object *ob, int required_mode)