DRW: optimize mesh data extraction
authorCampbell Barton <ideasman42@gmail.com>
Tue, 30 Jun 2020 14:13:39 +0000 (00:13 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 1 Jul 2020 04:56:39 +0000 (14:56 +1000)
Change extraction callbacks to take index ranges instead of calling them
for each mesh element (poly, loop, vert & edge).

This gives a minor overall performance gain in my tests, ~5% on average.

Details:

- Use typed parameter structs and macros for looping over elements.
  Without this, changes to these callbacks is time consuming as changes
  need to be made in many places.
- Avoid iterating over polygon-loops when iterating over polygons
  is sufficient.
- Simplify logic to access adjacent loops for faster line extraction.
- Rename 'loop' iterators to 'poly' (as they take polygon ranges)
  the iterator callbacks can operator on either polygon or loop data.
- Use term 'last' for the last index (inclusive),
  use 'end' when this value (not inclusive).

source/blender/draw/intern/draw_cache_extract.h
source/blender/draw/intern/draw_cache_extract_mesh.c

index 0b1f625dc2c7ca2f5845f56005ed56b942498f15..302f9a0d3a85695de7e4683a182879c40f862cb9 100644 (file)
@@ -63,7 +63,7 @@ typedef struct DRW_MeshCDMask {
 
 typedef enum eMRIterType {
   MR_ITER_LOOPTRI = 1 << 0,
-  MR_ITER_LOOP = 1 << 1,
+  MR_ITER_POLY = 1 << 1,
   MR_ITER_LEDGE = 1 << 2,
   MR_ITER_LVERT = 1 << 3,
 } eMRIterType;
index f1a7ab8c9d8715f7b76ab3e4dca64223b78635ae..c92722fad7efb39e86d1b292383accacf0811319 100644 (file)
@@ -148,14 +148,14 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
       BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
 
       mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__);
-      const MEdge *medge = mr->medge;
-      for (int e = 0; e < mr->edge_len; e++, medge++) {
-        if (medge->flag & ME_LOOSEEDGE) {
-          mr->ledges[mr->edge_loose_len++] = e;
+      const MEdge *med = mr->medge;
+      for (int med_index = 0; med_index < mr->edge_len; med_index++, med++) {
+        if (med->flag & ME_LOOSEEDGE) {
+          mr->ledges[mr->edge_loose_len++] = med_index;
         }
         /* Tag verts as not loose. */
-        BLI_BITMAP_ENABLE(lvert_map, medge->v1);
-        BLI_BITMAP_ENABLE(lvert_map, medge->v2);
+        BLI_BITMAP_ENABLE(lvert_map, med->v1);
+        BLI_BITMAP_ENABLE(lvert_map, med->v2);
       }
       if (mr->edge_loose_len < mr->edge_len) {
         mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges));
@@ -173,7 +173,7 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
 
       MEM_freeN(lvert_map);
 
-      mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
+      mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
     }
   }
   else {
@@ -297,7 +297,7 @@ static void mesh_render_data_update_normals(MeshRenderData *mr,
       }
 
       mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
-      int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
+      const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
       BM_loops_calc_normal_vcos(mr->bm,
                                 vert_coords,
                                 vert_normals,
@@ -507,45 +507,254 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e
 /** \} */
 
 /* ---------------------------------------------------------------------- */
-/** \name Mesh Elements Extract Iter
+/** \name Mesh Elements Extract: Loop Triangles
  * \{ */
 
-typedef void *(ExtractInitFn)(const MeshRenderData *mr, void *buffer);
-
+typedef struct ExtractTriBMesh_Params {
+  BMLoop *(*looptris)[3];
+  int tri_range[2];
+} ExtractTriBMesh_Params;
 typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
-                                int tri_index,
-                                BMLoop **ltri,
+                                const ExtractTriBMesh_Params *params,
                                 void *data);
+
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \
+  CHECK_TYPE(params, const ExtractTriBMesh_Params *); \
+  { \
+    const int _tri_index_end = (params)->tri_range[1]; \
+    BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \
+    for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \
+         index_tri += 1, elem_tri += 3)
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END }
+
+typedef struct ExtractTriMesh_Params {
+  const MLoopTri *mlooptri;
+  int tri_range[2];
+} ExtractTriMesh_Params;
 typedef void(ExtractTriMeshFn)(const MeshRenderData *mr,
-                               int tri_index,
-                               const MLoopTri *mlt,
+                               const ExtractTriMesh_Params *params,
                                void *data);
 
-typedef void(ExtractLoopBMeshFn)(const MeshRenderData *mr, int loop_index, BMLoop *el, void *data);
-typedef void(ExtractLoopMeshFn)(const MeshRenderData *mr,
-                                int loop_index,
-                                const MLoop *mloop,
-                                int poly_index,
-                                const MPoly *mpoly,
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \
+  CHECK_TYPE(params, const ExtractTriMesh_Params *); \
+  { \
+    const int _tri_index_end = (params)->tri_range[1]; \
+    const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \
+    for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \
+         index_tri += 1, elem_tri += 1)
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Polygons, Loops
+ * \{ */
+
+typedef struct ExtractPolyBMesh_Params {
+  BMLoop *(*looptris)[3];
+  int poly_range[2];
+} ExtractPolyBMesh_Params;
+typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr,
+                                 const ExtractPolyBMesh_Params *params,
+                                 void *data);
+
+#define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \
+  CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \
+  { \
+    BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+    BMFace **_ftable = mr->bm->ftable; \
+    const int _poly_index_end = (params)->poly_range[1]; \
+    for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+         index_poly += 1) { \
+      BMFace *elem_poly = _ftable[index_poly]; \
+      (void)elem_poly;
+
+#define EXTRACT_POLY_FOREACH_BM_END \
+  } \
+  }
+
+/* Iterate over polygon and loop. */
+#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(elem_loop, index_loop, params, mr) \
+  CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \
+  { \
+    BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+    BMFace **_ftable = mr->bm->ftable; \
+    const int _poly_index_end = (params)->poly_range[1]; \
+    for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+         index_poly += 1) { \
+      BMFace *elem_face = _ftable[index_poly]; \
+      BMLoop *elem_loop, *l_first; \
+      elem_loop = l_first = BM_FACE_FIRST_LOOP(elem_face); \
+      do { \
+        const int index_loop = BM_elem_index_get(elem_loop); \
+        (void)index_loop; /* Quiet warning when unused. */
+
+#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(elem_loop) \
+  } \
+  while ((elem_loop = elem_loop->next) != l_first) \
+    ; \
+  } \
+  }
+
+typedef struct ExtractPolyMesh_Params {
+  int poly_range[2];
+} ExtractPolyMesh_Params;
+typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr,
+                                const ExtractPolyMesh_Params *params,
                                 void *data);
 
+#define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \
+  CHECK_TYPE(params, const ExtractPolyMesh_Params *); \
+  { \
+    const MPoly *_mpoly = mr->mpoly; \
+    const int _poly_index_end = (params)->poly_range[1]; \
+    for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+         index_poly += 1) { \
+      const MPoly *elem_poly = &_mpoly[index_poly]; \
+      (void)elem_poly;
+
+#define EXTRACT_POLY_FOREACH_MESH_END \
+  } \
+  }
+
+/* Iterate over polygon and loop. */
+#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN( \
+    elem_poly, index_poly, elem_loop, index_loop, params, mr) \
+  CHECK_TYPE(params, const ExtractPolyMesh_Params *); \
+  { \
+    const MPoly *_mpoly = mr->mpoly; \
+    const MLoop *_mloop = mr->mloop; \
+    const int _poly_index_end = (params)->poly_range[1]; \
+    for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+         index_poly += 1) { \
+      const MPoly *elem_poly = &_mpoly[index_poly]; \
+      const int _index_end = elem_poly->loopstart + elem_poly->totloop; \
+      for (int index_loop = elem_poly->loopstart; index_loop < _index_end; index_loop += 1) { \
+        const MLoop *elem_loop = &_mloop[index_loop]; \
+        (void)elem_loop;
+
+#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END \
+  } \
+  } \
+  }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Loose Edges
+ * \{ */
+
+typedef struct ExtractLEdgeBMesh_Params {
+  const int *ledge;
+  int ledge_range[2];
+} ExtractLEdgeBMesh_Params;
 typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr,
-                                  int ledge_index,
-                                  BMEdge *eed,
+                                  const ExtractLEdgeBMesh_Params *params,
                                   void *data);
+
+#define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \
+  CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \
+  { \
+    BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \
+    BMEdge **_etable = mr->bm->etable; \
+    const int *_ledge = (params)->ledge; \
+    const int _ledge_index_end = (params)->ledge_range[1]; \
+    for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \
+         index_ledge += 1) { \
+      BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \
+      (void)elem_edge; /* Quiet warning when unused. */ \
+      {
+#define EXTRACT_LEDGE_FOREACH_BM_END \
+  } \
+  } \
+  }
+
+typedef struct ExtractLEdgeMesh_Params {
+  const int *ledge;
+  int ledge_range[2];
+} ExtractLEdgeMesh_Params;
 typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr,
-                                 int ledge_index,
-                                 const MEdge *medge,
+                                 const ExtractLEdgeMesh_Params *params,
                                  void *data);
 
+#define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \
+  CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \
+  { \
+    const MEdge *_medge = mr->medge; \
+    const int *_ledge = (params)->ledge; \
+    const int _ledge_index_end = (params)->ledge_range[1]; \
+    for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \
+         index_ledge += 1) { \
+      const MEdge *elem_edge = &_medge[_ledge[index_ledge]]; \
+      (void)elem_edge; /* Quiet warning when unused. */ \
+      {
+#define EXTRACT_LEDGE_FOREACH_MESH_END \
+  } \
+  } \
+  }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Loose Vertices
+ * \{ */
+
+typedef struct ExtractLVertBMesh_Params {
+  const int *lvert;
+  int lvert_range[2];
+} ExtractLVertBMesh_Params;
 typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr,
-                                  int lvert_index,
-                                  BMVert *eve,
+                                  const ExtractLVertBMesh_Params *params,
                                   void *data);
+
+#define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \
+  CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \
+  { \
+    BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+    BMVert **vtable = mr->bm->vtable; \
+    const int *lverts = (params)->lvert; \
+    const int _lvert_index_end = (params)->lvert_range[1]; \
+    for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \
+         index_lvert += 1) { \
+      BMVert *elem_vert = vtable[lverts[index_lvert]]; \
+      (void)elem_vert; /* Quiet warning when unused. */ \
+      {
+#define EXTRACT_LVERT_FOREACH_BM_END \
+  } \
+  } \
+  }
+
+typedef struct ExtractLVertMesh_Params {
+  const int *lvert;
+  int lvert_range[2];
+} ExtractLVertMesh_Params;
 typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
-                                 int lvert_index,
-                                 const MVert *mvert,
+                                 const ExtractLVertMesh_Params *params,
                                  void *data);
+
+#define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \
+  CHECK_TYPE(params, const ExtractLVertMesh_Params *); \
+  { \
+    const MVert *mvert = mr->mvert; \
+    const int *lverts = (params)->lvert; \
+    const int _lvert_index_end = (params)->lvert_range[1]; \
+    for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \
+         index_lvert += 1) { \
+      const MVert *elem = &mvert[lverts[index_lvert]]; \
+      (void)elem; /* Quiet warning when unused. */ \
+      {
+#define EXTRACT_LVERT_FOREACH_MESH_END \
+  } \
+  } \
+  }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract Struct
+ * \{ */
+
+typedef void *(ExtractInitFn)(const MeshRenderData *mr, void *buffer);
 typedef void(ExtractFinishFn)(const MeshRenderData *mr, void *buffer, void *data);
 
 typedef struct MeshExtract {
@@ -554,8 +763,8 @@ typedef struct MeshExtract {
   /** Executed on one (or more if use_threading) worker thread(s). */
   ExtractTriBMeshFn *iter_looptri_bm;
   ExtractTriMeshFn *iter_looptri_mesh;
-  ExtractLoopBMeshFn *iter_loop_bm;
-  ExtractLoopMeshFn *iter_loop_mesh;
+  ExtractPolyBMeshFn *iter_poly_bm;
+  ExtractPolyMeshFn *iter_poly_mesh;
   ExtractLEdgeBMeshFn *iter_ledge_bm;
   ExtractLEdgeMeshFn *iter_ledge_mesh;
   ExtractLVertBMeshFn *iter_lvert_bm;
@@ -572,7 +781,7 @@ BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
 {
   eMRIterType type = 0;
   SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI);
-  SET_FLAG_FROM_TEST(type, (ext->iter_loop_bm || ext->iter_loop_mesh), MR_ITER_LOOP);
+  SET_FLAG_FROM_TEST(type, (ext->iter_poly_bm || ext->iter_poly_mesh), MR_ITER_POLY);
   SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE);
   SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT);
   return type;
@@ -611,11 +820,11 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
     }
   }
   else {
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0; p < mr->poly_len; p++, mpoly++) {
-      if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
-        int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
-        mat_tri_len[mat] += mpoly->totloop - 2;
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+        int mat = min_ii(mp->mat_nr, mr->mat_len - 1);
+        mat_tri_len[mat] += mp->totloop - 2;
       }
     }
   }
@@ -636,36 +845,44 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
   return data;
 }
 
-static void extract_tris_looptri_bmesh(const MeshRenderData *mr,
-                                       int UNUSED(t),
-                                       BMLoop **elt,
-                                       void *_data)
+static void extract_tris_iter_looptri_bm(const MeshRenderData *mr,
+                                         const struct ExtractTriBMesh_Params *params,
+                                         void *_data)
 {
-  if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
-    MeshExtract_Tri_Data *data = _data;
-    int *mat_tri_ofs = data->tri_mat_end;
-    int mat = min_ii(elt[0]->f->mat_nr, mr->mat_len - 1);
-    GPU_indexbuf_set_tri_verts(&data->elb,
-                               mat_tri_ofs[mat]++,
-                               BM_elem_index_get(elt[0]),
-                               BM_elem_index_get(elt[1]),
-                               BM_elem_index_get(elt[2]));
+  MeshExtract_Tri_Data *data = _data;
+  const int mat_last = mr->mat_len - 1;
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+  {
+    if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
+      int *mat_tri_ofs = data->tri_mat_end;
+      const int mat = min_ii(elt[0]->f->mat_nr, mat_last);
+      GPU_indexbuf_set_tri_verts(&data->elb,
+                                 mat_tri_ofs[mat]++,
+                                 BM_elem_index_get(elt[0]),
+                                 BM_elem_index_get(elt[1]),
+                                 BM_elem_index_get(elt[2]));
+    }
   }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
 }
 
