Blender V4.3
draw_cache_impl_subdivision.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
5#include "draw_subdivision.hh"
6
7#include "DNA_mesh_types.h"
8#include "DNA_object_types.h"
9#include "DNA_scene_types.h"
10
11#include "BKE_attribute.hh"
12#include "BKE_editmesh.hh"
13#include "BKE_mesh.hh"
14#include "BKE_mesh_mapping.hh"
15#include "BKE_modifier.hh"
16#include "BKE_object.hh"
17#include "BKE_scene.hh"
18#include "BKE_subdiv.hh"
19#include "BKE_subdiv_eval.hh"
20#include "BKE_subdiv_foreach.hh"
21#include "BKE_subdiv_mesh.hh"
23
24#include "BLI_linklist.h"
25#include "BLI_string.h"
26#include "BLI_string_utils.hh"
27#include "BLI_time.h"
28#include "BLI_virtual_array.hh"
29
30#include "DRW_engine.hh"
31#include "DRW_render.hh"
32
33#include "GPU_capabilities.hh"
34#include "GPU_compute.hh"
35#include "GPU_index_buffer.hh"
36#include "GPU_state.hh"
37#include "GPU_vertex_buffer.hh"
38
39#include "opensubdiv_capi.hh"
43#ifdef WITH_OPENSUBDIV
45#endif
46
47#include "draw_cache_extract.hh"
48#include "draw_cache_impl.hh"
49#include "draw_cache_inline.hh"
51
64
65namespace blender::draw {
66
67enum {
89
91};
92
94
95#define SHADER_CUSTOM_DATA_INTERP_MAX_DIMENSIONS 4
96static GPUShader
98
99static const char *get_shader_code(int shader_type)
100{
101 switch (shader_type) {
105 }
108 }
109 case SHADER_BUFFER_LNOR: {
111 }
115 }
118 }
122 }
129 }
135 }
138 }
141 }
144 }
145 }
146 return nullptr;
147}
148
149static const char *get_shader_name(int shader_type)
150{
151 switch (shader_type) {
152 case SHADER_BUFFER_LINES: {
153 return "subdiv lines build";
154 }
156 return "subdiv lines loose build";
157 }
158 case SHADER_BUFFER_LNOR: {
159 return "subdiv lnor build";
160 }
162 return "subdiv edge fac build";
163 }
166 return "subdiv tris";
167 }
169 return "subdiv normals accumulate";
170 }
172 return "subdiv normals finalize";
173 }
175 return "subdiv patch evaluation";
176 }
178 return "subdiv patch evaluation face-varying";
179 }
181 return "subdiv patch evaluation face dots";
182 }
184 return "subdiv patch evaluation face dots with normals";
185 }
187 return "subdiv patch evaluation orco";
188 }
190 return "subdiv custom data interp 1D";
191 }
193 return "subdiv custom data interp 2D";
194 }
196 return "subdiv custom data interp 3D";
197 }
199 return "subdiv custom data interp 4D";
200 }
202 return "subdiv sculpt data";
203 }
205 return "subdiv uv stretch angle";
206 }
208 return "subdiv uv stretch area";
209 }
210 }
211 return nullptr;
212}
213
215{
216 if (g_subdiv_shaders[shader_type] == nullptr) {
217 const char *compute_code = get_shader_code(shader_type);
218
219 const char *defines = nullptr;
220 if (shader_type == SHADER_PATCH_EVALUATION) {
221 defines =
222 "#define OSD_PATCH_BASIS_GLSL\n"
223 "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n";
224 }
225 else if (shader_type == SHADER_PATCH_EVALUATION_FVAR) {
226 defines =
227 "#define OSD_PATCH_BASIS_GLSL\n"
228 "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
229 "#define FVAR_EVALUATION\n";
230 }
231 else if (shader_type == SHADER_PATCH_EVALUATION_FACE_DOTS) {
232 defines =
233 "#define OSD_PATCH_BASIS_GLSL\n"
234 "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
235 "#define FDOTS_EVALUATION\n";
236 }
237 else if (shader_type == SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS) {
238 defines =
239 "#define OSD_PATCH_BASIS_GLSL\n"
240 "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
241 "#define FDOTS_EVALUATION\n"
242 "#define FDOTS_NORMALS\n";
243 }
244 else if (shader_type == SHADER_PATCH_EVALUATION_ORCO) {
245 defines =
246 "#define OSD_PATCH_BASIS_GLSL\n"
247 "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
248 "#define ORCO_EVALUATION\n";
249 }
250 else {
252 }
253
254 /* Merge OpenSubdiv library code with our own library code. */
255 const char *patch_basis_source = openSubdiv_getGLSLPatchBasisSource();
256 const char *subdiv_lib_code = datatoc_common_subdiv_lib_glsl;
257 char *library_code = BLI_string_joinN(patch_basis_source, subdiv_lib_code);
259 compute_code, library_code, defines, get_shader_name(shader_type));
260 MEM_freeN(library_code);
261 }
262
263 return g_subdiv_shaders[shader_type];
264}
265
266static GPUShader *get_subdiv_shader(int shader_type)
267{
268 if (ELEM(shader_type,
273 {
274 return get_patch_evaluation_shader(shader_type);
275 }
276
277 BLI_assert(!ELEM(shader_type,
282
283 if (g_subdiv_shaders[shader_type] == nullptr) {
284 const char *compute_code = get_shader_code(shader_type);
285 const char *defines = nullptr;
286
287 if (ELEM(shader_type,
292 {
293 defines = "#define SUBDIV_POLYGON_OFFSET\n";
294 }
295 else if (shader_type == SHADER_BUFFER_TRIS) {
296 defines =
297 "#define SUBDIV_POLYGON_OFFSET\n"
298 "#define SINGLE_MATERIAL\n";
299 }
300 else if (shader_type == SHADER_BUFFER_LINES_LOOSE) {
301 defines = "#define LINES_LOOSE\n";
302 }
303 else if (shader_type == SHADER_BUFFER_EDGE_FAC) {
304 /* No separate shader for the AMD driver case as we assume that the GPU will not change
305 * during the execution of the program. */
306 defines = GPU_crappy_amd_driver() ? "#define GPU_AMD_DRIVER_BYTE_BUG\n" : nullptr;
307 }
308 else if (shader_type == SHADER_BUFFER_CUSTOM_NORMALS_FINALIZE) {
309 defines = "#define CUSTOM_NORMALS\n";
310 }
311
313 compute_code, datatoc_common_subdiv_lib_glsl, defines, get_shader_name(shader_type));
314 }
315 return g_subdiv_shaders[shader_type];
316}
317
318static GPUShader *get_subdiv_custom_data_shader(int comp_type, int dimensions)
319{
320 BLI_assert(dimensions >= 1 && dimensions <= SHADER_CUSTOM_DATA_INTERP_MAX_DIMENSIONS);
321 if (comp_type == GPU_COMP_U16) {
322 BLI_assert(dimensions == 4);
323 }
324
325 GPUShader *&shader = g_subdiv_custom_data_shaders[dimensions - 1][comp_type];
326
327 if (shader == nullptr) {
328 const char *compute_code = get_shader_code(SHADER_COMP_CUSTOM_DATA_INTERP_1D + dimensions - 1);
329
330 int shader_type = SHADER_COMP_CUSTOM_DATA_INTERP_1D + dimensions - 1;
331
332 std::string defines = "#define SUBDIV_POLYGON_OFFSET\n";
333 defines += "#define DIMENSIONS " + std::to_string(dimensions) + "\n";
334 switch (comp_type) {
335 case GPU_COMP_U16:
336 defines += "#define GPU_COMP_U16\n";
337 break;
338 case GPU_COMP_I32:
339 defines += "#define GPU_COMP_I32\n";
340 break;
341 case GPU_COMP_F32:
342 /* float is the default */
343 break;
344 default:
346 break;
347 }
348
349 shader = GPU_shader_create_compute(compute_code,
351 defines.c_str(),
352 get_shader_name(shader_type));
353 }
354 return shader;
355}
356
357/* -------------------------------------------------------------------- */
364{
365 static GPUVertFormat format = {0};
366 if (format.attr_len == 0) {
368 }
369 return format;
370}
371
372/* Vertex format for `OpenSubdiv::Osd::PatchArray`. */
374{
375 static GPUVertFormat format = {0};
376 if (format.attr_len == 0) {
383 }
384 return format;
385}
386
387/* Vertex format used for the `PatchTable::PatchHandle`. */
389{
390 static GPUVertFormat format = {0};
391 if (format.attr_len == 0) {
395 }
396 return format;
397}
398
399/* Vertex format used for the quad-tree nodes of the PatchMap. */
401{
402 static GPUVertFormat format = {0};
403 if (format.attr_len == 0) {
405 }
406 return format;
407}
408
409/* Vertex format for `OpenSubdiv::Osd::PatchParam`, not really used, it is only for making sure
410 * that the #gpu::VertBuf used to wrap the OpenSubdiv patch param buffer is valid. */
412{
413 static GPUVertFormat format = {0};
414 if (format.attr_len == 0) {
416 }
417 return format;
418}
419
420/* Vertex format for the patches' vertices index buffer. */
422{
423 static GPUVertFormat format = {0};
424 if (format.attr_len == 0) {
426 }
427 return format;
428}
429
430/* Vertex format for the OpenSubdiv vertex buffer. */
432{
433 static GPUVertFormat format = {0};
434 if (format.attr_len == 0) {
435 /* We use 4 components for the vectors to account for padding in the compute shaders, where
436 * vec3 is promoted to vec4. */
438 }
439 return format;
440}
441
444 /* UV coordinate encoded as u << 16 | v, where u and v are quantized on 16-bits. */
446};
447
448MINLINE CompressedPatchCoord make_patch_coord(int ptex_face_index, float u, float v)
449{
450 CompressedPatchCoord patch_coord = {
451 ptex_face_index,
452 (uint(u * 65535.0f) << 16) | uint(v * 65535.0f),
453 };
454 return patch_coord;
455}
456
457/* Vertex format used for the #CompressedPatchCoord. */
459{
460 static GPUVertFormat format = {0};
461 if (format.attr_len == 0) {
462 /* WARNING! Adjust #CompressedPatchCoord accordingly. */
465 }
466 return format;
467}
468
470{
471 static GPUVertFormat format;
472 if (format.attr_len == 0) {
474 }
475 return format;
476}
477
479{
480 static GPUVertFormat format = {0};
481 if (format.attr_len == 0) {
485 }
486 return format;
487}
488
491/* -------------------------------------------------------------------- */
495static void vertbuf_bind_gpu(const OpenSubdiv_Buffer *buffer)
496{
497 gpu::VertBuf *verts = (gpu::VertBuf *)(buffer->data);
499}
500
501static void *vertbuf_alloc(const OpenSubdiv_Buffer *interface, const uint len)
502{
503 gpu::VertBuf *verts = (gpu::VertBuf *)(interface->data);
505 return verts->data<char>().data();
506}
507
508static void vertbuf_device_alloc(const OpenSubdiv_Buffer *interface, const uint len)
509{
510 gpu::VertBuf *verts = (gpu::VertBuf *)(interface->data);
511 /* This assumes that GPU_USAGE_DEVICE_ONLY was used, which won't allocate host memory. */
512 // BLI_assert(GPU_vertbuf_get_usage(verts) == GPU_USAGE_DEVICE_ONLY);
514}
515
516static void vertbuf_wrap_device_handle(const OpenSubdiv_Buffer *interface, uint64_t handle)
517{
518 gpu::VertBuf *verts = (gpu::VertBuf *)(interface->data);
520}
521
522static void vertbuf_update_data(const OpenSubdiv_Buffer *interface,
523 uint start,
524 uint len,
525 const void *data)
526{
527 gpu::VertBuf *verts = (gpu::VertBuf *)(interface->data);
528 GPU_vertbuf_update_sub(verts, start, len, data);
529}
530
531static void opensubdiv_gpu_buffer_init(OpenSubdiv_Buffer *buffer_interface, gpu::VertBuf *vertbuf)
532{
533 buffer_interface->data = vertbuf;
534 buffer_interface->bind_gpu = vertbuf_bind_gpu;
535 buffer_interface->buffer_offset = 0;
537 buffer_interface->alloc = vertbuf_alloc;
538 buffer_interface->device_alloc = vertbuf_device_alloc;
539 buffer_interface->device_update = vertbuf_update_data;
540}
541
543 const GPUVertFormat &format)
544{
547 opensubdiv_gpu_buffer_init(interface, buffer);
548 return buffer;
549}
550
553// --------------------------------------------------------
554
555static uint tris_count_from_number_of_loops(const uint number_of_loops)
556{
557 const uint32_t number_of_quads = number_of_loops / 4;
558 return number_of_quads * 2;
559}
560
561/* -------------------------------------------------------------------- */
566 int32_t *vert_origindex,
567 uint num_loops,
568 uint loose_len)
569{
571 GPU_vertbuf_data_alloc(buffer, num_loops + loose_len);
572
573 buffer.data<int32_t>().take_front(num_loops).copy_from({vert_origindex, num_loops});
574}
575
577{
579 draw_subdiv_init_origindex_buffer(*buffer, vert_origindex, num_loops, 0);
580 return buffer;
581}
582
585/* -------------------------------------------------------------------- */
589static void draw_patch_map_build(DRWPatchMap *gpu_patch_map, bke::subdiv::Subdiv *subdiv)
590{
591 gpu::VertBuf *patch_map_handles = GPU_vertbuf_calloc();
593
594 gpu::VertBuf *patch_map_quadtree = GPU_vertbuf_calloc();
596
597 OpenSubdiv_Buffer patch_map_handles_interface;
598 opensubdiv_gpu_buffer_init(&patch_map_handles_interface, patch_map_handles);
599
600 OpenSubdiv_Buffer patch_map_quad_tree_interface;
601 opensubdiv_gpu_buffer_init(&patch_map_quad_tree_interface, patch_map_quadtree);
602
603 int min_patch_face = 0;
604 int max_patch_face = 0;
605 int max_depth = 0;
606 int patches_are_triangular = 0;
607
608 OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
609 evaluator->getPatchMap(evaluator,
610 &patch_map_handles_interface,
611 &patch_map_quad_tree_interface,
612 &min_patch_face,
613 &max_patch_face,
614 &max_depth,
615 &patches_are_triangular);
616
617 gpu_patch_map->patch_map_handles = patch_map_handles;
618 gpu_patch_map->patch_map_quadtree = patch_map_quadtree;
619 gpu_patch_map->min_patch_face = min_patch_face;
620 gpu_patch_map->max_patch_face = max_patch_face;
621 gpu_patch_map->max_depth = max_depth;
622 gpu_patch_map->patches_are_triangular = patches_are_triangular;
623}
624
625static void draw_patch_map_free(DRWPatchMap *gpu_patch_map)
626{
629 gpu_patch_map->min_patch_face = 0;
630 gpu_patch_map->max_patch_face = 0;
631 gpu_patch_map->max_depth = 0;
632 gpu_patch_map->patches_are_triangular = 0;
633}
634
637/* -------------------------------------------------------------------- */
642{
643 return cache.subdiv && cache.subdiv->evaluator && cache.num_subdiv_loops != 0;
644}
645
652
660
691
692/* Flags used in #DRWSubdivCache.extra_coarse_face_data. The flags are packed in the upper bits of
693 * each uint (one per coarse face), #SUBDIV_COARSE_FACE_FLAG_OFFSET tells where they are in the
694 * packed bits. */
695#define SUBDIV_COARSE_FACE_FLAG_SMOOTH 1u
696#define SUBDIV_COARSE_FACE_FLAG_SELECT 2u
697#define SUBDIV_COARSE_FACE_FLAG_ACTIVE 4u
698#define SUBDIV_COARSE_FACE_FLAG_HIDDEN 8u
699
700#define SUBDIV_COARSE_FACE_FLAG_OFFSET 28u
701
702#define SUBDIV_COARSE_FACE_FLAG_SMOOTH_MASK \
703 (SUBDIV_COARSE_FACE_FLAG_SMOOTH << SUBDIV_COARSE_FACE_FLAG_OFFSET)
704#define SUBDIV_COARSE_FACE_FLAG_SELECT_MASK \
705 (SUBDIV_COARSE_FACE_FLAG_SELECT << SUBDIV_COARSE_FACE_FLAG_OFFSET)
706#define SUBDIV_COARSE_FACE_FLAG_ACTIVE_MASK \
707 (SUBDIV_COARSE_FACE_FLAG_ACTIVE << SUBDIV_COARSE_FACE_FLAG_OFFSET)
708#define SUBDIV_COARSE_FACE_FLAG_HIDDEN_MASK \
709 (SUBDIV_COARSE_FACE_FLAG_HIDDEN << SUBDIV_COARSE_FACE_FLAG_OFFSET)
710
711#define SUBDIV_COARSE_FACE_LOOP_START_MASK \
712 ~((SUBDIV_COARSE_FACE_FLAG_SMOOTH | SUBDIV_COARSE_FACE_FLAG_SELECT | \
713 SUBDIV_COARSE_FACE_FLAG_ACTIVE | SUBDIV_COARSE_FACE_FLAG_HIDDEN) \
714 << SUBDIV_COARSE_FACE_FLAG_OFFSET)
715
717{
718 uint32_t flag = 0;
721 }
724 }
725 if (f == efa_act) {
727 }
728 return flag;
729}
730
732 BMFace *efa_act,
733 MutableSpan<uint32_t> flags_data)
734{
735 BMFace *f;
736 BMIter iter;
737
738 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
739 const int index = BM_elem_index_get(f);
743 }
744 const int loopstart = BM_elem_index_get(f->l_first);
745 flags_data[index] = uint(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
746 }
747}
748
750 const Mesh *mesh,
751 MutableSpan<uint32_t> flags_data)
752{
753 const OffsetIndices faces = mesh->faces();
754 for (const int i : faces.index_range()) {
755 uint32_t flag = 0;
757 (!mr.sharp_faces.is_empty() && mr.sharp_faces[i])))
758 {
760 }
761 if (!mr.select_poly.is_empty() && mr.select_poly[i]) {
763 }
764 if (!mr.hide_poly.is_empty() && mr.hide_poly[i]) {
766 }
767 flags_data[i] = uint(faces[i].start()) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
768 }
769}
770
772 BMesh *bm,
773 MeshRenderData &mr,
774 MutableSpan<uint32_t> flags_data)
775{
776 if (bm == nullptr) {
778 return;
779 }
780
781 const OffsetIndices faces = mesh->faces();
782 for (const int i : faces.index_range()) {
783 BMFace *f = bm_original_face_get(mr, i);
784 /* Selection and hiding from bmesh. */
786 /* Smooth from mesh. */
788 (!mr.sharp_faces.is_empty() && mr.sharp_faces[i])))
789 {
791 }
792 flags_data[i] = uint(faces[i].start()) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
793 }
794}
795
797 const Mesh *mesh,
798 MeshRenderData &mr)
799{
800 if (cache.extra_coarse_face_data == nullptr) {
802 static GPUVertFormat format;
803 if (format.attr_len == 0) {
805 }
808 mr.extract_type == MR_EXTRACT_BMESH ? cache.bm->totface :
809 mesh->faces_num);
810 }
811
813
814 if (mr.extract_type == MR_EXTRACT_BMESH) {
816 }
817 else if (mr.orig_index_face != nullptr) {
818 draw_subdiv_cache_extra_coarse_face_data_mapped(mesh, cache.bm, mr, flags_data);
819 }
820 else {
822 }
823
824 /* Make sure updated data is re-uploaded. */
826}
827
829{
830 DRWSubdivCache *subdiv_cache = mbc.subdiv_cache;
831 if (subdiv_cache == nullptr) {
832 subdiv_cache = MEM_new<DRWSubdivCache>(__func__);
833 }
834 mbc.subdiv_cache = subdiv_cache;
835 return *subdiv_cache;
836}
837
839 const Mesh *mesh)
840{
841 if (!(subdiv && subdiv->evaluator)) {
842 return;
843 }
844
845 const bool has_orco = CustomData_has_layer(&mesh->vert_data, CD_ORCO);
846 if (has_orco && !subdiv->evaluator->hasVertexData(subdiv->evaluator)) {
847 /* If we suddenly have/need original coordinates, recreate the evaluator if the extra
848 * source was not created yet. The refiner also has to be recreated as refinement for source
849 * and vertex data is done only once. */
851 subdiv->evaluator = nullptr;
852
853#ifdef WITH_OPENSUBDIV
854 delete subdiv->topology_refiner;
855 subdiv->topology_refiner = nullptr;
856#endif
857 }
858}
859
862/* -------------------------------------------------------------------- */
877
879
880 /* Pointers into #DRWSubdivCache buffers for easier access during traversal. */
888
889 /* Temporary buffers used during traversal. */
893
894 /* #CD_ORIGINDEX layers from the mesh to directly look up during traversal the original-index
895 * from the base mesh for edit data so that we do not have to handle yet another GPU buffer and
896 * do this in the shaders. */
897 const int *orig_index_vert;
898 const int *orig_index_edge;
899};
900
902 const int num_verts,
903 const int num_edges,
904 const int num_loops,
905 const int num_faces,
906 const int *subdiv_face_offset)
907{
908 /* num_loops does not take into account meshes with only loose geometry, which might be meshes
909 * used as custom bone shapes, so let's check the num_verts also. */
910 if (num_verts == 0 && num_loops == 0) {
911 return false;
912 }
913
914 DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
915 DRWSubdivCache *cache = ctx->cache;
916
917 /* Set topology information only if we have loops. */
918 if (num_loops != 0) {
919 cache->num_subdiv_edges = uint(num_edges);
920 cache->num_subdiv_loops = uint(num_loops);
921 cache->num_subdiv_verts = uint(num_verts);
922 cache->num_subdiv_quads = uint(num_faces);
923 cache->subdiv_face_offset = static_cast<int *>(MEM_dupallocN(subdiv_face_offset));
924 }
925
926 cache->may_have_loose_geom = num_verts != 0 || num_edges != 0;
927
928 /* Initialize cache buffers, prefer dynamic usage so we can reuse memory on the host even after
929 * it was sent to the device, since we may use the data while building other buffers on the CPU
930 * side.
931 *
932 * These VBOs are created even when there are no faces and only loose geometry. This avoids the
933 * need for many null checks. Binding them must be avoided if they are empty though. */
938
943
948
953
958
959 cache->subdiv_loop_subdiv_vert_index = static_cast<int *>(
960 MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_vert_index"));
961
962 cache->subdiv_loop_subdiv_edge_index = static_cast<int *>(
963 MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_edge_index"));
964
965 cache->subdiv_loop_face_index = static_cast<int *>(
966 MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_face_index"));
967
968 /* Initialize context pointers and temporary buffers. */
970 ctx->subdiv_loop_vert_index = cache->verts_orig_index->data<int>().data();
971 ctx->subdiv_loop_edge_index = cache->edges_orig_index->data<int>().data();
972 ctx->subdiv_loop_edge_draw_flag = cache->edges_draw_flag->data<int>().data();
976
977 ctx->orig_index_vert = static_cast<const int *>(
979
980 ctx->orig_index_edge = static_cast<const int *>(
982
983 if (cache->num_subdiv_verts) {
984 ctx->vert_origindex_map = static_cast<int *>(
985 MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map"));
986 for (int i = 0; i < num_verts; i++) {
987 ctx->vert_origindex_map[i] = -1;
988 }
989 }
990
991 if (cache->num_subdiv_edges) {
992 ctx->edge_origindex_map = static_cast<int *>(
993 MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map"));
994 for (int i = 0; i < num_edges; i++) {
995 ctx->edge_origindex_map[i] = -1;
996 }
997 ctx->edge_draw_flag_map = static_cast<int *>(
998 MEM_callocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_draw_flag_map"));
999 }
1000
1001 return true;
1002}
1003
1005 void * /*tls*/,
1006 const int /*ptex_face_index*/,
1007 const float /*u*/,
1008 const float /*v*/,
1009 const int coarse_vertex_index,
1010 const int /*coarse_face_index*/,
1011 const int /*coarse_corner*/,
1012 const int subdiv_vertex_index)
1013{
1014 BLI_assert(coarse_vertex_index != ORIGINDEX_NONE);
1015 DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
1016 ctx->vert_origindex_map[subdiv_vertex_index] = coarse_vertex_index;
1017}
1018
1019static void draw_subdiv_vertex_edge_cb(const bke::subdiv::ForeachContext * /*foreach_context*/,
1020 void * /*tls_v*/,
1021 const int /*ptex_face_index*/,
1022 const float /*u*/,
1023 const float /*v*/,
1024 const int /*coarse_edge_index*/,
1025 const int /*coarse_face_index*/,
1026 const int /*coarse_corner*/,
1027 const int /*subdiv_vertex_index*/)
1028{
1029 /* Required if bke::subdiv::ForeachContext.vertex_corner is also set. */
1030}
1031
1032static void draw_subdiv_edge_cb(const bke::subdiv::ForeachContext *foreach_context,
1033 void * /*tls*/,
1034 const int coarse_edge_index,
1035 const int subdiv_edge_index,
1036 const bool /*is_loose*/,
1037 const int /*subdiv_v1*/,
1038 const int /*subdiv_v2*/)
1039{
1040 DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
1041
1042 if (!ctx->edge_origindex_map) {
1043 return;
1044 }
1045
1046 if (coarse_edge_index == ORIGINDEX_NONE) {
1047 /* Not mapped to edge in the subdivision base mesh. */
1048 ctx->edge_origindex_map[subdiv_edge_index] = ORIGINDEX_NONE;
1049 if (!ctx->cache->optimal_display) {
1050 ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
1051 }
1052 }
1053 else {
1054 if (ctx->orig_index_edge) {
1055 const int origindex = ctx->orig_index_edge[coarse_edge_index];
1056 ctx->edge_origindex_map[subdiv_edge_index] = origindex;
1057 if (!(origindex == ORIGINDEX_NONE && ctx->cache->hide_unmapped_edges)) {
1058 /* Not mapped to edge in original mesh (generated by a preceding modifier). */
1059 ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
1060 }
1061 }
1062 else {
1063 ctx->edge_origindex_map[subdiv_edge_index] = coarse_edge_index;
1064 ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
1065 }
1066 }
1067}
1068
1069static void draw_subdiv_loop_cb(const bke::subdiv::ForeachContext *foreach_context,
1070 void * /*tls_v*/,
1071 const int ptex_face_index,
1072 const float u,
1073 const float v,
1074 const int /*coarse_loop_index*/,
1075 const int coarse_face_index,
1076 const int /*coarse_corner*/,
1077 const int subdiv_loop_index,
1078 const int subdiv_vertex_index,
1079 const int subdiv_edge_index)
1080{
1081 DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
1082 ctx->patch_coords[subdiv_loop_index] = make_patch_coord(ptex_face_index, u, v);
1083
1084 int coarse_vertex_index = ctx->vert_origindex_map[subdiv_vertex_index];
1085
1086 ctx->subdiv_loop_subdiv_vert_index[subdiv_loop_index] = subdiv_vertex_index;
1087 ctx->subdiv_loop_subdiv_edge_index[subdiv_loop_index] = subdiv_edge_index;
1088 ctx->subdiv_loop_face_index[subdiv_loop_index] = coarse_face_index;
1089 ctx->subdiv_loop_vert_index[subdiv_loop_index] = coarse_vertex_index;
1090}
1091
1093{
1094 memset(foreach_context, 0, sizeof(*foreach_context));
1096 foreach_context->loop = draw_subdiv_loop_cb;
1097 foreach_context->edge = draw_subdiv_edge_cb;
1099 foreach_context->vertex_edge = draw_subdiv_vertex_edge_cb;
1100}
1101
1102static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context,
1103 bke::subdiv::Subdiv *subdiv)
1104{
1105 bke::subdiv::ForeachContext foreach_context;
1106 draw_subdiv_foreach_callbacks(&foreach_context);
1107 foreach_context.user_data = cache_building_context;
1108
1110 &foreach_context,
1111 cache_building_context->settings,
1112 cache_building_context->coarse_mesh);
1113
1114 /* Now that traversal is done, we can set up the right original indices for the
1115 * subdiv-loop-to-coarse-edge map.
1116 */
1117 for (int i = 0; i < cache_building_context->cache->num_subdiv_loops; i++) {
1118 const int edge_index = cache_building_context->subdiv_loop_subdiv_edge_index[i];
1119 cache_building_context->subdiv_loop_edge_index[i] =
1120 cache_building_context->edge_origindex_map[edge_index];
1121 cache_building_context->subdiv_loop_edge_draw_flag[i] =
1122 cache_building_context->edge_draw_flag_map[edge_index];
1123 }
1124}
1125
1133
1134/* Build maps to hold enough information to tell which face is adjacent to which vertex; those will
1135 * be used for computing normals if limit surfaces are unavailable. */
1137{
1138 /* +1 so that we do not require a special case for the last vertex, this extra offset will
1139 * contain the total number of adjacent faces. */
1142
1143 MutableSpan<int> vertex_offsets = cache.subdiv_vertex_face_adjacency_offsets->data<int>();
1144 vertex_offsets.fill(0);
1145
1147 {cache.subdiv_loop_subdiv_vert_index, cache.num_subdiv_loops}, vertex_offsets);
1148
1150 cache.num_subdiv_loops);
1151 MutableSpan<int> adjacent_faces = cache.subdiv_vertex_face_adjacency->data<int>();
1152 int *tmp_set_faces = static_cast<int *>(
1153 MEM_callocN(sizeof(int) * cache.num_subdiv_verts, "tmp subdiv vertex offset"));
1154
1155 for (int i = 0; i < cache.num_subdiv_loops / 4; i++) {
1156 for (int j = 0; j < 4; j++) {
1157 const int subdiv_vertex = cache.subdiv_loop_subdiv_vert_index[i * 4 + j];
1158 int first_face_offset = vertex_offsets[subdiv_vertex] + tmp_set_faces[subdiv_vertex];
1159 adjacent_faces[first_face_offset] = i;
1160 tmp_set_faces[subdiv_vertex] += 1;
1161 }
1162 }
1163
1164 MEM_freeN(tmp_set_faces);
1165}
1166
1168 bke::subdiv::Subdiv *subdiv,
1169 const Mesh *mesh_eval,
1170 const SubsurfRuntimeData *runtime_data)
1171{
1172 bke::subdiv::ToMeshSettings to_mesh_settings;
1173 to_mesh_settings.resolution = runtime_data->resolution;
1174 to_mesh_settings.use_optimal_display = false;
1175
1176 if (cache.resolution != to_mesh_settings.resolution) {
1177 /* Resolution changed, we need to rebuild, free any existing cached data. */
1179 }
1180
1181 /* If the resolution between the cache and the settings match for some reason, check if the patch
1182 * coordinates were not already generated. Those coordinates are specific to the resolution, so
1183 * they should be null either after initialization, or after freeing if the resolution (or some
1184 * other subdivision setting) changed.
1185 */
1186 if (cache.patch_coords != nullptr) {
1187 return true;
1188 }
1189
1190 DRWCacheBuildingContext cache_building_context;
1191 memset(&cache_building_context, 0, sizeof(DRWCacheBuildingContext));
1192 cache_building_context.coarse_mesh = mesh_eval;
1193 cache_building_context.settings = &to_mesh_settings;
1194 cache_building_context.cache = &cache;
1195
1196 do_subdiv_traversal(&cache_building_context, subdiv);
1197 if (cache.num_subdiv_loops == 0 && cache.num_subdiv_verts == 0 && !cache.may_have_loose_geom) {
1198 /* Either the traversal failed, or we have an empty mesh, either way we cannot go any further.
1199 * The subdiv_face_offset cannot then be reliably stored in the cache, so free it directly.
1200 */
1202 return false;
1203 }
1204
1205 /* Only build face related data if we have polygons. */
1206 const OffsetIndices faces = mesh_eval->faces();
1207 if (cache.num_subdiv_loops != 0) {
1208 /* Build buffers for the PatchMap. */
1209 draw_patch_map_build(&cache.gpu_patch_map, subdiv);
1210
1212
1213 /* Build patch coordinates for all the face dots. */
1215 mesh_eval->faces_num);
1216 CompressedPatchCoord *blender_fdots_patch_coords =
1218 for (int i = 0; i < mesh_eval->faces_num; i++) {
1219 const int ptex_face_index = cache.face_ptex_offset[i];
1220 if (faces[i].size() == 4) {
1221 /* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */
1222 blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f);
1223 }
1224 else {
1225 /* For N-gons, since they are split into quads from the center, and since the center is
1226 * chosen to be the top right corner of each quad, the center coordinate of the coarse face
1227 * is any one of those top right corners with `u = v = 1.0`. */
1228 blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f);
1229 }
1230 }
1231
1233 faces.size());
1234
1236 faces.size() + 1);
1237
1239 }
1240
1241 cache.resolution = to_mesh_settings.resolution;
1242 cache.num_coarse_faces = faces.size();
1243
1244 /* To avoid floating point precision issues when evaluating patches at patch boundaries,
1245 * ensure that all loops sharing a vertex use the same patch coordinate. This could cause
1246 * the mesh to not be watertight, leading to shadowing artifacts (see #97877). */
1247 Vector<int> first_loop_index(cache.num_subdiv_verts, -1);
1248
1249 /* Save coordinates for corners, as attributes may vary for each loop connected to the same
1250 * vertex. */
1251 if (cache.num_subdiv_loops > 0) {
1252 memcpy(cache.corner_patch_coords->data<CompressedPatchCoord>().data(),
1253 cache_building_context.patch_coords,
1254 sizeof(CompressedPatchCoord) * cache.num_subdiv_loops);
1255
1256 for (int i = 0; i < cache.num_subdiv_loops; i++) {
1257 const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i];
1258 if (first_loop_index[vertex] != -1) {
1259 continue;
1260 }
1261 first_loop_index[vertex] = i;
1262 }
1263
1264 for (int i = 0; i < cache.num_subdiv_loops; i++) {
1265 const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i];
1266 cache_building_context.patch_coords[i] =
1267 cache_building_context.patch_coords[first_loop_index[vertex]];
1268 }
1269 }
1270
1271 /* Cleanup. */
1272 MEM_SAFE_FREE(cache_building_context.vert_origindex_map);
1273 MEM_SAFE_FREE(cache_building_context.edge_origindex_map);
1274 MEM_SAFE_FREE(cache_building_context.edge_draw_flag_map);
1275
1276 return true;
1277}
1278
1281/* -------------------------------------------------------------------- */
1288 /* Offsets in the buffers data where the source and destination data start. */
1291
1292 /* Parameters for the DRWPatchMap. */
1297
1298 /* Coarse topology information. */
1301
1302 /* Refined topology information. */
1304
1305 /* The sculpt mask data layer may be null. */
1307
1308 /* Masks for the extra coarse face data. */
1314
1315 /* Number of elements to process in the compute shader (can be the coarse quad count, or the
1316 * final vertex count, depending on which compute pass we do). This is used to early out in case
1317 * of out of bond accesses as compute dispatch are of fixed size. */
1319
1324};
1325
1326static_assert((sizeof(DRWSubdivUboStorage) % 16) == 0,
1327 "DRWSubdivUboStorage is not padded to a multiple of the size of vec4");
1328
1331 const int src_offset,
1332 const int dst_offset,
1333 const uint total_dispatch_size,
1334 const bool has_sculpt_mask,
1335 const uint edge_loose_offset)
1336{
1337 ubo->src_offset = src_offset;
1338 ubo->dst_offset = dst_offset;
1341 ubo->max_depth = cache.gpu_patch_map.max_depth;
1345 ubo->edge_loose_offset = edge_loose_offset;
1346 ubo->has_sculpt_mask = has_sculpt_mask;
1352 ubo->total_dispatch_size = total_dispatch_size;
1353 ubo->is_edit_mode = cache.is_edit_mode;
1354 ubo->use_hide = cache.use_hide;
1355}
1356
1358 GPUShader *shader,
1359 const int src_offset,
1360 const int dst_offset,
1361 const uint total_dispatch_size,
1362 const bool has_sculpt_mask = false,
1363 const uint edge_loose_offset = 0)
1364{
1365 DRWSubdivUboStorage storage;
1367 &storage,
1368 src_offset,
1369 dst_offset,
1370 total_dispatch_size,
1371 has_sculpt_mask,
1372 edge_loose_offset);
1373
1374 if (!cache.ubo) {
1375 const_cast<DRWSubdivCache *>(&cache)->ubo = GPU_uniformbuf_create_ex(
1376 sizeof(DRWSubdivUboStorage), &storage, "DRWSubdivUboStorage");
1377 }
1378
1379 GPU_uniformbuf_update(cache.ubo, &storage);
1380
1381 const int binding = GPU_shader_get_ubo_binding(shader, "shader_data");
1382 GPU_uniformbuf_bind(cache.ubo, binding);
1383}
1384
1387// --------------------------------------------------------
1388
1389#define SUBDIV_LOCAL_WORK_GROUP_SIZE 64
1391{
1393}
1394
1401 GPUShader *shader,
1402 const int src_offset,
1403 const int dst_offset,
1404 uint total_dispatch_size,
1405 const bool has_sculpt_mask = false,
1406 const uint edge_loose_offset = 0)
1407{
1408 const uint max_res_x = uint(GPU_max_work_group_count(0));
1409
1410 const uint dispatch_size = get_dispatch_size(total_dispatch_size);
1411 uint dispatch_rx = dispatch_size;
1412 uint dispatch_ry = 1u;
1413 if (dispatch_rx > max_res_x) {
1414 /* Since there are some limitations with regards to the maximum work group size (could be as
1415 * low as 64k elements per call), we split the number elements into a "2d" number, with the
1416 * final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum
1417 * work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements
1418 * total, which should be enough. If not, we could also use the 3rd dimension. */
1419 /* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and
1420 * get the smallest rect fitting the requirements. */
1421 dispatch_rx = dispatch_ry = ceilf(sqrtf(dispatch_size));
1422 /* Avoid a completely empty dispatch line caused by rounding. */
1423 if ((dispatch_rx * (dispatch_ry - 1)) >= dispatch_size) {
1424 dispatch_ry -= 1;
1425 }
1426 }
1427
1428 /* X and Y dimensions may have different limits so the above computation may not be right, but
1429 * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore,
1430 * we presume it all fits. */
1431 BLI_assert(dispatch_ry < uint(GPU_max_work_group_count(1)));
1432
1434 shader,
1435 src_offset,
1436 dst_offset,
1437 total_dispatch_size,
1438 has_sculpt_mask,
1439 edge_loose_offset);
1440
1441 GPU_compute_dispatch(shader, dispatch_rx, dispatch_ry, 1);
1442}
1443
1445 gpu::VertBuf *flags_buffer,
1446 gpu::VertBuf *pos_nor,
1447 gpu::VertBuf *orco)
1448{
1450 /* Happens on meshes with only loose geometry. */
1451 return;
1452 }
1453
1454 bke::subdiv::Subdiv *subdiv = cache.subdiv;
1455 OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
1456
1457 OpenSubdiv_Buffer src_buffer_interface;
1458 gpu::VertBuf *src_buffer = create_buffer_and_interface(&src_buffer_interface,
1460 evaluator->wrapSrcBuffer(evaluator, &src_buffer_interface);
1461
1462 gpu::VertBuf *src_extra_buffer = nullptr;
1463 if (orco) {
1464 OpenSubdiv_Buffer src_extra_buffer_interface;
1465 src_extra_buffer = create_buffer_and_interface(&src_extra_buffer_interface,
1467 evaluator->wrapSrcVertexDataBuffer(evaluator, &src_extra_buffer_interface);
1468 }
1469
1470 OpenSubdiv_Buffer patch_arrays_buffer_interface;
1471 gpu::VertBuf *patch_arrays_buffer = create_buffer_and_interface(&patch_arrays_buffer_interface,
1473 evaluator->fillPatchArraysBuffer(evaluator, &patch_arrays_buffer_interface);
1474
1475 OpenSubdiv_Buffer patch_index_buffer_interface;
1476 gpu::VertBuf *patch_index_buffer = create_buffer_and_interface(&patch_index_buffer_interface,
1478 evaluator->wrapPatchIndexBuffer(evaluator, &patch_index_buffer_interface);
1479
1480 OpenSubdiv_Buffer patch_param_buffer_interface;
1481 gpu::VertBuf *patch_param_buffer = create_buffer_and_interface(&patch_param_buffer_interface,
1483 evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
1484
1487 GPU_shader_bind(shader);
1488
1489 int binding_point = 0;
1490 GPU_vertbuf_bind_as_ssbo(src_buffer, binding_point++);
1493 GPU_vertbuf_bind_as_ssbo(cache.patch_coords, binding_point++);
1494 GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, binding_point++);
1495 GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, binding_point++);
1496 GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
1497 GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
1498 if (flags_buffer) {
1499 GPU_vertbuf_bind_as_ssbo(flags_buffer, binding_point);
1500 }
1501 binding_point++;
1502 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1503 if (orco) {
1504 GPU_vertbuf_bind_as_ssbo(src_extra_buffer, binding_point++);
1505 GPU_vertbuf_bind_as_ssbo(orco, binding_point++);
1506 }
1507 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1508
1509 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1510
1511 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
1512 * We also need it for subsequent compute shaders, so a barrier on the shader storage is also
1513 * needed. */
1515
1516 /* Cleanup. */
1518
1519 GPU_vertbuf_discard(patch_index_buffer);
1520 GPU_vertbuf_discard(patch_param_buffer);
1521 GPU_vertbuf_discard(patch_arrays_buffer);
1522 GPU_vertbuf_discard(src_buffer);
1523 GPU_VERTBUF_DISCARD_SAFE(src_extra_buffer);
1524}
1525
1527 gpu::VertBuf *uvs,
1528 const int face_varying_channel,
1529 const int dst_offset)
1530{
1532 /* Happens on meshes with only loose geometry. */
1533 return;
1534 }
1535
1536 bke::subdiv::Subdiv *subdiv = cache.subdiv;
1537 OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
1538
1539 OpenSubdiv_Buffer src_buffer_interface;
1540 gpu::VertBuf *src_buffer = create_buffer_and_interface(&src_buffer_interface, get_uvs_format());
1541 evaluator->wrapFVarSrcBuffer(evaluator, face_varying_channel, &src_buffer_interface);
1542
1543 OpenSubdiv_Buffer patch_arrays_buffer_interface;
1544 gpu::VertBuf *patch_arrays_buffer = create_buffer_and_interface(&patch_arrays_buffer_interface,
1546 evaluator->fillFVarPatchArraysBuffer(
1547 evaluator, face_varying_channel, &patch_arrays_buffer_interface);
1548
1549 OpenSubdiv_Buffer patch_index_buffer_interface;
1550 gpu::VertBuf *patch_index_buffer = create_buffer_and_interface(&patch_index_buffer_interface,
1552 evaluator->wrapFVarPatchIndexBuffer(
1553 evaluator, face_varying_channel, &patch_index_buffer_interface);
1554
1555 OpenSubdiv_Buffer patch_param_buffer_interface;
1556 gpu::VertBuf *patch_param_buffer = create_buffer_and_interface(&patch_param_buffer_interface,
1558 evaluator->wrapFVarPatchParamBuffer(
1559 evaluator, face_varying_channel, &patch_param_buffer_interface);
1560
1562 GPU_shader_bind(shader);
1563
1564 int binding_point = 0;
1565 GPU_vertbuf_bind_as_ssbo(src_buffer, binding_point++);
1568 GPU_vertbuf_bind_as_ssbo(cache.corner_patch_coords, binding_point++);
1569 GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, binding_point++);
1570 GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, binding_point++);
1571 GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
1572 GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
1573 GPU_vertbuf_bind_as_ssbo(uvs, binding_point++);
1574 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1575
1576 /* The buffer offset has the stride baked in (which is 2 as we have UVs) so remove the stride by
1577 * dividing by 2 */
1578 const int src_offset = src_buffer_interface.buffer_offset / 2;
1579 drw_subdiv_compute_dispatch(cache, shader, src_offset, dst_offset, cache.num_subdiv_quads);
1580
1581 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
1582 * Since it may also be used for computing UV stretches, we also need a barrier on the shader
1583 * storage. */
1585
1586 /* Cleanup. */
1588
1589 GPU_vertbuf_discard(patch_index_buffer);
1590 GPU_vertbuf_discard(patch_param_buffer);
1591 GPU_vertbuf_discard(patch_arrays_buffer);
1592 GPU_vertbuf_discard(src_buffer);
1593}
1594
1596 gpu::VertBuf &src_data,
1597 gpu::VertBuf &dst_data,
1598 int comp_type, /*GPUVertCompType*/
1599 int dimensions,
1600 int dst_offset)
1601{
1603 /* Happens on meshes with only loose geometry. */
1604 return;
1605 }
1606
1607 GPUShader *shader = get_subdiv_custom_data_shader(comp_type, dimensions);
1608 GPU_shader_bind(shader);
1609
1610 int binding_point = 0;
1611 /* subdiv_face_offset is always at binding point 0 for each shader using it. */
1613 GPU_vertbuf_bind_as_ssbo(&src_data, binding_point++);
1614 GPU_vertbuf_bind_as_ssbo(cache.face_ptex_offset_buffer, binding_point++);
1615 GPU_vertbuf_bind_as_ssbo(cache.corner_patch_coords, binding_point++);
1616 GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data, binding_point++);
1617 GPU_vertbuf_bind_as_ssbo(&dst_data, binding_point++);
1618 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1619
1620 drw_subdiv_compute_dispatch(cache, shader, 0, dst_offset, cache.num_subdiv_quads);
1621
1622 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. Put
1623 * a barrier on the shader storage as we may use the result in another compute shader. */
1625
1626 /* Cleanup. */
1628}
1629
1631 gpu::VertBuf *mask_vbo,
1632 gpu::VertBuf *face_set_vbo,
1633 gpu::VertBuf *sculpt_data)
1634{
1636 GPU_shader_bind(shader);
1637
1638 /* Mask VBO is always at binding point 0. */
1639 if (mask_vbo) {
1640 GPU_vertbuf_bind_as_ssbo(mask_vbo, 0);
1641 }
1642
1643 int binding_point = 1;
1644 GPU_vertbuf_bind_as_ssbo(face_set_vbo, binding_point++);
1645 GPU_vertbuf_bind_as_ssbo(sculpt_data, binding_point++);
1646 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1647
1648 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads, mask_vbo != nullptr);
1649
1650 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
1652
1653 /* Cleanup. */
1655}
1656
1658 gpu::VertBuf *pos_nor,
1659 gpu::VertBuf *face_adjacency_offsets,
1660 gpu::VertBuf *face_adjacency_lists,
1661 gpu::VertBuf *vertex_loop_map,
1662 gpu::VertBuf *vert_normals)
1663{
1665 GPU_shader_bind(shader);
1666
1667 int binding_point = 0;
1668
1669 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1670 GPU_vertbuf_bind_as_ssbo(face_adjacency_offsets, binding_point++);
1671 GPU_vertbuf_bind_as_ssbo(face_adjacency_lists, binding_point++);
1672 GPU_vertbuf_bind_as_ssbo(vertex_loop_map, binding_point++);
1673 GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
1674 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1675
1676 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_verts);
1677
1678 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
1679 * We also need it for subsequent compute shaders, so a barrier on the shader storage is also
1680 * needed. */
1682
1683 /* Cleanup. */
1685}
1686
1688 gpu::VertBuf *vert_normals,
1689 gpu::VertBuf *subdiv_loop_subdiv_vert_index,
1690 gpu::VertBuf *pos_nor)
1691{
1693 GPU_shader_bind(shader);
1694
1695 int binding_point = 0;
1696 GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
1697 GPU_vertbuf_bind_as_ssbo(subdiv_loop_subdiv_vert_index, binding_point++);
1698 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1699 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1700
1701 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1702
1703 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
1704 * We also need it for subsequent compute shaders, so a barrier on the shader storage is also
1705 * needed. */
1707
1708 /* Cleanup. */
1710}
1711
1713 gpu::VertBuf *src_custom_normals,
1714 gpu::VertBuf *pos_nor)
1715{
1717 GPU_shader_bind(shader);
1718
1719 int binding_point = 0;
1720 GPU_vertbuf_bind_as_ssbo(src_custom_normals, binding_point++);
1721 /* outputPosNor is bound at index 2 in the base shader. */
1722 binding_point = 2;
1723 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1724 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1725
1726 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1727
1728 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
1729 * We also need it for subsequent compute shaders, so a barrier on the shader storage is also
1730 * needed. */
1732
1733 /* Cleanup. */
1735}
1736
1738 gpu::IndexBuf *subdiv_tris,
1739 const int material_count)
1740{
1742 /* Happens on meshes with only loose geometry. */
1743 return;
1744 }
1745
1746 const bool do_single_material = material_count <= 1;
1747
1748 GPUShader *shader = get_subdiv_shader(
1750 GPU_shader_bind(shader);
1751
1752 int binding_point = 0;
1753
1754 /* subdiv_face_offset is always at binding point 0 for each shader using it. */
1756 GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data, binding_point++);
1757
1758 /* Outputs */
1759 GPU_indexbuf_bind_as_ssbo(subdiv_tris, binding_point++);
1760
1761 if (!do_single_material) {
1762 GPU_vertbuf_bind_as_ssbo(cache.face_mat_offset, binding_point++);
1763 }
1764
1765 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1766
1767 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1768
1769 /* This generates an index buffer, so we need to put a barrier on the element array. */
1771
1772 /* Cleanup. */
1774}
1775
1777 gpu::VertBuf *fdots_pos,
1778 gpu::VertBuf *fdots_nor,
1779 gpu::IndexBuf *fdots_indices)
1780{
1782 /* Happens on meshes with only loose geometry. */
1783 return;
1784 }
1785
1786 bke::subdiv::Subdiv *subdiv = cache.subdiv;
1787 OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
1788
1789 OpenSubdiv_Buffer src_buffer_interface;
1790 gpu::VertBuf *src_buffer = create_buffer_and_interface(&src_buffer_interface,
1792 evaluator->wrapSrcBuffer(evaluator, &src_buffer_interface);
1793
1794 OpenSubdiv_Buffer patch_arrays_buffer_interface;
1795 gpu::VertBuf *patch_arrays_buffer = create_buffer_and_interface(&patch_arrays_buffer_interface,
1797 opensubdiv_gpu_buffer_init(&patch_arrays_buffer_interface, patch_arrays_buffer);
1798 evaluator->fillPatchArraysBuffer(evaluator, &patch_arrays_buffer_interface);
1799
1800 OpenSubdiv_Buffer patch_index_buffer_interface;
1801 gpu::VertBuf *patch_index_buffer = create_buffer_and_interface(&patch_index_buffer_interface,
1803 evaluator->wrapPatchIndexBuffer(evaluator, &patch_index_buffer_interface);
1804
1805 OpenSubdiv_Buffer patch_param_buffer_interface;
1806 gpu::VertBuf *patch_param_buffer = create_buffer_and_interface(&patch_param_buffer_interface,
1808 evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
1809
1813 GPU_shader_bind(shader);
1814
1815 int binding_point = 0;
1816 GPU_vertbuf_bind_as_ssbo(src_buffer, binding_point++);
1819 GPU_vertbuf_bind_as_ssbo(cache.fdots_patch_coords, binding_point++);
1820 GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, binding_point++);
1821 GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, binding_point++);
1822 GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
1823 GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
1824 GPU_vertbuf_bind_as_ssbo(fdots_pos, binding_point++);
1825 /* F-dots normals may not be requested, still reserve the binding point. */
1826 if (fdots_nor) {
1827 GPU_vertbuf_bind_as_ssbo(fdots_nor, binding_point);
1828 }
1829 binding_point++;
1830 GPU_indexbuf_bind_as_ssbo(fdots_indices, binding_point++);
1831 GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data, binding_point++);
1832 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1833
1834 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_coarse_faces);
1835
1836 /* This generates two vertex buffers and an index buffer, so we need to put a barrier on the
1837 * vertex attributes and element arrays. */
1839
1840 /* Cleanup. */
1842
1843 GPU_vertbuf_discard(patch_index_buffer);
1844 GPU_vertbuf_discard(patch_param_buffer);
1845 GPU_vertbuf_discard(patch_arrays_buffer);
1846 GPU_vertbuf_discard(src_buffer);
1847}
1848
1850{
1852 GPU_shader_bind(shader);
1853
1854 int binding_point = 0;
1856 GPU_vertbuf_bind_as_ssbo(cache.edges_draw_flag, binding_point++);
1857 GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data, binding_point++);
1858 GPU_indexbuf_bind_as_ssbo(lines_indices, binding_point++);
1859 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1860
1861 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1862
1863 /* This generates an index buffer, so we need to put a barrier on the element array. */
1865
1866 /* Cleanup. */
1868}
1869
1871 gpu::IndexBuf *lines_indices,
1872 gpu::VertBuf *lines_flags,
1873 uint edge_loose_offset,
1874 uint num_loose_edges)
1875{
1877 GPU_shader_bind(shader);
1878
1879 GPU_indexbuf_bind_as_ssbo(lines_indices, 3);
1880 GPU_vertbuf_bind_as_ssbo(lines_flags, 4);
1881
1882 drw_subdiv_compute_dispatch(cache, shader, 0, 0, num_loose_edges, false, edge_loose_offset);
1883
1884 /* This generates an index buffer, so we need to put a barrier on the element array. */
1886
1887 /* Cleanup. */
1889}
1890
1892 gpu::VertBuf *pos_nor,
1893 gpu::VertBuf *edge_draw_flag,
1894 gpu::VertBuf *poly_other_map,
1895 gpu::VertBuf *edge_fac)
1896{
1898 GPU_shader_bind(shader);
1899
1900 int binding_point = 0;
1901 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1902 GPU_vertbuf_bind_as_ssbo(edge_draw_flag, binding_point++);
1903 GPU_vertbuf_bind_as_ssbo(poly_other_map, binding_point++);
1904 GPU_vertbuf_bind_as_ssbo(edge_fac, binding_point++);
1905 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1906
1907 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1908
1909 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
1911
1912 /* Cleanup. */
1914}
1915
1917 gpu::VertBuf *pos_nor,
1918 gpu::VertBuf *lnor)
1919{
1921 /* Happens on meshes with only loose geometry. */
1922 return;
1923 }
1924
1926 GPU_shader_bind(shader);
1927
1928 int binding_point = 0;
1929 /* Inputs */
1930 /* subdiv_face_offset is always at binding point 0 for each shader using it. */
1932 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1933 GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data, binding_point++);
1934 GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, binding_point++);
1935
1936 /* Outputs */
1937 GPU_vertbuf_bind_as_ssbo(lnor, binding_point++);
1938 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1939
1940 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1941
1942 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
1944
1945 /* Cleanup. */
1947}
1948
1950 gpu::VertBuf *coarse_data,
1951 gpu::VertBuf *subdiv_data)
1952{
1954 GPU_shader_bind(shader);
1955
1956 int binding_point = 0;
1957 /* Inputs */
1958 /* subdiv_face_offset is always at binding point 0 for each shader using it. */
1960 GPU_vertbuf_bind_as_ssbo(coarse_data, binding_point++);
1961
1962 /* Outputs */
1963 GPU_vertbuf_bind_as_ssbo(subdiv_data, binding_point++);
1964 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1965
1966 drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
1967
1968 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
1970
1971 /* Cleanup. */
1973}
1974
1976 gpu::VertBuf *pos_nor,
1977 gpu::VertBuf *uvs,
1978 int uvs_offset,
1979 gpu::VertBuf *stretch_angles)
1980{
1982 GPU_shader_bind(shader);
1983
1984 int binding_point = 0;
1985 /* Inputs */
1986 GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
1987 GPU_vertbuf_bind_as_ssbo(uvs, binding_point++);
1988
1989 /* Outputs */
1990 GPU_vertbuf_bind_as_ssbo(stretch_angles, binding_point++);
1991 BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
1992
1993 drw_subdiv_compute_dispatch(cache, shader, uvs_offset, 0, cache.num_subdiv_quads);
1994
1995 /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
1997
1998 /* Cleanup. */
2000}
2001
2002/* -------------------------------------------------------------------- */
2003
2038 const Mesh *mesh_eval,
2039 uint mat_len)
2040{
2042
2043 const int number_of_quads = cache.num_subdiv_loops / 4;
2044
2045 if (mat_len == 1) {
2046 cache.mat_start = static_cast<int *>(MEM_callocN(sizeof(int), "subdiv mat_end"));
2047 cache.mat_end = static_cast<int *>(MEM_callocN(sizeof(int), "subdiv mat_end"));
2048 cache.mat_start[0] = 0;
2049 cache.mat_end[0] = number_of_quads;
2050 return;
2051 }
2052
2053 const bke::AttributeAccessor attributes = mesh_eval->attributes();
2054 const VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
2055 "material_index", bke::AttrDomain::Face, 0);
2056
2057 /* Count number of subdivided polygons for each material. */
2058 int *mat_start = static_cast<int *>(MEM_callocN(sizeof(int) * mat_len, "subdiv mat_start"));
2059 int *subdiv_face_offset = cache.subdiv_face_offset;
2060
2061 /* TODO: parallel_reduce? */
2062 for (int i = 0; i < mesh_eval->faces_num; i++) {
2063 const int next_offset = (i == mesh_eval->faces_num - 1) ? number_of_quads :
2064 subdiv_face_offset[i + 1];
2065 const int quad_count = next_offset - subdiv_face_offset[i];
2066 const int mat_index = material_indices[i];
2067 mat_start[mat_index] += quad_count;
2068 }
2069
2070 /* Accumulate offsets. */
2071 int ofs = mat_start[0];
2072 mat_start[0] = 0;
2073 for (uint i = 1; i < mat_len; i++) {
2074 int tmp = mat_start[i];
2075 mat_start[i] = ofs;
2076 ofs += tmp;
2077 }
2078
2079 /* Compute per face offsets. */
2080 int *mat_end = static_cast<int *>(MEM_dupallocN(mat_start));
2081 int *per_face_mat_offset = static_cast<int *>(
2082 MEM_mallocN(sizeof(int) * mesh_eval->faces_num, "per_face_mat_offset"));
2083
2084 for (int i = 0; i < mesh_eval->faces_num; i++) {
2085 const int mat_index = material_indices[i];
2086 const int single_material_index = subdiv_face_offset[i];
2087 const int material_offset = mat_end[mat_index];
2088 const int next_offset = (i == mesh_eval->faces_num - 1) ? number_of_quads :
2089 subdiv_face_offset[i + 1];
2090 const int quad_count = next_offset - subdiv_face_offset[i];
2091 mat_end[mat_index] += quad_count;
2092
2093 per_face_mat_offset[i] = material_offset - single_material_index;
2094 }
2095
2096 cache.face_mat_offset = draw_subdiv_build_origindex_buffer(per_face_mat_offset,
2097 mesh_eval->faces_num);
2098 cache.mat_start = mat_start;
2099 cache.mat_end = mat_end;
2100
2101 MEM_freeN(per_face_mat_offset);
2102}
2103
2105 Mesh &mesh,
2106 MeshBatchCache &batch_cache,
2107 MeshBufferCache &mbc,
2108 const bool is_editmode,
2109 const bool is_paint_mode,
2110 const bool edit_mode_active,
2111 const float4x4 &object_to_world,
2112 const bool do_final,
2113 const bool do_uvedit,
2114 const bool do_cage,
2115 const ToolSettings *ts,
2116 const bool use_hide,
2117 OpenSubdiv_EvaluatorCache *evaluator_cache)
2118{
2119 SubsurfRuntimeData *runtime_data = mesh.runtime->subsurf_runtime_data;
2120 BLI_assert(runtime_data && runtime_data->has_gpu_subdiv);
2121
2122 if (runtime_data->settings.level == 0) {
2123 return false;
2124 }
2125
2126 const Mesh *mesh_eval = &mesh;
2127 BMesh *bm = nullptr;
2128 if (mesh.runtime->edit_mesh) {
2129 mesh_eval = BKE_object_get_editmesh_eval_final(&ob);
2130 bm = mesh.runtime->edit_mesh->bm;
2131 }
2132
2133 draw_subdiv_invalidate_evaluator_for_orco(runtime_data->subdiv_gpu, mesh_eval);
2134
2136 runtime_data, mesh_eval, true);
2137 if (!subdiv) {
2138 return false;
2139 }
2140
2142 subdiv, mesh_eval, {}, bke::subdiv::SUBDIV_EVALUATOR_TYPE_GPU, evaluator_cache))
2143 {
2144 /* This could happen in two situations:
2145 * - OpenSubdiv is disabled.
2146 * - Something totally bad happened, and OpenSubdiv rejected our
2147 * topology.
2148 * In either way, we can't safely continue. However, we still have to handle potential loose
2149 * geometry, which is done separately. */
2150 if (mesh_eval->faces_num) {
2151 return false;
2152 }
2153 }
2154
2155 DRWSubdivCache &draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache);
2156
2157 draw_cache.optimal_display = runtime_data->use_optimal_display;
2158 /* If there is no distinct cage, hide unmapped edges that can't be selected. */
2159 draw_cache.hide_unmapped_edges = is_editmode && !do_cage;
2160 draw_cache.bm = bm;
2161 draw_cache.mesh = mesh_eval;
2162 draw_cache.subdiv = subdiv;
2163
2164 if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, runtime_data)) {
2165 return false;
2166 }
2167
2169
2170 /* Copy topology information for stats display. */
2171 runtime_data->stats_totvert = draw_cache.num_subdiv_verts;
2172 runtime_data->stats_totedge = draw_cache.num_subdiv_edges;
2173 runtime_data->stats_faces_num = draw_cache.num_subdiv_quads;
2174 runtime_data->stats_totloop = draw_cache.num_subdiv_loops;
2175
2176 draw_cache.use_custom_loop_normals = (runtime_data->use_loop_normals) &&
2179
2180 if (DRW_ibo_requested(mbc.buff.ibo.tris)) {
2181 draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache.mat_len);
2182 }
2183
2184 std::unique_ptr<MeshRenderData> mr = mesh_render_data_create(ob,
2185 mesh,
2186 is_editmode,
2187 is_paint_mode,
2188 edit_mode_active,
2189 object_to_world,
2190 do_final,
2191 do_uvedit,
2192 use_hide,
2193 ts);
2194 draw_cache.use_hide = use_hide;
2195
2196 /* Used for setting loop normals flags. Mapped extraction is only used during edit mode.
2197 * See comments in #extract_lnor_iter_face_mesh.
2198 */
2199 draw_cache.is_edit_mode = mr->edit_bmesh != nullptr;
2200
2201 draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval, *mr);
2202
2203 mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, *mr);
2204
2205 return true;
2206}
2207
2209{
2210 const Span<int> loose_edges = cache.loose_geom.edges;
2211 if (loose_edges.is_empty()) {
2212 return;
2213 }
2214
2215 if (!subdiv_cache.loose_edge_positions.is_empty()) {
2216 /* Already processed. */
2217 return;
2218 }
2219
2220 const Mesh *coarse_mesh = subdiv_cache.mesh;
2221 const bool is_simple = subdiv_cache.subdiv->settings.is_simple;
2222 const int resolution = subdiv_cache.resolution;
2223 const int resolution_1 = resolution - 1;
2224 const float inv_resolution_1 = 1.0f / float(resolution_1);
2225
2226 const Span<float3> coarse_positions = coarse_mesh->vert_positions();
2227 const Span<int2> coarse_edges = coarse_mesh->edges();
2228
2229 Array<int> vert_to_edge_offsets;
2230 Array<int> vert_to_edge_indices;
2231 const GroupedSpan<int> vert_to_edge_map = bke::mesh::build_vert_to_edge_map(
2232 coarse_edges, coarse_mesh->verts_num, vert_to_edge_offsets, vert_to_edge_indices);
2233
2234 /* Also store the last vertex to simplify copying the positions to the VBO. */
2235 subdiv_cache.loose_edge_positions.reinitialize(loose_edges.size() * resolution);
2236 MutableSpan<float3> edge_positions = subdiv_cache.loose_edge_positions;
2237
2238 threading::parallel_for(loose_edges.index_range(), 1024, [&](const IndexRange range) {
2239 for (const int i : range) {
2240 const int coarse_edge = loose_edges[i];
2241 MutableSpan positions = edge_positions.slice(i * resolution, resolution);
2242 for (const int j : positions.index_range()) {
2243 positions[j] = bke::subdiv::mesh_interpolate_position_on_edge(coarse_positions,
2244 coarse_edges,
2245 vert_to_edge_map,
2246 coarse_edge,
2247 is_simple,
2248 j * inv_resolution_1);
2249 }
2250 }
2251 });
2252}
2253
2255
2257 Mesh &mesh,
2258 MeshBatchCache &batch_cache,
2259 MeshBufferCache &mbc,
2260 const bool is_editmode,
2261 const bool is_paint_mode,
2262 const bool edit_mode_active,
2263 const float4x4 &object_to_world,
2264 const bool do_final,
2265 const bool do_uvedit,
2266 const bool do_cage,
2267 const ToolSettings *ts,
2268 const bool use_hide)
2269{
2270 if (g_evaluator_cache == nullptr) {
2272 }
2273
2274#undef TIME_SUBDIV
2275
2276#ifdef TIME_SUBDIV
2277 const double begin_time = BLI_time_now_seconds();
2278#endif
2279
2281 mesh,
2282 batch_cache,
2283 mbc,
2284 is_editmode,
2285 is_paint_mode,
2286 edit_mode_active,
2287 object_to_world,
2288 do_final,
2289 do_uvedit,
2290 do_cage,
2291 ts,
2292 use_hide,
2294 {
2295 return;
2296 }
2297
2298#ifdef TIME_SUBDIV
2299 const double end_time = BLI_time_now_seconds();
2300 fprintf(stderr, "Time to update subdivision: %f\n", end_time - begin_time);
2301 fprintf(stderr, "Maximum FPS: %f\n", 1.0 / (end_time - begin_time));
2302#endif
2303}
2304
2306{
2307 for (int i = 0; i < NUM_SHADERS; ++i) {
2309 }
2310
2312
2313 if (g_evaluator_cache) {
2315 g_evaluator_cache = nullptr;
2316 }
2317}
2318
2321
2328
2330{
2331 if (gpu_subdiv_free_queue == nullptr) {
2332 return;
2333 }
2334
2336
2337 while (gpu_subdiv_free_queue != nullptr) {
2338 bke::subdiv::Subdiv *subdiv = static_cast<bke::subdiv::Subdiv *>(
2340 /* Set the type to CPU so that we do actually free the cache. */
2342 bke::subdiv::free(subdiv);
2343 }
2344
2346}
2347
2348} // namespace blender::draw
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
#define ORIGINDEX_NONE
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
#define MAX_GPU_SUBDIV_SSBOS
blender::bke::subdiv::Subdiv * BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, bool for_draw_code)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE uint divide_ceil_u(uint a, uint b)
#define MINLINE
#define BLI_string_joinN(...)
unsigned int uint
#define BLI_MUTEX_INITIALIZER
Definition BLI_threads.h:84
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define ELEM(...)
@ CD_CUSTOMLOOPNORMAL
Object is a sort of wrapper for general info.
bool GPU_crappy_amd_driver()
int GPU_max_work_group_count(int index)
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len)
void GPU_indexbuf_bind_as_ssbo(blender::gpu::IndexBuf *elem, int binding)
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_free(GPUShader *shader)
GPUShader * GPU_shader_create_compute(const char *computecode, const char *libcode, const char *defines, const char *shname)
void GPU_shader_unbind()
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:374
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
@ GPU_BARRIER_ELEMENT_ARRAY
Definition GPU_state.hh:52
@ GPU_BARRIER_VERTEX_ATTRIB_ARRAY
Definition GPU_state.hh:50
GPUUniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
void GPU_vertbuf_use(blender::gpu::VertBuf *)
void GPU_vertbuf_tag_dirty(blender::gpu::VertBuf *verts)
void GPU_vertbuf_wrap_handle(blender::gpu::VertBuf *verts, uint64_t handle)
#define GPU_vertbuf_init_with_format(verts, format)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
blender::gpu::VertBuf * GPU_vertbuf_calloc()
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertbuf_bind_as_ssbo(blender::gpu::VertBuf *verts, int binding)
void GPU_vertbuf_update_sub(blender::gpu::VertBuf *verts, uint start, uint len, const void *data)
void GPU_vertbuf_init_with_format_ex(blender::gpu::VertBuf &verts, const GPUVertFormat &format, GPUUsageType)
void GPU_vertbuf_discard(blender::gpu::VertBuf *)
@ GPU_USAGE_STATIC
@ GPU_USAGE_DYNAMIC
@ GPU_USAGE_DEVICE_ONLY
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias)
@ GPU_COMP_U16
@ GPU_COMP_MAX
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U32
#define MEM_SAFE_FREE(v)
struct GPUShader GPUShader
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
@ BM_ELEM_SMOOTH
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
AttributeSet attributes
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
bool is_empty() const
Definition BLI_array.hh:253
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr bool is_empty() const
Definition BLI_span.hh:261
MutableSpan< T > data()
#define ceilf(x)
#define sqrtf(x)
#define SUBDIV_COARSE_FACE_FLAG_HIDDEN
char datatoc_common_subdiv_patch_evaluation_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_HIDDEN_MASK
char datatoc_common_subdiv_lib_glsl[]
char datatoc_common_subdiv_ibo_lines_comp_glsl[]
char datatoc_common_subdiv_ibo_tris_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_ACTIVE_MASK
char datatoc_common_subdiv_vbo_sculpt_data_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_OFFSET
char datatoc_common_subdiv_normals_finalize_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_SMOOTH_MASK
#define SUBDIV_COARSE_FACE_FLAG_SMOOTH
char datatoc_common_subdiv_vbo_lnor_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_ACTIVE
#define SUBDIV_COARSE_FACE_FLAG_SELECT_MASK
char datatoc_common_subdiv_custom_data_interp_comp_glsl[]
char datatoc_common_subdiv_vbo_edituv_strech_area_comp_glsl[]
#define SUBDIV_LOCAL_WORK_GROUP_SIZE
char datatoc_common_subdiv_normals_accumulate_comp_glsl[]
char datatoc_common_subdiv_vbo_edge_fac_comp_glsl[]
#define SHADER_CUSTOM_DATA_INTERP_MAX_DIMENSIONS
char datatoc_common_subdiv_vbo_edituv_strech_angle_comp_glsl[]
#define SUBDIV_COARSE_FACE_FLAG_SELECT
#define SUBDIV_COARSE_FACE_LOOP_START_MASK
bool DRW_ibo_requested(blender::gpu::IndexBuf *ibo)
int len
draw_view in_light_buf[] float
void openSubdiv_deleteEvaluatorCache(OpenSubdiv_EvaluatorCache *evaluator_cache)
const char * openSubdiv_getGLSLPatchBasisSource(void)
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator)
OpenSubdiv_EvaluatorCache * openSubdiv_createEvaluatorCache(eOpenSubdivEvaluator evaluator_type)
Extraction of Mesh data into VBO to feed to GPU.
static float verts[][3]
format
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
bool foreach_subdiv_geometry(Subdiv *subdiv, const ForeachContext *context, const ToMeshSettings *mesh_settings, const Mesh *coarse_mesh)
bool eval_begin_from_mesh(Subdiv *subdiv, const Mesh *mesh, Span< float3 > coarse_vert_positions, eSubdivEvaluatorType evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache)
int * face_ptex_offset_get(Subdiv *subdiv)
Definition subdiv.cc:219
static void opensubdiv_gpu_buffer_init(OpenSubdiv_Buffer *buffer_interface, gpu::VertBuf *vertbuf)
BLI_INLINE BMFace * bm_original_face_get(const MeshRenderData &mr, int idx)
static void draw_subdiv_init_ubo_storage(const DRWSubdivCache &cache, DRWSubdivUboStorage *ubo, const int src_offset, const int dst_offset, const uint total_dispatch_size, const bool has_sculpt_mask, const uint edge_loose_offset)
static void draw_subdiv_cache_free_material_data(DRWSubdivCache &cache)
static void draw_subdiv_free_edit_mode_cache(DRWSubdivCache &cache)
static void draw_subdiv_vertex_edge_cb(const bke::subdiv::ForeachContext *, void *, const int, const float, const float, const int, const int, const int, const int)
static bool draw_subdiv_create_requested_buffers(Object &ob, Mesh &mesh, MeshBatchCache &batch_cache, MeshBufferCache &mbc, const bool is_editmode, const bool is_paint_mode, const bool edit_mode_active, const float4x4 &object_to_world, const bool do_final, const bool do_uvedit, const bool do_cage, const ToolSettings *ts, const bool use_hide, OpenSubdiv_EvaluatorCache *evaluator_cache)
static const GPUVertFormat & get_patch_array_format()
void draw_subdiv_build_edge_fac_buffer(const DRWSubdivCache &cache, gpu::VertBuf *pos_nor, gpu::VertBuf *edge_draw_flag, gpu::VertBuf *poly_other_map, gpu::VertBuf *edge_fac)
static bool draw_subdiv_cache_need_face_data(const DRWSubdivCache &cache)
void draw_subdiv_extract_uvs(const DRWSubdivCache &cache, gpu::VertBuf *uvs, const int face_varying_channel, const int dst_offset)
static void vertbuf_update_data(const OpenSubdiv_Buffer *interface, uint start, uint len, const void *data)
static GPUShader * get_subdiv_shader(int shader_type)
static const char * get_shader_code(int shader_type)
void draw_subdiv_build_edituv_stretch_area_buffer(const DRWSubdivCache &cache, gpu::VertBuf *coarse_data, gpu::VertBuf *subdiv_data)
static void vertbuf_device_alloc(const OpenSubdiv_Buffer *interface, const uint len)
static void draw_patch_map_free(DRWPatchMap *gpu_patch_map)
static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache &cache, const Mesh *mesh_eval, uint mat_len)
void draw_subdiv_build_fdots_buffers(const DRWSubdivCache &cache, gpu::VertBuf *fdots_pos, gpu::VertBuf *fdots_nor, gpu::IndexBuf *fdots_indices)
static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context, bke::subdiv::Subdiv *subdiv)
void DRW_subdivide_loose_geom(DRWSubdivCache &subdiv_cache, const MeshBufferCache &cache)
void DRW_create_subdivision(Object &ob, Mesh &mesh, MeshBatchCache &batch_cache, MeshBufferCache &mbc, const bool is_editmode, const bool is_paint_mode, const bool edit_mode_active, const float4x4 &object_to_world, const bool do_final, const bool do_uvedit, const bool do_cage, const ToolSettings *ts, const bool use_hide)
void draw_subdiv_cache_free(DRWSubdivCache &cache)
static GPUShader * get_subdiv_custom_data_shader(int comp_type, int dimensions)
static GPUShader * g_subdiv_custom_data_shaders[SHADER_CUSTOM_DATA_INTERP_MAX_DIMENSIONS][GPU_COMP_MAX]
static const char * get_shader_name(int shader_type)
void draw_subdiv_build_tris_buffer(const DRWSubdivCache &cache, gpu::IndexBuf *subdiv_tris, const int material_count)
static void draw_subdiv_foreach_callbacks(bke::subdiv::ForeachContext *foreach_context)
static void draw_subdiv_edge_cb(const bke::subdiv::ForeachContext *foreach_context, void *, const int coarse_edge_index, const int subdiv_edge_index, const bool, const int, const int)
static ThreadMutex gpu_subdiv_queue_mutex
static LinkNode * gpu_subdiv_free_queue
void DRW_subdiv_cache_free(bke::subdiv::Subdiv *subdiv)
void draw_subdiv_accumulate_normals(const DRWSubdivCache &cache, gpu::VertBuf *pos_nor, gpu::VertBuf *face_adjacency_offsets, gpu::VertBuf *face_adjacency_lists, gpu::VertBuf *vertex_loop_map, gpu::VertBuf *vert_normals)
void draw_subdiv_build_lines_buffer(const DRWSubdivCache &cache, gpu::IndexBuf *lines_indices)
static uint get_dispatch_size(uint elements)
static void * vertbuf_alloc(const OpenSubdiv_Buffer *interface, const uint len)
static GPUShader * g_subdiv_shaders[NUM_SHADERS]
void draw_subdiv_build_lnor_buffer(const DRWSubdivCache &cache, gpu::VertBuf *pos_nor, gpu::VertBuf *lnor)
void draw_subdiv_extract_pos_nor(const DRWSubdivCache &cache, gpu::VertBuf *flags_buffer, gpu::VertBuf *pos_nor, gpu::VertBuf *orco)
static void draw_subdiv_vertex_corner_cb(const bke::subdiv::ForeachContext *foreach_context, void *, const int, const float, const float, const int coarse_vertex_index, const int, const int, const int subdiv_vertex_index)
static void drw_subdiv_compute_dispatch(const DRWSubdivCache &cache, GPUShader *shader, const int src_offset, const int dst_offset, uint total_dispatch_size, const bool has_sculpt_mask=false, const uint edge_loose_offset=0)
static DRWSubdivCache & mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache &mbc)
void draw_subdiv_build_lines_loose_buffer(const DRWSubdivCache &cache, gpu::IndexBuf *lines_indices, gpu::VertBuf *lines_flags, uint edge_loose_offset, uint num_loose_edges)
static uint32_t compute_coarse_face_flag_bm(BMFace *f, BMFace *efa_act)
static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData &mr, const Mesh *mesh, MutableSpan< uint32_t > flags_data)
static const GPUVertFormat & get_blender_patch_coords_format()
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, MeshBufferCache &mbc, DRWSubdivCache &subdiv_cache, MeshRenderData &mr)
static void vertbuf_bind_gpu(const OpenSubdiv_Buffer *buffer)
static uint tris_count_from_number_of_loops(const uint number_of_loops)
void draw_subdiv_build_sculpt_data_buffer(const DRWSubdivCache &cache, gpu::VertBuf *mask_vbo, gpu::VertBuf *face_set_vbo, gpu::VertBuf *sculpt_data)
std::unique_ptr< MeshRenderData > mesh_render_data_create(Object &object, Mesh &mesh, const bool is_editmode, const bool is_paint_mode, const bool edit_mode_active, const float4x4 &object_to_world, const bool do_final, const bool do_uvedit, const bool use_hide, const ToolSettings *ts)
void draw_subdiv_interp_custom_data(const DRWSubdivCache &cache, gpu::VertBuf &src_data, gpu::VertBuf &dst_data, int comp_type, int dimensions, int dst_offset)
static const GPUVertFormat & get_uvs_format()
void draw_subdiv_finalize_normals(const DRWSubdivCache &cache, gpu::VertBuf *vert_normals, gpu::VertBuf *subdiv_loop_subdiv_vert_index, gpu::VertBuf *pos_nor)
static void draw_patch_map_build(DRWPatchMap *gpu_patch_map, bke::subdiv::Subdiv *subdiv)
static void draw_subdiv_invalidate_evaluator_for_orco(bke::subdiv::Subdiv *subdiv, const Mesh *mesh)
gpu::VertBuf * draw_subdiv_build_origindex_buffer(int *vert_origindex, uint num_loops)
static void draw_subdiv_cache_extra_coarse_face_data_mapped(const Mesh *mesh, BMesh *bm, MeshRenderData &mr, MutableSpan< uint32_t > flags_data)
static void vertbuf_wrap_device_handle(const OpenSubdiv_Buffer *interface, uint64_t handle)
static gpu::VertBuf * create_buffer_and_interface(OpenSubdiv_Buffer *interface, const GPUVertFormat &format)
static gpu::VertBuf * gpu_vertbuf_create_from_format(const GPUVertFormat &format, uint len)
static const GPUVertFormat & get_quadtree_format()
static GPUShader * get_patch_evaluation_shader(int shader_type)
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache &cache, const Mesh *mesh, MeshRenderData &mr)
static const GPUVertFormat & get_subdiv_vertex_format()
static bool draw_subdiv_build_cache(DRWSubdivCache &cache, bke::subdiv::Subdiv *subdiv, const Mesh *mesh_eval, const SubsurfRuntimeData *runtime_data)
static void build_vertex_face_adjacency_maps(DRWSubdivCache &cache)
static const GPUVertFormat & get_patch_index_format()
static const GPUVertFormat & get_origindex_format()
MINLINE CompressedPatchCoord make_patch_coord(int ptex_face_index, float u, float v)
static const GPUVertFormat & get_patch_param_format()
static const GPUVertFormat & get_patch_handle_format()
const GPUVertFormat & draw_subdiv_get_pos_nor_format()
static void draw_subdiv_loop_cb(const bke::subdiv::ForeachContext *foreach_context, void *, const int ptex_face_index, const float u, const float v, const int, const int coarse_face_index, const int, const int subdiv_loop_index, const int subdiv_vertex_index, const int subdiv_edge_index)
void draw_subdiv_init_origindex_buffer(gpu::VertBuf &buffer, int32_t *vert_origindex, uint num_loops, uint loose_len)
static void draw_subdiv_ubo_update_and_bind(const DRWSubdivCache &cache, GPUShader *shader, const int src_offset, const int dst_offset, const uint total_dispatch_size, const bool has_sculpt_mask=false, const uint edge_loose_offset=0)
void draw_subdiv_finalize_custom_normals(const DRWSubdivCache &cache, gpu::VertBuf *src_custom_normals, gpu::VertBuf *pos_nor)
static bool draw_subdiv_topology_info_cb(const bke::subdiv::ForeachContext *foreach_context, const int num_verts, const int num_edges, const int num_loops, const int num_faces, const int *subdiv_face_offset)
void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache &cache, gpu::VertBuf *pos_nor, gpu::VertBuf *uvs, int uvs_offset, gpu::VertBuf *stretch_angles)
static OpenSubdiv_EvaluatorCache * g_evaluator_cache
static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm, BMFace *efa_act, MutableSpan< uint32_t > flags_data)
void build_reverse_offsets(Span< int > indices, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
@ OPENSUBDIV_EVALUATOR_GPU
@ OPENSUBDIV_EVALUATOR_CPU
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned __int64 uint64_t
Definition stdint.h:90
BMLoop * l_first
int totface
CustomData edge_data
CustomData corner_data
CustomData vert_data
int faces_num
int verts_num
void(* device_update)(const OpenSubdiv_Buffer *buffer, unsigned int start, unsigned int len, const void *data)
void(* bind_gpu)(const OpenSubdiv_Buffer *buffer)
void(* wrap_device_handle)(const OpenSubdiv_Buffer *buffer, uint64_t device_ptr)
void(* device_alloc)(const OpenSubdiv_Buffer *buffer, const unsigned int size)
void *(* alloc)(const OpenSubdiv_Buffer *buffer, const unsigned int size)
void(* wrapFVarPatchIndexBuffer)(OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, OpenSubdiv_Buffer *patch_index_buffer)
void(* wrapPatchIndexBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *patch_index_buffer)
void(* wrapFVarSrcBuffer)(OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, OpenSubdiv_Buffer *src_buffer)
void(* fillPatchArraysBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *patch_array_buffer)
bool(* hasVertexData)(OpenSubdiv_Evaluator *evaluator)
void(* getPatchMap)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *patch_map_handles, OpenSubdiv_Buffer *patch_map_quadtree, int *min_patch_face, int *max_patch_face, int *max_depth, int *patches_are_triangular)
void(* wrapSrcVertexDataBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *src_buffer)
void(* wrapPatchParamBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *patch_param_buffer)
void(* wrapFVarPatchParamBuffer)(OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, OpenSubdiv_Buffer *patch_param_buffer)
void(* wrapSrcBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *src_buffer)
void(* fillFVarPatchArraysBuffer)(OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, OpenSubdiv_Buffer *patch_array_buffer)
blender::bke::subdiv::Settings settings
blender::bke::subdiv::Subdiv * subdiv_gpu
ForeachTopologyInformationCb topology_info
OpenSubdiv_Evaluator * evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner
const bke::subdiv::ToMeshSettings * settings
gpu::VertBuf * subdiv_vertex_face_adjacency_offsets
struct blender::draw::MeshBufferList::@248 ibo
VArraySpan< bool > sharp_faces
VArraySpan< bool > select_poly
bke::MeshNormalDomain normals_domain
uint8_t flag
Definition wm_window.cc:138