From 449ad3509317d1398647a7fdd820711f6af1f871 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 27 Apr 2017 00:01:23 +1000 Subject: [PATCH 1/7] Move depth select loop into its own function Useful for splitting out draw logic in 2.8x --- .../editors/space_view3d/view3d_draw.c | 71 ++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3fb2761d40e..8f2ea86f836 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2393,43 +2393,13 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) } -void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d) { - RegionView3D *rv3d = ar->regiondata; Base *base; - short zbuf = v3d->zbuf; - short flag = v3d->flag; - float glalphaclip = U.glalphaclip; - int obcenter_dia = U.obcenter_dia; + /* no need for color when drawing depth buffer */ const short dflag_depth = DRAW_CONSTCOLOR; - /* temp set drawtype to solid */ - - /* Setting these temporarily is not nice */ - v3d->flag &= ~V3D_SELECT_OUTLINE; - U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ - U.obcenter_dia = 0; - - view3d_winmatrix_set(ar, v3d, NULL); - view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); - - glClear(GL_DEPTH_BUFFER_BIT); - - glLoadMatrixf(rv3d->viewmat); - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } - /* get surface depth without bias */ - rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); - /* draw set first */ if (scene->set) { Scene *sce_iter; @@ -2503,7 +2473,44 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover glDepthMask(mask_orig); } +} + +void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +{ + RegionView3D *rv3d = ar->regiondata; + short zbuf = v3d->zbuf; + short flag = v3d->flag; + float glalphaclip = U.glalphaclip; + int obcenter_dia = U.obcenter_dia; + /* temp set drawtype to solid */ + /* Setting these temporarily is not nice */ + v3d->flag &= ~V3D_SELECT_OUTLINE; + U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ + U.obcenter_dia = 0; + + view3d_winmatrix_set(ar, v3d, NULL); + view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ + + mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + invert_m4_m4(rv3d->persinv, rv3d->persmat); + invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + + glClear(GL_DEPTH_BUFFER_BIT); + + glLoadMatrixf(rv3d->viewmat); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + /* get surface depth without bias */ + rv3d->rflag |= RV3D_ZOFFSET_DISABLED; + + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); + + view3d_draw_depth_loop(scene, ar, v3d); + if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } From 146db944e5a48b401bc5881dbf3c7f1548c355c4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 14:50:21 +0200 Subject: [PATCH 2/7] Threading: Remove thread lock which seems useless Render data is never guarded by image drawe lock. --- source/blender/editors/render/render_opengl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 1d0f433ba38..ee21594856f 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -257,10 +257,8 @@ static void screen_opengl_views_setup(OGLRender *oglrender) } } - BLI_lock_thread(LOCK_DRAW_IMAGE); if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd))) oglrender->iuser.flag &= ~IMA_SHOW_STEREO; - BLI_unlock_thread(LOCK_DRAW_IMAGE); /* will only work for non multiview correctly */ if (v3d) { From c0f555905d250643bd6a17bf292bce06d363050f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 15:06:31 +0200 Subject: [PATCH 3/7] User preferences: Use checkbox for Cycles device selection It was totally unclear whether the device is enabled or disabled. Lots of people got fully lost in the current interface. While the solution is not fully ideal, it is at least solves ambiguity in the interface. --- intern/cycles/blender/addon/properties.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index cbf469b3a89..e6d2a0b85b3 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1297,14 +1297,14 @@ class CyclesPreferences(bpy.types.AddonPreferences): row = layout.row() if self.compute_device_type == 'CUDA' and cuda_devices: - col = row.column(align=True) + box = row.box() for device in cuda_devices: - col.prop(device, "use", text=device.name, toggle=True) + box.prop(device, "use", text=device.name) if self.compute_device_type == 'OPENCL' and opencl_devices: - col = row.column(align=True) + box = row.box() for device in opencl_devices: - col.prop(device, "use", text=device.name, toggle=True) + box.prop(device, "use", text=device.name) def draw(self, context): From e2f8bb56d6783585953934b08e3a937666a72acc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 15:11:58 +0200 Subject: [PATCH 4/7] Avoid race condition copying Scene for off-thread OpenGL image save --- source/blender/editors/render/render_opengl.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ee21594856f..1b0ba382284 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -872,7 +872,7 @@ static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) typedef struct WriteTaskData { RenderResult *rr; - int cfra; + Scene tmp_scene; } WriteTaskData; static void write_result_func(TaskPool * __restrict pool, @@ -881,10 +881,10 @@ static void write_result_func(TaskPool * __restrict pool, { OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool); WriteTaskData *task_data = (WriteTaskData *) task_data_v; - Scene *scene = oglrender->scene; + Scene *scene = &task_data->tmp_scene; RenderResult *rr = task_data->rr; const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); - const int cfra = task_data->cfra; + const int cfra = scene->r.cfra; bool ok; /* Don't attempt to write if we've got an error. */ if (!oglrender->pool_ok) { @@ -906,13 +906,11 @@ static void write_result_func(TaskPool * __restrict pool, * This is because underlying calls do not use r.cfra but use scene * for that. */ - Scene tmp_scene = *scene; - tmp_scene.r.cfra = cfra; if (is_movie) { ok = RE_WriteRenderViewsMovie(&reports, rr, - &tmp_scene, - &tmp_scene.r, + scene, + &scene->r, oglrender->mh, oglrender->movie_ctx_arr, oglrender->totvideos, @@ -932,8 +930,8 @@ static void write_result_func(TaskPool * __restrict pool, true, NULL); - BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false); - ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name); + BKE_render_result_stamp_info(scene, scene->camera, rr, false); + ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name); if (!ok) { BKE_reportf(&reports, RPT_ERROR, @@ -972,7 +970,7 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr) Scene *scene = oglrender->scene; WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data"); task_data->rr = rr; - task_data->cfra = scene->r.cfra; + task_data->tmp_scene = *scene; BLI_mutex_lock(&oglrender->task_mutex); oglrender->num_scheduled_frames++; if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) { From e61ba39e7c3582c673955d51694799081532b857 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 15:23:46 +0200 Subject: [PATCH 5/7] Ensure task scheduler exists before any threading starts in Blender --- source/blender/blenlib/intern/threads.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 77da3be0600..abf611d1245 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -813,6 +813,11 @@ void BLI_begin_threaded_malloc(void) unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); if (level == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + /* There is a little chance that two threads will meed to acces to a + * scheduler which was not yet created from main thread. which could + * cause scheduler created multiple times. + */ + BLI_task_scheduler_get(); } } From e6954a5a7cd9439787c3b0bf04e8970962eb6315 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 15:40:32 +0200 Subject: [PATCH 6/7] Fix race condition invalidating object data's bounding box --- source/blender/blenkernel/intern/object.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6e754755cf3..fbca03c1e07 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -127,6 +127,7 @@ #endif #include "CCGSubSurf.h" +#include "atomic_ops.h" #include "GPU_material.h" @@ -319,19 +320,24 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr /* free data derived from mesh, called when mesh changes or is freed */ void BKE_object_free_derived_caches(Object *ob) { - /* also serves as signal to remake texspace */ + /* Also serves as signal to remake texspace. + * + * NOTE: This function can be called from threads on different objects + * sharing same data datablock. So we need to ensure atomic nature of + * data modification here. + */ if (ob->type == OB_MESH) { Mesh *me = ob->data; if (me && me->bb) { - me->bb->flag |= BOUNDBOX_DIRTY; + atomic_fetch_and_or_uint32((uint*)&me->bb->flag, BOUNDBOX_DIRTY); } } else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { Curve *cu = ob->data; if (cu && cu->bb) { - cu->bb->flag |= BOUNDBOX_DIRTY; + atomic_fetch_and_or_uint32((uint*)&cu->bb->flag, BOUNDBOX_DIRTY); } } From be60e9b8c57223d102bb8b34f1dddc8c454b0ded Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 26 Apr 2017 15:58:40 +0200 Subject: [PATCH 7/7] Cycles: Fix over-allocation of triangles storage for triangle primitive hair Was also causing some bad memory access caused by read data from non-initialized arrays. Repoted by bzztploink in IRC, thanks! --- intern/cycles/blender/blender_curves.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 6fa038e8bf0..ed361cc971e 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -411,7 +411,7 @@ static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, } } - mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size()); + mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles()); mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals(); @@ -546,7 +546,7 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, } } - mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size()); + mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles()); mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals();