Fix T75908: Sculpt GPU Batches + Render Artifacts

When sculpting the GPU batches are constructed with only the required data
for a single viewport. When that viewport changes shading or coloring mode (object
to vertex) batches might not hold all the needed information.

There is also a case when you have two 3d viewport one in object color
mode and the other in vertex color mode that the GPU batches were
updated without any vertex colors.

In order to fix these category of issues this patch would always
construct the full GPU batches for sculpting.

Reviewed By: Clément Foucault, Pablo Dobarro

Maniphest Tasks: T75908

Differential Revision: https://developer.blender.org/D7701
This commit is contained in:
Jeroen Bakker 2020-05-14 11:56:16 +02:00 • committed by Jeroen Bakker
parent 975c45df9a
commit 7d38f50367
10 changed files with 24 additions and 39 deletions

View file

@ -190,7 +190,6 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
/* Drawing */
void BKE_pbvh_draw_cb(PBVH *bvh,
bool show_vcol,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,

View file

@ -1009,7 +1009,6 @@ typedef struct PBVHUpdateData {
float (*vnors)[3];
int flag;
bool show_vcol;
bool show_sculpt_face_sets;
} PBVHUpdateData;
@ -1250,12 +1249,10 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
}
static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol)
static int pbvh_get_buffers_update_flags(PBVH *UNUSED(bvh))
{
int update_flags = 0;
update_flags |= bvh->show_mask ? GPU_PBVH_BUFFERS_SHOW_MASK : 0;
update_flags |= show_vcol ? GPU_PBVH_BUFFERS_SHOW_VCOL : 0;
update_flags |= bvh->show_face_sets ? GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS : 0;
int update_flags = GPU_PBVH_BUFFERS_SHOW_VCOL | GPU_PBVH_BUFFERS_SHOW_MASK |
GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS;
return update_flags;
}
@ -1295,7 +1292,7 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
}
if (node->flag & PBVH_UpdateDrawBuffers) {
const int update_flags = pbvh_get_buffers_update_flags(bvh, data->show_vcol);
const int update_flags = pbvh_get_buffers_update_flags(bvh);
switch (bvh->type) {
case PBVH_GRIDS:
GPU_pbvh_grid_buffers_update(node->draw_buffers,
@ -1335,8 +1332,7 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
}
}
static void pbvh_update_draw_buffers(
PBVH *bvh, PBVHNode **nodes, int totnode, bool show_vcol, int update_flag)
static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int update_flag)
{
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(bvh->type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
@ -1362,7 +1358,6 @@ static void pbvh_update_draw_buffers(
PBVHUpdateData data = {
.bvh = bvh,
.nodes = nodes,
.show_vcol = show_vcol,
};
PBVHParallelSettings settings;
@ -2679,7 +2674,6 @@ static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v)
}
void BKE_pbvh_draw_cb(PBVH *bvh,
bool show_vcol,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,
@ -2696,7 +2690,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
if (totnode) {
pbvh_update_draw_buffers(bvh, nodes, totnode, show_vcol, update_flag);
pbvh_update_draw_buffers(bvh, nodes, totnode, update_flag);
}
MEM_SAFE_FREE(nodes);
@ -2708,7 +2702,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
if (update_only_visible && (data.accum_update_flag & update_flag)) {
/* Update draw buffers in visible nodes. */
pbvh_update_draw_buffers(bvh, nodes, totnode, show_vcol, data.accum_update_flag);
pbvh_update_draw_buffers(bvh, nodes, totnode, data.accum_update_flag);
}
/* Draw. */

View file

@ -202,7 +202,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
stl->g_data->depth_shgrp[do_in_front];
if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, false, false, false);
DRW_shgroup_call_sculpt(shgrp, ob, false, false);
}
else {
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);

View file

@ -2073,23 +2073,21 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
}
if (use_sculpt_pbvh) {
/* Vcol is not supported in the modes that require PBVH drawing. */
const bool use_vcol = false;
struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array,
materials_len);
for (int i = 0; i < materials_len; i++) {
sculpt_shgrps_array[i] = shgrps_array[i].shading_grp;
}
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob, use_vcol);
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
for (int i = 0; i < materials_len; i++) {
sculpt_shgrps_array[i] = shgrps_array[i].depth_grp;
}
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob, use_vcol);
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
for (int i = 0; i < materials_len; i++) {
sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp;
}
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob, use_vcol);
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
for (int renderpass_index = 0;
renderpass_index < stl->g_data->render_passes_material_count;
@ -2097,7 +2095,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
for (int i = 0; i < materials_len; i++) {
sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index];
}
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob, use_vcol);
DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
}
/* TODO(fclem): Support shadows in sculpt mode. */