-static void extract_tris_looptri_mesh(const MeshRenderData *mr,
-                                      int UNUSED(t),
-                                      const MLoopTri *mlt,
-                                      void *_data)
+static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr,
+                                           const struct ExtractTriMesh_Params *params,
+                                           void *_data)
 {
-  const MPoly *mpoly = &mr->mpoly[mlt->poly];
-  if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
-    MeshExtract_Tri_Data *data = _data;
-    int *mat_tri_ofs = data->tri_mat_end;
-    int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
-    GPU_indexbuf_set_tri_verts(
-        &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+  MeshExtract_Tri_Data *data = _data;
+  const int mat_last = mr->mat_len - 1;
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+  {
+    const MPoly *mp = &mr->mpoly[mlt->poly];
+    if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+      int *mat_tri_ofs = data->tri_mat_end;
+      const int mat = min_ii(mp->mat_nr, mat_last);
+      GPU_indexbuf_set_tri_verts(
+          &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+    }
   }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
 }
 
 static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data)
@@ -677,8 +894,8 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data
     BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo);
     for (int i = 0; i < mr->mat_len; i++) {
       /* Multiply by 3 because these are triangle indices. */
-      int start = data->tri_mat_start[i] * 3;
-      int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
+      const int start = data->tri_mat_start[i] * 3;
+      const int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
       GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len);
       /* WARNING: We modify the #GPUBatch here! */
       GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true);
@@ -691,8 +908,8 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data
 
 static const MeshExtract extract_tris = {
     .init = extract_tris_init,
-    .iter_looptri_bm = extract_tris_looptri_bmesh,
-    .iter_looptri_mesh = extract_tris_looptri_mesh,
+    .iter_looptri_bm = extract_tris_iter_looptri_bm,
+    .iter_looptri_mesh = extract_tris_iter_looptri_mesh,
     .finish = extract_tris_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -713,71 +930,113 @@ static void *extract_lines_init(const MeshRenderData *mr, void *UNUSED(buf))
   return elb;
 }
 
-static void extract_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                     int l,
-                                     BMLoop *loop,
-                                     void *elb)
-{
-  if (!BM_elem_flag_test(loop->e, BM_ELEM_HIDDEN)) {
-    GPU_indexbuf_set_line_verts(elb, BM_elem_index_get(loop->e), l, BM_elem_index_get(loop->next));
-  }
-  else {
-    GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(loop->e));
+static void extract_lines_iter_poly_bm(const MeshRenderData *mr,
+                                       const ExtractPolyBMesh_Params *params,
+                                       void *elb)
+{
+  /* Using poly & loop iterator would complicate accessing the adjacent loop. */
+  EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+  {
+    BMLoop *l_iter, *l_first;
+    /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */
+    l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev;
+    do {
+      if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) {
+        GPU_indexbuf_set_line_verts(elb,
+                                    BM_elem_index_get(l_iter->e),
+                                    BM_elem_index_get(l_iter),
+                                    BM_elem_index_get(l_iter->next));
+      }
+      else {
+        GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(l_iter->e));
+      }
+    } while ((l_iter = l_iter->next) != l_first);
   }
+  EXTRACT_POLY_FOREACH_BM_END;
 }
 
-static void extract_lines_loop_mesh(const MeshRenderData *mr,
-                                    int l,
-                                    const MLoop *mloop,
-                                    int UNUSED(p),
-                                    const MPoly *mpoly,
-                                    void *elb)
+static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
+                                         const ExtractPolyMesh_Params *params,
+                                         void *elb)
 {
-  const MEdge *medge = &mr->medge[mloop->e];
-  if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
-        ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
-         (mr->e_origindex[mloop->e] == ORIGINDEX_NONE)))) {
-    int loopend = mpoly->totloop + mpoly->loopstart - 1;
-    int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
-    GPU_indexbuf_set_line_verts(elb, mloop->e, l, other_loop);
+  /* Using poly & loop iterator would complicate accessing the adjacent loop. */
+  const MLoop *mloop = mr->mloop;
+  const MEdge *medge = mr->medge;
+  if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != NULL)) {
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      const int ml_index_last = mp->loopstart + (mp->totloop - 1);
+      int ml_index = ml_index_last, ml_index_next = mp->loopstart;
+      do {
+        const MLoop *ml = &mloop[ml_index];
+        const MEdge *med = &medge[ml->e];
+        if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
+              ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+               (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) {
+          GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
+        }
+        else {
+          GPU_indexbuf_set_line_restart(elb, ml->e);
+        }
+      } while ((ml_index = ml_index_next++) != ml_index_last);
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
   }
   else {
-    GPU_indexbuf_set_line_restart(elb, mloop->e);
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      const int ml_index_last = mp->loopstart + (mp->totloop - 1);
+      int ml_index = ml_index_last, ml_index_next = mp->loopstart;
+      do {
+        const MLoop *ml = &mloop[ml_index];
+        GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
+      } while ((ml_index = ml_index_next++) != ml_index_last);
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
   }
 }
 
-static void extract_lines_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
+static void extract_lines_iter_ledge_bm(const MeshRenderData *mr,
+                                        const ExtractLEdgeBMesh_Params *params,
+                                        void *elb)
 {
-  int ledge_idx = mr->edge_len + e;
-  if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
-    int l = mr->loop_len + e * 2;
-    GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
-  }
-  else {
-    GPU_indexbuf_set_line_restart(elb, ledge_idx);
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    const int l_index_offset = mr->edge_len + ledge_index;
+    if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+      const int l_index = mr->loop_len + ledge_index * 2;
+      GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
+    }
+    else {
+      GPU_indexbuf_set_line_restart(elb, l_index_offset);
+    }
+    /* Don't render the edge twice. */
+    GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
   }
-  /* Don't render the edge twice. */
-  GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_lines_ledge_mesh(const MeshRenderData *mr,
-                                     int e,
-                                     const MEdge *medge,
-                                     void *elb)
+static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr,
+                                          const ExtractLEdgeMesh_Params *params,
+                                          void *elb)
 {
-  int ledge_idx = mr->edge_len + e;
-  int edge_idx = mr->ledges[e];
-  if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
-        ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
-         (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
-    int l = mr->loop_len + e * 2;
-    GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
-  }
-  else {
-    GPU_indexbuf_set_line_restart(elb, ledge_idx);
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    const int l_index_offset = mr->edge_len + ledge_index;
+    const int e_index = mr->ledges[ledge_index];
+    if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
+          ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+           (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
+      const int l_index = mr->loop_len + ledge_index * 2;
+      GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
+    }
+    else {
+      GPU_indexbuf_set_line_restart(elb, l_index_offset);
+    }
+    /* Don't render the edge twice. */
+    GPU_indexbuf_set_line_restart(elb, e_index);
   }
-  /* Don't render the edge twice. */
-  GPU_indexbuf_set_line_restart(elb, edge_idx);
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
 static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
@@ -788,10 +1047,10 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo
 
 static const MeshExtract extract_lines = {
     .init = extract_lines_init,
-    .iter_loop_bm = extract_lines_loop_bmesh,
-    .iter_loop_mesh = extract_lines_loop_mesh,
-    .iter_ledge_bm = extract_lines_ledge_bmesh,
-    .iter_ledge_mesh = extract_lines_ledge_mesh,
+    .iter_poly_bm = extract_lines_iter_poly_bm,
+    .iter_poly_mesh = extract_lines_iter_poly_mesh,
+    .iter_ledge_bm = extract_lines_iter_ledge_bm,
+    .iter_ledge_mesh = extract_lines_iter_ledge_mesh,
     .finish = extract_lines_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -822,10 +1081,10 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void
 
 static const MeshExtract extract_lines_with_lines_loose = {
     .init = extract_lines_init,
-    .iter_loop_bm = extract_lines_loop_bmesh,
-    .iter_loop_mesh = extract_lines_loop_mesh,
-    .iter_ledge_bm = extract_lines_ledge_bmesh,
-    .iter_ledge_mesh = extract_lines_ledge_mesh,
+    .iter_poly_bm = extract_lines_iter_poly_bm,
+    .iter_poly_mesh = extract_lines_iter_poly_mesh,
+    .iter_ledge_bm = extract_lines_iter_ledge_bm,
+    .iter_ledge_mesh = extract_lines_iter_ledge_mesh,
     .finish = extract_lines_with_lines_loose_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -844,77 +1103,101 @@ static void *extract_points_init(const MeshRenderData *mr, void *UNUSED(buf))
   return elb;
 }
 
-BLI_INLINE void vert_set_bmesh(GPUIndexBufBuilder *elb, BMVert *eve, int loop)
+BLI_INLINE void vert_set_bm(GPUIndexBufBuilder *elb, BMVert *eve, int l_index)
 {
-  int vert_idx = BM_elem_index_get(eve);
+  const int v_index = BM_elem_index_get(eve);
   if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
-    GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
+    GPU_indexbuf_set_point_vert(elb, v_index, l_index);
   }
   else {
-    GPU_indexbuf_set_point_restart(elb, vert_idx);
+    GPU_indexbuf_set_point_restart(elb, v_index);
   }
 }
 
 BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb,
                               const MeshRenderData *mr,
-                              int vert_idx,
-                              int loop)
+                              const int v_index,
+                              const int l_index)
 {
-  const MVert *mvert = &mr->mvert[vert_idx];
-  if (!((mr->use_hide && (mvert->flag & ME_HIDE)) ||
+  const MVert *mv = &mr->mvert[v_index];
+  if (!((mr->use_hide && (mv->flag & ME_HIDE)) ||
         ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
-         (mr->v_origindex[vert_idx] == ORIGINDEX_NONE)))) {
-    GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
+         (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) {
+    GPU_indexbuf_set_point_vert(elb, v_index, l_index);
   }
   else {
-    GPU_indexbuf_set_point_restart(elb, vert_idx);
+    GPU_indexbuf_set_point_restart(elb, v_index);
   }
 }
 
-static void extract_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                      int l,
-                                      BMLoop *loop,
-                                      void *elb)
+static void extract_points_iter_poly_bm(const MeshRenderData *mr,
+                                        const ExtractPolyBMesh_Params *params,
+                                        void *elb)
 {
-  vert_set_bmesh(elb, loop->v, l);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    vert_set_bm(elb, l->v, l_index);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_points_loop_mesh(const MeshRenderData *mr,
-                                     int l,
-                                     const MLoop *mloop,
-                                     int UNUSED(p),
-                                     const MPoly *UNUSED(mpoly),
-                                     void *elb)
+static void extract_points_iter_poly_mesh(const MeshRenderData *mr,
+                                          const ExtractPolyMesh_Params *params,
+                                          void *elb)
 {
-  vert_set_mesh(elb, mr, mloop->v, l);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    vert_set_mesh(elb, mr, ml->v, ml_index);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_points_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
+static void extract_points_iter_ledge_bm(const MeshRenderData *mr,
+                                         const ExtractLEdgeBMesh_Params *params,
+                                         void *elb)
 {
-  vert_set_bmesh(elb, eed->v1, mr->loop_len + e * 2);
-  vert_set_bmesh(elb, eed->v2, mr->loop_len + e * 2 + 1);
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    vert_set_bm(elb, eed->v1, mr->loop_len + (ledge_index * 2));
+    vert_set_bm(elb, eed->v2, mr->loop_len + (ledge_index * 2) + 1);
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_points_ledge_mesh(const MeshRenderData *mr,
-                                      int e,
-                                      const MEdge *medge,
-                                      void *elb)
+static void extract_points_iter_ledge_mesh(const MeshRenderData *mr,
+                                           const ExtractLEdgeMesh_Params *params,
+                                           void *elb)
 {
-  vert_set_mesh(elb, mr, medge->v1, mr->loop_len + e * 2);
-  vert_set_mesh(elb, mr, medge->v2, mr->loop_len + e * 2 + 1);
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    vert_set_mesh(elb, mr, med->v1, mr->loop_len + (ledge_index * 2));
+    vert_set_mesh(elb, mr, med->v2, mr->loop_len + (ledge_index * 2) + 1);
+  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
-static void extract_points_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *elb)
+static void extract_points_iter_lvert_bm(const MeshRenderData *mr,
+                                         const ExtractLVertBMesh_Params *params,
+                                         void *elb)
 {
-  vert_set_bmesh(elb, eve, mr->loop_len + mr->edge_loose_len * 2 + v);
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+  {
+    vert_set_bm(elb, eve, offset + lvert_index);
+  }
+  EXTRACT_LVERT_FOREACH_BM_END;
 }
 
-static void extract_points_lvert_mesh(const MeshRenderData *mr,
-                                      int v,
-                                      const MVert *UNUSED(mvert),
-                                      void *elb)
+static void extract_points_iter_lvert_mesh(const MeshRenderData *mr,
+                                           const ExtractLVertMesh_Params *params,
+                                           void *elb)
 {
-  vert_set_mesh(elb, mr, mr->lverts[v], mr->loop_len + mr->edge_loose_len * 2 + v);
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+  {
+    vert_set_mesh(elb, mr, mr->lverts[lvert_index], offset + lvert_index);
+  }
+  EXTRACT_LVERT_FOREACH_MESH_END;
 }
 
 static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
@@ -925,12 +1208,12 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, v
 
 static const MeshExtract extract_points = {
     .init = extract_points_init,
-    .iter_loop_bm = extract_points_loop_bmesh,
-    .iter_loop_mesh = extract_points_loop_mesh,
-    .iter_ledge_bm = extract_points_ledge_bmesh,
-    .iter_ledge_mesh = extract_points_ledge_mesh,
-    .iter_lvert_bm = extract_points_lvert_bmesh,
-    .iter_lvert_mesh = extract_points_lvert_mesh,
+    .iter_poly_bm = extract_points_iter_poly_bm,
+    .iter_poly_mesh = extract_points_iter_poly_mesh,
+    .iter_ledge_bm = extract_points_iter_ledge_bm,
+    .iter_ledge_mesh = extract_points_iter_ledge_mesh,
+    .iter_lvert_bm = extract_points_iter_lvert_bm,
+    .iter_lvert_mesh = extract_points_iter_lvert_mesh,
     .finish = extract_points_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -949,34 +1232,51 @@ static void *extract_fdots_init(const MeshRenderData *mr, void *UNUSED(buf))
   return elb;
 }
 
-static void extract_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                     int UNUSED(l),
-                                     BMLoop *loop,
-                                     void *elb)
+static void extract_fdots_iter_poly_bm(const MeshRenderData *mr,
+                                       const ExtractPolyBMesh_Params *params,
+                                       void *elb)
 {
-  int face_idx = BM_elem_index_get(loop->f);
-  if (!BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN)) {
-    GPU_indexbuf_set_point_vert(elb, face_idx, face_idx);
-  }
-  else {
-    GPU_indexbuf_set_point_restart(elb, face_idx);
+  EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+  {
+    if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+      GPU_indexbuf_set_point_vert(elb, f_index, f_index);
+    }
+    else {
+      GPU_indexbuf_set_point_restart(elb, f_index);
+    }
   }
+  EXTRACT_POLY_FOREACH_BM_END;
 }
 
-static void extract_fdots_loop_mesh(const MeshRenderData *mr,
-                                    int UNUSED(l),
-                                    const MLoop *mloop,
-                                    int p,
-                                    const MPoly *mpoly,
-                                    void *elb)
+static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
+                                         const ExtractPolyMesh_Params *params,
+                                         void *elb)
 {
-  const MVert *mvert = &mr->mvert[mloop->v];
-  if ((!mr->use_subsurf_fdots || (mvert->flag & ME_VERT_FACEDOT)) &&
-      !(mr->use_hide && (mpoly->flag & ME_HIDE))) {
-    GPU_indexbuf_set_point_vert(elb, p, p);
+  if (mr->use_subsurf_fdots) {
+    /* Check #ME_VERT_FACEDOT. */
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      const MVert *mv = &mr->mvert[ml->v];
+      if ((mv->flag & ME_VERT_FACEDOT) && !(mr->use_hide && (mp->flag & ME_HIDE))) {
+        GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
+      }
+      else {
+        GPU_indexbuf_set_point_restart(elb, mp_index);
+      }
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
   }
   else {
-    GPU_indexbuf_set_point_restart(elb, p);
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+        GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
+      }
+      else {
+        GPU_indexbuf_set_point_restart(elb, mp_index);
+      }
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
   }
 }
 
@@ -988,8 +1288,8 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo
 
 static const MeshExtract extract_fdots = {
     .init = extract_fdots_init,
-    .iter_loop_bm = extract_fdots_loop_bmesh,
-    .iter_loop_mesh = extract_fdots_loop_mesh,
+    .iter_poly_bm = extract_fdots_iter_poly_bm,
+    .iter_poly_mesh = extract_fdots_iter_poly_mesh,
     .finish = extract_fdots_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1015,48 +1315,49 @@ static void *extract_lines_paint_mask_init(const MeshRenderData *mr, void *UNUSE
   return data;
 }
 
-static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr,
-                                               int l,
-                                               const MLoop *mloop,
-                                               int UNUSED(p),
-                                               const MPoly *mpoly,
-                                               void *_data)
-{
-  MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
-  const int edge_idx = mloop->e;
-  const MEdge *medge = &mr->medge[edge_idx];
-  if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
-        ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
-         (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
-
-    int loopend = mpoly->totloop + mpoly->loopstart - 1;
-    int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
-    if (mpoly->flag & ME_FACE_SEL) {
-      if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) {
-        /* Hide edge as it has more than 2 selected loop. */
-        GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
+static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
+                                                    const ExtractPolyMesh_Params *params,
+                                                    void *_data)
+{
+  MeshExtract_LinePaintMask_Data *data = _data;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    const int e_index = ml->e;
+    const MEdge *me = &mr->medge[e_index];
+    if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
+          ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+           (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
+
+      const int ml_index_last = mp->totloop + mp->loopstart - 1;
+      const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+      if (mp->flag & ME_FACE_SEL) {
+        if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) {
+          /* Hide edge as it has more than 2 selected loop. */
+          GPU_indexbuf_set_line_restart(&data->elb, e_index);
+        }
+        else {
+          /* First selected loop. Set edge visible, overwriting any unselected loop. */
+          GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
+        }
       }
       else {
-        /* First selected loop. Set edge visible, overwriting any unselected loop. */
-        GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
+        /* Set theses unselected loop only if this edge has no other selected loop. */
+        if (!BLI_BITMAP_TEST(data->select_map, e_index)) {
+          GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
+        }
       }
     }
     else {
-      /* Set theses unselected loop only if this edge has no other selected loop. */
-      if (!BLI_BITMAP_TEST(data->select_map, edge_idx)) {
-        GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
-      }
+      GPU_indexbuf_set_line_restart(&data->elb, e_index);
     }
   }
-  else {
-    GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
-  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
                                             void *ibo,
                                             void *_data)
 {
-  MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
+  MeshExtract_LinePaintMask_Data *data = _data;
 
   GPU_indexbuf_build_in_place(&data->elb, ibo);
   MEM_freeN(data);
@@ -1064,7 +1365,7 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
 
 static const MeshExtract extract_lines_paint_mask = {
     .init = extract_lines_paint_mask_init,
-    .iter_loop_mesh = extract_lines_paint_mask_loop_mesh,
+    .iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh,
     .finish = extract_lines_paint_mask_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1143,42 +1444,48 @@ BLI_INLINE void lines_adjacency_triangle(
   }
 }
 
-static void extract_lines_adjacency_looptri_bmesh(const MeshRenderData *UNUSED(mr),
-                                                  int UNUSED(t),
-                                                  BMLoop **elt,
-                                                  void *data)
+static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
+                                                    const struct ExtractTriBMesh_Params *params,
+                                                    void *data)
 {
-  if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
-    lines_adjacency_triangle(BM_elem_index_get(elt[0]->v),
-                             BM_elem_index_get(elt[1]->v),
-                             BM_elem_index_get(elt[2]->v),
-                             BM_elem_index_get(elt[0]),
-                             BM_elem_index_get(elt[1]),
-                             BM_elem_index_get(elt[2]),
-                             data);
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+  {
+    if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
+      lines_adjacency_triangle(BM_elem_index_get(elt[0]->v),
+                               BM_elem_index_get(elt[1]->v),
+                               BM_elem_index_get(elt[2]->v),
+                               BM_elem_index_get(elt[0]),
+                               BM_elem_index_get(elt[1]),
+                               BM_elem_index_get(elt[2]),
+                               data);
+    }
   }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
 }
 
-static void extract_lines_adjacency_looptri_mesh(const MeshRenderData *mr,
-                                                 int UNUSED(t),
-                                                 const MLoopTri *mlt,
-                                                 void *data)
+static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr,
+                                                      const struct ExtractTriMesh_Params *params,
+                                                      void *data)
 {
-  const MPoly *mpoly = &mr->mpoly[mlt->poly];
-  if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
-    lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
-                             mr->mloop[mlt->tri[1]].v,
-                             mr->mloop[mlt->tri[2]].v,
-                             mlt->tri[0],
-                             mlt->tri[1],
-                             mlt->tri[2],
-                             data);
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+  {
+    const MPoly *mp = &mr->mpoly[mlt->poly];
+    if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+      lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
+                               mr->mloop[mlt->tri[1]].v,
+                               mr->mloop[mlt->tri[2]].v,
+                               mlt->tri[0],
+                               mlt->tri[1],
+                               mlt->tri[2],
+                               data);
+    }
   }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
 }
 
 static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, void *_data)
 {
-  MeshExtract_LineAdjacency_Data *data = (MeshExtract_LineAdjacency_Data *)_data;
+  MeshExtract_LineAdjacency_Data *data = _data;
   /* Create edges for remaining non manifold edges. */
   EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh);
   for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
