From aa81e2dd4a09227fffc7ec90f5eacd31db36e11a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 4 Jun 2024 17:43:11 +0200 Subject: [PATCH] Fix #122455: Wireframe overlay can crash with loose geometry The `nor` vertex buffer wasn't large enough for the indices in the lines index buffer. This is undefined behavior at best AFAIK. On some drivers it caused crashes when there was only loose geometry. This commit makes the VBO large enough for all indices, filling the loose geometry normals with (0,0,0,0), which the overlay wireframe shader already checks for. Pull Request: https://projects.blender.org/blender/blender/pulls/122720 --- .../mesh_extractors/extract_mesh_vbo_lnor.cc | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index d59334ac404..3cc0f172124 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -215,6 +215,7 @@ static void extract_normals_bm(const MeshRenderData &mr, MutableSpan no void extract_normals(const MeshRenderData &mr, const bool use_hq, gpu::VertBuf &vbo) { + const int size = mr.corners_num + mr.loose_indices_num; if (use_hq) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { @@ -223,15 +224,19 @@ void extract_normals(const MeshRenderData &mr, const bool use_hq, gpu::VertBuf & } GPU_vertbuf_init_with_format(&vbo, &format); GPU_vertbuf_data_alloc(&vbo, mr.corners_num); - MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), mr.corners_num); + MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), size); + MutableSpan corners_data = vbo_data.take_front(mr.corners_num); + MutableSpan loose_data = vbo_data.take_back(mr.loose_indices_num); if (mr.extract_type == MR_EXTRACT_MESH) { - extract_normals_mesh(mr, vbo_data); - extract_paint_overlay_flags(mr, vbo_data); + extract_normals_mesh(mr, corners_data); + extract_paint_overlay_flags(mr, corners_data); } else { - extract_normals_bm(mr, vbo_data); + extract_normals_bm(mr, corners_data); } + + loose_data.fill(short4(0)); } else { static GPUVertFormat format = {0}; @@ -240,17 +245,20 @@ void extract_normals(const MeshRenderData &mr, const bool use_hq, gpu::VertBuf & GPU_vertformat_alias_add(&format, "lnor"); } GPU_vertbuf_init_with_format(&vbo, &format); - GPU_vertbuf_data_alloc(&vbo, mr.corners_num); - MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), - mr.corners_num); + GPU_vertbuf_data_alloc(&vbo, size); + MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), size); + MutableSpan corners_data = vbo_data.take_front(mr.corners_num); + MutableSpan loose_data = vbo_data.take_back(mr.loose_indices_num); if (mr.extract_type == MR_EXTRACT_MESH) { - extract_normals_mesh(mr, vbo_data); - extract_paint_overlay_flags(mr, vbo_data); + extract_normals_mesh(mr, corners_data); + extract_paint_overlay_flags(mr, corners_data); } else { - extract_normals_bm(mr, vbo_data); + extract_normals_bm(mr, corners_data); } + + loose_data.fill(GPUPackedNormal{}); } }