diff options
-rw-r--r-- | source/blender/blenkernel/intern/mesh_runtime.c | 10 | ||||
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract.h | 23 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.cc | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 352 | ||||
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc | 398 | ||||
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc | 64 | ||||
-rw-r--r-- | source/blender/gpu/GPU_batch.h | 8 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_mesh_types.h | 4 |
10 files changed, 123 insertions, 741 deletions
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 1c8646a4bdd..7ac4c29f0ee 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -52,8 +52,6 @@ void BKE_mesh_runtime_reset(Mesh *mesh) memset(&mesh->runtime, 0, sizeof(mesh->runtime)); mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex"); BLI_mutex_init(mesh->runtime.eval_mutex); - mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex"); - BLI_mutex_init(mesh->runtime.render_mutex); } /* Clear all pointers which we don't want to be shared on copying the datablock. @@ -73,9 +71,6 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag)) mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex"); BLI_mutex_init(mesh->runtime.eval_mutex); - - mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex"); - BLI_mutex_init(mesh->runtime.render_mutex); } void BKE_mesh_runtime_clear_cache(Mesh *mesh) @@ -85,11 +80,6 @@ void BKE_mesh_runtime_clear_cache(Mesh *mesh) MEM_freeN(mesh->runtime.eval_mutex); mesh->runtime.eval_mutex = NULL; } - if (mesh->runtime.render_mutex != NULL) { - BLI_mutex_end(mesh->runtime.render_mutex); - MEM_freeN(mesh->runtime.render_mutex); - mesh->runtime.render_mutex = NULL; - } if (mesh->runtime.mesh_eval != NULL) { mesh->runtime.mesh_eval->edit_mesh = NULL; BKE_id_free(NULL, mesh->runtime.mesh_eval); diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 0baf994d978..baf83234354 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -61,7 +61,6 @@ set(SRC intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc intern/mesh_extractors/extract_mesh_ibo_points.cc intern/mesh_extractors/extract_mesh_ibo_tris.cc - intern/mesh_extractors/extract_mesh_vbo_attributes.cc intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc intern/mesh_extractors/extract_mesh_vbo_edit_data.cc intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index ba42cdf66e7..a680cc0d6b7 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -24,10 +24,6 @@ struct TaskGraph; -#include "DNA_customdata_types.h" - -#include "BKE_attribute.h" - #include "GPU_batch.h" #include "GPU_index_buffer.h" #include "GPU_vertex_buffer.h" @@ -60,6 +56,7 @@ typedef struct DRW_MeshCDMask { uint32_t uv : 8; uint32_t tan : 8; uint32_t vcol : 8; + uint32_t sculpt_vcol : 8; uint32_t orco : 1; uint32_t tan_orco : 1; uint32_t sculpt_overlays : 1; @@ -67,10 +64,10 @@ typedef struct DRW_MeshCDMask { * modifiers could remove it. (see T68857) */ uint32_t edit_uv : 1; } DRW_MeshCDMask; -/* Keep `DRW_MeshCDMask` struct within an `uint32_t`. +/* Keep `DRW_MeshCDMask` struct within an `uint64_t`. * bit-wise and atomic operations are used to compare and update the struct. * See `mesh_cd_layers_type_*` functions. */ -BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask exceeds 32 bits") +BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint64_t), "DRW_MeshCDMask exceeds 64 bits") typedef enum eMRIterType { MR_ITER_LOOPTRI = 1 << 0, MR_ITER_POLY = 1 << 1, @@ -79,17 +76,6 @@ typedef enum eMRIterType { } eMRIterType; ENUM_OPERATORS(eMRIterType, MR_ITER_LVERT) -typedef struct DRW_AttributeRequest { - CustomDataType cd_type; - int layer_index; - AttributeDomain domain; -} DRW_AttributeRequest; - -typedef struct DRW_MeshAttributes { - DRW_AttributeRequest requests[GPU_MAX_ATTR]; - int num_requests; -} DRW_MeshAttributes; - typedef enum eMRDataType { MR_DATA_NONE = 0, MR_DATA_POLY_NOR = 1 << 1, @@ -147,7 +133,6 @@ typedef struct MeshBufferList { GPUVertBuf *edge_idx; /* extend */ GPUVertBuf *poly_idx; GPUVertBuf *fdot_idx; - GPUVertBuf *attr[GPU_MAX_ATTR]; } vbo; /* Index Buffers: * Only need to be updated when topology changes. */ @@ -300,8 +285,6 @@ typedef struct MeshBatchCache { DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time; - DRW_MeshAttributes attr_used, attr_needed, attr_used_over_time; - int lastmatch; /* Valid only if edge_detection is up to date. */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index f3b72503907..06c449fe590 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -650,9 +650,6 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, EXTRACT_ADD_REQUESTED(vbo, vert_idx); EXTRACT_ADD_REQUESTED(vbo, fdot_idx); EXTRACT_ADD_REQUESTED(vbo, skin_roots); - for (int i = 0; i < GPU_MAX_ATTR; i++) { - EXTRACT_ADD_REQUESTED(vbo, attr[i]); - } EXTRACT_ADD_REQUESTED(ibo, tris); if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) { diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 847913927f7..18664498d00 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -41,7 +41,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_attribute.h" #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" @@ -122,8 +121,6 @@ # define _MDEPS_ASSERT6(b, n1, n2, n3, n4, n5) _MDEPS_ASSERT5(b, n1, n2, n3, n4); _MDEPS_ASSERT2(b, n5) # define _MDEPS_ASSERT7(b, n1, n2, n3, n4, n5, n6) _MDEPS_ASSERT6(b, n1, n2, n3, n4, n5); _MDEPS_ASSERT2(b, n6) # define _MDEPS_ASSERT8(b, n1, n2, n3, n4, n5, n6, n7) _MDEPS_ASSERT7(b, n1, n2, n3, n4, n5, n6); _MDEPS_ASSERT2(b, n7) -# define _MDEPS_ASSERT21(b, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20) _MDEPS_ASSERT8(b, n1, n2, n3, n4, n5, n6, n7); _MDEPS_ASSERT8(b, n8, n9, n10, n11, n12, n13, n14); _MDEPS_ASSERT7(b, n15, n16, n17, n18, n19, n20) -# define _MDEPS_ASSERT22(b, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21) _MDEPS_ASSERT21(b, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20); _MDEPS_ASSERT2(b, n21); # define MDEPS_ASSERT_FLAG(...) VA_NARGS_CALL_OVERLOAD(_MDEPS_ASSERT, __VA_ARGS__) # define MDEPS_ASSERT(batch_name, ...) MDEPS_ASSERT_FLAG(BATCH_FLAG(batch_name), __VA_ARGS__) @@ -195,21 +192,6 @@ static const DRWBatchFlag g_buffer_deps[] = { [BUFFER_INDEX(vbo.edge_idx)] = BATCH_FLAG(edit_selection_edges), [BUFFER_INDEX(vbo.poly_idx)] = BATCH_FLAG(edit_selection_faces), [BUFFER_INDEX(vbo.fdot_idx)] = BATCH_FLAG(edit_selection_fdots), - [BUFFER_INDEX(vbo.attr[0])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[1])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[2])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[3])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[4])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[5])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[6])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[7])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[8])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[9])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[10])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[11])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[12])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[13])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, - [BUFFER_INDEX(vbo.attr[14])] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG, [BUFFER_INDEX(ibo.tris)] = BATCH_FLAG(surface, surface_weights, @@ -258,12 +240,12 @@ static void mesh_batch_cache_discard_batch(MeshBatchCache *cache, const DRWBatch /* Return true is all layers in _b_ are inside _a_. */ BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b); + return (*((uint64_t *)&a) & *((uint64_t *)&b)) == *((uint64_t *)&b); } BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return *((uint32_t *)&a) == *((uint32_t *)&b); + return *((uint64_t *)&a) == *((uint64_t *)&b); } BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) @@ -271,11 +253,12 @@ BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) uint32_t *a_p = (uint32_t *)a; uint32_t *b_p = (uint32_t *)&b; atomic_fetch_and_or_uint32(a_p, *b_p); + atomic_fetch_and_or_uint32(a_p + 1, *(b_p + 1)); } BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a) { - *((uint32_t *)a) = 0; + *((uint64_t *)a) = 0; } BLI_INLINE const Mesh *editmesh_final_or_this(const Mesh *me) @@ -288,95 +271,6 @@ static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *c cd_used->edit_uv = 1; } -/** \name DRW_MeshAttributes - * - * Utilities for handling requested attributes. - * \{ */ - -/* Return true if the given DRW_AttributeRequest is already in the requests. */ -static bool has_request(const DRW_MeshAttributes *requests, DRW_AttributeRequest req) -{ - for (int i = 0; i < requests->num_requests; i++) { - const DRW_AttributeRequest src_req = requests->requests[i]; - if (src_req.domain != req.domain) { - continue; - } - if (src_req.layer_index != req.layer_index) { - continue; - } - if (src_req.cd_type != req.cd_type) { - continue; - } - return true; - } - return false; -} - -static void mesh_attrs_merge_requests(const DRW_MeshAttributes *src_requests, - DRW_MeshAttributes *dst_requests) -{ - for (int i = 0; i < src_requests->num_requests; i++) { - if (dst_requests->num_requests == GPU_MAX_ATTR) { - return; - } - - if (has_request(dst_requests, src_requests->requests[i])) { - continue; - } - - dst_requests->requests[dst_requests->num_requests] = src_requests->requests[i]; - dst_requests->num_requests += 1; - } -} - -static void drw_mesh_attributes_clear(DRW_MeshAttributes *attributes) -{ - memset(attributes, 0, sizeof(DRW_MeshAttributes)); -} - -static void drw_mesh_attributes_merge(DRW_MeshAttributes *dst, - const DRW_MeshAttributes *src, - ThreadMutex *mesh_render_mutex) -{ - BLI_mutex_lock(mesh_render_mutex); - mesh_attrs_merge_requests(src, dst); - BLI_mutex_unlock(mesh_render_mutex); -} - -/* Return true if all requests in b are in a. */ -static bool drw_mesh_attributes_overlap(DRW_MeshAttributes *a, DRW_MeshAttributes *b) -{ - if (a->num_requests != b->num_requests) { - return false; - } - - for (int i = 0; i < a->num_requests; i++) { - if (!has_request(a, b->requests[i])) { - return false; - } - } - - return true; -} - -static void drw_mesh_attributes_add_request(DRW_MeshAttributes *attrs, - CustomDataType type, - int layer, - AttributeDomain domain) -{ - if (attrs->num_requests >= GPU_MAX_ATTR) { - return; - } - - DRW_AttributeRequest *req = &attrs->requests[attrs->num_requests]; - req->cd_type = type; - req->layer_index = layer; - req->domain = domain; - attrs->num_requests += 1; -} - -/** \} */ - BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) { switch ((eMeshWrapperType)me->runtime.wrapper_type) { @@ -392,36 +286,6 @@ BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) return &me->ldata; } -BLI_INLINE const CustomData *mesh_cd_pdata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_MDATA: - return &me->pdata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->pdata; - break; - } - - BLI_assert(0); - return &me->pdata; -} - -BLI_INLINE const CustomData *mesh_cd_edata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_MDATA: - return &me->edata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->edata; - break; - } - - BLI_assert(0); - return &me->edata; -} - BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) { switch ((eMeshWrapperType)me->runtime.wrapper_type) { @@ -457,14 +321,14 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd } } -static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshAttributes *attrs_used) +static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR); if (layer != -1) { - drw_mesh_attributes_add_request(attrs_used, CD_PROP_COLOR, layer, ATTR_DOMAIN_POINT); + cd_used->sculpt_vcol |= (1 << layer); } } @@ -479,45 +343,13 @@ static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *c } } -static bool custom_data_match_attribute(const CustomData *custom_data, - const char *name, - int *r_layer_index, - int *r_type) -{ - const int possible_attribute_types[6] = { - CD_PROP_BOOL, - CD_PROP_INT32, - CD_PROP_FLOAT, - CD_PROP_FLOAT2, - CD_PROP_FLOAT3, - CD_PROP_COLOR, - }; - - for (int i = 0; i < ARRAY_SIZE(possible_attribute_types); i++) { - const int attr_type = possible_attribute_types[i]; - int layer_index = CustomData_get_named_layer(custom_data, attr_type, name); - if (layer_index == -1) { - continue; - } - - *r_layer_index = layer_index; - *r_type = attr_type; - return true; - } - - return false; -} - static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, struct GPUMaterial **gpumat_array, - int gpumat_array_len, - DRW_MeshAttributes *attributes) + int gpumat_array_len) { const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); - const CustomData *cd_pdata = mesh_cd_pdata_get_from_mesh(me_final); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); - const CustomData *cd_edata = mesh_cd_edata_get_from_mesh(me_final); /* See: DM_vertex_attributes_from_gpu for similar logic */ DRW_MeshCDMask cd_used; @@ -531,8 +363,6 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, const char *name = gpu_attr->name; int type = gpu_attr->type; int layer = -1; - /* ATTR_DOMAIN_NUM is standard for "invalid value". */ - AttributeDomain domain = ATTR_DOMAIN_NUM; if (type == CD_AUTO_FROM_NAME) { /* We need to deduct what exact layer is used. @@ -544,6 +374,13 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, type = CD_MTFACE; if (layer == -1) { + if (U.experimental.use_sculpt_vertex_colors) { + layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); + type = CD_PROP_COLOR; + } + } + + if (layer == -1) { layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name); type = CD_MCOL; } @@ -555,27 +392,6 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, } #endif if (layer == -1) { - /* Try to match a generic attribute, we use the first attribute domain with a - * matching name. */ - if (custom_data_match_attribute(cd_vdata, name, &layer, &type)) { - domain = ATTR_DOMAIN_POINT; - } - else if (custom_data_match_attribute(cd_ldata, name, &layer, &type)) { - domain = ATTR_DOMAIN_CORNER; - } - else if (custom_data_match_attribute(cd_pdata, name, &layer, &type)) { - domain = ATTR_DOMAIN_FACE; - } - else if (custom_data_match_attribute(cd_edata, name, &layer, &type)) { - domain = ATTR_DOMAIN_EDGE; - } - else { - layer = -1; - domain = ATTR_DOMAIN_NUM; - } - } - - if (layer == -1) { continue; } } @@ -616,6 +432,31 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, } break; } + case CD_PROP_COLOR: { + /* Sculpt Vertex Colors */ + bool use_mloop_cols = false; + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name) : + CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR); + /* Fallback to Vertex Color data */ + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) : + CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL); + use_mloop_cols = true; + } + } + if (layer != -1) { + if (use_mloop_cols) { + cd_used.vcol |= (1 << layer); + } + else { + cd_used.sculpt_vcol |= (1 << layer); + } + } + break; + } case CD_MCOL: { /* Vertex Color Data */ if (layer == -1) { @@ -632,17 +473,6 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, cd_used.orco = 1; break; } - case CD_PROP_BOOL: - case CD_PROP_INT32: - case CD_PROP_FLOAT: - case CD_PROP_FLOAT2: - case CD_PROP_FLOAT3: - case CD_PROP_COLOR: { - if (layer != -1 && domain != ATTR_DOMAIN_NUM) { - drw_mesh_attributes_add_request(attributes, type, layer, domain); - } - break; - } } } } @@ -1105,14 +935,14 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me) static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me) { - DRW_MeshAttributes attrs_needed; - drw_mesh_attributes_clear(&attrs_needed); - mesh_cd_calc_active_vcol_layer(me, &attrs_needed); + DRW_MeshCDMask cd_needed; + mesh_cd_layers_type_clear(&cd_needed); + mesh_cd_calc_active_vcol_layer(me, &cd_needed); - BLI_assert(attrs_needed.num_requests != 0 && + BLI_assert(cd_needed.sculpt_vcol != 0 && "No MPropCol layer available in Sculpt, but batches requested anyway!"); - drw_mesh_attributes_merge(&cache->attr_needed, &attrs_needed, me->runtime.render_mutex); + mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me) @@ -1185,16 +1015,11 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, uint gpumat_array_len) { MeshBatchCache *cache = mesh_batch_cache_get(me); - DRW_MeshAttributes attrs_needed; - drw_mesh_attributes_clear(&attrs_needed); - DRW_MeshCDMask cd_needed = mesh_cd_calc_used_gpu_layers( - me, gpumat_array, gpumat_array_len, &attrs_needed); + DRW_MeshCDMask cd_needed = mesh_cd_calc_used_gpu_layers(me, gpumat_array, gpumat_array_len); BLI_assert(gpumat_array_len == cache->mat_len); mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); - ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex; - drw_mesh_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex); mesh_batch_cache_request_surface_batches(cache); return cache->surface_per_mat; } @@ -1471,25 +1296,11 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) cache->lastmatch = ctime; } - if (drw_mesh_attributes_overlap(&cache->attr_used_over_time, &cache->attr_used)) { - cache->lastmatch = ctime; - } - if (ctime - cache->lastmatch > U.vbotimeout) { mesh_batch_cache_discard_shaded_tri(cache); } mesh_cd_layers_type_clear(&cache->cd_used_over_time); - drw_mesh_attributes_clear(&cache->attr_used_over_time); -} - -static void drw_add_attributes_vbo(GPUBatch *batch, - MeshBufferList *mbuflist, - DRW_MeshAttributes *attr_used) -{ - for (int i = 0; i < attr_used->num_requests; i++) { - DRW_vbo_request(batch, &mbuflist->vbo.attr[i]); - } } #ifdef DEBUG @@ -1598,15 +1409,12 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, } } - ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex; - /* Verify that all surface batches have needed attribute layers. */ /* TODO(fclem): We could be a bit smarter here and only do it per * material. */ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed); - bool attr_overlap = drw_mesh_attributes_overlap(&cache->attr_used, &cache->attr_needed); - if (cd_overlap == false || attr_overlap == false) { + if (cd_overlap == false) { FOREACH_MESH_BUFFER_CACHE (cache, mbc) { if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv); @@ -1622,14 +1430,11 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.sculpt_overlays != cache->cd_needed.sculpt_overlays) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.sculpt_data); } - if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) { + if (((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) || + ((cache->cd_used.sculpt_vcol & cache->cd_needed.sculpt_vcol) != + cache->cd_needed.sculpt_vcol)) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.vcol); } - if (!drw_mesh_attributes_overlap(&cache->attr_used, &cache->attr_needed)) { - for (int i = 0; i < GPU_MAX_ATTR; i++) { - GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.attr[i]); - } - } } /* We can't discard batches at this point as they have been * referenced for drawing. Just clear them in place. */ @@ -1640,13 +1445,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, cache->batch_ready &= ~(MBC_SURFACE); mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); - drw_mesh_attributes_merge(&cache->attr_used, &cache->attr_needed, mesh_render_mutex); } mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); mesh_cd_layers_type_clear(&cache->cd_needed); - - drw_mesh_attributes_merge(&cache->attr_used_over_time, &cache->attr_needed, mesh_render_mutex); - drw_mesh_attributes_clear(&cache->attr_needed); } if (batch_requested & MBC_EDITUV) { @@ -1705,27 +1506,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, MeshBufferList *mbuflist = &cache->final.buff; /* Initialize batches and request VBO's & IBO's. */ - MDEPS_ASSERT(surface, - ibo.tris, - vbo.lnor, - vbo.pos_nor, - vbo.uv, - vbo.vcol, - vbo.attr[0], - vbo.attr[1], - vbo.attr[2], - vbo.attr[3], - vbo.attr[4], - vbo.attr[5], - vbo.attr[6], - vbo.attr[7], - vbo.attr[8], - vbo.attr[9], - vbo.attr[10], - vbo.attr[11], - vbo.attr[12], - vbo.attr[13], - vbo.attr[14]); + MDEPS_ASSERT(surface, ibo.tris, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.vcol); if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.surface, &mbuflist->ibo.tris); /* Order matters. First ones override latest VBO's attributes. */ @@ -1734,10 +1515,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.uv != 0) { DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.uv); } - if (cache->cd_used.vcol != 0) { + if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) { DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.vcol); } - drw_add_attributes_vbo(cache->batch.surface, mbuflist, &cache->attr_used); } MDEPS_ASSERT(all_verts, vbo.pos_nor); if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) { @@ -1800,28 +1580,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, } /* Per Material */ - MDEPS_ASSERT_FLAG(SURFACE_PER_MAT_FLAG, - vbo.lnor, - vbo.pos_nor, - vbo.uv, - vbo.tan, - vbo.vcol, - vbo.orco, - vbo.attr[0], - vbo.attr[1], - vbo.attr[2], - vbo.attr[3], - vbo.attr[4], - vbo.attr[5], - vbo.attr[6], - vbo.attr[7], - vbo.attr[8], - vbo.attr[9], - vbo.attr[10], - vbo.attr[11], - vbo.attr[12], - vbo.attr[13], - vbo.attr[14]); + MDEPS_ASSERT_FLAG( + SURFACE_PER_MAT_FLAG, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.tan, vbo.vcol, vbo.orco); MDEPS_ASSERT_INDEX(TRIS_PER_MAT_INDEX, SURFACE_PER_MAT_FLAG); for (int i = 0; i < cache->mat_len; i++) { if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) { @@ -1835,13 +1595,12 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) { DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.tan); } - if (cache->cd_used.vcol != 0) { + if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) { DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.vcol); } if (cache->cd_used.orco != 0) { DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.orco); } - drw_add_attributes_vbo(cache->surface_per_mat[i], mbuflist, &cache->attr_used); } } @@ -1992,9 +1751,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, MDEPS_ASSERT_MAP(vbo.edituv_stretch_angle); MDEPS_ASSERT_MAP(vbo.fdots_uv); MDEPS_ASSERT_MAP(vbo.fdots_edituv_data); - for (int i = 0; i < GPU_MAX_ATTR; i++) { - MDEPS_ASSERT_MAP(vbo.attr[i]); - } MDEPS_ASSERT_MAP(ibo.tris); MDEPS_ASSERT_MAP(ibo.lines); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h index d1ffef4fe92..d9f397fd8b8 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h @@ -328,7 +328,6 @@ extern const MeshExtract extract_poly_idx; extern const MeshExtract extract_edge_idx; extern const MeshExtract extract_vert_idx; extern const MeshExtract extract_fdot_idx; -extern const MeshExtract extract_attr[GPU_MAX_ATTR]; #ifdef __cplusplus } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc deleted file mode 100644 index f8cc92de1eb..00000000000 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ /dev/null @@ -1,398 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2021 by Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup draw - */ - -#include "MEM_guardedalloc.h" - -#include <functional> - -#include "BLI_float2.hh" -#include "BLI_float3.hh" -#include "BLI_float4.hh" -#include "BLI_string.h" - -#include "BKE_attribute.h" - -#include "extract_mesh.h" - -namespace blender::draw { - -/* ---------------------------------------------------------------------- */ -/** \name Extract Attributes - * \{ */ - -static CustomData *get_custom_data_for_domain(const MeshRenderData *mr, AttributeDomain domain) -{ - switch (domain) { - default: { - return nullptr; - } - case ATTR_DOMAIN_POINT: { - return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; - } - case ATTR_DOMAIN_CORNER: { - return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - } - case ATTR_DOMAIN_FACE: { - return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; - } - case ATTR_DOMAIN_EDGE: { - return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->edata : &mr->me->edata; - } - } -} - -/* Utility to convert from the type used in the attributes to the types for the VBO. - * This is mostly used to promote integers and booleans to floats, as other types (float, float2, - * etc.) directly map to avalaible GPU types. Booleans are still converted as attributes are vec4 - * in the shader. - */ -template<typename AttributeType, typename VBOType> struct attribute_type_converter { - static VBOType convert_value(AttributeType value) - { - if constexpr (std::is_same_v<AttributeType, VBOType>) { - return value; - } - - /* This should only concern bools which are converted to floats. */ - return static_cast<VBOType>(value); - } -}; - -/* Similar to the one in #extract_mesh_vcol_vbo.cc */ -struct gpuMeshCol { - ushort r, g, b, a; -}; - -template<> struct attribute_type_converter<MPropCol, gpuMeshCol> { - static gpuMeshCol convert_value(MPropCol value) - { - gpuMeshCol result; - result.r = unit_float_to_ushort_clamp(value.color[0]); - result.g = unit_float_to_ushort_clamp(value.color[1]); - result.b = unit_float_to_ushort_clamp(value.color[2]); - result.a = unit_float_to_ushort_clamp(value.color[3]); - return result; - } -}; - -/* Return the number of component for the attribute's value type, or 0 if is it unsupported. */ -static uint gpu_component_size_for_attribute_type(CustomDataType type) -{ - switch (type) { - case CD_PROP_BOOL: - case CD_PROP_INT32: - case CD_PROP_FLOAT: { - /* TODO(kevindietrich) : should be 1 when scalar attributes conversion is handled by us. See - * comment #extract_attr_init. */ - return 3; - } - case CD_PROP_FLOAT2: { - return 2; - } - case CD_PROP_FLOAT3: { - return 3; - } - case CD_PROP_COLOR: { - return 4; - } - default: { - return 0; - } - } -} - -static GPUVertFetchMode get_fetch_mode_for_type(CustomDataType type) -{ - switch (type) { - case CD_PROP_INT32: { - return GPU_FETCH_INT_TO_FLOAT; - } - case CD_PROP_COLOR: { - return GPU_FETCH_INT_TO_FLOAT_UNIT; - } - default: { - return GPU_FETCH_FLOAT; - } - } -} - -static GPUVertCompType get_comp_type_for_type(CustomDataType type) -{ - switch (type) { - case CD_PROP_INT32: { - return GPU_COMP_I32; - } - case CD_PROP_COLOR: { - return GPU_COMP_U16; - } - default: { - return GPU_COMP_F32; - } - } -} - -static void init_vbo_for_attribute(const MeshRenderData *mr, - GPUVertBuf *vbo, - const DRW_AttributeRequest &request) -{ - GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type); - GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type); - const uint comp_size = gpu_component_size_for_attribute_type(request.cd_type); - /* We should not be here if the attribute type is not supported. */ - BLI_assert(comp_size != 0); - - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name( - custom_data, request.cd_type, request.layer_index); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - /* Attributes use auto-name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - - GPUVertFormat format = {0}; - GPU_vertformat_deinterleave(&format); - GPU_vertformat_attr_add(&format, attr_name, comp_type, comp_size, fetch_mode); - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, static_cast<uint32_t>(mr->loop_len)); -} - -template<typename AttributeType, typename VBOType> -static void fill_vertbuf_with_attribute(const MeshRenderData *mr, - VBOType *vbo_data, - const DRW_AttributeRequest &request) -{ - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); - BLI_assert(custom_data); - const int layer_index = request.layer_index; - - const MPoly *mpoly = mr->mpoly; - const MLoop *mloop = mr->mloop; - - const AttributeType *attr_data = static_cast<AttributeType *>( - CustomData_get_layer_n(custom_data, request.cd_type, layer_index)); - - using converter = attribute_type_converter<AttributeType, VBOType>; - - switch (request.domain) { - default: { - BLI_assert(false); - break; - } - case ATTR_DOMAIN_POINT: { - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) { - *vbo_data = converter::convert_value(attr_data[mloop->v]); - } - break; - } - case ATTR_DOMAIN_CORNER: { - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) { - *vbo_data = converter::convert_value(attr_data[ml_index]); - } - break; - } - case ATTR_DOMAIN_EDGE: { - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) { - *vbo_data = converter::convert_value(attr_data[mloop->e]); - } - break; - } - case ATTR_DOMAIN_FACE: { - for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { - const MPoly &poly = mpoly[mp_index]; - const VBOType value = converter::convert_value(attr_data[mp_index]); - for (int l = 0; l < poly.totloop; l++) { - *vbo_data++ = value; - } - } - break; - } - } -} - -template<typename AttributeType, typename VBOType> -static void fill_vertbuf_with_attribute_bm(const MeshRenderData *mr, - VBOType *&vbo_data, - const DRW_AttributeRequest &request) -{ - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); - BLI_assert(custom_data); - const int layer_index = request.layer_index; - - int cd_ofs = CustomData_get_n_offset(custom_data, request.cd_type, layer_index); - - using converter = attribute_type_converter<AttributeType, VBOType>; - - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const AttributeType *attr_data = nullptr; - if (request.domain == ATTR_DOMAIN_POINT) { - attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_CORNER) { - attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_FACE) { - attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(efa, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_EDGE) { - attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->e, cd_ofs)); - } - else { - BLI_assert(false); - continue; - } - *vbo_data = converter::convert_value(*attr_data); - vbo_data++; - } while ((l_iter = l_iter->next) != l_first); - } -} - -template<typename AttributeType, typename VBOType = AttributeType> -static void extract_attr_generic(const MeshRenderData *mr, - GPUVertBuf *vbo, - const DRW_AttributeRequest &request) -{ - VBOType *vbo_data = static_cast<VBOType *>(GPU_vertbuf_get_data(vbo)); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - fill_vertbuf_with_attribute_bm<AttributeType>(mr, vbo_data, request); - } - else { - fill_vertbuf_with_attribute<AttributeType>(mr, vbo_data, request); - } -} - -static void extract_attr_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data), - int index) -{ - const DRW_MeshAttributes *attrs_used = &cache->attr_used; - const DRW_AttributeRequest &request = attrs_used->requests[index]; - - GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); - - init_vbo_for_attribute(mr, vbo, request); - - /* TODO(kevindietrich) : float3 is used for scalar attributes as the implicit conversion done by - * OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the - * Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a similar - * texture as for volume attribute, so we can control the conversion ourselves. */ - switch (request.cd_type) { - case CD_PROP_BOOL: { - extract_attr_generic<bool, float3>(mr, vbo, request); - break; - } - case CD_PROP_INT32: { - extract_attr_generic<int32_t, float3>(mr, vbo, request); - break; - } - case CD_PROP_FLOAT: { - extract_attr_generic<float, float3>(mr, vbo, request); - break; - } - case CD_PROP_FLOAT2: { - extract_attr_generic<float2>(mr, vbo, request); - break; - } - case CD_PROP_FLOAT3: { - extract_attr_generic<float3>(mr, vbo, request); - break; - } - case CD_PROP_COLOR: { - extract_attr_generic<MPropCol, gpuMeshCol>(mr, vbo, request); - break; - } - default: { - BLI_assert(false); - } - } -} - -/* Wrappers around extract_attr_init so we can pass the index of the attribute that we want to - * extract. The overall API does not allow us to pass this in a convenient way. */ -#define EXTRACT_INIT_WRAPPER(index) \ - static void extract_attr_init##index( \ - const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf, void *tls_data) \ - { \ - extract_attr_init(mr, cache, buf, tls_data, index); \ - } - -EXTRACT_INIT_WRAPPER(0) -EXTRACT_INIT_WRAPPER(1) -EXTRACT_INIT_WRAPPER(2) -EXTRACT_INIT_WRAPPER(3) -EXTRACT_INIT_WRAPPER(4) -EXTRACT_INIT_WRAPPER(5) -EXTRACT_INIT_WRAPPER(6) -EXTRACT_INIT_WRAPPER(7) -EXTRACT_INIT_WRAPPER(8) -EXTRACT_INIT_WRAPPER(9) -EXTRACT_INIT_WRAPPER(10) -EXTRACT_INIT_WRAPPER(11) -EXTRACT_INIT_WRAPPER(12) -EXTRACT_INIT_WRAPPER(13) -EXTRACT_INIT_WRAPPER(14) - -template<int index> constexpr MeshExtract create_extractor_attr(ExtractInitFn fn) -{ - MeshExtract extractor = {nullptr}; - extractor.init = fn; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = 0; - extractor.use_threading = false; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.attr[index]); - return extractor; -} - -/** \} */ - -} // namespace blender::draw - -extern "C" { -#define CREATE_EXTRACTOR_ATTR(index) \ - blender::draw::create_extractor_attr<index>(blender::draw::extract_attr_init##index) - -const MeshExtract extract_attr[GPU_MAX_ATTR] = { - CREATE_EXTRACTOR_ATTR(0), - CREATE_EXTRACTOR_ATTR(1), - CREATE_EXTRACTOR_ATTR(2), - CREATE_EXTRACTOR_ATTR(3), - CREATE_EXTRACTOR_ATTR(4), - CREATE_EXTRACTOR_ATTR(5), - CREATE_EXTRACTOR_ATTR(6), - CREATE_EXTRACTOR_ATTR(7), - CREATE_EXTRACTOR_ATTR(8), - CREATE_EXTRACTOR_ATTR(9), - CREATE_EXTRACTOR_ATTR(10), - CREATE_EXTRACTOR_ATTR(11), - CREATE_EXTRACTOR_ATTR(12), - CREATE_EXTRACTOR_ATTR(13), - CREATE_EXTRACTOR_ATTR(14), -}; -} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc index f8878eb2617..2c7770c8e72 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc @@ -43,7 +43,9 @@ static void extract_vcol_init(const MeshRenderData *mr, GPU_vertformat_deinterleave(&format); CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; uint32_t vcol_layers = cache->cd_used.vcol; + uint32_t svcol_layers = cache->cd_used.sculpt_vcol; for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { @@ -62,14 +64,42 @@ static void extract_vcol_init(const MeshRenderData *mr, } /* Gather number of auto layers. */ - /* We only do `vcols` that are not overridden by `uvs`. */ - if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { + /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 && + CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) { BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); GPU_vertformat_alias_add(&format, attr_name); } } } + /* Sculpt Vertex Colors */ + if (U.experimental.use_sculpt_vertex_colors) { + for (int i = 0; i < 8; i++) { + if (svcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "ac"); + } + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs`. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + } + } + } + } + GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); @@ -78,6 +108,7 @@ static void extract_vcol_init(const MeshRenderData *mr, }; gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); + MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP); for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { @@ -108,6 +139,35 @@ static void extract_vcol_init(const MeshRenderData *mr, } } } + + if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MPropCol *prop_col = (const MPropCol *)BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs); + vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]); + vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]); + vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]); + vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]); + vcol_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + MPropCol *vcol = (MPropCol *)CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) { + vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]); + vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]); + vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]); + vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]); + } + } + } } } diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 911c8cc2e42..018e192bf37 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -32,7 +32,7 @@ #include "GPU_shader.h" #include "GPU_vertex_buffer.h" -#define GPU_BATCH_VBO_MAX_LEN 16 +#define GPU_BATCH_VBO_MAX_LEN 6 #define GPU_BATCH_INST_VBO_MAX_LEN 2 #define GPU_BATCH_VAO_STATIC_LEN 3 #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16 @@ -54,11 +54,11 @@ typedef enum eGPUBatchFlag { GPU_BATCH_OWNS_INDEX = (GPU_BATCH_OWNS_INST_VBO_MAX << 1), /** Has been initialized. At least one VBO is set. */ - GPU_BATCH_INIT = (1 << 26), + GPU_BATCH_INIT = (1 << 16), /** Batch is initialized but its VBOs are still being populated. (optional) */ - GPU_BATCH_BUILDING = (1 << 26), + GPU_BATCH_BUILDING = (1 << 16), /** Cached data need to be rebuild. (VAO, PSO, ...) */ - GPU_BATCH_DIRTY = (1 << 27), + GPU_BATCH_DIRTY = (1 << 17), } eGPUBatchFlag; #define GPU_BATCH_OWNS_NONE GPU_BATCH_INVALID diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 3943c063c39..97f14b2195d 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -127,10 +127,6 @@ typedef struct Mesh_Runtime { /** Needed in case we need to lazily initialize the mesh. */ CustomData_MeshMasks cd_mask_extra; - /** Needed to ensure some thread-safety during render data pre-processing. */ - void *render_mutex; - void *_pad3; - } Mesh_Runtime; typedef struct Mesh { |