@@ -1209,8 +1516,8 @@ static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo,
 
 static const MeshExtract extract_lines_adjacency = {
     .init = extract_lines_adjacency_init,
-    .iter_looptri_bm = extract_lines_adjacency_looptri_bmesh,
-    .iter_looptri_mesh = extract_lines_adjacency_looptri_mesh,
+    .iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm,
+    .iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh,
     .finish = extract_lines_adjacency_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1243,44 +1550,50 @@ BLI_INLINE void edituv_tri_add(
   }
 }
 
-static void extract_edituv_tris_looptri_bmesh(const MeshRenderData *UNUSED(mr),
-                                              int UNUSED(t),
-                                              BMLoop **elt,
-                                              void *data)
+static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
+                                                const struct ExtractTriBMesh_Params *params,
+                                                void *data)
 {
-  edituv_tri_add(data,
-                 BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
-                 BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
-                 BM_elem_index_get(elt[0]),
-                 BM_elem_index_get(elt[1]),
-                 BM_elem_index_get(elt[2]));
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+  {
+    edituv_tri_add(data,
+                   BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
+                   BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
+                   BM_elem_index_get(elt[0]),
+                   BM_elem_index_get(elt[1]),
+                   BM_elem_index_get(elt[2]));
+  }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
 }
 
-static void extract_edituv_tris_looptri_mesh(const MeshRenderData *mr,
-                                             int UNUSED(t),
-                                             const MLoopTri *mlt,
-                                             void *data)
+static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr,
+                                                  const struct ExtractTriMesh_Params *params,
+                                                  void *data)
 {
-  const MPoly *mpoly = &mr->mpoly[mlt->poly];
-  edituv_tri_add(data,
-                 (mpoly->flag & ME_HIDE) != 0,
-                 (mpoly->flag & ME_FACE_SEL) != 0,
-                 mlt->tri[0],
-                 mlt->tri[1],
-                 mlt->tri[2]);
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+  {
+    const MPoly *mp = &mr->mpoly[mlt->poly];
+    edituv_tri_add(data,
+                   (mp->flag & ME_HIDE) != 0,
+                   (mp->flag & ME_FACE_SEL) != 0,
+                   mlt->tri[0],
+                   mlt->tri[1],
+                   mlt->tri[2]);
+  }
+  EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
 }
 
 static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
 {
-  MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+  MeshExtract_EditUvElem_Data *extract_data = data;
   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
   MEM_freeN(extract_data);
 }
 
 static const MeshExtract extract_edituv_tris = {
     .init = extract_edituv_tris_init,
-    .iter_looptri_bm = extract_edituv_tris_looptri_bmesh,
-    .iter_looptri_mesh = extract_edituv_tris_looptri_mesh,
+    .iter_looptri_bm = extract_edituv_tris_iter_looptri_bm,
+    .iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh,
     .finish = extract_edituv_tris_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1309,46 +1622,50 @@ BLI_INLINE void edituv_edge_add(
   }
 }
 
-static void extract_edituv_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                            int l,
-                                            BMLoop *loop,
-                                            void *data)
+static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *mr,
+                                              const ExtractPolyBMesh_Params *params,
+                                              void *data)
 {
-  edituv_edge_add(data,
-                  BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
-                  BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
-                  l,
-                  BM_elem_index_get(loop->next));
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
+  {
+    edituv_edge_add(data,
+                    BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
+                    BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
+                    l_index,
+                    BM_elem_index_get(loop->next));
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
 }
 
-static void extract_edituv_lines_loop_mesh(const MeshRenderData *mr,
-                                           int loop_idx,
-                                           const MLoop *mloop,
-                                           int UNUSED(p),
-                                           const MPoly *mpoly,
-                                           void *data)
+static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
+                                                const ExtractPolyMesh_Params *params,
+                                                void *data)
 {
-  int loopend = mpoly->totloop + mpoly->loopstart - 1;
-  int loop_next_idx = (loop_idx == loopend) ? mpoly->loopstart : (loop_idx + 1);
-  const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[mloop->e] != ORIGINDEX_NONE);
-  edituv_edge_add(data,
-                  (mpoly->flag & ME_HIDE) != 0 || !real_edge,
-                  (mpoly->flag & ME_FACE_SEL) != 0,
-                  loop_idx,
-                  loop_next_idx);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    const int ml_index_last = mp->totloop + mp->loopstart - 1;
+    const int ml_index_next = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+    const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[ml->e] != ORIGINDEX_NONE);
+    edituv_edge_add(data,
+                    (mp->flag & ME_HIDE) != 0 || !real_edge,
+                    (mp->flag & ME_FACE_SEL) != 0,
+                    ml_index,
+                    ml_index_next);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
 {
-  MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+  MeshExtract_EditUvElem_Data *extract_data = data;
   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
   MEM_freeN(extract_data);
 }
 
 static const MeshExtract extract_edituv_lines = {
     .init = extract_edituv_lines_init,
-    .iter_loop_bm = extract_edituv_lines_loop_bmesh,
-    .iter_loop_mesh = extract_edituv_lines_loop_mesh,
+    .iter_poly_bm = extract_edituv_lines_iter_poly_bm,
+    .iter_poly_mesh = extract_edituv_lines_iter_poly_mesh,
     .finish = extract_edituv_lines_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1379,41 +1696,45 @@ BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data,
   }
 }
 
-static void extract_edituv_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                             int l,
-                                             BMLoop *loop,
-                                             void *data)
+static void extract_edituv_points_iter_poly_bm(const MeshRenderData *mr,
+                                               const ExtractPolyBMesh_Params *params,
+                                               void *data)
 {
-  edituv_point_add(data,
-                   BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
-                   BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
-                   l);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    edituv_point_add(data,
+                     BM_elem_flag_test(l->f, BM_ELEM_HIDDEN),
+                     BM_elem_flag_test(l->f, BM_ELEM_SELECT),
+                     l_index);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_edituv_points_loop_mesh(const MeshRenderData *mr,
-                                            int l,
-                                            const MLoop *mloop,
-                                            int UNUSED(p),
-                                            const MPoly *mpoly,
-                                            void *data)
+static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr,
+                                                 const ExtractPolyMesh_Params *params,
+                                                 void *data)
 {
-  const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
-                          mr->v_origindex[mloop->v] != ORIGINDEX_NONE);
-  edituv_point_add(
-      data, ((mpoly->flag & ME_HIDE) != 0) || !real_vert, (mpoly->flag & ME_FACE_SEL) != 0, l);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
+                            mr->v_origindex[ml->v] != ORIGINDEX_NONE);
+    edituv_point_add(
+        data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
 {
-  MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+  MeshExtract_EditUvElem_Data *extract_data = data;
   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
   MEM_freeN(extract_data);
 }
 
 static const MeshExtract extract_edituv_points = {
     .init = extract_edituv_points_init,
-    .iter_loop_bm = extract_edituv_points_loop_bmesh,
-    .iter_loop_mesh = extract_edituv_points_loop_mesh,
+    .iter_poly_bm = extract_edituv_points_iter_poly_bm,
+    .iter_poly_mesh = extract_edituv_points_iter_poly_mesh,
     .finish = extract_edituv_points_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1437,55 +1758,72 @@ static void *extract_edituv_fdots_init(const MeshRenderData *mr, void *UNUSED(ib
 BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data,
                                    bool hidden,
                                    bool selected,
-                                   int face_idx)
+                                   int face_index)
 {
   if (!hidden && (data->sync_selection || selected)) {
-    GPU_indexbuf_set_point_vert(&data->elb, face_idx, face_idx);
+    GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index);
   }
   else {
-    GPU_indexbuf_set_point_restart(&data->elb, face_idx);
+    GPU_indexbuf_set_point_restart(&data->elb, face_index);
   }
 }
 
-static void extract_edituv_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                            int UNUSED(l),
-                                            BMLoop *loop,
-                                            void *data)
+static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *mr,
+                                              const ExtractPolyBMesh_Params *params,
+                                              void *data)
 {
-  edituv_facedot_add(data,
-                     BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
-                     BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
-                     BM_elem_index_get(loop->f));
+  EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+  {
+    edituv_facedot_add(
+        data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), f_index);
+  }
+  EXTRACT_POLY_FOREACH_BM_END;
 }
 
