From efd70ab78f0c0d9288508fd28988c969a0cbd31a Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 21 Oct 2017 16:47:25 +0200 Subject: [PATCH 1/7] Move & rename uiLayoutOperatorButs to interface_templates.c --- source/blender/editors/include/UI_interface.h | 12 +- .../editors/interface/interface_layout.c | 121 ----------------- .../editors/interface/interface_templates.c | 128 ++++++++++++++++++ .../blender/editors/space_clip/clip_toolbar.c | 2 +- .../blender/editors/space_file/file_panels.c | 2 +- .../editors/space_view3d/view3d_toolbar.c | 2 +- .../windowmanager/intern/wm_operators.c | 8 +- 7 files changed, 141 insertions(+), 134 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 890fe720991..303d689fee7 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -829,9 +829,9 @@ void UI_exit(void); #define UI_ITEM_R_NO_BG (1 << 7) #define UI_ITEM_R_IMMEDIATE (1 << 8) -/* uiLayoutOperatorButs flags */ -#define UI_LAYOUT_OP_SHOW_TITLE 1 -#define UI_LAYOUT_OP_SHOW_EMPTY 2 +/* uiTemplateOperatorPropertyButs flags */ +#define UI_TEMPLATE_OP_PROPS_SHOW_TITLE 1 +#define UI_TEMPLATE_OP_PROPS_SHOW_EMPTY 2 /* used for transp checkers */ #define UI_ALPHA_CHECKER_DARK 100 @@ -866,9 +866,6 @@ void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv); void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr); void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context); const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing -void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), - const char label_align, const short flag); struct MenuType *UI_but_menutype_get(uiBut *but); void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext); @@ -942,6 +939,9 @@ void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, struct Image *ima void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); void UI_but_func_operator_search(uiBut *but); void uiTemplateOperatorSearch(uiLayout *layout); +void uiTemplateOperatorPropertyButs(const struct bContext *C, uiLayout *layout, struct wmOperator *op, + bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cabfca14392..2dc5b91a112 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -64,8 +64,6 @@ /************************ Structs and Defines *************************/ -// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. - #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \ if (ot == NULL) { \ ui_item_disabled(layout, _opname); \ @@ -3561,125 +3559,6 @@ const char *uiLayoutIntrospect(uiLayout *layout) return str; } -#ifdef USE_OP_RESET_BUT -static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) -{ - WM_operator_properties_reset((wmOperator *)op_pt); -} -#endif - -/* this function does not initialize the layout, functions can be called on the layout before and after */ -void uiLayoutOperatorButs( - const bContext *C, uiLayout *layout, wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), - const char label_align, const short flag) -{ - if (!op->properties) { - IDPropertyTemplate val = {0}; - op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - - if (flag & UI_LAYOUT_OP_SHOW_TITLE) { - uiItemL(layout, RNA_struct_ui_name(op->type->srna), ICON_NONE); - } - - /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens - * just fails silently */ - if (!WM_operator_repeat_check(C, op)) { - UI_block_lock_set(uiLayoutGetBlock(layout), true, "Operator can't' redo"); - - /* XXX, could give some nicer feedback or not show redo panel at all? */ - uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE); - } - else { - /* useful for macros where only one of the steps can't be re-done */ - UI_block_lock_clear(uiLayoutGetBlock(layout)); - } - - /* menu */ - if (op->type->flag & OPTYPE_PRESET) { - /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */ - PointerRNA op_ptr; - uiLayout *row; - - uiLayoutGetBlock(layout)->ui_operator = op; - - row = uiLayoutRow(layout, true); - uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); - - wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); - op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); - RNA_string_set(&op_ptr, "operator", op->type->idname); - - op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); - RNA_string_set(&op_ptr, "operator", op->type->idname); - RNA_boolean_set(&op_ptr, "remove_active", true); - } - - if (op->type->ui) { - op->layout = layout; - op->type->ui((bContext *)C, op); - op->layout = NULL; - - /* UI_LAYOUT_OP_SHOW_EMPTY ignored */ - } - else { - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - int empty; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* main draw call */ - empty = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0; - - if (empty && (flag & UI_LAYOUT_OP_SHOW_EMPTY)) { - uiItemL(layout, IFACE_("No Properties"), ICON_NONE); - } - } - -#ifdef USE_OP_RESET_BUT - /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled - * but this is not so important if this button is drawn in those cases - * (which isn't all that likely anyway) - campbell */ - if (op->properties->len) { - uiBlock *block; - uiBut *but; - uiLayout *col; /* needed to avoid alignment errors with previous buttons */ - - col = uiLayoutColumn(layout, false); - block = uiLayoutGetBlock(col); - but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_FILE_REFRESH, IFACE_("Reset"), 0, 0, UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults")); - UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); - } -#endif - - /* set various special settings for buttons */ - { - uiBlock *block = uiLayoutGetBlock(layout); - const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; - uiBut *but; - - - for (but = block->buttons.first; but; but = but->next) { - /* no undo for buttons for operator redo panels */ - UI_but_flag_disable(but, UI_BUT_UNDO); - - /* only for popups, see [#36109] */ - - /* if button is operator's default property, and a text-field, enable focus for it - * - this is used for allowing operators with popups to rename stuff with fewer clicks - */ - if (is_popup) { - if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { - UI_but_focus_on_enter_event(CTX_wm_window(C), but); - } - } - } - } -} - /* this is a bit of a hack but best keep it in one place at least */ MenuType *UI_but_menutype_get(uiBut *but) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 430795d0ee1..c392464ec3e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -58,6 +58,7 @@ #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" +#include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -87,6 +88,10 @@ #include "PIL_time.h" + +// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. + + void UI_template_fix_linking(void) { } @@ -3385,6 +3390,129 @@ void uiTemplateOperatorSearch(uiLayout *layout) UI_but_func_operator_search(but); } +/************************* Operator Redo Properties Template **************************/ + +#ifdef USE_OP_RESET_BUT +static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) +{ + WM_operator_properties_reset((wmOperator *)op_pt); +} +#endif + +/** + * Draw Operator property buttons for redoing execution with different settings. + * This function does not initialize the layout, functions can be called on the layout before and after. + */ +void uiTemplateOperatorPropertyButs( + const bContext *C, uiLayout *layout, wmOperator *op, + bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag) +{ + if (!op->properties) { + IDPropertyTemplate val = {0}; + op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + + if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { + uiItemL(layout, RNA_struct_ui_name(op->type->srna), ICON_NONE); + } + + /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens + * just fails silently */ + if (!WM_operator_repeat_check(C, op)) { + UI_block_lock_set(uiLayoutGetBlock(layout), true, "Operator can't' redo"); + + /* XXX, could give some nicer feedback or not show redo panel at all? */ + uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE); + } + else { + /* useful for macros where only one of the steps can't be re-done */ + UI_block_lock_clear(uiLayoutGetBlock(layout)); + } + + /* menu */ + if (op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + uiLayoutGetBlock(layout)->ui_operator = op; + + row = uiLayoutRow(layout, true); + uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); + + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_string_set(&op_ptr, "operator", op->type->idname); + + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", true); + } + + if (op->type->ui) { + op->layout = layout; + op->type->ui((bContext *)C, op); + op->layout = NULL; + + /* UI_LAYOUT_OP_SHOW_EMPTY ignored */ + } + else { + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + int empty; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* main draw call */ + empty = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0; + + if (empty && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { + uiItemL(layout, IFACE_("No Properties"), ICON_NONE); + } + } + +#ifdef USE_OP_RESET_BUT + /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled + * but this is not so important if this button is drawn in those cases + * (which isn't all that likely anyway) - campbell */ + if (op->properties->len) { + uiBlock *block; + uiBut *but; + uiLayout *col; /* needed to avoid alignment errors with previous buttons */ + + col = uiLayoutColumn(layout, false); + block = uiLayoutGetBlock(col); + but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_FILE_REFRESH, IFACE_("Reset"), 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults")); + UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); + } +#endif + + /* set various special settings for buttons */ + { + uiBlock *block = uiLayoutGetBlock(layout); + const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + /* no undo for buttons for operator redo panels */ + UI_but_flag_disable(but, UI_BUT_UNDO); + + /* only for popups, see [#36109] */ + + /* if button is operator's default property, and a text-field, enable focus for it + * - this is used for allowing operators with popups to rename stuff with fewer clicks + */ + if (is_popup) { + if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { + UI_but_focus_on_enter_event(CTX_wm_window(C), but); + } + } + } + } +} + /************************* Running Jobs Template **************************/ #define B_STOPRENDER 1 diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index b042bbe8fea..1504ce1a7ba 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -193,7 +193,7 @@ void CLIP_OT_tools(wmOperatorType *ot) static void clip_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOperator *op) { - uiLayoutOperatorButs(C, pa->layout, op, NULL, 'V', 0); + uiTemplateOperatorPropertyButs(C, pa->layout, op, NULL, 'V', 0); } static void clip_panel_operator_redo_header(const bContext *C, Panel *pa) diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 7acf2564fb2..1839e861518 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -88,7 +88,7 @@ static void file_panel_operator(const bContext *C, Panel *pa) UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL); - uiLayoutOperatorButs(C, pa->layout, op, file_panel_check_prop, '\0', UI_LAYOUT_OP_SHOW_EMPTY); + uiTemplateOperatorPropertyButs(C, pa->layout, op, file_panel_check_prop, '\0', UI_TEMPLATE_OP_PROPS_SHOW_EMPTY); UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL); } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 62f605ab99c..1d99fcfdd3a 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -67,7 +67,7 @@ static void view3d_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOperator *op) { - uiLayoutOperatorButs(C, pa->layout, op, NULL, 'V', 0); + uiTemplateOperatorPropertyButs(C, pa->layout, op, NULL, 'V', 0); } static void view3d_panel_operator_redo_header(const bContext *C, Panel *pa) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index be952df23b1..a2bcf6db7de 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1406,13 +1406,13 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + uiTemplateOperatorPropertyButs(C, layout, op, NULL, 'H', UI_TEMPLATE_OP_PROPS_SHOW_TITLE); if (op->next) uiItemS(layout); } } else { - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + uiTemplateOperatorPropertyButs(C, layout, op, NULL, 'H', UI_TEMPLATE_OP_PROPS_SHOW_TITLE); } UI_block_bounds_set_popup(block, 4, 0, 0); @@ -1481,7 +1481,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + uiTemplateOperatorPropertyButs(C, layout, op, NULL, 'H', UI_TEMPLATE_OP_PROPS_SHOW_TITLE); /* clear so the OK button is left alone */ UI_block_func_set(block, NULL, NULL, NULL); @@ -1520,7 +1520,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); /* since ui is defined the auto-layout args are not used */ - uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0); + uiTemplateOperatorPropertyButs(C, layout, op, NULL, 'V', 0); UI_block_func_set(block, NULL, NULL, NULL); From dc9eb8234fe4c9c561a3bfb9a8e3a3cefe77d5e3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 21 Oct 2017 18:58:59 +0200 Subject: [PATCH 2/7] Cycles: combined CPU + GPU rendering support. CPU rendering will be restricted to a BVH2, which is not ideal for raytracing performance but can be shared with the GPU. Decoupled volume shading will be disabled to match GPU volume sampling. The number of CPU rendering threads is reduced to leave one core dedicated to each GPU. Viewport rendering will also only use GPU rendering still. So along with the BVH2 usage, perfect scaling should not be expected. Go to User Preferences > System to enable the CPU to render alongside the GPU. Differential Revision: https://developer.blender.org/D2873 --- intern/cycles/blender/addon/properties.py | 15 ++++++- intern/cycles/blender/blender_sync.cpp | 45 +++++++++++++++------ intern/cycles/device/device.cpp | 32 ++++++++++++--- intern/cycles/device/device.h | 6 ++- intern/cycles/device/device_cpu.cpp | 18 +++++---- intern/cycles/device/opencl/opencl_util.cpp | 15 ++++++- 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 7b16ef1d543..2e149527066 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1351,8 +1351,9 @@ class CyclesPreferences(bpy.types.AddonPreferences): cuda_devices = [] opencl_devices = [] + cpu_devices = [] for device in device_list: - if not device[1] in {'CUDA', 'OPENCL'}: + if not device[1] in {'CUDA', 'OPENCL', 'CPU'}: continue entry = None @@ -1361,18 +1362,28 @@ class CyclesPreferences(bpy.types.AddonPreferences): if dev.id == device[2] and dev.type == device[1]: entry = dev break - # Create new entry if no existing one was found if not entry: + # Create new entry if no existing one was found entry = self.devices.add() entry.id = device[2] entry.name = device[0] entry.type = device[1] + entry.use = entry.type != 'CPU' + elif entry.name != device[0]: + # Update name in case it changed + entry.name = device[0] # Sort entries into lists if entry.type == 'CUDA': cuda_devices.append(entry) elif entry.type == 'OPENCL': opencl_devices.append(entry) + else: + cpu_devices.append(entry) + + cuda_devices.extend(cpu_devices) + opencl_devices.extend(cpu_devices) + return cuda_devices, opencl_devices diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 2e3301c4209..5eddf189468 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -675,6 +675,15 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, /* feature set */ params.experimental = (get_enum(cscene, "feature_set") != 0); + /* threads */ + if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_scene.render().threads(); + else + params.threads = 0; + + /* Background */ + params.background = background; + /* device type */ vector& devices = Device::available_devices(); @@ -703,12 +712,28 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, } } - int compute_device = get_enum(b_preferences, "compute_device_type"); + enum ComputeDevice { + COMPUTE_DEVICE_CPU = 0, + COMPUTE_DEVICE_CUDA = 1, + COMPUTE_DEVICE_OPENCL = 2, + COMPUTE_DEVICE_NUM = 3, + }; - if(compute_device != 0) { + ComputeDevice compute_device = (ComputeDevice)get_enum(b_preferences, + "compute_device_type", + COMPUTE_DEVICE_NUM, + COMPUTE_DEVICE_CPU); + + if(compute_device != COMPUTE_DEVICE_CPU) { vector used_devices; RNA_BEGIN(&b_preferences, device, "devices") { - if(get_enum(device, "type") == compute_device && get_boolean(device, "use")) { + ComputeDevice device_type = (ComputeDevice)get_enum(device, + "type", + COMPUTE_DEVICE_NUM, + COMPUTE_DEVICE_CPU); + + if(get_boolean(device, "use") && + (device_type == compute_device || device_type == COMPUTE_DEVICE_CPU)) { string id = get_string(device, "id"); foreach(DeviceInfo& info, devices) { if(info.id == id) { @@ -723,15 +748,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.device = used_devices[0]; } else if(used_devices.size() > 1) { - params.device = Device::get_multi_device(used_devices); + params.device = Device::get_multi_device(used_devices, + params.threads, + params.background); } /* Else keep using the CPU device that was set before. */ } } - /* Background */ - params.background = background; - /* samples */ int samples = get_int(cscene, "samples"); int aa_samples = get_int(cscene, "aa_samples"); @@ -791,15 +815,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.tile_order = TILE_BOTTOM_TO_TOP; } + /* other parameters */ params.start_resolution = get_int(cscene, "preview_start_resolution"); params.pixel_size = b_engine.get_preview_pixel_size(b_scene); - /* other parameters */ - if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) - params.threads = b_scene.render().threads(); - else - params.threads = 0; - params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout"); params.text_timeout = (double)get_float(cscene, "debug_text_timeout"); diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 7b0875965f8..f31cacd8ec1 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -23,9 +23,11 @@ #include "util/util_debug.h" #include "util/util_foreach.h" #include "util/util_half.h" +#include "util/util_logging.h" #include "util/util_math.h" #include "util/util_opengl.h" #include "util/util_time.h" +#include "util/util_system.h" #include "util/util_types.h" #include "util/util_vector.h" #include "util/util_string.h" @@ -365,7 +367,7 @@ string Device::device_capabilities() return capabilities; } -DeviceInfo Device::get_multi_device(vector subdevices) +DeviceInfo Device::get_multi_device(const vector& subdevices, int threads, bool background) { assert(subdevices.size() > 1); @@ -373,18 +375,38 @@ DeviceInfo Device::get_multi_device(vector subdevices) info.type = DEVICE_MULTI; info.id = "MULTI"; info.description = "Multi Device"; - info.multi_devices = subdevices; info.num = 0; info.has_bindless_textures = true; info.has_volume_decoupled = true; info.has_qbvh = true; - foreach(DeviceInfo &device, subdevices) { - assert(device.type == info.multi_devices[0].type); - + foreach(const DeviceInfo &device, subdevices) { info.has_bindless_textures &= device.has_bindless_textures; info.has_volume_decoupled &= device.has_volume_decoupled; info.has_qbvh &= device.has_qbvh; + + if(device.type == DEVICE_CPU && subdevices.size() > 1) { + if(background) { + int orig_cpu_threads = (threads)? threads: system_cpu_thread_count(); + int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0); + + if(cpu_threads >= 1) { + DeviceInfo cpu_device = device; + cpu_device.cpu_threads = cpu_threads; + info.multi_devices.push_back(cpu_device); + } + + VLOG(1) << "CPU render threads reduced from " + << orig_cpu_threads << " to " << cpu_threads + << ", to dedicate to GPU."; + } + else { + VLOG(1) << "CPU render threads disabled for interactive render."; + } + } + else { + info.multi_devices.push_back(device); + } } return info; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 5cd9cf46769..f400eeb3e6b 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -58,6 +58,7 @@ public: bool has_volume_decoupled; bool has_qbvh; bool use_split_kernel; /* Denotes if the device is going to run cycles using split-kernel */ + int cpu_threads; vector multi_devices; DeviceInfo() @@ -65,6 +66,7 @@ public: type = DEVICE_CPU; id = "CPU"; num = 0; + cpu_threads = 0; display_device = false; advanced_shading = true; has_bindless_textures = false; @@ -345,7 +347,9 @@ public: static vector& available_types(); static vector& available_devices(); static string device_capabilities(); - static DeviceInfo get_multi_device(vector subdevices); + static DeviceInfo get_multi_device(const vector& subdevices, + int threads, + bool background); /* Tag devices lists for update. */ static void tag_update(); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index a17caabc850..af1bbc0db18 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -207,8 +207,8 @@ public: KERNEL_NAME_EVAL(cpu_avx, name), \ KERNEL_NAME_EVAL(cpu_avx2, name) - CPUDevice(DeviceInfo& info, Stats &stats, bool background) - : Device(info, stats, background), + CPUDevice(DeviceInfo& info_, Stats &stats_, bool background_) + : Device(info_, stats_, background_), #define REGISTER_KERNEL(name) name ## _kernel(KERNEL_FUNCTIONS(name)) REGISTER_KERNEL(path_trace), REGISTER_KERNEL(convert_to_half_float), @@ -229,6 +229,9 @@ public: REGISTER_KERNEL(data_init) #undef REGISTER_KERNEL { + if(info.cpu_threads == 0) { + info.cpu_threads = TaskScheduler::num_threads(); + } #ifdef WITH_OSL kernel_globals.osl = &osl_globals; @@ -237,7 +240,6 @@ public: if(use_split_kernel) { VLOG(1) << "Will be using split kernel."; } - need_texture_info = false; #define REGISTER_SPLIT_KERNEL(name) split_kernels[#name] = KernelFunctions(KERNEL_FUNCTIONS(name)) @@ -271,7 +273,7 @@ public: virtual bool show_samples() const { - return (TaskScheduler::num_threads() == 1); + return (info.cpu_threads == 1); } void load_texture_info() @@ -826,9 +828,9 @@ public: int get_split_task_count(DeviceTask& task) { if(task.type == DeviceTask::SHADER) - return task.get_subtask_count(TaskScheduler::num_threads(), 256); + return task.get_subtask_count(info.cpu_threads, 256); else - return task.get_subtask_count(TaskScheduler::num_threads()); + return task.get_subtask_count(info.cpu_threads); } void task_add(DeviceTask& task) @@ -840,9 +842,9 @@ public: list tasks; if(task.type == DeviceTask::SHADER) - task.split(tasks, TaskScheduler::num_threads(), 256); + task.split(tasks, info.cpu_threads, 256); else - task.split(tasks, TaskScheduler::num_threads()); + task.split(tasks, info.cpu_threads); foreach(DeviceTask& task, tasks) task_pool.push(new CPUDeviceTask(this, task)); diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp index 7d5173a5f1d..459d512172f 100644 --- a/intern/cycles/device/opencl/opencl_util.cpp +++ b/intern/cycles/device/opencl/opencl_util.cpp @@ -1080,6 +1080,7 @@ cl_device_type OpenCLInfo::get_device_type(cl_device_id device_id) string OpenCLInfo::get_readable_device_name(cl_device_id device_id) { + string name = ""; char board_name[1024]; size_t length = 0; if(clGetDeviceInfo(device_id, @@ -1089,11 +1090,21 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id) &length) == CL_SUCCESS) { if(length != 0 && board_name[0] != '\0') { - return board_name; + name = board_name; } } + /* Fallback to standard device name API. */ - return get_device_name(device_id); + if(name.empty()) { + name = get_device_name(device_id); + } + + /* Distinguish from our native CPU device. */ + if(get_device_type(device_id) & CL_DEVICE_TYPE_CPU) { + name += " (OpenCL)"; + } + + return name; } bool OpenCLInfo::get_driver_version(cl_device_id device_id, From 6199a606a6fad1722d1f4b2152e895d655db4757 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 10 Oct 2017 02:28:23 +0200 Subject: [PATCH 3/7] Cycles: disable progressive refine if denoising or save buffers is used. Progressive refine undoes memory saving from save buffers, so enabling both does not make much sense. Previously enabling progressive refine would disable denoising, but it should be the other way around since denoise actually affects the render result. Includes some code refactor for progressive refine render buffers, and avoids recomputing tiles for each progressive sample. --- intern/cycles/blender/addon/ui.py | 10 ++- intern/cycles/blender/blender_session.cpp | 14 ++-- intern/cycles/blender/blender_sync.cpp | 23 ++++-- intern/cycles/render/session.cpp | 95 +++++++---------------- intern/cycles/render/session.h | 2 - intern/cycles/render/tile.cpp | 31 ++++++-- intern/cycles/render/tile.h | 3 +- 7 files changed, 85 insertions(+), 93 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 7d19bccae4e..67f1029acb9 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -405,7 +405,12 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel): sub.prop(rd, "tile_x", text="X") sub.prop(rd, "tile_y", text="Y") - sub.prop(cscene, "use_progressive_refine") + subsub = sub.column() + subsub.active = not rd.use_save_buffers + for rl in rd.layers: + if rl.cycles.use_denoising: + subsub.active = False + subsub.prop(cscene, "use_progressive_refine") col = split.column() @@ -595,7 +600,6 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): cscene = context.scene.cycles layout = self.layout - layout.active = not cscene.use_progressive_refine layout.prop(crl, "use_denoising", text="") def draw(self, context): @@ -607,7 +611,7 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): rl = rd.layers.active crl = rl.cycles - layout.active = crl.use_denoising and not cscene.use_progressive_refine + layout.active = crl.use_denoising split = layout.split() diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 9e54b7de573..f1226388a62 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -305,11 +305,10 @@ static void end_render_result(BL::RenderEngine& b_engine, void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight) { - BufferParams& params = rtile.buffers->params; - int x = params.full_x - session->tile_manager.params.full_x; - int y = params.full_y - session->tile_manager.params.full_y; - int w = params.width; - int h = params.height; + int x = rtile.x - session->tile_manager.params.full_x; + int y = rtile.y - session->tile_manager.params.full_y; + int w = rtile.w; + int h = rtile.h; /* get render result */ BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str()); @@ -401,7 +400,7 @@ void BlenderSession::render() buffer_params.passes = passes; PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles"); - bool use_denoising = !session_params.progressive_refine && get_boolean(crl, "use_denoising"); + bool use_denoising = get_boolean(crl, "use_denoising"); buffer_params.denoising_data_pass = use_denoising; session->tile_manager.schedule_denoising = use_denoising; session->params.use_denoising = use_denoising; @@ -659,10 +658,9 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr, if(!buffers->copy_from_device()) return; - BufferParams& params = buffers->params; float exposure = scene->film->exposure; - vector pixels(params.width*params.height*4); + vector pixels(rtile.w*rtile.h*4); /* Adjust absolute sample number to the range. */ int sample = rtile.sample; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 5eddf189468..b070bf89d44 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -573,8 +573,7 @@ array BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles"); if(get_boolean(crp, "denoising_store_passes") && - get_boolean(crp, "use_denoising") && - !session_params.progressive_refine) { + get_boolean(crp, "use_denoising")) { b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str()); b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str()); b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str()); @@ -676,8 +675,9 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.experimental = (get_enum(cscene, "feature_set") != 0); /* threads */ - if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) - params.threads = b_scene.render().threads(); + BL::RenderSettings b_r = b_scene.render(); + if(b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_r.threads(); else params.threads = 0; @@ -819,11 +819,24 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.start_resolution = get_int(cscene, "preview_start_resolution"); params.pixel_size = b_engine.get_preview_pixel_size(b_scene); + /* other parameters */ params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout"); params.text_timeout = (double)get_float(cscene, "debug_text_timeout"); - params.progressive_refine = get_boolean(cscene, "use_progressive_refine"); + /* progressive refine */ + params.progressive_refine = get_boolean(cscene, "use_progressive_refine") && + !b_r.use_save_buffers(); + + if(params.progressive_refine) { + BL::RenderSettings::layers_iterator b_rlay; + for(b_r.layers.begin(b_rlay); b_rlay != b_r.layers.end(); ++b_rlay) { + PointerRNA crl = RNA_pointer_get(&b_rlay->ptr, "cycles"); + if(get_boolean(crl, "use_denoising")) { + params.progressive_refine = false; + } + } + } if(background) { if(params.progressive_refine) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index f1ff6b49b71..d9264309273 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -114,9 +114,7 @@ Session::~Session() } /* clean up */ - foreach(RenderTile &rtile, render_tiles) - delete rtile.buffers; - tile_manager.free_device(); + tile_manager.device_free(); delete buffers; delete display; @@ -380,19 +378,17 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) /* in case of a permanent buffer, return it, otherwise we will allocate * a new temporary buffer */ - if(!(params.background && params.output_path.empty())) { + if(buffers) { tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = buffers->buffer.device_pointer; rtile.buffers = buffers; - tile->buffers = buffers; device->map_tile(tile_device, rtile); return true; } - bool store_rtile = false; if(tile->buffers == NULL) { /* fill buffer parameters */ BufferParams buffer_params = tile_manager.params; @@ -402,52 +398,15 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) buffer_params.height = rtile.h; /* allocate buffers */ - if(params.progressive_refine) { - tile_lock.lock(); - - if(render_tiles.size() == 0) { - RenderTile nulltile; - nulltile.buffers = NULL; - render_tiles.resize(tile_manager.state.num_tiles, nulltile); - } - - /* In certain circumstances number of tiles in the tile manager could - * be changed. This is not supported by the progressive refine feature. - */ - assert(render_tiles.size() == tile_manager.state.num_tiles); - - RenderTile &stored_rtile = render_tiles[tile->index]; - if(stored_rtile.buffers == NULL) { - tile->buffers = new RenderBuffers(tile_device); - tile->buffers->reset(tile_device, buffer_params); - store_rtile = true; - } - else { - assert(rtile.x == stored_rtile.x && - rtile.y == stored_rtile.y && - rtile.w == stored_rtile.w && - rtile.h == stored_rtile.h); - tile_lock.unlock(); - tile->buffers = stored_rtile.buffers; - } - } - else { - tile->buffers = new RenderBuffers(tile_device); - - tile->buffers->reset(tile_device, buffer_params); - } + tile->buffers = new RenderBuffers(tile_device); + tile->buffers->reset(tile_device, buffer_params); } tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = tile->buffers->buffer.device_pointer; rtile.buffers = tile->buffers; - rtile.sample = 0; - - if(store_rtile) { - render_tiles[tile->index] = rtile; - tile_lock.unlock(); - } + rtile.sample = tile_manager.state.sample; /* this will tag tile as IN PROGRESS in blender-side render pipeline, * which is needed to highlight currently rendering tile before first @@ -484,10 +443,11 @@ void Session::release_tile(RenderTile& rtile) if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) { if(write_render_tile_cb && params.progressive_refine == false) { write_render_tile_cb(rtile); - if(delete_tile) { - delete rtile.buffers; - tile_manager.state.tiles[rtile.tile_index].buffers = NULL; - } + } + + if(delete_tile) { + delete rtile.buffers; + tile_manager.state.tiles[rtile.tile_index].buffers = NULL; } } else { @@ -794,10 +754,10 @@ bool Session::draw(BufferParams& buffer_params, DeviceDrawParams &draw_params) void Session::reset_(BufferParams& buffer_params, int samples) { - if(buffers) { - if(buffer_params.modified(buffers->params)) { - gpu_draw_ready = false; - buffers->reset(device, buffer_params); + if(buffers && buffer_params.modified(tile_manager.params)) { + gpu_draw_ready = false; + buffers->reset(device, buffer_params); + if(display) { display->reset(device, buffer_params); } } @@ -819,15 +779,6 @@ void Session::reset(BufferParams& buffer_params, int samples) reset_gpu(buffer_params, samples); else reset_cpu(buffer_params, samples); - - if(params.progressive_refine) { - thread_scoped_lock buffers_lock(buffers_mutex); - - foreach(RenderTile &rtile, render_tiles) - delete rtile.buffers; - - render_tiles.clear(); - } } void Session::set_samples(int samples) @@ -1045,8 +996,18 @@ bool Session::update_progressive_refine(bool cancel) } if(params.progressive_refine) { - foreach(RenderTile &rtile, render_tiles) { + foreach(Tile& tile, tile_manager.state.tiles) { + if(!tile.buffers) { + continue; + } + + RenderTile rtile; + rtile.x = tile_manager.state.buffer.full_x + tile.x; + rtile.y = tile_manager.state.buffer.full_y + tile.y; + rtile.w = tile.w; + rtile.h = tile.h; rtile.sample = sample; + rtile.buffers = tile.buffers; if(write) { if(write_render_tile_cb) @@ -1068,11 +1029,7 @@ void Session::device_free() { scene->device_free(); - foreach(RenderTile &tile, render_tiles) - delete tile.buffers; - tile_manager.free_device(); - - render_tiles.clear(); + tile_manager.device_free(); /* used from background render only, so no need to * re-create render/display buffers here diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 980eda0876d..8495d95666b 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -221,8 +221,6 @@ protected: double last_update_time; bool update_progressive_refine(bool cancel); - vector render_tiles; - DeviceRequestedFeatures get_requested_device_features(); /* ** Split kernel routines ** */ diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index a9620f79fa0..2f08288be0d 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -17,6 +17,7 @@ #include "render/tile.h" #include "util/util_algorithm.h" +#include "util/util_foreach.h" #include "util/util_types.h" CCL_NAMESPACE_BEGIN @@ -113,14 +114,16 @@ TileManager::~TileManager() { } -void TileManager::free_device() +void TileManager::device_free() { - if(schedule_denoising) { + if(schedule_denoising || progressive) { for(int i = 0; i < state.tiles.size(); i++) { delete state.tiles[i].buffers; state.tiles[i].buffers = NULL; } } + + state.tiles.clear(); } static int get_divider(int w, int h, int start_resolution) @@ -150,7 +153,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.resolution_divider = get_divider(params.width, params.height, start_resolution); state.render_tiles.clear(); state.denoising_tiles.clear(); - state.tiles.clear(); + device_free(); } void TileManager::set_samples(int num_samples_) @@ -196,7 +199,7 @@ int TileManager::gen_tiles(bool sliced) int slice_num = sliced? num: 1; int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x); - state.tiles.clear(); + device_free(); state.render_tiles.clear(); state.denoising_tiles.clear(); state.render_tiles.resize(num); @@ -345,6 +348,14 @@ int TileManager::gen_tiles(bool sliced) return idx; } +void TileManager::gen_render_tiles() +{ + /* Regenerate just the render tiles for progressive render. */ + foreach(Tile& tile, state.tiles) { + state.render_tiles[tile.device].push_back(tile.index); + } +} + void TileManager::set_tiles() { int resolution = state.resolution_divider; @@ -401,6 +412,10 @@ bool TileManager::finish_tile(int index, bool &delete_tile) { delete_tile = false; + if(progressive) { + return true; + } + switch(state.tiles[index].state) { case Tile::RENDER: { @@ -501,7 +516,13 @@ bool TileManager::next() state.num_samples = range_num_samples; state.resolution_divider = pixel_size; - set_tiles(); + + if(state.sample == 0) { + set_tiles(); + } + else { + gen_render_tiles(); + } } return true; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 4cd57b7b30c..2692c7cf9f0 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -91,7 +91,7 @@ public: bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1, int pixel_size = 1); ~TileManager(); - void free_device(); + void device_free(); void reset(BufferParams& params, int num_samples); void set_samples(int num_samples); bool next(); @@ -146,6 +146,7 @@ protected: /* Generate tile list, return number of tiles. */ int gen_tiles(bool sliced); + void gen_render_tiles(); int get_neighbor_index(int index, int neighbor); bool check_neighbor_state(int index, Tile::State state); From 0836795a0d6967f1c0dc3a5ae84d3e9d30814b0e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 21 Oct 2017 20:57:31 +0200 Subject: [PATCH 4/7] Fix issue with resumable rendering in recent changes. --- intern/cycles/render/session.cpp | 2 +- intern/cycles/render/tile.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index d9264309273..4642dcfa9a1 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -922,7 +922,7 @@ void Session::update_status_time(bool show_pause, bool show_done) void Session::render() { /* Clear buffers. */ - if(buffers && tile_manager.state.sample == 0) { + if(buffers && tile_manager.state.sample == tile_manager.range_start_sample) { buffers->zero(device); } diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 2f08288be0d..a388f5dfc8b 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -517,7 +517,7 @@ bool TileManager::next() state.resolution_divider = pixel_size; - if(state.sample == 0) { + if(state.sample == range_start_sample) { set_tiles(); } else { From 92ec4863c22f249a21a5b5224d91fcab5c602100 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 20 Oct 2017 04:20:37 +0200 Subject: [PATCH 5/7] Code refactor: simplify image device memory allocation. --- intern/cycles/render/image.cpp | 276 +++++++-------------------------- intern/cycles/render/image.h | 12 +- intern/cycles/render/mesh.cpp | 5 +- intern/cycles/render/mesh.h | 1 - intern/cycles/render/scene.cpp | 6 +- intern/cycles/render/scene.h | 8 - 6 files changed, 67 insertions(+), 241 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index bb94b9bb82a..c9fbd237010 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -364,6 +364,7 @@ int ImageManager::add_image(const string& filename, img->extension = extension; img->users = 1; img->use_alpha = use_alpha; + img->mem = NULL; images[type][slot] = img; @@ -696,7 +697,6 @@ bool ImageManager::file_load_image(Image *img, } void ImageManager::device_load_image(Device *device, - DeviceScene *dscene, Scene *scene, ImageDataType type, int slot, @@ -717,26 +717,27 @@ void ImageManager::device_load_image(Device *device, /* Slot assignment */ int flat_slot = type_index_to_flattened_slot(slot, type); - string name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot); - if(type == IMAGE_DATA_TYPE_FLOAT4) { - if(dscene->tex_float4_image[slot] == NULL) - dscene->tex_float4_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_float4_image[slot]; + /* Free previous texture in slot. */ + if(img->mem) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(*img->mem); + delete img->mem; + img->mem = NULL; + } - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + /* Create new texture. */ + if(type == IMAGE_DATA_TYPE_FLOAT4) { + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - float *pixels = (float*)tex_img.resize(1, 1); + float *pixels = (float*)tex_img->resize(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; pixels[1] = TEX_IMAGE_MISSING_G; @@ -744,60 +745,34 @@ void ImageManager::device_load_image(Device *device, pixels[3] = TEX_IMAGE_MISSING_A; } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } else if(type == IMAGE_DATA_TYPE_FLOAT) { - if(dscene->tex_float_image[slot] == NULL) - dscene->tex_float_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_float_image[slot]; - - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - float *pixels = (float*)tex_img.resize(1, 1); + float *pixels = (float*)tex_img->resize(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } else if(type == IMAGE_DATA_TYPE_BYTE4) { - if(dscene->tex_byte4_image[slot] == NULL) - dscene->tex_byte4_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_byte4_image[slot]; - - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - uchar *pixels = (uchar*)tex_img.resize(1, 1); + uchar *pixels = (uchar*)tex_img->resize(1, 1); pixels[0] = (TEX_IMAGE_MISSING_R * 255); pixels[1] = (TEX_IMAGE_MISSING_G * 255); @@ -805,58 +780,32 @@ void ImageManager::device_load_image(Device *device, pixels[3] = (TEX_IMAGE_MISSING_A * 255); } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } - else if(type == IMAGE_DATA_TYPE_BYTE){ - if(dscene->tex_byte_image[slot] == NULL) - dscene->tex_byte_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_byte_image[slot]; - - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + else if(type == IMAGE_DATA_TYPE_BYTE) { + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) { + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - uchar *pixels = (uchar*)tex_img.resize(1, 1); + uchar *pixels = (uchar*)tex_img->resize(1, 1); pixels[0] = (TEX_IMAGE_MISSING_R * 255); } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } - else if(type == IMAGE_DATA_TYPE_HALF4){ - if(dscene->tex_half4_image[slot] == NULL) - dscene->tex_half4_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_half4_image[slot]; - - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + else if(type == IMAGE_DATA_TYPE_HALF4) { + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) { + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - half *pixels = (half*)tex_img.resize(1, 1); + half *pixels = (half*)tex_img->resize(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; pixels[1] = TEX_IMAGE_MISSING_G; @@ -864,47 +813,38 @@ void ImageManager::device_load_image(Device *device, pixels[3] = TEX_IMAGE_MISSING_A; } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } - else if(type == IMAGE_DATA_TYPE_HALF){ - if(dscene->tex_half_image[slot] == NULL) - dscene->tex_half_image[slot] = new device_vector(); - device_vector& tex_img = *dscene->tex_half_image[slot]; - - if(tex_img.device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(tex_img); - } + else if(type == IMAGE_DATA_TYPE_HALF) { + device_vector *tex_img = new device_vector(); if(!file_load_image(img, type, texture_limit, - tex_img)) { + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ - half *pixels = (half*)tex_img.resize(1, 1); + half *pixels = (half*)tex_img->resize(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; } - { - thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), - tex_img, - img->interpolation, - img->extension); - } + img->mem = tex_img; } + /* Copy to device. */ + if(img->mem) { + thread_scoped_lock device_lock(device_mutex); + device->tex_alloc(name.c_str(), + *img->mem, + img->interpolation, + img->extension); + } + + img->need_load = false; } -void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot) +void ImageManager::device_free_image(Device *device, ImageDataType type, int slot) { Image *img = images[type][slot]; @@ -915,105 +855,20 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename); #endif } - else { - device_memory *tex_img = NULL; - switch(type) { - case IMAGE_DATA_TYPE_FLOAT4: - if(slot >= dscene->tex_float4_image.size()) { - break; - } - tex_img = dscene->tex_float4_image[slot]; - dscene->tex_float4_image[slot] = NULL; - break; - case IMAGE_DATA_TYPE_BYTE4: - if(slot >= dscene->tex_byte4_image.size()) { - break; - } - tex_img = dscene->tex_byte4_image[slot]; - dscene->tex_byte4_image[slot]= NULL; - break; - case IMAGE_DATA_TYPE_HALF4: - if(slot >= dscene->tex_half4_image.size()) { - break; - } - tex_img = dscene->tex_half4_image[slot]; - dscene->tex_half4_image[slot]= NULL; - break; - case IMAGE_DATA_TYPE_FLOAT: - if(slot >= dscene->tex_float_image.size()) { - break; - } - tex_img = dscene->tex_float_image[slot]; - dscene->tex_float_image[slot] = NULL; - break; - case IMAGE_DATA_TYPE_BYTE: - if(slot >= dscene->tex_byte_image.size()) { - break; - } - tex_img = dscene->tex_byte_image[slot]; - dscene->tex_byte_image[slot]= NULL; - break; - case IMAGE_DATA_TYPE_HALF: - if(slot >= dscene->tex_half_image.size()) { - break; - } - tex_img = dscene->tex_half_image[slot]; - dscene->tex_half_image[slot]= NULL; - break; - default: - assert(0); - tex_img = NULL; - } - if(tex_img) { - if(tex_img->device_pointer) { - thread_scoped_lock device_lock(device_mutex); - device->tex_free(*tex_img); - } - delete tex_img; - } + if(img->mem) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(*img->mem); + delete img->mem; } - delete images[type][slot]; + delete img; images[type][slot] = NULL; --tex_num_images[type]; } } -void ImageManager::device_prepare_update(DeviceScene *dscene) -{ - for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { - switch(type) { - case IMAGE_DATA_TYPE_FLOAT4: - if(dscene->tex_float4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_FLOAT4]) - dscene->tex_float4_image.resize(tex_num_images[IMAGE_DATA_TYPE_FLOAT4]); - break; - case IMAGE_DATA_TYPE_BYTE4: - if(dscene->tex_byte4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_BYTE4]) - dscene->tex_byte4_image.resize(tex_num_images[IMAGE_DATA_TYPE_BYTE4]); - break; - case IMAGE_DATA_TYPE_HALF4: - if(dscene->tex_half4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_HALF4]) - dscene->tex_half4_image.resize(tex_num_images[IMAGE_DATA_TYPE_HALF4]); - break; - case IMAGE_DATA_TYPE_BYTE: - if(dscene->tex_byte_image.size() <= tex_num_images[IMAGE_DATA_TYPE_BYTE]) - dscene->tex_byte_image.resize(tex_num_images[IMAGE_DATA_TYPE_BYTE]); - break; - case IMAGE_DATA_TYPE_FLOAT: - if(dscene->tex_float_image.size() <= tex_num_images[IMAGE_DATA_TYPE_FLOAT]) - dscene->tex_float_image.resize(tex_num_images[IMAGE_DATA_TYPE_FLOAT]); - break; - case IMAGE_DATA_TYPE_HALF: - if(dscene->tex_half_image.size() <= tex_num_images[IMAGE_DATA_TYPE_HALF]) - dscene->tex_half_image.resize(tex_num_images[IMAGE_DATA_TYPE_HALF]); - break; - } - } -} - void ImageManager::device_update(Device *device, - DeviceScene *dscene, Scene *scene, Progress& progress) { @@ -1021,9 +876,6 @@ void ImageManager::device_update(Device *device, return; } - /* Make sure arrays are proper size. */ - device_prepare_update(dscene); - TaskPool pool; for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { for(size_t slot = 0; slot < images[type].size(); slot++) { @@ -1031,14 +883,13 @@ void ImageManager::device_update(Device *device, continue; if(images[type][slot]->users == 0) { - device_free_image(device, dscene, (ImageDataType)type, slot); + device_free_image(device, (ImageDataType)type, slot); } else if(images[type][slot]->need_load) { if(!osl_texture_system || images[type][slot]->builtin_data) pool.push(function_bind(&ImageManager::device_load_image, this, device, - dscene, scene, (ImageDataType)type, slot, @@ -1053,7 +904,6 @@ void ImageManager::device_update(Device *device, } void ImageManager::device_update_slot(Device *device, - DeviceScene *dscene, Scene *scene, int flat_slot, Progress *progress) @@ -1065,12 +915,11 @@ void ImageManager::device_update_slot(Device *device, assert(image != NULL); if(image->users == 0) { - device_free_image(device, dscene, type, slot); + device_free_image(device, type, slot); } else if(image->need_load) { if(!osl_texture_system || image->builtin_data) device_load_image(device, - dscene, scene, type, slot, @@ -1078,31 +927,24 @@ void ImageManager::device_update_slot(Device *device, } } -void ImageManager::device_free_builtin(Device *device, DeviceScene *dscene) +void ImageManager::device_free_builtin(Device *device) { for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { for(size_t slot = 0; slot < images[type].size(); slot++) { if(images[type][slot] && images[type][slot]->builtin_data) - device_free_image(device, dscene, (ImageDataType)type, slot); + device_free_image(device, (ImageDataType)type, slot); } } } -void ImageManager::device_free(Device *device, DeviceScene *dscene) +void ImageManager::device_free(Device *device) { for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { for(size_t slot = 0; slot < images[type].size(); slot++) { - device_free_image(device, dscene, (ImageDataType)type, slot); + device_free_image(device, (ImageDataType)type, slot); } images[type].clear(); } - - dscene->tex_float4_image.clear(); - dscene->tex_byte4_image.clear(); - dscene->tex_half4_image.clear(); - dscene->tex_float_image.clear(); - dscene->tex_byte_image.clear(); - dscene->tex_half_image.clear(); } CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index c86d1cbedbf..cc7c8544bed 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -28,7 +28,6 @@ CCL_NAMESPACE_BEGIN class Device; -class DeviceScene; class Progress; class Scene; @@ -62,18 +61,15 @@ public: bool& is_linear, bool& builtin_free_cache); - void device_prepare_update(DeviceScene *dscene); void device_update(Device *device, - DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_slot(Device *device, - DeviceScene *dscene, Scene *scene, int flat_slot, Progress *progress); - void device_free(Device *device, DeviceScene *dscene); - void device_free_builtin(Device *device, DeviceScene *dscene); + void device_free(Device *device); + void device_free_builtin(Device *device); void set_osl_texture_system(void *texture_system); bool set_animation_frame_update(int frame); @@ -115,6 +111,8 @@ public: InterpolationType interpolation; ExtensionType extension; + device_memory *mem; + int users; }; @@ -151,13 +149,11 @@ private: string name_from_type(int type); void device_load_image(Device *device, - DeviceScene *dscene, Scene *scene, ImageDataType type, int slot, Progress *progess); void device_free_image(Device *device, - DeviceScene *dscene, ImageDataType type, int slot); }; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 6470b3b1075..efec1d3e491 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1913,7 +1913,6 @@ void MeshManager::device_update_flags(Device * /*device*/, } void MeshManager::device_update_displacement_images(Device *device, - DeviceScene *dscene, Scene *scene, Progress& progress) { @@ -1941,12 +1940,10 @@ void MeshManager::device_update_displacement_images(Device *device, } } } - image_manager->device_prepare_update(dscene); foreach(int slot, bump_images) { pool.push(function_bind(&ImageManager::device_update_slot, image_manager, device, - dscene, scene, slot, &progress)); @@ -2029,7 +2026,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } if(true_displacement_used) { VLOG(1) << "Updating images used for true displacement."; - device_update_displacement_images(device, dscene, scene, progress); + device_update_displacement_images(device, scene, progress); old_need_object_flags_update = scene->object_manager->need_flags_update; scene->object_manager->device_update_flags(device, dscene, diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index ed7cb881e91..f663275ffc1 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -368,7 +368,6 @@ protected: Progress& progress); void device_update_displacement_images(Device *device, - DeviceScene *dscene, Scene *scene, Progress& progress); }; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index c59a5d97df5..cf89385a33d 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -107,9 +107,9 @@ void Scene::free_memory(bool final) bake_manager->device_free(device, &dscene); if(!params.persistent_data || final) - image_manager->device_free(device, &dscene); + image_manager->device_free(device); else - image_manager->device_free_builtin(device, &dscene); + image_manager->device_free_builtin(device); lookup_tables->device_free(device, &dscene); } @@ -185,7 +185,7 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel() || device->have_error()) return; progress.set_status("Updating Images"); - image_manager->device_update(device, &dscene, this, progress); + image_manager->device_update(device, this, progress); if(progress.get_cancel() || device->have_error()) return; diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index a1966afd23b..32d5c0943e4 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -113,14 +113,6 @@ public: /* integrator */ device_vector sobol_directions; - /* cpu images */ - vector* > tex_float4_image; - vector* > tex_byte4_image; - vector* > tex_half4_image; - vector* > tex_float_image; - vector* > tex_byte_image; - vector* > tex_half_image; - KernelData data; }; From 57a0cb797d60024357a3e3a64c1873844b0178bd Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 20 Oct 2017 04:32:29 +0200 Subject: [PATCH 6/7] Code refactor: avoid some unnecessary device memory copying. --- intern/cycles/device/device_cpu.cpp | 2 +- intern/cycles/device/device_cuda.cpp | 5 +- intern/cycles/device/device_memory.h | 36 +++----- intern/cycles/device/opencl/opencl_base.cpp | 13 +-- intern/cycles/device/opencl/opencl_split.cpp | 3 +- intern/cycles/render/mesh.cpp | 87 ++++++++++---------- intern/cycles/render/mesh.h | 2 - intern/cycles/render/scene.h | 14 ++-- intern/cycles/render/svm.cpp | 46 +++++------ intern/cycles/render/svm.h | 6 +- intern/cycles/render/tables.cpp | 4 +- intern/cycles/util/util_vector.h | 9 ++ 12 files changed, 109 insertions(+), 118 deletions(-) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index af1bbc0db18..0ba00da16a6 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -379,7 +379,7 @@ public: texture_info.resize(flat_slot + 128); } - TextureInfo& info = texture_info.get_data()[flat_slot]; + TextureInfo& info = texture_info[flat_slot]; info.data = (uint64_t)mem.data_pointer; info.cl_buffer = 0; info.interpolation = interpolation; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index c245d7d8408..0f17b67c8c6 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -840,7 +840,7 @@ public: } /* Set Mapping and tag that we need to (re-)upload to device */ - TextureInfo& info = texture_info.get_data()[flat_slot]; + TextureInfo& info = texture_info[flat_slot]; info.data = (uint64_t)tex; info.cl_buffer = 0; info.interpolation = interpolation; @@ -1911,9 +1911,10 @@ uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory 0, 0, (void**)&args, 0)); device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t)); + size_t size = size_buffer[0]; device->mem_free(size_buffer); - return *size_buffer.get_data(); + return size; } bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim, diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 20707ad04c9..eeeca61496e 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -270,31 +270,14 @@ public: return &data[0]; } - T *copy(T *ptr, size_t width, size_t height = 0, size_t depth = 0) + void steal_data(array& from) { - T *mem = resize(width, height, depth); - if(mem != NULL) { - memcpy(mem, ptr, memory_size()); - } - return mem; - } - - void copy_at(T *ptr, size_t offset, size_t size) - { - if(size > 0) { - size_t mem_size = size*data_elements*datatype_size(data_type); - memcpy(&data[0] + offset, ptr, mem_size); - } - } - - void reference(T *ptr, size_t width, size_t height = 0, size_t depth = 0) - { - data.clear(); - data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth); - data_pointer = (device_ptr)ptr; - data_width = width; - data_height = height; - data_depth = depth; + data.steal_data(from); + data_size = data.size(); + data_pointer = (data_size)? (device_ptr)&data[0]: 0; + data_width = data_size; + data_height = 0; + data_depth = 0; } void clear() @@ -318,6 +301,11 @@ public: return &data[0]; } + T& operator[](size_t i) + { + return data[i]; + } + private: array data; }; diff --git a/intern/cycles/device/opencl/opencl_base.cpp b/intern/cycles/device/opencl/opencl_base.cpp index 6747a8a83ac..48c32a9dc5c 100644 --- a/intern/cycles/device/opencl/opencl_base.cpp +++ b/intern/cycles/device/opencl/opencl_base.cpp @@ -494,20 +494,21 @@ void OpenCLDeviceBase::mem_free_sub_ptr(device_ptr device_pointer) void OpenCLDeviceBase::const_copy_to(const char *name, void *host, size_t size) { ConstMemMap::iterator i = const_mem_map.find(name); + device_vector *data; if(i == const_mem_map.end()) { - device_vector *data = new device_vector(); - data->copy((uchar*)host, size); + data = new device_vector(); + data->resize(size); mem_alloc(name, *data, MEM_READ_ONLY); - i = const_mem_map.insert(ConstMemMap::value_type(name, data)).first; + const_mem_map.insert(ConstMemMap::value_type(name, data)); } else { - device_vector *data = i->second; - data->copy((uchar*)host, size); + data = i->second; } - mem_copy_to(*i->second); + memcpy(data->get_data(), host, size); + mem_copy_to(*data); } void OpenCLDeviceBase::tex_alloc(const char *name, diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp index b4e9419ebbd..920106f92d4 100644 --- a/intern/cycles/device/opencl/opencl_split.cpp +++ b/intern/cycles/device/opencl/opencl_split.cpp @@ -309,6 +309,7 @@ public: device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel"); device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t)); + size_t size = size_buffer[0]; device->mem_free(size_buffer); if(device->ciErr != CL_SUCCESS) { @@ -318,7 +319,7 @@ public: return 0; } - return *size_buffer.get_data(); + return size; } virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim, diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index efec1d3e491..69c21fc3cb3 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1127,14 +1127,12 @@ bool Mesh::is_instanced() const MeshManager::MeshManager() { - bvh = NULL; need_update = true; need_flags_update = true; } MeshManager::~MeshManager() { - delete bvh; } void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector& mesh_attributes) @@ -1393,11 +1391,11 @@ static void update_attribute_element_size(Mesh *mesh, } static void update_attribute_element_offset(Mesh *mesh, - vector& attr_float, + device_vector& attr_float, size_t& attr_float_offset, - vector& attr_float3, + device_vector& attr_float3, size_t& attr_float3_offset, - vector& attr_uchar4, + device_vector& attr_uchar4, size_t& attr_uchar4_offset, Attribute *mattr, AttributePrimitive prim, @@ -1425,7 +1423,7 @@ static void update_attribute_element_offset(Mesh *mesh, uchar4 *data = mattr->data_uchar4(); offset = attr_uchar4_offset; - assert(attr_uchar4.capacity() >= offset + size); + assert(attr_uchar4.size() >= offset + size); for(size_t k = 0; k < size; k++) { attr_uchar4[offset+k] = data[k]; } @@ -1435,7 +1433,7 @@ static void update_attribute_element_offset(Mesh *mesh, float *data = mattr->data_float(); offset = attr_float_offset; - assert(attr_float.capacity() >= offset + size); + assert(attr_float.size() >= offset + size); for(size_t k = 0; k < size; k++) { attr_float[offset+k] = data[k]; } @@ -1445,7 +1443,7 @@ static void update_attribute_element_offset(Mesh *mesh, Transform *tfm = mattr->data_transform(); offset = attr_float3_offset; - assert(attr_float3.capacity() >= offset + size * 4); + assert(attr_float3.size() >= offset + size * 4); for(size_t k = 0; k < size*4; k++) { attr_float3[offset+k] = (&tfm->x)[k]; } @@ -1455,7 +1453,7 @@ static void update_attribute_element_offset(Mesh *mesh, float4 *data = mattr->data_float4(); offset = attr_float3_offset; - assert(attr_float3.capacity() >= offset + size); + assert(attr_float3.size() >= offset + size); for(size_t k = 0; k < size; k++) { attr_float3[offset+k] = data[k]; } @@ -1556,9 +1554,9 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, } } - vector attr_float(attr_float_size); - vector attr_float3(attr_float3_size); - vector attr_uchar4(attr_uchar4_size); + dscene->attributes_float.resize(attr_float_size); + dscene->attributes_float3.resize(attr_float3_size); + dscene->attributes_uchar4.resize(attr_uchar4_size); size_t attr_float_offset = 0; size_t attr_float3_offset = 0; @@ -1577,27 +1575,27 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Attribute *subd_mattr = mesh->subd_attributes.find(req); update_attribute_element_offset(mesh, - attr_float, attr_float_offset, - attr_float3, attr_float3_offset, - attr_uchar4, attr_uchar4_offset, + dscene->attributes_float, attr_float_offset, + dscene->attributes_float3, attr_float3_offset, + dscene->attributes_uchar4, attr_uchar4_offset, triangle_mattr, ATTR_PRIM_TRIANGLE, req.triangle_type, req.triangle_desc); update_attribute_element_offset(mesh, - attr_float, attr_float_offset, - attr_float3, attr_float3_offset, - attr_uchar4, attr_uchar4_offset, + dscene->attributes_float, attr_float_offset, + dscene->attributes_float3, attr_float3_offset, + dscene->attributes_uchar4, attr_uchar4_offset, curve_mattr, ATTR_PRIM_CURVE, req.curve_type, req.curve_desc); update_attribute_element_offset(mesh, - attr_float, attr_float_offset, - attr_float3, attr_float3_offset, - attr_uchar4, attr_uchar4_offset, + dscene->attributes_float, attr_float_offset, + dscene->attributes_float3, attr_float3_offset, + dscene->attributes_uchar4, attr_uchar4_offset, subd_mattr, ATTR_PRIM_SUBD, req.subd_type, @@ -1618,16 +1616,13 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, /* copy to device */ progress.set_status("Updating Mesh", "Copying Attributes to device"); - if(attr_float.size()) { - dscene->attributes_float.copy(&attr_float[0], attr_float.size()); + if(dscene->attributes_float.size()) { device->tex_alloc("__attributes_float", dscene->attributes_float); } - if(attr_float3.size()) { - dscene->attributes_float3.copy(&attr_float3[0], attr_float3.size()); + if(dscene->attributes_float3.size()) { device->tex_alloc("__attributes_float3", dscene->attributes_float3); } - if(attr_uchar4.size()) { - dscene->attributes_uchar4.copy(&attr_uchar4[0], attr_uchar4.size()); + if(dscene->attributes_uchar4.size()) { device->tex_alloc("__attributes_uchar4", dscene->attributes_uchar4); } } @@ -1725,10 +1720,9 @@ void MeshManager::device_update_mesh(Device *device, } } else { - PackedBVH& pack = bvh->pack; - for(size_t i = 0; i < pack.prim_index.size(); ++i) { - if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { - tri_prim_index[pack.prim_index[i]] = pack.prim_tri_index[i]; + for(size_t i = 0; i < dscene->prim_index.size(); ++i) { + if((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { + tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i]; } } } @@ -1832,11 +1826,13 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * VLOG(1) << (bparams.use_qbvh ? "Using QBVH optimization structure" : "Using regular BVH optimization structure"); - delete bvh; - bvh = BVH::create(bparams, scene->objects); + BVH *bvh = BVH::create(bparams, scene->objects); bvh->build(progress); - if(progress.get_cancel()) return; + if(progress.get_cancel()) { + delete bvh; + return; + } /* copy to device */ progress.set_status("Updating Scene BVH", "Copying BVH to device"); @@ -1844,49 +1840,51 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * PackedBVH& pack = bvh->pack; if(pack.nodes.size()) { - dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size()); + dscene->bvh_nodes.steal_data(pack.nodes); device->tex_alloc("__bvh_nodes", dscene->bvh_nodes); } if(pack.leaf_nodes.size()) { - dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size()); + dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes); device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes); } if(pack.object_node.size()) { - dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size()); + dscene->object_node.steal_data(pack.object_node); device->tex_alloc("__object_node", dscene->object_node); } if(pack.prim_tri_index.size()) { - dscene->prim_tri_index.reference((uint*)&pack.prim_tri_index[0], pack.prim_tri_index.size()); + dscene->prim_tri_index.steal_data(pack.prim_tri_index); device->tex_alloc("__prim_tri_index", dscene->prim_tri_index); } if(pack.prim_tri_verts.size()) { - dscene->prim_tri_verts.reference((float4*)&pack.prim_tri_verts[0], pack.prim_tri_verts.size()); + dscene->prim_tri_verts.steal_data(pack.prim_tri_verts); device->tex_alloc("__prim_tri_verts", dscene->prim_tri_verts); } if(pack.prim_type.size()) { - dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size()); + dscene->prim_type.steal_data(pack.prim_type); device->tex_alloc("__prim_type", dscene->prim_type); } if(pack.prim_visibility.size()) { - dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size()); + dscene->prim_visibility.steal_data(pack.prim_visibility); device->tex_alloc("__prim_visibility", dscene->prim_visibility); } if(pack.prim_index.size()) { - dscene->prim_index.reference((uint*)&pack.prim_index[0], pack.prim_index.size()); + dscene->prim_index.steal_data(pack.prim_index); device->tex_alloc("__prim_index", dscene->prim_index); } if(pack.prim_object.size()) { - dscene->prim_object.reference((uint*)&pack.prim_object[0], pack.prim_object.size()); + dscene->prim_object.steal_data(pack.prim_object); device->tex_alloc("__prim_object", dscene->prim_object); } if(pack.prim_time.size()) { - dscene->prim_time.reference((float2*)&pack.prim_time[0], pack.prim_time.size()); + dscene->prim_time.steal_data(pack.prim_time); device->tex_alloc("__prim_time", dscene->prim_time); } dscene->data.bvh.root = pack.root_index; dscene->data.bvh.use_qbvh = bparams.use_qbvh; dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); + + delete bvh; } void MeshManager::device_update_flags(Device * /*device*/, @@ -2168,6 +2166,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->attributes_uchar4); dscene->bvh_nodes.clear(); + dscene->bvh_leaf_nodes.clear(); dscene->object_node.clear(); dscene->prim_tri_verts.clear(); dscene->prim_tri_index.clear(); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index f663275ffc1..30f5e9063e6 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -321,8 +321,6 @@ public: class MeshManager { public: - BVH *bvh; - bool need_update; bool need_flags_update; diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 32d5c0943e4..d4ec7d90ff5 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -60,15 +60,15 @@ class BakeData; class DeviceScene { public: /* BVH */ - device_vector bvh_nodes; - device_vector bvh_leaf_nodes; - device_vector object_node; + device_vector bvh_nodes; + device_vector bvh_leaf_nodes; + device_vector object_node; device_vector prim_tri_index; device_vector prim_tri_verts; - device_vector prim_type; + device_vector prim_type; device_vector prim_visibility; - device_vector prim_index; - device_vector prim_object; + device_vector prim_index; + device_vector prim_object; device_vector prim_time; /* mesh */ @@ -103,7 +103,7 @@ public: device_vector particles; /* shaders */ - device_vector svm_nodes; + device_vector svm_nodes; device_vector shader_flag; device_vector object_flag; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 32f89897970..278a8a87b20 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -48,15 +48,15 @@ void SVMShaderManager::reset(Scene * /*scene*/) void SVMShaderManager::device_update_shader(Scene *scene, Shader *shader, Progress *progress, - vector *global_svm_nodes) + array *global_svm_nodes) { if(progress->get_cancel()) { return; } assert(shader->graph); - vector svm_nodes; - svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); + array svm_nodes; + svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); SVMCompiler::Summary summary; SVMCompiler compiler(scene->shader_manager, scene->image_manager); @@ -79,12 +79,12 @@ void SVMShaderManager::device_update_shader(Scene *scene, global_svm_nodes->resize(global_nodes_size + svm_nodes.size()); /* Offset local SVM nodes to a global address space. */ - int4& jump_node = global_svm_nodes->at(shader->id); + int4& jump_node = (*global_svm_nodes)[shader->id]; jump_node.y = svm_nodes[0].y + global_nodes_size - 1; jump_node.z = svm_nodes[0].z + global_nodes_size - 1; jump_node.w = svm_nodes[0].w + global_nodes_size - 1; /* Copy new nodes to global storage. */ - memcpy(&global_svm_nodes->at(global_nodes_size), + memcpy(&(*global_svm_nodes)[global_nodes_size], &svm_nodes[1], sizeof(int4) * (svm_nodes.size() - 1)); nodes_lock_.unlock(); @@ -106,11 +106,11 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene device_update_shaders_used(scene); /* svm_nodes */ - vector svm_nodes; + array svm_nodes; size_t i; for(i = 0; i < scene->shaders.size(); i++) { - svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); + svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); } TaskPool task_pool; @@ -129,7 +129,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene return; } - dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size()); + dscene->svm_nodes.steal_data(svm_nodes); device->tex_alloc("__svm_nodes", dscene->svm_nodes); for(i = 0; i < scene->shaders.size(); i++) { @@ -366,17 +366,17 @@ uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w) void SVMCompiler::add_node(int a, int b, int c, int d) { - current_svm_nodes.push_back(make_int4(a, b, c, d)); + current_svm_nodes.push_back_slow(make_int4(a, b, c, d)); } void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c) { - current_svm_nodes.push_back(make_int4(type, a, b, c)); + current_svm_nodes.push_back_slow(make_int4(type, a, b, c)); } void SVMCompiler::add_node(ShaderNodeType type, const float3& f) { - current_svm_nodes.push_back(make_int4(type, + current_svm_nodes.push_back_slow(make_int4(type, __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z))); @@ -384,7 +384,7 @@ void SVMCompiler::add_node(ShaderNodeType type, const float3& f) void SVMCompiler::add_node(const float4& f) { - current_svm_nodes.push_back(make_int4( + current_svm_nodes.push_back_slow(make_int4( __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), @@ -627,7 +627,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node, /* Add instruction to skip closure and its dependencies if mix * weight is zero. */ - current_svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, + current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0)); @@ -645,7 +645,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node, /* Add instruction to skip closure and its dependencies if mix * weight is zero. */ - current_svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, + current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0)); @@ -797,7 +797,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty void SVMCompiler::compile(Scene *scene, Shader *shader, - vector& svm_nodes, + array& svm_nodes, int index, Summary *summary) { @@ -839,9 +839,7 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL); compile_type(shader, shader->graph, SHADER_TYPE_BUMP); svm_nodes[index].y = svm_nodes.size(); - svm_nodes.insert(svm_nodes.end(), - current_svm_nodes.begin(), - current_svm_nodes.end()); + svm_nodes.append(current_svm_nodes); } /* generate surface shader */ @@ -852,9 +850,7 @@ void SVMCompiler::compile(Scene *scene, if(!has_bump) { svm_nodes[index].y = svm_nodes.size(); } - svm_nodes.insert(svm_nodes.end(), - current_svm_nodes.begin(), - current_svm_nodes.end()); + svm_nodes.append(current_svm_nodes); } /* generate volume shader */ @@ -862,9 +858,7 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL); compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); svm_nodes[index].z = svm_nodes.size(); - svm_nodes.insert(svm_nodes.end(), - current_svm_nodes.begin(), - current_svm_nodes.end()); + svm_nodes.append(current_svm_nodes); } /* generate displacement shader */ @@ -872,9 +866,7 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL); compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); svm_nodes[index].w = svm_nodes.size(); - svm_nodes.insert(svm_nodes.end(), - current_svm_nodes.begin(), - current_svm_nodes.end()); + svm_nodes.append(current_svm_nodes); } /* Fill in summary information. */ diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 98ef5fa05d8..0e9905957c7 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -55,7 +55,7 @@ protected: void device_update_shader(Scene *scene, Shader *shader, Progress *progress, - vector *global_svm_nodes); + array *global_svm_nodes); }; /* Graph Compiler */ @@ -98,7 +98,7 @@ public: SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager); void compile(Scene *scene, Shader *shader, - vector& svm_nodes, + array& svm_nodes, int index, Summary *summary = NULL); @@ -207,7 +207,7 @@ protected: /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); - vector current_svm_nodes; + array current_svm_nodes; ShaderType current_type; Shader *current_shader; ShaderGraph *current_graph; diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp index bf1ef12d602..c08c83cfe11 100644 --- a/intern/cycles/render/tables.cpp +++ b/intern/cycles/render/tables.cpp @@ -90,7 +90,9 @@ size_t LookupTables::add_table(DeviceScene *dscene, vector& data) } /* copy table data and return offset */ - dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size()); + float *dtable = dscene->lookup_table.get_data(); + memcpy(dtable + new_table.offset, &data[0], sizeof(float) * data.size()); + return new_table.offset; } diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 4add91a3368..9e74505b14a 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -273,6 +273,15 @@ public: push_back_slow(t); } + void append(const array& from) + { + if(from.size()) { + size_t old_size = size(); + resize(old_size + from.size()); + memcpy(data_ + old_size, from.data(), sizeof(T) * from.size()); + } + } + protected: inline T* mem_allocate(size_t N) { From 6dfe4cbc6b8717223c631e80af6c7552576966e1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Oct 2017 01:15:26 +1100 Subject: [PATCH 7/7] Polyfill Beautify: half-edge optimization Was using an edge hash for triangle -> edge lookups, updating triangle indices for each edge-rotation. Replace this with half-edge which can rotate edges much more simply, writing triangles back once the solution has been calculated. Gives ~33% speedup in own tests. --- .../blender/blenlib/BLI_polyfill2d_beautify.h | 3 +- .../blenlib/intern/polyfill2d_beautify.c | 436 ++++++++---------- source/blender/bmesh/intern/bmesh_polygon.c | 9 +- source/blender/bmesh/intern/bmesh_polygon.h | 3 +- .../bmesh/operators/bmo_connect_concave.c | 11 +- .../bmesh/tools/bmesh_decimate_collapse.c | 12 +- .../blender/bmesh/tools/bmesh_triangulate.c | 15 +- tests/gtests/blenlib/BLI_polyfill2d_test.cc | 5 +- 8 files changed, 204 insertions(+), 290 deletions(-) diff --git a/source/blender/blenlib/BLI_polyfill2d_beautify.h b/source/blender/blenlib/BLI_polyfill2d_beautify.h index 29a900200bb..278771e9611 100644 --- a/source/blender/blenlib/BLI_polyfill2d_beautify.h +++ b/source/blender/blenlib/BLI_polyfill2d_beautify.h @@ -21,7 +21,6 @@ #ifndef __BLI_POLYFILL2D_BEAUTIFY_H__ #define __BLI_POLYFILL2D_BEAUTIFY_H__ -struct EdgeHash; struct Heap; struct MemArena; @@ -31,7 +30,7 @@ void BLI_polyfill_beautify( unsigned int (*tris)[3], /* structs for reuse */ - struct MemArena *arena, struct Heap *eheap, struct EdgeHash *eh); + struct MemArena *arena, struct Heap *eheap); float BLI_polyfill_beautify_quad_rotate_calc_ex( const float v1[2], const float v2[2], const float v3[2], const float v4[2], diff --git a/source/blender/blenlib/intern/polyfill2d_beautify.c b/source/blender/blenlib/intern/polyfill2d_beautify.c index 5f6fb8e6cd4..f2a1c194eb1 100644 --- a/source/blender/blenlib/intern/polyfill2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill2d_beautify.c @@ -42,77 +42,56 @@ #include "BLI_math.h" #include "BLI_memarena.h" -#include "BLI_edgehash.h" #include "BLI_heap.h" #include "BLI_polyfill2d_beautify.h" /* own include */ #include "BLI_strict_flags.h" -struct PolyEdge { - /** ordered vert indices (smaller first) */ - unsigned int verts[2]; - /** ordered face indices (depends on winding compared to the edge verts) - * - (verts[0], verts[1]) == faces[0] - * - (verts[1], verts[0]) == faces[1] - */ - unsigned int faces[2]; - /** - * The face-index which isn't used by either of the edges verts [0 - 2]. - * could be calculated each time, but cleaner to store for reuse. - */ - unsigned int faces_other_v[2]; +/* Used to find matching edges. */ +struct OrderEdge { + uint verts[2]; + uint e_half; }; +/* Half edge used for rotating in-place. */ +struct HalfEdge { + uint v; + uint e_next; + uint e_radial; + uint base_index; +}; -#ifndef NDEBUG -/** - * Only to check for error-cases. - */ -static void polyfill_validate_tri(unsigned int (*tris)[3], unsigned int tri_index, EdgeHash *ehash) +static int oedge_cmp(const void *a1, const void *a2) { - const unsigned int *tri = tris[tri_index]; - int j_curr; - - BLI_assert(!ELEM(tri[0], tri[1], tri[2]) && - !ELEM(tri[1], tri[0], tri[2]) && - !ELEM(tri[2], tri[0], tri[1])); - - for (j_curr = 0; j_curr < 3; j_curr++) { - struct PolyEdge *e; - unsigned int e_v1 = tri[(j_curr ) ]; - unsigned int e_v2 = tri[(j_curr + 1) % 3]; - e = BLI_edgehash_lookup(ehash, e_v1, e_v2); - if (e) { - if (e->faces[0] == tri_index) { - BLI_assert(e->verts[0] == e_v1); - BLI_assert(e->verts[1] == e_v2); - } - else if (e->faces[1] == tri_index) { - BLI_assert(e->verts[0] == e_v2); - BLI_assert(e->verts[1] == e_v1); - } - else { - BLI_assert(0); - } - - BLI_assert(e->faces[0] != e->faces[1]); - BLI_assert(ELEM(e_v1, UNPACK3(tri))); - BLI_assert(ELEM(e_v2, UNPACK3(tri))); - BLI_assert(ELEM(e_v1, UNPACK2(e->verts))); - BLI_assert(ELEM(e_v2, UNPACK2(e->verts))); - BLI_assert(e_v1 != tris[e->faces[0]][e->faces_other_v[0]]); - BLI_assert(e_v1 != tris[e->faces[1]][e->faces_other_v[1]]); - BLI_assert(e_v2 != tris[e->faces[0]][e->faces_other_v[0]]); - BLI_assert(e_v2 != tris[e->faces[1]][e->faces_other_v[1]]); - - BLI_assert(ELEM(tri_index, UNPACK2(e->faces))); - } + const struct OrderEdge *x1 = a1, *x2 = a2; + if (x1->verts[0] > x2->verts[0]) { + return 1; + } + else if (x1->verts[0] < x2->verts[0]) { + return -1; } -} -#endif -BLI_INLINE bool is_boundary_edge(unsigned int i_a, unsigned int i_b, const unsigned int coord_last) + if (x1->verts[1] > x2->verts[1]) { + return 1; + } + else if (x1->verts[1] < x2->verts[1]) { + return -1; + } + + /* only for pradictability */ + if (x1->e_half > x2->e_half) { + return 1; + } + else if (x1->e_half < x2->e_half) { + return -1; + } + /* Should never get here, no two edges should be the same. */ + BLI_assert(false); + return 0; +} + +BLI_INLINE bool is_boundary_edge(uint i_a, uint i_b, const uint coord_last) { BLI_assert(i_a < i_b); return ((i_a + 1 == i_b) || UNLIKELY((i_a == 0) && (i_b == coord_last))); @@ -215,27 +194,31 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex( static float polyedge_rotate_beauty_calc( const float (*coords)[2], - const unsigned int (*tris)[3], - const struct PolyEdge *e) + const struct HalfEdge *edges, + const struct HalfEdge *e_a) { + const struct HalfEdge *e_b = &edges[e_a->e_radial]; + + const struct HalfEdge *e_a_other = &edges[edges[e_a->e_next].e_next]; + const struct HalfEdge *e_b_other = &edges[edges[e_b->e_next].e_next]; + const float *v1, *v2, *v3, *v4; - v1 = coords[tris[e->faces[0]][e->faces_other_v[0]]]; - v3 = coords[tris[e->faces[1]][e->faces_other_v[1]]]; - v2 = coords[e->verts[0]]; - v4 = coords[e->verts[1]]; + v1 = coords[e_a_other->v]; + v2 = coords[e_a->v]; + v3 = coords[e_b_other->v]; + v4 = coords[e_b->v]; return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4); } static void polyedge_beauty_cost_update_single( const float (*coords)[2], - const unsigned int (*tris)[3], - const struct PolyEdge *edges, - struct PolyEdge *e, + const struct HalfEdge *edges, + struct HalfEdge *e, Heap *eheap, HeapNode **eheap_table) { - const unsigned int i = (unsigned int)(e - edges); + const uint i = e->base_index; if (eheap_table[i]) { BLI_heap_remove(eheap, eheap_table[i]); @@ -244,7 +227,7 @@ static void polyedge_beauty_cost_update_single( { /* recalculate edge */ - const float cost = polyedge_rotate_beauty_calc(coords, tris, e); + const float cost = polyedge_rotate_beauty_calc(coords, edges, e); /* We can get cases where both choices generate very small negative costs, which leads to infinite loop. * Anyway, costs above that are not worth recomputing, maybe we could even optimize it to a smaller limit? * Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully? @@ -260,39 +243,22 @@ static void polyedge_beauty_cost_update_single( static void polyedge_beauty_cost_update( const float (*coords)[2], - const unsigned int (*tris)[3], - const struct PolyEdge *edges, - struct PolyEdge *e, - Heap *eheap, HeapNode **eheap_table, - EdgeHash *ehash) + struct HalfEdge *edges, + struct HalfEdge *e, + Heap *eheap, HeapNode **eheap_table) { - const unsigned int *tri_0 = tris[e->faces[0]]; - const unsigned int *tri_1 = tris[e->faces[1]]; - unsigned int i; + struct HalfEdge *e_arr[4]; + e_arr[0] = &edges[e->e_next]; + e_arr[1] = &edges[e_arr[0]->e_next]; - struct PolyEdge *e_arr[4] = { - BLI_edgehash_lookup(ehash, - tri_0[(e->faces_other_v[0] ) % 3], - tri_0[(e->faces_other_v[0] + 1) % 3]), - BLI_edgehash_lookup(ehash, - tri_0[(e->faces_other_v[0] + 2) % 3], - tri_0[(e->faces_other_v[0] ) % 3]), - BLI_edgehash_lookup(ehash, - tri_1[(e->faces_other_v[1] ) % 3], - tri_1[(e->faces_other_v[1] + 1) % 3]), - BLI_edgehash_lookup(ehash, - tri_1[(e->faces_other_v[1] + 2) % 3], - tri_1[(e->faces_other_v[1] ) % 3]), - }; - - - for (i = 0; i < 4; i++) { - if (e_arr[i]) { - BLI_assert(!(ELEM(e_arr[i]->faces[0], UNPACK2(e->faces)) && - ELEM(e_arr[i]->faces[1], UNPACK2(e->faces)))); + e = &edges[e->e_radial]; + e_arr[2] = &edges[e->e_next]; + e_arr[3] = &edges[e_arr[2]->e_next]; + for (uint i = 0; i < 4; i++) { + if (e_arr[i] && e_arr[i]->base_index != UINT_MAX) { polyedge_beauty_cost_update_single( - coords, tris, edges, + coords, edges, e_arr[i], eheap, eheap_table); } @@ -300,91 +266,49 @@ static void polyedge_beauty_cost_update( } static void polyedge_rotate( - unsigned int (*tris)[3], - struct PolyEdge *e, - EdgeHash *ehash) + struct HalfEdge *edges, + struct HalfEdge *e) { - unsigned int e_v1_new = tris[e->faces[0]][e->faces_other_v[0]]; - unsigned int e_v2_new = tris[e->faces[1]][e->faces_other_v[1]]; + /** CCW winding, rotate internal edge to new vertical state. + *
+	 *   Before         After
+	 *      X             X
+	 *     / \           /|\
+	 *  e4/   \e5     e4/ | \e5
+	 *   / e3  \       /  |  \
+	 * X ------- X -> X e0|e3 X
+	 *   \ e0  /       \  |  /
+	 *  e2\   /e1     e2\ | /e1
+	 *     \ /           \|/
+	 *      X             X
+	 * 
+ */ + struct HalfEdge *ed[6]; + uint ed_index[6]; -#ifndef NDEBUG - polyfill_validate_tri(tris, e->faces[0], ehash); - polyfill_validate_tri(tris, e->faces[1], ehash); -#endif + ed_index[0] = (uint)(e - edges); + ed[0] = &edges[ed_index[0]]; + ed_index[1] = ed[0]->e_next; + ed[1] = &edges[ed_index[1]]; + ed_index[2] = ed[1]->e_next; + ed[2] = &edges[ed_index[2]]; - BLI_assert(e_v1_new != e_v2_new); - BLI_assert(!ELEM(e_v2_new, UNPACK3(tris[e->faces[0]]))); - BLI_assert(!ELEM(e_v1_new, UNPACK3(tris[e->faces[1]]))); + ed_index[3] = e->e_radial; + ed[3] = &edges[ed_index[3]]; + ed_index[4] = ed[3]->e_next; + ed[4] = &edges[ed_index[4]]; + ed_index[5] = ed[4]->e_next; + ed[5] = &edges[ed_index[5]]; - tris[e->faces[0]][(e->faces_other_v[0] + 1) % 3] = e_v2_new; - tris[e->faces[1]][(e->faces_other_v[1] + 1) % 3] = e_v1_new; + ed[0]->e_next = ed_index[2]; + ed[1]->e_next = ed_index[3]; + ed[2]->e_next = ed_index[4]; + ed[3]->e_next = ed_index[5]; + ed[4]->e_next = ed_index[0]; + ed[5]->e_next = ed_index[1]; - e->faces_other_v[0] = (e->faces_other_v[0] + 2) % 3; - e->faces_other_v[1] = (e->faces_other_v[1] + 2) % 3; - - BLI_assert((tris[e->faces[0]][e->faces_other_v[0]] != e_v1_new) && - (tris[e->faces[0]][e->faces_other_v[0]] != e_v2_new)); - BLI_assert((tris[e->faces[1]][e->faces_other_v[1]] != e_v1_new) && - (tris[e->faces[1]][e->faces_other_v[1]] != e_v2_new)); - - BLI_edgehash_remove(ehash, e->verts[0], e->verts[1], NULL); - BLI_edgehash_insert(ehash, e_v1_new, e_v2_new, e); - - if (e_v1_new < e_v2_new) { - e->verts[0] = e_v1_new; - e->verts[1] = e_v2_new; - } - else { - /* maintain winding info */ - e->verts[0] = e_v2_new; - e->verts[1] = e_v1_new; - - SWAP(unsigned int, e->faces[0], e->faces[1]); - SWAP(unsigned int, e->faces_other_v[0], e->faces_other_v[1]); - } - - /* update adjacent data */ - { - unsigned int e_side = 0; - - for (e_side = 0; e_side < 2; e_side++) { - /* 't_other' which we need to swap out is always the same edge-order */ - const unsigned int t_other = (((e->faces_other_v[e_side]) + 2)) % 3; - unsigned int t_index = e->faces[e_side]; - unsigned int t_index_other = e->faces[!e_side]; - unsigned int *tri = tris[t_index]; - - struct PolyEdge *e_other; - unsigned int e_v1 = tri[(t_other ) ]; - unsigned int e_v2 = tri[(t_other + 1) % 3]; - - e_other = BLI_edgehash_lookup(ehash, e_v1, e_v2); - if (e_other) { - BLI_assert(t_index != e_other->faces[0] && t_index != e_other->faces[1]); - if (t_index_other == e_other->faces[0]) { - e_other->faces[0] = t_index; - e_other->faces_other_v[0] = (t_other + 2) % 3; - BLI_assert(!ELEM(tri[e_other->faces_other_v[0]], e_v1, e_v2)); - } - else if (t_index_other == e_other->faces[1]) { - e_other->faces[1] = t_index; - e_other->faces_other_v[1] = (t_other + 2) % 3; - BLI_assert(!ELEM(tri[e_other->faces_other_v[1]], e_v1, e_v2)); - } - else { - BLI_assert(0); - } - } - } - } - -#ifndef NDEBUG - polyfill_validate_tri(tris, e->faces[0], ehash); - polyfill_validate_tri(tris, e->faces[1], ehash); -#endif - - BLI_assert(!ELEM(tris[e->faces[0]][e->faces_other_v[0]], UNPACK2(e->verts))); - BLI_assert(!ELEM(tris[e->faces[1]][e->faces_other_v[1]], UNPACK2(e->verts))); + ed[0]->v = ed[5]->v; + ed[3]->v = ed[2]->v; } /** @@ -397,108 +321,124 @@ static void polyedge_rotate( */ void BLI_polyfill_beautify( const float (*coords)[2], - const unsigned int coords_tot, - unsigned int (*tris)[3], + const uint coords_tot, + uint (*tris)[3], /* structs for reuse */ - MemArena *arena, Heap *eheap, EdgeHash *ehash) + MemArena *arena, Heap *eheap) { - const unsigned int coord_last = coords_tot - 1; - const unsigned int tris_tot = coords_tot - 2; + const uint coord_last = coords_tot - 1; + const uint tris_len = coords_tot - 2; /* internal edges only (between 2 tris) */ - const unsigned int edges_tot = tris_tot - 1; - unsigned int edges_tot_used = 0; - unsigned int i; + const uint edges_len = tris_len - 1; HeapNode **eheap_table; - struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges)); - - BLI_assert(BLI_heap_size(eheap) == 0); - BLI_assert(BLI_edgehash_size(ehash) == 0); + const uint half_edges_len = 3 * tris_len; + struct HalfEdge *half_edges = BLI_memarena_alloc(arena, sizeof(*half_edges) * half_edges_len); + struct OrderEdge *order_edges = BLI_memarena_alloc(arena, sizeof(struct OrderEdge) * 2 * edges_len); + uint order_edges_len = 0; /* first build edges */ - for (i = 0; i < tris_tot; i++) { - unsigned int j_prev, j_curr, j_next; - j_prev = 2; - j_next = 1; - for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) { - int e_index; + for (uint i = 0; i < tris_len; i++) { + for (uint j_curr = 0, j_prev = 2; j_curr < 3; j_prev = j_curr++) { + const uint e_index_prev = (i * 3) + j_prev; + const uint e_index_curr = (i * 3) + j_curr; - unsigned int e_pair[2] = { - tris[i][j_prev], - tris[i][j_curr], - }; + half_edges[e_index_prev].v = tris[i][j_prev]; + half_edges[e_index_prev].e_next = e_index_curr; + half_edges[e_index_prev].e_radial = UINT_MAX; + half_edges[e_index_prev].base_index = UINT_MAX; + uint e_pair[2] = {tris[i][j_prev], tris[i][j_curr]}; if (e_pair[0] > e_pair[1]) { - SWAP(unsigned int, e_pair[0], e_pair[1]); - e_index = 1; - } - else { - e_index = 0; + SWAP(uint, e_pair[0], e_pair[1]); } + /* ensure internal edges. */ if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) { - struct PolyEdge *e; - void **val_p; - - if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) { - e = &edges[edges_tot_used++]; - *val_p = e; - memcpy(e->verts, e_pair, sizeof(e->verts)); -#ifndef NDEBUG - e->faces[!e_index] = (unsigned int)-1; -#endif - } - else { - e = *val_p; - /* ensure each edge only ever has 2x users */ -#ifndef NDEBUG - BLI_assert(e->faces[e_index] == (unsigned int)-1); - BLI_assert((e->verts[0] == e_pair[0]) && - (e->verts[1] == e_pair[1])); -#endif - } - - e->faces[e_index] = i; - e->faces_other_v[e_index] = j_next; + order_edges[order_edges_len].verts[0] = e_pair[0]; + order_edges[order_edges_len].verts[1] = e_pair[1]; + order_edges[order_edges_len].e_half = e_index_prev; + order_edges_len += 1; } } } + BLI_assert(edges_len * 2 == order_edges_len); - /* now perform iterative rotations */ - eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot); + qsort(order_edges, order_edges_len, sizeof(struct OrderEdge), oedge_cmp); - // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); } + for (uint i = 0, base_index = 0; i < order_edges_len; base_index++) { + const struct OrderEdge *oe_a = &order_edges[i++]; + const struct OrderEdge *oe_b = &order_edges[i++]; + BLI_assert(oe_a->verts[0] == oe_a->verts[0] && oe_a->verts[1] == oe_a->verts[1]); + half_edges[oe_a->e_half].e_radial = oe_b->e_half; + half_edges[oe_b->e_half].e_radial = oe_a->e_half; + half_edges[oe_a->e_half].base_index = base_index; + half_edges[oe_b->e_half].base_index = base_index; + } + /* order_edges could be freed now. */ - /* build heap */ - for (i = 0; i < edges_tot; i++) { - struct PolyEdge *e = &edges[i]; - const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e); - if (cost < 0.0f) { - eheap_table[i] = BLI_heap_insert(eheap, cost, e); - } - else { - eheap_table[i] = NULL; + /* Now perform iterative rotations. */ +#if 0 + eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_len); +#else + /* We can re-use this since its big enough. */ + eheap_table = (void *)order_edges; + order_edges = NULL; +#endif + + /* Build heap. */ + { + struct HalfEdge *e = half_edges; + for (uint i = 0; i < half_edges_len; i++, e++) { + /* Accounts for boundary edged too (UINT_MAX). */ + if (e->e_radial < i) { + const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e); + if (cost < 0.0f) { + eheap_table[e->base_index] = BLI_heap_insert(eheap, cost, e); + } + else { + eheap_table[e->base_index] = NULL; + } + } } } while (BLI_heap_is_empty(eheap) == false) { - struct PolyEdge *e = BLI_heap_popmin(eheap); - i = (unsigned int)(e - edges); - eheap_table[i] = NULL; + struct HalfEdge *e = BLI_heap_popmin(eheap); + eheap_table[e->base_index] = NULL; - polyedge_rotate(tris, e, ehash); + polyedge_rotate(half_edges, e); /* recalculate faces connected on the heap */ polyedge_beauty_cost_update( - coords, (const unsigned int (*)[3])tris, edges, + coords, half_edges, e, - eheap, eheap_table, ehash); + eheap, eheap_table); } BLI_heap_clear(eheap, NULL); - BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE); /* MEM_freeN(eheap_table); */ /* arena */ + + /* get tris from half edge. */ + uint tri_index = 0; + for (uint i = 0; i < half_edges_len; i++) { + struct HalfEdge *e = &half_edges[i]; + if (e->v != UINT_MAX) { + uint *tri = tris[tri_index++]; + + tri[0] = e->v; + e->v = UINT_MAX; + + e = &half_edges[e->e_next]; + tri[1] = e->v; + e->v = UINT_MAX; + + e = &half_edges[e->e_next]; + tri[2] = e->v; + e->v = UINT_MAX; + } + } } diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 977ae192c79..bf5fc18935d 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -925,7 +925,7 @@ void BM_face_triangulate( MemArena *pf_arena, /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ - struct Heap *pf_heap, struct EdgeHash *pf_ehash) + struct Heap *pf_heap) { const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); @@ -1041,7 +1041,7 @@ void BM_face_triangulate( if (use_beauty) { BLI_polyfill_beautify( projverts, f->len, tris, - pf_arena, pf_heap, pf_ehash); + pf_arena, pf_heap); } BLI_memarena_clear(pf_arena); @@ -1497,7 +1497,6 @@ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_ /* use_beauty */ Heap *pf_heap = NULL; - EdgeHash *pf_ehash = NULL; BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { /* don't consider two-edged faces */ @@ -1574,7 +1573,6 @@ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_ if (UNLIKELY(pf_arena == NULL)) { pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE); } tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri); @@ -1593,7 +1591,7 @@ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_ BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena); - BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap, pf_ehash); + BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap); for (j = 0; j < totfilltri; j++) { BMLoop **l_ptr = looptris[i++]; @@ -1612,7 +1610,6 @@ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_ BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, NULL); - BLI_edgehash_free(pf_ehash, NULL); } *r_looptris_tot = i; diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 313caac1243..4ec8ea59018 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -27,7 +27,6 @@ * \ingroup bmesh */ -struct EdgeHash; struct Heap; #include "BLI_compiler_attrs.h" @@ -83,7 +82,7 @@ void BM_face_triangulate( const int quad_method, const int ngon_method, const bool use_tag, struct MemArena *pf_arena, - struct Heap *pf_heap, struct EdgeHash *pf_ehash + struct Heap *pf_heap ) ATTR_NONNULL(1, 2); void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index 9bb67ed9341..80774323d31 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -41,7 +41,6 @@ #include "BLI_heap.h" #include "BLI_polyfill2d.h" #include "BLI_polyfill2d_beautify.h" -#include "BLI_edgehash.h" #include "BLI_linklist.h" #include "bmesh.h" @@ -77,7 +76,7 @@ static bool bm_face_split_by_concave( BMesh *bm, BMFace *f_base, const float eps, MemArena *pf_arena, - struct Heap *pf_heap, struct EdgeHash *pf_ehash) + struct Heap *pf_heap) { const int f_base_len = f_base->len; int faces_array_tot = f_base_len - 3; @@ -99,7 +98,7 @@ static bool bm_face_split_by_concave( &faces_double, quad_method, ngon_method, false, pf_arena, - pf_heap, pf_ehash); + pf_heap); BLI_assert(edges_array_tot <= f_base_len - 3); @@ -161,7 +160,6 @@ static bool bm_face_split_by_concave( } BLI_heap_clear(pf_heap, NULL); - BLI_edgehash_clear_ex(pf_ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE); while (faces_double) { LinkNode *next = faces_double->next; @@ -201,17 +199,15 @@ void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op) MemArena *pf_arena; Heap *pf_heap; - EdgeHash *pf_ehash; pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE); BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (f->len > 3 && bm_face_convex_tag_verts(f)) { if (bm_face_split_by_concave( bm, f, FLT_EPSILON, - pf_arena, pf_heap, pf_ehash)) + pf_arena, pf_heap)) { changed = true; } @@ -225,5 +221,4 @@ void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op) BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, NULL); - BLI_edgehash_free(pf_ehash, NULL); } diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 36ae7231f94..d734d9b6ae1 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -497,7 +497,7 @@ static bool bm_face_triangulate( MemArena *pf_arena, /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ - struct Heap *pf_heap, struct EdgeHash *pf_ehash) + struct Heap *pf_heap) { const int f_base_len = f_base->len; int faces_array_tot = f_base_len - 3; @@ -516,8 +516,7 @@ static bool bm_face_triangulate( edges_array, &edges_array_tot, r_faces_double, quad_method, ngon_method, false, - pf_arena, - pf_heap, pf_ehash); + pf_arena, pf_heap); for (int i = 0; i < edges_array_tot; i++) { BMLoop *l_iter, *l_first; @@ -567,19 +566,16 @@ static bool bm_decim_triangulate_begin(BMesh *bm, int *r_edges_tri_tot) { MemArena *pf_arena; Heap *pf_heap; - EdgeHash *pf_ehash; LinkNode *faces_double = NULL; if (has_ngon) { pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE); } else { pf_arena = NULL; pf_heap = NULL; - pf_ehash = NULL; } /* adding new faces as we loop over faces @@ -591,8 +587,7 @@ static bool bm_decim_triangulate_begin(BMesh *bm, int *r_edges_tri_tot) bm, f, &faces_double, r_edges_tri_tot, - pf_arena, - pf_heap, pf_ehash); + pf_arena, pf_heap); } } @@ -606,7 +601,6 @@ static bool bm_decim_triangulate_begin(BMesh *bm, int *r_edges_tri_tot) if (has_ngon) { BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, NULL); - BLI_edgehash_free(pf_ehash, NULL); } BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c index ce1bc46d5e8..bd201fa89bf 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.c +++ b/source/blender/bmesh/tools/bmesh_triangulate.c @@ -35,7 +35,6 @@ #include "BLI_alloca.h" #include "BLI_memarena.h" #include "BLI_heap.h" -#include "BLI_edgehash.h" #include "BLI_linklist.h" /* only for defines */ @@ -57,7 +56,7 @@ static void bm_face_triangulate_mapping( MemArena *pf_arena, /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ - struct Heap *pf_heap, struct EdgeHash *pf_ehash) + struct Heap *pf_heap) { int faces_array_tot = face->len - 3; BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot); @@ -71,7 +70,7 @@ static void bm_face_triangulate_mapping( &faces_double, quad_method, ngon_method, use_tag, pf_arena, - pf_heap, pf_ehash); + pf_heap); if (faces_array_tot) { int i; @@ -98,17 +97,14 @@ void BM_mesh_triangulate( BMFace *face; MemArena *pf_arena; Heap *pf_heap; - EdgeHash *pf_ehash; pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) { pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE); } else { pf_heap = NULL; - pf_ehash = NULL; } if (slot_facemap_out) { @@ -120,8 +116,7 @@ void BM_mesh_triangulate( bm, face, quad_method, ngon_method, tag_only, op, slot_facemap_out, slot_facemap_double_out, - pf_arena, - pf_heap, pf_ehash); + pf_arena, pf_heap); } } } @@ -138,8 +133,7 @@ void BM_mesh_triangulate( NULL, NULL, &faces_double, quad_method, ngon_method, tag_only, - pf_arena, - pf_heap, pf_ehash); + pf_arena, pf_heap); } } } @@ -156,6 +150,5 @@ void BM_mesh_triangulate( if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) { BLI_heap_free(pf_heap, NULL); - BLI_edgehash_free(pf_ehash, NULL); } } diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc index df98ead4cb9..235bae3e5ff 100644 --- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc +++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc @@ -13,7 +13,6 @@ extern "C" { #include "BLI_array_utils.h" #include "BLI_polyfill2d.h" #include "BLI_math.h" -#include "BLI_edgehash.h" #include "MEM_guardedalloc.h" #ifdef USE_OBJ_PREVIEW @@ -195,17 +194,15 @@ static void test_polyfill_template( { MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - EdgeHash *pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE); BLI_polyfill_beautify( poly, poly_tot, tris, - pf_arena, pf_heap, pf_ehash); + pf_arena, pf_heap); test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot); BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, NULL); - BLI_edgehash_free(pf_ehash, NULL); } #endif }