View file

@ -63,7 +63,7 @@ void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob)
const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0;
if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(pd->facing_grp[is_xray], ob, false, false, false);
DRW_shgroup_call_sculpt(pd->facing_grp[is_xray], ob, false, false);
}
else {
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);

View file

@ -54,7 +54,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
if (use_pbvh || !ob->sculpt->deform_modifiers_active || ob->sculpt->shapekey_active) {
if (!use_pbvh || pbvh_has_mask(pbvh) || pbvh_has_face_sets(pbvh)) {
DRW_shgroup_call_sculpt(pd->sculpt_mask_grp, ob, false, true, false);
DRW_shgroup_call_sculpt(pd->sculpt_mask_grp, ob, false, true);
}
}
}

View file

@ -230,7 +230,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
DRW_shgroup_call_no_cull(shgrp, geom, ob);
}
else if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, true, false, false);
DRW_shgroup_call_sculpt(shgrp, ob, true, false);
}
else {
DRW_shgroup_call(shgrp, geom, ob);

View file

@ -118,7 +118,7 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd,
if (use_single_drawcall) {
DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, NULL);
DRW_shgroup_call_sculpt(grp, ob, false, false, use_vcol);
DRW_shgroup_call_sculpt(grp, ob, false, false);
}
else {
const int materials_len = DRW_cache_object_material_count_get(ob);
@ -126,7 +126,7 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd,
for (int i = 0; i < materials_len; i++) {
shgrps[i] = workbench_material_setup(wpd, ob, i + 1, color_type, NULL);
}
DRW_shgroup_call_sculpt_with_materials(shgrps, materials_len, ob, false);
DRW_shgroup_call_sculpt_with_materials(shgrps, materials_len, ob);
}
}

View file

@ -410,11 +410,8 @@ void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup,
struct GPUBatch *geom,
struct GPUBatch *inst_attributes);
void DRW_shgroup_call_sculpt(DRWShadingGroup *sh, Object *ob, bool wire, bool mask, bool vcol);
void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **sh,
int num_sh,
Object *ob,
bool vcol);
void DRW_shgroup_call_sculpt(DRWShadingGroup *sh, Object *ob, bool wire, bool mask);
void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **sh, int num_sh, Object *ob);
DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shading_group,
struct GPUVertFormat *format,

View file

@ -954,7 +954,7 @@ static void drw_sculpt_get_frustum_planes(Object *ob, float planes[6][4])
}
}
static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol)
static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
{
/* PBVH should always exist for non-empty meshes, created by depsgrah eval. */
PBVH *pbvh = (scd->ob->sculpt) ? scd->ob->sculpt->pbvh : NULL;
@ -1015,7 +1015,6 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol)
BKE_pbvh_update_normals(pbvh, mesh->runtime.subdiv_ccg);
BKE_pbvh_draw_cb(pbvh,
use_vcol,
update_only_visible,
&update_frustum,
&draw_frustum,
@ -1033,8 +1032,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol)
}
}
void DRW_shgroup_call_sculpt(
DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask, bool use_vcol)
void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask)
{
DRWSculptCallbackData scd = {
.ob = ob,
@ -1044,13 +1042,12 @@ void DRW_shgroup_call_sculpt(
.use_mats = false,
.use_mask = use_mask,
};
drw_sculpt_generate_calls(&scd, use_vcol);
drw_sculpt_generate_calls(&scd);
}
void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
int num_shgroups,
Object *ob,
bool use_vcol)
Object *ob)
{
DRWSculptCallbackData scd = {
.ob = ob,
@ -1060,7 +1057,7 @@ void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
.use_mats = true,
.use_mask = false,
};
drw_sculpt_generate_calls(&scd, use_vcol);
drw_sculpt_generate_calls(&scd);
}
static GPUVertFormat inst_select_format = {0};