-static void extract_edituv_fdots_loop_mesh(const MeshRenderData *mr,
-                                           int UNUSED(l),
-                                           const MLoop *mloop,
-                                           int p,
-                                           const MPoly *mpoly,
-                                           void *data)
+static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
+                                                const ExtractPolyMesh_Params *params,
+                                                void *data)
 {
-  const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
-                          mr->p_origindex[p] != ORIGINDEX_NONE);
-  const bool subd_fdot = (!mr->use_subsurf_fdots ||
-                          (mr->mvert[mloop->v].flag & ME_VERT_FACEDOT) != 0);
-  edituv_facedot_add(data,
-                     ((mpoly->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
-                     (mpoly->flag & ME_FACE_SEL) != 0,
-                     p);
+  if (mr->use_subsurf_fdots) {
+    /* Check #ME_VERT_FACEDOT. */
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+                              mr->p_origindex[mp_index] != ORIGINDEX_NONE);
+      const bool subd_fdot = (!mr->use_subsurf_fdots ||
+                              (mr->mvert[ml->v].flag & ME_VERT_FACEDOT) != 0);
+      edituv_facedot_add(data,
+                         ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
+                         (mp->flag & ME_FACE_SEL) != 0,
+                         mp_index);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+  }
+  else {
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+                              mr->p_origindex[mp_index] != ORIGINDEX_NONE);
+      edituv_facedot_add(data,
+                         ((mp->flag & ME_HIDE) != 0) || !real_fdot,
+                         (mp->flag & ME_FACE_SEL) != 0,
+                         mp_index);
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
+  }
 }
 
 static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *_data)
 {
-  MeshExtract_EditUvElem_Data *data = (MeshExtract_EditUvElem_Data *)_data;
+  MeshExtract_EditUvElem_Data *data = _data;
   GPU_indexbuf_build_in_place(&data->elb, ibo);
   MEM_freeN(data);
 }
 
 static const MeshExtract extract_edituv_fdots = {
     .init = extract_edituv_fdots_init,
-    .iter_loop_bm = extract_edituv_fdots_loop_bmesh,
-    .iter_loop_mesh = extract_edituv_fdots_loop_mesh,
+    .iter_poly_bm = extract_edituv_fdots_iter_poly_bm,
+    .iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh,
     .finish = extract_edituv_fdots_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -1535,95 +1873,122 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
     }
   }
   else {
-    const MVert *mvert = mr->mvert;
-    for (int v = 0; v < mr->vert_len; v++, mvert++) {
-      data->packed_nor[v] = GPU_normal_convert_i10_s3(mvert->no);
+    const MVert *mv = mr->mvert;
+    for (int v = 0; v < mr->vert_len; v++, mv++) {
+      data->packed_nor[v] = GPU_normal_convert_i10_s3(mv->no);
     }
   }
   return data;
 }
 
-static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
+static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
+                                         const ExtractPolyBMesh_Params *params,
+                                         void *_data)
 {
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v));
-  vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
-  BMFace *efa = loop->f;
-  vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    PosNorLoop *vert = &data->vbo_data[l_index];
+    copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v));
+    vert->nor = data->packed_nor[BM_elem_index_get(l->v)];
+    BMFace *efa = l->f;
+    vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
-                                      int l,
-                                      const MLoop *mloop,
-                                      int UNUSED(p),
-                                      const MPoly *mpoly,
-                                      void *_data)
+static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
+                                           const ExtractPolyMesh_Params *params,
+                                           void *_data)
 {
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  const MVert *mvert = &mr->mvert[mloop->v];
-  copy_v3_v3(vert->pos, mvert->co);
-  vert->nor = data->packed_nor[mloop->v];
-  /* Flag for paint mode overlay. */
-  if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE ||
-      ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
-       (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) {
-    vert->nor.w = -1;
-  }
-  else if (mvert->flag & SELECT) {
-    vert->nor.w = 1;
-  }
-  else {
-    vert->nor.w = 0;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    PosNorLoop *vert = &data->vbo_data[ml_index];
+    const MVert *mv = &mr->mvert[ml->v];
+    copy_v3_v3(vert->pos, mv->co);
+    vert->nor = data->packed_nor[ml->v];
+    /* Flag for paint mode overlay. */
+    if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
+        ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
+         (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
+      vert->nor.w = -1;
+    }
+    else if (mv->flag & SELECT) {
+      vert->nor.w = 1;
+    }
+    else {
+      vert->nor.w = 0;
+    }
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data)
+static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr,
+                                          const ExtractLEdgeBMesh_Params *params,
+                                          void *_data)
 {
-  int l = mr->loop_len + e * 2;
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
-  copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
-  vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
-  vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    int l_index = mr->loop_len + ledge_index * 2;
+    PosNorLoop *vert = &data->vbo_data[l_index];
+    copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+    copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
+    vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
+    vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_pos_nor_ledge_mesh(const MeshRenderData *mr,
-                                       int e,
-                                       const MEdge *medge,
-                                       void *_data)
+static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr,
+                                            const ExtractLEdgeMesh_Params *params,
+                                            void *_data)
 {
-  int l = mr->loop_len + e * 2;
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  copy_v3_v3(vert[0].pos, mr->mvert[medge->v1].co);
-  copy_v3_v3(vert[1].pos, mr->mvert[medge->v2].co);
-  vert[0].nor = data->packed_nor[medge->v1];
-  vert[1].nor = data->packed_nor[medge->v2];
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    const int ml_index = mr->loop_len + ledge_index * 2;
+    PosNorLoop *vert = &data->vbo_data[ml_index];
+    copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
+    copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
+    vert[0].nor = data->packed_nor[med->v1];
+    vert[1].nor = data->packed_nor[med->v2];
+  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
-static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *_data)
+static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr,
+                                          const ExtractLVertBMesh_Params *params,
+                                          void *_data)
 {
-  int l = mr->loop_len + mr->edge_loose_len * 2 + v;
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
-  vert->nor = data->packed_nor[BM_elem_index_get(eve)];
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+  {
+    const int l_index = offset + lvert_index;
+    PosNorLoop *vert = &data->vbo_data[l_index];
+    copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
+    vert->nor = data->packed_nor[BM_elem_index_get(eve)];
+  }
+  EXTRACT_LVERT_FOREACH_BM_END;
 }
 
-static void extract_pos_nor_lvert_mesh(const MeshRenderData *mr,
-                                       int v,
-                                       const MVert *mvert,
-                                       void *_data)
+static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr,
+                                            const ExtractLVertMesh_Params *params,
+                                            void *_data)
 {
-  int l = mr->loop_len + mr->edge_loose_len * 2 + v;
-  int v_idx = mr->lverts[v];
   MeshExtract_PosNor_Data *data = _data;
-  PosNorLoop *vert = data->vbo_data + l;
-  copy_v3_v3(vert->pos, mvert->co);
-  vert->nor = data->packed_nor[v_idx];
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+  {
+    const int ml_index = offset + lvert_index;
+    const int v_index = mr->lverts[lvert_index];
+    PosNorLoop *vert = &data->vbo_data[ml_index];
+    copy_v3_v3(vert->pos, mv->co);
+    vert->nor = data->packed_nor[v_index];
+  }
+  EXTRACT_LVERT_FOREACH_MESH_END;
 }
 
 static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(vbo), void *data)
@@ -1633,12 +1998,12 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
 
 static const MeshExtract extract_pos_nor = {
     .init = extract_pos_nor_init,
-    .iter_loop_bm = extract_pos_nor_loop_bmesh,
-    .iter_loop_mesh = extract_pos_nor_loop_mesh,
-    .iter_ledge_bm = extract_pos_nor_ledge_bmesh,
-    .iter_ledge_mesh = extract_pos_nor_ledge_mesh,
-    .iter_lvert_bm = extract_pos_nor_lvert_bmesh,
-    .iter_lvert_mesh = extract_pos_nor_lvert_mesh,
+    .iter_poly_bm = extract_pos_nor_iter_poly_bm,
+    .iter_poly_mesh = extract_pos_nor_iter_poly_mesh,
+    .iter_ledge_bm = extract_pos_nor_iter_ledge_bm,
+    .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh,
+    .iter_lvert_bm = extract_pos_nor_iter_lvert_bm,
+    .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh,
     .finish = extract_pos_nor_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -1667,53 +2032,69 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr, void *buf)
   return vbo->data;
 }
 
-static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
+static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
+                                         const ExtractPolyBMesh_Params *params,
+                                         void *data)
 {
   if (mr->loop_normals) {
-    normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
-  }
-  else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
-    normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v));
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(_l, l_index, params, mr)
+    {
+      normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(_l);
   }
   else {
-    normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f));
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+    {
+      if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) {
+        normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l->v));
+      }
+      else {
+        normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, l->f));
+      }
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
   }
 }
 
-static void extract_lnor_hq_loop_mesh(
-    const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
+static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
+                                           const ExtractPolyMesh_Params *params,
+                                           void *data)
 {
-  gpuHQNor *lnor_data = &((gpuHQNor *)data)[l];
-  if (mr->loop_normals) {
-    normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]);
-  }
-  else if (mpoly->flag & ME_SMOOTH) {
-    copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no);
-  }
-  else {
-    normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]);
-  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index];
+    if (mr->loop_normals) {
+      normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
+    }
+    else if (mp->flag & ME_SMOOTH) {
+      copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
+    }
+    else {
+      normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
+    }
 
-  /* Flag for paint mode overlay.
-   * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
-   * In paint mode it will use the un-mapped data to draw the wire-frame. */
-  if (mpoly->flag & ME_HIDE ||
-      (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
-       mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
-    lnor_data->w = -1;
-  }
-  else if (mpoly->flag & ME_FACE_SEL) {
-    lnor_data->w = 1;
-  }
-  else {
-    lnor_data->w = 0;
+    /* Flag for paint mode overlay.
+     * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+     * In paint mode it will use the un-mapped data to draw the wire-frame. */
+    if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+                               (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+      lnor_data->w = -1;
+    }
+    else if (mp->flag & ME_FACE_SEL) {
+      lnor_data->w = 1;
+    }
+    else {
+      lnor_data->w = 0;
+    }
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static const MeshExtract extract_lnor_hq = {
     .init = extract_lnor_hq_init,
-    .iter_loop_bm = extract_lnor_hq_loop_bmesh,
-    .iter_loop_mesh = extract_lnor_hq_loop_mesh,
+    .iter_poly_bm = extract_lnor_hq_iter_poly_bm,
+    .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh,
     .data_flag = MR_DATA_LOOP_NOR,
     .use_threading = true,
 };
@@ -1737,55 +2118,73 @@ static void *extract_lnor_init(const MeshRenderData *mr, void *buf)
   return vbo->data;
 }
 
-static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
+static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
+                                      const ExtractPolyBMesh_Params *params,
+                                      void *data)
 {
   if (mr->loop_normals) {
-    ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
-  }
-  else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
-    ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+    {
+      ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]);
+      BMFace *efa = l->f;
+      ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
   }
   else {
-    ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f));
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+    {
+      if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) {
+        ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l->v));
+      }
+      else {
+        ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, l->f));
+      }
+      BMFace *efa = l->f;
+      ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
   }
-  BMFace *efa = loop->f;
-  ((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
 }
 
-static void extract_lnor_loop_mesh(
-    const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
+static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
+                                        const ExtractPolyMesh_Params *params,
+                                        void *data)
 {
-  GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l];
-  if (mr->loop_normals) {
-    *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
-  }
-  else if (mpoly->flag & ME_SMOOTH) {
-    *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no);
-  }
-  else {
-    *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
-  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index];
+    if (mr->loop_normals) {
+      *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
+    }
+    else if (mp->flag & ME_SMOOTH) {
+      *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
+    }
+    else {
+      *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
+    }
 
-  /* Flag for paint mode overlay.
-   * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
-   * In paint mode it will use the un-mapped data to draw the wire-frame. */
-  if (mpoly->flag & ME_HIDE ||
-      (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
-       mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
-    lnor_data->w = -1;
-  }
-  else if (mpoly->flag & ME_FACE_SEL) {
-    lnor_data->w = 1;
-  }
-  else {
-    lnor_data->w = 0;
+    /* Flag for paint mode overlay.
+     * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+     * In paint mode it will use the un-mapped data to draw the wire-frame. */
+    if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+                               (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+      lnor_data->w = -1;
+    }
+    else if (mp->flag & ME_FACE_SEL) {
+      lnor_data->w = 1;
+    }
+    else {
+      lnor_data->w = 0;
+    }
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static const MeshExtract extract_lnor = {
     .init = extract_lnor_init,
-    .iter_loop_bm = extract_lnor_loop_bmesh,
-    .iter_loop_mesh = extract_lnor_loop_mesh,
+    .iter_poly_bm = extract_lnor_iter_poly_bm,
+    .iter_poly_mesh = extract_lnor_iter_poly_mesh,
     .data_flag = MR_DATA_LOOP_NOR,
     .use_threading = true,
 };
@@ -1871,7 +2270,7 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
       }
       else {
         MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
-        for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) {
+        for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
           memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
         }
       }
@@ -1946,9 +2345,9 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
       }
     }
     else {
-      const MVert *mvert = mr->mvert;
-      for (int v = 0; v < mr->vert_len; v++, mvert++) {
-        copy_v3_v3(orco[v], mvert->co);
+      const MVert *mv = mr->mvert;
+      for (int v = 0; v < mr->vert_len; v++, mv++) {
+        copy_v3_v3(orco[v], mv->co);
       }
     }
     BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0);
@@ -2023,17 +2422,17 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
     for (int i = 0; i < tan_len; i++) {
       const char *name = tangent_names[i];
       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
-      for (int l = 0; l < mr->loop_len; l++) {
-        normal_float_to_short_v3(*tan_data, layer_data[l]);
-        (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+      for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+        normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+        (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
         tan_data++;
       }
     }
     if (use_orco_tan) {
       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
-      for (int l = 0; l < mr->loop_len; l++) {
-        normal_float_to_short_v3(*tan_data, layer_data[l]);
-        (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+      for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+        normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+        (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
         tan_data++;
       }
     }
@@ -2043,17 +2442,17 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
     for (int i = 0; i < tan_len; i++) {
       const char *name = tangent_names[i];
       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
-      for (int l = 0; l < mr->loop_len; l++) {
-        *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
-        tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
+      for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+        *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+        tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
         tan_data++;
       }
     }
     if (use_orco_tan) {
       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
-      for (int l = 0; l < mr->loop_len; l++) {
-        *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
-        tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
+      for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+        *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+        tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
         tan_data++;
       }
     }
@@ -2192,7 +2591,7 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
       }
       else {
         const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
-        for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
+        for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) {
           vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
           vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
           vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
@@ -2221,11 +2620,11 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
       }
       else {
         MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
-        for (int l = 0; l < mr->loop_len; l++, vcol_data++) {
-          vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[l].v].color[0]);
-          vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[l].v].color[1]);
-          vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[l].v].color[2]);
-          vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[l].v].color[3]);
+        for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) {
+          vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]);
+          vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]);
+          vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]);
+          vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]);
         }
       }
 
