From 23eaf3117c68f0c2bc636171dddb77630f8c8659 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 23 Oct 2020 18:54:45 +0200 Subject: [PATCH 1/8] Fix Cycles unnecessary overhead cancelling finished task pool --- intern/cycles/util/util_task.cpp | 15 ++++++++++----- intern/cycles/util/util_task.h | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 4fb61392e92..50c236ac968 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -24,7 +24,7 @@ CCL_NAMESPACE_BEGIN /* Task Pool */ -TaskPool::TaskPool() : start_time(time_dt()), num_tasks_handled(0) +TaskPool::TaskPool() : start_time(time_dt()), num_tasks_pushed(0) { } @@ -36,7 +36,7 @@ TaskPool::~TaskPool() void TaskPool::push(TaskRunFunction &&task) { tbb_group.run(std::move(task)); - num_tasks_handled++; + num_tasks_pushed++; } void TaskPool::wait_work(Summary *stats) @@ -45,14 +45,19 @@ void TaskPool::wait_work(Summary *stats) if (stats != NULL) { stats->time_total = time_dt() - start_time; - stats->num_tasks_handled = num_tasks_handled; + stats->num_tasks_handled = num_tasks_pushed; } + + num_tasks_pushed = 0; } void TaskPool::cancel() { - tbb_group.cancel(); - tbb_group.wait(); + if (num_tasks_pushed > 0) { + tbb_group.cancel(); + tbb_group.wait(); + num_tasks_pushed = 0; + } } bool TaskPool::canceled() diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index d3c3c11f8e2..f2718600f30 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -71,8 +71,8 @@ class TaskPool { /* Time time stamp of first task pushed. */ double start_time; - /* Number of all tasks handled by this pool. */ - int num_tasks_handled; + /* Number of all tasks pushed to the pool. Cleared after wait_work() and cancel(). */ + int num_tasks_pushed; }; /* Task Scheduler From 8442d6ca8a01b3f20f907bd298d9460bf57aa45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:26:35 +0200 Subject: [PATCH 2/8] CLOG: Add getter to know if output supports coloring --- intern/clog/CLG_log.h | 2 ++ intern/clog/clog.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/intern/clog/CLG_log.h b/intern/clog/CLG_log.h index a2841c5c8b3..3e51e228bac 100644 --- a/intern/clog/CLG_log.h +++ b/intern/clog/CLG_log.h @@ -150,6 +150,8 @@ void CLG_level_set(int level); void CLG_logref_init(CLG_LogRef *clg_ref); +int CLG_color_support_get(CLG_LogRef *clg_ref); + /** Declare outside function, declare as extern in header. */ #define CLG_LOGREF_DECLARE_GLOBAL(var, id) \ static CLG_LogRef _static_##var = {id}; \ diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 37c8393f532..2bc3985c71f 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -755,4 +755,12 @@ void CLG_logref_init(CLG_LogRef *clg_ref) #endif } +int CLG_color_support_get(CLG_LogRef *clg_ref) +{ + if (clg_ref->type == NULL) { + CLG_logref_init(clg_ref); + } + return clg_ref->type->ctx->use_color; +} + /** \} */ From a4f883268ba7f8506cd71eba42e8b734c128519d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:29:27 +0200 Subject: [PATCH 3/8] GPU: Use CLOG to for debug output This removes the escape color control caracters when the output does not supports it (i.e: file output, windows cmd). --- source/blender/gpu/CMakeLists.txt | 1 + source/blender/gpu/intern/gpu_debug.cc | 2 +- source/blender/gpu/intern/gpu_shader.cc | 60 +++++++++++++------ .../gpu/intern/gpu_shader_interface.cc | 1 - .../blender/gpu/intern/gpu_shader_private.hh | 2 +- source/blender/gpu/opengl/gl_debug.cc | 41 +++++++++---- source/blender/gpu/opengl/gl_shader.cc | 8 +-- 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 482e4086452..92f540f859f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -44,6 +44,7 @@ set(INC ../nodes ../nodes/intern + ../../../intern/clog ../../../intern/ghost ../../../intern/glew-mx ../../../intern/guardedalloc diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc index d7944f0de50..63e7024b74b 100644 --- a/source/blender/gpu/intern/gpu_debug.cc +++ b/source/blender/gpu/intern/gpu_debug.cc @@ -74,7 +74,7 @@ void GPU_debug_get_groups_names(int name_buf_len, char *r_name_buf) for (StringRef &name : stack) { sz += BLI_snprintf_rlen(r_name_buf + sz, name_buf_len - sz, "%s > ", name.data()); } - r_name_buf[sz - 2] = ':'; + r_name_buf[sz - 3] = '\0'; } /* Return true if inside a debug group with the same name. */ diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 05c81c2efeb..5f46f57c09a 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -23,6 +23,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_dynstr.h" #include "BLI_math_base.h" #include "BLI_math_vector.h" #include "BLI_path_util.h" @@ -47,8 +48,12 @@ #include "gpu_context_private.hh" #include "gpu_shader_private.hh" +#include "CLG_log.h" + extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[]; +static CLG_LogRef LOG = {"gpu.shader"}; + using namespace blender; using namespace blender::gpu; @@ -56,12 +61,21 @@ using namespace blender::gpu; /** \name Debug functions * \{ */ -void Shader::print_errors(Span sources, char *log, const char *stage) +void Shader::print_log(Span sources, char *log, const char *stage, const bool error) { const char line_prefix[] = " | "; + char err_col[] = "\033[31;1m"; + char warn_col[] = "\033[33;1m"; + char info_col[] = "\033[0;2m"; + char reset_col[] = "\033[0;0m"; char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size()); + DynStr *dynstr = BLI_dynstr_new(); - fprintf(stderr, "GPUShader: Compilation Log : %s : %s\n", this->name, stage); + if (!CLG_color_support_get(&LOG)) { + err_col[0] = warn_col[0] = info_col[0] = reset_col[0] = '\0'; + } + + BLI_dynstr_appendf(dynstr, "\n"); char *log_line = log, *line_end; char *error_line_number_end; @@ -136,10 +150,10 @@ void Shader::print_errors(Span sources, char *log, const char *sta } /* Separate from previous block. */ if (last_error_line != error_line) { - fprintf(stderr, "\033[90m%s\033[39m\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s%s%s\n", info_col, line_prefix, reset_col); } else if (error_char != last_error_char) { - fprintf(stderr, "%s\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s\n", line_prefix); } /* Print line from the source file that is producing the error. */ if ((error_line != -1) && (error_line != last_error_line || error_char != last_error_char)) { @@ -159,24 +173,24 @@ void Shader::print_errors(Span sources, char *log, const char *sta /* Print error source. */ if (found_line_id) { if (error_line != last_error_line) { - fprintf(stderr, "%5d | ", src_line_index); + BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index); } else { - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); } - fwrite(src_line, (src_line_end + 1) - src_line, 1, stderr); + BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line); /* Print char offset. */ - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); if (error_char != -1) { for (int i = 0; i < error_char; i++) { - fprintf(stderr, " "); + BLI_dynstr_appendf(dynstr, " "); } - fprintf(stderr, "^"); + BLI_dynstr_appendf(dynstr, "^"); } - fprintf(stderr, "\n"); + BLI_dynstr_appendf(dynstr, "\n"); } } - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); /* Skip to message. Avoid redundant info. */ const char *keywords[] = {"error", "warning"}; for (int i = 0; i < ARRAY_SIZE(prefix); i++) { @@ -191,22 +205,32 @@ void Shader::print_errors(Span sources, char *log, const char *sta log_line++; } if (type == 0) { - fprintf(stderr, "\033[31;1mError\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", err_col, "Error", info_col); } else if (type == 1) { - fprintf(stderr, "\033[33;1mWarning\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", warn_col, "Warning", info_col); } /* Print the error itself. */ - fprintf(stderr, "\033[2m"); - fwrite(log_line, (line_end + 1) - log_line, 1, stderr); - fprintf(stderr, "\033[0m"); + BLI_dynstr_appendf(dynstr, info_col); + BLI_dynstr_nappend(dynstr, log_line, (line_end + 1) - log_line); + BLI_dynstr_appendf(dynstr, reset_col); /* Continue to next line. */ log_line = line_end + 1; last_error_line = error_line; last_error_char = error_char; } - fprintf(stderr, "\n"); MEM_freeN(sources_combined); + + CLG_Severity severity = error ? CLG_SEVERITY_ERROR : CLG_SEVERITY_WARN; + + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= 0)) || + (severity >= CLG_SEVERITY_WARN)) { + const char *_str = BLI_dynstr_get_cstring(dynstr); + CLG_log_str(LOG.type, severity, this->name, stage, _str); + MEM_freeN((void *)_str); + } + + BLI_dynstr_free(dynstr); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc index 4a7c7bc15a3..e5fb8025e7f 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.cc +++ b/source/blender/gpu/intern/gpu_shader_interface.cc @@ -85,7 +85,6 @@ void ShaderInterface::debug_print(void) char *name_buf = name_buffer_; const char format[] = " | %.8x : %4d : %s\n"; - printf(" \033[1mGPUShaderInterface : \033[0m\n"); if (attrs.size() > 0) { printf("\n Attributes :\n"); } diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index b7acc0f9353..eac39dccd81 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -70,7 +70,7 @@ class Shader { }; protected: - void print_errors(Span sources, char *log, const char *stage); + void print_log(Span sources, char *log, const char *stage, const bool error); }; /* Syntacting suggar. */ diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index b2b05124463..848c0c462fe 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -33,6 +33,8 @@ #include "GPU_debug.h" #include "GPU_platform.h" +#include "CLG_log.h" + #include "glew-mx.h" #include "gl_context.hh" @@ -42,6 +44,8 @@ #include +static CLG_LogRef LOG = {"gpu.debug"}; + /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 @@ -61,8 +65,6 @@ namespace blender::gpu::debug { # define APIENTRY #endif -#define VERBOSE 1 - static void APIENTRY debug_callback(GLenum UNUSED(source), GLenum type, GLuint UNUSED(id), @@ -86,36 +88,47 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + const bool use_color = CLG_color_support_get(&LOG); + if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) { - if (VERBOSE) { - fprintf(stderr, format, "\033[2m", "", message); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= CLG_SEVERITY_INFO))) { + const char *format = use_color ? "\033[2m%s\033[0m" : "%s"; + CLG_logf(LOG.type, CLG_SEVERITY_INFO, "Notification", "", format, message); } } else { char debug_groups[512] = ""; GPU_debug_get_groups_names(sizeof(debug_groups), debug_groups); + CLG_Severity clog_severity; switch (type) { case GL_DEBUG_TYPE_ERROR: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - fprintf(stderr, format, "\033[31;1mError\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_ERROR; break; case GL_DEBUG_TYPE_PORTABILITY: case GL_DEBUG_TYPE_PERFORMANCE: case GL_DEBUG_TYPE_OTHER: case GL_DEBUG_TYPE_MARKER: /* KHR has this, ARB does not */ default: - fprintf(stderr, format, "\033[33;1mWarning\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_WARN; break; } - if (VERBOSE && severity == GL_DEBUG_SEVERITY_HIGH) { - /* Focus on error message. */ - fprintf(stderr, "\033[2m"); - BLI_system_backtrace(stderr); - fprintf(stderr, "\033[0m\n"); - fflush(stderr); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= clog_severity))) { + CLG_logf(LOG.type, clog_severity, debug_groups, "", message); + if (severity == GL_DEBUG_SEVERITY_HIGH) { + /* Focus on error message. */ + if (use_color) { + fprintf(stderr, "\033[2m"); + } + BLI_system_backtrace(stderr); + if (use_color) { + fprintf(stderr, "\033[0m\n"); + } + fflush(stderr); + } } } } @@ -125,6 +138,8 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), /* This function needs to be called once per context. */ void init_gl_callbacks(void) { + CLOG_ENSURE(&LOG); + char msg[256] = ""; const char format[] = "Successfully hooked OpenGL debug callback using %s"; @@ -154,7 +169,7 @@ void init_gl_callbacks(void) msg); } else { - fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback. Use fallback debug layer.\n"); + CLOG_STR_WARN(&LOG, "Failed to hook OpenGL debug callback. Use fallback debug layer."); init_debug_layer(); } } diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 9af9bf96503..193e4ee8a70 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -134,13 +134,13 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan if (log[0] != '\0') { switch (gl_stage) { case GL_VERTEX_SHADER: - this->print_errors(sources, log, "VertShader"); + this->print_log(sources, log, "VertShader", !status); break; case GL_GEOMETRY_SHADER: - this->print_errors(sources, log, "GeomShader"); + this->print_log(sources, log, "GeomShader", !status); break; case GL_FRAGMENT_SHADER: - this->print_errors(sources, log, "FragShader"); + this->print_log(sources, log, "FragShader", !status); break; } } @@ -186,7 +186,7 @@ bool GLShader::finalize(void) char log[5000]; glGetProgramInfoLog(shader_program_, sizeof(log), NULL, log); Span sources; - this->print_errors(sources, log, "Linking"); + this->print_log(sources, log, "Linking", true); return false; } From 70cc0d7121aa70894bb98bb6ae25f8c461918350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:31:57 +0200 Subject: [PATCH 4/8] GPU: Debug: Trim shader stats from output log We don't make use of it anyway. --- source/blender/gpu/opengl/gl_debug.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 848c0c462fe..69289d7602e 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -48,6 +48,8 @@ static CLG_LogRef LOG = {"gpu.debug"}; /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 +/* Avoid unneeded shader statistics. */ +#define TRIM_SHADER_STATS_INFO 1 namespace blender::gpu::debug { @@ -81,12 +83,15 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), if (TRIM_NVIDIA_BUFFER_INFO && GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && - STREQLEN("Buffer detailed info", message, 20)) { - /** Supress buffer infos flooding the output. */ + STRPREFIX(message, "Buffer detailed info")) { + /** Suppress buffer infos flooding the output. */ return; } - const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + if (TRIM_SHADER_STATS_INFO && STRPREFIX(message, "Shader Stats")) { + /** Suppress buffer infos flooding the output. */ + return; + } const bool use_color = CLG_color_support_get(&LOG); From d65e5e8bc56858997073e960d8aea7112aaaa384 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 13:53:16 -0400 Subject: [PATCH 5/8] Fix T82019 Crash loading 2.78 splash demo. The versioning code to default to old booleans for old files was faulty because really old files had a 'solver' field (later removed, but then added back for new booleans). --- source/blender/blenloader/intern/versioning_290.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 00085cb7d59..eeb0dd336a3 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -705,14 +705,12 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Solver and Collections for Boolean. */ - if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "char", "solver")) { - for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { - LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - if (md->type == eModifierType_Boolean) { - BooleanModifierData *bmd = (BooleanModifierData *)md; - bmd->solver = eBooleanModifierSolver_Fast; - bmd->flag = eBooleanModifierFlag_Object; - } + for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Boolean) { + BooleanModifierData *bmd = (BooleanModifierData *)md; + bmd->solver = eBooleanModifierSolver_Fast; + bmd->flag = eBooleanModifierFlag_Object; } } } From 574d711008ab430228ce26eac05e9de3b0b828f2 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 14:44:28 -0400 Subject: [PATCH 6/8] Fix T81884, clamping with percent, addendum. The previous fix forgot the case where there is an intermediate edge and everything isn't in one plane. Differential Revision: https://developer.blender.org/D9336 --- source/blender/bmesh/tools/bmesh_bevel.c | 33 ++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index f54db513d0f..3a6ae9883e2 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1520,9 +1520,16 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em * in-between edge emid. Viewed from the vertex normal side, the CCW order of these edges is e1, * emid, e2. Return true if we placed meetco as compromise between where two edges met. If we did, * put the ratio of sines of angles in *r_sinratio too. + * However, if the bp->offset_type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, we just slide + * along emid by the specified amount. */ -static bool offset_on_edge_between( - EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio) +static bool offset_on_edge_between(BevelParams *bp, + EdgeHalf *e1, + EdgeHalf *e2, + EdgeHalf *emid, + BMVert *v, + float meetco[3], + float *r_sinratio) { bool retval = false; @@ -1532,6 +1539,22 @@ static bool offset_on_edge_between( float meet1[3], meet2[3]; bool ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1); bool ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2); + if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { + BMVert *v2 = BM_edge_other_vert(emid->e, v); + if (bp->offset_type == BEVEL_AMT_PERCENT) { + interp_v3_v3v3(meetco, v->co, v2->co, bp->offset / 100.0f); + } + else { + float dir[3]; + sub_v3_v3v3(dir, v2->co, v->co); + normalize_v3(dir); + madd_v3_v3v3fl(meetco, v->co, dir, bp->offset); + } + if (r_sinratio) { + *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1); + } + return true; + } if (ok1 && ok2) { mid_v3_v3v3(meetco, meet1, meet2); if (r_sinratio) { @@ -2953,7 +2976,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } else if (not_in_plane > 0) { if (bp->loop_slide && not_in_plane == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) { - if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, enip, bv->v, co, &r)) { eon = enip; } } @@ -2964,7 +2987,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) else { /* n_in_plane > 0 and n_not_in_plane == 0. */ if (bp->loop_slide && in_plane == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) { - if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, eip, bv->v, co, &r)) { eon = eip; } } @@ -7195,7 +7218,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { if (ea->is_bev && ebother != NULL && ebother->prev->is_bev) { if (bp->offset_type == BEVEL_AMT_PERCENT) { - return bp->offset > 50.0f ? 50.0f : 100.f; + return 50.0f; } /* This is only right sometimes. The exact answer is very hard to calculate. */ float blen = BM_edge_calc_length(eb->e); From 1c653a0315b04269a2e7385efad6a033ddad2420 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 17:36:38 -0400 Subject: [PATCH 7/8] Fix T81999, Boolean Exact+Self Difference fails. A cell with winding number > 1 for the second operand was incorrectly included in the output. --- source/blender/blenlib/intern/mesh_boolean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 169687cf9d1..bad0b84d10f 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -2068,7 +2068,7 @@ static bool apply_bool_op(BoolOpType bool_optype, const Array &winding) return true; } for (int i = 1; i < nw; ++i) { - if (winding[i] == 1) { + if (winding[i] >= 1) { return false; } } From 31629c1363cc8d004eacae9bd43623826af649a6 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Fri, 23 Oct 2020 02:12:34 +0200 Subject: [PATCH 8/8] Fix T81904: Cloth brush simulation failing with local area and mirror When using local area, all nodes need to build their constraints first before activating them for simulation. THis ensures that nodes get their structural constraints from the initial location of each symmetry pass. Reviewed By: sergey Maniphest Tasks: T81904 Differential Revision: https://developer.blender.org/D9303 --- .../editors/sculpt_paint/sculpt_cloth.c | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 1a1200bb6c2..67129d5da50 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -1127,14 +1127,27 @@ void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim, } } +static void sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt *sd, + Object *ob, + PBVHNode **nodes, + int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + const float radius = ss->cache->initial_radius; + const float limit = radius + (radius * brush->cloth_sim_limit); + float sim_location[3]; + cloth_brush_simulation_location_get(ss, brush, sim_location); + SCULPT_cloth_brush_ensure_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, sim_location, limit); +} + /* Main Brush Function. */ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - /* In the first brush step of each symmetry pass, build the constraints for the vertices in all - * nodes inside the simulation's limits. */ /* Brushes that use anchored strokes and restore the mesh can't rely on symmetry passes and steps * count as it is always the first step, so the simulation needs to be created when it does not * exist for this stroke. */ @@ -1151,14 +1164,26 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode SCULPT_is_cloth_deform_brush(brush)); SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); } + + if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) { + /* When using simulation a fixed local simulation area, constraints are created only using + * the initial stroke position and initial radius (per symmetry pass) instead of per node. + * This allows to skip unnecessary constraints that will never be simulated, making the + * solver faster. When the simulation starts for a node, the node gets activated and all its + * constraints are considered final. As the same node can be included inside the brush radius + * from multiple symmetry passes, the cloth brush can't activate the node for simulation yet + * as this will cause the ensure constraints function to skip the node in the next symmetry + * passes. It needs to build the constraints here and skip simulating the first step, so all + * passes can add their constraints to all affected nodes. */ + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); + } + /* The first step of a symmetry pass is never simulated as deformation modes need valid delta + * for brush tip alignement. */ return; } /* Ensure the constraints for the nodes. */ - const float radius = ss->cache->initial_radius; - const float limit = radius + (radius * brush->cloth_sim_limit); - SCULPT_cloth_brush_ensure_nodes_constraints( - sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit); + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); /* Store the initial state in the simulation. */ SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);