From 285a68b7bbf2fa40e41d507991467387f5dd5264 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Wed, 8 Jun 2022 12:30:01 -0700 Subject: Sculpt: PBVH Draw Support for EEVEE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for PBVH drawing in EEVEE. Notes: # PBVH_FACES only. For Multires we'll need an API to get/cache attributes. DynTopo support will be merged in later with sculpt-dev's DynTopo implementation. # Supports vertex color and UV attributes only; other types can be added fairly easily though. # Workbench only sends the active vertex color and UV layers to the GPU. # Added a new draw engine API method, DRW_cdlayer_attr_aliases_add. Please review. # The vertex format object is now stored in the pbvh. Reviewed By: Clément Foucault & Brecht Van Lommel & Jeroen Bakker Differential Revision: https://developer.blender.org/D13897 Ref D13897 --- source/blender/blenkernel/BKE_pbvh.h | 3 +- source/blender/blenkernel/intern/paint.c | 4 +- source/blender/blenkernel/intern/pbvh.c | 98 ++++++++++++++++++++------ source/blender/blenkernel/intern/pbvh_bmesh.c | 3 + source/blender/blenkernel/intern/pbvh_intern.h | 8 ++- 5 files changed, 89 insertions(+), 27 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 7a89dee4148..f517ff3a949 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -221,7 +221,8 @@ void BKE_pbvh_draw_cb(PBVH *pbvh, PBVHFrustumPlanes *update_frustum, PBVHFrustumPlanes *draw_frustum, void (*draw_fn)(void *user_data, struct GPU_PBVH_Buffers *buffers), - void *user_data); + void *user_data, + bool full_render); void BKE_pbvh_draw_debug_cb( PBVH *pbvh, diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1016d91614b..c9f60356451 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -2293,8 +2293,8 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *v3d) if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { /* Regular mesh only draws from PBVH without modifiers and shape keys. */ - const bool full_shading = (v3d && (v3d->shading.type > OB_SOLID)); - return !(ss->shapekey_active || ss->deform_modifiers_active || full_shading); + + return !(ss->shapekey_active || ss->deform_modifiers_active); } /* Multires and dyntopo always draw directly from the PBVH. */ diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index cdc4dfdccff..8c9db339753 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -714,6 +714,10 @@ void BKE_pbvh_free(PBVH *pbvh) MEM_SAFE_FREE(pbvh->vert_bitmap); + if (pbvh->vbo_id) { + GPU_pbvh_free_format(pbvh->vbo_id); + } + MEM_freeN(pbvh); } @@ -1299,6 +1303,17 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; + CustomData *vdata, *ldata; + + if (!pbvh->bm) { + vdata = pbvh->vdata; + ldata = pbvh->ldata; + } + else { + vdata = &pbvh->bm->vdata; + ldata = &pbvh->bm->ldata; + } + if (node->flag & PBVH_RebuildDrawBuffers) { switch (pbvh->type) { case PBVH_GRIDS: @@ -1326,7 +1341,8 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, const int update_flags = pbvh_get_buffers_update_flags(pbvh); switch (pbvh->type) { case PBVH_GRIDS: - GPU_pbvh_grid_buffers_update(node->draw_buffers, + GPU_pbvh_grid_buffers_update(pbvh->vbo_id, + node->draw_buffers, pbvh->subdiv_ccg, pbvh->grids, pbvh->grid_flag_mats, @@ -1339,26 +1355,22 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, update_flags); break; case PBVH_FACES: { - CustomDataLayer *layer = NULL; - eAttrDomain domain; - - BKE_pbvh_get_color_layer(pbvh->mesh, &layer, &domain); - - GPU_pbvh_mesh_buffers_update(node->draw_buffers, + GPU_pbvh_mesh_buffers_update(pbvh->vbo_id, + node->draw_buffers, pbvh->verts, - pbvh->vert_normals, + vdata, + ldata, CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK), - layer ? layer->data : NULL, - layer ? layer->type : -1, - layer ? domain : ATTR_DOMAIN_AUTO, CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), pbvh->face_sets_color_seed, pbvh->face_sets_color_default, - update_flags); + update_flags, + pbvh->vert_normals); break; } case PBVH_BMESH: - GPU_pbvh_bmesh_buffers_update(node->draw_buffers, + GPU_pbvh_bmesh_buffers_update(pbvh->vbo_id, + node->draw_buffers, pbvh->bm, node->bm_faces, node->bm_unique_verts, @@ -1379,8 +1391,49 @@ void pbvh_free_draw_buffers(PBVH *pbvh, PBVHNode *node) } } -static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag) +static void pbvh_update_draw_buffers( + PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag, bool full_render) { + const CustomData *vdata; + const CustomData *ldata; + + if (!pbvh->vbo_id) { + pbvh->vbo_id = GPU_pbvh_make_format(); + } + + switch (pbvh->type) { + case PBVH_BMESH: + if (!pbvh->bm) { + /* BMesh hasn't been created yet */ + return; + } + + vdata = &pbvh->bm->vdata; + ldata = &pbvh->bm->ldata; + break; + case PBVH_FACES: + vdata = pbvh->vdata; + ldata = pbvh->ldata; + break; + case PBVH_GRIDS: + ldata = vdata = NULL; + break; + } + + const bool active_attrs_only = !full_render; + + /* rebuild all draw buffers if attribute layout changed */ + if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, active_attrs_only)) { + /* attribute layout changed; force rebuild */ + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = pbvh->nodes + i; + + if (node->flag & PBVH_Leaf) { + node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; + } + } + } + if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) { /* Free buffers uses OpenGL, so not in parallel. */ for (int n = 0; n < totnode; n++) { @@ -2783,8 +2836,11 @@ void BKE_pbvh_draw_cb(PBVH *pbvh, PBVHFrustumPlanes *update_frustum, PBVHFrustumPlanes *draw_frustum, void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers), - void *user_data) + void *user_data, + bool full_render) { + pbvh->draw_cache_invalid = false; + PBVHNode **nodes; int totnode; int update_flag = 0; @@ -2808,7 +2864,7 @@ void BKE_pbvh_draw_cb(PBVH *pbvh, /* Update draw buffers. */ if (totnode != 0 && (update_flag & (PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers))) { - pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag); + pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag, full_render); } MEM_SAFE_FREE(nodes); @@ -3156,6 +3212,11 @@ bool BKE_pbvh_is_drawing(const PBVH *pbvh) return pbvh->is_drawing; } +bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh) +{ + return pbvh->draw_cache_invalid; +} + void BKE_pbvh_is_drawing_set(PBVH *pbvh, bool val) { pbvh->is_drawing = val; @@ -3229,8 +3290,3 @@ void BKE_pbvh_ensure_node_loops(PBVH *pbvh) MEM_SAFE_FREE(visit); } - -bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh) -{ - return pbvh->draw_cache_invalid; -} diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index d4c6dcfbc96..112fd01c699 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -376,6 +376,9 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index) return false; } + /* Trigger draw manager cache invalidation. */ + pbvh->draw_cache_invalid = true; + /* For each BMFace, store the AABB and AABB centroid */ BBC *bbc_array = MEM_mallocN(sizeof(BBC) * bm_faces_size, "BBC"); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 98b490b28dd..a4ac2744a73 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -2,6 +2,8 @@ #pragma once +struct PBVHGPUFormat; + /** \file * \ingroup bke */ @@ -123,9 +125,7 @@ struct PBVHNode { PBVHPixelsNode pixels; }; -typedef enum { - PBVH_DYNTOPO_SMOOTH_SHADING = 1, -} PBVHFlags; +typedef enum { PBVH_DYNTOPO_SMOOTH_SHADING = 1 } PBVHFlags; typedef struct PBVHBMeshLog PBVHBMeshLog; @@ -204,6 +204,8 @@ struct PBVH { /* Used by DynTopo to invalidate the draw cache. */ bool draw_cache_invalid; + + struct PBVHGPUFormat *vbo_id; }; /* pbvh.c */ -- cgit v1.2.3