@@ -2277,28 +2676,32 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_orco_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                    int l,
-                                    BMLoop *loop,
-                                    void *data)
+static void extract_orco_iter_poly_bm(const MeshRenderData *mr,
+                                      const ExtractPolyBMesh_Params *params,
+                                      void *data)
 {
   MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
-  float *loop_orco = orco_data->vbo_data[l];
-  copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
-  loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
+  {
+    float *loop_orco = orco_data->vbo_data[l_index];
+    copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
+    loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
 }
 
-static void extract_orco_loop_mesh(const MeshRenderData *UNUSED(mr),
-                                   int l,
-                                   const MLoop *mloop,
-                                   int UNUSED(p),
-                                   const MPoly *UNUSED(mpoly),
-                                   void *data)
+static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
+                                        const ExtractPolyMesh_Params *params,
+                                        void *data)
 {
-  MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
-  float *loop_orco = orco_data->vbo_data[l];
-  copy_v3_v3(loop_orco, orco_data->orco[mloop->v]);
-  loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
+    float *loop_orco = orco_data->vbo_data[ml_index];
+    copy_v3_v3(loop_orco, orco_data->orco[ml->v]);
+    loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
@@ -2308,8 +2711,8 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(b
 
 static const MeshExtract extract_orco = {
     .init = extract_orco_init,
-    .iter_loop_bm = extract_orco_loop_bmesh,
-    .iter_loop_mesh = extract_orco_loop_mesh,
+    .iter_poly_bm = extract_orco_iter_poly_bm,
+    .iter_poly_mesh = extract_orco_iter_poly_mesh,
     .finish = extract_orco_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -2363,9 +2766,9 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
 
     /* HACK(fclem) Detecting the need for edge render.
      * We could have a flag in the mesh instead or check the modifier stack. */
-    const MEdge *medge = mr->medge;
-    for (int e = 0; e < mr->edge_len; e++, medge++) {
-      if ((medge->flag & ME_EDGERENDER) == 0) {
+    const MEdge *med = mr->medge;
+    for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
+      if ((med->flag & ME_EDGERENDER) == 0) {
         data->use_edge_render = true;
         break;
       }
@@ -2381,76 +2784,98 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
+static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *_data)
 {
-  MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
-  if (BM_edge_is_manifold(loop->e)) {
-    float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f),
-                                       bm_vert_co_get(mr, loop->v),
-                                       bm_vert_no_get(mr, loop->v),
-                                       bm_vert_co_get(mr, loop->next->v));
-    data->vbo_data[l] = ratio * 253 + 1;
-  }
-  else {
-    data->vbo_data[l] = 255;
+  MeshExtract_EdgeFac_Data *data = _data;
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    if (BM_edge_is_manifold(l->e)) {
+      float ratio = loop_edge_factor_get(bm_face_no_get(mr, l->f),
+                                         bm_vert_co_get(mr, l->v),
+                                         bm_vert_no_get(mr, l->v),
+                                         bm_vert_co_get(mr, l->next->v));
+      data->vbo_data[l_index] = ratio * 253 + 1;
+    }
+    else {
+      data->vbo_data[l_index] = 255;
+    }
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_edge_fac_loop_mesh(
-    const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
+static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *_data)
 {
   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
+
   if (data->use_edge_render) {
-    const MEdge *medge = &mr->medge[mloop->e];
-    data->vbo_data[l] = (medge->flag & ME_EDGERENDER) ? 255 : 0;
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      const MEdge *med = &mr->medge[ml->e];
+      data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0;
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
   }
   else {
-    /* Count loop per edge to detect non-manifold. */
-    if (data->edge_loop_count[mloop->e] < 3) {
-      data->edge_loop_count[mloop->e]++;
-    }
-    if (data->edge_loop_count[mloop->e] == 2) {
-      /* Manifold */
-      int loopend = mpoly->totloop + mpoly->loopstart - 1;
-      int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
-      const MLoop *mloop_next = &mr->mloop[other_loop];
-      const MVert *v1 = &mr->mvert[mloop->v];
-      const MVert *v2 = &mr->mvert[mloop_next->v];
-      float vnor_f[3];
-      normal_short_to_float_v3(vnor_f, v1->no);
-      float ratio = loop_edge_factor_get(mr->poly_normals[p], v1->co, vnor_f, v2->co);
-      data->vbo_data[l] = ratio * 253 + 1;
-    }
-    else {
-      /* Non-manifold */
-      data->vbo_data[l] = 255;
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      /* Count loop per edge to detect non-manifold. */
+      if (data->edge_loop_count[ml->e] < 3) {
+        data->edge_loop_count[ml->e]++;
+      }
+      if (data->edge_loop_count[ml->e] == 2) {
+        /* Manifold */
+        const int ml_index_last = mp->totloop + mp->loopstart - 1;
+        const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+        const MLoop *ml_next = &mr->mloop[ml_index_other];
+        const MVert *v1 = &mr->mvert[ml->v];
+        const MVert *v2 = &mr->mvert[ml_next->v];
+        float vnor_f[3];
+        normal_short_to_float_v3(vnor_f, v1->no);
+        float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
+        data->vbo_data[ml_index] = ratio * 253 + 1;
+      }
+      else {
+        /* Non-manifold */
+        data->vbo_data[ml_index] = 255;
+      }
     }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
   }
 }
 
-static void extract_edge_fac_ledge_bmesh(const MeshRenderData *mr,
-                                         int e,
-                                         BMEdge *UNUSED(eed),
-                                         void *_data)
+static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr,
+                                           const ExtractLEdgeBMesh_Params *params,
+                                           void *_data)
 {
-  MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
-  data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
-  data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
+  MeshExtract_EdgeFac_Data *data = _data;
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255;
+    data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255;
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_edge_fac_ledge_mesh(const MeshRenderData *mr,
-                                        int e,
-                                        const MEdge *UNUSED(edge),
-                                        void *_data)
+static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr,
+                                             const ExtractLEdgeMesh_Params *params,
+                                             void *_data)
 {
-  MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
-  data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
-  data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
+  MeshExtract_EdgeFac_Data *data = _data;
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255;
+    data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255;
+  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
 static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_data)
 {
-  MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
+  MeshExtract_EdgeFac_Data *data = _data;
 
   if (GPU_crappy_amd_driver()) {
     GPUVertBuf *vbo = (GPUVertBuf *)buf;
@@ -2470,8 +2895,8 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_
     GPU_vertbuf_data_alloc(vbo, buf_len);
 
     float *fdata = (float *)vbo->data;
-    for (int l = 0; l < buf_len; l++, fdata++) {
-      *fdata = data->vbo_data[l] / 255.0f;
+    for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) {
+      *fdata = data->vbo_data[ml_index] / 255.0f;
     }
     /* Free old byte data. */
     MEM_freeN(data->vbo_data);
@@ -2481,10 +2906,10 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_
 
 static const MeshExtract extract_edge_fac = {
     .init = extract_edge_fac_init,
-    .iter_loop_bm = extract_edge_fac_loop_bmesh,
-    .iter_loop_mesh = extract_edge_fac_loop_mesh,
-    .iter_ledge_bm = extract_edge_fac_ledge_bmesh,
-    .iter_ledge_mesh = extract_edge_fac_ledge_mesh,
+    .iter_poly_bm = extract_edge_fac_iter_poly_bm,
+    .iter_poly_mesh = extract_edge_fac_iter_poly_mesh,
+    .iter_ledge_bm = extract_edge_fac_iter_ledge_bm,
+    .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh,
     .finish = extract_edge_fac_finish,
     .data_flag = MR_DATA_POLY_NOR,
     .use_threading = false,
@@ -2585,27 +3010,49 @@ static void *extract_weights_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_weights_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                       int l,
-                                       BMLoop *loop,
-                                       void *_data)
+static void extract_weights_iter_poly_bm(const MeshRenderData *mr,
+                                         const ExtractPolyBMesh_Params *params,
+                                         void *_data)
 {
-  MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
-  const MDeformVert *dvert = (data->cd_ofs != -1) ? BM_ELEM_CD_GET_VOID_P(loop->v, data->cd_ofs) :
-                                                    NULL;
-  data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
+  MeshExtract_Weight_Data *data = _data;
+  if (data->cd_ofs != -1) {
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+    {
+      const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l->v, data->cd_ofs);
+      data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+  }
+  else {
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+    {
+      data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+  }
 }
 
-static void extract_weights_loop_mesh(const MeshRenderData *UNUSED(mr),
-                                      int l,
-                                      const MLoop *mloop,
-                                      int UNUSED(p),
-                                      const MPoly *UNUSED(mpoly),
-                                      void *_data)
+static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
+                                           const ExtractPolyMesh_Params *params,
+                                           void *_data)
 {
-  MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
-  const MDeformVert *dvert = data->dvert ? &data->dvert[mloop->v] : NULL;
-  data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
+  MeshExtract_Weight_Data *data = _data;
+  if (data->dvert != NULL) {
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      const MDeformVert *dvert = &data->dvert[ml->v];
+      data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+  }
+  else {
+    const MDeformVert *dvert = NULL;
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+  }
 }
 
 static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
@@ -2615,8 +3062,8 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
 
 static const MeshExtract extract_weights = {
     .init = extract_weights_init,
-    .iter_loop_bm = extract_weights_loop_bmesh,
-    .iter_loop_mesh = extract_weights_loop_mesh,
+    .iter_poly_bm = extract_weights_iter_poly_bm,
+    .iter_poly_mesh = extract_weights_iter_poly_mesh,
     .finish = extract_weights_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -2726,31 +3173,31 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr, BMEdge *eed, Ed
 }
 
 static void mesh_render_data_loop_flag(const MeshRenderData *mr,
-                                       BMLoop *loop,
+                                       BMLoop *l,
                                        const int cd_ofs,
                                        EditLoopData *eattr)
 {
   if (cd_ofs == -1) {
     return;
   }
-  MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+  MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
   if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) {
     eattr->v_flag |= VFLAG_VERT_UV_PINNED;
   }
-  if (uvedit_uv_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
+  if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) {
     eattr->v_flag |= VFLAG_VERT_UV_SELECT;
   }
 }
 
 static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
-                                            BMLoop *loop,
+                                            BMLoop *l,
                                             const int cd_ofs,
                                             EditLoopData *eattr)
 {
   if (cd_ofs == -1) {
     return;
   }
-  if (uvedit_edge_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
+  if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) {
     eattr->v_flag |= VFLAG_EDGE_UV_SELECT;
     eattr->v_flag |= VFLAG_VERT_UV_SELECT;
   }
@@ -2780,109 +3227,128 @@ static void *extract_edit_data_init(const MeshRenderData *mr, void *buf)
   return vbo->data;
 }
 
-static void extract_edit_data_loop_bmesh(const MeshRenderData *mr,
-                                         int l,
-                                         BMLoop *loop,
-                                         void *_data)
+static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
+                                           const ExtractPolyBMesh_Params *params,
+                                           void *_data)
 {
-  EditLoopData *data = (EditLoopData *)_data + l;
-  memset(data, 0x0, sizeof(*data));
-  mesh_render_data_face_flag(mr, loop->f, -1, data);
-  mesh_render_data_edge_flag(mr, loop->e, data);
-  mesh_render_data_vert_flag(mr, loop->v, data);
-}
 
-static void extract_edit_data_loop_mesh(const MeshRenderData *mr,
-                                        int l,
-                                        const MLoop *mloop,
-                                        int p,
-                                        const MPoly *UNUSED(mpoly),
-                                        void *_data)
-{
-  EditLoopData *data = (EditLoopData *)_data + l;
-  memset(data, 0x0, sizeof(*data));
-  BMFace *efa = bm_original_face_get(mr, p);
-  BMEdge *eed = bm_original_edge_get(mr, mloop->e);
-  BMVert *eve = bm_original_vert_get(mr, mloop->v);
-  if (efa) {
-    mesh_render_data_face_flag(mr, efa, -1, data);
-  }
-  if (eed) {
-    mesh_render_data_edge_flag(mr, eed, data);
-  }
-  if (eve) {
-    mesh_render_data_vert_flag(mr, eve, data);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    EditLoopData *data = (EditLoopData *)_data + l_index;
+    memset(data, 0x0, sizeof(*data));
+    mesh_render_data_face_flag(mr, l->f, -1, data);
+    mesh_render_data_edge_flag(mr, l->e, data);
+    mesh_render_data_vert_flag(mr, l->v, data);
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_edit_data_ledge_bmesh(const MeshRenderData *mr,
-                                          int e,
-                                          BMEdge *eed,
-                                          void *_data)
+static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
+                                             const ExtractPolyMesh_Params *params,
+                                             void *_data)
 {
-  EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
-  memset(data, 0x0, sizeof(*data) * 2);
-  mesh_render_data_edge_flag(mr, eed, &data[0]);
-  data[1] = data[0];
-  mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
-  mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    EditLoopData *data = (EditLoopData *)_data + ml_index;
+    memset(data, 0x0, sizeof(*data));
+    BMFace *efa = bm_original_face_get(mr, mp_index);
+    BMEdge *eed = bm_original_edge_get(mr, ml->e);
+    BMVert *eve = bm_original_vert_get(mr, ml->v);
+    if (efa) {
+      mesh_render_data_face_flag(mr, efa, -1, data);
+    }
+    if (eed) {
+      mesh_render_data_edge_flag(mr, eed, data);
+    }
+    if (eve) {
+      mesh_render_data_vert_flag(mr, eve, data);
+    }
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_edit_data_ledge_mesh(const MeshRenderData *mr,
-                                         int e,
-                                         const MEdge *edge,
-                                         void *_data)
+static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr,
+                                            const ExtractLEdgeBMesh_Params *params,
+                                            void *_data)
 {
-  EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
-  memset(data, 0x0, sizeof(*data) * 2);
-  int e_idx = mr->ledges[e];
-  BMEdge *eed = bm_original_edge_get(mr, e_idx);
-  BMVert *eve1 = bm_original_vert_get(mr, edge->v1);
-  BMVert *eve2 = bm_original_vert_get(mr, edge->v2);
-  if (eed) {
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2);
+    memset(data, 0x0, sizeof(*data) * 2);
     mesh_render_data_edge_flag(mr, eed, &data[0]);
     data[1] = data[0];
+    mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
+    mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
+}
+
+static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr,
+                                              const ExtractLEdgeMesh_Params *params,
+                                              void *_data)
+{
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2;
+    memset(data, 0x0, sizeof(*data) * 2);
+    const int e_index = mr->ledges[ledge_index];
+    BMEdge *eed = bm_original_edge_get(mr, e_index);
+    BMVert *eve1 = bm_original_vert_get(mr, med->v1);
+    BMVert *eve2 = bm_original_vert_get(mr, med->v2);
+    if (eed) {
+      mesh_render_data_edge_flag(mr, eed, &data[0]);
+      data[1] = data[0];
+    }
+    if (eve1) {
+      mesh_render_data_vert_flag(mr, eve1, &data[0]);
+    }
+    if (eve2) {
+      mesh_render_data_vert_flag(mr, eve2, &data[1]);
+    }
   }
-  if (eve1) {
-    mesh_render_data_vert_flag(mr, eve1, &data[0]);
-  }
-  if (eve2) {
-    mesh_render_data_vert_flag(mr, eve2, &data[1]);
-  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
-static void extract_edit_data_lvert_bmesh(const MeshRenderData *mr,
-                                          int v,
-                                          BMVert *eve,
-                                          void *_data)
+static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr,
+                                            const ExtractLVertBMesh_Params *params,
+                                            void *_data)
 {
-  EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
-  memset(data, 0x0, sizeof(*data));
-  mesh_render_data_vert_flag(mr, eve, data);
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+  {
+    EditLoopData *data = (EditLoopData *)_data + offset + lvert_index;
+    memset(data, 0x0, sizeof(*data));
+    mesh_render_data_vert_flag(mr, eve, data);
+  }
+  EXTRACT_LVERT_FOREACH_BM_END;
 }
 
-static void extract_edit_data_lvert_mesh(const MeshRenderData *mr,
-                                         int v,
-                                         const MVert *UNUSED(mvert),
-                                         void *_data)
+static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
+                                              const ExtractLVertMesh_Params *params,
+                                              void *_data)
 {
-  EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
-  memset(data, 0x0, sizeof(*data));
-  int v_idx = mr->lverts[v];
-  BMVert *eve = bm_original_vert_get(mr, v_idx);
-  if (eve) {
-    mesh_render_data_vert_flag(mr, eve, data);
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+  {
+    EditLoopData *data = (EditLoopData *)_data + offset + lvert_index;
+    memset(data, 0x0, sizeof(*data));
+    const int v_index = mr->lverts[lvert_index];
+    BMVert *eve = bm_original_vert_get(mr, v_index);
+    if (eve) {
+      mesh_render_data_vert_flag(mr, eve, data);
+    }
   }
+  EXTRACT_LVERT_FOREACH_MESH_END;
 }
 
 static const MeshExtract extract_edit_data = {
     .init = extract_edit_data_init,
-    .iter_loop_bm = extract_edit_data_loop_bmesh,
-    .iter_loop_mesh = extract_edit_data_loop_mesh,
-    .iter_ledge_bm = extract_edit_data_ledge_bmesh,
-    .iter_ledge_mesh = extract_edit_data_ledge_mesh,
-    .iter_lvert_bm = extract_edit_data_lvert_bmesh,
-    .iter_lvert_mesh = extract_edit_data_lvert_mesh,
+    .iter_poly_bm = extract_edit_data_iter_poly_bm,
+    .iter_poly_mesh = extract_edit_data_iter_poly_mesh,
+    .iter_ledge_bm = extract_edit_data_iter_ledge_bm,
+    .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh,
+    .iter_lvert_bm = extract_edit_data_iter_lvert_bm,
+    .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
@@ -2919,51 +3385,59 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_edituv_data_loop_bmesh(const MeshRenderData *mr,
-                                           int l,
-                                           BMLoop *loop,
-                                           void *_data)
+static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+                                             const ExtractPolyBMesh_Params *params,
+                                             void *_data)
 {
-  MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
-  EditLoopData *eldata = data->vbo_data + l;
-  memset(eldata, 0x0, sizeof(*eldata));
-  mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
-  mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata);
-  mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
-}
-
-static void extract_edituv_data_loop_mesh(
-    const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
-{
-  MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
-  EditLoopData *eldata = data->vbo_data + l;
-  memset(eldata, 0x0, sizeof(*eldata));
-  BMFace *efa = bm_original_face_get(mr, p);
-  if (efa) {
-    BMEdge *eed = bm_original_edge_get(mr, mloop->e);
-    BMVert *eve = bm_original_vert_get(mr, mloop->v);
-    if (eed && eve) {
-      /* Loop on an edge endpoint. */
-      BMLoop *loop = BM_face_edge_share_loop(efa, eed);
-      mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
-      mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
-    }
-    else {
-      if (eed == NULL) {
-        /* Find if the loop's vert is not part of an edit edge.
-         * For this, we check if the previous loop was on an edge. */
-        int loopend = mpoly->loopstart + mpoly->totloop - 1;
-        int l_prev = (l == mpoly->loopstart) ? loopend : (l - 1);
-        const MLoop *mloop_prev = &mr->mloop[l_prev];
-        eed = bm_original_edge_get(mr, mloop_prev->e);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    MeshExtract_EditUVData_Data *data = _data;
+    EditLoopData *eldata = &data->vbo_data[l_index];
+    memset(eldata, 0x0, sizeof(*eldata));
+    mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
+    mesh_render_data_face_flag(mr, l->f, data->cd_ofs, eldata);
+    mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+}
+
+static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+                                               const ExtractPolyMesh_Params *params,
+                                               void *_data)
+{
+  MeshExtract_EditUVData_Data *data = _data;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    EditLoopData *eldata = &data->vbo_data[ml_index];
+    memset(eldata, 0x0, sizeof(*eldata));
+    BMFace *efa = bm_original_face_get(mr, mp_index);
+    if (efa) {
+      BMEdge *eed = bm_original_edge_get(mr, ml->e);
+      BMVert *eve = bm_original_vert_get(mr, ml->v);
+      if (eed && eve) {
+        /* Loop on an edge endpoint. */
+        BMLoop *l = BM_face_edge_share_loop(efa, eed);
+        mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
+        mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
       }
-      if (eed) {
-        /* Mapped points on an edge between two edit verts. */
-        BMLoop *loop = BM_face_edge_share_loop(efa, eed);
-        mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
+      else {
+        if (eed == NULL) {
+          /* Find if the loop's vert is not part of an edit edge.
+           * For this, we check if the previous loop was on an edge. */
+          const int ml_index_last = mp->loopstart + mp->totloop - 1;
+          const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1);
+          const MLoop *ml_prev = &mr->mloop[l_prev];
+          eed = bm_original_edge_get(mr, ml_prev->e);
+        }
+        if (eed) {
+          /* Mapped points on an edge between two edit verts. */
+          BMLoop *l = BM_face_edge_share_loop(efa, eed);
+          mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+        }
       }
     }
   }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
@@ -2975,8 +3449,8 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
 
 static const MeshExtract extract_edituv_data = {
     .init = extract_edituv_data_init,
-    .iter_loop_bm = extract_edituv_data_loop_bmesh,
-    .iter_loop_mesh = extract_edituv_data_loop_mesh,
+    .iter_poly_bm = extract_edituv_data_iter_poly_bm,
+    .iter_poly_mesh = extract_edituv_data_iter_poly_mesh,
     .finish = extract_edituv_data_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -3039,13 +3513,13 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
   }
   else if (mr->extract_type == MR_EXTRACT_MAPPED) {
     const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0; p < mr->poly_len; p++, mpoly++) {
-      float area = BKE_mesh_calc_poly_area(mpoly, &mr->mloop[mpoly->loopstart], mr->mvert);
-      float uvarea = BKE_mesh_calc_poly_uv_area(mpoly, uv_data);
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert);
+      float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
       tot_area += area;
       tot_uv_area += uvarea;
-      area_ratio[p] = area_ratio_get(area, uvarea);
+      area_ratio[mp_index] = area_ratio_get(area, uvarea);
     }
   }
   else {
@@ -3058,8 +3532,8 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
 
   /* Convert in place to avoid an extra allocation */
   uint16_t *poly_stretch = (uint16_t *)area_ratio;
-  for (int p = 0; p < mr->poly_len; p++) {
-    poly_stretch[p] = area_ratio[p] * SHRT_MAX;
+  for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+    poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX;
   }
 
   /* Copy face data for each loop. */
@@ -3069,18 +3543,18 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
   if (mr->extract_type == MR_EXTRACT_BMESH) {
     BMFace *efa;
     BMIter f_iter;
-    int f, l = 0;
+    int f, l_index = 0;
     BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
-      for (int i = 0; i < efa->len; i++, l++) {
-        loop_stretch[l] = poly_stretch[f];
+      for (int i = 0; i < efa->len; i++, l_index++) {
+        loop_stretch[l_index] = poly_stretch[f];
       }
     }
   }
   else if (mr->extract_type == MR_EXTRACT_MAPPED) {
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
-      for (int i = 0; i < mpoly->totloop; i++, l++) {
-        loop_stretch[l] = poly_stretch[p];
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      for (int i = 0; i < mp->totloop; i++, l_index++) {
+        loop_stretch[l_index] = poly_stretch[mp_index];
       }
     }
   }
@@ -3186,94 +3660,95 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr,
-                                             int l,
-                                             BMLoop *loop,
-                                             void *_data)
+static void extract_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
+                                               const ExtractPolyBMesh_Params *params,
+                                               void *_data)
 {
-  MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
+  MeshExtract_StretchAngle_Data *data = _data;
   float(*auv)[2] = data->auv, *last_auv = data->last_auv;
   float(*av)[3] = data->av, *last_av = data->last_av;
-  const MLoopUV *luv, *luv_next;
-  BMLoop *l_next = loop->next;
-  BMFace *efa = loop->f;
-  if (loop == BM_FACE_FIRST_LOOP(efa)) {
-    /* First loop in face. */
-    BMLoop *l_tmp = loop->prev;
-    BMLoop *l_next_tmp = loop;
-    luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
-    luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
-    compute_normalize_edge_vectors(auv,
-                                   av,
-                                   luv->uv,
-                                   luv_next->uv,
-                                   bm_vert_co_get(mr, l_tmp->v),
-                                   bm_vert_co_get(mr, l_next_tmp->v));
-    /* Save last edge. */
-    copy_v2_v2(last_auv, auv[1]);
-    copy_v3_v3(last_av, av[1]);
-  }
-  if (l_next == BM_FACE_FIRST_LOOP(efa)) {
-    /* Move previous edge. */
-    copy_v2_v2(auv[0], auv[1]);
-    copy_v3_v3(av[0], av[1]);
-    /* Copy already calculated last edge. */
-    copy_v2_v2(auv[1], last_auv);
-    copy_v3_v3(av[1], last_av);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    const MLoopUV *luv, *luv_next;
+    BMLoop *l_next = l->next;
+    BMFace *efa = l->f;
+    if (l == BM_FACE_FIRST_LOOP(efa)) {
+      /* First loop in face. */
+      BMLoop *l_tmp = l->prev;
+      BMLoop *l_next_tmp = l;
+      luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
+      luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
+      compute_normalize_edge_vectors(auv,
+                                     av,
+                                     luv->uv,
+                                     luv_next->uv,
+                                     bm_vert_co_get(mr, l_tmp->v),
+                                     bm_vert_co_get(mr, l_next_tmp->v));
+      /* Save last edge. */
+      copy_v2_v2(last_auv, auv[1]);
+      copy_v3_v3(last_av, av[1]);
+    }
+    if (l_next == BM_FACE_FIRST_LOOP(efa)) {
+      /* Move previous edge. */
+      copy_v2_v2(auv[0], auv[1]);
+      copy_v3_v3(av[0], av[1]);
+      /* Copy already calculated last edge. */
+      copy_v2_v2(auv[1], last_auv);
+      copy_v3_v3(av[1], last_av);
+    }
+    else {
+      luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs);
+      luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
+      compute_normalize_edge_vectors(
+          auv, av, luv->uv, luv_next->uv, bm_vert_co_get(mr, l->v), bm_vert_co_get(mr, l_next->v));
+    }
+    edituv_get_stretch_angle(auv, av, &data->vbo_data[l_index]);
   }
-  else {
-    luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
-    luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
-    compute_normalize_edge_vectors(auv,
-                                   av,
-                                   luv->uv,
-                                   luv_next->uv,
-                                   bm_vert_co_get(mr, loop->v),
-                                   bm_vert_co_get(mr, l_next->v));
-  }
-  edituv_get_stretch_angle(auv, av, data->vbo_data + l);
-}
-
-static void extract_stretch_angle_loop_mesh(const MeshRenderData *mr,
-                                            int l,
-                                            const MLoop *UNUSED(mloop),
-                                            int UNUSED(p),
-                                            const MPoly *mpoly,
-                                            void *_data)
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+}
+
+static void extract_stretch_angle_iter_poly_mesh(const MeshRenderData *mr,
+                                                 const ExtractPolyMesh_Params *params,
+                                                 void *_data)
 {
-  MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
-  float(*auv)[2] = data->auv, *last_auv = data->last_auv;
-  float(*av)[3] = data->av, *last_av = data->last_av;
-  int l_next = l + 1, loopend = mpoly->loopstart + mpoly->totloop;
-  const MVert *v, *v_next;
-  if (l == mpoly->loopstart) {
-    /* First loop in face. */
-    int l_tmp = loopend - 1;
-    int l_next_tmp = mpoly->loopstart;
-    v = &mr->mvert[mr->mloop[l_tmp].v];
-    v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
-    compute_normalize_edge_vectors(
-        auv, av, data->luv[l_tmp].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
-    /* Save last edge. */
-    copy_v2_v2(last_auv, auv[1]);
-    copy_v3_v3(last_av, av[1]);
-  }
-  if (l_next == loopend) {
-    l_next = mpoly->loopstart;
-    /* Move previous edge. */
-    copy_v2_v2(auv[0], auv[1]);
-    copy_v3_v3(av[0], av[1]);
-    /* Copy already calculated last edge. */
-    copy_v2_v2(auv[1], last_auv);
-    copy_v3_v3(av[1], last_av);
-  }
-  else {
-    v = &mr->mvert[mr->mloop[l].v];
-    v_next = &mr->mvert[mr->mloop[l_next].v];
-    compute_normalize_edge_vectors(
-        auv, av, data->luv[l].uv, data->luv[l_next].uv, v->co, v_next->co);
+  MeshExtract_StretchAngle_Data *data = _data;
+
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    float(*auv)[2] = data->auv, *last_auv = data->last_auv;
+    float(*av)[3] = data->av, *last_av = data->last_av;
+    int l_next = ml_index + 1, ml_index_end = mp->loopstart + mp->totloop;
+    const MVert *v, *v_next;
+    if (ml_index == mp->loopstart) {
+      /* First loop in face. */
+      const int ml_index_last = ml_index_end - 1;
+      const int l_next_tmp = mp->loopstart;
+      v = &mr->mvert[mr->mloop[ml_index_last].v];
+      v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
+      compute_normalize_edge_vectors(
+          auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
+      /* Save last edge. */
+      copy_v2_v2(last_auv, auv[1]);
+      copy_v3_v3(last_av, av[1]);
+    }
+    if (l_next == ml_index_end) {
+      l_next = mp->loopstart;
+      /* Move previous edge. */
+      copy_v2_v2(auv[0], auv[1]);
+      copy_v3_v3(av[0], av[1]);
+      /* Copy already calculated last edge. */
+      copy_v2_v2(auv[1], last_auv);
+      copy_v3_v3(av[1], last_av);
+    }
+    else {
+      v = &mr->mvert[mr->mloop[ml_index].v];
+      v_next = &mr->mvert[mr->mloop[l_next].v];
+      compute_normalize_edge_vectors(
+          auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co);
+    }
+    edituv_get_stretch_angle(auv, av, &data->vbo_data[ml_index]);
   }
-  edituv_get_stretch_angle(auv, av, data->vbo_data + l);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
@@ -3285,8 +3760,8 @@ static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
 
 static const MeshExtract extract_stretch_angle = {
     .init = extract_stretch_angle_init,
-    .iter_loop_bm = extract_stretch_angle_loop_bmesh,
-    .iter_loop_mesh = extract_stretch_angle_loop_mesh,
+    .iter_poly_bm = extract_stretch_angle_iter_poly_bm,
+    .iter_poly_mesh = extract_stretch_angle_iter_poly_mesh,
     .finish = extract_stretch_angle_finish,
     .data_flag = 0,
     .use_threading = false,
@@ -3361,22 +3836,22 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
   normalize_v3(dir);
 
   if (mr->extract_type == MR_EXTRACT_BMESH) {
-    int l = 0;
+    int l_index = 0;
     BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
       float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
       fac = overhang_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < f->len; i++, l++) {
-        r_overhang[l] = fac;
+      for (int i = 0; i < f->len; i++, l_index++) {
+        r_overhang[l_index] = fac;
       }
     }
   }
   else {
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
-      float fac = angle_normalized_v3v3(mr->poly_normals[p], dir) / (float)M_PI;
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI;
       fac = overhang_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < mpoly->totloop; i++, l++) {
-        r_overhang[l] = fac;
+      for (int i = 0; i < mp->totloop; i++, l_index++) {
+        r_overhang[l_index] = fac;
       }
     }
   }
@@ -3476,12 +3951,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
 
     BMIter iter;
     BMFace *f;
-    int l = 0;
+    int l_index = 0;
     BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
       float fac = face_dists[BM_elem_index_get(f)];
       fac = thickness_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < f->len; i++, l++) {
-        r_thickness[l] = fac;
+      for (int i = 0; i < f->len; i++, l_index++) {
+        r_thickness[l_index] = fac;
       }
     }
   }
