Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt7
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl65
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c8
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h4
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl4
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_mesh.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_mode_transfer.c159
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h12
-rw-r--r--source/blender/draw/intern/DRW_render.h7
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h43
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc1004
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_extractors.c (renamed from source/blender/draw/intern/draw_cache_extract_mesh.c)3296
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_private.h514
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_render_data.c371
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h1
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.cc171
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_hair.c3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c59
-rw-r--r--source/blender/draw/intern/draw_cache_inline.h4
-rw-r--r--source/blender/draw/intern/draw_hair.c200
-rw-r--r--source/blender/draw/intern/draw_manager.h13
-rw-r--r--source/blender/draw/intern/draw_manager_data.c36
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c10
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c1
-rw-r--r--source/blender/draw/intern/shaders/common_hair_lib.glsl78
-rw-r--r--source/blender/draw/intern/shaders/common_hair_refine_comp.glsl24
-rw-r--r--source/blender/draw/intern/shaders/common_hair_refine_vert.glsl45
-rw-r--r--source/blender/draw/intern/shaders/common_math_lib.glsl2
34 files changed, 3626 insertions, 2545 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 045adf4b380..ee5b2c549a5 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../depsgraph
../editors/include
../editors/space_view3d
+ ../functions
../gpu
../imbuf
../makesdna
@@ -50,7 +51,9 @@ set(INC
set(SRC
intern/draw_cache.c
- intern/draw_cache_extract_mesh.c
+ intern/draw_cache_extract_mesh_extractors.c
+ intern/draw_cache_extract_mesh_render_data.c
+ intern/draw_cache_extract_mesh.cc
intern/draw_cache_impl_curve.cc
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_gpencil.c
@@ -146,6 +149,7 @@ set(SRC
engines/overlay/overlay_image.c
engines/overlay/overlay_lattice.c
engines/overlay/overlay_metaball.c
+ engines/overlay/overlay_mode_transfer.c
engines/overlay/overlay_motion_path.c
engines/overlay/overlay_outline.c
engines/overlay/overlay_paint.c
@@ -321,6 +325,7 @@ data_to_c_simple(intern/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_pointcloud_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_refine_vert.glsl SRC)
+data_to_c_simple(intern/shaders/common_hair_refine_comp.glsl SRC)
data_to_c_simple(intern/shaders/common_math_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_math_geom_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_view_lib.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index cba86d058ea..e23a5a81169 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -96,7 +96,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
}
}
else if (ELEM(la->type, LA_SPOT, LA_LOCAL)) {
- power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* 1/(4*r²*Pi²) */
+ power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* `1/(4*(r^2)*(Pi^2))` */
/* for point lights (a.k.a radius == 0.0) */
// power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
@@ -106,7 +106,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
/* Make illumination power closer to cycles for bigger radii. Cycles uses a cos^3 term that we
* cannot reproduce so we account for that by scaling the light power. This function is the
* result of a rough manual fitting. */
- power += 1.0f / (2.0f * M_PI); /* power *= 1 + r²/2 */
+ power += 1.0f / (2.0f * M_PI); /* `power *= 1 + (r^2)/2` */
}
return power;
}
@@ -257,7 +257,7 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
float power = max_fff(UNPACK3(evli->color)) * evli->volume;
if (power > 0.0f && evli->light_type != LA_SUN) {
/* The limit of the power attenuation function when the distance to the light goes to 0 is
- * 2 / r² where r is the light radius. We need to find the right radius that emits at most
+ * `2 / r^2` where r is the light radius. We need to find the right radius that emits at most
* the volume light upper bound. Inverting the function we get: */
float min_radius = 1.0f / sqrtf(0.5f * upper_bound / power);
/* Square it here to avoid a multiplication inside the shader. */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 5739024993e..5ada53ab98c 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -79,7 +79,7 @@ bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata)
* type the rest of the bits are used for the name hash. */
int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov)
{
- int hash = BLI_hash_string(aov->name);
+ int hash = BLI_hash_string(aov->name) << 1;
SET_FLAG_FROM_TEST(hash, aov->type == AOV_TYPE_COLOR, EEVEE_AOV_HASH_COLOR_TYPE_MASK);
return hash;
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index fdbb70e917d..05496ad4ab0 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -138,30 +138,55 @@ void accumulate_light(vec3 light, float fac, inout vec4 accum)
/* Same thing as Cycles without the comments to make it shorter. */
vec3 ensure_valid_reflection(vec3 Ng, vec3 I, vec3 N)
{
- vec3 R;
- float NI = dot(N, I);
- float NgR, threshold;
- /* Check if the incident ray is coming from behind normal N. */
- if (NI > 0.0) {
- /* Normal reflection. */
- R = (2.0 * NI) * N - I;
- NgR = dot(Ng, R);
- /* Reflection rays may always be at least as shallow as the incoming ray. */
- threshold = min(0.9 * dot(Ng, I), 0.01);
- if (NgR >= threshold) {
- return N;
+ vec3 R = -reflect(I, N);
+
+ /* Reflection rays may always be at least as shallow as the incoming ray. */
+ float threshold = min(0.9 * dot(Ng, I), 0.025);
+ if (dot(Ng, R) >= threshold) {
+ return N;
+ }
+
+ float NdotNg = dot(N, Ng);
+ vec3 X = normalize(N - NdotNg * Ng);
+
+ float Ix = dot(I, X), Iz = dot(I, Ng);
+ float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
+ float a = Ix2 + Iz2;
+
+ float b = sqrt(Ix2 * (a - sqr(threshold)));
+ float c = Iz * threshold + a;
+
+ float fac = 0.5 / a;
+ float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
+ bool valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5));
+ bool valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5));
+
+ vec2 N_new;
+ if (valid1 && valid2) {
+ /* If both are possible, do the expensive reflection-based check. */
+ vec2 N1 = vec2(safe_sqrt(1.0 - N1_z2), safe_sqrt(N1_z2));
+ vec2 N2 = vec2(safe_sqrt(1.0 - N2_z2), safe_sqrt(N2_z2));
+
+ float R1 = 2.0 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz;
+ float R2 = 2.0 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz;
+
+ valid1 = (R1 >= 1e-5);
+ valid2 = (R2 >= 1e-5);
+ if (valid1 && valid2) {
+ N_new = (R1 < R2) ? N1 : N2;
}
+ else {
+ N_new = (R1 > R2) ? N1 : N2;
+ }
+ }
+ else if (valid1 || valid2) {
+ float Nz2 = valid1 ? N1_z2 : N2_z2;
+ N_new = vec2(safe_sqrt(1.0 - Nz2), safe_sqrt(Nz2));
}
else {
- /* Bad incident. */
- R = -I;
- NgR = dot(Ng, R);
- threshold = 0.01;
+ return Ng;
}
- /* Lift the reflection above the threshold. */
- R = R + Ng * (threshold - NgR);
- /* Find a bisector. */
- return safe_normalize(I * length(R) + R * length(I));
+ return N_new.x * X + N_new.y * Ng;
}
/* ----------- Cone angle Approximation --------- */
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index adb70f97585..af8b029a08e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -274,7 +274,13 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
const bool override_vertcol = (pd->v3d_color_type != -1);
const bool is_vert_col_mode = (pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) ||
GPENCIL_VERTEX_MODE(gpd) || pd->is_render;
- bool is_masked = (gpl->flag & GP_LAYER_USE_MASK) && !BLI_listbase_is_empty(&gpl->mask_layers);
+ const bool is_viewlayer_render = pd->is_render && (gpl->viewlayername[0] != '\0') &&
+ STREQ(pd->view_layer->name, gpl->viewlayername);
+ const bool disable_masks_render = is_viewlayer_render &&
+ (gpl->flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER);
+ bool is_masked = disable_masks_render ? false :
+ (gpl->flag & GP_LAYER_USE_MASK) &&
+ !BLI_listbase_is_empty(&gpl->mask_layers);
float vert_col_opacity = (override_vertcol) ?
(is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 5ceb909bc88..34fe29055d6 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -297,7 +297,9 @@ typedef struct GPENCIL_PrivateData {
int v3d_color_type;
/* Current frame */
int cfra;
- /* If we are rendering for final render (F12). */
+ /* If we are rendering for final render (F12).
+ * NOTE: set to false for viewport and opengl rendering (including VSE scene rendering), but set
+ * to true when rendering in `OB_RENDER` shading mode (viewport or opengl rendering) */
bool is_render;
/* If we are in viewport display (used for VFX). */
bool is_viewport;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 7412959a30b..ac48b94fea9 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -442,6 +442,10 @@ void stroke_vertex()
if (is_dot) {
# ifdef GP_MATERIAL_BUFFER_LEN
int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT;
+ /* For one point strokes use object aligment. */
+ if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) {
+ alignement = GP_STROKE_ALIGNMENT_OBJECT;
+ }
# endif
vec2 x_axis;
diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
index 40a9dbe01c0..7639911286f 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
@@ -149,7 +149,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
DRWState state_common = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
/* Faces */
- /* Cage geom needs to be offsetted to avoid Z-fighting. */
+ /* Cage geom needs an offset applied to avoid Z-fighting. */
for (int j = 0; j < 2; j++) {
DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] :
&psl->edit_mesh_faces_cage_ps[i];
@@ -197,7 +197,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
grp = pd->edit_mesh_skin_roots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
- /* Facedots */
+ /* Face-dots */
if (select_face && show_face_dots) {
sh = OVERLAY_shader_edit_mesh_facedot();
grp = pd->edit_mesh_facedots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index b8f721946f2..19f822e3f68 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -207,6 +207,7 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_armature_cache_init(vedata);
OVERLAY_background_cache_init(vedata);
OVERLAY_fade_cache_init(vedata);
+ OVERLAY_mode_transfer_cache_init(vedata);
OVERLAY_extra_cache_init(vedata);
OVERLAY_facing_cache_init(vedata);
OVERLAY_gpencil_cache_init(vedata);
@@ -323,6 +324,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
!is_select;
const bool draw_fade = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FADE_INACTIVE) &&
overlay_should_fade_object(ob, draw_ctx->obact);
+ const bool draw_mode_transfer = draw_surface && (pd->overlay.flag & V3D_OVERLAY_MODE_TRANSFER);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
const bool draw_wires = draw_surface && has_surface &&
(pd->wireframe_mode || !pd->hide_overlays);
@@ -349,6 +351,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
if (draw_facing) {
OVERLAY_facing_cache_populate(vedata, ob);
}
+ if (draw_mode_transfer) {
+ OVERLAY_mode_transfer_cache_populate(vedata, ob);
+ }
if (draw_wires) {
OVERLAY_wireframe_cache_populate(vedata, ob, dupli, do_init);
}
@@ -504,6 +509,7 @@ static void OVERLAY_cache_finish(void *vedata)
{GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
}
+ OVERLAY_mode_transfer_cache_finish(vedata);
OVERLAY_antialiasing_cache_finish(vedata);
OVERLAY_armature_cache_finish(vedata);
OVERLAY_image_cache_finish(vedata);
@@ -566,6 +572,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_image_draw(vedata);
OVERLAY_fade_draw(vedata);
OVERLAY_facing_draw(vedata);
+ OVERLAY_mode_transfer_draw(vedata);
OVERLAY_extra_blend_draw(vedata);
OVERLAY_volume_draw(vedata);
@@ -605,6 +612,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_fade_infront_draw(vedata);
OVERLAY_facing_infront_draw(vedata);
+ OVERLAY_mode_transfer_infront_draw(vedata);
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(fbl->overlay_line_in_front_fb);
diff --git a/source/blender/draw/engines/overlay/overlay_mode_transfer.c b/source/blender/draw/engines/overlay/overlay_mode_transfer.c
new file mode 100644
index 00000000000..253f606b086
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_mode_transfer.c
@@ -0,0 +1,159 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "BKE_paint.h"
+#include "DRW_render.h"
+
+#include "ED_view3d.h"
+
+#include "PIL_time.h"
+#include "UI_resources.h"
+
+#include "overlay_private.h"
+
+void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+
+ pd->mode_transfer.time = PIL_check_seconds_timer();
+
+ for (int i = 0; i < 2; i++) {
+ /* Non Meshes Pass (Camera, empties, lights ...) */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->mode_transfer_ps[i], state | pd->clipping_state);
+ }
+}
+
+#define MODE_TRANSFER_FLASH_LENGTH 0.55f
+/* TODO(pablodp606): Remove this option for 3.0 if fade in/out is not used. */
+#define MODE_TRANSFER_FLASH_FADE 0.0f
+#define MODE_TRANSFER_FLASH_MAX_ALPHA 0.25f
+
+static bool mode_transfer_is_animation_running(const float anim_time)
+{
+ return anim_time >= 0.0f && anim_time <= MODE_TRANSFER_FLASH_LENGTH;
+}
+
+static float mode_transfer_alpha_for_animation_time_get(const float anim_time)
+{
+ if (anim_time > MODE_TRANSFER_FLASH_LENGTH) {
+ return 0.0f;
+ }
+
+ if (anim_time < 0.0f) {
+ return 0.0f;
+ }
+
+ if (MODE_TRANSFER_FLASH_FADE <= 0.0f) {
+ return (1.0f - (anim_time / MODE_TRANSFER_FLASH_LENGTH)) * MODE_TRANSFER_FLASH_MAX_ALPHA;
+ }
+
+ const float flash_fade_in_time = MODE_TRANSFER_FLASH_LENGTH * MODE_TRANSFER_FLASH_FADE;
+ const float flash_fade_out_time = MODE_TRANSFER_FLASH_LENGTH - flash_fade_in_time;
+
+ float alpha = 0.0f;
+ if (anim_time < flash_fade_in_time) {
+ alpha = anim_time / flash_fade_in_time;
+ }
+ else {
+ const float fade_out_anim_time = anim_time - flash_fade_in_time;
+ alpha = 1.0f - (fade_out_anim_time / flash_fade_out_time);
+ }
+
+ return alpha * MODE_TRANSFER_FLASH_MAX_ALPHA;
+}
+
+void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ OVERLAY_PassList *psl = vedata->psl;
+
+ if (pd->xray_enabled) {
+ return;
+ }
+
+ const float animation_time = pd->mode_transfer.time -
+ ob->runtime.overlay_mode_transfer_start_time;
+
+ if (!mode_transfer_is_animation_running(animation_time)) {
+ return;
+ }
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ !DRW_state_is_image_render();
+ const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
+
+ DRWShadingGroup *mode_transfer_grp[2];
+
+ for (int i = 0; i < 2; i++) {
+ GPUShader *sh = OVERLAY_shader_uniform_color();
+ mode_transfer_grp[i] = DRW_shgroup_create(sh, psl->mode_transfer_ps[i]);
+ DRW_shgroup_uniform_block(mode_transfer_grp[i], "globalsBlock", G_draw.block_ubo);
+
+ float color[4];
+ UI_GetThemeColor3fv(TH_VERTEX_SELECT, color);
+ color[3] = mode_transfer_alpha_for_animation_time_get(animation_time);
+ srgb_to_linearrgb_v4(color, color);
+ DRW_shgroup_uniform_vec4_copy(mode_transfer_grp[i], "color", color);
+ }
+
+ if (!pd->use_in_front) {
+ mode_transfer_grp[IN_FRONT] = mode_transfer_grp[NOT_IN_FRONT];
+ }
+
+ pd->mode_transfer.any_animated = true;
+
+ if (use_sculpt_pbvh) {
+ DRW_shgroup_call_sculpt(mode_transfer_grp[is_xray], ob, false, false);
+ }
+ else {
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ DRW_shgroup_call(mode_transfer_grp[is_xray], geom, ob);
+ }
+ }
+}
+
+void OVERLAY_mode_transfer_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ DRW_draw_pass(psl->mode_transfer_ps[NOT_IN_FRONT]);
+}
+
+void OVERLAY_mode_transfer_infront_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ DRW_draw_pass(psl->mode_transfer_ps[IN_FRONT]);
+}
+
+void OVERLAY_mode_transfer_cache_finish(OVERLAY_Data *vedata)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ if (pd->mode_transfer.any_animated) {
+ DRW_viewport_request_redraw();
+ }
+ pd->mode_transfer.any_animated = false;
+}
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index 48b7b53a5ba..a92f11aca38 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -190,7 +190,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
if ((show_keyframes && show_keyframes_no && is_keyframe) || (show_frame_no && (i == 0))) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), " %d", frame);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), " %d", frame);
DRW_text_cache_add(
dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, (is_keyframe) ? col_kf : col);
}
@@ -200,7 +200,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
/* Only draw frame number if several consecutive highlighted points
* don't occur on same point. */
if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), " %d", frame);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), " %d", frame);
DRW_text_cache_add(dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, col);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index db43136e308..969289a3219 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -107,6 +107,7 @@ typedef struct OVERLAY_PassList {
DRWPass *gpencil_canvas_ps;
DRWPass *facing_ps[2];
DRWPass *fade_ps[2];
+ DRWPass *mode_transfer_ps[2];
DRWPass *grid_ps;
DRWPass *image_background_ps;
DRWPass *image_background_scene_ps;
@@ -282,6 +283,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *extra_grid_grp;
DRWShadingGroup *facing_grp[2];
DRWShadingGroup *fade_grp[2];
+ DRWShadingGroup *flash_grp[2];
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *outlines_grp;
@@ -414,6 +416,10 @@ typedef struct OVERLAY_PrivateData {
struct {
DRWCallBuffer *handle[2];
} mball;
+ struct {
+ double time;
+ bool any_animated;
+ } mode_transfer;
} OVERLAY_PrivateData; /* Transient data */
typedef struct OVERLAY_StorageList {
@@ -607,6 +613,12 @@ void OVERLAY_fade_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_fade_draw(OVERLAY_Data *vedata);
void OVERLAY_fade_infront_draw(OVERLAY_Data *vedata);
+void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_mode_transfer_draw(OVERLAY_Data *vedata);
+void OVERLAY_mode_transfer_infront_draw(OVERLAY_Data *vedata);
+void OVERLAY_mode_transfer_cache_finish(OVERLAY_Data *vedata);
+
void OVERLAY_grid_init(OVERLAY_Data *vedata);
void OVERLAY_grid_cache_init(OVERLAY_Data *vedata);
void OVERLAY_grid_draw(OVERLAY_Data *vedata);
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 2545cfa65dc..5071658fd82 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -438,6 +438,10 @@ void DRW_shgroup_call_range(
void DRW_shgroup_call_instance_range(
DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct);
+void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
+ int groups_x_len,
+ int groups_y_len,
+ int groups_z_len);
void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_count);
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_count);
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, Object *ob, uint tri_count);
@@ -575,6 +579,9 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
const char *name,
const float (*value)[4],
int arraysize);
+void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUVertBuf *vertex_buffer);
bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index bbb97fc09a3..810deaec349 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -24,6 +24,10 @@
struct TaskGraph;
+#include "GPU_batch.h"
+#include "GPU_index_buffer.h"
+#include "GPU_vertex_buffer.h"
+
/* Vertex Group Selection and display options */
typedef struct DRW_MeshWeightState {
int defgroup_active;
@@ -64,13 +68,13 @@ typedef struct DRW_MeshCDMask {
* bit-wise and atomic operations are used to compare and update the struct.
* See `mesh_cd_layers_type_*` functions. */
BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint64_t), "DRW_MeshCDMask exceeds 64 bits")
-
typedef enum eMRIterType {
MR_ITER_LOOPTRI = 1 << 0,
MR_ITER_POLY = 1 << 1,
MR_ITER_LEDGE = 1 << 2,
MR_ITER_LVERT = 1 << 3,
} eMRIterType;
+ENUM_OPERATORS(eMRIterType, MR_ITER_LVERT)
typedef enum eMRDataType {
MR_DATA_POLY_NOR = 1 << 1,
@@ -79,12 +83,11 @@ typedef enum eMRDataType {
/** Force loop normals calculation. */
MR_DATA_TAN_LOOP_NOR = 1 << 4,
} eMRDataType;
+ENUM_OPERATORS(eMRDataType, MR_DATA_TAN_LOOP_NOR)
-typedef enum eMRExtractType {
- MR_EXTRACT_BMESH,
- MR_EXTRACT_MAPPED,
- MR_EXTRACT_MESH,
-} eMRExtractType;
+#ifdef __cplusplus
+extern "C" {
+#endif
BLI_INLINE int mesh_render_mat_len_get(Mesh *me)
{
@@ -150,6 +153,18 @@ typedef struct MeshBufferCache {
GPUIndexBuf **tris_per_mat;
} MeshBufferCache;
+/**
+ * Data that are kept around between extractions to reduce rebuilding time.
+ *
+ * - Loose geometry.
+ */
+typedef struct MeshBufferExtractionCache {
+ int edge_loose_len;
+ int vert_loose_len;
+ int *lverts;
+ int *ledges;
+} MeshBufferExtractionCache;
+
typedef enum DRWBatchFlag {
MBC_SURFACE = (1 << 0),
MBC_SURFACE_WEIGHTS = (1 << 1),
@@ -195,6 +210,10 @@ typedef enum DRWBatchFlag {
typedef struct MeshBatchCache {
MeshBufferCache final, cage, uv_cage;
+ MeshBufferExtractionCache final_extraction_cache;
+ MeshBufferExtractionCache cage_extraction_cache;
+ MeshBufferExtractionCache uv_cage_extraction_cache;
+
struct {
/* Surfaces / Render */
GPUBatch *surface;
@@ -264,9 +283,14 @@ typedef struct MeshBatchCache {
bool no_loose_wire;
} MeshBatchCache;
+#define MBC_BATCH_LEN (sizeof(((MeshBatchCache){0}).batch) / sizeof(void *))
+#define MBC_VBO_LEN (sizeof(((MeshBufferCache){0}).vbo) / sizeof(void *))
+#define MBC_IBO_LEN (sizeof(((MeshBufferCache){0}).ibo) / sizeof(void *))
+
void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
MeshBatchCache *cache,
- MeshBufferCache mbc,
+ MeshBufferCache *mbc,
+ MeshBufferExtractionCache *extraction_cache,
Mesh *me,
const bool is_editmode,
const bool is_paint_mode,
@@ -275,7 +299,10 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
const bool do_final,
const bool do_uvedit,
const bool use_subsurf_fdots,
- const DRW_MeshCDMask *cd_layer_used,
const Scene *scene,
const ToolSettings *ts,
const bool use_hide);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
new file mode 100644
index 00000000000..fca40206659
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -0,0 +1,1004 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Extraction of Mesh data into VBO to feed to GPU.
+ */
+#include "MEM_guardedalloc.h"
+
+#include "atomic_ops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_task.h"
+#include "BLI_vector.hh"
+
+#include "BKE_editmesh.h"
+
+#include "GPU_capabilities.h"
+
+#include "draw_cache_extract.h"
+#include "draw_cache_extract_mesh_private.h"
+#include "draw_cache_inline.h"
+
+// #define DEBUG_TIME
+
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
+#define CHUNK_SIZE 8192
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract Struct
+ * \{ */
+
+struct ExtractorRunData {
+ /* Extractor where this run data belongs to. */
+ const MeshExtract *extractor;
+ /* During iteration the VBO/IBO that is being build. */
+ void *buffer = nullptr;
+ /* User data during iteration. Created in MeshExtract.init and passed along to other MeshExtract
+ * functions. */
+ void *user_data = nullptr;
+
+ ExtractorRunData(const MeshExtract *extractor) : extractor(extractor)
+ {
+ }
+};
+
+class ExtractorRunDatas : public Vector<ExtractorRunData> {
+ public:
+ void filter_into(ExtractorRunDatas &result, eMRIterType iter_type) const
+ {
+ for (const ExtractorRunData &data : *this) {
+ const MeshExtract *extractor = data.extractor;
+ if ((iter_type & MR_ITER_LOOPTRI) && extractor->iter_looptri_bm) {
+ BLI_assert(extractor->iter_looptri_mesh);
+ result.append(data);
+ continue;
+ }
+ if ((iter_type & MR_ITER_POLY) && extractor->iter_poly_bm) {
+ BLI_assert(extractor->iter_poly_mesh);
+ result.append(data);
+ continue;
+ }
+ if ((iter_type & MR_ITER_LEDGE) && extractor->iter_ledge_bm) {
+ BLI_assert(extractor->iter_ledge_mesh);
+ result.append(data);
+ continue;
+ }
+ if ((iter_type & MR_ITER_LVERT) && extractor->iter_lvert_bm) {
+ BLI_assert(extractor->iter_lvert_mesh);
+ result.append(data);
+ continue;
+ }
+ }
+ }
+
+ void filter_threaded_extractors_into(ExtractorRunDatas &result)
+ {
+ for (const ExtractorRunData &data : *this) {
+ const MeshExtract *extractor = data.extractor;
+ if (extractor->use_threading) {
+ result.append(extractor);
+ }
+ }
+ }
+
+ eMRIterType iter_types()
+ {
+ eMRIterType iter_type = static_cast<eMRIterType>(0);
+
+ for (const ExtractorRunData &data : *this) {
+ const MeshExtract *extractor = data.extractor;
+ iter_type |= mesh_extract_iter_type(extractor);
+ }
+ return iter_type;
+ }
+
+ eMRDataType data_types()
+ {
+ eMRDataType data_type = static_cast<eMRDataType>(0);
+ for (const ExtractorRunData &data : *this) {
+ const MeshExtract *extractor = data.extractor;
+ data_type |= extractor->data_type;
+ }
+ return data_type;
+ }
+};
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract
+ * \{ */
+
+BLI_INLINE void extract_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ ExtractorRunDatas &extractors,
+ MeshBufferCache *mbc)
+{
+ /* Multi thread. */
+ for (ExtractorRunData &run_data : extractors) {
+ const MeshExtract *extractor = run_data.extractor;
+ run_data.buffer = mesh_extract_buffer_get(extractor, mbc);
+ run_data.user_data = extractor->init(mr, cache, run_data.buffer);
+ }
+}
+
+BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr,
+ const ExtractTriBMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LOOPTRI);
+
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, elt_index, params)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_looptri_bm(mr, elt, elt_index, run_data.user_data);
+ }
+ }
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
+}
+
+BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr,
+ const ExtractTriMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LOOPTRI);
+
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, mlt_index, params)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_looptri_mesh(mr, mlt, mlt_index, run_data.user_data);
+ }
+ }
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
+}
+
+BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_POLY);
+
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_poly_bm(mr, f, f_index, run_data.user_data);
+ }
+ }
+ EXTRACT_POLY_FOREACH_BM_END;
+}
+
+BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_POLY);
+
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_poly_mesh(mr, mp, mp_index, run_data.user_data);
+ }
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
+}
+
+BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LEDGE);
+
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_ledge_bm(mr, eed, ledge_index, run_data.user_data);
+ }
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
+}
+
+BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LEDGE);
+
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_ledge_mesh(mr, med, ledge_index, run_data.user_data);
+ }
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
+}
+
+BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LVERT);
+
+ EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_lvert_bm(mr, eve, lvert_index, run_data.user_data);
+ }
+ }
+ EXTRACT_LVERT_FOREACH_BM_END;
+}
+
+BLI_INLINE void extract_iter_lvert_mesh(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ const ExtractorRunDatas &all_extractors)
+{
+ ExtractorRunDatas extractors;
+ all_extractors.filter_into(extractors, MR_ITER_LVERT);
+
+ EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+ {
+ for (ExtractorRunData &run_data : extractors) {
+ run_data.extractor->iter_lvert_mesh(mr, mv, lvert_index, run_data.user_data);
+ }
+ }
+ EXTRACT_LVERT_FOREACH_MESH_END;
+}
+
+BLI_INLINE void extract_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ const ExtractorRunDatas &extractors)
+{
+ for (const ExtractorRunData &run_data : extractors) {
+ const MeshExtract *extractor = run_data.extractor;
+ if (extractor->finish) {
+ extractor->finish(mr, cache, run_data.buffer, run_data.user_data);
+ }
+ }
+}
+
+/* Single Thread. */
+BLI_INLINE void extract_run_and_finish_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ ExtractorRunDatas &extractors,
+ eMRIterType iter_type,
+ MeshBufferCache *mbc)
+{
+ extract_init(mr, cache, extractors, mbc);
+
+ bool is_mesh = mr->extract_type != MR_EXTRACT_BMESH;
+ if (iter_type & MR_ITER_LOOPTRI) {
+ if (is_mesh) {
+ ExtractTriMesh_Params params;
+ params.mlooptri = mr->mlooptri;
+ params.tri_range[0] = 0;
+ params.tri_range[1] = mr->tri_len;
+ extract_iter_looptri_mesh(mr, &params, extractors);
+ }
+ else {
+ ExtractTriBMesh_Params params;
+ params.looptris = mr->edit_bmesh->looptris;
+ params.tri_range[0] = 0;
+ params.tri_range[1] = mr->tri_len;
+ extract_iter_looptri_bm(mr, &params, extractors);
+ }
+ }
+ if (iter_type & MR_ITER_POLY) {
+ if (is_mesh) {
+ ExtractPolyMesh_Params params;
+ params.poly_range[0] = 0;
+ params.poly_range[1] = mr->poly_len;
+ extract_iter_poly_mesh(mr, &params, extractors);
+ }
+ else {
+ ExtractPolyBMesh_Params params;
+ params.poly_range[0] = 0;
+ params.poly_range[1] = mr->poly_len;
+ extract_iter_poly_bm(mr, &params, extractors);
+ }
+ }
+ if (iter_type & MR_ITER_LEDGE) {
+ if (is_mesh) {
+ ExtractLEdgeMesh_Params params;
+ params.ledge = mr->ledges;
+ params.ledge_range[0] = 0;
+ params.ledge_range[1] = mr->edge_loose_len;
+ extract_iter_ledge_mesh(mr, &params, extractors);
+ }
+ else {
+ ExtractLEdgeBMesh_Params params;
+ params.ledge = mr->ledges;
+ params.ledge_range[0] = 0;
+ params.ledge_range[1] = mr->edge_loose_len;
+ extract_iter_ledge_bm(mr, &params, extractors);
+ }
+ }
+ if (iter_type & MR_ITER_LVERT) {
+ if (is_mesh) {
+ ExtractLVertMesh_Params params;
+ params.lvert = mr->lverts;
+ params.lvert_range[0] = 0;
+ params.lvert_range[1] = mr->vert_loose_len;
+ extract_iter_lvert_mesh(mr, &params, extractors);
+ }
+ else {
+ ExtractLVertBMesh_Params params;
+ params.lvert = mr->lverts;
+ params.lvert_range[0] = 0;
+ params.lvert_range[1] = mr->vert_loose_len;
+ extract_iter_lvert_bm(mr, &params, extractors);
+ }
+ }
+ extract_finish(mr, cache, extractors);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name ExtractTaskData
+ * \{ */
+struct ExtractTaskData {
+ const MeshRenderData *mr = nullptr;
+ MeshBatchCache *cache = nullptr;
+ /* #UserData is shared between the iterations as it holds counters to detect if the
+ * extraction is finished. To make sure the duplication of the user_data does not create a new
+ * instance of the counters we allocate the user_data in its own container.
+ *
+ * This structure makes sure that when extract_init is called, that the user data of all
+ * iterations are updated. */
+
+ ExtractorRunDatas *extractors = nullptr;
+ MeshBufferCache *mbc = nullptr;
+ int32_t *task_counter = nullptr;
+
+ eMRIterType iter_type;
+ int start = 0;
+ int end = INT_MAX;
+ /** Decremented each time a task is finished. */
+
+ ExtractTaskData(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ ExtractorRunDatas *extractors,
+ MeshBufferCache *mbc,
+ int32_t *task_counter)
+ : mr(mr), cache(cache), extractors(extractors), mbc(mbc), task_counter(task_counter)
+ {
+ iter_type = extractors->iter_types();
+ };
+
+ ExtractTaskData(const ExtractTaskData &src) = default;
+
+ ~ExtractTaskData()
+ {
+ delete extractors;
+ }
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("DRW:ExtractTaskData")
+#endif
+};
+
+static ExtractTaskData *extract_extract_iter_task_data_create_mesh(const MeshRenderData *mr,
+ MeshBatchCache *cache,
+ ExtractorRunDatas *extractors,
+ MeshBufferCache *mbc,
+ int32_t *task_counter)
+
+{
+ ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbc, task_counter);
+ return taskdata;
+}
+
+static void extract_task_data_free(void *data)
+{
+ ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data);
+ delete task_data;
+}
+
+static void extract_task_data_free_ex(void *data)
+{
+ ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data);
+ task_data->extractors = nullptr;
+ delete task_data;
+}
+
+BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
+ const eMRIterType iter_type,
+ int start,
+ int end,
+ ExtractorRunDatas &extractors)
+{
+ switch (mr->extract_type) {
+ case MR_EXTRACT_BMESH:
+ if (iter_type & MR_ITER_LOOPTRI) {
+ ExtractTriBMesh_Params params;
+ params.looptris = mr->edit_bmesh->looptris;
+ params.tri_range[0] = start;
+ params.tri_range[1] = min_ii(mr->tri_len, end);
+ extract_iter_looptri_bm(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_POLY) {
+ ExtractPolyBMesh_Params params;
+ params.poly_range[0] = start;
+ params.poly_range[1] = min_ii(mr->poly_len, end);
+ extract_iter_poly_bm(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_LEDGE) {
+ ExtractLEdgeBMesh_Params params;
+ params.ledge = mr->ledges;
+ params.ledge_range[0] = start;
+ params.ledge_range[1] = min_ii(mr->edge_loose_len, end);
+ extract_iter_ledge_bm(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_LVERT) {
+ ExtractLVertBMesh_Params params;
+ params.lvert = mr->lverts;
+ params.lvert_range[0] = start;
+ params.lvert_range[1] = min_ii(mr->vert_loose_len, end);
+ extract_iter_lvert_bm(mr, &params, extractors);
+ }
+ break;
+ case MR_EXTRACT_MAPPED:
+ case MR_EXTRACT_MESH:
+ if (iter_type & MR_ITER_LOOPTRI) {
+ ExtractTriMesh_Params params;
+ params.mlooptri = mr->mlooptri;
+ params.tri_range[0] = start;
+ params.tri_range[1] = min_ii(mr->tri_len, end);
+ extract_iter_looptri_mesh(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_POLY) {
+ ExtractPolyMesh_Params params;
+ params.poly_range[0] = start;
+ params.poly_range[1] = min_ii(mr->poly_len, end);
+ extract_iter_poly_mesh(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_LEDGE) {
+ ExtractLEdgeMesh_Params params;
+ params.ledge = mr->ledges;
+ params.ledge_range[0] = start;
+ params.ledge_range[1] = min_ii(mr->edge_loose_len, end);
+ extract_iter_ledge_mesh(mr, &params, extractors);
+ }
+ if (iter_type & MR_ITER_LVERT) {
+ ExtractLVertMesh_Params params;
+ params.lvert = mr->lverts;
+ params.lvert_range[0] = start;
+ params.lvert_range[1] = min_ii(mr->vert_loose_len, end);
+ extract_iter_lvert_mesh(mr, &params, extractors);
+ }
+ break;
+ }
+}
+
+static void extract_task_init(ExtractTaskData *data)
+{
+ extract_init(data->mr, data->cache, *data->extractors, data->mbc);
+}
+
+static void extract_task_run(void *__restrict taskdata)
+{
+ ExtractTaskData *data = (ExtractTaskData *)taskdata;
+ mesh_extract_iter(data->mr, data->iter_type, data->start, data->end, *data->extractors);
+
+ /* If this is the last task, we do the finish function. */
+ int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1);
+ if (remainin_tasks == 0) {
+ extract_finish(data->mr, data->cache, *data->extractors);
+ }
+}
+
+static void extract_task_init_and_run(void *__restrict taskdata)
+{
+ ExtractTaskData *data = (ExtractTaskData *)taskdata;
+ extract_run_and_finish_init(
+ data->mr, data->cache, *data->extractors, data->iter_type, data->mbc);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Update Mesh Render Data
+ * \{ */
+struct MeshRenderDataUpdateTaskData {
+ MeshRenderData *mr = nullptr;
+ eMRIterType iter_type;
+ eMRDataType data_flag;
+
+ ~MeshRenderDataUpdateTaskData()
+ {
+ mesh_render_data_free(mr);
+ }
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("DRW:MeshRenderDataUpdateTaskData")
+#endif
+};
+
+static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ delete taskdata;
+}
+
+static void mesh_extract_render_data_node_exec(void *__restrict task_data)
+{
+ MeshRenderDataUpdateTaskData *update_task_data = static_cast<MeshRenderDataUpdateTaskData *>(
+ task_data);
+ MeshRenderData *mr = update_task_data->mr;
+ const eMRIterType iter_type = update_task_data->iter_type;
+ const eMRDataType data_flag = update_task_data->data_flag;
+
+ mesh_render_data_update_normals(mr, data_flag);
+ mesh_render_data_update_looptris(mr, iter_type, data_flag);
+}
+
+static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
+ MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ MeshRenderDataUpdateTaskData *task_data = new (MeshRenderDataUpdateTaskData);
+ task_data->mr = mr;
+ task_data->iter_type = iter_type;
+ task_data->data_flag = data_flag;
+
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ mesh_extract_render_data_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Extract Single Threaded
+ * \{ */
+
+static struct TaskNode *extract_single_threaded_task_node_create(struct TaskGraph *task_graph,
+ ExtractTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ extract_task_init_and_run,
+ task_data,
+ (TaskGraphNodeFreeFunction)extract_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - UserData Initializer
+ * \{ */
+struct UserDataInitTaskData {
+ ExtractTaskData *td;
+ int32_t task_counter = 0;
+
+ ~UserDataInitTaskData()
+ {
+ extract_task_data_free(td);
+ }
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("DRW:UserDataInitTaskData")
+#endif
+};
+
+static void user_data_init_task_data_free(UserDataInitTaskData *taskdata)
+{
+ delete taskdata;
+}
+
+static void user_data_init_task_data_exec(void *__restrict task_data)
+{
+ UserDataInitTaskData *extract_task_data = static_cast<UserDataInitTaskData *>(task_data);
+ ExtractTaskData *taskdata_base = extract_task_data->td;
+ extract_task_init(taskdata_base);
+}
+
+static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph,
+ UserDataInitTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ user_data_init_task_data_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)user_data_init_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loop
+ * \{ */
+
+static void extract_range_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_user_data_init,
+ ExtractTaskData *taskdata,
+ const eMRIterType type,
+ int start,
+ int length)
+{
+ taskdata = new ExtractTaskData(*taskdata);
+ atomic_add_and_fetch_int32(taskdata->task_counter, 1);
+ taskdata->iter_type = type;
+ taskdata->start = start;
+ taskdata->end = start + length;
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph, extract_task_run, taskdata, extract_task_data_free_ex);
+ BLI_task_graph_edge_create(task_node_user_data_init, task_node);
+}
+
+static int extract_range_task_num_elements_get(const MeshRenderData *mr,
+ const eMRIterType iter_type)
+{
+ /* Divide task into sensible chunks. */
+ int iter_len = 0;
+ if (iter_type & MR_ITER_LOOPTRI) {
+ iter_len += mr->tri_len;
+ }
+ if (iter_type & MR_ITER_POLY) {
+ iter_len += mr->poly_len;
+ }
+ if (iter_type & MR_ITER_LEDGE) {
+ iter_len += mr->edge_loose_len;
+ }
+ if (iter_type & MR_ITER_LVERT) {
+ iter_len += mr->vert_loose_len;
+ }
+ return iter_len;
+}
+
+static int extract_range_task_chunk_size_get(const MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const int num_threads)
+{
+ /* Divide task into sensible chunks. */
+ const int num_elements = extract_range_task_num_elements_get(mr, iter_type);
+ int range_len = (num_elements + num_threads) / num_threads;
+ CLAMP_MIN(range_len, CHUNK_SIZE);
+ return range_len;
+}
+
+static void extract_task_in_ranges_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_user_data_init,
+ ExtractTaskData *taskdata_base,
+ const int num_threads)
+{
+ const MeshRenderData *mr = taskdata_base->mr;
+ const int range_len = extract_range_task_chunk_size_get(
+ mr, taskdata_base->iter_type, num_threads);
+
+ if (taskdata_base->iter_type & MR_ITER_LOOPTRI) {
+ for (int i = 0; i < mr->tri_len; i += range_len) {
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LOOPTRI, i, range_len);
+ }
+ }
+ if (taskdata_base->iter_type & MR_ITER_POLY) {
+ for (int i = 0; i < mr->poly_len; i += range_len) {
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata_base, MR_ITER_POLY, i, range_len);
+ }
+ }
+ if (taskdata_base->iter_type & MR_ITER_LEDGE) {
+ for (int i = 0; i < mr->edge_loose_len; i += range_len) {
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LEDGE, i, range_len);
+ }
+ }
+ if (taskdata_base->iter_type & MR_ITER_LVERT) {
+ for (int i = 0; i < mr->vert_loose_len; i += range_len) {
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LVERT, i, range_len);
+ }
+ }
+}
+
+static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
+ MeshBufferCache *mbc,
+ MeshBufferExtractionCache *extraction_cache,
+ Mesh *me,
+
+ const bool is_editmode,
+ const bool is_paint_mode,
+ const bool is_mode_active,
+ const float obmat[4][4],
+ const bool do_final,
+ const bool do_uvedit,
+ const bool use_subsurf_fdots,
+ const Scene *scene,
+ const ToolSettings *ts,
+ const bool use_hide)
+{
+ /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
+ * This sub-graph starts with an extract_render_data_node. This fills/converts the required
+ * data from Mesh.
+ *
+ * Small extractions and extractions that can't be multi-threaded are grouped in a single
+ * `extract_single_threaded_task_node`.
+ *
+ * Other extractions will create a node for each loop exceeding 8192 items. these nodes are
+ * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the
+ * user_data needed for the extraction based on the data extracted from the mesh.
+ * counters are used to check if the finalize of a task has to be called.
+ *
+ * Mesh extraction sub graph
+ *
+ * +----------------------+
+ * +-----> | extract_task1_loop_1 |
+ * | +----------------------+
+ * +------------------+ +----------------------+ +----------------------+
+ * | mesh_render_data | --> | | --> | extract_task1_loop_2 |
+ * +------------------+ | | +----------------------+
+ * | | | +----------------------+
+ * | | user_data_init | --> | extract_task2_loop_1 |
+ * v | | +----------------------+
+ * +------------------+ | | +----------------------+
+ * | single_threaded | | | --> | extract_task2_loop_2 |
+ * +------------------+ +----------------------+ +----------------------+
+ * | +----------------------+
+ * +-----> | extract_task2_loop_3 |
+ * +----------------------+
+ */
+ const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
+ GPU_use_hq_normals_workaround();
+
+ /* Create an array containing all the extractors that needs to be executed. */
+ ExtractorRunDatas extractors;
+
+#define EXTRACT_ADD_REQUESTED(type, type_lowercase, name) \
+ do { \
+ if (DRW_##type_lowercase##_requested(mbc->type_lowercase.name)) { \
+ const MeshExtract *extractor = mesh_extract_override_get(&extract_##name, do_hq_normals); \
+ extractors.append(extractor); \
+ } \
+ } while (0)
+
+ EXTRACT_ADD_REQUESTED(VBO, vbo, pos_nor);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, lnor);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, uv);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, tan);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, vcol);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, sculpt_data);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, orco);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edge_fac);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, weights);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edit_data);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_data);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_stretch_area);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_stretch_angle);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, mesh_analysis);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_pos);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_nor);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_uv);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_edituv_data);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, poly_idx);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, edge_idx);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, vert_idx);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, fdot_idx);
+ EXTRACT_ADD_REQUESTED(VBO, vbo, skin_roots);
+
+ EXTRACT_ADD_REQUESTED(IBO, ibo, tris);
+ if (DRW_ibo_requested(mbc->ibo.lines)) {
+ const MeshExtract *extractor;
+ if (mbc->ibo.lines_loose != nullptr) {
+ /* Update #lines_loose ibo. */
+ extractor = &extract_lines_with_lines_loose;
+ }
+ else {
+ extractor = &extract_lines;
+ }
+ extractors.append(extractor);
+ }
+ else if (DRW_ibo_requested(mbc->ibo.lines_loose)) {
+ /* Note: #ibo.lines must have been created first. */
+ const MeshExtract *extractor = &extract_lines_loose_only;
+ extractors.append(extractor);
+ }
+ EXTRACT_ADD_REQUESTED(IBO, ibo, points);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, fdots);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, lines_paint_mask);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, lines_adjacency);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_tris);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_lines);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_points);
+ EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_fdots);
+
+#undef EXTRACT_ADD_REQUESTED
+
+ if (extractors.is_empty()) {
+ return;
+ }
+
+#ifdef DEBUG_TIME
+ double rdata_start = PIL_check_seconds_timer();
+#endif
+
+ eMRIterType iter_type = extractors.iter_types();
+ eMRDataType data_flag = extractors.data_types();
+
+ MeshRenderData *mr = mesh_render_data_create(me,
+ extraction_cache,
+ is_editmode,
+ is_paint_mode,
+ is_mode_active,
+ obmat,
+ do_final,
+ do_uvedit,
+ ts,
+ iter_type);
+ mr->use_hide = use_hide;
+ mr->use_subsurf_fdots = use_subsurf_fdots;
+ mr->use_final_mesh = do_final;
+
+#ifdef DEBUG_TIME
+ double rdata_end = PIL_check_seconds_timer();
+#endif
+
+ struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
+ task_graph, mr, iter_type, data_flag);
+
+ /* Simple heuristic. */
+ const bool use_thread = (mr->loop_len + mr->loop_loose_len) > CHUNK_SIZE;
+
+ if (use_thread) {
+ uint single_threaded_extractors_len = 0;
+
+ /* First run the requested extractors that do not support asynchronous ranges. */
+ for (const ExtractorRunData &run_data : extractors) {
+ const MeshExtract *extractor = run_data.extractor;
+ if (!extractor->use_threading) {
+ ExtractorRunDatas *single_threaded_extractors = new ExtractorRunDatas();
+ single_threaded_extractors->append(extractor);
+ ExtractTaskData *taskdata = extract_extract_iter_task_data_create_mesh(
+ mr, cache, single_threaded_extractors, mbc, nullptr);
+ struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph,
+ taskdata);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
+ single_threaded_extractors_len++;
+ }
+ }
+
+ /* Distribute the remaining extractors into ranges per core. */
+ ExtractorRunDatas *multi_threaded_extractors = new ExtractorRunDatas();
+ extractors.filter_threaded_extractors_into(*multi_threaded_extractors);
+ if (!multi_threaded_extractors->is_empty()) {
+ /*
+ * Determine the number of thread to use for multithreading.
+ * Thread can be used for single threaded tasks. These typically take longer to execute so
+ * fill the rest of the threads for range operations.
+ */
+ int num_threads = BLI_task_scheduler_num_threads();
+ num_threads -= single_threaded_extractors_len % num_threads;
+
+ UserDataInitTaskData *user_data_init_task_data = new UserDataInitTaskData();
+ struct TaskNode *task_node_user_data_init = user_data_init_task_node_create(
+ task_graph, user_data_init_task_data);
+
+ user_data_init_task_data->td = extract_extract_iter_task_data_create_mesh(
+ mr, cache, multi_threaded_extractors, mbc, &user_data_init_task_data->task_counter);
+
+ extract_task_in_ranges_create(
+ task_graph, task_node_user_data_init, user_data_init_task_data->td, num_threads);
+
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init);
+ }
+ else {
+ /* No tasks created freeing extractors list. */
+ delete multi_threaded_extractors;
+ }
+ }
+ else {
+ /* Run all requests on the same thread. */
+ ExtractorRunDatas *extractors_copy = new ExtractorRunDatas(extractors);
+ ExtractTaskData *taskdata = extract_extract_iter_task_data_create_mesh(
+ mr, cache, extractors_copy, mbc, nullptr);
+
+ struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph, taskdata);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
+ }
+
+ /* Trigger the sub-graph for this mesh. */
+ BLI_task_graph_node_push_work(task_node_mesh_render_data);
+
+#ifdef DEBUG_TIME
+ BLI_task_graph_work_and_wait(task_graph);
+ double end = PIL_check_seconds_timer();
+
+ static double avg = 0;
+ static double avg_fps = 0;
+ static double avg_rdata = 0;
+ static double end_prev = 0;
+
+ if (end_prev == 0) {
+ end_prev = end;
+ }
+
+ avg = avg * 0.95 + (end - rdata_end) * 0.05;
+ avg_fps = avg_fps * 0.95 + (end - end_prev) * 0.05;
+ avg_rdata = avg_rdata * 0.95 + (rdata_end - rdata_start) * 0.05;
+
+ printf(
+ "rdata %.0fms iter %.0fms (frame %.0fms)\n", avg_rdata * 1000, avg * 1000, avg_fps * 1000);
+
+ end_prev = end;
+#endif
+}
+
+} // namespace blender::draw
+
+extern "C" {
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
+ MeshBufferCache *mbc,
+ MeshBufferExtractionCache *extraction_cache,
+ Mesh *me,
+
+ const bool is_editmode,
+ const bool is_paint_mode,
+ const bool is_mode_active,
+ const float obmat[4][4],
+ const bool do_final,
+ const bool do_uvedit,
+ const bool use_subsurf_fdots,
+ const Scene *scene,
+ const ToolSettings *ts,
+ const bool use_hide)
+{
+ blender::draw::mesh_buffer_cache_create_requested(task_graph,
+ cache,
+ mbc,
+ extraction_cache,
+ me,
+ is_editmode,
+ is_paint_mode,
+ is_mode_active,
+ obmat,
+ do_final,
+ do_uvedit,
+ use_subsurf_fdots,
+ scene,
+ ts,
+ use_hide);
+}
+
+} // extern "C"
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c
index f167ea3d540..0a3945291bb 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c
@@ -13,7 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
@@ -25,773 +25,82 @@
#include "MEM_guardedalloc.h"
-#include "BLI_alloca.h"
-#include "BLI_bitmap.h"
-#include "BLI_buffer.h"
+#include "atomic_ops.h"
+
+#include "DNA_object_types.h"
+
#include "BLI_edgehash.h"
#include "BLI_jitter_2d.h"
-#include "BLI_math_bits.h"
-#include "BLI_math_vector.h"
+#include "BLI_kdopbvh.h"
#include "BLI_string.h"
-#include "BLI_task.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "BKE_bvhutils.h"
-#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_tangent.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_mesh_tangent.h"
-#include "BKE_modifier.h"
-#include "BKE_object_deform.h"
#include "BKE_paint.h"
-#include "atomic_ops.h"
-
-#include "bmesh.h"
+#include "ED_uvedit.h"
-#include "GPU_batch.h"
#include "GPU_capabilities.h"
-#include "DRW_render.h"
-
-#include "ED_mesh.h"
-#include "ED_uvedit.h"
-
+#include "draw_cache_extract_mesh_private.h"
#include "draw_cache_impl.h"
-#include "draw_cache_inline.h"
-
-#include "draw_cache_extract.h"
-
-// #define DEBUG_TIME
-
-#ifdef DEBUG_TIME
-# include "PIL_time_utildefines.h"
-#endif
-
-/* ---------------------------------------------------------------------- */
-/** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
- * \{ */
-
-typedef struct MeshRenderData {
- eMRExtractType extract_type;
-
- int poly_len, edge_len, vert_len, loop_len;
- int edge_loose_len;
- int vert_loose_len;
- int loop_loose_len;
- int tri_len;
- int mat_len;
-
- bool use_hide;
- bool use_subsurf_fdots;
- bool use_final_mesh;
-
- /** Use for #MeshStatVis calculation which use world-space coords. */
- float obmat[4][4];
-
- const ToolSettings *toolsettings;
- /** Edit Mesh */
- BMEditMesh *edit_bmesh;
- BMesh *bm;
- EditMeshData *edit_data;
-
- /* For deformed edit-mesh data. */
- /* Use for #ME_WRAPPER_TYPE_BMESH. */
- const float (*bm_vert_coords)[3];
- const float (*bm_vert_normals)[3];
- const float (*bm_poly_normals)[3];
- const float (*bm_poly_centers)[3];
-
- int *v_origindex, *e_origindex, *p_origindex;
- int crease_ofs;
- int bweight_ofs;
- int freestyle_edge_ofs;
- int freestyle_face_ofs;
- /** Mesh */
- Mesh *me;
- const MVert *mvert;
- const MEdge *medge;
- const MLoop *mloop;
- const MPoly *mpoly;
- BMVert *eve_act;
- BMEdge *eed_act;
- BMFace *efa_act;
- BMFace *efa_act_uv;
- /* Data created on-demand (usually not for #BMesh based data). */
- MLoopTri *mlooptri;
- float (*loop_normals)[3];
- float (*poly_normals)[3];
- int *lverts, *ledges;
-} MeshRenderData;
-
-static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
- const eMRIterType iter_type,
- const eMRDataType UNUSED(data_flag))
-{
- if (mr->extract_type != MR_EXTRACT_BMESH) {
- /* Mesh */
- if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
- mr->vert_loose_len = 0;
- mr->edge_loose_len = 0;
-
- BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
-
- mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__);
- 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, 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));
- }
-
- mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__);
- for (int v = 0; v < mr->vert_len; v++) {
- if (!BLI_BITMAP_TEST(lvert_map, v)) {
- mr->lverts[mr->vert_loose_len++] = v;
- }
- }
- if (mr->vert_loose_len < mr->vert_len) {
- mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts));
- }
-
- MEM_freeN(lvert_map);
-
- mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
- }
- }
- else {
- /* #BMesh */
- BMesh *bm = mr->bm;
- if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
- int elem_id;
- BMIter iter;
- BMVert *eve;
- BMEdge *ede;
- mr->vert_loose_len = 0;
- mr->edge_loose_len = 0;
-
- mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__);
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) {
- if (eve->e == NULL) {
- mr->lverts[mr->vert_loose_len++] = elem_id;
- }
- }
- if (mr->vert_loose_len < mr->vert_len) {
- mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts));
- }
-
- mr->ledges = MEM_mallocN(mr->edge_len * sizeof(*mr->ledges), __func__);
- BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) {
- if (ede->l == NULL) {
- mr->ledges[mr->edge_loose_len++] = elem_id;
- }
- }
- if (mr->edge_loose_len < mr->edge_len) {
- mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges));
- }
-
- mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
- }
- }
-}
-
-/**
- * Part of the creation of the #MeshRenderData that happens in a thread.
- */
-static void mesh_render_data_update_looptris(MeshRenderData *mr,
- const eMRIterType iter_type,
- const eMRDataType data_flag)
-{
- Mesh *me = mr->me;
- if (mr->extract_type != MR_EXTRACT_BMESH) {
- /* Mesh */
- if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
- mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI");
- BKE_mesh_recalc_looptri(
- me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri);
- }
- }
- else {
- /* #BMesh */
- if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
- /* Edit mode ensures this is valid, no need to calculate. */
- BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL));
- }
- }
-}
-
-static void mesh_render_data_update_normals(MeshRenderData *mr,
- const eMRIterType UNUSED(iter_type),
- const eMRDataType data_flag)
-{
- Mesh *me = mr->me;
- const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
- const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
-
- if (mr->extract_type != MR_EXTRACT_BMESH) {
- /* Mesh */
- if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
- mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
- BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
- NULL,
- mr->vert_len,
- mr->mloop,
- mr->mpoly,
- mr->loop_len,
- mr->poly_len,
- mr->poly_normals,
- true);
- }
- if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
- mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
- short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL);
- BKE_mesh_normals_loop_split(mr->me->mvert,
- mr->vert_len,
- mr->me->medge,
- mr->edge_len,
- mr->me->mloop,
- mr->loop_normals,
- mr->loop_len,
- mr->me->mpoly,
- mr->poly_normals,
- mr->poly_len,
- is_auto_smooth,
- split_angle,
- NULL,
- clnors,
- NULL);
- }
- }
- else {
- /* #BMesh */
- if (data_flag & MR_DATA_POLY_NOR) {
- /* Use #BMFace.no instead. */
- }
- if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
-
- const float(*vert_coords)[3] = NULL;
- const float(*vert_normals)[3] = NULL;
- const float(*poly_normals)[3] = NULL;
-
- if (mr->edit_data && mr->edit_data->vertexCos) {
- vert_coords = mr->bm_vert_coords;
- vert_normals = mr->bm_vert_normals;
- poly_normals = mr->bm_poly_normals;
- }
-
- mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
- const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_loops_calc_normal_vcos(mr->bm,
- vert_coords,
- vert_normals,
- poly_normals,
- is_auto_smooth,
- split_angle,
- mr->loop_normals,
- NULL,
- NULL,
- clnors_offset,
- false);
- }
- }
-}
-
-/**
- * \param is_mode_active: When true, use the modifiers from the edit-data,
- * otherwise don't use modifiers as they are not from this object.
- */
-static MeshRenderData *mesh_render_data_create(Mesh *me,
- const bool is_editmode,
- const bool is_paint_mode,
- const bool is_mode_active,
- const float obmat[4][4],
- const bool do_final,
- const bool do_uvedit,
- const DRW_MeshCDMask *UNUSED(cd_used),
- const ToolSettings *ts,
- const eMRIterType iter_type,
- const eMRDataType data_flag)
-{
- MeshRenderData *mr = MEM_callocN(sizeof(*mr), __func__);
- mr->toolsettings = ts;
- mr->mat_len = mesh_render_mat_len_get(me);
-
- copy_m4_m4(mr->obmat, obmat);
-
- if (is_editmode) {
- BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
- mr->bm = me->edit_mesh->bm;
- mr->edit_bmesh = me->edit_mesh;
- mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
- mr->edit_data = is_mode_active ? mr->me->runtime.edit_data : NULL;
-
- if (mr->edit_data) {
- EditMeshData *emd = mr->edit_data;
- if (emd->vertexCos) {
- BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd);
- BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd);
- }
-
- mr->bm_vert_coords = mr->edit_data->vertexCos;
- mr->bm_vert_normals = mr->edit_data->vertexNos;
- mr->bm_poly_normals = mr->edit_data->polyNos;
- mr->bm_poly_centers = mr->edit_data->polyCos;
- }
-
- bool has_mdata = is_mode_active && (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
- bool use_mapped = is_mode_active &&
- (has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original);
-
- int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
-
- BM_mesh_elem_index_ensure(mr->bm, bm_ensure_types);
- BM_mesh_elem_table_ensure(mr->bm, bm_ensure_types & ~BM_LOOP);
-
- mr->efa_act_uv = EDBM_uv_active_face_get(mr->edit_bmesh, false, false);
- mr->efa_act = BM_mesh_active_face_get(mr->bm, false, true);
- mr->eed_act = BM_mesh_active_edge_get(mr->bm);
- mr->eve_act = BM_mesh_active_vert_get(mr->bm);
-
- mr->crease_ofs = CustomData_get_offset(&mr->bm->edata, CD_CREASE);
- mr->bweight_ofs = CustomData_get_offset(&mr->bm->edata, CD_BWEIGHT);
-#ifdef WITH_FREESTYLE
- mr->freestyle_edge_ofs = CustomData_get_offset(&mr->bm->edata, CD_FREESTYLE_EDGE);
- mr->freestyle_face_ofs = CustomData_get_offset(&mr->bm->pdata, CD_FREESTYLE_FACE);
-#endif
-
- if (use_mapped) {
- mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
- mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
- mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
-
- use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
- }
-
- mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_BMESH;
- /* Seems like the mesh_eval_final do not have the right origin indices.
- * Force not mapped in this case. */
- if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
- // mr->edit_bmesh = NULL;
- mr->extract_type = MR_EXTRACT_MESH;
- }
- }
- else {
- mr->me = me;
- mr->edit_bmesh = NULL;
-
- bool use_mapped = is_paint_mode && mr->me && !mr->me->runtime.is_original;
- if (use_mapped) {
- mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
- mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
- mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
-
- use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
- }
-
- mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_MESH;
- }
-
- if (mr->extract_type != MR_EXTRACT_BMESH) {
- /* Mesh */
- mr->vert_len = mr->me->totvert;
- mr->edge_len = mr->me->totedge;
- mr->loop_len = mr->me->totloop;
- mr->poly_len = mr->me->totpoly;
- mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
-
- mr->mvert = CustomData_get_layer(&mr->me->vdata, CD_MVERT);
- mr->medge = CustomData_get_layer(&mr->me->edata, CD_MEDGE);
- mr->mloop = CustomData_get_layer(&mr->me->ldata, CD_MLOOP);
- mr->mpoly = CustomData_get_layer(&mr->me->pdata, CD_MPOLY);
-
- mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
- mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
- mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
- }
- else {
- /* #BMesh */
- BMesh *bm = mr->bm;
-
- mr->vert_len = bm->totvert;
- mr->edge_len = bm->totedge;
- mr->loop_len = bm->totloop;
- mr->poly_len = bm->totface;
- mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
- }
- mesh_render_data_update_loose_geom(mr, iter_type, data_flag);
-
- return mr;
-}
-
-static void mesh_render_data_free(MeshRenderData *mr)
+void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc)
{
- MEM_SAFE_FREE(mr->mlooptri);
- MEM_SAFE_FREE(mr->poly_normals);
- MEM_SAFE_FREE(mr->loop_normals);
-
- MEM_SAFE_FREE(mr->lverts);
- MEM_SAFE_FREE(mr->ledges);
-
- MEM_freeN(mr);
+ /* NOTE: POINTER_OFFSET on windows platforms casts internally to `void *`, but on GCC/CLANG to
+ * `MeshBufferCache *`. What shows a different usage versus intent. */
+ void **buffer_ptr = (void **)POINTER_OFFSET(mbc, extractor->mesh_buffer_offset);
+ void *buffer = *buffer_ptr;
+ BLI_assert(buffer);
+ return buffer;
}
-BLI_INLINE BMFace *bm_original_face_get(const MeshRenderData *mr, int idx)
+eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
{
- return ((mr->p_origindex != NULL) && (mr->p_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
- BM_face_at_index(mr->bm, mr->p_origindex[idx]) :
- NULL;
-}
-
-BLI_INLINE BMEdge *bm_original_edge_get(const MeshRenderData *mr, int idx)
-{
- return ((mr->e_origindex != NULL) && (mr->e_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
- BM_edge_at_index(mr->bm, mr->e_origindex[idx]) :
- NULL;
-}
-
-BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx)
-{
- return ((mr->v_origindex != NULL) && (mr->v_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
- BM_vert_at_index(mr->bm, mr->v_origindex[idx]) :
- NULL;
-}
-
-BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
-{
- const float(*vert_coords)[3] = mr->bm_vert_coords;
- if (vert_coords != NULL) {
- return vert_coords[BM_elem_index_get(eve)];
- }
-
- UNUSED_VARS(mr);
- return eve->co;
-}
-
-BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve)
-{
- const float(*vert_normals)[3] = mr->bm_vert_normals;
- if (vert_normals != NULL) {
- return vert_normals[BM_elem_index_get(eve)];
- }
-
- UNUSED_VARS(mr);
- return eve->no;
-}
-
-BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
-{
- const float(*poly_normals)[3] = mr->bm_poly_normals;
- if (poly_normals != NULL) {
- return poly_normals[BM_elem_index_get(efa)];
- }
-
- UNUSED_VARS(mr);
- return efa->no;
+ 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_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;
}
-/** \} */
-
/* ---------------------------------------------------------------------- */
-/** \name Mesh Elements Extract: Loop Triangles
+/** \name Override extractors
+ * Extractors can be overridden. When overridden a specialized version is used. The next functions
+ * would check for any needed overrides and usage of the specialized version.
* \{ */
-typedef struct ExtractTriBMesh_Params {
- BMLoop *(*looptris)[3];
- int tri_range[2];
-} ExtractTriBMesh_Params;
-typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
- 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,
- const ExtractTriMesh_Params *params,
- void *data);
-
-#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 \
- } \
- } \
+static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *extractor)
+{
+ if (extractor == &extract_pos_nor) {
+ return &extract_pos_nor_hq;
}
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \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,
- 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,
- 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 \
- } \
- } \
+ if (extractor == &extract_lnor) {
+ return &extract_lnor_hq;
}
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \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,
- 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,
- 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 \
- } \
- } \
+ if (extractor == &extract_tan) {
+ return &extract_tan_hq;
}
+ if (extractor == &extract_fdots_nor) {
+ return &extract_fdots_nor_hq;
+ }
+ return extractor;
+}
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Mesh Elements Extract Struct
- * \{ */
-
-typedef void *(ExtractInitFn)(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buffer);
-typedef void(ExtractFinishFn)(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buffer,
- void *data);
-
-typedef struct MeshExtract {
- /** Executed on main thread and return user data for iteration functions. */
- ExtractInitFn *init;
- /** Executed on one (or more if use_threading) worker thread(s). */
- ExtractTriBMeshFn *iter_looptri_bm;
- ExtractTriMeshFn *iter_looptri_mesh;
- ExtractPolyBMeshFn *iter_poly_bm;
- ExtractPolyMeshFn *iter_poly_mesh;
- ExtractLEdgeBMeshFn *iter_ledge_bm;
- ExtractLEdgeMeshFn *iter_ledge_mesh;
- ExtractLVertBMeshFn *iter_lvert_bm;
- ExtractLVertMeshFn *iter_lvert_mesh;
- /** Executed on one worker thread after all elements iterations. */
- ExtractFinishFn *finish;
- /** Used to request common data. */
- const eMRDataType data_flag;
- /** Used to know if the element callbacks are thread-safe and can be parallelized. */
- const bool use_threading;
-} MeshExtract;
-
-BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
+const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
+ const bool do_hq_normals)
{
- 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_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;
+ if (do_hq_normals) {
+ extractor = mesh_extract_override_hq_normals(extractor);
+ }
+ return extractor;
}
/** \} */
@@ -855,69 +164,65 @@ static void *extract_tris_init(const MeshRenderData *mr,
}
static void extract_tris_iter_looptri_bm(const MeshRenderData *mr,
- const struct ExtractTriBMesh_Params *params,
+ BMLoop **elt,
+ const int UNUSED(elt_index),
void *_data)
{
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]));
- }
+
+ 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_iter_looptri_mesh(const MeshRenderData *mr,
- const struct ExtractTriMesh_Params *params,
+ const MLoopTri *mlt,
+ const int UNUSED(elt_index),
void *_data)
{
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]);
- }
+ 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,
struct MeshBatchCache *cache,
- void *ibo,
+ void *buf,
void *_data)
{
+ GPUIndexBuf *ibo = buf;
MeshExtract_Tri_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
/* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
* is created before the surfaces-per-material. */
if (mr->use_final_mesh && cache->final.tris_per_mat) {
- MeshBufferCache *mbc = &cache->final;
+ MeshBufferCache *mbc_final = &cache->final;
for (int i = 0; i < mr->mat_len; i++) {
/* These IBOs have not been queried yet but we create them just in case they are needed
* later since they are not tracked by mesh_buffer_cache_create_requested(). */
- if (mbc->tris_per_mat[i] == NULL) {
- mbc->tris_per_mat[i] = GPU_indexbuf_calloc();
+ if (mbc_final->tris_per_mat[i] == NULL) {
+ mbc_final->tris_per_mat[i] = GPU_indexbuf_calloc();
}
/* Multiply by 3 because these are triangle indices. */
const int mat_start = data->tri_mat_start[i];
const int mat_end = data->tri_mat_end[i];
const int start = mat_start * 3;
const int len = (mat_end - mat_start) * 3;
- GPU_indexbuf_create_subrange_in_place(mbc->tris_per_mat[i], ibo, start, len);
+ GPU_indexbuf_create_subrange_in_place(mbc_final->tris_per_mat[i], ibo, start, len);
}
}
MEM_freeN(data->tri_mat_start);
@@ -925,13 +230,14 @@ static void extract_tris_finish(const MeshRenderData *mr,
MEM_freeN(data);
}
-static const MeshExtract extract_tris = {
+const MeshExtract extract_tris = {
.init = extract_tris_init,
.iter_looptri_bm = extract_tris_iter_looptri_bm,
.iter_looptri_mesh = extract_tris_iter_looptri_mesh,
.finish = extract_tris_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris),
};
/** \} */
@@ -951,138 +257,124 @@ static void *extract_lines_init(const MeshRenderData *mr,
return elb;
}
-static void extract_lines_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
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;
+ 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);
}
static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *elb)
{
/* 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;
+ 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);
}
else {
- 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;
+ 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);
}
}
static void extract_lines_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *elb)
{
- 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));
+ 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);
}
- EXTRACT_LEDGE_FOREACH_BM_END;
+ /* Don't render the edge twice. */
+ GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
}
static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
void *elb)
{
- 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);
+ 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);
}
- EXTRACT_LEDGE_FOREACH_MESH_END;
+ /* Don't render the edge twice. */
+ GPU_indexbuf_set_line_restart(elb, e_index);
}
static void extract_lines_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *elb)
{
+ GPUIndexBuf *ibo = buf;
GPU_indexbuf_build_in_place(elb, ibo);
MEM_freeN(elb);
}
-static const MeshExtract extract_lines = {
+const MeshExtract extract_lines = {
.init = extract_lines_init,
.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,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines),
};
+
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loose Edges Sub Buffer
+/** \name Extract Lines and Loose Edges Sub Buffer
* \{ */
static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshBatchCache *cache)
@@ -1098,24 +390,47 @@ static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshB
static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr,
struct MeshBatchCache *cache,
- void *ibo,
+ void *buf,
void *elb)
{
+ GPUIndexBuf *ibo = buf;
GPU_indexbuf_build_in_place(elb, ibo);
extract_lines_loose_subbuffer(mr, cache);
MEM_freeN(elb);
}
-static const MeshExtract extract_lines_with_lines_loose = {
+const MeshExtract extract_lines_with_lines_loose = {
.init = extract_lines_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines)};
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loose Edges Sub Buffer
+ * \{ */
+
+static void *extract_lines_loose_only_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf)
+{
+ BLI_assert(buf == cache->final.ibo.lines_loose);
+ UNUSED_VARS_NDEBUG(buf);
+ extract_lines_loose_subbuffer(mr, cache);
+ return NULL;
+}
+
+const MeshExtract extract_lines_loose_only = {
+ .init = extract_lines_loose_only_init,
+ .data_type = 0,
+ .use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_loose)};
/** \} */
@@ -1159,86 +474,81 @@ BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb,
}
}
-static void extract_points_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_points_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *elb)
{
- 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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ vert_set_bm(elb, l_iter->v, l_index);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_points_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *elb)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
vert_set_mesh(elb, mr, ml->v, ml_index);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_points_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *elb)
{
- 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;
+ 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);
}
static void extract_points_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
void *elb)
{
- 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;
+ 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);
}
static void extract_points_iter_lvert_bm(const MeshRenderData *mr,
- const ExtractLVertBMesh_Params *params,
+ BMVert *eve,
+ const int lvert_index,
void *elb)
{
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;
+ vert_set_bm(elb, eve, offset + lvert_index);
}
static void extract_points_iter_lvert_mesh(const MeshRenderData *mr,
- const ExtractLVertMesh_Params *params,
+ const MVert *UNUSED(mv),
+ const int lvert_index,
void *elb)
{
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;
+
+ vert_set_mesh(elb, mr, mr->lverts[lvert_index], offset + lvert_index);
}
static void extract_points_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *elb)
{
+ GPUIndexBuf *ibo = buf;
GPU_indexbuf_build_in_place(elb, ibo);
MEM_freeN(elb);
}
-static const MeshExtract extract_points = {
+const MeshExtract extract_points = {
.init = extract_points_init,
.iter_poly_bm = extract_points_iter_poly_bm,
.iter_poly_mesh = extract_points_iter_poly_mesh,
@@ -1247,14 +557,15 @@ static const MeshExtract extract_points = {
.iter_lvert_bm = extract_points_iter_lvert_bm,
.iter_lvert_mesh = extract_points_iter_lvert_mesh,
.finish = extract_points_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points),
};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots Indices
+/** \name Extract Face-dots Indices
* \{ */
static void *extract_fdots_init(const MeshRenderData *mr,
@@ -1266,70 +577,66 @@ static void *extract_fdots_init(const MeshRenderData *mr,
return elb;
}
-static void extract_fdots_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int f_index,
void *elb)
{
- 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);
- }
+ 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_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *elb)
{
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 MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
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);
+ return;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+ GPU_indexbuf_set_point_restart(elb, mp_index);
}
else {
- 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);
- }
+ 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;
}
}
static void extract_fdots_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *elb)
{
+ GPUIndexBuf *ibo = buf;
GPU_indexbuf_build_in_place(elb, ibo);
MEM_freeN(elb);
}
-static const MeshExtract extract_fdots = {
+const MeshExtract extract_fdots = {
.init = extract_fdots_init,
.iter_poly_bm = extract_fdots_iter_poly_bm,
.iter_poly_mesh = extract_fdots_iter_poly_mesh,
.finish = extract_fdots_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots),
};
/** \} */
@@ -1346,7 +653,7 @@ typedef struct MeshExtract_LinePaintMask_Data {
static void *extract_lines_paint_mask_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
- void *UNUSED(buf))
+ void *UNUSED(ibo))
{
size_t bitmap_size = BLI_BITMAP_SIZE(mr->edge_len);
MeshExtract_LinePaintMask_Data *data = MEM_callocN(sizeof(*data) + bitmap_size, __func__);
@@ -1355,12 +662,16 @@ static void *extract_lines_paint_mask_init(const MeshRenderData *mr,
}
static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *_data)
{
MeshExtract_LinePaintMask_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
const int e_index = ml->e;
const MEdge *me = &mr->medge[e_index];
if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
@@ -1390,26 +701,26 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
GPU_indexbuf_set_line_restart(&data->elb, e_index);
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
+
static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *_data)
{
+ GPUIndexBuf *ibo = buf;
MeshExtract_LinePaintMask_Data *data = _data;
-
GPU_indexbuf_build_in_place(&data->elb, ibo);
MEM_freeN(data);
}
-static const MeshExtract extract_lines_paint_mask = {
+const MeshExtract extract_lines_paint_mask = {
.init = extract_lines_paint_mask_init,
.iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh,
.finish = extract_lines_paint_mask_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_paint_mask)};
/** \} */
@@ -1487,49 +798,44 @@ BLI_INLINE void lines_adjacency_triangle(
}
static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
- const struct ExtractTriBMesh_Params *params,
+ BMLoop **elt,
+ const int UNUSED(elt_index),
void *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);
- }
+ 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_iter_looptri_mesh(const MeshRenderData *mr,
- const struct ExtractTriMesh_Params *params,
+ const MLoopTri *mlt,
+ const int UNUSED(elt_index),
void *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);
- }
+ 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 *UNUSED(mr),
struct MeshBatchCache *cache,
- void *ibo,
+ void *buf,
void *_data)
{
+ GPUIndexBuf *ibo = buf;
MeshExtract_LineAdjacency_Data *data = _data;
/* Create edges for remaining non manifold edges. */
EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh);
@@ -1559,14 +865,14 @@ static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr),
#undef NO_EDGE
-static const MeshExtract extract_lines_adjacency = {
+const MeshExtract extract_lines_adjacency = {
.init = extract_lines_adjacency_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_adjacency)};
/** \} */
@@ -1598,56 +904,51 @@ BLI_INLINE void edituv_tri_add(
}
static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
- const struct ExtractTriBMesh_Params *params,
+ BMLoop **elt,
+ const int UNUSED(elt_index),
void *data)
{
- 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;
+ 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]));
}
static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr,
- const struct ExtractTriMesh_Params *params,
+ const MLoopTri *mlt,
+ const int UNUSED(elt_index),
void *data)
{
- 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;
+ 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]);
}
static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *data)
{
+ GPUIndexBuf *ibo = buf;
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 = {
+const MeshExtract extract_edituv_tris = {
.init = extract_edituv_tris_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_tris)};
/** \} */
@@ -1674,27 +975,34 @@ BLI_INLINE void edituv_edge_add(
}
}
-static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
edituv_edge_add(data,
- BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
- BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
+ BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN),
+ BM_elem_flag_test_bool(f, BM_ELEM_SELECT),
l_index,
- BM_elem_index_get(loop->next));
- }
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
+ BM_elem_index_get(l_iter->next));
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
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);
@@ -1704,27 +1012,27 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
ml_index,
ml_index_next);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *data)
{
+ GPUIndexBuf *ibo = buf;
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 = {
+const MeshExtract extract_edituv_lines = {
.init = extract_edituv_lines_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_lines)};
/** \} */
@@ -1753,57 +1061,62 @@ BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data,
}
}
-static void extract_edituv_points_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_edituv_points_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- 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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ edituv_point_add(
+ data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), l_index);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
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),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *data)
{
+ GPUIndexBuf *ibo = buf;
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 = {
+const MeshExtract extract_edituv_points = {
.init = extract_edituv_points_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_points)};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Edit UV Facedots Indices
+/** \name Extract Edit UV Face-dots Indices
* \{ */
static void *extract_edituv_fdots_init(const MeshRenderData *mr,
@@ -1830,26 +1143,29 @@ BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data,
}
}
-static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int f_index,
void *data)
{
- 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;
+ edituv_facedot_add(data,
+ BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN),
+ BM_elem_flag_test_bool(f, BM_ELEM_SELECT),
+ f_index);
}
static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *data)
{
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 MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
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 ||
@@ -1859,40 +1175,34 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
(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;
+ 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);
}
}
static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *ibo,
+ void *buf,
void *_data)
{
+ GPUIndexBuf *ibo = buf;
MeshExtract_EditUvElem_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
MEM_freeN(data);
}
-static const MeshExtract extract_edituv_fdots = {
+const MeshExtract extract_edituv_fdots = {
.init = extract_edituv_fdots_init,
.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,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_fdots)};
/** \} */
@@ -1914,6 +1224,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING Adjust #PosNorLoop struct accordingly. */
@@ -1921,7 +1232,6 @@ static void *extract_pos_nor_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "vnor");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
@@ -1949,28 +1259,34 @@ static void *extract_pos_nor_init(const MeshRenderData *mr,
}
static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
PosNorLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v));
- vert->nor = data->normals[BM_elem_index_get(l->v)].low;
- 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);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
+ vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low;
+ vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
PosNorLoop *vert = &data->vbo_data[ml_index];
const MVert *mv = &mr->mvert[ml->v];
copy_v3_v3(vert->pos, mv->co);
@@ -1988,85 +1304,75 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
vert->nor.w = 0;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- 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->normals[BM_elem_index_get(eed->v1)].low;
- vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low;
- }
- EXTRACT_LEDGE_FOREACH_BM_END;
+
+ 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->normals[BM_elem_index_get(eed->v1)].low;
+ vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low;
}
static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- 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->normals[med->v1].low;
- vert[1].nor = data->normals[med->v2].low;
- }
- EXTRACT_LEDGE_FOREACH_MESH_END;
+ 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->normals[med->v1].low;
+ vert[1].nor = data->normals[med->v2].low;
}
static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr,
- const ExtractLVertBMesh_Params *params,
+ BMVert *eve,
+ const int lvert_index,
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
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->normals[BM_elem_index_get(eve)].low;
- }
- EXTRACT_LVERT_FOREACH_BM_END;
+
+ 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->normals[BM_elem_index_get(eve)].low;
}
static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr,
- const ExtractLVertMesh_Params *params,
+ const MVert *mv,
+ const int lvert_index,
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
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->normals[v_index].low;
- }
- EXTRACT_LVERT_FOREACH_MESH_END;
+
+ 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->normals[v_index].low;
}
static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *UNUSED(vbo),
+ void *UNUSED(buf),
void *data)
{
MEM_freeN(data);
}
-static const MeshExtract extract_pos_nor = {
+const MeshExtract extract_pos_nor = {
.init = extract_pos_nor_init,
.iter_poly_bm = extract_pos_nor_iter_poly_bm,
.iter_poly_mesh = extract_pos_nor_iter_poly_mesh,
@@ -2075,9 +1381,11 @@ static const MeshExtract extract_pos_nor = {
.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,
+ .data_type = 0,
.use_threading = true,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor),
};
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -2098,6 +1406,7 @@ static void *extract_pos_nor_hq_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING Adjust #PosNorHQLoop struct accordingly. */
@@ -2105,7 +1414,6 @@ static void *extract_pos_nor_hq_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "vnor");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
@@ -2133,29 +1441,35 @@ static void *extract_pos_nor_hq_init(const MeshRenderData *mr,
}
static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
PosNorHQLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v));
- copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l->v)].high);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
+ copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high);
- BMFace *efa = l->f;
+ BMFace *efa = l_iter->f;
vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
- }
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
PosNorHQLoop *vert = &data->vbo_data[ml_index];
const MVert *mv = &mr->mvert[ml->v];
copy_v3_v3(vert->pos, mv->co);
@@ -2174,91 +1488,80 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr,
vert->nor[3] = 0;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
- EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
- {
- int l_index = mr->loop_len + ledge_index * 2;
- PosNorHQLoop *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));
- copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high);
- vert[0].nor[3] = 0;
- copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high);
- vert[1].nor[3] = 0;
- }
- EXTRACT_LEDGE_FOREACH_BM_END;
+ int l_index = mr->loop_len + ledge_index * 2;
+ PosNorHQLoop *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));
+ copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high);
+ vert[0].nor[3] = 0;
+ copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high);
+ vert[1].nor[3] = 0;
}
static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
- EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
- {
- const int ml_index = mr->loop_len + ledge_index * 2;
- PosNorHQLoop *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);
- copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high);
- vert[0].nor[3] = 0;
- copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high);
- vert[1].nor[3] = 0;
- }
- EXTRACT_LEDGE_FOREACH_MESH_END;
+ const int ml_index = mr->loop_len + ledge_index * 2;
+ PosNorHQLoop *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);
+ copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high);
+ vert[0].nor[3] = 0;
+ copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high);
+ vert[1].nor[3] = 0;
}
static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr,
- const ExtractLVertBMesh_Params *params,
+ BMVert *eve,
+ const int lvert_index,
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
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;
- PosNorHQLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
- copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high);
- vert->nor[3] = 0;
- }
- EXTRACT_LVERT_FOREACH_BM_END;
+
+ const int l_index = offset + lvert_index;
+ PosNorHQLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
+ copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high);
+ vert->nor[3] = 0;
}
static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr,
- const ExtractLVertMesh_Params *params,
+ const MVert *mv,
+ const int lvert_index,
void *_data)
{
MeshExtract_PosNorHQ_Data *data = _data;
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];
- PosNorHQLoop *vert = &data->vbo_data[ml_index];
- copy_v3_v3(vert->pos, mv->co);
- copy_v3_v3_short(vert->nor, data->normals[v_index].high);
- vert->nor[3] = 0;
- }
- EXTRACT_LVERT_FOREACH_MESH_END;
+
+ const int ml_index = offset + lvert_index;
+ const int v_index = mr->lverts[lvert_index];
+ PosNorHQLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert->pos, mv->co);
+ copy_v3_v3_short(vert->nor, data->normals[v_index].high);
+ vert->nor[3] = 0;
}
static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
- void *UNUSED(vbo),
+ void *UNUSED(buf),
void *data)
{
MEM_freeN(data);
}
-static const MeshExtract extract_pos_nor_hq = {
+const MeshExtract extract_pos_nor_hq = {
.init = extract_pos_nor_hq_init,
.iter_poly_bm = extract_pos_nor_hq_iter_poly_bm,
.iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh,
@@ -2267,9 +1570,9 @@ static const MeshExtract extract_pos_nor_hq = {
.iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm,
.iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh,
.finish = extract_pos_nor_hq_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -2284,12 +1587,12 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "lnor");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -2297,36 +1600,37 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr,
}
static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- if (mr->loop_normals) {
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(_l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (mr->loop_normals) {
normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(_l);
- }
- else {
- 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 {
+ if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l_iter->v));
}
else {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, l->f));
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, f));
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index];
if (mr->loop_normals) {
normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
@@ -2352,15 +1656,15 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
lnor_data->w = 0;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static const MeshExtract extract_lnor_hq = {
+const MeshExtract extract_lnor_hq = {
.init = extract_lnor_hq_init,
.iter_poly_bm = extract_lnor_hq_iter_poly_bm,
.iter_poly_mesh = extract_lnor_hq_iter_poly_mesh,
- .data_flag = MR_DATA_LOOP_NOR,
+ .data_type = MR_DATA_LOOP_NOR,
.use_threading = true,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor),
};
/** \} */
@@ -2372,12 +1676,12 @@ static void *extract_lnor_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "lnor");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -2385,40 +1689,39 @@ static void *extract_lnor_init(const MeshRenderData *mr,
}
static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- if (mr->loop_normals) {
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (mr->loop_normals) {
((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 {
- 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 {
+ if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
+ ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(
+ bm_vert_no_get(mr, l_iter->v));
}
else {
- ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, l->f));
+ ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, 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);
- }
+ ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index];
if (mr->loop_normals) {
*lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
@@ -2444,15 +1747,15 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
lnor_data->w = 0;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static const MeshExtract extract_lnor = {
+const MeshExtract extract_lnor = {
.init = extract_lnor_init,
.iter_poly_bm = extract_lnor_iter_poly_bm,
.iter_poly_mesh = extract_lnor_iter_poly_mesh,
- .data_flag = MR_DATA_LOOP_NOR,
+ .data_type = MR_DATA_LOOP_NOR,
.use_threading = true,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor),
};
/** \} */
@@ -2463,6 +1766,7 @@ static const MeshExtract extract_lnor = {
static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf)
{
+ GPUVertBuf *vbo = buf;
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
@@ -2512,7 +1816,6 @@ static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *ca
v_len = 1;
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, v_len);
@@ -2545,10 +1848,11 @@ static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *ca
return NULL;
}
-static const MeshExtract extract_uv = {
+const MeshExtract extract_uv = {
.init = extract_uv_init,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv),
};
/** \} */
@@ -2557,10 +1861,10 @@ static const MeshExtract extract_uv = {
/** \name Extract Tangent layers
* \{ */
-static void extract_tan_ex(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- GPUVertBuf *vbo,
- const bool do_hq)
+static void extract_tan_ex_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ GPUVertBuf *vbo,
+ const bool do_hq)
{
GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10;
GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
@@ -2731,14 +2035,15 @@ static void extract_tan_ex(const MeshRenderData *mr,
static void *extract_tan_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf)
{
- extract_tan_ex(mr, cache, buf, false);
+ extract_tan_ex_init(mr, cache, buf, false);
return NULL;
}
-static const MeshExtract extract_tan = {
+const MeshExtract extract_tan = {
.init = extract_tan_init,
- .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
+ .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan),
};
/** \} */
@@ -2749,13 +2054,13 @@ static const MeshExtract extract_tan = {
static void *extract_tan_hq_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf)
{
- extract_tan_ex(mr, cache, buf, true);
+ extract_tan_ex_init(mr, cache, buf, true);
return NULL;
}
-static const MeshExtract extract_tan_hq = {
+const MeshExtract extract_tan_hq = {
.init = extract_tan_hq_init,
- .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
+ .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
.use_threading = false,
};
@@ -2769,6 +2074,7 @@ static void *extract_sculpt_data_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
GPUVertFormat format = {0};
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
@@ -2783,7 +2089,6 @@ static void *extract_sculpt_data_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -2852,12 +2157,12 @@ static void *extract_sculpt_data_init(const MeshRenderData *mr,
return NULL;
}
-static const MeshExtract extract_sculpt_data = {
+const MeshExtract extract_sculpt_data = {
.init = extract_sculpt_data_init,
- .data_flag = 0,
+ .data_type = 0,
/* TODO: enable threading. */
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data)};
/** \} */
@@ -2867,6 +2172,7 @@ static const MeshExtract extract_sculpt_data = {
static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf)
{
+ GPUVertBuf *vbo = buf;
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
@@ -2928,7 +2234,6 @@ static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *
}
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -3001,10 +2306,11 @@ static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *
return NULL;
}
-static const MeshExtract extract_vcol = {
+const MeshExtract extract_vcol = {
.init = extract_vcol_init,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol),
};
/** \} */
@@ -3022,6 +2328,7 @@ static void *extract_orco_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
@@ -3031,7 +2338,6 @@ static void *extract_orco_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -3045,32 +2351,36 @@ static void *extract_orco_init(const MeshRenderData *mr,
return data;
}
-static void extract_orco_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
float *loop_orco = orco_data->vbo_data[l_index];
- copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
+ copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]);
loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
- }
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
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),
@@ -3081,13 +2391,14 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-static const MeshExtract extract_orco = {
+const MeshExtract extract_orco = {
.init = extract_orco_init,
.iter_poly_bm = extract_orco_iter_poly_bm,
.iter_poly_mesh = extract_orco_iter_poly_mesh,
.finish = extract_orco_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco),
};
/** \} */
@@ -3124,11 +2435,12 @@ static void *extract_edge_fac_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
@@ -3159,43 +2471,47 @@ static void *extract_edge_fac_init(const MeshRenderData *mr,
}
static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
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));
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ if (BM_edge_is_manifold(l_iter->e)) {
+ float ratio = loop_edge_factor_get(bm_face_no_get(mr, f),
+ bm_vert_co_get(mr, l_iter->v),
+ bm_vert_no_get(mr, l_iter->v),
+ bm_vert_co_get(mr, l_iter->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);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *_data)
{
MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
- if (data->use_edge_render) {
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
+ if (data->use_edge_render) {
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 {
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ else {
+
/* Count loop per edge to detect non-manifold. */
if (data->edge_loop_count[ml->e] < 3) {
data->edge_loop_count[ml->e]++;
@@ -3217,34 +2533,28 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
data->vbo_data[ml_index] = 255;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
}
static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *UNUSED(eed),
+ const int ledge_index,
void *_data)
{
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;
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255;
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255;
}
static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *UNUSED(med),
+ const uint ledge_index,
void *_data)
{
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;
+
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255;
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255;
}
static void extract_edge_fac_finish(const MeshRenderData *mr,
@@ -3252,10 +2562,10 @@ static void extract_edge_fac_finish(const MeshRenderData *mr,
void *buf,
void *_data)
{
+ GPUVertBuf *vbo = buf;
MeshExtract_EdgeFac_Data *data = _data;
if (GPU_crappy_amd_driver()) {
- GPUVertBuf *vbo = (GPUVertBuf *)buf;
/* Some AMD drivers strangely crash with VBO's with a one byte format.
* To workaround we reinitialize the VBO with another format and convert
* all bytes to floats. */
@@ -3281,16 +2591,16 @@ static void extract_edge_fac_finish(const MeshRenderData *mr,
MEM_freeN(data);
}
-static const MeshExtract extract_edge_fac = {
+const MeshExtract extract_edge_fac = {
.init = extract_edge_fac_init,
.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,
+ .data_type = MR_DATA_POLY_NOR,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac)};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -3361,11 +2671,11 @@ static void *extract_weights_init(const MeshRenderData *mr,
struct MeshBatchCache *cache,
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
@@ -3389,48 +2699,44 @@ static void *extract_weights_init(const MeshRenderData *mr,
return data;
}
-static void extract_weights_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (data->cd_ofs != -1) {
+ const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l_iter->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)
- {
+ else {
data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *_data)
{
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 MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (data->dvert != NULL) {
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)
- {
+ else {
+ const MDeformVert *dvert = NULL;
data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
}
@@ -3442,13 +2748,14 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-static const MeshExtract extract_weights = {
+const MeshExtract extract_weights = {
.init = extract_weights_init,
.iter_poly_bm = extract_weights_iter_poly_bm,
.iter_poly_mesh = extract_weights_iter_poly_mesh,
.finish = extract_weights_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights),
};
/** \} */
@@ -3599,40 +2906,45 @@ static void *extract_edit_data_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING: Adjust #EditLoopData struct accordingly. */
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
GPU_vertformat_alias_add(&format, "flag");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
return GPU_vertbuf_get_data(vbo);
}
static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
- 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);
+ mesh_render_data_face_flag(mr, f, -1, data);
+ mesh_render_data_edge_flag(mr, l_iter->e, data);
+ mesh_render_data_vert_flag(mr, l_iter->v, data);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *_data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
EditLoopData *data = (EditLoopData *)_data + ml_index;
memset(data, 0x0, sizeof(*data));
BMFace *efa = bm_original_face_get(mr, mp_index);
@@ -3648,84 +2960,72 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
mesh_render_data_vert_flag(mr, eve, data);
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *_data)
{
- 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;
+ 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]);
}
static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
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]);
- }
+ 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]);
}
- EXTRACT_LEDGE_FOREACH_MESH_END;
}
static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr,
- const ExtractLVertBMesh_Params *params,
+ BMVert *eve,
+ const int lvert_index,
void *_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;
+ EditLoopData *data = (EditLoopData *)_data + offset + lvert_index;
+ memset(data, 0x0, sizeof(*data));
+ mesh_render_data_vert_flag(mr, eve, data);
}
static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
- const ExtractLVertMesh_Params *params,
+ const MVert *UNUSED(mv),
+ const int lvert_index,
void *_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);
- }
+
+ 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 = {
+const MeshExtract extract_edit_data = {
.init = extract_edit_data_init,
.iter_poly_bm = extract_edit_data_iter_poly_bm,
.iter_poly_mesh = extract_edit_data_iter_poly_mesh,
@@ -3733,9 +3033,9 @@ static const MeshExtract extract_edit_data = {
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data)};
/** \} */
@@ -3752,6 +3052,7 @@ static void *extract_edituv_data_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING: Adjust #EditLoopData struct accordingly. */
@@ -3759,7 +3060,6 @@ static void *extract_edituv_data_init(const MeshRenderData *mr,
GPU_vertformat_alias_add(&format, "flag");
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -3772,28 +3072,34 @@ static void *extract_edituv_data_init(const MeshRenderData *mr,
}
static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
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);
+ mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata);
+ mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
+ mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *_data)
{
MeshExtract_EditUVData_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
EditLoopData *eldata = &data->vbo_data[ml_index];
memset(eldata, 0x0, sizeof(*eldata));
BMFace *efa = bm_original_face_get(mr, mp_index);
@@ -3823,7 +3129,6 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
}
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
@@ -3834,14 +3139,14 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-static const MeshExtract extract_edituv_data = {
+const MeshExtract extract_edituv_data = {
.init = extract_edituv_data_init,
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data)};
/** \} */
@@ -3853,12 +3158,12 @@ static void *extract_edituv_stretch_area_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -3880,11 +3185,12 @@ BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_t
return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
}
-static void mesh_edituv_stretch_area_finish(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(data))
+static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(data))
{
+ GPUVertBuf *vbo = buf;
float tot_area = 0.0f, tot_uv_area = 0.0f;
float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__);
@@ -3926,7 +3232,6 @@ static void mesh_edituv_stretch_area_finish(const MeshRenderData *mr,
}
/* Copy face data for each loop. */
- GPUVertBuf *vbo = buf;
uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo);
if (mr->extract_type == MR_EXTRACT_BMESH) {
@@ -3952,12 +3257,12 @@ static void mesh_edituv_stretch_area_finish(const MeshRenderData *mr,
MEM_freeN(area_ratio);
}
-static const MeshExtract extract_edituv_stretch_area = {
+const MeshExtract extract_edituv_stretch_area = {
.init = extract_edituv_stretch_area_init,
- .finish = mesh_edituv_stretch_area_finish,
- .data_flag = 0,
+ .finish = extract_edituv_stretch_area_finish,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area)};
/** \} */
@@ -4023,6 +3328,7 @@ static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* Waning: adjust #UVStretchAngle struct accordingly. */
@@ -4030,7 +3336,6 @@ static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -4049,21 +3354,24 @@ static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr,
}
static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_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;
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
- {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
const MLoopUV *luv, *luv_next;
- BMLoop *l_next = l->next;
- BMFace *efa = l->f;
- if (l == BM_FACE_FIRST_LOOP(efa)) {
+ BMLoop *l_next = l_iter->next;
+ if (l_iter == BM_FACE_FIRST_LOOP(f)) {
/* First loop in face. */
- BMLoop *l_tmp = l->prev;
- BMLoop *l_next_tmp = l;
+ BMLoop *l_tmp = l_iter->prev;
+ BMLoop *l_next_tmp = l_iter;
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,
@@ -4076,7 +3384,7 @@ static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
copy_v2_v2(last_auv, auv[1]);
copy_v3_v3(last_av, av[1]);
}
- if (l_next == BM_FACE_FIRST_LOOP(efa)) {
+ if (l_next == BM_FACE_FIRST_LOOP(f)) {
/* Move previous edge. */
copy_v2_v2(auv[0], auv[1]);
copy_v3_v3(av[0], av[1]);
@@ -4085,27 +3393,31 @@ static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
copy_v3_v3(av[1], last_av);
}
else {
- luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs);
+ luv = BM_ELEM_CD_GET_VOID_P(l_iter, 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));
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_iter->v),
+ bm_vert_co_get(mr, l_next->v));
}
edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]);
- }
- EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *_data)
{
MeshExtract_StretchAngle_Data *data = _data;
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
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;
+ int l_next = ml_index + 1;
const MVert *v, *v_next;
if (ml_index == mp->loopstart) {
/* First loop in face. */
@@ -4136,7 +3448,6 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
}
edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]);
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
@@ -4147,14 +3458,14 @@ static void extract_edituv_stretch_angle_finish(const MeshRenderData *UNUSED(mr)
MEM_freeN(data);
}
-static const MeshExtract extract_edituv_stretch_angle = {
+const MeshExtract extract_edituv_stretch_angle = {
.init = extract_edituv_stretch_angle_init,
.iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm,
.iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh,
.finish = extract_edituv_stretch_angle_finish,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle)};
/** \} */
@@ -4166,12 +3477,12 @@ static void *extract_mesh_analysis_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -4725,14 +4036,14 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
MEM_freeN(vert_angles);
}
-static void extract_mesh_analysis_finish(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(data))
+static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
{
+ GPUVertBuf *vbo = buf;
BLI_assert(mr->edit_bmesh);
- GPUVertBuf *vbo = buf;
float *l_weight = (float *)GPU_vertbuf_get_data(vbo);
switch (mr->toolsettings->statvis.type) {
@@ -4754,103 +4065,99 @@ static void extract_mesh_analysis_finish(const MeshRenderData *mr,
}
}
-static const MeshExtract extract_mesh_analysis = {
+const MeshExtract extract_mesh_analysis = {
.init = extract_mesh_analysis_init,
- .finish = extract_mesh_analysis_finish,
+ .finish = extract_analysis_iter_finish_mesh,
/* This is not needed for all visualization types.
* * Maybe split into different extract. */
- .data_flag = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
+ .data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis)};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots positions
+/** \name Extract Face-dots positions
* \{ */
static void *extract_fdots_pos_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
return GPU_vertbuf_get_data(vbo);
}
static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int f_index,
void *data)
{
float(*center)[3] = data;
- EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
- {
- float *co = center[f_index];
- zero_v3(co);
+ float *co = center[f_index];
+ zero_v3(co);
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- add_v3_v3(co, bm_vert_co_get(mr, l_iter->v));
- } while ((l_iter = l_iter->next) != l_first);
- mul_v3_fl(co, 1.0f / (float)f->len);
- }
- EXTRACT_POLY_FOREACH_BM_END;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ add_v3_v3(co, bm_vert_co_get(mr, l_iter->v));
+ } while ((l_iter = l_iter->next) != l_first);
+ mul_v3_fl(co, 1.0f / (float)f->len);
}
static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *data)
{
float(*center)[3] = (float(*)[3])data;
+ float *co = center[mp_index];
+ zero_v3(co);
+
const MVert *mvert = mr->mvert;
const MLoop *mloop = mr->mloop;
- if (mr->use_subsurf_fdots) {
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (mr->use_subsurf_fdots) {
const MVert *mv = &mr->mvert[ml->v];
if (mv->flag & ME_VERT_FACEDOT) {
copy_v3_v3(center[mp_index], mv->co);
+ break;
}
}
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
- }
- else {
- EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
- {
- float *co = center[mp_index];
- zero_v3(co);
-
- const MLoop *ml = &mloop[mp->loopstart];
- for (int i = 0; i < mp->totloop; i++, ml++) {
- const MVert *mv = &mvert[ml->v];
- add_v3_v3(center[mp_index], mv->co);
- }
- mul_v3_fl(co, 1.0f / (float)mp->totloop);
+ else {
+ const MVert *mv = &mvert[ml->v];
+ add_v3_v3(center[mp_index], mv->co);
}
- EXTRACT_POLY_FOREACH_MESH_END;
+ }
+
+ if (!mr->use_subsurf_fdots) {
+ mul_v3_fl(co, 1.0f / (float)mp->totloop);
}
}
-static const MeshExtract extract_fdots_pos = {
+const MeshExtract extract_fdots_pos = {
.init = extract_fdots_pos_init,
.iter_poly_bm = extract_fdots_pos_iter_poly_bm,
.iter_poly_mesh = extract_fdots_pos_iter_poly_mesh,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos)};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots Normal and edit flag
+/** \name Extract Face-dots Normal and edit flag
* \{ */
#define NOR_AND_FLAG_DEFAULT 0
#define NOR_AND_FLAG_SELECT 1
@@ -4861,11 +4168,12 @@ static void *extract_fdots_nor_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
@@ -4877,8 +4185,8 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr,
void *buf,
void *UNUSED(data))
{
- static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
GPUVertBuf *vbo = buf;
+ static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
BMFace *efa;
@@ -4921,27 +4229,28 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr,
}
}
-static const MeshExtract extract_fdots_nor = {
+const MeshExtract extract_fdots_nor = {
.init = extract_fdots_nor_init,
.finish = extract_fdots_nor_finish,
- .data_flag = MR_DATA_POLY_NOR,
+ .data_type = MR_DATA_POLY_NOR,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots High Quality Normal and edit flag
+/** \name Extract Face-dots High Quality Normal and edit flag
* \{ */
static void *extract_fdots_nor_hq_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
@@ -4953,8 +4262,8 @@ static void extract_fdots_nor_hq_finish(const MeshRenderData *mr,
void *buf,
void *UNUSED(data))
{
- static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
GPUVertBuf *vbo = buf;
+ static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
short *nor = (short *)GPU_vertbuf_get_data(vbo);
BMFace *efa;
@@ -4997,17 +4306,17 @@ static void extract_fdots_nor_hq_finish(const MeshRenderData *mr,
}
}
-static const MeshExtract extract_fdots_nor_hq = {
+const MeshExtract extract_fdots_nor_hq = {
.init = extract_fdots_nor_hq_init,
.finish = extract_fdots_nor_hq_finish,
- .data_flag = MR_DATA_POLY_NOR,
+ .data_type = MR_DATA_POLY_NOR,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots UV
+/** \name Extract Face-dots UV
* \{ */
typedef struct MeshExtract_FdotUV_Data {
@@ -5020,13 +4329,14 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_vertformat_alias_add(&format, "au");
GPU_vertformat_alias_add(&format, "pos");
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
@@ -5047,42 +4357,41 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr,
return data;
}
-static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ float w = 1.0f / (float)f->len;
+ const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
+ madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *_data)
{
MeshExtract_FdotUV_Data *data = _data;
- if (mr->use_subsurf_fdots) {
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (mr->use_subsurf_fdots) {
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 {
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ else {
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;
}
}
@@ -5094,18 +4403,19 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-static const MeshExtract extract_fdots_uv = {
+const MeshExtract extract_fdots_uv = {
.init = extract_fdots_uv_init,
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv)};
+
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots Edit UV flag
+/** \name Extract Face-dots Edit UV flag
* \{ */
typedef struct MeshExtract_EditUVFdotData_Data {
@@ -5117,11 +4427,12 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
@@ -5132,34 +4443,28 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr,
}
static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+ BMFace *f,
+ const int UNUSED(f_index),
void *_data)
{
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;
+ 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);
}
static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *UNUSED(mp),
+ const int mp_index,
void *_data)
{
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);
- }
+ 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),
@@ -5170,14 +4475,15 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-static const MeshExtract extract_fdots_edituv_data = {
+const MeshExtract extract_fdots_edituv_data = {
.init = extract_fdots_edituv_data_init,
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data)};
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -5193,6 +4499,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
/* Exclusively for edit mode. */
BLI_assert(mr->bm);
@@ -5201,7 +4508,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr,
GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->bm->totvert);
@@ -5228,11 +4535,11 @@ static void *extract_skin_roots_init(const MeshRenderData *mr,
return NULL;
}
-static const MeshExtract extract_skin_roots = {
+const MeshExtract extract_skin_roots = {
.init = extract_skin_roots_init,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = false,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots)};
/** \} */
@@ -5244,12 +4551,12 @@ static void *extract_select_idx_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* TODO rename "color" to something more descriptive. */
GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
}
- GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
return GPU_vertbuf_get_data(vbo);
@@ -5260,169 +4567,163 @@ static void *extract_select_idx_init(const MeshRenderData *mr,
* 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_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int f_index,
void *data)
{
- 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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ ((uint32_t *)data)[l_index] = f_index;
+ } while ((l_iter = l_iter->next) != l_first);
}
-static void extract_edge_idx_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- 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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->e);
+ } while ((l_iter = l_iter->next) != l_first);
}
-static void extract_vert_idx_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *f,
+ const int UNUSED(f_index),
void *data)
{
- 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);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
}
static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *data)
{
- 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;
+ ((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);
}
static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr,
- const ExtractLEdgeBMesh_Params *params,
+ BMEdge *eed,
+ const int ledge_index,
void *data)
{
- 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;
+ ((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);
}
static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr,
- const ExtractLVertBMesh_Params *params,
+ BMVert *eve,
+ const int lvert_index,
void *data)
{
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;
+
+ ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve);
}
static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int mp_index,
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
((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_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
((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_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
void *data)
{
- EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
- {
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
((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_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *UNUSED(med),
+ const uint ledge_index,
void *data)
{
- 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;
+ 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;
}
static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr,
- const ExtractLEdgeMesh_Params *params,
+ const MEdge *med,
+ const uint ledge_index,
void *data)
{
- 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;
+ 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;
}
static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
- const ExtractLVertMesh_Params *params,
+ const MVert *UNUSED(mv),
+ const int lvert_index,
void *data)
{
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;
+
+ 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;
}
-static const MeshExtract extract_poly_idx = {
+const MeshExtract extract_poly_idx = {
.init = extract_select_idx_init,
.iter_poly_bm = extract_poly_idx_iter_poly_bm,
.iter_poly_mesh = extract_poly_idx_iter_poly_mesh,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx)};
-static const MeshExtract extract_edge_idx = {
+const MeshExtract extract_edge_idx = {
.init = extract_select_idx_init,
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx)};
-static const MeshExtract extract_vert_idx = {
+const MeshExtract extract_vert_idx = {
.init = extract_select_idx_init,
.iter_poly_bm = extract_vert_idx_iter_poly_bm,
.iter_poly_mesh = extract_vert_idx_iter_poly_mesh,
@@ -5430,736 +4731,51 @@ static const MeshExtract extract_vert_idx = {
.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,
+ .data_type = 0,
.use_threading = true,
-};
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx)};
-static void *extract_select_fdot_idx_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf)
+static void *extract_fdot_idx_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf)
{
+ GPUVertBuf *vbo = buf;
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* TODO rename "color" to something more descriptive. */
GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
}
- GPUVertBuf *vbo = buf;
+
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
return GPU_vertbuf_get_data(vbo);
}
-static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *mr,
- const ExtractPolyBMesh_Params *params,
+static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ BMFace *UNUSED(f),
+ const int f_index,
void *data)
{
- EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
- {
- ((uint32_t *)data)[f_index] = f_index;
- }
- EXTRACT_POLY_FOREACH_BM_END;
+ ((uint32_t *)data)[f_index] = f_index;
}
static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr,
- const ExtractPolyMesh_Params *params,
+ const MPoly *UNUSED(mp),
+ const int mp_index,
void *data)
{
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;
+ ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index];
}
else {
- EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
- {
- ((uint32_t *)data)[mp_index] = mp_index;
- }
- EXTRACT_POLY_FOREACH_MESH_END;
+ ((uint32_t *)data)[mp_index] = mp_index;
}
}
-static const MeshExtract extract_fdot_idx = {
- .init = extract_select_fdot_idx_init,
+const MeshExtract extract_fdot_idx = {
+ .init = extract_fdot_idx_init,
.iter_poly_bm = extract_fdot_idx_iter_poly_bm,
.iter_poly_mesh = extract_fdot_idx_iter_poly_mesh,
- .data_flag = 0,
+ .data_type = 0,
.use_threading = true,
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name ExtractTaskData
- * \{ */
-typedef struct ExtractUserData {
- void *user_data;
-} ExtractUserData;
-
-typedef enum ExtractTaskDataType {
- EXTRACT_MESH_EXTRACT,
- EXTRACT_LINES_LOOSE,
-} ExtractTaskDataType;
-
-typedef struct ExtractTaskData {
- void *next, *prev;
- const MeshRenderData *mr;
- struct MeshBatchCache *cache;
- const MeshExtract *extract;
- ExtractTaskDataType tasktype;
- eMRIterType iter_type;
- int start, end;
- /** Decremented each time a task is finished. */
- int32_t *task_counter;
- void *buf;
- ExtractUserData *user_data;
-} ExtractTaskData;
-
-static ExtractTaskData *extract_task_data_create_mesh_extract(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- const MeshExtract *extract,
- void *buf,
- int32_t *task_counter)
-{
- ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), __func__);
- taskdata->next = NULL;
- taskdata->prev = NULL;
- taskdata->tasktype = EXTRACT_MESH_EXTRACT;
- taskdata->mr = mr;
- taskdata->cache = cache;
- taskdata->extract = extract;
- taskdata->buf = buf;
-
- /* #ExtractUserData is shared between the iterations as it holds counters to detect if the
- * extraction is finished. To make sure the duplication of the user_data does not create a new
- * instance of the counters we allocate the user_data in its own container.
- *
- * This structure makes sure that when extract_init is called, that the user data of all
- * iterations are updated. */
- taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__);
- taskdata->iter_type = mesh_extract_iter_type(extract);
- taskdata->task_counter = task_counter;
- taskdata->start = 0;
- taskdata->end = INT_MAX;
- return taskdata;
-}
-
-static ExtractTaskData *extract_task_data_create_lines_loose(const MeshRenderData *mr,
- struct MeshBatchCache *cache)
-{
- ExtractTaskData *taskdata = MEM_callocN(sizeof(*taskdata), __func__);
- taskdata->tasktype = EXTRACT_LINES_LOOSE;
- taskdata->mr = mr;
- taskdata->cache = cache;
- return taskdata;
-}
-
-static void extract_task_data_free(void *data)
-{
- ExtractTaskData *task_data = data;
- MEM_SAFE_FREE(task_data->user_data);
- MEM_freeN(task_data);
-}
-
-BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
- const eMRIterType iter_type,
- int start,
- int end,
- const MeshExtract *extract,
- void *user_data)
-{
- switch (mr->extract_type) {
- case MR_EXTRACT_BMESH:
- if (iter_type & MR_ITER_LOOPTRI) {
- 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_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) {
- 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) {
- 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) {
- 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_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) {
- 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) {
- extract->iter_lvert_mesh(mr,
- &(const ExtractLVertMesh_Params){
- .lvert = mr->lverts,
- .lvert_range = {start, min_ii(mr->vert_loose_len, end)},
- },
- user_data);
- }
- break;
- }
-}
-
-static void extract_init(ExtractTaskData *data)
-{
- if (data->tasktype == EXTRACT_MESH_EXTRACT) {
- data->user_data->user_data = data->extract->init(data->mr, data->cache, data->buf);
- }
-}
-
-static void extract_run(void *__restrict taskdata)
-{
- ExtractTaskData *data = (ExtractTaskData *)taskdata;
- if (data->tasktype == EXTRACT_MESH_EXTRACT) {
- mesh_extract_iter(data->mr,
- data->iter_type,
- data->start,
- data->end,
- data->extract,
- data->user_data->user_data);
-
- /* If this is the last task, we do the finish function. */
- int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1);
- if (remainin_tasks == 0 && data->extract->finish != NULL) {
- data->extract->finish(data->mr, data->cache, data->buf, data->user_data->user_data);
- }
- }
- else if (data->tasktype == EXTRACT_LINES_LOOSE) {
- extract_lines_loose_subbuffer(data->mr, data->cache);
- }
-}
-
-static void extract_init_and_run(void *__restrict taskdata)
-{
- extract_init((ExtractTaskData *)taskdata);
- extract_run(taskdata);
-}
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Task Node - Update Mesh Render Data
- * \{ */
-typedef struct MeshRenderDataUpdateTaskData {
- MeshRenderData *mr;
- eMRIterType iter_type;
- eMRDataType data_flag;
-} MeshRenderDataUpdateTaskData;
-
-static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata)
-{
- BLI_assert(taskdata);
- MeshRenderData *mr = taskdata->mr;
- mesh_render_data_free(mr);
- MEM_freeN(taskdata);
-}
-
-static void mesh_extract_render_data_node_exec(void *__restrict task_data)
-{
- MeshRenderDataUpdateTaskData *update_task_data = task_data;
- MeshRenderData *mr = update_task_data->mr;
- const eMRIterType iter_type = update_task_data->iter_type;
- const eMRDataType data_flag = update_task_data->data_flag;
-
- mesh_render_data_update_normals(mr, iter_type, data_flag);
- mesh_render_data_update_looptris(mr, iter_type, data_flag);
-}
-
-static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
- MeshRenderData *mr,
- const eMRIterType iter_type,
- const eMRDataType data_flag)
-{
- MeshRenderDataUpdateTaskData *task_data = MEM_mallocN(sizeof(MeshRenderDataUpdateTaskData),
- __func__);
- task_data->mr = mr;
- task_data->iter_type = iter_type;
- task_data->data_flag = data_flag;
-
- struct TaskNode *task_node = BLI_task_graph_node_create(
- task_graph,
- mesh_extract_render_data_node_exec,
- task_data,
- (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
- return task_node;
-}
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Task Node - Extract Single Threaded
- * \{ */
-typedef struct ExtractSingleThreadedTaskData {
- ListBase task_datas;
-} ExtractSingleThreadedTaskData;
-
-static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata)
-{
- BLI_assert(taskdata);
- LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
- extract_task_data_free(td);
- }
- BLI_listbase_clear(&taskdata->task_datas);
- MEM_freeN(taskdata);
-}
-
-static void extract_single_threaded_task_node_exec(void *__restrict task_data)
-{
- ExtractSingleThreadedTaskData *extract_task_data = task_data;
- LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
- extract_init_and_run(td);
- }
-}
-
-static struct TaskNode *extract_single_threaded_task_node_create(
- struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data)
-{
- struct TaskNode *task_node = BLI_task_graph_node_create(
- task_graph,
- extract_single_threaded_task_node_exec,
- task_data,
- (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free);
- return task_node;
-}
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Task Node - UserData Initializer
- * \{ */
-typedef struct UserDataInitTaskData {
- ListBase task_datas;
- int32_t *task_counters;
-
-} UserDataInitTaskData;
-
-static void user_data_init_task_data_free(UserDataInitTaskData *taskdata)
-{
- BLI_assert(taskdata);
- LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
- extract_task_data_free(td);
- }
- BLI_listbase_clear(&taskdata->task_datas);
- MEM_SAFE_FREE(taskdata->task_counters);
- MEM_freeN(taskdata);
-}
-
-static void user_data_init_task_data_exec(void *__restrict task_data)
-{
- UserDataInitTaskData *extract_task_data = task_data;
- LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
- extract_init(td);
- }
-}
-
-static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph,
- UserDataInitTaskData *task_data)
-{
- struct TaskNode *task_node = BLI_task_graph_node_create(
- task_graph,
- user_data_init_task_data_exec,
- task_data,
- (TaskGraphNodeFreeFunction)user_data_init_task_data_free);
- return task_node;
-}
-
-/** \} */
-/* ---------------------------------------------------------------------- */
-/** \name Extract Loop
- * \{ */
-
-static void extract_range_task_create(struct TaskGraph *task_graph,
- struct TaskNode *task_node_user_data_init,
- ExtractTaskData *taskdata,
- const eMRIterType type,
- int start,
- int length)
-{
- taskdata = MEM_dupallocN(taskdata);
- atomic_add_and_fetch_int32(taskdata->task_counter, 1);
- taskdata->iter_type = type;
- taskdata->start = start;
- taskdata->end = start + length;
- struct TaskNode *task_node = BLI_task_graph_node_create(
- task_graph, extract_run, taskdata, MEM_freeN);
- BLI_task_graph_edge_create(task_node_user_data_init, task_node);
-}
-
-static void extract_task_create(struct TaskGraph *task_graph,
- struct TaskNode *task_node_mesh_render_data,
- struct TaskNode *task_node_user_data_init,
- ListBase *single_threaded_task_datas,
- ListBase *user_data_init_task_datas,
- const Scene *scene,
- const MeshRenderData *mr,
- MeshBatchCache *cache,
- const MeshExtract *extract,
- void *buf,
- int32_t *task_counter)
-{
- BLI_assert(scene != NULL);
- const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
- GPU_use_hq_normals_workaround();
- if (do_hq_normals) {
- if (extract == &extract_lnor) {
- extract = &extract_lnor_hq;
- }
- else if (extract == &extract_pos_nor) {
- extract = &extract_pos_nor_hq;
- }
- else if (extract == &extract_tan) {
- extract = &extract_tan_hq;
- }
- else if (extract == &extract_fdots_nor) {
- extract = &extract_fdots_nor_hq;
- }
- }
-
- /* Divide extraction of the VBO/IBO into sensible chunks of works. */
- ExtractTaskData *taskdata = extract_task_data_create_mesh_extract(
- mr, cache, extract, buf, task_counter);
-
- /* Simple heuristic. */
- const int chunk_size = 8192;
- const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size;
- if (use_thread && extract->use_threading) {
-
- /* Divide task into sensible chunks. */
- if (taskdata->iter_type & MR_ITER_LOOPTRI) {
- for (int i = 0; i < mr->tri_len; i += chunk_size) {
- extract_range_task_create(
- task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
- }
- }
- 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_POLY, i, chunk_size);
- }
- }
- if (taskdata->iter_type & MR_ITER_LEDGE) {
- for (int i = 0; i < mr->edge_loose_len; i += chunk_size) {
- extract_range_task_create(
- task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size);
- }
- }
- if (taskdata->iter_type & MR_ITER_LVERT) {
- for (int i = 0; i < mr->vert_loose_len; i += chunk_size) {
- extract_range_task_create(
- task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size);
- }
- }
- BLI_addtail(user_data_init_task_datas, taskdata);
- }
- else if (use_thread) {
- /* One task for the whole VBO. */
- (*task_counter)++;
- struct TaskNode *one_task = BLI_task_graph_node_create(
- task_graph, extract_init_and_run, taskdata, extract_task_data_free);
- BLI_task_graph_edge_create(task_node_mesh_render_data, one_task);
- }
- else {
- /* Single threaded extraction. */
- (*task_counter)++;
- BLI_addtail(single_threaded_task_datas, taskdata);
- }
-}
-
-void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
- MeshBatchCache *cache,
- MeshBufferCache mbc,
- Mesh *me,
-
- const bool is_editmode,
- const bool is_paint_mode,
- const bool is_mode_active,
- const float obmat[4][4],
- const bool do_final,
- const bool do_uvedit,
- const bool use_subsurf_fdots,
- const DRW_MeshCDMask *cd_layer_used,
- const Scene *scene,
- const ToolSettings *ts,
- const bool use_hide)
-{
- /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
- * This sub-graph starts with an extract_render_data_node. This fills/converts the required data
- * from Mesh.
- *
- * Small extractions and extractions that can't be multi-threaded are grouped in a single
- * `extract_single_threaded_task_node`.
- *
- * Other extractions will create a node for each loop exceeding 8192 items. these nodes are
- * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the
- * user_data needed for the extraction based on the data extracted from the mesh.
- * counters are used to check if the finalize of a task has to be called.
- *
- * Mesh extraction sub graph
- *
- * +----------------------+
- * +-----> | extract_task1_loop_1 |
- * | +----------------------+
- * +------------------+ +----------------------+ +----------------------+
- * | mesh_render_data | --> | | --> | extract_task1_loop_2 |
- * +------------------+ | | +----------------------+
- * | | | +----------------------+
- * | | user_data_init | --> | extract_task2_loop_1 |
- * v | | +----------------------+
- * +------------------+ | | +----------------------+
- * | single_threaded | | | --> | extract_task2_loop_2 |
- * +------------------+ +----------------------+ +----------------------+
- * | +----------------------+
- * +-----> | extract_task2_loop_3 |
- * +----------------------+
- */
- eMRIterType iter_flag = 0;
- eMRDataType data_flag = 0;
-
- const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL;
-
-#define TEST_ASSIGN(type, type_lowercase, name) \
- do { \
- if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \
- iter_flag |= mesh_extract_iter_type(&extract_##name); \
- data_flag |= extract_##name.data_flag; \
- } \
- } while (0)
-
- TEST_ASSIGN(VBO, vbo, pos_nor);
- TEST_ASSIGN(VBO, vbo, lnor);
- TEST_ASSIGN(VBO, vbo, uv);
- TEST_ASSIGN(VBO, vbo, tan);
- TEST_ASSIGN(VBO, vbo, vcol);
- TEST_ASSIGN(VBO, vbo, sculpt_data);
- TEST_ASSIGN(VBO, vbo, orco);
- TEST_ASSIGN(VBO, vbo, edge_fac);
- TEST_ASSIGN(VBO, vbo, weights);
- TEST_ASSIGN(VBO, vbo, edit_data);
- TEST_ASSIGN(VBO, vbo, edituv_data);
- TEST_ASSIGN(VBO, vbo, edituv_stretch_area);
- TEST_ASSIGN(VBO, vbo, edituv_stretch_angle);
- TEST_ASSIGN(VBO, vbo, mesh_analysis);
- TEST_ASSIGN(VBO, vbo, fdots_pos);
- TEST_ASSIGN(VBO, vbo, fdots_nor);
- TEST_ASSIGN(VBO, vbo, fdots_uv);
- TEST_ASSIGN(VBO, vbo, fdots_edituv_data);
- TEST_ASSIGN(VBO, vbo, poly_idx);
- TEST_ASSIGN(VBO, vbo, edge_idx);
- TEST_ASSIGN(VBO, vbo, vert_idx);
- TEST_ASSIGN(VBO, vbo, fdot_idx);
- TEST_ASSIGN(VBO, vbo, skin_roots);
-
- TEST_ASSIGN(IBO, ibo, tris);
- TEST_ASSIGN(IBO, ibo, lines);
- TEST_ASSIGN(IBO, ibo, points);
- TEST_ASSIGN(IBO, ibo, fdots);
- TEST_ASSIGN(IBO, ibo, lines_paint_mask);
- TEST_ASSIGN(IBO, ibo, lines_adjacency);
- TEST_ASSIGN(IBO, ibo, edituv_tris);
- TEST_ASSIGN(IBO, ibo, edituv_lines);
- TEST_ASSIGN(IBO, ibo, edituv_points);
- TEST_ASSIGN(IBO, ibo, edituv_fdots);
-
- if (do_lines_loose_subbuffer) {
- iter_flag |= MR_ITER_LEDGE;
- }
-
-#undef TEST_ASSIGN
-
-#ifdef DEBUG_TIME
- double rdata_start = PIL_check_seconds_timer();
-#endif
-
- MeshRenderData *mr = mesh_render_data_create(me,
- is_editmode,
- is_paint_mode,
- is_mode_active,
- obmat,
- do_final,
- do_uvedit,
- cd_layer_used,
- ts,
- iter_flag,
- data_flag);
- mr->use_hide = use_hide;
- mr->use_subsurf_fdots = use_subsurf_fdots;
- mr->use_final_mesh = do_final;
-
-#ifdef DEBUG_TIME
- double rdata_end = PIL_check_seconds_timer();
-#endif
-
- size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t);
- int32_t *task_counters = MEM_callocN(counters_size, __func__);
- int counter_used = 0;
-
- struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
- task_graph, mr, iter_flag, data_flag);
- ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN(
- sizeof(ExtractSingleThreadedTaskData), __func__);
- UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData),
- __func__);
- user_data_init_task_data->task_counters = task_counters;
- struct TaskNode *task_node_user_data_init = user_data_init_task_node_create(
- task_graph, user_data_init_task_data);
-
-#define EXTRACT(buf, name) \
- if (mbc.buf.name) { \
- extract_task_create(task_graph, \
- task_node_mesh_render_data, \
- task_node_user_data_init, \
- &single_threaded_task_data->task_datas, \
- &user_data_init_task_data->task_datas, \
- scene, \
- mr, \
- cache, \
- &extract_##name, \
- mbc.buf.name, \
- &task_counters[counter_used++]); \
- } \
- ((void)0)
-
- EXTRACT(vbo, pos_nor);
- EXTRACT(vbo, lnor);
- EXTRACT(vbo, uv);
- EXTRACT(vbo, tan);
- EXTRACT(vbo, vcol);
- EXTRACT(vbo, sculpt_data);
- EXTRACT(vbo, orco);
- EXTRACT(vbo, edge_fac);
- EXTRACT(vbo, weights);
- EXTRACT(vbo, edit_data);
- EXTRACT(vbo, edituv_data);
- EXTRACT(vbo, edituv_stretch_area);
- EXTRACT(vbo, edituv_stretch_angle);
- EXTRACT(vbo, mesh_analysis);
- EXTRACT(vbo, fdots_pos);
- EXTRACT(vbo, fdots_nor);
- EXTRACT(vbo, fdots_uv);
- EXTRACT(vbo, fdots_edituv_data);
- EXTRACT(vbo, poly_idx);
- EXTRACT(vbo, edge_idx);
- EXTRACT(vbo, vert_idx);
- EXTRACT(vbo, fdot_idx);
- EXTRACT(vbo, skin_roots);
-
- EXTRACT(ibo, tris);
- if (mbc.ibo.lines) {
- /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates
- * the `lines_loose` sub-buffer. */
- const MeshExtract *lines_extractor = do_lines_loose_subbuffer ?
- &extract_lines_with_lines_loose :
- &extract_lines;
- extract_task_create(task_graph,
- task_node_mesh_render_data,
- task_node_user_data_init,
- &single_threaded_task_data->task_datas,
- &user_data_init_task_data->task_datas,
- scene,
- mr,
- cache,
- lines_extractor,
- mbc.ibo.lines,
- &task_counters[counter_used++]);
- }
- else {
- if (do_lines_loose_subbuffer) {
- ExtractTaskData *taskdata = extract_task_data_create_lines_loose(mr, cache);
- BLI_addtail(&single_threaded_task_data->task_datas, taskdata);
- }
- }
- EXTRACT(ibo, points);
- EXTRACT(ibo, fdots);
- EXTRACT(ibo, lines_paint_mask);
- EXTRACT(ibo, lines_adjacency);
- EXTRACT(ibo, edituv_tris);
- EXTRACT(ibo, edituv_lines);
- EXTRACT(ibo, edituv_points);
- EXTRACT(ibo, edituv_fdots);
-
- /* Only create the edge when there is user data that needs to be initialized.
- * The task is still part of the graph so the task_data will be freed when the graph is freed.
- */
- if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) {
- BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init);
- }
-
- if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) {
- struct TaskNode *task_node = extract_single_threaded_task_node_create(
- task_graph, single_threaded_task_data);
- BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
- }
- else {
- extract_single_threaded_task_data_free(single_threaded_task_data);
- }
-
- /* Trigger the sub-graph for this mesh. */
- BLI_task_graph_node_push_work(task_node_mesh_render_data);
-
-#undef EXTRACT
-
-#ifdef DEBUG_TIME
- BLI_task_graph_work_and_wait(task_graph);
- double end = PIL_check_seconds_timer();
-
- static double avg = 0;
- static double avg_fps = 0;
- static double avg_rdata = 0;
- static double end_prev = 0;
-
- if (end_prev == 0) {
- end_prev = end;
- }
-
- avg = avg * 0.95 + (end - rdata_end) * 0.05;
- avg_fps = avg_fps * 0.95 + (end - end_prev) * 0.05;
- avg_rdata = avg_rdata * 0.95 + (rdata_end - rdata_start) * 0.05;
-
- printf(
- "rdata %.0fms iter %.0fms (frame %.0fms)\n", avg_rdata * 1000, avg * 1000, avg_fps * 1000);
-
- end_prev = end;
-#endif
-}
-
-/** \} */
+ .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)};
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_private.h b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
new file mode 100644
index 00000000000..6761282fe79
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
@@ -0,0 +1,514 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Extraction of Mesh data into VBO to feed to GPU.
+ */
+
+#pragma once
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_editmesh.h"
+
+#include "draw_cache_extract.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum eMRExtractType {
+ MR_EXTRACT_BMESH,
+ MR_EXTRACT_MAPPED,
+ MR_EXTRACT_MESH,
+} eMRExtractType;
+
+typedef struct MeshRenderData {
+ eMRExtractType extract_type;
+
+ int poly_len, edge_len, vert_len, loop_len;
+ int edge_loose_len;
+ int vert_loose_len;
+ int loop_loose_len;
+ int tri_len;
+ int mat_len;
+
+ bool use_hide;
+ bool use_subsurf_fdots;
+ bool use_final_mesh;
+
+ /** Use for #MeshStatVis calculation which use world-space coords. */
+ float obmat[4][4];
+
+ const ToolSettings *toolsettings;
+ /** Edit Mesh */
+ BMEditMesh *edit_bmesh;
+ BMesh *bm;
+ EditMeshData *edit_data;
+
+ /* For deformed edit-mesh data. */
+ /* Use for #ME_WRAPPER_TYPE_BMESH. */
+ const float (*bm_vert_coords)[3];
+ const float (*bm_vert_normals)[3];
+ const float (*bm_poly_normals)[3];
+ const float (*bm_poly_centers)[3];
+
+ int *v_origindex, *e_origindex, *p_origindex;
+ int crease_ofs;
+ int bweight_ofs;
+ int freestyle_edge_ofs;
+ int freestyle_face_ofs;
+ /** Mesh */
+ Mesh *me;
+ const MVert *mvert;
+ const MEdge *medge;
+ const MLoop *mloop;
+ const MPoly *mpoly;
+ BMVert *eve_act;
+ BMEdge *eed_act;
+ BMFace *efa_act;
+ BMFace *efa_act_uv;
+ /* Data created on-demand (usually not for #BMesh based data). */
+ MLoopTri *mlooptri;
+ float (*loop_normals)[3];
+ float (*poly_normals)[3];
+ int *lverts, *ledges;
+} MeshRenderData;
+
+BLI_INLINE BMFace *bm_original_face_get(const MeshRenderData *mr, int idx)
+{
+ return ((mr->p_origindex != NULL) && (mr->p_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
+ BM_face_at_index(mr->bm, mr->p_origindex[idx]) :
+ NULL;
+}
+
+BLI_INLINE BMEdge *bm_original_edge_get(const MeshRenderData *mr, int idx)
+{
+ return ((mr->e_origindex != NULL) && (mr->e_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
+ BM_edge_at_index(mr->bm, mr->e_origindex[idx]) :
+ NULL;
+}
+
+BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx)
+{
+ return ((mr->v_origindex != NULL) && (mr->v_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
+ BM_vert_at_index(mr->bm, mr->v_origindex[idx]) :
+ NULL;
+}
+
+BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_coords)[3] = mr->bm_vert_coords;
+ if (vert_coords != NULL) {
+ return vert_coords[BM_elem_index_get(eve)];
+ }
+
+ UNUSED_VARS(mr);
+ return eve->co;
+}
+
+BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_normals)[3] = mr->bm_vert_normals;
+ if (vert_normals != NULL) {
+ return vert_normals[BM_elem_index_get(eve)];
+ }
+
+ UNUSED_VARS(mr);
+ return eve->no;
+}
+
+BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
+{
+ const float(*poly_normals)[3] = mr->bm_poly_normals;
+ if (poly_normals != NULL) {
+ return poly_normals[BM_elem_index_get(efa)];
+ }
+
+ UNUSED_VARS(mr);
+ return efa->no;
+}
+
+/* TODO(jbakker): phase out batch iteration macros as they are only used once. */
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Loop Triangles
+ * \{ */
+
+typedef struct ExtractTriBMesh_Params {
+ BMLoop *(*looptris)[3];
+ int tri_range[2];
+} ExtractTriBMesh_Params;
+typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
+ BMLoop **elt,
+ const int elt_index,
+ 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,
+ const MLoopTri *mlt,
+ const int elt_index,
+ void *data);
+
+#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,
+ BMFace *f,
+ const int f_index,
+ 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 MPoly *mp,
+ const int mp_index,
+ 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,
+ BMEdge *eed,
+ const int ledge_index,
+ 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,
+ const MEdge *med,
+ const uint ledge_index,
+ 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,
+ BMVert *eve,
+ const int lvert_index,
+ 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,
+ const MVert *mv,
+ const int lvert_index,
+ 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,
+ struct MeshBatchCache *cache,
+ void *buffer);
+typedef void(ExtractFinishFn)(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *data);
+
+typedef struct MeshExtract {
+ /** Executed on main thread and return user data for iteration functions. */
+ ExtractInitFn *init;
+ /** Executed on one (or more if use_threading) worker thread(s). */
+ ExtractTriBMeshFn *iter_looptri_bm;
+ ExtractTriMeshFn *iter_looptri_mesh;
+ ExtractPolyBMeshFn *iter_poly_bm;
+ ExtractPolyMeshFn *iter_poly_mesh;
+ ExtractLEdgeBMeshFn *iter_ledge_bm;
+ ExtractLEdgeMeshFn *iter_ledge_mesh;
+ ExtractLVertBMeshFn *iter_lvert_bm;
+ ExtractLVertMeshFn *iter_lvert_mesh;
+ /** Executed on one worker thread after all elements iterations. */
+ ExtractFinishFn *finish;
+ /** Used to request common data. */
+ const eMRDataType data_type;
+ /** Used to know if the element callbacks are thread-safe and can be parallelized. */
+ const bool use_threading;
+ /**
+ * Offset in bytes of the buffer inside a MeshBufferCache instance. Points to a vertex or index
+ * buffer.
+ */
+ const size_t mesh_buffer_offset;
+} MeshExtract;
+
+/** \} */
+
+/* draw_cache_extract_mesh_render_data.c */
+MeshRenderData *mesh_render_data_create(Mesh *me,
+ MeshBufferExtractionCache *cache,
+ const bool is_editmode,
+ const bool is_paint_mode,
+ const bool is_mode_active,
+ const float obmat[4][4],
+ const bool do_final,
+ const bool do_uvedit,
+ const ToolSettings *ts,
+ const eMRIterType iter_type);
+void mesh_render_data_free(MeshRenderData *mr);
+void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag);
+void mesh_render_data_update_looptris(MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag);
+
+/* draw_cache_extract_mesh_extractors.c */
+void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc);
+eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
+const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
+ const bool do_hq_normals);
+/*
+ * Total number of extractions types.
+ */
+#define M_EXTRACT_LEN 38
+
+extern const MeshExtract extract_tris;
+extern const MeshExtract extract_lines;
+extern const MeshExtract extract_lines_with_lines_loose;
+extern const MeshExtract extract_lines_loose_only;
+extern const MeshExtract extract_points;
+extern const MeshExtract extract_fdots;
+extern const MeshExtract extract_lines_paint_mask;
+extern const MeshExtract extract_lines_adjacency;
+extern const MeshExtract extract_edituv_tris;
+extern const MeshExtract extract_edituv_lines;
+extern const MeshExtract extract_edituv_points;
+extern const MeshExtract extract_edituv_fdots;
+extern const MeshExtract extract_pos_nor;
+extern const MeshExtract extract_pos_nor_hq;
+extern const MeshExtract extract_lnor_hq;
+extern const MeshExtract extract_lnor;
+extern const MeshExtract extract_uv;
+extern const MeshExtract extract_tan;
+extern const MeshExtract extract_tan_hq;
+extern const MeshExtract extract_sculpt_data;
+extern const MeshExtract extract_vcol;
+extern const MeshExtract extract_orco;
+extern const MeshExtract extract_edge_fac;
+extern const MeshExtract extract_weights;
+extern const MeshExtract extract_edit_data;
+extern const MeshExtract extract_edituv_data;
+extern const MeshExtract extract_edituv_stretch_area;
+extern const MeshExtract extract_edituv_stretch_angle;
+extern const MeshExtract extract_mesh_analysis;
+extern const MeshExtract extract_fdots_pos;
+extern const MeshExtract extract_fdots_nor;
+extern const MeshExtract extract_fdots_nor_hq;
+extern const MeshExtract extract_fdots_uv;
+extern const MeshExtract extract_fdots_edituv_data;
+extern const MeshExtract extract_skin_roots;
+extern const MeshExtract extract_poly_idx;
+extern const MeshExtract extract_edge_idx;
+extern const MeshExtract extract_vert_idx;
+extern const MeshExtract extract_fdot_idx;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
new file mode 100644
index 00000000000..4741bcb06c9
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
@@ -0,0 +1,371 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Extraction of Mesh data into VBO to feed to GPU.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
+#include "BKE_mesh.h"
+
+#include "GPU_batch.h"
+
+#include "ED_mesh.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
+ * \{ */
+
+static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferExtractionCache *cache)
+{
+ mr->ledges = cache->ledges;
+ mr->lverts = cache->lverts;
+ mr->vert_loose_len = cache->vert_loose_len;
+ mr->edge_loose_len = cache->edge_loose_len;
+
+ mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
+}
+
+static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr,
+ MeshBufferExtractionCache *cache)
+{
+ /* Early exit: Are loose geometry already available. Only checking for loose verts as loose edges
+ * and verts are calculated at the same time.*/
+ if (cache->lverts) {
+ return;
+ }
+
+ cache->vert_loose_len = 0;
+ cache->edge_loose_len = 0;
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
+
+ BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
+
+ cache->ledges = MEM_mallocN(mr->edge_len * sizeof(*cache->ledges), __func__);
+ const MEdge *med = mr->medge;
+ for (int med_index = 0; med_index < mr->edge_len; med_index++, med++) {
+ if (med->flag & ME_LOOSEEDGE) {
+ cache->ledges[cache->edge_loose_len++] = med_index;
+ }
+ /* Tag verts as not loose. */
+ BLI_BITMAP_ENABLE(lvert_map, med->v1);
+ BLI_BITMAP_ENABLE(lvert_map, med->v2);
+ }
+ if (cache->edge_loose_len < mr->edge_len) {
+ cache->ledges = MEM_reallocN(cache->ledges, cache->edge_loose_len * sizeof(*cache->ledges));
+ }
+
+ cache->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__);
+ for (int v = 0; v < mr->vert_len; v++) {
+ if (!BLI_BITMAP_TEST(lvert_map, v)) {
+ cache->lverts[cache->vert_loose_len++] = v;
+ }
+ }
+ if (cache->vert_loose_len < mr->vert_len) {
+ cache->lverts = MEM_reallocN(cache->lverts, cache->vert_loose_len * sizeof(*cache->lverts));
+ }
+
+ MEM_freeN(lvert_map);
+ }
+ else {
+ /* #BMesh */
+ BMesh *bm = mr->bm;
+ int elem_id;
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *ede;
+
+ cache->lverts = MEM_mallocN(mr->vert_len * sizeof(*cache->lverts), __func__);
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) {
+ if (eve->e == NULL) {
+ cache->lverts[cache->vert_loose_len++] = elem_id;
+ }
+ }
+ if (cache->vert_loose_len < mr->vert_len) {
+ cache->lverts = MEM_reallocN(cache->lverts, cache->vert_loose_len * sizeof(*cache->lverts));
+ }
+
+ cache->ledges = MEM_mallocN(mr->edge_len * sizeof(*cache->ledges), __func__);
+ BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) {
+ if (ede->l == NULL) {
+ cache->ledges[cache->edge_loose_len++] = elem_id;
+ }
+ }
+ if (cache->edge_loose_len < mr->edge_len) {
+ cache->ledges = MEM_reallocN(cache->ledges, cache->edge_loose_len * sizeof(*cache->ledges));
+ }
+ }
+}
+
+/**
+ * Part of the creation of the #MeshRenderData that happens in a thread.
+ */
+void mesh_render_data_update_looptris(MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ Mesh *me = mr->me;
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
+ if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
+ mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI");
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri);
+ }
+ }
+ else {
+ /* #BMesh */
+ if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
+ /* Edit mode ensures this is valid, no need to calculate. */
+ BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL));
+ }
+ }
+}
+
+void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag)
+{
+ Mesh *me = mr->me;
+ const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
+ if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
+ mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
+ BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
+ NULL,
+ mr->vert_len,
+ mr->mloop,
+ mr->mpoly,
+ mr->loop_len,
+ mr->poly_len,
+ mr->poly_normals,
+ true);
+ }
+ if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
+ mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
+ short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL);
+ BKE_mesh_normals_loop_split(mr->me->mvert,
+ mr->vert_len,
+ mr->me->medge,
+ mr->edge_len,
+ mr->me->mloop,
+ mr->loop_normals,
+ mr->loop_len,
+ mr->me->mpoly,
+ mr->poly_normals,
+ mr->poly_len,
+ is_auto_smooth,
+ split_angle,
+ NULL,
+ clnors,
+ NULL);
+ }
+ }
+ else {
+ /* #BMesh */
+ if (data_flag & MR_DATA_POLY_NOR) {
+ /* Use #BMFace.no instead. */
+ }
+ if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
+
+ const float(*vert_coords)[3] = NULL;
+ const float(*vert_normals)[3] = NULL;
+ const float(*poly_normals)[3] = NULL;
+
+ if (mr->edit_data && mr->edit_data->vertexCos) {
+ vert_coords = mr->bm_vert_coords;
+ vert_normals = mr->bm_vert_normals;
+ poly_normals = mr->bm_poly_normals;
+ }
+
+ mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
+ const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
+ BM_loops_calc_normal_vcos(mr->bm,
+ vert_coords,
+ vert_normals,
+ poly_normals,
+ is_auto_smooth,
+ split_angle,
+ mr->loop_normals,
+ NULL,
+ NULL,
+ clnors_offset,
+ false);
+ }
+ }
+}
+
+/**
+ * \param is_mode_active: When true, use the modifiers from the edit-data,
+ * otherwise don't use modifiers as they are not from this object.
+ */
+MeshRenderData *mesh_render_data_create(Mesh *me,
+ MeshBufferExtractionCache *cache,
+ const bool is_editmode,
+ const bool is_paint_mode,
+ const bool is_mode_active,
+ const float obmat[4][4],
+ const bool do_final,
+ const bool do_uvedit,
+ const ToolSettings *ts,
+ const eMRIterType iter_type)
+{
+ MeshRenderData *mr = MEM_callocN(sizeof(*mr), __func__);
+ mr->toolsettings = ts;
+ mr->mat_len = mesh_render_mat_len_get(me);
+
+ copy_m4_m4(mr->obmat, obmat);
+
+ if (is_editmode) {
+ BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
+ mr->bm = me->edit_mesh->bm;
+ mr->edit_bmesh = me->edit_mesh;
+ mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
+ mr->edit_data = is_mode_active ? mr->me->runtime.edit_data : NULL;
+
+ if (mr->edit_data) {
+ EditMeshData *emd = mr->edit_data;
+ if (emd->vertexCos) {
+ BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd);
+ BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd);
+ }
+
+ mr->bm_vert_coords = mr->edit_data->vertexCos;
+ mr->bm_vert_normals = mr->edit_data->vertexNos;
+ mr->bm_poly_normals = mr->edit_data->polyNos;
+ mr->bm_poly_centers = mr->edit_data->polyCos;
+ }
+
+ bool has_mdata = is_mode_active && (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
+ bool use_mapped = is_mode_active &&
+ (has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original);
+
+ int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
+
+ BM_mesh_elem_index_ensure(mr->bm, bm_ensure_types);
+ BM_mesh_elem_table_ensure(mr->bm, bm_ensure_types & ~BM_LOOP);
+
+ mr->efa_act_uv = EDBM_uv_active_face_get(mr->edit_bmesh, false, false);
+ mr->efa_act = BM_mesh_active_face_get(mr->bm, false, true);
+ mr->eed_act = BM_mesh_active_edge_get(mr->bm);
+ mr->eve_act = BM_mesh_active_vert_get(mr->bm);
+
+ mr->crease_ofs = CustomData_get_offset(&mr->bm->edata, CD_CREASE);
+ mr->bweight_ofs = CustomData_get_offset(&mr->bm->edata, CD_BWEIGHT);
+#ifdef WITH_FREESTYLE
+ mr->freestyle_edge_ofs = CustomData_get_offset(&mr->bm->edata, CD_FREESTYLE_EDGE);
+ mr->freestyle_face_ofs = CustomData_get_offset(&mr->bm->pdata, CD_FREESTYLE_FACE);
+#endif
+
+ if (use_mapped) {
+ mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
+ mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
+ mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+
+ use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
+ }
+
+ mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_BMESH;
+
+ /* Seems like the mesh_eval_final do not have the right origin indices.
+ * Force not mapped in this case. */
+ if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
+ // mr->edit_bmesh = NULL;
+ mr->extract_type = MR_EXTRACT_MESH;
+ }
+ }
+ else {
+ mr->me = me;
+ mr->edit_bmesh = NULL;
+
+ bool use_mapped = is_paint_mode && mr->me && !mr->me->runtime.is_original;
+ if (use_mapped) {
+ mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
+ mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
+ mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+
+ use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
+ }
+
+ mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_MESH;
+ }
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
+ mr->vert_len = mr->me->totvert;
+ mr->edge_len = mr->me->totedge;
+ mr->loop_len = mr->me->totloop;
+ mr->poly_len = mr->me->totpoly;
+ mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
+
+ mr->mvert = CustomData_get_layer(&mr->me->vdata, CD_MVERT);
+ mr->medge = CustomData_get_layer(&mr->me->edata, CD_MEDGE);
+ mr->mloop = CustomData_get_layer(&mr->me->ldata, CD_MLOOP);
+ mr->mpoly = CustomData_get_layer(&mr->me->pdata, CD_MPOLY);
+
+ mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
+ mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
+ mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+ }
+ else {
+ /* #BMesh */
+ BMesh *bm = mr->bm;
+
+ mr->vert_len = bm->totvert;
+ mr->edge_len = bm->totedge;
+ mr->loop_len = bm->totloop;
+ mr->poly_len = bm->totface;
+ mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
+ }
+
+ if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
+ mesh_render_data_loose_geom_ensure(mr, cache);
+ mesh_render_data_loose_geom_load(mr, cache);
+ }
+
+ return mr;
+}
+
+void mesh_render_data_free(MeshRenderData *mr)
+{
+ MEM_SAFE_FREE(mr->mlooptri);
+ MEM_SAFE_FREE(mr->poly_normals);
+ MEM_SAFE_FREE(mr->loop_normals);
+
+ /* Loose geometry are owned by MeshBufferExtractionCache. */
+ mr->ledges = NULL;
+ mr->lverts = NULL;
+
+ MEM_freeN(mr);
+}
+
+/** \} */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 2c2ab9eaadd..5743f39f7da 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -266,7 +266,6 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object *
struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object,
struct ParticleSystem *psys,
struct PTCacheEdit *edit);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc
index 223b44724b6..ee6a47e3dc6 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curve.cc
@@ -25,8 +25,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.hh"
+#include "BLI_float3.hh"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
+#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
@@ -34,6 +37,8 @@
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_font.h"
+#include "BKE_geometry_set.hh"
+#include "BKE_spline.hh"
#include "GPU_batch.h"
#include "GPU_capabilities.h"
@@ -48,6 +53,11 @@
#include "draw_cache_impl.h" /* own include */
+using blender::Array;
+using blender::float3;
+using blender::IndexRange;
+using blender::Span;
+
/* See: edit_curve_point_vert.glsl for duplicate includes. */
#define SELECT 1
#define ACTIVE_NURB (1 << 2)
@@ -139,6 +149,21 @@ static void curve_render_wire_verts_edges_len_get(const CurveCache *ob_curve_cac
}
}
+static void curve_eval_render_wire_verts_edges_len_get(const CurveEval &curve_eval,
+ int *r_curve_len,
+ int *r_vert_len,
+ int *r_edge_len)
+{
+ Span<SplinePtr> splines = curve_eval.splines();
+ *r_curve_len = splines.size();
+ *r_vert_len = 0;
+ *r_edge_len = 0;
+ for (const SplinePtr &spline : splines) {
+ *r_vert_len += spline->evaluated_points_size();
+ *r_edge_len += spline->evaluated_edges_size();
+ }
+}
+
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
{
int normal_len = 0;
@@ -192,6 +217,9 @@ struct CurveRenderData {
/* borrow from 'Object' */
CurveCache *ob_curve_cache;
+ /* Owned by the evaluated object's geometry set (#geometry_set_eval). */
+ const CurveEval *curve_eval;
+
/* borrow from 'Curve' */
ListBase *nurbs;
@@ -230,11 +258,21 @@ static CurveRenderData *curve_render_data_create(Curve *cu,
rdata->ob_curve_cache = ob_curve_cache;
+ rdata->curve_eval = cu->curve_eval;
+
if (types & CU_DATATYPE_WIRE) {
- curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache,
- &rdata->wire.curve_len,
- &rdata->wire.vert_len,
- &rdata->wire.edge_len);
+ if (rdata->curve_eval != nullptr) {
+ curve_eval_render_wire_verts_edges_len_get(*rdata->curve_eval,
+ &rdata->wire.curve_len,
+ &rdata->wire.vert_len,
+ &rdata->wire.edge_len);
+ }
+ else {
+ curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache,
+ &rdata->wire.curve_len,
+ &rdata->wire.vert_len,
+ &rdata->wire.edge_len);
+ }
}
if (cu->editnurb) {
@@ -556,8 +594,6 @@ void DRW_curve_batch_cache_free(Curve *cu)
/* GPUBatch cache usage. */
static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
{
- BLI_assert(rdata->ob_curve_cache != nullptr);
-
static GPUVertFormat format = {0};
static struct {
uint pos;
@@ -570,30 +606,46 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
- int v_idx = 0;
- LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
- if (bl->nr <= 0) {
- continue;
- }
- const int i_end = v_idx + bl->nr;
- for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
- GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
+ if (rdata->curve_eval != nullptr) {
+ const CurveEval &curve_eval = *rdata->curve_eval;
+ Span<SplinePtr> splines = curve_eval.splines();
+ Array<int> offsets = curve_eval.evaluated_point_offsets();
+ BLI_assert(offsets.last() == vert_len);
+
+ for (const int i_spline : splines.index_range()) {
+ Span<float3> positions = splines[i_spline]->evaluated_positions();
+ for (const int i_point : positions.index_range()) {
+ GPU_vertbuf_attr_set(
+ vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]);
+ }
}
}
- LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- for (int i = 0; i < dl->nr; v_idx++, i++) {
- GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
+ else {
+ BLI_assert(rdata->ob_curve_cache != nullptr);
+
+ int v_idx = 0;
+ LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
+ if (bl->nr <= 0) {
+ continue;
+ }
+ const int i_end = v_idx + bl->nr;
+ for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
+ GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
}
}
+ LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ for (int i = 0; i < dl->nr; v_idx++, i++) {
+ GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
+ }
+ }
+ }
+ BLI_assert(v_idx == vert_len);
}
- BLI_assert(v_idx == vert_len);
}
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
{
- BLI_assert(rdata->ob_curve_cache != nullptr);
-
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
const int edge_len = curve_render_data_wire_edges_len_get(rdata);
const int curve_len = curve_render_data_wire_curve_len_get(rdata);
@@ -603,34 +655,56 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
- int v_idx = 0;
- LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
- if (bl->nr <= 0) {
- continue;
- }
- const bool is_cyclic = bl->poly != -1;
- if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
- }
- for (int i = 0; i < bl->nr; i++) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
+ if (rdata->curve_eval != nullptr) {
+ const CurveEval &curve_eval = *rdata->curve_eval;
+ Span<SplinePtr> splines = curve_eval.splines();
+ Array<int> offsets = curve_eval.evaluated_point_offsets();
+ BLI_assert(offsets.last() == vert_len);
+
+ for (const int i_spline : splines.index_range()) {
+ const int eval_size = splines[i_spline]->evaluated_points_size();
+ if (splines[i_spline]->is_cyclic()) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1);
+ }
+ for (const int i_point : IndexRange(eval_size)) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point);
+ }
+ GPU_indexbuf_add_primitive_restart(&elb);
}
- GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += bl->nr;
}
- LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- const bool is_cyclic = dl->type == DL_POLY;
+ else {
+ BLI_assert(rdata->ob_curve_cache != nullptr);
+
+ int v_idx = 0;
+ LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
+ if (bl->nr <= 0) {
+ continue;
+ }
+ const bool is_cyclic = bl->poly != -1;
if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
}
- for (int i = 0; i < dl->nr; i++) {
+ for (int i = 0; i < bl->nr; i++) {
GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
}
GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += dl->nr;
+ v_idx += bl->nr;
+ }
+ LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ const bool is_cyclic = dl->type == DL_POLY;
+ if (is_cyclic) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
+ }
+ for (int i = 0; i < dl->nr; i++) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
+ }
+ GPU_indexbuf_add_primitive_restart(&elb);
+ v_idx += dl->nr;
+ }
}
}
+
GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
}
@@ -769,6 +843,9 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2;
int vbo_len_used = 0;
+#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL))
+#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL))
+
if (DRW_TEST_ASSIGN_VBO(vbo_pos)) {
GPU_vertbuf_init_with_format(vbo_pos, &format_pos);
GPU_vertbuf_data_alloc(vbo_pos, verts_len_capacity);
@@ -789,6 +866,9 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity);
}
+#undef DRW_TEST_ASSIGN_VBO
+#undef DRW_TEST_ASSIGN_IBO
+
int nu_id = 0;
for (Nurb *nu = (Nurb *)rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
const BezTriple *bezt = nu->bezt;
@@ -796,7 +876,7 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
if (bezt) {
for (int a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == true) {
+ if (bezt->hide != 0) {
continue;
}
const bool handle_selected = BEZT_ISSEL_ANY(bezt);
@@ -831,7 +911,7 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
else if (bp) {
int pt_len = nu->pntsu * nu->pntsv;
for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) {
- if (bp->hide == true) {
+ if (bp->hide != 0) {
continue;
}
int u = (a % nu->pntsu);
@@ -1070,8 +1150,11 @@ void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scen
CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag);
- /* DispLists */
- ListBase *lb = &rdata->ob_curve_cache->disp;
+ /* The object's curve cache can be empty (in one case because we use #CurveEval's cache instead),
+ * If so, point to an empty DispList list to avoid the need to check for null in the following
+ * functions. */
+ ListBase empty_lb = {nullptr, nullptr};
+ ListBase *lb = rdata->ob_curve_cache == nullptr ? &empty_lb : &rdata->ob_curve_cache->disp;
/* Generate VBOs */
if (DRW_vbo_requested(cache->ordered.pos_nor)) {
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index d606f70db9e..ee16cb1a022 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -532,6 +532,8 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb,
GPUVertBufRaw uv_step = {0};
GPUVertBufRaw tan_step = {0};
+#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL))
+
if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor)) {
GPU_vertbuf_init_with_format(vbo_pos_nor,
do_hq_normals ? &format_pos_nor_hq : &format_pos_nor);
@@ -550,6 +552,8 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb,
GPU_vertbuf_attr_get_raw_data(vbo_tan, tan_id, &tan_step);
}
+#undef DRW_TEST_ASSIGN_VBO
+
BKE_displist_normals_add(lb);
LISTBASE_FOREACH (const DispList *, dl, lb) {
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index 49b5e0fecd3..bea9ba1122b 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -405,7 +405,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
if (cache->vbo == NULL) {
/* Should be discarded together. */
BLI_assert(cache->vbo == NULL && cache->ibo == NULL);
- BLI_assert(cache->stroke_batch == NULL && cache->stroke_batch == NULL);
+ BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL);
/* TODO/PERF: Could be changed to only do it if needed.
* For now it's simpler to assume we always need it
* since multiple viewport could or could not need it.
diff --git a/source/blender/draw/intern/draw_cache_impl_hair.c b/source/blender/draw/intern/draw_cache_impl_hair.c
index fd28ac00186..6424b21666d 100644
--- a/source/blender/draw/intern/draw_cache_impl_hair.c
+++ b/source/blender/draw/intern/draw_cache_impl_hair.c
@@ -243,7 +243,8 @@ static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *c
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format(&format);
+ cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(&format,
+ GPU_USAGE_DEVICE_ONLY);
/* Create a destination buffer for the transform feedback. Sized appropriately */
/* Those are points! not line segments. */
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index af54b57b162..3cc71e47f28 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -707,6 +707,26 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
}
}
+static void mesh_buffer_cache_clear(MeshBufferCache *mbufcache)
+{
+ GPUVertBuf **vbos = (GPUVertBuf **)&mbufcache->vbo;
+ GPUIndexBuf **ibos = (GPUIndexBuf **)&mbufcache->ibo;
+ for (int i = 0; i < sizeof(mbufcache->vbo) / sizeof(void *); i++) {
+ GPU_VERTBUF_DISCARD_SAFE(vbos[i]);
+ }
+ for (int i = 0; i < sizeof(mbufcache->ibo) / sizeof(void *); i++) {
+ GPU_INDEXBUF_DISCARD_SAFE(ibos[i]);
+ }
+}
+
+static void mesh_buffer_extraction_cache_clear(MeshBufferExtractionCache *extraction_cache)
+{
+ MEM_SAFE_FREE(extraction_cache->lverts);
+ MEM_SAFE_FREE(extraction_cache->ledges);
+ extraction_cache->edge_loose_len = 0;
+ extraction_cache->vert_loose_len = 0;
+}
+
static void mesh_batch_cache_clear(Mesh *me)
{
MeshBatchCache *cache = me->runtime.batch_cache;
@@ -714,16 +734,13 @@ static void mesh_batch_cache_clear(Mesh *me)
return;
}
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPUVertBuf **vbos = (GPUVertBuf **)&mbufcache->vbo;
- GPUIndexBuf **ibos = (GPUIndexBuf **)&mbufcache->ibo;
- for (int i = 0; i < sizeof(mbufcache->vbo) / sizeof(void *); i++) {
- GPU_VERTBUF_DISCARD_SAFE(vbos[i]);
- }
- for (int i = 0; i < sizeof(mbufcache->ibo) / sizeof(void *); i++) {
- GPU_INDEXBUF_DISCARD_SAFE(ibos[i]);
- }
+ mesh_buffer_cache_clear(mbufcache);
}
+ mesh_buffer_extraction_cache_clear(&cache->final_extraction_cache);
+ mesh_buffer_extraction_cache_clear(&cache->cage_extraction_cache);
+ mesh_buffer_extraction_cache_clear(&cache->uv_cage_extraction_cache);
+
for (int i = 0; i < cache->mat_len; i++) {
GPU_INDEXBUF_DISCARD_SAFE(cache->final.tris_per_mat[i]);
}
@@ -1160,25 +1177,25 @@ static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, M
* some issues (See T77867 where we needed to disable this function in order to debug what was
* happening in release builds). */
BLI_task_graph_work_and_wait(task_graph);
- for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_BATCH_LEN; i++) {
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
- for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_VBO_LEN; i++) {
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i]));
}
- for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_IBO_LEN; i++) {
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i]));
}
- for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_VBO_LEN; i++) {
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i]));
}
- for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_IBO_LEN; i++) {
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i]));
}
- for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_VBO_LEN; i++) {
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i]));
}
- for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) {
+ for (int i = 0; i < MBC_IBO_LEN; i++) {
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i]));
}
}
@@ -1542,7 +1559,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
if (do_uvcage) {
mesh_buffer_cache_create_requested(task_graph,
cache,
- cache->uv_cage,
+ &cache->uv_cage,
+ &cache->uv_cage_extraction_cache,
me,
is_editmode,
is_paint_mode,
@@ -1551,7 +1569,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
false,
true,
false,
- &cache->cd_used,
scene,
ts,
true);
@@ -1560,7 +1577,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
if (do_cage) {
mesh_buffer_cache_create_requested(task_graph,
cache,
- cache->cage,
+ &cache->cage,
+ &cache->cage_extraction_cache,
me,
is_editmode,
is_paint_mode,
@@ -1569,7 +1587,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
false,
false,
use_subsurf_fdots,
- &cache->cd_used,
scene,
ts,
true);
@@ -1577,7 +1594,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
mesh_buffer_cache_create_requested(task_graph,
cache,
- cache->final,
+ &cache->final,
+ &cache->final_extraction_cache,
me,
is_editmode,
is_paint_mode,
@@ -1586,7 +1604,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
true,
false,
use_subsurf_fdots,
- &cache->cd_used,
scene,
ts,
use_hide);
diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h
index bfc714e5d6a..6e537a3bffa 100644
--- a/source/blender/draw/intern/draw_cache_inline.h
+++ b/source/blender/draw/intern/draw_cache_inline.h
@@ -40,10 +40,6 @@
(flag |= DRW_ibo_requested(ibo) ? (value) : 0)
#endif
-/* Test and assign NULL if test fails */
-#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL))
-#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL))
-
BLI_INLINE GPUBatch *DRW_batch_request(GPUBatch **batch)
{
/* XXX TODO(fclem): We are writing to batch cache here. Need to make this thread safe. */
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index bca227a24e2..585e171adc5 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -36,15 +36,28 @@
#include "BKE_duplilist.h"
#include "GPU_batch.h"
+#include "GPU_capabilities.h"
+#include "GPU_compute.h"
#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "GPU_vertex_buffer.h"
#include "draw_hair_private.h"
#ifndef __APPLE__
# define USE_TRANSFORM_FEEDBACK
+# define USE_COMPUTE_SHADERS
#endif
+BLI_INLINE bool drw_hair_use_compute_shaders(void)
+{
+#ifdef USE_COMPUTE_SHADERS
+ return GPU_compute_shader_support();
+#else
+ return false;
+#endif
+}
+
typedef enum ParticleRefineShader {
PART_REFINE_CATMULL_ROM = 0,
PART_REFINE_MAX_SHADER,
@@ -71,38 +84,89 @@ static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in t
extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_common_hair_refine_vert_glsl[];
+extern char datatoc_common_hair_refine_comp_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
-static GPUShader *hair_refine_shader_get(ParticleRefineShader sh)
+/* TODO(jbakker): move shader creation to `draw_shaders` and add test cases. */
+/* TODO(jbakker): replace defines with `constexpr` to check compilation on all OS's.
+ * Currently the `__APPLE__` code-path does not compile on other platforms and vice versa. */
+#ifdef USE_COMPUTE_SHADERS
+static GPUShader *hair_refine_shader_compute_create(ParticleRefineShader UNUSED(refinement))
{
- if (g_refine_shaders[sh]) {
- return g_refine_shaders[sh];
- }
-
- char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl,
- datatoc_common_hair_refine_vert_glsl);
+ GPUShader *sh = NULL;
+ sh = GPU_shader_create_compute(datatoc_common_hair_refine_comp_glsl,
+ datatoc_common_hair_lib_glsl,
+ "#define HAIR_PHASE_SUBDIV\n",
+ __func__);
+ return sh;
+}
+#endif
#ifdef USE_TRANSFORM_FEEDBACK
+static GPUShader *hair_refine_shader_transform_feedback_create(
+ ParticleRefineShader UNUSED(refinement))
+{
+ GPUShader *sh = NULL;
+
+ char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
+ datatoc_common_hair_refine_vert_glsl);
const char *var_names[1] = {"finalColor"};
- g_refine_shaders[sh] = DRW_shader_create_with_transform_feedback(
- vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1);
-#else
- g_refine_shaders[sh] = DRW_shader_create(vert_with_lib,
- NULL,
- datatoc_gpu_shader_3D_smooth_color_frag_glsl,
- "#define blender_srgb_to_framebuffer_space(a) a\n"
- "#define HAIR_PHASE_SUBDIV\n"
- "#define TF_WORKAROUND\n");
+ sh = DRW_shader_create_with_transform_feedback(
+ shader_src, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1);
+ MEM_freeN(shader_src);
+
+ return sh;
+}
#endif
- MEM_freeN(vert_with_lib);
+static GPUShader *hair_refine_shader_transform_feedback_workaround_create(
+ ParticleRefineShader UNUSED(refinement))
+{
+ GPUShader *sh = NULL;
+
+ char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
+ datatoc_common_hair_refine_vert_glsl);
+ sh = DRW_shader_create(shader_src,
+ NULL,
+ datatoc_gpu_shader_3D_smooth_color_frag_glsl,
+ "#define blender_srgb_to_framebuffer_space(a) a\n"
+ "#define HAIR_PHASE_SUBDIV\n"
+ "#define TF_WORKAROUND\n");
+ MEM_freeN(shader_src);
+
+ return sh;
+}
+
+static GPUShader *hair_refine_shader_get(ParticleRefineShader refinement)
+{
+ if (g_refine_shaders[refinement]) {
+ return g_refine_shaders[refinement];
+ }
+
+#ifdef USE_COMPUTE_SHADERS
+ if (drw_hair_use_compute_shaders()) {
+ g_refine_shaders[refinement] = hair_refine_shader_compute_create(refinement);
+ if (g_refine_shaders[refinement]) {
+ return g_refine_shaders[refinement];
+ }
+ }
+#endif
+
+#ifdef USE_TRANSFORM_FEEDBACK
+ g_refine_shaders[refinement] = hair_refine_shader_transform_feedback_create(refinement);
+ if (g_refine_shaders[refinement]) {
+ return g_refine_shaders[refinement];
+ }
+#endif
- return g_refine_shaders[sh];
+ g_refine_shaders[refinement] = hair_refine_shader_transform_feedback_workaround_create(
+ refinement);
+ return g_refine_shaders[refinement];
}
void DRW_hair_init(void)
{
-#ifdef USE_TRANSFORM_FEEDBACK
+#if defined(USE_TRANSFORM_FEEDBACK) || defined(USE_COMPUTE_SHADERS)
g_tf_pass = DRW_pass_create("Update Hair Pass", 0);
#else
g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR);
@@ -125,6 +189,67 @@ void DRW_hair_init(void)
}
}
+static void drw_hair_particle_cache_shgrp_attach_resources(DRWShadingGroup *shgrp,
+ ParticleHairCache *cache,
+ const int subdiv)
+{
+ DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", cache->point_tex);
+ DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex);
+ DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
+ DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
+}
+
+static void drw_hair_particle_cache_update_compute(ParticleHairCache *cache, const int subdiv)
+{
+ const int strands_len = cache->strands_len;
+ const int final_points_len = cache->final[subdiv].strands_res * strands_len;
+ if (final_points_len > 0) {
+ GPUShader *shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass);
+ drw_hair_particle_cache_shgrp_attach_resources(shgrp, cache, subdiv);
+ DRW_shgroup_vertex_buffer(shgrp, "hairPointOutputBuffer", cache->final[subdiv].proc_buf);
+
+ const int max_strands_per_call = GPU_max_work_group_count(0);
+ int strands_start = 0;
+ while (strands_start < strands_len) {
+ int batch_strands_len = MIN2(strands_len - strands_start, max_strands_per_call);
+ DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start);
+ DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final[subdiv].strands_res, 1);
+ strands_start += batch_strands_len;
+ }
+ }
+}
+
+static void drw_hair_particle_cache_update_transform_feedback(ParticleHairCache *cache,
+ const int subdiv)
+{
+ const int final_points_len = cache->final[subdiv].strands_res * cache->strands_len;
+ if (final_points_len > 0) {
+ GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
+
+#ifdef USE_TRANSFORM_FEEDBACK
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
+ tf_shader, g_tf_pass, cache->final[subdiv].proc_buf);
+#else
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
+
+ ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
+ pr_call->next = g_tf_calls;
+ pr_call->vbo = cache->final[subdiv].proc_buf;
+ pr_call->shgrp = tf_shgrp;
+ pr_call->vert_len = final_points_len;
+ g_tf_calls = pr_call;
+ DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
+#endif
+
+ drw_hair_particle_cache_shgrp_attach_resources(tf_shgrp, cache, subdiv);
+ DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
+ }
+}
+
static ParticleHairCache *drw_hair_particle_cache_get(
Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res)
{
@@ -140,32 +265,11 @@ static ParticleHairCache *drw_hair_particle_cache_get(
}
if (update) {
- int final_points_len = cache->final[subdiv].strands_res * cache->strands_len;
- if (final_points_len > 0) {
- GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
-
-#ifdef USE_TRANSFORM_FEEDBACK
- DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
- tf_shader, g_tf_pass, cache->final[subdiv].proc_buf);
-#else
- DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
-
- ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
- pr_call->next = g_tf_calls;
- pr_call->vbo = cache->final[subdiv].proc_buf;
- pr_call->shgrp = tf_shgrp;
- pr_call->vert_len = final_points_len;
- g_tf_calls = pr_call;
- DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
- DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
- DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
-#endif
-
- DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", cache->point_tex);
- DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", cache->strand_tex);
- DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
- DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
- DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
+ if (drw_hair_use_compute_shaders()) {
+ drw_hair_particle_cache_update_compute(cache, subdiv);
+ }
+ else {
+ drw_hair_particle_cache_update_transform_feedback(cache, subdiv);
}
}
return cache;
@@ -367,9 +471,11 @@ void DRW_hair_update(void)
MEM_freeN(data);
GPU_framebuffer_free(fb);
#else
- /* TODO(fclem): replace by compute shader. */
- /* Just render using transform feedback. */
+ /* Just render the pass when using compute shaders or transform feedback. */
DRW_draw_pass(g_tf_pass);
+ if (drw_hair_use_compute_shaders()) {
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
+ }
#endif
}
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 84bc0327aa2..d4e22c83798 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -187,6 +187,10 @@ typedef enum {
DRW_CMD_DRAW_INSTANCE = 2,
DRW_CMD_DRAW_INSTANCE_RANGE = 3,
DRW_CMD_DRAW_PROCEDURAL = 4,
+
+ /* Compute Commands. */
+ DRW_CMD_COMPUTE = 8,
+
/* Other Commands */
DRW_CMD_CLEAR = 12,
DRW_CMD_DRWSTATE = 13,
@@ -224,6 +228,12 @@ typedef struct DRWCommandDrawInstanceRange {
uint inst_count;
} DRWCommandDrawInstanceRange;
+typedef struct DRWCommandCompute {
+ int groups_x_len;
+ int groups_y_len;
+ int groups_z_len;
+} DRWCommandCompute;
+
typedef struct DRWCommandDrawProcedural {
GPUBatch *batch;
DRWResourceHandle handle;
@@ -260,6 +270,7 @@ typedef union DRWCommand {
DRWCommandDrawInstance instance;
DRWCommandDrawInstanceRange instance_range;
DRWCommandDrawProcedural procedural;
+ DRWCommandCompute compute;
DRWCommandSetMutableState state;
DRWCommandSetStencil stencil;
DRWCommandSetSelectID select_id;
@@ -274,6 +285,7 @@ struct DRWCallBuffer {
};
/** Used by #DRWUniform.type */
+/* TODO(jbakker): rename to DRW_RESOURCE/DRWResourceType. */
typedef enum {
DRW_UNIFORM_INT = 0,
DRW_UNIFORM_INT_COPY,
@@ -286,6 +298,7 @@ typedef enum {
DRW_UNIFORM_BLOCK,
DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
+ DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 6bdc5305fed..3b852e7f8c8 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -47,6 +47,7 @@
#endif
#include "GPU_buffers.h"
+#include "GPU_capabilities.h"
#include "GPU_material.h"
#include "GPU_uniform_buffer.h"
@@ -446,6 +447,19 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
}
}
+void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUVertBuf *vertex_buffer)
+{
+ int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ if (location == -1) {
+ BLI_assert(false && "Unable to locate binding of shader storage buffer objects.");
+ return;
+ }
+ drw_shgroup_uniform_create_ex(
+ shgroup, location, DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE, vertex_buffer, 0, 0, 1);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -700,6 +714,17 @@ static void drw_command_draw_intance_range(
cmd->inst_count = count;
}
+static void drw_command_compute(DRWShadingGroup *shgroup,
+ int groups_x_len,
+ int groups_y_len,
+ int groups_z_len)
+{
+ DRWCommandCompute *cmd = drw_command_create(shgroup, DRW_CMD_COMPUTE);
+ cmd->groups_x_len = groups_x_len;
+ cmd->groups_y_len = groups_y_len;
+ cmd->groups_z_len = groups_z_len;
+}
+
static void drw_command_draw_procedural(DRWShadingGroup *shgroup,
GPUBatch *batch,
DRWResourceHandle handle,
@@ -815,6 +840,17 @@ void DRW_shgroup_call_instance_range(
drw_command_draw_intance_range(shgroup, geom, handle, i_sta, i_ct);
}
+void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
+ int groups_x_len,
+ int groups_y_len,
+ int groups_z_len)
+{
+ BLI_assert(groups_x_len > 0 && groups_y_len > 0 && groups_z_len > 0);
+ BLI_assert(GPU_compute_shader_support());
+
+ drw_command_compute(shgroup, groups_x_len, groups_y_len, groups_z_len);
+}
+
static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
GPUBatch *geom,
Object *ob,
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 4c8fcb0e016..f29caebeb84 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -29,6 +29,7 @@
#include "BKE_global.h"
+#include "GPU_compute.h"
#include "GPU_platform.h"
#include "GPU_shader.h"
#include "GPU_state.h"
@@ -672,6 +673,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
*use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
((GPUVertBuf *)uni->pvalue));
break;
+ case DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE:
+ GPU_vertbuf_bind_as_ssbo((GPUVertBuf *)uni->pvalue, uni->location);
+ break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
state->baseinst_loc = uni->location;
@@ -1050,6 +1054,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
cmd->instance_range.inst_count,
false);
break;
+ case DRW_CMD_COMPUTE:
+ GPU_compute_dispatch(shgroup->shader,
+ cmd->compute.groups_x_len,
+ cmd->compute.groups_y_len,
+ cmd->compute.groups_z_len);
+ break;
}
}
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 2aad1f10154..83d0030f89b 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -396,6 +396,7 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
datatoc_gpu_shader_depth_only_frag_glsl,
geom,
NULL,
+ NULL,
defines,
prim_type,
varying_names,
diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl
index 8684d82f228..02c335ddae2 100644
--- a/source/blender/draw/intern/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl
@@ -28,6 +28,9 @@ uniform bool hairCloseTip = true;
uniform vec4 hairDupliMatrix[4];
+/* Strand batch offset when used in compute shaders. */
+uniform int hairStrandOffset = 0;
+
/* -- Per control points -- */
uniform samplerBuffer hairPointBuffer; /* RGBA32F */
#define point_position xyz
@@ -43,13 +46,37 @@ uniform usamplerBuffer hairStrandSegBuffer; /* R16UI */
/* -- Subdivision stage -- */
/**
- * We use a transform feedback to preprocess the strands and add more subdivision to it.
- * For the moment these are simple smooth interpolation but one could hope to see the full
+ * We use a transform feedback or compute shader to preprocess the strands and add more subdivision
+ * to it. For the moment these are simple smooth interpolation but one could hope to see the full
* children particle modifiers being evaluated at this stage.
*
* If no more subdivision is needed, we can skip this step.
*/
+#ifdef GPU_VERTEX_SHADER
+float hair_get_local_time()
+{
+ return float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1);
+}
+
+int hair_get_id()
+{
+ return gl_VertexID / hairStrandsRes;
+}
+#endif
+
+#ifdef GPU_COMPUTE_SHADER
+float hair_get_local_time()
+{
+ return float(gl_GlobalInvocationID.y) / float(hairStrandsRes - 1);
+}
+
+int hair_get_id()
+{
+ return int(gl_GlobalInvocationID.x) + hairStrandOffset;
+}
+#endif
+
#ifdef HAIR_PHASE_SUBDIV
int hair_get_base_id(float local_time, int strand_segments, out float interp_time)
{
@@ -64,9 +91,9 @@ int hair_get_base_id(float local_time, int strand_segments, out float interp_tim
void hair_get_interp_attrs(
out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time)
{
- float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1);
+ float local_time = hair_get_local_time();
- int hair_id = gl_VertexID / hairStrandsRes;
+ int hair_id = hair_get_id();
int strand_offset = int(texelFetch(hairStrandBuffer, hair_id).x);
int strand_segments = int(texelFetch(hairStrandSegBuffer, hair_id).x);
@@ -96,6 +123,7 @@ void hair_get_interp_attrs(
*/
#if !defined(HAIR_PHASE_SUBDIV) && defined(GPU_VERTEX_SHADER)
+
int hair_get_strand_id(void)
{
return gl_VertexID / (hairStrandsRes * hairThicknessRes);
@@ -227,3 +255,45 @@ vec2 hair_resolve_barycentric(vec2 vert_barycentric)
return vec2(1.0 - vert_barycentric.x, 0.0);
}
}
+
+/* Hair interpolation functions. */
+vec4 hair_get_weights_cardinal(float t)
+{
+ float t2 = t * t;
+ float t3 = t2 * t;
+#if defined(CARDINAL)
+ float fc = 0.71;
+#else /* defined(CATMULL_ROM) */
+ float fc = 0.5;
+#endif
+
+ vec4 weights;
+ /* GLSL Optimized version of key_curve_position_weights() */
+ float fct = t * fc;
+ float fct2 = t2 * fc;
+ float fct3 = t3 * fc;
+ weights.x = (fct2 * 2.0 - fct3) - fct;
+ weights.y = (t3 * 2.0 - fct3) + (-t2 * 3.0 + fct2) + 1.0;
+ weights.z = (-t3 * 2.0 + fct3) + (t2 * 3.0 - (2.0 * fct2)) + fct;
+ weights.w = fct3 - fct2;
+ return weights;
+}
+
+/* TODO(fclem): This one is buggy, find why. (it's not the optimization!!) */
+vec4 hair_get_weights_bspline(float t)
+{
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ vec4 weights;
+ /* GLSL Optimized version of key_curve_position_weights() */
+ weights.xz = vec2(-0.16666666, -0.5) * t3 + (0.5 * t2 + 0.5 * vec2(-t, t) + 0.16666666);
+ weights.y = (0.5 * t3 - t2 + 0.66666666);
+ weights.w = (0.16666666 * t3);
+ return weights;
+}
+
+vec4 hair_interp_data(vec4 v0, vec4 v1, vec4 v2, vec4 v3, vec4 w)
+{
+ return v0 * w.x + v1 * w.y + v2 * w.z + v3 * w.w;
+}
diff --git a/source/blender/draw/intern/shaders/common_hair_refine_comp.glsl b/source/blender/draw/intern/shaders/common_hair_refine_comp.glsl
new file mode 100644
index 00000000000..4dcde4b0245
--- /dev/null
+++ b/source/blender/draw/intern/shaders/common_hair_refine_comp.glsl
@@ -0,0 +1,24 @@
+
+/*
+ * To be compiled with common_hair_lib.glsl.
+ */
+
+layout(local_size_x = 1, local_size_y = 1) in;
+layout(std430, binding = 0) writeonly buffer hairPointOutputBuffer
+{
+ vec4 posTime[];
+}
+out_vertbuf;
+
+void main(void)
+{
+ float interp_time;
+ vec4 data0, data1, data2, data3;
+ hair_get_interp_attrs(data0, data1, data2, data3, interp_time);
+
+ vec4 weights = hair_get_weights_cardinal(interp_time);
+ vec4 result = hair_interp_data(data0, data1, data2, data3, weights);
+
+ uint index = uint(hair_get_id() * hairStrandsRes) + gl_GlobalInvocationID.y;
+ out_vertbuf.posTime[index] = result;
+}
diff --git a/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl b/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
index 3f5e3f8226f..371d43827b9 100644
--- a/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
+++ b/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
@@ -3,47 +3,6 @@
out vec4 finalColor;
-vec4 get_weights_cardinal(float t)
-{
- float t2 = t * t;
- float t3 = t2 * t;
-#if defined(CARDINAL)
- float fc = 0.71;
-#else /* defined(CATMULL_ROM) */
- float fc = 0.5;
-#endif
-
- vec4 weights;
- /* GLSL Optimized version of key_curve_position_weights() */
- float fct = t * fc;
- float fct2 = t2 * fc;
- float fct3 = t3 * fc;
- weights.x = (fct2 * 2.0 - fct3) - fct;
- weights.y = (t3 * 2.0 - fct3) + (-t2 * 3.0 + fct2) + 1.0;
- weights.z = (-t3 * 2.0 + fct3) + (t2 * 3.0 - (2.0 * fct2)) + fct;
- weights.w = fct3 - fct2;
- return weights;
-}
-
-/* TODO(fclem): This one is buggy, find why. (it's not the optimization!!) */
-vec4 get_weights_bspline(float t)
-{
- float t2 = t * t;
- float t3 = t2 * t;
-
- vec4 weights;
- /* GLSL Optimized version of key_curve_position_weights() */
- weights.xz = vec2(-0.16666666, -0.5) * t3 + (0.5 * t2 + 0.5 * vec2(-t, t) + 0.16666666);
- weights.y = (0.5 * t3 - t2 + 0.66666666);
- weights.w = (0.16666666 * t3);
- return weights;
-}
-
-vec4 interp_data(vec4 v0, vec4 v1, vec4 v2, vec4 v3, vec4 w)
-{
- return v0 * w.x + v1 * w.y + v2 * w.z + v3 * w.w;
-}
-
#ifdef TF_WORKAROUND
uniform int targetWidth;
uniform int targetHeight;
@@ -56,8 +15,8 @@ void main(void)
vec4 data0, data1, data2, data3;
hair_get_interp_attrs(data0, data1, data2, data3, interp_time);
- vec4 weights = get_weights_cardinal(interp_time);
- finalColor = interp_data(data0, data1, data2, data3, weights);
+ vec4 weights = hair_get_weights_cardinal(interp_time);
+ finalColor = hair_interp_data(data0, data1, data2, data3, weights);
#ifdef TF_WORKAROUND
int id = gl_VertexID - idOffset;
diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl
index 33deae0b0a1..479f9cd1827 100644
--- a/source/blender/draw/intern/shaders/common_math_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_math_lib.glsl
@@ -86,6 +86,8 @@ float safe_rcp(float a) { return (a != 0.0) ? (1.0 / a) : 0.0; }
vec2 safe_rcp(vec2 a) { return mix(vec2(0.0), (1.0 / a), notEqual(a, vec2(0.0))); }
vec4 safe_rcp(vec4 a) { return mix(vec4(0.0), (1.0 / a), notEqual(a, vec4(0.0))); }
+float safe_sqrt(float a) { return sqrt(max(a, 0.0)); }
+
float sqr(float a) { return a * a; }
vec2 sqr(vec2 a) { return a * a; }
vec3 sqr(vec3 a) { return a * a; }