Mesh Batch Cache: Optimization & Refactor shaded surface support

This now only upload data per loops to the GPU, making use of index buffer
to draw polygon. This make use of the vertex cache, speed up renders
and saves a lot of vram.

Update performance is also slightly faster and can even be improved further
by updating only uvs or vcol independently.

This commits breaks texture paint batches. It will be added back in another
commit.
This commit is contained in:
Clément Foucault 2018-12-16 15:17:31 +01:00
parent bc74e48680
commit 36cc42e796
Notes: blender-bot 2023-02-14 08:47:25 +01:00
Referenced by issue #59554, Crash drawing armature with custom bone shapes
11 changed files with 657 additions and 561 deletions

View File

@ -157,10 +157,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
}
}
const bool is_active = (ob == draw_ctx->obact);
const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
struct GPUBatch *geom = DRW_cache_object_surface_get_ex(ob, use_hide);
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
/* Depth Prepass */

View File

@ -1523,7 +1523,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
int *auto_layer_is_srgb;
int auto_layer_count;
struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, use_hide,
ob, gpumat_array, materials_len,
&auto_layer_names,
&auto_layer_is_srgb,
&auto_layer_count);

View File

@ -823,7 +823,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob, use_hide) : NULL;
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if (materials_len > 0 && geom_array) {
for (int i = 0; i < materials_len; i++) {
if (geom_array[i] == NULL) {
@ -846,7 +846,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (!is_drawn) {
if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_RANDOM_COLOR)) {
/* No material split needed */
struct GPUBatch *geom = DRW_cache_object_surface_get_ex(ob, use_hide);
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
if (is_sculpt_mode) {
@ -865,7 +865,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, use_hide, NULL, NULL, NULL);
ob, gpumat_array, materials_len, NULL, NULL, NULL);
if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
if (mat_geom[i] == NULL) {

View File

@ -497,7 +497,6 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
bool is_drawn = false;
if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
@ -505,7 +504,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob, use_hide) : NULL;
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if (materials_len > 0 && geom_array) {
for (int i = 0; i < materials_len; i++) {
if (geom_array[i] == NULL) {
@ -538,7 +537,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (!is_drawn) {
if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_RANDOM_COLOR)) {
/* No material split needed */
struct GPUBatch *geom = DRW_cache_object_surface_get_ex(ob, use_hide);
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
if (is_sculpt_mode) {
@ -563,7 +562,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, use_hide, NULL, NULL, NULL);
ob, gpumat_array, materials_len, NULL, NULL, NULL);
if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
if (mat_geom[i] == NULL) {

View File

@ -732,15 +732,10 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
}
GPUBatch *DRW_cache_object_surface_get(Object *ob)
{
return DRW_cache_object_surface_get_ex(ob, false);
}
GPUBatch *DRW_cache_object_surface_get_ex(Object *ob, bool use_hide)
{
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_get(ob, use_hide);
return DRW_cache_mesh_surface_get(ob);
case OB_CURVE:
return DRW_cache_curve_surface_get(ob);
case OB_SURF:
@ -755,7 +750,7 @@ GPUBatch *DRW_cache_object_surface_get_ex(Object *ob, bool use_hide)
}
GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
if (auto_layer_names != NULL) {
@ -766,7 +761,7 @@ GPUBatch **DRW_cache_object_surface_material_get(
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len, use_hide,
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len,
auto_layer_names, auto_layer_is_srgb, auto_layer_count);
case OB_CURVE:
return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
@ -3029,12 +3024,12 @@ GPUBatch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
return DRW_mesh_batch_cache_get_edge_detection(me, r_is_manifold);
}
GPUBatch *DRW_cache_mesh_surface_get(Object *ob, bool use_hide)
GPUBatch *DRW_cache_mesh_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_triangles_with_normals(me, use_hide);
return DRW_mesh_batch_cache_get_triangles_with_normals(me);
}
GPUBatch *DRW_cache_mesh_face_wireframe_get(Object *ob)
@ -3106,23 +3101,23 @@ GPUBatch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
/* Return list of batches */
GPUBatch **DRW_cache_mesh_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_surface_shaded(me, gpumat_array, gpumat_array_len, use_hide,
return DRW_mesh_batch_cache_get_surface_shaded(me, gpumat_array, gpumat_array_len,
auto_layer_names, auto_layer_is_srgb, auto_layer_count);
}
/* Return list of batches */
GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob, bool use_hide)
GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_surface_texpaint(me, use_hide);
return DRW_mesh_batch_cache_get_surface_texpaint(me);
}
GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
@ -3235,7 +3230,7 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob)
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
@ -3281,7 +3276,7 @@ GPUBatch **DRW_cache_curve_surface_shaded_get(
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
@ -3339,7 +3334,7 @@ GPUBatch *DRW_cache_text_surface_get(Object *ob)
return NULL;
}
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
@ -3389,7 +3384,7 @@ GPUBatch **DRW_cache_text_surface_shaded_get(
return NULL;
}
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
@ -3410,7 +3405,7 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob)
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
@ -3464,7 +3459,7 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
@ -3788,6 +3783,7 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines)
GPUBatch *DRW_batch_request(GPUBatch **batch)
{
/* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
if (*batch == NULL) {
*batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
}

View File

@ -53,10 +53,9 @@ struct GPUBatch *DRW_cache_screenspace_circle_get(void);
struct GPUBatch *DRW_cache_object_wire_outline_get(struct Object *ob);
struct GPUBatch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold);
struct GPUBatch *DRW_cache_object_surface_get(struct Object *ob);
struct GPUBatch *DRW_cache_object_surface_get_ex(struct Object *ob, bool use_hide);
struct GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob);
struct GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
struct GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob);
@ -129,7 +128,7 @@ struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_face_centers_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold);
struct GPUBatch *DRW_cache_mesh_surface_get(struct Object *ob, bool use_hide);
struct GPUBatch *DRW_cache_mesh_surface_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob, struct ToolSettings *ts, bool paint_mode);
struct GPUBatch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
@ -140,9 +139,9 @@ struct GPUBatch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool
struct GPUBatch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
struct GPUBatch **DRW_cache_mesh_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob, bool use_hide);
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob);

View File

@ -122,16 +122,16 @@ bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const st
void DRW_mesh_batch_cache_create_requested(struct Object *ob, struct Mesh *me);
struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me, bool use_hide);
struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel, bool use_hide);
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me, bool use_hide);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, const struct DRW_MeshWeightState *wstate);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset);

File diff suppressed because it is too large Load Diff

View File

@ -1917,6 +1917,8 @@ void DRW_render_object_iter(
DST.dupli_source = data_.dupli_object_current;
DST.ob_state = NULL;
callback(vedata, ob, engine, depsgraph);
drw_batch_cache_generate_requested(ob);
}
}
DEG_OBJECT_ITER_END

View File

@ -662,7 +662,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
}
if (do_occlude_wire) {
geom = DRW_cache_mesh_surface_get(ob, false);
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat);
}

View File

@ -300,9 +300,9 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if (use_surface) {
if (me->mloopuv != NULL) {
if (use_material_slots || use_face_sel) {
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob, use_face_sel) : NULL;
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if ((me->totcol == 0) || (geom_array == NULL)) {
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob, use_face_sel);
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
ok = true;
}
@ -329,7 +329,7 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
}
if (!ok) {
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob, use_face_sel);
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
}
}