@@ -3522,12 +3997,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
       }
     }
 
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
-      float fac = face_dists[p];
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      float fac = face_dists[mp_index];
       fac = thickness_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < mpoly->totloop; i++, l++) {
-        r_thickness[l] = fac;
+      for (int i = 0; i < mp->totloop; i++, l_index++) {
+        r_thickness[l_index] = fac;
       }
     }
   }
@@ -3578,8 +4053,8 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
 {
   BMEditMesh *em = mr->edit_bmesh;
 
-  for (int l = 0; l < mr->loop_len; l++) {
-    r_intersect[l] = -1.0f;
+  for (int l_index = 0; l_index < mr->loop_len; l_index++) {
+    r_intersect[l_index] = -1.0f;
   }
 
   if (mr->extract_type == MR_EXTRACT_BMESH) {
@@ -3600,9 +4075,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
         for (int j = 0; j < 2; j++) {
           BMFace *f_hit = f_hit_pair[j];
           BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
-          int l = BM_elem_index_get(l_first);
-          for (int k = 0; k < f_hit->len; k++, l++) {
-            r_intersect[l] = 1.0f;
+          int l_index = BM_elem_index_get(l_first);
+          for (int k = 0; k < f_hit->len; k++, l_index++) {
+            r_intersect[l_index] = 1.0f;
           }
         }
       }
@@ -3629,9 +4104,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
         };
         for (int j = 0; j < 2; j++) {
           const MPoly *f_hit = f_hit_pair[j];
-          int l = f_hit->loopstart;
-          for (int k = 0; k < f_hit->totloop; k++, l++) {
-            r_intersect[l] = 1.0f;
+          int l_index = f_hit->loopstart;
+          for (int k = 0; k < f_hit->totloop; k++, l_index++) {
+            r_intersect[l_index] = 1.0f;
           }
         }
       }
@@ -3674,9 +4149,9 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
       BM_mesh_elem_index_ensure(em->bm, BM_VERT);
     }
 
-    int l = 0;
-    int p = 0;
-    BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) {
+    int l_index = 0;
+    int f_index = 0;
+    BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
       float fac = -1.0f;
 
       if (f->len > 3) {
@@ -3688,7 +4163,7 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
           const float *no_face;
           float no_corner[3];
           if (mr->bm_vert_coords != NULL) {
-            no_face = mr->bm_poly_normals[p];
+            no_face = mr->bm_poly_normals[f_index];
             BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
           }
           else {
@@ -3707,24 +4182,24 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
       }
 
       fac = distort_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < f->len; i++, l++) {
-        r_distort[l] = fac;
+      for (int i = 0; i < f->len; i++, l_index++) {
+        r_distort[l_index] = fac;
       }
     }
   }
   else {
-    const MPoly *mpoly = mr->mpoly;
-    for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
+    const MPoly *mp = mr->mpoly;
+    for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
       float fac = -1.0f;
 
-      if (mpoly->totloop > 3) {
-        float *f_no = mr->poly_normals[p];
+      if (mp->totloop > 3) {
+        float *f_no = mr->poly_normals[mp_index];
         fac = 0.0f;
 
-        for (int i = 1; i <= mpoly->totloop; i++) {
-          const MLoop *l_prev = &mr->mloop[mpoly->loopstart + (i - 1) % mpoly->totloop];
-          const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop];
-          const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop];
+        for (int i = 1; i <= mp->totloop; i++) {
+          const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop];
+          const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+          const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
           float no_corner[3];
           normal_tri_v3(no_corner,
                         mr->mvert[l_prev->v].co,
@@ -3740,8 +4215,8 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
       }
 
       fac = distort_remap(fac, min, max, minmax_irange);
-      for (int i = 0; i < mpoly->totloop; i++, l++) {
-        r_distort[l] = fac;
+      for (int i = 0; i < mp->totloop; i++, l_index++) {
+        r_distort[l_index] = fac;
       }
     }
   }
@@ -3791,34 +4266,34 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
       BMLoop *l_iter, *l_first;
       l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
       do {
-        int l = BM_elem_index_get(l_iter);
-        int v = BM_elem_index_get(l_iter->v);
-        r_sharp[l] = sharp_remap(vert_angles[v], min, max, minmax_irange);
+        int l_index = BM_elem_index_get(l_iter);
+        int v_index = BM_elem_index_get(l_iter->v);
+        r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
       } while ((l_iter = l_iter->next) != l_first);
     }
   }
   else {
     /* first assign float values to verts */
-    const MPoly *mpoly = mr->mpoly;
+    const MPoly *mp = mr->mpoly;
 
     EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len);
 
