Fix T98392: GPU subdivision crash with knife tools

The face dots normals may not be always requested, thus leading to a
crash by null pointer dereference.
This commit is contained in:
Kévin Dietrich 2022-05-26 14:51:44 +02:00
parent 38a2576ace
commit 55e3930b25
Notes: blender-bot 2023-02-13 15:21:05 +01:00
Referenced by commit 7f7ed8e098, Fix T98571: corrupted face selection drawing with GPU subdivision
Referenced by issue #98392, GPU Subdivision: Crash when knife cut is made on object with mirror modifier
3 changed files with 32 additions and 7 deletions

View File

@ -69,6 +69,7 @@ enum {
SHADER_PATCH_EVALUATION,
SHADER_PATCH_EVALUATION_FVAR,
SHADER_PATCH_EVALUATION_FACE_DOTS,
SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS,
SHADER_COMP_CUSTOM_DATA_INTERP_1D,
SHADER_COMP_CUSTOM_DATA_INTERP_2D,
SHADER_COMP_CUSTOM_DATA_INTERP_3D,
@ -107,7 +108,8 @@ static const char *get_shader_code(int shader_type)
}
case SHADER_PATCH_EVALUATION:
case SHADER_PATCH_EVALUATION_FVAR:
case SHADER_PATCH_EVALUATION_FACE_DOTS: {
case SHADER_PATCH_EVALUATION_FACE_DOTS:
case SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS: {
return datatoc_common_subdiv_patch_evaluation_comp_glsl;
}
case SHADER_COMP_CUSTOM_DATA_INTERP_1D:
@ -163,6 +165,9 @@ static const char *get_shader_name(int shader_type)
case SHADER_PATCH_EVALUATION_FACE_DOTS: {
return "subdiv patch evaluation face dots";
}
case SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS: {
return "subdiv patch evaluation face dots with normals";
}
case SHADER_COMP_CUSTOM_DATA_INTERP_1D: {
return "subdiv custom data interp 1D";
}
@ -206,6 +211,13 @@ static GPUShader *get_patch_evaluation_shader(int shader_type)
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
"#define FDOTS_EVALUATION\n";
}
else if (shader_type == SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS) {
defines =
"#define OSD_PATCH_BASIS_GLSL\n"
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
"#define FDOTS_EVALUATION\n"
"#define FOTS_NORMALS\n";
}
else {
defines =
"#define OSD_PATCH_BASIS_GLSL\n"
@ -1625,7 +1637,9 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache *cache,
get_patch_param_format());
evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
GPUShader *shader = get_patch_evaluation_shader(SHADER_PATCH_EVALUATION_FACE_DOTS);
GPUShader *shader = get_patch_evaluation_shader(
fdots_nor ? SHADER_PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS :
SHADER_PATCH_EVALUATION_FACE_DOTS);
GPU_shader_bind(shader);
int binding_point = 0;
@ -1638,7 +1652,11 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(fdots_pos, binding_point++);
GPU_vertbuf_bind_as_ssbo(fdots_nor, binding_point++);
/* F-dots normals may not be requested, still reserve the binding point. */
if (fdots_nor) {
GPU_vertbuf_bind_as_ssbo(fdots_nor, binding_point);
}
binding_point++;
GPU_indexbuf_bind_as_ssbo(fdots_indices, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->extra_coarse_face_data, binding_point++);
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);

View File

@ -110,8 +110,11 @@ static void extract_fdots_init_subdiv(const DRWSubdivCache *subdiv_cache,
GPUVertBuf *fdots_nor_vbo = cache->final.buff.vbo.fdots_nor;
GPUIndexBuf *fdots_pos_ibo = cache->final.buff.ibo.fdots;
GPU_vertbuf_init_build_on_device(
fdots_nor_vbo, get_fdots_nor_format_subdiv(), subdiv_cache->num_coarse_poly);
/* The normals may not be requested. */
if (fdots_nor_vbo) {
GPU_vertbuf_init_build_on_device(
fdots_nor_vbo, get_fdots_nor_format_subdiv(), subdiv_cache->num_coarse_poly);
}
GPU_vertbuf_init_build_on_device(
fdots_pos_vbo, get_fdots_pos_format(), subdiv_cache->num_coarse_poly);
GPU_indexbuf_init_build_on_device(fdots_pos_ibo, subdiv_cache->num_coarse_poly);

View File

@ -70,10 +70,12 @@ layout(std430, binding = 8) writeonly buffer outputVertices
FDotVert output_verts[];
};
# ifdef FDOTS_NORMALS
layout(std430, binding = 9) writeonly buffer outputNormals
{
FDotNor output_nors[];
};
# endif
layout(std430, binding = 10) writeonly buffer outputFdotsIndices
{
@ -375,13 +377,15 @@ void main()
fnor.flag = get_face_flag(coarse_quad_index);
output_verts[coarse_quad_index] = vert;
# ifdef FDOTS_NORMALS
output_nors[coarse_quad_index] = fnor;
# endif
if (is_face_hidden(coarse_quad_index)) {
output_indices[coarse_quad_index] = 0xffffffff;
output_indices[coarse_quad_index] = 0xffffffff;
}
else {
output_indices[coarse_quad_index] = coarse_quad_index;
output_indices[coarse_quad_index] = coarse_quad_index;
}
}
#else