Fix T96344: edit mode GPU subdivision crashes with X-ray mode and modifiers

The crash happens because the origindex layers created as part of
the modifier stack evaluation are not set in the `MeshRenderData` when
they should have been.

This is because when selecting in X-ray mode, a subdivision wrapper
is created to ensure that selection happens with a subdivided
geometry, and this replaces the `MDATA` wrapper which is also used to
setup the `MeshRenderData`.

As we do not seemingly have an `MDATA` wrapper, the draw code decides
that we can extract draw buffers directly from the BMesh, instead of
the mapped Mesh with origin indices layers.

To fix this, we should also consider to use mapped extraction if a
subdivision wrapper exists on the mesh.

Differential Revision: https://developer.blender.org/D14485
This commit is contained in:
Kévin Dietrich 2022-03-30 17:31:40 +02:00
parent 9b9fda2122
commit ba28c10199
Notes: blender-bot 2023-02-14 05:44:22 +01:00
Referenced by issue #96344, GPU subdivision: Crash on select in Edit Mode with X-Ray on and Mirror Modifier
Referenced by issue #96241, 3.1: Potential candidates for corrective releases
1 changed files with 8 additions and 1 deletions

View File

@ -461,7 +461,14 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->bm_poly_centers = mr->edit_data->polyCos;
}
bool has_mdata = is_mode_active && (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
/* A subdivision wrapper may be created in edit mode when X-ray is turned on to ensure that the
* topology seen by the user matches the one used for the selection routines. This wrapper
* seemingly takes precedence over the MDATA one, however the mesh we use for rendering is not
* the subdivided one, but the one where the MDATA wrapper would have been added. So consider
* the subdivision wrapper as well for the `has_mdata` case. */
bool has_mdata = is_mode_active && ELEM(mr->me->runtime.wrapper_type,
ME_WRAPPER_TYPE_MDATA,
ME_WRAPPER_TYPE_SUBD);
bool use_mapped = is_mode_active &&
(has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original);