-    for (int p = 0; p < mr->poly_len; p++, mpoly++) {
-      for (int i = 0; i < mpoly->totloop; i++) {
-        const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop];
-        const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop];
+    for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+      for (int i = 0; i < mp->totloop; i++) {
+        const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+        const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
         const MVert *v_curr = &mr->mvert[l_curr->v];
         const MVert *v_next = &mr->mvert[l_next->v];
         float angle;
         void **pval;
         bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
         if (!value_is_init) {
-          *pval = mr->poly_normals[p];
+          *pval = mr->poly_normals[mp_index];
           /* non-manifold edge, yet... */
           continue;
         }
         else if (*pval != NULL) {
-          const float *f1_no = mr->poly_normals[p];
+          const float *f1_no = mr->poly_normals[mp_index];
           const float *f2_no = *pval;
           angle = angle_normalized_v3v3(f1_no, f2_no);
           angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle;
@@ -3851,9 +4326,9 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
     BLI_edgehashIterator_free(ehi);
     BLI_edgehash_free(eh, NULL);
 
-    const MLoop *mloop = mr->mloop;
-    for (int l = 0; l < mr->loop_len; l++, mloop++) {
-      r_sharp[l] = sharp_remap(vert_angles[mloop->v], min, max, minmax_irange);
+    const MLoop *ml = mr->mloop;
+    for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) {
+      r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange);
     }
   }
 
@@ -3917,40 +4392,44 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf)
   return vbo->data;
 }
 
-static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr,
-                                         int UNUSED(l),
-                                         BMLoop *loop,
-                                         void *data)
+static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr,
+                                           const ExtractPolyBMesh_Params *params,
+                                           void *data)
 {
-  float(*center)[3] = (float(*)[3])data;
-  float w = 1.0f / (float)loop->f->len;
-  madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w);
+  float(*center)[3] = data;
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    float w = 1.0f / (float)l->f->len;
+    madd_v3_v3fl(center[BM_elem_index_get(l->f)], bm_vert_co_get(mr, l->v), w);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr,
-                                        int UNUSED(l),
-                                        const MLoop *mloop,
-                                        int p,
-                                        const MPoly *mpoly,
-                                        void *data)
+static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
+                                             const ExtractPolyMesh_Params *params,
+                                             void *data)
 {
   float(*center)[3] = (float(*)[3])data;
-  const MVert *mvert = &mr->mvert[mloop->v];
-  if (mr->use_subsurf_fdots) {
-    if (mvert->flag & ME_VERT_FACEDOT) {
-      copy_v3_v3(center[p], mvert->co);
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    const MVert *mv = &mr->mvert[ml->v];
+    if (mr->use_subsurf_fdots) {
+      if (mv->flag & ME_VERT_FACEDOT) {
+        copy_v3_v3(center[mp_index], mv->co);
+      }
+    }
+    else {
+      float w = 1.0f / (float)mp->totloop;
+      madd_v3_v3fl(center[mp_index], mv->co, w);
     }
   }
-  else {
-    float w = 1.0f / (float)mpoly->totloop;
-    madd_v3_v3fl(center[p], mvert->co, w);
-  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
 static const MeshExtract extract_fdots_pos = {
     .init = extract_fdots_pos_init,
-    .iter_loop_bm = extract_fdots_pos_loop_bmesh,
-    .iter_loop_mesh = extract_fdots_pos_loop_mesh,
+    .iter_poly_bm = extract_fdots_pos_iter_poly_bm,
+    .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
@@ -4072,30 +4551,42 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_fdots_uv_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                        int UNUSED(l),
-                                        BMLoop *loop,
-                                        void *_data)
+static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *_data)
 {
-  MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data;
-  float w = 1.0f / (float)loop->f->len;
-  const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
-  madd_v2_v2fl(data->vbo_data[BM_elem_index_get(loop->f)], luv->uv, w);
+  MeshExtract_FdotUV_Data *data = _data;
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    float w = 1.0f / (float)l->f->len;
+    const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs);
+    madd_v2_v2fl(data->vbo_data[BM_elem_index_get(l->f)], luv->uv, w);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_fdots_uv_loop_mesh(
-    const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
+static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *_data)
 {
-  MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data;
+  MeshExtract_FdotUV_Data *data = _data;
   if (mr->use_subsurf_fdots) {
-    const MVert *mvert = &mr->mvert[mloop->v];
-    if (mvert->flag & ME_VERT_FACEDOT) {
-      copy_v2_v2(data->vbo_data[p], data->uv_data[l].uv);
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      const MVert *mv = &mr->mvert[ml->v];
+      if (mv->flag & ME_VERT_FACEDOT) {
+        copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv);
+      }
     }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
   }
   else {
-    float w = 1.0f / (float)mpoly->totloop;
-    madd_v2_v2fl(data->vbo_data[p], data->uv_data[l].uv, w);
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+    {
+      float w = 1.0f / (float)mp->totloop;
+      madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w);
+    }
+    EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
   }
 }
 
@@ -4108,8 +4599,8 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr),
 
 static const MeshExtract extract_fdots_uv = {
     .init = extract_fdots_uv_init,
-    .iter_loop_bm = extract_fdots_uv_loop_bmesh,
-    .iter_loop_mesh = extract_fdots_uv_loop_mesh,
+    .iter_poly_bm = extract_fdots_uv_iter_poly_bm,
+    .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh,
     .finish = extract_fdots_uv_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -4141,31 +4632,35 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, void *buf)
   return data;
 }
 
-static void extract_fdots_edituv_data_loop_bmesh(const MeshRenderData *mr,
-                                                 int UNUSED(l),
-                                                 BMLoop *loop,
-                                                 void *_data)
+static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+                                                   const ExtractPolyBMesh_Params *params,
+                                                   void *_data)
 {
-  MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data;
-  EditLoopData *eldata = data->vbo_data + BM_elem_index_get(loop->f);
-  memset(eldata, 0x0, sizeof(*eldata));
-  mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata);
+  MeshExtract_EditUVFdotData_Data *data = _data;
+  EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+  {
+    EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)];
+    memset(eldata, 0x0, sizeof(*eldata));
+    mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
+  }
+  EXTRACT_POLY_FOREACH_BM_END;
 }
 
