Compare commits
1 Commits
gsoc-2021-
...
temp-mesh-
Author | SHA1 | Date | |
---|---|---|---|
2e4e3adb3e |
@@ -2279,6 +2279,20 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
|
||||
)
|
||||
|
||||
|
||||
class USERPREF_PT_experimental_mesh_perf(ExperimentalPanel, Panel):
|
||||
bl_label = "Debugging"
|
||||
|
||||
def draw(self, context):
|
||||
self._draw_items(
|
||||
context, (
|
||||
({"property": "use_mesh_no_tess_calc"}, None),
|
||||
({"property": "use_mesh_no_normal_calc"}, None),
|
||||
({"property": "use_mesh_no_transform_update"}, None),
|
||||
({"property": "use_mesh_no_draw"}, None),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Class Registration
|
||||
|
||||
@@ -2375,6 +2389,7 @@ classes = (
|
||||
USERPREF_PT_experimental_new_features,
|
||||
USERPREF_PT_experimental_prototypes,
|
||||
USERPREF_PT_experimental_debugging,
|
||||
USERPREF_PT_experimental_mesh_perf,
|
||||
|
||||
# Add dynamically generated editor theme panels last,
|
||||
# so they show up last in the theme section.
|
||||
|
@@ -118,6 +118,10 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
|
||||
((looptris_tot_prev_alloc >= looptris_tot) &&
|
||||
(looptris_tot_prev_alloc <= looptris_tot * 2))) {
|
||||
looptris = em->looptris;
|
||||
|
||||
if (U.experimental.use_mesh_no_tess_calc) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (em->looptris) {
|
||||
|
@@ -499,6 +499,10 @@ static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *
|
||||
*/
|
||||
void BM_mesh_normals_update(BMesh *bm)
|
||||
{
|
||||
if (U.experimental.use_mesh_no_normal_calc) {
|
||||
return;
|
||||
}
|
||||
|
||||
float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
|
||||
|
||||
/* Parallel mempool iteration does not allow generating indices inline anymore... */
|
||||
@@ -540,6 +544,10 @@ void BM_verts_calc_normal_vcos(BMesh *bm,
|
||||
const float (*vcos)[3],
|
||||
float (*vnos)[3])
|
||||
{
|
||||
if (U.experimental.use_mesh_no_normal_calc) {
|
||||
return;
|
||||
}
|
||||
|
||||
float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
|
||||
|
||||
/* Compute normalized direction vectors for each edge.
|
||||
@@ -1355,6 +1363,10 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
|
||||
const int cd_loop_clnors_offset,
|
||||
const bool do_rebuild)
|
||||
{
|
||||
if (U.experimental.use_mesh_no_normal_calc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
|
||||
|
||||
if (use_split_normals) {
|
||||
|
@@ -1124,6 +1124,16 @@ bool deg_copy_on_write_is_expanded(const ID *id_cow)
|
||||
bool deg_copy_on_write_is_needed(const ID *id_orig)
|
||||
{
|
||||
const ID_Type id_type = GS(id_orig->name);
|
||||
|
||||
if (U.experimental.use_mesh_no_transform_update) {
|
||||
if (id_type == ID_ME) {
|
||||
Mesh *me_orig = (Mesh *)id_orig;
|
||||
if (me_orig->edit_mesh) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deg_copy_on_write_is_needed(id_type);
|
||||
}
|
||||
|
||||
|
@@ -1074,6 +1074,10 @@ static void drw_engines_cache_populate(Object *ob)
|
||||
{
|
||||
DST.ob_handle = 0;
|
||||
|
||||
if (U.experimental.use_mesh_no_draw) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* HACK: DrawData is copied by COW from the duplicated object.
|
||||
* This is valid for IDs that cannot be instantiated but this
|
||||
* is not what we want in this case so we clear the pointer
|
||||
|
@@ -36,9 +36,14 @@
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
@@ -1676,7 +1681,9 @@ void recalcData_mesh(TransInfo *t)
|
||||
}
|
||||
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
|
||||
DEG_id_tag_update(tc->obedit->data,
|
||||
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); /* sets recalc flags */
|
||||
|
||||
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
|
||||
EDBM_mesh_normals_update(em);
|
||||
BKE_editmesh_looptri_calc(em);
|
||||
|
@@ -646,7 +646,12 @@ typedef struct UserDef_Experimental {
|
||||
char use_sculpt_tools_tilt;
|
||||
char use_asset_browser;
|
||||
char use_override_templates;
|
||||
char _pad[6];
|
||||
|
||||
char use_mesh_no_tess_calc;
|
||||
char use_mesh_no_transform_update;
|
||||
char use_mesh_no_normal_calc;
|
||||
char use_mesh_no_draw;
|
||||
char _pad[2];
|
||||
/** `makesdna` does not allow empty structs. */
|
||||
} UserDef_Experimental;
|
||||
|
||||
|
@@ -6305,6 +6305,22 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_override_templates", 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Override Templates", "Enable library override template in the python API");
|
||||
|
||||
prop = RNA_def_property(srna, "use_mesh_no_tess_calc", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_mesh_no_tess_calc", 1);
|
||||
RNA_def_property_ui_text(prop, "No Mesh Tessellation Calculation", "XXX");
|
||||
|
||||
prop = RNA_def_property(srna, "use_mesh_no_transform_update", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_mesh_no_transform_update", 1);
|
||||
RNA_def_property_ui_text(prop, "No Mesh COW Update in Edit Mode", "XXX");
|
||||
|
||||
prop = RNA_def_property(srna, "use_mesh_no_normal_calc", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_mesh_no_normal_calc", 1);
|
||||
RNA_def_property_ui_text(prop, "No Mesh Normal Calculation", "XXX");
|
||||
|
||||
prop = RNA_def_property(srna, "use_mesh_no_draw", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_mesh_no_draw", 1);
|
||||
RNA_def_property_ui_text(prop, "No Mesh Drawing", "XXX");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
|
165
tests/python/transform_perf_benchmark.py
Normal file
165
tests/python/transform_perf_benchmark.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# Example usage:
|
||||
#
|
||||
# ./blender.bin --factory-startup --enable-event-simulate --python tests/python/transform_perf_benchmark.py
|
||||
#
|
||||
# Or to run on many files:
|
||||
#
|
||||
# find /d/perf_test -iname '*.blend' | sort | \
|
||||
# xargs -I {} /src/cmake_release/bin/blender --factory-startup {} --enable-event-simulate --python tests/python/transform_perf_benchmark.py
|
||||
|
||||
import bpy
|
||||
win = bpy.context.window_manager.windows[0]
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Simulate Events
|
||||
|
||||
|
||||
def run_event_simulate(event_iter):
|
||||
last_event = dict(
|
||||
x = win.width // 2,
|
||||
y = win.height // 2,
|
||||
)
|
||||
|
||||
def event_step():
|
||||
win = bpy.context.window_manager.windows[0]
|
||||
|
||||
val = next(event_step.run_events, Ellipsis)
|
||||
if val is Ellipsis:
|
||||
bpy.app.use_event_simulate = False
|
||||
print("Finished simulation")
|
||||
|
||||
import sys; sys.exit(0)
|
||||
return None
|
||||
|
||||
# Run event simulation.
|
||||
for attr in ("x", "y"):
|
||||
if attr in val:
|
||||
last_event[attr] = val
|
||||
else:
|
||||
val[attr] = last_event[attr]
|
||||
|
||||
# Fake event value, since press, release is so common.
|
||||
if val.get("value") == 'TAP':
|
||||
del val["value"]
|
||||
win.event_simulate(**val, value='PRESS')
|
||||
win = bpy.context.window_manager.windows[0]
|
||||
win.event_simulate(**val, value='RELEASE')
|
||||
else:
|
||||
win.event_simulate(**val)
|
||||
return 0.0
|
||||
|
||||
event_step.run_events = iter(event_iter)
|
||||
|
||||
bpy.app.timers.register(event_step, first_interval=0.0, persistent=True)
|
||||
|
||||
|
||||
def setup_default_preferences(preferences):
|
||||
""" Set preferences useful for automation.
|
||||
"""
|
||||
preferences.view.show_splash = False
|
||||
preferences.view.smooth_view = 0
|
||||
preferences.view.use_save_prompt = False
|
||||
preferences.view.show_developer_ui = True
|
||||
preferences.filepaths.use_auto_save_temporary_files = False
|
||||
|
||||
|
||||
def setup_experemental_preferences(preferences, attr, attr_default):
|
||||
preferences.experimental.use_mesh_no_tess_calc = attr_default
|
||||
preferences.experimental.use_mesh_no_normal_calc = attr_default
|
||||
preferences.experimental.use_mesh_no_transform_update = attr_default
|
||||
preferences.experimental.use_mesh_no_draw = attr_default
|
||||
if attr:
|
||||
setattr(preferences.experimental, attr, True)
|
||||
|
||||
|
||||
def perform_coverage_test():
|
||||
import os
|
||||
|
||||
import time
|
||||
from math import sin, cos, pi
|
||||
# Number of mouse steps.
|
||||
steps = 128
|
||||
# In pixels.
|
||||
radius = 100
|
||||
# Number of times to
|
||||
times = 1
|
||||
|
||||
x_init = win.width // 2
|
||||
y_init = win.height // 2
|
||||
y_init_ofs = y_init + radius
|
||||
|
||||
yield dict(type='MOUSEMOVE', value='NOTHING', x=x_init, y=y_init)
|
||||
|
||||
# Maximize 3D view.
|
||||
yield dict(type='SPACE', value='TAP', ctrl=True, alt=True, x=x_init, y=y_init)
|
||||
print("\n" "Times for: %s" % os.path.basename(bpy.data.filepath))
|
||||
|
||||
for attr, attr_default in (
|
||||
(None, False), # default (all on).
|
||||
(None, True), # fast (all off).
|
||||
("use_mesh_no_tess_calc", False),
|
||||
("use_mesh_no_normal_calc", False),
|
||||
("use_mesh_no_transform_update", False),
|
||||
("use_mesh_no_draw", False),
|
||||
):
|
||||
setup_experemental_preferences(bpy.context.preferences, attr, attr_default)
|
||||
|
||||
# Start grab.
|
||||
yield dict(type='G', value='TAP', x=x_init, y=y_init)
|
||||
|
||||
t = time.time()
|
||||
step_total = 0
|
||||
for _ in range(times):
|
||||
for i in range(1, steps + 1):
|
||||
phi = (i / steps) * 2.0 * pi
|
||||
x_ofs = -radius * sin(phi)
|
||||
y_ofs = +radius * cos(phi)
|
||||
step_total += 1
|
||||
yield dict(
|
||||
type='MOUSEMOVE',
|
||||
value='NOTHING',
|
||||
x=int(x_init + x_ofs),
|
||||
y=int((y_init + y_ofs) - radius),
|
||||
)
|
||||
delta = time.time() - t
|
||||
delta_step = delta / step_total
|
||||
print(
|
||||
"%s: %s" % (
|
||||
(attr or ("(default)" if attr_default is False else "(all_options_off)")).rjust(30),
|
||||
("%.6f FPS" % (1 / delta_step)).rjust(10),
|
||||
)
|
||||
)
|
||||
|
||||
# Cancel transform.
|
||||
yield dict(type='ESC', value='TAP', x=x_init, y=y_init)
|
||||
print("\n")
|
||||
|
||||
|
||||
def main():
|
||||
setup_default_preferences(bpy.context.preferences)
|
||||
|
||||
run_event_simulate(perform_coverage_test())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user