-static void extract_fdots_edituv_data_loop_mesh(const MeshRenderData *mr,
-                                                int UNUSED(l),
-                                                const MLoop *UNUSED(mloop),
-                                                int p,
-                                                const MPoly *UNUSED(mpoly),
-                                                void *_data)
+static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+                                                     const ExtractPolyMesh_Params *params,
+                                                     void *_data)
 {
-  MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data;
-  EditLoopData *eldata = data->vbo_data + p;
-  memset(eldata, 0x0, sizeof(*eldata));
-  BMFace *efa = bm_original_face_get(mr, p);
-  if (efa) {
-    mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
+  MeshExtract_EditUVFdotData_Data *data = _data;
+  EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+  {
+    EditLoopData *eldata = &data->vbo_data[mp_index];
+    memset(eldata, 0x0, sizeof(*eldata));
+    BMFace *efa = bm_original_face_get(mr, mp_index);
+    if (efa) {
+      mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
+    }
   }
+  EXTRACT_POLY_FOREACH_MESH_END;
 }
 
 static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
@@ -4177,8 +4672,8 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
 
 static const MeshExtract extract_fdots_edituv_data = {
     .init = extract_fdots_edituv_data_init,
-    .iter_loop_bm = extract_fdots_edituv_data_loop_bmesh,
-    .iter_loop_mesh = extract_fdots_edituv_data_loop_mesh,
+    .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm,
+    .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh,
     .finish = extract_fdots_edituv_data_finish,
     .data_flag = 0,
     .use_threading = true,
@@ -4261,135 +4756,176 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf)
  * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
  * shader to output original index. */
 
-static void extract_poly_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                        int l,
-                                        BMLoop *loop,
-                                        void *data)
+static void extract_poly_idx_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *data)
 {
-  ((uint32_t *)data)[l] = BM_elem_index_get(loop->f);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    ((uint32_t *)data)[l_index] = BM_elem_index_get(l->f);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_edge_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                        int l,
-                                        BMLoop *loop,
-                                        void *data)
+static void extract_edge_idx_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *data)
 {
-  ((uint32_t *)data)[l] = BM_elem_index_get(loop->e);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    ((uint32_t *)data)[l_index] = BM_elem_index_get(l->e);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_vert_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                        int l,
-                                        BMLoop *loop,
-                                        void *data)
+static void extract_vert_idx_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *data)
 {
-  ((uint32_t *)data)[l] = BM_elem_index_get(loop->v);
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+  {
+    ((uint32_t *)data)[l_index] = BM_elem_index_get(l->v);
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
 }
 
-static void extract_edge_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data)
+static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr,
+                                           const ExtractLEdgeBMesh_Params *params,
+                                           void *data)
 {
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed);
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed);
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed);
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed);
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_vert_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data)
+static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr,
+                                           const ExtractLEdgeBMesh_Params *params,
+                                           void *data)
 {
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed->v1);
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed->v2);
+  EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+  {
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1);
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2);
+  }
+  EXTRACT_LEDGE_FOREACH_BM_END;
 }
 
-static void extract_vert_idx_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *data)
+static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr,
+                                           const ExtractLVertBMesh_Params *params,
+                                           void *data)
 {
-  ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = BM_elem_index_get(eve);
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+  {
+    ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve);
+  }
+  EXTRACT_LVERT_FOREACH_BM_END;
 }
 
-static void extract_poly_idx_loop_mesh(const MeshRenderData *mr,
-                                       int l,
-                                       const MLoop *UNUSED(mloop),
-                                       int p,
-                                       const MPoly *UNUSED(mpoly),
-                                       void *data)
+static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *data)
 {
-  ((uint32_t *)data)[l] = (mr->p_origindex) ? mr->p_origindex[p] : p;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    ((uint32_t *)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index;
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_edge_idx_loop_mesh(const MeshRenderData *mr,
-                                       int l,
-                                       const MLoop *mloop,
-                                       int UNUSED(p),
-                                       const MPoly *UNUSED(mpoly),
-                                       void *data)
+static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *data)
 {
-  ((uint32_t *)data)[l] = (mr->e_origindex) ? mr->e_origindex[mloop->e] : mloop->e;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    ((uint32_t *)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e;
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_vert_idx_loop_mesh(const MeshRenderData *mr,
-                                       int l,
-                                       const MLoop *mloop,
-                                       int UNUSED(p),
-                                       const MPoly *UNUSED(mpoly),
-                                       void *data)
+static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *data)
 {
-  ((uint32_t *)data)[l] = (mr->v_origindex) ? mr->v_origindex[mloop->v] : mloop->v;
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+  {
+    ((uint32_t *)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v;
+  }
+  EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
 }
 
-static void extract_edge_idx_ledge_mesh(const MeshRenderData *mr,
-                                        int e,
-                                        const MEdge *UNUSED(medge),
-                                        void *data)
+static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr,
+                                             const ExtractLEdgeMesh_Params *params,
+                                             void *data)
 {
-  int e_idx = mr->ledges[e];
-  int e_orig = (mr->e_origindex) ? mr->e_origindex[e_idx] : e_idx;
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = e_orig;
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = e_orig;
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    const int e_index = mr->ledges[ledge_index];
+    const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index;
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig;
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig;
+  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
-static void extract_vert_idx_ledge_mesh(const MeshRenderData *mr,
-                                        int e,
-                                        const MEdge *medge,
-                                        void *data)
+static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr,
+                                             const ExtractLEdgeMesh_Params *params,
+                                             void *data)
 {
-  int v1_orig = (mr->v_origindex) ? mr->v_origindex[medge->v1] : medge->v1;
-  int v2_orig = (mr->v_origindex) ? mr->v_origindex[medge->v2] : medge->v2;
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = v1_orig;
-  ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = v2_orig;
+  EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+  {
+    int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1;
+    int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2;
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig;
+    ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig;
+  }
+  EXTRACT_LEDGE_FOREACH_MESH_END;
 }
 
-static void extract_vert_idx_lvert_mesh(const MeshRenderData *mr,
-                                        int v,
-                                        const MVert *UNUSED(mvert),
-                                        void *data)
+static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
+                                             const ExtractLVertMesh_Params *params,
+                                             void *data)
 {
-  int v_idx = mr->lverts[v];
-  int v_orig = (mr->v_origindex) ? mr->v_origindex[v_idx] : v_idx;
-  ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = v_orig;
+  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+  EXTRACT_LVERT_FOREACH_MESH_BEGIN(med, lvert_index, params, mr)
+  {
+    const int v_index = mr->lverts[lvert_index];
+    const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index;
+    ((uint32_t *)data)[offset + lvert_index] = v_orig;
+  }
+  EXTRACT_LVERT_FOREACH_MESH_END;
 }
 
 static const MeshExtract extract_poly_idx = {
     .init = extract_select_idx_init,
-    .iter_loop_bm = extract_poly_idx_loop_bmesh,
-    .iter_loop_mesh = extract_poly_idx_loop_mesh,
+    .iter_poly_bm = extract_poly_idx_iter_poly_bm,
+    .iter_poly_mesh = extract_poly_idx_iter_poly_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
 
 static const MeshExtract extract_edge_idx = {
     .init = extract_select_idx_init,
-    .iter_loop_bm = extract_edge_idx_loop_bmesh,
-    .iter_loop_mesh = extract_edge_idx_loop_mesh,
-    .iter_ledge_bm = extract_edge_idx_ledge_bmesh,
-    .iter_ledge_mesh = extract_edge_idx_ledge_mesh,
+    .iter_poly_bm = extract_edge_idx_iter_poly_bm,
+    .iter_poly_mesh = extract_edge_idx_iter_poly_mesh,
+    .iter_ledge_bm = extract_edge_idx_iter_ledge_bm,
+    .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
 
 static const MeshExtract extract_vert_idx = {
     .init = extract_select_idx_init,
-    .iter_loop_bm = extract_vert_idx_loop_bmesh,
-    .iter_loop_mesh = extract_vert_idx_loop_mesh,
-    .iter_ledge_bm = extract_vert_idx_ledge_bmesh,
-    .iter_ledge_mesh = extract_vert_idx_ledge_mesh,
-    .iter_lvert_bm = extract_vert_idx_lvert_bmesh,
-    .iter_lvert_mesh = extract_vert_idx_lvert_mesh,
+    .iter_poly_bm = extract_vert_idx_iter_poly_bm,
+    .iter_poly_mesh = extract_vert_idx_iter_poly_mesh,
+    .iter_ledge_bm = extract_vert_idx_iter_ledge_bm,
+    .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh,
+    .iter_lvert_bm = extract_vert_idx_iter_lvert_bm,
+    .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
@@ -4407,28 +4943,41 @@ static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf)
   return vbo->data;
 }
 
-static void extract_fdot_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
-                                        int UNUSED(l),
-                                        BMLoop *loop,
-                                        void *data)
+static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *mr,
+                                          const ExtractPolyBMesh_Params *params,
+                                          void *data)
 {
-  ((uint32_t *)data)[BM_elem_index_get(loop->f)] = BM_elem_index_get(loop->f);
+  EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+  {
+    ((uint32_t *)data)[f_index] = f_index;
+  }
+  EXTRACT_POLY_FOREACH_BM_END;
 }
 
-static void extract_fdot_idx_loop_mesh(const MeshRenderData *mr,
-                                       int UNUSED(l),
-                                       const MLoop *UNUSED(mloop),
-                                       int p,
-                                       const MPoly *UNUSED(mpoly),
-                                       void *data)
+static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr,
+                                            const ExtractPolyMesh_Params *params,
+                                            void *data)
 {
-  ((uint32_t *)data)[p] = (mr->p_origindex) ? mr->p_origindex[p] : p;
+  if (mr->p_origindex != NULL) {
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index];
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
+  }
+  else {
+    EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+    {
+      ((uint32_t *)data)[mp_index] = mp_index;
+    }
+    EXTRACT_POLY_FOREACH_MESH_END;
+  }
 }
 
 static const MeshExtract extract_fdot_idx = {
     .init = extract_select_fdot_idx_init,
-    .iter_loop_bm = extract_fdot_idx_loop_bmesh,
-    .iter_loop_mesh = extract_fdot_idx_loop_mesh,
+    .iter_poly_bm = extract_fdot_idx_iter_poly_bm,
+    .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh,
     .data_flag = 0,
     .use_threading = true,
 };
@@ -4512,67 +5061,69 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
   switch (mr->extract_type) {
     case MR_EXTRACT_BMESH:
       if (iter_type & MR_ITER_LOOPTRI) {
-        int t_end = min_ii(mr->tri_len, end);
-        for (int t = start; t < t_end; t++) {
-          BMLoop **elt = &mr->edit_bmesh->looptris[t][0];
-          extract->iter_looptri_bm(mr, t, elt, user_data);
-        }
+        extract->iter_looptri_bm(mr,
+                                 &(const ExtractTriBMesh_Params){
+                                     .looptris = mr->edit_bmesh->looptris,
+                                     .tri_range = {start, min_ii(mr->tri_len, end)},
+                                 },
+                                 user_data);
       }
-      if (iter_type & MR_ITER_LOOP) {
-        int l_end = min_ii(mr->poly_len, end);
-        for (int f = start; f < l_end; f++) {
-          BMFace *efa = BM_face_at_index(mr->bm, f);
-          BMLoop *l_iter, *l_first;
-          l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
-          do {
-            extract->iter_loop_bm(mr, BM_elem_index_get(l_iter), l_iter, user_data);
-          } while ((l_iter = l_iter->next) != l_first);
-        }
+      if (iter_type & MR_ITER_POLY) {
+        extract->iter_poly_bm(mr,
+                              &(const ExtractPolyBMesh_Params){
+                                  .poly_range = {start, min_ii(mr->poly_len, end)},
+                              },
+                              user_data);
       }
       if (iter_type & MR_ITER_LEDGE) {
-        int le_end = min_ii(mr->edge_loose_len, end);
-        for (int e = start; e < le_end; e++) {
-          BMEdge *eed = BM_edge_at_index(mr->bm, mr->ledges[e]);
-          extract->iter_ledge_bm(mr, e, eed, user_data);
-        }
+        extract->iter_ledge_bm(mr,
+                               &(const ExtractLEdgeBMesh_Params){
+                                   .ledge = mr->ledges,
+                                   .ledge_range = {start, min_ii(mr->edge_loose_len, end)},
+                               },
+                               user_data);
       }
       if (iter_type & MR_ITER_LVERT) {
-        int lv_end = min_ii(mr->vert_loose_len, end);
-        for (int v = start; v < lv_end; v++) {
-          BMVert *eve = BM_vert_at_index(mr->bm, mr->lverts[v]);
-          extract->iter_lvert_bm(mr, v, eve, user_data);
-        }
+        extract->iter_lvert_bm(mr,
+                               &(const ExtractLVertBMesh_Params){
+                                   .lvert = mr->lverts,
+                                   .lvert_range = {start, min_ii(mr->vert_loose_len, end)},
+                               },
+                               user_data);
       }
       break;
     case MR_EXTRACT_MAPPED:
     case MR_EXTRACT_MESH:
       if (iter_type & MR_ITER_LOOPTRI) {
-        int t_end = min_ii(mr->tri_len, end);
-        for (int t = start; t < t_end; t++) {
-          extract->iter_looptri_mesh(mr, t, &mr->mlooptri[t], user_data);
-        }
+        extract->iter_looptri_mesh(mr,
+                                   &(const ExtractTriMesh_Params){
+                                       .mlooptri = mr->mlooptri,
+                                       .tri_range = {start, min_ii(mr->tri_len, end)},
+                                   },
+                                   user_data);
       }
-      if (iter_type & MR_ITER_LOOP) {
-        int l_end = min_ii(mr->poly_len, end);
-        for (int p = start; p < l_end; p++) {
-          const MPoly *mpoly = &mr->mpoly[p];
-          int l = mpoly->loopstart;
-          for (int i = 0; i < mpoly->totloop; i++, l++) {
-            extract->iter_loop_mesh(mr, l, &mr->mloop[l], p, mpoly, user_data);
-          }
-        }
+      if (iter_type & MR_ITER_POLY) {
+        extract->iter_poly_mesh(mr,
+                                &(const ExtractPolyMesh_Params){
+                                    .poly_range = {start, min_ii(mr->poly_len, end)},
+                                },
+                                user_data);
       }
       if (iter_type & MR_ITER_LEDGE) {
-        int le_end = min_ii(mr->edge_loose_len, end);
-        for (int e = start; e < le_end; e++) {
-          extract->iter_ledge_mesh(mr, e, &mr->medge[mr->ledges[e]], user_data);
-        }
+        extract->iter_ledge_mesh(mr,
+                                 &(const ExtractLEdgeMesh_Params){
+                                     .ledge = mr->ledges,
+                                     .ledge_range = {start, min_ii(mr->edge_loose_len, end)},
+                                 },
+                                 user_data);
       }
       if (iter_type & MR_ITER_LVERT) {
-        int lv_end = min_ii(mr->vert_loose_len, end);
-        for (int v = start; v < lv_end; v++) {
-          extract->iter_lvert_mesh(mr, v, &mr->mvert[mr->lverts[v]], user_data);
-        }
+        extract->iter_lvert_mesh(mr,
+                                 &(const ExtractLVertMesh_Params){
+                                     .lvert = mr->lverts,
+                                     .lvert_range = {start, min_ii(mr->vert_loose_len, end)},
+                                 },
+                                 user_data);
       }
       break;
   }
@@ -4799,10 +5350,10 @@ static void extract_task_create(struct TaskGraph *task_graph,
             task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
       }
     }
-    if (taskdata->iter_type & MR_ITER_LOOP) {
+    if (taskdata->iter_type & MR_ITER_POLY) {
       for (int i = 0; i < mr->poly_len; i += chunk_size) {
         extract_range_task_create(
-            task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size);
+            task_graph, task_node_user_data_init, taskdata, MR_ITER_POLY, i, chunk_size);
       }
     }
     if (taskdata->iter_type & MR_ITER_LEDGE) {