Merge remote-tracking branch 'origin/blender-v2.93-release'
authorSybren A. Stüvel <sybren@blender.org>
Thu, 20 May 2021 11:00:07 +0000 (13:00 +0200)
committerSybren A. Stüvel <sybren@blender.org>
Thu, 20 May 2021 11:00:07 +0000 (13:00 +0200)
675 files changed:
.clang-format
build_files/build_environment/CMakeLists.txt
build_files/build_environment/cmake/boost.cmake
build_files/build_environment/cmake/embree.cmake
build_files/build_environment/cmake/gmp.cmake
build_files/build_environment/cmake/harvest.cmake
build_files/build_environment/cmake/llvm.cmake
build_files/build_environment/cmake/opencolorio.cmake
build_files/build_environment/cmake/options.cmake
build_files/build_environment/cmake/png.cmake
build_files/build_environment/cmake/sse2neon.cmake
build_files/build_environment/cmake/ssl.cmake
build_files/build_environment/cmake/ssl.conf
build_files/build_environment/cmake/tbb.cmake
build_files/build_environment/cmake/versions.cmake
build_files/build_environment/cmake/x264.cmake
build_files/build_environment/install_deps.sh
build_files/build_environment/patches/cmakelists_tbb.txt
build_files/build_environment/patches/tbb.diff
build_files/build_environment/patches/theora.diff
build_files/build_environment/patches/usd.diff
build_files/buildbot/buildbot_utils.py
build_files/cmake/Modules/FindEmbree.cmake
build_files/cmake/macros.cmake
doc/doxygen/Doxyfile
doc/python_api/examples/bpy.types.RenderEngine.py
doc/python_api/examples/gpu.4.py
doc/python_api/examples/gpu.6.py
doc/python_api/examples/gpu.7.py
doc/python_api/examples/gpu.8.py
doc/python_api/examples/gpu.9.py
doc/python_api/examples/mathutils.Matrix.LocRotScale.py [new file with mode: 0644]
doc/python_api/examples/mathutils.Matrix.py
doc/python_api/rst/info_gotcha.rst
doc/python_api/sphinx_doc_gen.py
intern/clog/clog.c
intern/cycles/app/CMakeLists.txt
intern/cycles/blender/addon/engine.py
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/device/device_optix.cpp
intern/cycles/graph/node.cpp
intern/cycles/graph/node.h
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/bvh/bvh.h
intern/cycles/kernel/bvh/bvh_shadow_all.h
intern/cycles/kernel/bvh/bvh_util.h [new file with mode: 0644]
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/CMakeLists.txt
intern/cycles/render/alembic.cpp
intern/cycles/render/alembic.h
intern/cycles/render/alembic_read.cpp [new file with mode: 0644]
intern/cycles/render/alembic_read.h [new file with mode: 0644]
intern/cycles/render/background.cpp
intern/cycles/render/geometry.cpp
intern/cycles/render/geometry.h
intern/cycles/render/light.cpp
intern/cycles/render/osl.cpp
intern/cycles/render/osl.h
intern/cycles/render/scene.cpp
intern/cycles/render/shader.cpp
intern/cycles/render/shader.h
intern/cycles/render/svm.cpp
intern/cycles/render/svm.h
intern/cycles/util/util_math_fast.h
intern/cycles/util/util_simd.h
intern/cycles/util/util_sseb.h
intern/cycles/util/util_ssef.h
intern/cycles/util/util_ssei.h
intern/cycles/util/util_texture.h
intern/ffmpeg/ffmpeg_compat.h
intern/ghost/CMakeLists.txt
intern/ghost/GHOST_C-api.h
intern/ghost/GHOST_IXrContext.h
intern/ghost/GHOST_Types.h
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_DropTargetX11.cpp
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_Util.h [new file with mode: 0644]
intern/ghost/intern/GHOST_XrAction.cpp [new file with mode: 0644]
intern/ghost/intern/GHOST_XrAction.h [new file with mode: 0644]
intern/ghost/intern/GHOST_XrContext.cpp
intern/ghost/intern/GHOST_XrContext.h
intern/ghost/intern/GHOST_XrException.h
intern/ghost/intern/GHOST_XrSession.cpp
intern/ghost/intern/GHOST_XrSession.h
intern/ghost/intern/GHOST_Xr_intern.h
intern/ghost/test/gears/GHOST_C-Test.c
intern/ghost/test/multitest/MultiTest.c
release/datafiles/locale
release/datafiles/splash.png
release/scripts/addons
release/scripts/addons_contrib
release/scripts/modules/addon_utils.py
release/scripts/modules/bl_ui_utils/bug_report_url.py
release/scripts/modules/bpy/path.py
release/scripts/modules/bpy_extras/asset_utils.py
release/scripts/modules/bpy_types.py
release/scripts/modules/gpu_extras/presets.py
release/scripts/modules/keyingsets_utils.py
release/scripts/modules/rna_manual_reference.py
release/scripts/modules/rna_prop_ui.py
release/scripts/modules/sys_info.py
release/scripts/presets/keyconfig/keymap_data/blender_default.py
release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
release/scripts/startup/bl_operators/clip.py
release/scripts/startup/bl_operators/constraint.py
release/scripts/startup/bl_operators/node.py
release/scripts/startup/bl_operators/userpref.py
release/scripts/startup/bl_operators/view3d.py
release/scripts/startup/bl_ui/properties_data_bone.py
release/scripts/startup/bl_ui/properties_data_gpencil.py
release/scripts/startup/bl_ui/properties_grease_pencil_common.py
release/scripts/startup/bl_ui/properties_material.py
release/scripts/startup/bl_ui/properties_material_gpencil.py
release/scripts/startup/bl_ui/properties_object.py
release/scripts/startup/bl_ui/properties_paint_common.py
release/scripts/startup/bl_ui/space_info.py
release/scripts/startup/bl_ui/space_topbar.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
release/scripts/startup/keyingsets_builtins.py
release/scripts/startup/nodeitems_builtins.py
release/scripts/templates_py/operator_modal_draw.py
source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/BKE_attribute_access.hh
source/blender/blenkernel/BKE_attribute_math.hh
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenkernel/BKE_callbacks.h
source/blender/blenkernel/BKE_context.h
source/blender/blenkernel/BKE_geometry_set.h
source/blender/blenkernel/BKE_geometry_set.hh
source/blender/blenkernel/BKE_gpencil.h
source/blender/blenkernel/BKE_lib_override.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_mesh_sample.hh [new file with mode: 0644]
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_nla.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_node_ui_storage.hh
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/BKE_persistent_data_handle.hh [deleted file]
source/blender/blenkernel/BKE_softbody.h
source/blender/blenkernel/BKE_spline.hh [new file with mode: 0644]
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/intern/DerivedMesh.cc
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim_data.c
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/appdir.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/attribute_access.cc
source/blender/blenkernel/intern/attribute_access_intern.hh
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/blendfile.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/context.c
source/blender/blenkernel/intern/curve_eval.cc [new file with mode: 0644]
source/blender/blenkernel/intern/curveprofile.c
source/blender/blenkernel/intern/displist.cc [moved from source/blender/blenkernel/intern/displist.c with 87% similarity]
source/blender/blenkernel/intern/geometry_component_curve.cc [new file with mode: 0644]
source/blender/blenkernel/intern/geometry_component_instances.cc
source/blender/blenkernel/intern/geometry_component_mesh.cc
source/blender/blenkernel/intern/geometry_component_pointcloud.cc
source/blender/blenkernel/intern/geometry_set.cc
source/blender/blenkernel/intern/geometry_set_instances.cc
source/blender/blenkernel/intern/gpencil.c
source/blender/blenkernel/intern/gpencil_curve.c
source/blender/blenkernel/intern/gpencil_geom.c
source/blender/blenkernel/intern/lib_id.c
source/blender/blenkernel/intern/lib_id_test.cc [new file with mode: 0644]
source/blender/blenkernel/intern/lib_override.c
source/blender/blenkernel/intern/lib_query.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball_tessellate.c
source/blender/blenkernel/intern/mesh_convert.c
source/blender/blenkernel/intern/mesh_sample.cc [new file with mode: 0644]
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/nla.c
source/blender/blenkernel/intern/node.cc
source/blender/blenkernel/intern/node_ui_storage.cc
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/object_dupli.cc
source/blender/blenkernel/intern/pbvh_intern.h
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/spline_base.cc [new file with mode: 0644]
source/blender/blenkernel/intern/spline_bezier.cc [new file with mode: 0644]
source/blender/blenkernel/intern/spline_nurbs.cc [new file with mode: 0644]
source/blender/blenkernel/intern/spline_poly.cc [new file with mode: 0644]
source/blender/blenkernel/intern/volume.cc
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenkernel/nla_private.h
source/blender/blenlib/BLI_compiler_attrs.h
source/blender/blenlib/BLI_enumerable_thread_specific.hh [new file with mode: 0644]
source/blender/blenlib/BLI_fileops.h
source/blender/blenlib/BLI_float3.hh
source/blender/blenlib/BLI_float4x4.hh
source/blender/blenlib/BLI_hash.hh
source/blender/blenlib/BLI_linear_allocator.hh
source/blender/blenlib/BLI_map.hh
source/blender/blenlib/BLI_map_slots.hh
source/blender/blenlib/BLI_math_color.h
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/BLI_math_matrix.h
source/blender/blenlib/BLI_math_solvers.h
source/blender/blenlib/BLI_math_vector.h
source/blender/blenlib/BLI_span.hh
source/blender/blenlib/BLI_stack.hh
source/blender/blenlib/BLI_vector.hh
source/blender/blenlib/BLI_vector_set.hh
source/blender/blenlib/BLI_virtual_array.hh
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/intern/BLI_dial_2d.c
source/blender/blenlib/intern/math_geom.c
source/blender/blenlib/intern/mesh_intersect.cc
source/blender/blenlib/intern/storage.c
source/blender/blenlib/intern/uvproject.c
source/blender/blenlib/tests/BLI_linear_allocator_test.cc
source/blender/blenlib/tests/BLI_map_test.cc
source/blender/blenlib/tests/BLI_stack_cxx_test.cc
source/blender/blenlib/tests/BLI_vector_set_test.cc
source/blender/blenlib/tests/BLI_vector_test.cc
source/blender/blenlib/tests/BLI_virtual_array_test.cc
source/blender/blenloader/CMakeLists.txt
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/versioning_290.c
source/blender/blenloader/intern/versioning_300.c [new file with mode: 0644]
source/blender/blenloader/intern/versioning_legacy.c
source/blender/bmesh/intern/bmesh_polygon_edgenet.c
source/blender/bmesh/tools/bmesh_bisect_plane.c
source/blender/compositor/COM_defines.h
source/blender/compositor/intern/COM_ChunkOrderHotspot.cc
source/blender/compositor/intern/COM_Debug.cc
source/blender/compositor/intern/COM_Debug.h
source/blender/compositor/intern/COM_MemoryBuffer.cc
source/blender/compositor/intern/COM_MemoryBuffer.h
source/blender/compositor/intern/COM_WorkScheduler.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/draw/CMakeLists.txt
source/blender/draw/engines/eevee/eevee_cryptomatte.c
source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/eevee/eevee_volumes.c
source/blender/draw/engines/gpencil/gpencil_cache_utils.c
source/blender/draw/engines/gpencil/gpencil_draw_data.c
source/blender/draw/engines/gpencil/gpencil_shader_fx.c
source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
source/blender/draw/engines/overlay/overlay_armature.c
source/blender/draw/engines/overlay/overlay_gpencil.c
source/blender/draw/engines/overlay/overlay_paint.c
source/blender/draw/engines/overlay/overlay_particle.c
source/blender/draw/engines/workbench/workbench_materials.c
source/blender/draw/engines/workbench/workbench_volume.c
source/blender/draw/intern/draw_cache_extract.h
source/blender/draw/intern/draw_cache_impl_gpencil.c
source/blender/draw/tests/draw_testing.cc [new file with mode: 0644]
source/blender/draw/tests/draw_testing.hh [new file with mode: 0644]
source/blender/draw/tests/shaders_test.cc
source/blender/editors/armature/CMakeLists.txt
source/blender/editors/armature/armature_add.c
source/blender/editors/armature/pose_slide.c
source/blender/editors/curve/editcurve.c
source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
source/blender/editors/gpencil/CMakeLists.txt
source/blender/editors/gpencil/annotate_paint.c
source/blender/editors/gpencil/gpencil_add_blank.c [new file with mode: 0644]
source/blender/editors/gpencil/gpencil_add_lineart.c
source/blender/editors/gpencil/gpencil_add_monkey.c
source/blender/editors/gpencil/gpencil_add_stroke.c
source/blender/editors/gpencil/gpencil_convert.c
source/blender/editors/gpencil/gpencil_data.c
source/blender/editors/gpencil/gpencil_edit.c
source/blender/editors/gpencil/gpencil_fill.c
source/blender/editors/gpencil/gpencil_intern.h
source/blender/editors/gpencil/gpencil_interpolate.c
source/blender/editors/gpencil/gpencil_ops.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/gpencil/gpencil_primitive.c
source/blender/editors/gpencil/gpencil_trace_ops.c
source/blender/editors/gpencil/gpencil_utils.c
source/blender/editors/include/ED_fileselect.h
source/blender/editors/include/ED_gizmo_library.h
source/blender/editors/include/ED_gpencil.h
source/blender/editors/include/ED_keyframing.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_transform_snap_object_context.h
source/blender/editors/include/UI_interface.h
source/blender/editors/include/UI_resources.h
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_ops.c
source/blender/editors/interface/interface_region_menu_popup.c
source/blender/editors/interface/interface_region_tooltip.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/io/io_alembic.c
source/blender/editors/io/io_collada.c
source/blender/editors/io/io_gpencil_export.c
source/blender/editors/io/io_gpencil_import.c
source/blender/editors/mask/mask_shapekey.c
source/blender/editors/mesh/editmesh_bevel.c
source/blender/editors/mesh/editmesh_intersect.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/editmesh_utils.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modes.c
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_relations.c
source/blender/editors/render/render_preview.c
source/blender/editors/screen/area.c
source/blender/editors/screen/screen_draw.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_geometry.c
source/blender/editors/screen/screen_intern.h
source/blender/editors/screen/screen_ops.c
source/blender/editors/screen/screendump.c
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_intern.h
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_buttons/buttons_intern.h
source/blender/editors/space_buttons/buttons_texture.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/file_intern.h
source/blender/editors/space_file/file_ops.c
source/blender/editors/space_file/filelist.c
source/blender/editors/space_file/space_file.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_info/info_ops.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_info/space_info.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_relationships.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_spreadsheet/space_spreadsheet.cc
source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_gizmo_ruler.c
source/blender/editors/space_view3d/view3d_placement.c
source/blender/editors/space_view3d/view3d_walk.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_convert.c
source/blender/editors/transform/transform_convert.h
source/blender/editors/transform/transform_convert_cursor.c
source/blender/editors/transform/transform_convert_curve.c
source/blender/editors/transform/transform_convert_mball.c
source/blender/editors/transform/transform_convert_mesh.c
source/blender/editors/transform/transform_convert_mesh_skin.c
source/blender/editors/transform/transform_convert_sequencer.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_mode.c
source/blender/editors/transform/transform_mode.h
source/blender/editors/transform/transform_mode_curveshrinkfatten.c
source/blender/editors/transform/transform_mode_edge_rotate_normal.c
source/blender/editors/transform/transform_mode_gpopacity.c
source/blender/editors/transform/transform_mode_gpshrinkfatten.c
source/blender/editors/transform/transform_mode_maskshrinkfatten.c
source/blender/editors/transform/transform_mode_mirror.c
source/blender/editors/transform/transform_mode_resize.c
source/blender/editors/transform/transform_mode_rotate.c
source/blender/editors/transform/transform_mode_shear.c
source/blender/editors/transform/transform_mode_skin_resize.c
source/blender/editors/transform/transform_mode_translate.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/transform/transform_snap_object.c
source/blender/functions/FN_cpp_type.hh
source/blender/functions/FN_generic_pointer.hh
source/blender/functions/FN_generic_span.hh
source/blender/functions/FN_generic_value_map.hh
source/blender/functions/FN_generic_vector_array.hh
source/blender/functions/FN_generic_virtual_array.hh
source/blender/functions/FN_generic_virtual_vector_array.hh
source/blender/functions/FN_multi_function_params.hh
source/blender/functions/intern/generic_vector_array.cc
source/blender/functions/intern/generic_virtual_array.cc
source/blender/functions/intern/generic_virtual_vector_array.cc
source/blender/functions/intern/multi_function_network_evaluation.cc
source/blender/functions/tests/FN_multi_function_network_test.cc
source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
source/blender/gpu/GPU_capabilities.h
source/blender/gpu/GPU_common.h
source/blender/gpu/GPU_framebuffer.h
source/blender/gpu/GPU_platform.h
source/blender/gpu/GPU_texture.h
source/blender/gpu/intern/gpu_capabilities.cc
source/blender/gpu/intern/gpu_capabilities_private.hh
source/blender/gpu/intern/gpu_context.cc
source/blender/gpu/intern/gpu_debug.cc
source/blender/gpu/intern/gpu_framebuffer.cc
source/blender/gpu/intern/gpu_framebuffer_private.hh
source/blender/gpu/intern/gpu_matrix.cc
source/blender/gpu/intern/gpu_platform.cc
source/blender/gpu/intern/gpu_platform_private.hh
source/blender/gpu/intern/gpu_shader.cc
source/blender/gpu/intern/gpu_state.cc
source/blender/gpu/intern/gpu_texture.cc
source/blender/gpu/intern/gpu_texture_private.hh
source/blender/gpu/opengl/gl_backend.cc
source/blender/gpu/opengl/gl_batch.cc
source/blender/gpu/opengl/gl_batch.hh
source/blender/gpu/opengl/gl_immediate.hh
source/blender/gpu/tests/gpu_testing.cc
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/intern/IMB_anim.h
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/indexer.c
source/blender/imbuf/intern/tiff.c
source/blender/imbuf/intern/util.c
source/blender/io/alembic/ABC_alembic.h
source/blender/io/alembic/exporter/abc_writer_mesh.cc
source/blender/io/alembic/intern/abc_customdata.cc
source/blender/io/alembic/intern/abc_customdata.h
source/blender/io/alembic/intern/abc_reader_mesh.cc
source/blender/io/collada/Materials.cpp
source/blender/io/collada/Materials.h
source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
source/blender/io/gpencil/nanosvg/nanosvg.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_boid_types.h
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_effect_types.h
source/blender/makesdna/DNA_gpencil_modifier_defaults.h
source/blender/makesdna/DNA_gpencil_modifier_types.h
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_object_force_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_pointcache_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesdna/DNA_xr_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_define.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_ID.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_attribute.c
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_define.c
source/blender/makesrna/intern/rna_fcurve.c
source/blender/makesrna/intern/rna_gpencil.c
source/blender/makesrna/intern/rna_gpencil_modifier.c
source/blender/makesrna/intern/rna_internal_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_pose.c
source/blender/makesrna/intern/rna_sculpt_paint.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/intern/MOD_armature.c
source/blender/modifiers/intern/MOD_array.c
source/blender/modifiers/intern/MOD_bevel.c
source/blender/modifiers/intern/MOD_boolean.cc
source/blender/modifiers/intern/MOD_build.c
source/blender/modifiers/intern/MOD_cast.c
source/blender/modifiers/intern/MOD_cloth.c
source/blender/modifiers/intern/MOD_collision.c
source/blender/modifiers/intern/MOD_correctivesmooth.c
source/blender/modifiers/intern/MOD_curve.c
source/blender/modifiers/intern/MOD_datatransfer.c
source/blender/modifiers/intern/MOD_decimate.c
source/blender/modifiers/intern/MOD_displace.c
source/blender/modifiers/intern/MOD_dynamicpaint.c
source/blender/modifiers/intern/MOD_edgesplit.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_fluid.c
source/blender/modifiers/intern/MOD_hook.c
source/blender/modifiers/intern/MOD_laplaciandeform.c
source/blender/modifiers/intern/MOD_laplaciansmooth.c
source/blender/modifiers/intern/MOD_lattice.c
source/blender/modifiers/intern/MOD_mask.cc
source/blender/modifiers/intern/MOD_mesh_to_volume.cc
source/blender/modifiers/intern/MOD_meshcache.c
source/blender/modifiers/intern/MOD_meshdeform.c
source/blender/modifiers/intern/MOD_meshsequencecache.c
source/blender/modifiers/intern/MOD_mirror.c
source/blender/modifiers/intern/MOD_multires.c
source/blender/modifiers/intern/MOD_nodes.cc
source/blender/modifiers/intern/MOD_nodes_evaluator.cc [new file with mode: 0644]
source/blender/modifiers/intern/MOD_nodes_evaluator.hh [new file with mode: 0644]
source/blender/modifiers/intern/MOD_none.c
source/blender/modifiers/intern/MOD_normal_edit.c
source/blender/modifiers/intern/MOD_ocean.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/modifiers/intern/MOD_particlesystem.c
source/blender/modifiers/intern/MOD_remesh.c
source/blender/modifiers/intern/MOD_screw.c
source/blender/modifiers/intern/MOD_shapekey.c
source/blender/modifiers/intern/MOD_shrinkwrap.c
source/blender/modifiers/intern/MOD_simpledeform.c
source/blender/modifiers/intern/MOD_skin.c
source/blender/modifiers/intern/MOD_smooth.c
source/blender/modifiers/intern/MOD_softbody.c
source/blender/modifiers/intern/MOD_solidify.c
source/blender/modifiers/intern/MOD_subsurf.c
source/blender/modifiers/intern/MOD_surface.c
source/blender/modifiers/intern/MOD_surfacedeform.c
source/blender/modifiers/intern/MOD_triangulate.c
source/blender/modifiers/intern/MOD_uvproject.c
source/blender/modifiers/intern/MOD_uvwarp.c
source/blender/modifiers/intern/MOD_volume_displace.cc
source/blender/modifiers/intern/MOD_volume_to_mesh.cc
source/blender/modifiers/intern/MOD_warp.c
source/blender/modifiers/intern/MOD_wave.c
source/blender/modifiers/intern/MOD_weighted_normal.c
source/blender/modifiers/intern/MOD_weightvgedit.c
source/blender/modifiers/intern/MOD_weightvgmix.c
source/blender/modifiers/intern/MOD_weightvgproximity.c
source/blender/modifiers/intern/MOD_weld.c
source/blender/modifiers/intern/MOD_wireframe.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_derived_node_tree.hh
source/blender/nodes/NOD_geometry.h
source/blender/nodes/NOD_geometry_exec.hh
source/blender/nodes/NOD_static_types.h
source/blender/nodes/NOD_type_conversions.hh
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/geometry/node_geometry_tree.cc
source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc
source/blender/nodes/geometry/nodes/node_geo_attribute_vector_rotate.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
source/blender/nodes/geometry/nodes/node_geo_input_material.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
source/blender/nodes/geometry/nodes/node_geo_material_assign.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
source/blender/nodes/geometry/nodes/node_geo_object_info.cc
source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc
source/blender/nodes/geometry/nodes/node_geo_point_scale.cc
source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
source/blender/nodes/geometry/nodes/node_geo_point_translate.cc
source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
source/blender/nodes/geometry/nodes/node_geo_switch.cc [new file with mode: 0644]
source/blender/nodes/geometry/nodes/node_geo_transform.cc
source/blender/nodes/intern/node_geometry_exec.cc
source/blender/nodes/intern/node_socket.cc
source/blender/nodes/intern/node_tree_ref.cc
source/blender/nodes/intern/node_util.c
source/blender/nodes/intern/type_conversions.cc
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/texture/node_texture_tree.c
source/blender/python/bmesh/bmesh_py_types.c
source/blender/python/generic/idprop_py_api.c
source/blender/python/generic/idprop_py_api.h
source/blender/python/gpu/CMakeLists.txt
source/blender/python/gpu/gpu_py_api.c
source/blender/python/gpu/gpu_py_buffer.c
source/blender/python/gpu/gpu_py_capabilities.c [new file with mode: 0644]
source/blender/python/gpu/gpu_py_capabilities.h [new file with mode: 0644]
source/blender/python/gpu/gpu_py_framebuffer.c
source/blender/python/gpu/gpu_py_framebuffer.h
source/blender/python/gpu/gpu_py_offscreen.c
source/blender/python/gpu/gpu_py_platform.c [new file with mode: 0644]
source/blender/python/gpu/gpu_py_platform.h [new file with mode: 0644]
source/blender/python/gpu/gpu_py_state.c
source/blender/python/gpu/gpu_py_texture.c
source/blender/python/gpu/gpu_py_texture.h
source/blender/python/intern/CMakeLists.txt
source/blender/python/intern/bpy_app_handlers.c
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_operator.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna_operator.c [new file with mode: 0644]
source/blender/python/intern/bpy_rna_operator.h [new file with mode: 0644]
source/blender/python/intern/bpy_rna_types_capi.c
source/blender/python/mathutils/mathutils.c
source/blender/python/mathutils/mathutils_Euler.c
source/blender/python/mathutils/mathutils_Matrix.c
source/blender/python/mathutils/mathutils_interpolate.c
source/blender/python/mathutils/mathutils_kdtree.c
source/blender/render/intern/zbuf.c
source/blender/sequencer/SEQ_iterator.h
source/blender/sequencer/SEQ_sequencer.h
source/blender/sequencer/SEQ_utils.h
source/blender/sequencer/intern/effects.c
source/blender/sequencer/intern/iterator.c
source/blender/sequencer/intern/render.c
source/blender/sequencer/intern/render.h
source/blender/sequencer/intern/sequencer.c
source/blender/sequencer/intern/strip_add.c
source/blender/sequencer/intern/strip_edit.c
source/blender/sequencer/intern/strip_time.c
source/blender/sequencer/intern/utils.c
source/blender/shader_fx/intern/FX_shader_glow.c
source/blender/windowmanager/CMakeLists.txt
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_cursors.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_playanim.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm_files.h
source/blender/windowmanager/xr/intern/wm_xr.c
source/blender/windowmanager/xr/intern/wm_xr_actions.c [new file with mode: 0644]
source/blender/windowmanager/xr/intern/wm_xr_draw.c
source/blender/windowmanager/xr/intern/wm_xr_intern.h
source/blender/windowmanager/xr/intern/wm_xr_session.c
source/creator/CMakeLists.txt
source/creator/creator.c
source/creator/creator_args.c
source/creator/creator_intern.h
tests/python/bl_blendfile_library_overrides.py
tests/python/bl_pyapi_idprop.py
tests/python/bl_pyapi_mathutils.py
tests/python/compositor_render_tests.py
tests/python/operators.py

index b61ce6018d3e8c3fcfd93cb13250850fe6c7e8a7..9cc3cdeaaf8529a96eeb6fa948a137db2631857c 100644 (file)
@@ -255,6 +255,7 @@ ForEachMacros:
   - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
   - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
   - SEQ_ALL_BEGIN
+  - SEQ_ITERATOR_FOREACH
   - SURFACE_QUAD_ITER_BEGIN
   - foreach
   - ED_screen_areas_iter
index a3d694b4bc323b09819ea17698ba5e7c67ed39db..fb79eee62be46eefa407f86d6ab151a779a87a92 100644 (file)
@@ -113,7 +113,7 @@ include(cmake/expat.cmake)
 include(cmake/yamlcpp.cmake)
 include(cmake/opencolorio.cmake)
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
+if(BLENDER_PLATFORM_ARM)
   include(cmake/sse2neon.cmake)
 endif()
 
index 8b36af7dc41ea6db33028e08110f46b5cd1eb44f..5170a3a123eef413514cff844425a2e5a92a538d 100644 (file)
 
 set(BOOST_ADDRESS_MODEL 64)
 
+if(BLENDER_PLATFORM_ARM)
+  set(BOOST_ARCHITECTURE arm)
+else()
+  set(BOOST_ARCHITECTURE x86)
+endif()
+
 if(WIN32)
   set(BOOST_TOOLSET toolset=msvc-14.1)
   set(BOOST_COMPILER_STRING -vc141)
@@ -29,7 +35,6 @@ if(WIN32)
   if(BUILD_MODE STREQUAL Release)
     set(BOOST_HARVEST_CMD ${BOOST_HARVEST_CMD} && ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/include/boost-${BOOST_VERSION_NODOTS_SHORT}/ ${HARVEST_TARGET}/boost/include/)
   endif()
-
 elseif(APPLE)
   set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh)
   set(BOOST_BUILD_COMMAND ./b2)
@@ -93,7 +98,7 @@ ExternalProject_Add(external_boost
   UPDATE_COMMAND  ""
   PATCH_COMMAND ${BOOST_PATCH_COMMAND}
   CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND}
-  BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=x86 address-model=${BOOST_ADDRESS_MODEL} link=static threading=multi ${BOOST_OPTIONS}    --prefix=${LIBDIR}/boost install
+  BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=${BOOST_ARCHITECTURE} address-model=${BOOST_ADDRESS_MODEL} link=static threading=multi ${BOOST_OPTIONS}    --prefix=${LIBDIR}/boost install
   BUILD_IN_SOURCE 1
   INSTALL_COMMAND "${BOOST_HARVEST_CMD}"
 )
index 4830630def0798f0525419d0433adb6f19927554..cd693d766dca53d52f5b2f9a28dc0166d9dfddcb 100644 (file)
@@ -47,7 +47,7 @@ else()
   set(EMBREE_BUILD_DIR)
 endif()
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
+if(BLENDER_PLATFORM_ARM)
   ExternalProject_Add(external_embree
     GIT_REPOSITORY ${EMBREE_ARM_GIT}
     GIT_TAG "blender-arm"
index 323630a63aab9f7b69d564664e5535adb668fa44..6ca81678a32beef2029bddd1752c58e45d545075 100644 (file)
@@ -25,19 +25,12 @@ else()
   set(GMP_OPTIONS --enable-static --disable-shared )
 endif()
 
-if(APPLE)
-  if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
-    set(GMP_OPTIONS
-      ${GMP_OPTIONS}
-      --disable-assembly
-    )
-  else()
-    set(GMP_OPTIONS
-      ${GMP_OPTIONS}
-      --with-pic
-    )
-  endif()
-elseif(UNIX)
+if(APPLE AND NOT BLENDER_PLATFORM_ARM)
+  set(GMP_OPTIONS
+    ${GMP_OPTIONS}
+    --with-pic
+  )
+elseif(UNIX AND NOT APPLE)
   set(GMP_OPTIONS
     ${GMP_OPTIONS}
     --with-pic
@@ -45,6 +38,13 @@ elseif(UNIX)
   )
 endif()
 
+if(BLENDER_PLATFORM_ARM)
+  set(GMP_OPTIONS
+    ${GMP_OPTIONS}
+    --disable-assembly
+  )
+endif()
+
 ExternalProject_Add(external_gmp
   URL file://${PACKAGE_DIR}/${GMP_FILE}
   DOWNLOAD_DIR ${DOWNLOAD_DIR}
index 23d0dcbab7b88ada60db712930c348a89785e375..fc7e652a028dc286ab0f3a393a3ccacc2b964aa0 100644 (file)
@@ -109,9 +109,9 @@ harvest(llvm/lib llvm/lib "libclang*.a")
 if(APPLE)
   harvest(openmp/lib openmp/lib "*")
   harvest(openmp/include openmp/include "*.h")
-  if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
-    harvest(sse2neon sse2neon "*.h")
-  endif()
+endif()
+if(BLENDER_PLATFORM_ARM)
+  harvest(sse2neon sse2neon "*.h")
 endif()
 harvest(ogg/lib ffmpeg/lib "*.a")
 harvest(openal/include openal/include "*.h")
index f067267a4169ce44a8a8719bccd6a50b46e2aa45..cbb986410aa46e20ef127079d242dde252ae8b00 100644 (file)
@@ -16,7 +16,7 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
+if(BLENDER_PLATFORM_ARM)
   set(LLVM_TARGETS AArch64$<SEMICOLON>ARM)
 else()
   set(LLVM_TARGETS X86)
index bd03be5ebff45ff62b4cd9dfa8b84909d467f47e..28c93973cf53e757baeabb064aca5319633cc245 100644 (file)
@@ -36,7 +36,7 @@ set(OPENCOLORIO_EXTRA_ARGS
   -Dyaml-cpp_ROOT=${LIBDIR}/yamlcpp
 )
 
-if(APPLE AND NOT("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64"))
+if(BLENDER_PLATFORM_ARM)
   set(OPENCOLORIO_EXTRA_ARGS
     ${OPENCOLORIO_EXTRA_ARGS}
     -DOCIO_USE_SSE=OFF
index 486b3d1a80298706ea2f16a13105e01d1d693d87..8930bd70fabb3d044e5ca5fe3784c8549439eacf 100644 (file)
@@ -137,6 +137,10 @@ else()
     endif()
     set(OSX_SYSROOT ${XCODE_DEV_PATH}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk)
 
+    if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
+      set(BLENDER_PLATFORM_ARM ON)
+    endif()
+
     set(PLATFORM_CFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}")
     set(PLATFORM_CXXFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -std=c++11 -stdlib=libc++ -arch ${CMAKE_OSX_ARCHITECTURES}")
     set(PLATFORM_LDFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}")
@@ -151,6 +155,10 @@ else()
       -DCMAKE_OSX_SYSROOT:PATH=${OSX_SYSROOT}
     )
   else()
+    if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
+      set(BLENDER_PLATFORM_ARM ON)
+    endif()
+
     set(PLATFORM_CFLAGS "-fPIC")
     set(PLATFORM_CXXFLAGS "-std=c++11 -fPIC")
     set(PLATFORM_LDFLAGS)
index d9248b61c98872b9949e1eb6ff29c6e9ae730ed4..458d3a1fd987ad070328fcfca18b01f685065dee 100644 (file)
@@ -22,8 +22,8 @@ set(PNG_EXTRA_ARGS
   -DPNG_STATIC=ON
 )
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
-  set(PNG_EXTRA_ARGS ${PNG_EXTRA_ARGS} -DPNG_HARDWARE_OPTIMIZATIONS=ON -DPNG_ARM_NEON=on -DCMAKE_SYSTEM_PROCESSOR="aarch64")
+if(BLENDER_PLATFORM_ARM)
+  set(PNG_EXTRA_ARGS ${PNG_EXTRA_ARGS} -DPNG_HARDWARE_OPTIMIZATIONS=ON -DPNG_ARM_NEON=ON -DCMAKE_SYSTEM_PROCESSOR="aarch64")
 endif()
 
 ExternalProject_Add(external_png
index dca2d94f913d3325039cc01ea09f2715e879336b..d7987fdfd2f5712672f909c7da66df1596159273 100644 (file)
 #
 # ***** END GPL LICENSE BLOCK *****
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
-  ExternalProject_Add(external_sse2neon
-    GIT_REPOSITORY  ${SSE2NEON_GIT}
-    GIT_TAG ${SSE2NEON_GIT_HASH}
-    DOWNLOAD_DIR ${DOWNLOAD_DIR}
-    PREFIX ${BUILD_DIR}/sse2neon
-    CONFIGURE_COMMAND echo sse2neon - Nothing to configure
-    BUILD_COMMAND echo sse2neon - nothing to build
-    INSTALL_COMMAND mkdir -p ${LIBDIR}/sse2neon && cp ${BUILD_DIR}/sse2neon/src/external_sse2neon/sse2neon.h ${LIBDIR}/sse2neon
-    INSTALL_DIR ${LIBDIR}/sse2neon
-  )
-endif()
+ExternalProject_Add(external_sse2neon
+  GIT_REPOSITORY  ${SSE2NEON_GIT}
+  GIT_TAG ${SSE2NEON_GIT_HASH}
+  DOWNLOAD_DIR ${DOWNLOAD_DIR}
+  PREFIX ${BUILD_DIR}/sse2neon
+  CONFIGURE_COMMAND echo sse2neon - Nothing to configure
+  BUILD_COMMAND echo sse2neon - nothing to build
+  INSTALL_COMMAND mkdir -p ${LIBDIR}/sse2neon && cp ${BUILD_DIR}/sse2neon/src/external_sse2neon/sse2neon.h ${LIBDIR}/sse2neon
+  INSTALL_DIR ${LIBDIR}/sse2neon
+)
index 4426cc876c6e53382dfd536ad1d46a4442a1bf41..615b88167ece9e183bcd977f7fd302ff805d4aec 100644 (file)
@@ -22,7 +22,9 @@ set(SSL_PATCH_CMD echo .)
 if(APPLE)
   set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}")
 else()
-  if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+  if(BLENDER_PLATFORM_ARM)
+    set(SSL_OS_COMPILER "blender-linux-aarch64")
+  elseif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
     set(SSL_EXTRA_ARGS enable-ec_nistp_64_gcc_128)
     set(SSL_OS_COMPILER "blender-linux-x86_64")
   else()
index 8a9c9dcab4c60cf99595bbed0026be232993c351..fa59bcf282537878a180271110c14d1f7d01500e 100644 (file)
@@ -8,6 +8,11 @@ my %targets = (
     inherit_from     => [ "linux-x86_64" ],
     cflags => add("-fPIC"),
   },
+  "blender-linux-aarch64" => {
+    inherit_from     => [ "linux-aarch64" ],
+    cxxflags => add("-fPIC"),
+    cflags => add("-fPIC"),
+  },
   "blender-darwin-x86_64" => {
     inherit_from     => [ "darwin64-x86_64-cc" ],
     cflags => add("-fPIC"),
index b006898e6fdb2839ed5880b79de386c30b5168a5..44307cd2afba00879759094697afd8f51c046007 100644 (file)
@@ -21,6 +21,7 @@ if(WIN32)
     -DTBB_BUILD_TBBMALLOC=On
     -DTBB_BUILD_TBBMALLOC_PROXY=On
     -DTBB_BUILD_STATIC=Off
+    -DTBB_BUILD_TESTS=Off
   )
   set(TBB_LIBRARY tbb)
   set(TBB_STATIC_LIBRARY Off)
@@ -30,6 +31,7 @@ else()
     -DTBB_BUILD_TBBMALLOC=On
     -DTBB_BUILD_TBBMALLOC_PROXY=Off
     -DTBB_BUILD_STATIC=On
+    -DTBB_BUILD_TESTS=Off
   )
   set(TBB_LIBRARY tbb_static)
   set(TBB_STATIC_LIBRARY On)
@@ -42,7 +44,7 @@ ExternalProject_Add(external_tbb
   URL_HASH ${TBB_HASH_TYPE}=${TBB_HASH}
   PREFIX ${BUILD_DIR}/tbb
   PATCH_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_tbb.txt ${BUILD_DIR}/tbb/src/external_tbb/CMakeLists.txt &&
-  ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/tbb/src/external_tbb/build/vs2013/version_string.ver ${BUILD_DIR}/tbb/src/external_tbb/src/tbb/version_string.ver &&
+  ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/tbb/src/external_tbb/build/vs2013/version_string.ver ${BUILD_DIR}/tbb/src/external_tbb/build/version_string.ver.in &&
   ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/tbb/src/external_tbb < ${PATCH_DIR}/tbb.diff
   CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/tbb ${DEFAULT_CMAKE_FLAGS} ${TBB_EXTRA_ARGS}
   INSTALL_DIR ${LIBDIR}/tbb
index 97da5d54d48838b1e79837d991e1e0abef7cabb8..83e438614b67a06075e05788542f47567fa5280d 100644 (file)
@@ -152,7 +152,7 @@ set(OPENCOLORIO_HASH 1a2e3478b6cd9a1549f24e1b2205e3f0)
 set(OPENCOLORIO_HASH_TYPE MD5)
 set(OPENCOLORIO_FILE OpenColorIO-${OPENCOLORIO_VERSION}.tar.gz)
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
+if(BLENDER_PLATFORM_ARM)
   # Newer version required by ISPC with arm support.
   set(LLVM_VERSION 11.0.1)
   set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-project-${LLVM_VERSION}.src.tar.xz)
@@ -398,11 +398,20 @@ set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df)
 set(LZMA_HASH_TYPE SHA256)
 set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2)
 
-set(SSL_VERSION 1.1.1g)
-set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
-set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46)
-set(SSL_HASH_TYPE SHA256)
-set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
+if(BLENDER_PLATFORM_ARM)
+  # Need at least 1.1.1i for aarch64 support (https://github.com/openssl/openssl/pull/13218)
+  set(SSL_VERSION 1.1.1i)
+  set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
+  set(SSL_HASH e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242)
+  set(SSL_HASH_TYPE SHA256)
+  set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
+else()
+  set(SSL_VERSION 1.1.1g)
+  set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
+  set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46)
+  set(SSL_HASH_TYPE SHA256)
+  set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
+endif()
 
 set(SQLITE_VERSION 3.31.1)
 set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
@@ -453,7 +462,7 @@ set(XR_OPENXR_SDK_HASH 0df6b2fd6045423451a77ff6bc3e1a75)
 set(XR_OPENXR_SDK_HASH_TYPE MD5)
 set(XR_OPENXR_SDK_FILE OpenXR-SDK-${XR_OPENXR_SDK_VERSION}.tar.gz)
 
-if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
+if(BLENDER_PLATFORM_ARM)
   # Unreleased version with macOS arm support.
   set(ISPC_URI https://github.com/ispc/ispc/archive/f5949c055eb9eeb93696978a3da4bfb3a6a30b35.zip)
   set(ISPC_HASH d382fea18d01dbd0cd05d9e1ede36d7d)
index a32f119d1848c7aaa4bc1f9fc13784323cb5f3cf..08d698cc3ad77d45498ccaeb3ab6749ce79e8b63 100644 (file)
@@ -20,24 +20,16 @@ if(WIN32)
   set(X264_EXTRA_ARGS --enable-win32thread --cross-prefix=${MINGW_HOST}- --host=${MINGW_HOST})
 endif()
 
-
-if(APPLE)
-  if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
-    set(X264_EXTRA_ARGS ${X264_EXTRA_ARGS} "--disable-asm")
-    set(X264_CONFIGURE_ENV echo .)
-  else()
-    set(X264_CONFIGURE_ENV
-      export AS=${LIBDIR}/nasm/bin/nasm
-    )
-  endif()
-else()
-  set(X264_CONFIGURE_ENV echo .)
+if(BLENDER_PLATFORM_ARM)
+  set(X264_EXTRA_ARGS ${X264_EXTRA_ARGS} "--disable-asm")
 endif()
 
-if(UNIX AND NOT APPLE)
+if((APPLE AND NOT BLENDER_PLATFORM_ARM) OR (UNIX AND NOT APPLE))
   set(X264_CONFIGURE_ENV
     export AS=${LIBDIR}/nasm/bin/nasm
   )
+else()
+  set(X264_CONFIGURE_ENV echo .)
 endif()
 
 ExternalProject_Add(external_x264
index 7cd21b2885c9b9f90d92bf9a5e7d4a7518afb465..7d8c2ca3181fc43cd2817a603709ed0e286d92a6 100755 (executable)
@@ -1797,6 +1797,10 @@ compile_OCIO() {
     cmake_d="$cmake_d -D OCIO_BUILD_PYTHON=OFF"
     cmake_d="$cmake_d -D OCIO_BUILD_GPU_TESTS=OFF"
 
+    if [ $(uname -m) == "aarch64" ]; then
+      cmake_d="$cmake_d -D OCIO_USE_SSE=OFF"
+    fi
+
     if file /bin/cp | grep -q '32-bit'; then
       cflags="-fPIC -m32 -march=i686"
     else
@@ -2059,7 +2063,10 @@ compile_OIIO() {
     cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
     cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
     cmake_d="$cmake_d -D LINKSTATIC=OFF"
-    cmake_d="$cmake_d -D USE_SIMD=sse2"
+
+    if [ $(uname -m) != "aarch64" ]; then
+      cmake_d="$cmake_d -D USE_SIMD=sse2"
+    fi
 
     cmake_d="$cmake_d -D OPENEXR_VERSION=$OPENEXR_VERSION"
 
@@ -2079,7 +2086,7 @@ compile_OIIO() {
     cmake_d="$cmake_d -D USE_OPENCV=OFF"
     cmake_d="$cmake_d -D BUILD_TESTING=OFF"
     cmake_d="$cmake_d -D OIIO_BUILD_TESTS=OFF"
-    cmake_d="$cmake_d -D OIIO_BUILD_TOOLS=ON"
+    cmake_d="$cmake_d -D OIIO_BUILD_TOOLS=OFF"
     cmake_d="$cmake_d -D TXT2MAN="
     #cmake_d="$cmake_d -D CMAKE_EXPORT_COMPILE_COMMANDS=ON"
     #cmake_d="$cmake_d -D CMAKE_VERBOSE_MAKEFILE=ON"
@@ -2209,10 +2216,15 @@ compile_LLVM() {
     mkdir build
     cd build
 
+    LLVM_TARGETS="X86"
+    if [ $(uname -m) == "aarch64" ]; then
+      LLVM_TARGETS="AArch64"
+    fi
+
     cmake_d="-D CMAKE_BUILD_TYPE=Release"
     cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
     cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON"
-    cmake_d="$cmake_d -D LLVM_TARGETS_TO_BUILD=X86"
+    cmake_d="$cmake_d -D LLVM_TARGETS_TO_BUILD=$LLVM_TARGETS"
     cmake_d="$cmake_d -D LLVM_ENABLE_TERMINFO=OFF"
 
     if [ -d $_FFI_INCLUDE_DIR ]; then
@@ -2329,13 +2341,16 @@ compile_OSL() {
     cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
     cmake_d="$cmake_d -D OSL_BUILD_PLUGINS=OFF"
     cmake_d="$cmake_d -D OSL_BUILD_TESTS=OFF"
-    cmake_d="$cmake_d -D USE_SIMD=sse2"
     cmake_d="$cmake_d -D USE_LLVM_BITCODE=OFF"
     cmake_d="$cmake_d -D USE_PARTIO=OFF"
     cmake_d="$cmake_d -D OSL_BUILD_MATERIALX=OFF"
     cmake_d="$cmake_d -D USE_QT=OFF"
     cmake_d="$cmake_d -D USE_PYTHON=OFF"
 
+    if [ $(uname -m) != "aarch64" ]; then
+      cmake_d="$cmake_d -D USE_SIMD=sse2"
+    fi
+
     cmake_d="$cmake_d -D CMAKE_CXX_STANDARD=14"
 
     #~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
index 4032e5d6f8353b2a37adee7c4e51f8f0b4d0da4f..e05f27afdd6e3765b6b512c7092048470e0507e4 100644 (file)
@@ -1,5 +1,32 @@
-cmake_minimum_required (VERSION 2.8)
-project(tbb CXX)
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+if (POLICY CMP0048)
+  # cmake warns if loaded from a min-3.0-required parent dir, so silence the warning:
+  cmake_policy(SET CMP0048 NEW)
+endif()
+
+project (tbb CXX)
+
+include(CheckCXXCompilerFlag)
+include(CheckCXXSourceRuns)
+
+if(POLICY CMP0058)
+  cmake_policy(SET CMP0058 NEW)
+endif()
+
+if(POLICY CMP0068)
+  cmake_policy(SET CMP0068 NEW)
+endif()
+
+if (POLICY CMP0078)
+  # swig standard target names
+  cmake_policy(SET CMP0078 NEW)
+endif ()
+
+if (POLICY CMP0086)
+  # UseSWIG honors SWIG_MODULE_NAME via -module flag
+  cmake_policy(SET CMP0086 NEW)
+endif ()
 
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
   message(STATUS "Setting build type to 'Release' as none was specified.")
@@ -8,12 +35,36 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
     "MinSizeRel" "RelWithDebInfo")
 endif()
 
-include_directories(include src src/rml/include )
+if(NOT TBB_INSTALL_RUNTIME_DIR)
+  set(TBB_INSTALL_RUNTIME_DIR bin)
+endif()
+if(NOT TBB_INSTALL_LIBRARY_DIR)
+  set(TBB_INSTALL_LIBRARY_DIR lib)
+endif()
+if(NOT TBB_INSTALL_ARCHIVE_DIR)
+  set(TBB_INSTALL_ARCHIVE_DIR lib)
+endif()
+if(NOT TBB_INSTALL_INCLUDE_DIR)
+  set(TBB_INSTALL_INCLUDE_DIR include)
+endif()
+if(NOT TBB_CMAKE_PACKAGE_INSTALL_DIR)
+  set(TBB_CMAKE_PACKAGE_INSTALL_DIR lib/cmake/tbb)
+endif()
+
+include_directories(include src src/rml/include ${CMAKE_CURRENT_BINARY_DIR})
 
 option(TBB_BUILD_SHARED          "Build TBB shared library" ON)
 option(TBB_BUILD_STATIC          "Build TBB static library" ON)
 option(TBB_BUILD_TBBMALLOC       "Build TBB malloc library" ON)
 option(TBB_BUILD_TBBMALLOC_PROXY "Build TBB malloc proxy library" ON)
+option(TBB_BUILD_TESTS           "Build TBB tests and enable testing infrastructure" ON)
+option(TBB_NO_DATE               "Do not save the configure date in the version string" OFF)
+option(TBB_BUILD_PYTHON          "Build TBB Python bindings" OFF)
+option(TBB_SET_SOVERSION         "Set the SOVERSION (shared library build version suffix)?" OFF)
+
+# When this repository is part of a larger build system of a parent project
+# we may not want TBB to set up default installation targets
+option(TBB_INSTALL_TARGETS       "Include build targets for 'make install'" ON)
 
 if(APPLE)
   set(CMAKE_MACOSX_RPATH ON)
@@ -39,66 +90,143 @@ set(tbbmalloc_proxy_src
   src/tbbmalloc/proxy.cpp
   src/tbbmalloc/tbb_function_replacement.cpp)
 
-if (NOT APPLE)
-  add_definitions(-DDO_ITT_NOTIFY)
-else()
+add_library (tbb_interface INTERFACE)
+add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1)
+
+if (CMAKE_SYSTEM_PROCESSOR MATCHES "(i386|x86_64)")
+  if (NOT APPLE AND NOT MINGW)
+    target_compile_definitions(tbb_interface INTERFACE DO_ITT_NOTIFY)
+  endif()
+endif()
+
+if (APPLE)
   # Disable annoying "has no symbols" warnings
- set(CMAKE_C_ARCHIVE_CREATE   "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_C_ARCHIVE_FINISH   "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
- set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
 set(CMAKE_C_ARCHIVE_CREATE   "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
 set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
 set(CMAKE_C_ARCHIVE_FINISH   "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
 set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
 endif()
 
-if (UNIX)
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DUSE_PTHREAD")
-  if(NOT CMAKE_CXX_FLAGS MATCHES "-mno-rtm")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mrtm")
-  endif()
-  if (APPLE)
-    set(ARCH_PREFIX "mac")
-  else()
-    set(ARCH_PREFIX "lin")
-  endif()
-  if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-    set(ARCH_PREFIX "${ARCH_PREFIX}64")
+macro(CHECK_CXX_COMPILER_AND_LINKER_FLAGS _RESULT _CXX_FLAGS _LINKER_FLAGS)
+  set(CMAKE_REQUIRED_FLAGS ${_CXX_FLAGS})
+  set(CMAKE_REQUIRED_LIBRARIES ${_LINKER_FLAGS})
+  set(CMAKE_REQUIRED_QUIET TRUE)
+  check_cxx_source_runs("#include <iostream>\nint main(int argc, char **argv) { std::cout << \"test\"; return 0; }" ${_RESULT})
+  set(CMAKE_REQUIRED_FLAGS "")
+  set(CMAKE_REQUIRED_LIBRARIES "")
+endmacro()
+
+# Prefer libc++ in conjunction with Clang
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  if (CMAKE_CXX_FLAGS MATCHES "-stdlib=libc\\+\\+")
+    message(STATUS "TBB: using libc++.")
   else()
-    set(ARCH_PREFIX "${ARCH_PREFIX}32")
+    CHECK_CXX_COMPILER_AND_LINKER_FLAGS(HAS_LIBCPP "-stdlib=libc++" "-stdlib=libc++")
+    if (HAS_LIBCPP)
+      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -D_LIBCPP_VERSION")
+      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
+      set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++")
+      message(STATUS "TBB: using libc++.")
+    else()
+      message(STATUS "TBB: NOT using libc++.")
+    endif()
   endif()
-  set(ENABLE_RTTI "-frtti -fexceptions ")
-  set(DISABLE_RTTI "-fno-rtti -fno-exceptions ")
+endif()
+
+set (CMAKE_CXX_STANDARD 11)
+
+if (UNIX)
+  target_compile_definitions(tbb_interface INTERFACE USE_PTHREAD)
+
+  check_cxx_compiler_flag ("-mrtm -Werror" SUPPORTS_MRTM)
+  if (SUPPORTS_MRTM)
+    target_compile_options(tbb_interface INTERFACE "-mrtm")
+  endif ()
+
 elseif(WIN32)
-  cmake_minimum_required (VERSION 3.1)
-  enable_language(ASM_MASM)
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GS- /Zc:wchar_t /Zc:forScope /DUSE_WINTHREAD")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0600 /volatile:iso")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4800 /wd4146 /wd4244 /wd4018")
-
-  if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-    list(APPEND tbb_src src/tbb/intel64-masm/atomic_support.asm
-      src/tbb/intel64-masm/itsx.asm src/tbb/intel64-masm/intel64_misc.asm)
-    list(APPEND tbbmalloc_src src/tbb/intel64-masm/atomic_support.asm)
-    set(CMAKE_ASM_MASM_FLAGS "/DEM64T=1")
-    set(ARCH_PREFIX "win64")
-  else()
-    list(APPEND tbb_src src/tbb/ia32-masm/atomic_support.asm
-      src/tbb/ia32-masm/itsx.asm src/tbb/ia32-masm/lock_byte.asm)
-    list(APPEND tbbmalloc_src src/tbb/ia32-masm/atomic_support.asm)
-    set(ARCH_PREFIX "win32")
-  endif()
+  target_compile_definitions(tbb_interface INTERFACE USE_WINTHREAD _WIN32_WINNT=0x0600)
+  if (MSVC)
+    enable_language(ASM_MASM)
+    target_compile_options(tbb_interface INTERFACE /GS- /Zc:wchar_t /Zc:forScope)
+    check_cxx_compiler_flag ("/volatile:iso" SUPPORTS_VOLATILE_FLAG)
+    if (SUPPORTS_VOLATILE_FLAG)
+      target_compile_options(tbb_interface INTERFACE /volatile:iso)
+    endif ()
+    target_compile_options(tbb_interface INTERFACE $<$<COMPILE_LANGUAGE:CXX>:/wd4267 /wd4800 /wd4146 /wd4244 /wd4577 /wd4018>)
+    if (NOT CMAKE_SIZEOF_VOID_P)
+       message(FATAL_ERROR "'CMAKE_SIZEOF_VOID_P' is undefined. Please delete your build directory and rerun CMake again!")
+    endif()
+
+    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+      list(APPEND tbb_src src/tbb/intel64-masm/atomic_support.asm
+        src/tbb/intel64-masm/itsx.asm src/tbb/intel64-masm/intel64_misc.asm)
+      list(APPEND tbbmalloc_src src/tbb/intel64-masm/atomic_support.asm)
+      set(CMAKE_ASM_MASM_FLAGS "/DEM64T=1 ${CMAKE_ASM_MASM_FLAGS}")
+    else()
+      list(APPEND tbb_src src/tbb/ia32-masm/atomic_support.asm
+        src/tbb/ia32-masm/itsx.asm src/tbb/ia32-masm/lock_byte.asm)
+      # Enable SAFESEH feature for assembly (x86 builds only).
+      set(CMAKE_ASM_MASM_FLAGS "/safeseh ${CMAKE_ASM_MASM_FLAGS}")
+    endif()
+  elseif (MINGW)
+    target_compile_options(tbb_interface INTERFACE "-mthreads")
+  endif ()
+endif()
+
+if (MSVC)
   set(ENABLE_RTTI "/EHsc /GR ")
   set(DISABLE_RTTI "/EHs- /GR- ")
+elseif (UNIX)
+  set(ENABLE_RTTI "-frtti -fexceptions ")
+  set(DISABLE_RTTI "-fno-rtti -fno-exceptions ")
+endif ()
+
+##--------
+#   - Added TBB_USE_GLIBCXX_VERSION macro to specify the version of GNU
+#     libstdc++ when it cannot be properly recognized, e.g. when used
+#     with Clang on Linux* OS. Inspired by a contribution from David A.
+if (NOT TBB_USE_GLIBCXX_VERSION AND UNIX AND NOT APPLE)
+  if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    # using Clang
+    string(REPLACE "." "0" TBB_USE_GLIBCXX_VERSION ${CMAKE_CXX_COMPILER_VERSION})
+  endif()
 endif()
 
+if (TBB_USE_GLIBCXX_VERSION)
+  target_compile_definitions(tbb_interface INTERFACE TBB_USE_GLIBCXX_VERSION=${TBB_USE_GLIBCXX_VERSION})
+endif()
+
+##-------
+
 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
-  include(CheckCXXCompilerFlag)
-  check_cxx_compiler_flag("-flifetime-dse=1" SUPPORTS_FLIFETIME)
-  if (SUPPORTS_FLIFETIME)
-    add_definitions(-flifetime-dse=1)
-  endif()
+   check_cxx_compiler_flag ("-flifetime-dse=1" SUPPORTS_FLIFETIME)
+   if (SUPPORTS_FLIFETIME)
+     target_compile_options(tbb_interface INTERFACE -flifetime-dse=1)
+   endif()
 endif()
 
 # Linker export definitions
-if (WIN32)
+if (APPLE)
+  set (ARCH_PREFIX "mac")
+elseif(WIN32)
+  set (ARCH_PREFIX "win")
+else()
+  set (ARCH_PREFIX "lin")
+endif()
+
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set(ARCH_PREFIX "${ARCH_PREFIX}64")
+else()
+  set(ARCH_PREFIX "${ARCH_PREFIX}32")
+endif()
+
+if (MINGW)
+  set (ARCH_PREFIX "${ARCH_PREFIX}-gcc")
+  # there's no win32-gcc-tbb-export.def, use lin32-tbb-export.def
+  execute_process (COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/lin32-tbb-export.def ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/win32-gcc-tbb-export.def)
+endif()
+
+if (MSVC)
   add_custom_command(OUTPUT tbb.def
     COMMAND ${CMAKE_CXX_COMPILER} /TC /EP ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def  -I ${CMAKE_CURRENT_SOURCE_DIR}/include > tbb.def
     MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def
@@ -110,18 +238,15 @@ if (WIN32)
     MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def
     COMMENT "Preprocessing tbbmalloc.def"
   )
-  list(APPEND tbb_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/tbb_resource.rc)
-  list(APPEND tbbmalloc_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/tbbmalloc.rc)
-  list(APPEND tbbmalloc_proxy_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/tbbmalloc.rc)
 else()
   add_custom_command(OUTPUT tbb.def
-    COMMAND ${CMAKE_CXX_COMPILER} -xc++ -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def  -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o tbb.def
+    COMMAND ${CMAKE_CXX_COMPILER} -xc++ -std=c++11 -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def  -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o tbb.def
     MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def
     COMMENT "Preprocessing tbb.def"
   )
 
   add_custom_command(OUTPUT tbbmalloc.def
-    COMMAND ${CMAKE_CXX_COMPILER} -xc++ -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def  -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o   tbbmalloc.def
+    COMMAND ${CMAKE_CXX_COMPILER} -xc++ -std=c++11 -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def  -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o   tbbmalloc.def
     MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def
     COMMENT "Preprocessing tbbmalloc.def"
   )
@@ -132,34 +257,80 @@ add_custom_target(tbb_def_files DEPENDS tbb.def tbbmalloc.def)
 # TBB library
 if (TBB_BUILD_STATIC)
   add_library(tbb_static STATIC ${tbb_src})
-  set_property(TARGET tbb_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_BUILD=1")
-  set_property(TARGET tbb_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_SOURCE_DIRECTLY_INCLUDED=1")
+  target_link_libraries(tbb_static PRIVATE tbb_interface)
+  target_include_directories(tbb_static INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<INSTALL_INTERFACE:${TBB_INSTALL_INCLUDE_DIR}>")
   set_property(TARGET tbb_static APPEND_STRING PROPERTY COMPILE_FLAGS ${ENABLE_RTTI})
-  install(TARGETS tbb_static ARCHIVE DESTINATION lib)
+  if (TBB_INSTALL_TARGETS)
+    install(TARGETS tbb_static ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR})
+  endif()
+
+  target_compile_definitions(tbb_static
+    PRIVATE
+      -D__TBB_BUILD=1
+      -D__TBB_DYNAMIC_LOAD_ENABLED=0
+      -D__TBB_SOURCE_DIRECTLY_INCLUDED=1)
+
+  if (MSVC)
+    target_compile_definitions(tbb_static
+      PUBLIC -D__TBB_NO_IMPLICIT_LINKAGE=1
+      PRIVATE -D_CRT_SECURE_NO_WARNINGS)
+  endif()
+
+  if (UNIX AND NOT APPLE)
+    target_link_libraries(tbb_static PUBLIC pthread dl)
+  endif()
 endif()
 
 if (TBB_BUILD_SHARED)
   add_library(tbb SHARED ${tbb_src})
-  set_property(TARGET tbb APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_BUILD=1")
+  target_link_libraries(tbb PRIVATE tbb_interface)
+  target_include_directories(tbb INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<INSTALL_INTERFACE:${TBB_INSTALL_INCLUDE_DIR}>")
   set_property(TARGET tbb APPEND_STRING PROPERTY COMPILE_FLAGS ${ENABLE_RTTI})
+  if (TBB_SET_SOVERSION)
+    set_property(TARGET tbb PROPERTY SOVERSION 2)
+  endif ()
+
+  target_compile_definitions(tbb
+    PRIVATE -D__TBB_BUILD=1)
+
+  if (MSVC)
+    target_compile_definitions(tbb
+      PUBLIC -D__TBB_NO_IMPLICIT_LINKAGE=1
+      PRIVATE -D_CRT_SECURE_NO_WARNINGS)
+  endif()
+
   add_dependencies(tbb tbb_def_files)
+
   if (APPLE)
-    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
-  elseif(UNIX)
-    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
-  elseif(WIN32)
-    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "/DEF:${CMAKE_CURRENT_BINARY_DIR}/tbb.def")
-    
+    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,\"${CMAKE_CURRENT_BINARY_DIR}/tbb.def\"")
+  elseif (MSVC)
+    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "/DEF:\"${CMAKE_CURRENT_BINARY_DIR}/tbb.def\"")
+  else ()
+    set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,\"${CMAKE_CURRENT_BINARY_DIR}/tbb.def\"")
   endif()
-  install(TARGETS tbb DESTINATION lib)
-  if(WIN32)
-    set_target_properties(tbb PROPERTIES OUTPUT_NAME "tbb$<$<CONFIG:Debug>:_debug>")
+
+  if (TBB_INSTALL_TARGETS)
+    install(TARGETS tbb EXPORT TBB
+            LIBRARY DESTINATION ${TBB_INSTALL_LIBRARY_DIR}
+            ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR}
+            RUNTIME DESTINATION ${TBB_INSTALL_RUNTIME_DIR})
+    if (MSVC)
+      install(FILES $<TARGET_PDB_FILE:tbb> DESTINATION ${TBB_INSTALL_RUNTIME_DIR} OPTIONAL)
+    endif()
+  endif()
+
+  if (UNIX AND NOT APPLE)
+    target_link_libraries(tbb PUBLIC pthread dl)
   endif()
 endif()
 
-if(CMAKE_COMPILER_IS_GNUCC)
+
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
   # Quench a warning on GCC
   set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/governor.cpp COMPILE_FLAGS "-Wno-missing-field-initializers ")
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+  # Quench a warning on Clang
+  set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/itt_notify.cpp COMPILE_FLAGS "-Wno-varargs ")
 elseif(MSVC)
   # Quench a warning on MSVC
   set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/scheduler.cpp COMPILE_FLAGS "/wd4458 ")
@@ -169,24 +340,50 @@ if(TBB_BUILD_TBBMALLOC)
   # TBB malloc library
   if (TBB_BUILD_STATIC)
     add_library(tbbmalloc_static STATIC ${tbbmalloc_static_src})
+    target_link_libraries(tbbmalloc_static PRIVATE tbb_interface)
     set_property(TARGET tbbmalloc_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+    set_property(TARGET tbbmalloc_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_DYNAMIC_LOAD_ENABLED=0")
+    set_property(TARGET tbbmalloc_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_SOURCE_DIRECTLY_INCLUDED=1")
     set_property(TARGET tbbmalloc_static APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
-    install(TARGETS tbbmalloc_static ARCHIVE DESTINATION lib)
+    if (MSVC)
+      target_compile_definitions(tbbmalloc_static PUBLIC __TBB_NO_IMPLICIT_LINKAGE=1 __TBBMALLOC_NO_IMPLICIT_LINKAGE=1)
+    endif()
+    if (TBB_INSTALL_TARGETS)
+      install(TARGETS tbbmalloc_static ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR})
+    endif()
   endif()
 
   if (TBB_BUILD_SHARED)
     add_library(tbbmalloc SHARED ${tbbmalloc_src})
+    target_link_libraries(tbbmalloc PRIVATE tbb_interface)
     set_property(TARGET tbbmalloc APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
     set_property(TARGET tbbmalloc APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
+    if (TBB_SET_SOVERSION)
+      set_property(TARGET tbbmalloc PROPERTY SOVERSION 2)
+    endif ()
     add_dependencies(tbbmalloc tbb_def_files)
     if (APPLE)
-      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
-    elseif(UNIX)
-      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
-    elseif(WIN32)
-      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "/DEF:${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def")
+      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-exported_symbols_list,\"${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def\"")
+    elseif (MSVC)
+      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "/DEF:\"${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def\"")
+    else ()
+      set_property(TARGET tbbmalloc APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,\"${CMAKE_CURRENT_BINARY_DIR}/tbbmalloc.def\"")
+    endif()
+    if (MSVC)
+      target_compile_definitions(tbbmalloc PUBLIC __TBB_NO_IMPLICIT_LINKAGE=1 __TBBMALLOC_NO_IMPLICIT_LINKAGE=1)
+    endif()
+    if (TBB_INSTALL_TARGETS)
+      install(TARGETS tbbmalloc EXPORT TBB
+              LIBRARY DESTINATION ${TBB_INSTALL_LIBRARY_DIR}
+              ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR}
+              RUNTIME DESTINATION ${TBB_INSTALL_RUNTIME_DIR})
+      if (MSVC)
+        install(FILES $<TARGET_PDB_FILE:tbbmalloc> DESTINATION ${TBB_INSTALL_RUNTIME_DIR} OPTIONAL)
+      endif()
+    endif()
+    if (UNIX AND NOT APPLE)
+      target_link_libraries(tbbmalloc PUBLIC pthread dl)
     endif()
-    install(TARGETS tbbmalloc DESTINATION lib)
   endif()
 endif()
 
@@ -194,19 +391,298 @@ if(TBB_BUILD_TBBMALLOC_PROXY)
   # TBB malloc proxy library
   if (TBB_BUILD_STATIC)
     add_library(tbbmalloc_proxy_static STATIC ${tbbmalloc_proxy_src})
+    target_link_libraries(tbbmalloc_proxy_static PRIVATE tbb_interface)
     set_property(TARGET tbbmalloc_proxy_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
+    set_property(TARGET tbbmalloc_proxy_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_DYNAMIC_LOAD_ENABLED=0")
+    set_property(TARGET tbbmalloc_proxy_static APPEND PROPERTY COMPILE_DEFINITIONS "__TBB_SOURCE_DIRECTLY_INCLUDED=1")
     set_property(TARGET tbbmalloc_proxy_static APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
-    link_libraries(tbbmalloc_proxy_static tbbmalloc)
-    install(TARGETS tbbmalloc_proxy_static ARCHIVE DESTINATION lib)
+    if (TBB_INSTALL_TARGETS)
+      install(TARGETS tbbmalloc_proxy_static ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR})
+    endif()
   endif()
 
   if (TBB_BUILD_SHARED)
     add_library(tbbmalloc_proxy SHARED ${tbbmalloc_proxy_src})
+    target_link_libraries(tbbmalloc_proxy PRIVATE tbb_interface)
     set_property(TARGET tbbmalloc_proxy APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1")
     set_property(TARGET tbbmalloc_proxy APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI})
-    target_link_libraries(tbbmalloc_proxy tbbmalloc)
-    install(TARGETS tbbmalloc_proxy DESTINATION lib)
+    if (TBB_SET_SOVERSION)
+      set_property(TARGET tbbmalloc_proxy PROPERTY SOVERSION 2)
+    endif ()
+    target_link_libraries(tbbmalloc_proxy PUBLIC tbbmalloc)
+    if (TBB_INSTALL_TARGETS)
+      install(TARGETS tbbmalloc_proxy EXPORT TBB
+              LIBRARY DESTINATION ${TBB_INSTALL_LIBRARY_DIR}
+              ARCHIVE DESTINATION ${TBB_INSTALL_ARCHIVE_DIR}
+              RUNTIME DESTINATION ${TBB_INSTALL_RUNTIME_DIR})
+      if (MSVC)
+        install(FILES $<TARGET_PDB_FILE:tbbmalloc_proxy> DESTINATION ${TBB_INSTALL_RUNTIME_DIR} OPTIONAL)
+      endif()
+    endif()
+    if (UNIX AND NOT APPLE)
+      target_link_libraries(tbbmalloc_proxy PUBLIC pthread dl)
+    endif()
   endif()
 endif()
 
-install(DIRECTORY include/tbb DESTINATION include)
+if (TBB_INSTALL_TARGETS)
+  install(DIRECTORY include/tbb DESTINATION ${TBB_INSTALL_INCLUDE_DIR})
+  if (TBB_BUILD_SHARED)
+    install(EXPORT TBB DESTINATION ${TBB_CMAKE_PACKAGE_INSTALL_DIR} NAMESPACE TBB:: FILE TBBConfig.cmake)
+  endif()
+endif()
+
+# version file
+if (TBB_INSTALL_TARGETS)
+  set (_VERSION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/include/tbb/tbb_stddef.h)
+  file (STRINGS ${_VERSION_FILE} _VERSION_MAJOR_STRING REGEX ".*define[ ]+TBB_VERSION_MAJOR[ ]+[0-9]+.*")
+  file (STRINGS ${_VERSION_FILE} _VERSION_MINOR_STRING REGEX ".*define[ ]+TBB_VERSION_MINOR[ ]+[0-9]+.*")
+  string (REGEX REPLACE ".*TBB_VERSION_MAJOR[ ]+([0-9]+)" "\\1" TBB_MAJOR_VERSION ${_VERSION_MAJOR_STRING})
+  string (REGEX REPLACE ".*TBB_VERSION_MINOR[ ]+([0-9]+)" "\\1" TBB_MINOR_VERSION ${_VERSION_MINOR_STRING})
+  set (TBB_VERSION_STRING "${TBB_MAJOR_VERSION}.${TBB_MINOR_VERSION}")
+  include (CMakePackageConfigHelpers)
+  write_basic_package_version_file (TBBConfigVersion.cmake VERSION "${TBB_VERSION_STRING}" COMPATIBILITY AnyNewerVersion)
+  install (FILES ${CMAKE_CURRENT_BINARY_DIR}/TBBConfigVersion.cmake DESTINATION "${TBB_CMAKE_PACKAGE_INSTALL_DIR}")
+endif()
+
+# version_string.ver
+if (UNIX AND NOT TBB_NO_DATE)
+  execute_process (COMMAND date "+%a, %d %b %Y %H:%M:%S %z"
+                   OUTPUT_VARIABLE _configure_date
+                   OUTPUT_STRIP_TRAILING_WHITESPACE)
+elseif (WIN32 AND NOT TBB_NO_DATE)
+  execute_process (COMMAND cmd " /C date /T"
+                   OUTPUT_VARIABLE _configure_date
+                   OUTPUT_STRIP_TRAILING_WHITESPACE)
+else ()
+  set (_configure_date "Unknown")
+endif()
+set (TBB_CONFIG_DATE "${_configure_date}" CACHE STRING "First time that TBB was configured")
+set (_configure_date "${TBB_CONFIG_DATE}")
+include_directories (${CMAKE_BINARY_DIR})
+configure_file (build/version_string.ver.in version_string.ver @ONLY)
+
+if (TBB_BUILD_TESTS)
+  enable_language (C)
+  enable_testing ()
+
+  find_library (LIBRT_LIBRARIES rt)
+  find_library (LIDL_LIBRARIES dl)
+  find_package (Threads)
+  if (NOT APPLE)
+    find_package (OpenMP)
+  endif()
+
+  macro (tbb_add_test testname)
+    set (full_testname tbb_test_${testname})
+    add_executable (${full_testname} src/test/test_${testname}.cpp)
+    target_link_libraries(${full_testname} PRIVATE tbb_interface)
+    if (TBB_BUILD_SHARED)
+      target_link_libraries (${full_testname} PRIVATE tbb tbbmalloc)
+      target_compile_definitions (${full_testname} PRIVATE __TBB_LIB_NAME=tbb)
+    else ()
+      target_link_libraries (${full_testname} PRIVATE tbb_static tbbmalloc_static)
+      target_compile_definitions (${full_testname} PRIVATE __TBB_LIB_NAME=tbb_static)
+    endif ()
+    if (LIBRT_LIBRARIES)
+      target_link_libraries (${full_testname} PRIVATE ${LIBRT_LIBRARIES})
+    endif ()
+    if (LIDL_LIBRARIES)
+      target_link_libraries (${full_testname} PRIVATE ${LIDL_LIBRARIES})
+    endif ()
+    if (Threads_FOUND)
+      target_link_libraries (${full_testname} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
+    endif ()
+    if (OPENMP_FOUND AND "${testname}" MATCHES "openmp")
+      set_target_properties (${full_testname} PROPERTIES COMPILE_FLAGS "${OpenMP_CXX_FLAGS}")
+      set_target_properties (${full_testname} PROPERTIES LINK_FLAGS "${OpenMP_CXX_FLAGS}")
+    endif()
+    if (MINGW)
+      target_link_libraries (${full_testname} PRIVATE psapi)
+    endif ()
+    add_test (NAME ${full_testname} COMMAND ${full_testname})
+  endmacro ()
+
+  tbb_add_test (aggregator)
+  tbb_add_test (aligned_space)
+  tbb_add_test (assembly)
+  if (NOT WIN32)
+    tbb_add_test (async_msg) # msvc64/debug timeouts
+  endif()
+  tbb_add_test (async_node)
+  # tbb_add_test (atomic) # msvc64/debug timeouts: Compile-time initialization fails for static tbb::atomic variables
+  tbb_add_test (blocked_range2d)
+  tbb_add_test (blocked_range3d)
+  tbb_add_test (blocked_range)
+  tbb_add_test (broadcast_node)
+  tbb_add_test (buffer_node)
+  tbb_add_test (cache_aligned_allocator)
+  if (NOT WIN32)
+    tbb_add_test (cache_aligned_allocator_STL)
+  endif()
+  tbb_add_test (cilk_dynamic_load)
+  tbb_add_test (cilk_interop)
+  tbb_add_test (combinable)
+  tbb_add_test (composite_node)
+  tbb_add_test (concurrent_hash_map)
+  tbb_add_test (concurrent_lru_cache)
+  # tbb_add_test (concurrent_monitor) # too long
+  # tbb_add_test (concurrent_priority_queue)
+  if (NOT WIN32)
+    tbb_add_test (concurrent_queue) # msvc64/debug timeouts
+  endif()
+  # tbb_add_test (concurrent_queue_whitebox)
+  tbb_add_test (concurrent_unordered_map)
+  # tbb_add_test (concurrent_unordered_set)
+  tbb_add_test (concurrent_vector)
+  tbb_add_test (continue_node)
+  tbb_add_test (critical_section)
+  tbb_add_test (dynamic_link)
+  # tbb_add_test (eh_algorithms)
+  tbb_add_test (eh_flow_graph)
+  # tbb_add_test (eh_tasks)
+  tbb_add_test (enumerable_thread_specific)
+  tbb_add_test (examples_common_utility)
+  # tbb_add_test (fast_random)
+  tbb_add_test (flow_graph)
+  tbb_add_test (flow_graph_whitebox)
+  # tbb_add_test (fp) # mingw: harness_fp.h:66, assertion !checkConsistency || (ctl.mxcsr & SSE_RND_MODE_MASK) >> 3 == (ctl.x87cw & FE_RND_MODE_MASK): failed
+  # tbb_add_test (function_node) # mingw:random timeout
+  # tbb_add_test (global_control)
+  # tbb_add_test (global_control_whitebox)
+  tbb_add_test (halt)
+  tbb_add_test (handle_perror)
+  # tbb_add_test (hw_concurrency)
+  tbb_add_test (indexer_node)
+  tbb_add_test (inits_loop)
+  tbb_add_test (intrusive_list)
+  tbb_add_test (ittnotify)
+  # tbb_add_test (join_node) #msvc/64: fatal error C1128: number of sections exceeded object file format limit: compile with /bigob
+  tbb_add_test (lambda)
+  tbb_add_test (limiter_node)
+  # tbb_add_test (malloc_atexit)
+  # tbb_add_test (malloc_compliance) #mingw: Limits should be decreased for the test to work
+  tbb_add_test (malloc_init_shutdown)
+  # tbb_add_test (malloc_lib_unload)
+  # tbb_add_test (malloc_overload)
+  tbb_add_test (malloc_pools)
+  tbb_add_test (malloc_regression)
+  # tbb_add_test (malloc_used_by_lib)
+  # tbb_add_test (malloc_whitebox)
+  tbb_add_test (model_plugin)
+  # tbb_add_test (multifunction_node) # too long
+  tbb_add_test (mutex)
+  tbb_add_test (mutex_native_threads)
+  # tbb_add_test (opencl_node)
+  if (OPENMP_FOUND)
+    tbb_add_test (openmp)
+  endif ()
+  tbb_add_test (overwrite_node)
+  # tbb_add_test (parallel_do)
+  # This seems to fail on CI platforms (AppVeyor/Travis), perhaps because the VM exposes just 1 core?
+  tbb_add_test (parallel_for)
+  tbb_add_test (parallel_for_each)
+  tbb_add_test (parallel_for_vectorization)
+  tbb_add_test (parallel_invoke)
+  tbb_add_test (parallel_pipeline)
+  tbb_add_test (parallel_reduce)
+  tbb_add_test (parallel_scan)
+  tbb_add_test (parallel_sort)
+  tbb_add_test (parallel_while)
+  # tbb_add_test (partitioner_whitebox) # too long
+  tbb_add_test (pipeline)
+  # tbb_add_test (pipeline_with_tbf) # takes forever on appveyor
+  tbb_add_test (priority_queue_node)
+  tbb_add_test (queue_node)
+  tbb_add_test (reader_writer_lock)
+  # tbb_add_test (runtime_loader) # LINK : fatal error LNK1104: cannot open file 'tbbproxy.lib' [C:\projects\tbb\test_runtime_loader.vcxproj]
+  tbb_add_test (rwm_upgrade_downgrade)
+  # tbb_add_test (ScalableAllocator)
+  if (NOT WIN32)
+    tbb_add_test (ScalableAllocator_STL)
+  endif()
+  tbb_add_test (semaphore)
+  # tbb_add_test (sequencer_node) # msvc: timeout
+  tbb_add_test (source_node)
+  tbb_add_test (split_node)
+  tbb_add_test (static_assert)
+  tbb_add_test (std_thread)
+  tbb_add_test (tagged_msg)
+  # tbb_add_test (task_arena) # LINK : fatal error LNK1104: cannot open file '__TBB_LIB_NAME.lib' [C:\projects\tbb\test_task_arena.vcxproj]
+  # tbb_add_test (task_assertions)
+  tbb_add_test (task_auto_init)
+  tbb_add_test (task)
+  # tbb_add_test (task_enqueue) # too long
+  tbb_add_test (task_group)
+  # tbb_add_test (task_leaks)
+  # tbb_add_test (task_priority)
+  # tbb_add_test (task_scheduler_init) # msvc: test_task_scheduler_init.cpp:68, assertion !test_mandatory_parallelism || Harness::CanReachConcurrencyLevel(threads): failed
+  tbb_add_test (task_scheduler_observer)
+  tbb_add_test (task_steal_limit)
+  tbb_add_test (tbb_condition_variable)
+  tbb_add_test (tbb_fork)
+  # tbb_add_test (tbb_header)
+  tbb_add_test (tbb_thread)
+  # tbb_add_test (tbb_version)
+  tbb_add_test (tick_count)
+  tbb_add_test (tuple)
+  tbb_add_test (write_once_node)
+  tbb_add_test (yield)
+endif ()
+
+if (TBB_BUILD_PYTHON)
+  find_package(PythonInterp)
+  find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
+  find_package(SWIG 3)
+  if (PythonLibs_FOUND AND SWIG_FOUND AND TBB_BUILD_SHARED)
+    include (${SWIG_USE_FILE})
+    set_source_files_properties (python/tbb/api.i PROPERTIES CPLUSPLUS ON)
+    set (CMAKE_SWIG_FLAGS "-threads")
+
+    # swig_add_module is deprecated
+    if (CMAKE_VERSION VERSION_LESS 3.8)
+      swig_add_module (api python python/tbb/api.i)
+    else ()
+      swig_add_library (api LANGUAGE python SOURCES python/tbb/api.i)
+    endif ()
+
+    # UseSWIG generates now standard target names
+    if (CMAKE_VERSION VERSION_LESS 3.13)
+      set (module_target ${SWIG_MODULE_api_REAL_NAME})
+    else ()
+      set (module_target api)
+    endif ()
+
+    target_include_directories(${module_target} PRIVATE ${PYTHON_INCLUDE_DIRS})
+    target_link_libraries(${module_target} PRIVATE tbb)
+    if(WIN32)
+      target_link_libraries(${module_target} ${PYTHON_LIBRARIES})
+    elseif(APPLE)
+      set_target_properties(${module_target} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
+    endif()
+
+    if (WIN32)
+      set (PYTHON_SITE_PACKAGES Lib/site-packages)
+    else ()
+      set (PYTHON_SITE_PACKAGES lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages)
+    endif ()
+    if (TBB_INSTALL_TARGETS)
+      install(FILES python/TBB.py
+              DESTINATION ${PYTHON_SITE_PACKAGES})
+      install(FILES python/tbb/__init__.py python/tbb/pool.py python/tbb/test.py python/tbb/__main__.py ${CMAKE_CURRENT_BINARY_DIR}/api.py
+              DESTINATION ${PYTHON_SITE_PACKAGES}/tbb)
+      install(TARGETS ${module_target}
+              DESTINATION ${PYTHON_SITE_PACKAGES}/tbb)
+    endif()
+
+    if(UNIX AND NOT APPLE)
+      add_library(irml SHARED python/rml/ipc_server.cpp python/rml/ipc_utils.cpp src/tbb/cache_aligned_allocator.cpp src/tbb/dynamic_link.cpp src/tbb/tbb_misc_ex.cpp src/tbb/tbb_misc.cpp)
+      target_compile_definitions(irml PRIVATE DO_ITT_NOTIFY=0 USE_PTHREAD=1)
+      target_link_libraries(irml PRIVATE tbb)
+      set_target_properties(irml PROPERTIES VERSION 1)
+      if (TBB_INSTALL_TARGETS)
+        install(TARGETS irml DESTINATION ${TBB_INSTALL_LIBRARY_DIR})
+      endif()
+    endif ()
+  endif ()
+endif ()
index c05c35bca9543bb09140cdbe2e7d3ff81ce2dd37..07f70aa70072ec1f4949c2c53bf7a083896c2cf2 100644 (file)
@@ -10,4 +10,15 @@ index 7a8d06a0..886699d8 100644
 +    #if (__cplusplus >= 201402L && (!defined(_MSC_VER) || _MSC_VER >= 1920))
          #define __TBB_DEPRECATED [[deprecated]]
          #define __TBB_DEPRECATED_MSG(msg) [[deprecated(msg)]]
-     #elif _MSC_VER
\ No newline at end of file
+     #elif _MSC_VER
+--- a/src/tbb/tools_api/ittnotify_config.h
++++ b/src/tbb/tools_api/ittnotify_config.h
+@@ -162,7 +162,7 @@
+ #    define ITT_ARCH ITT_ARCH_IA32E
+ #  elif defined _M_IA64 || defined __ia64__
+ #    define ITT_ARCH ITT_ARCH_IA64
+-#  elif defined _M_ARM || defined __arm__
++#  elif defined _M_ARM || defined __arm__ || defined __aarch64__
+ #    define ITT_ARCH ITT_ARCH_ARM
+ #  elif defined __powerpc64__
+ #    define ITT_ARCH ITT_ARCH_PPC64
index 3abadb66be9e54a74ac0d905e922edf3c3a1fe96..4436577816ec27ed93d3975e77c99e44d40f35f6 100644 (file)
@@ -4,7 +4,7 @@
        # Some are omitted here because they have special meanings below.
        1750a | 580 \
        | a29k \
-+    | aarch64 \
++      | aarch64 \
        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
        | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
        | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
@@ -12,7 +12,7 @@
        # Recognize the basic CPU types with company name.
        580-* \
        | a29k-* \
-+    | aarch64-* \
++      | aarch64-* \
        | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
        | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
        | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
index 42527a4f443777425aa0993288bf6dc8fc7321e7..dc4982ad114840fea1bd4c85cab9d95ad0765761 100644 (file)
@@ -53,3 +53,147 @@ diff -ru USD-20.11/pxr/base/tf/pxrLZ4/lz4.cpp external_usd/pxr/base/tf/pxrLZ4/lz
  
  /*-******************************
  *  Compression functions
+
+From 442d087962f762deeb8b6e49a0955753fcf9aeb9 Mon Sep 17 00:00:00 2001
+From: Tsahi Zidenberg <tsahee@amazon.com>
+Date: Sun, 15 Nov 2020 15:18:24 +0000
+Subject: [PATCH 1/2] stackTrace: support aarch64/linux
+
+stacktrace calls syscall directly via assembler. Create compatible
+aarch64 code.
+---
+ pxr/base/arch/stackTrace.cpp | 30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+diff --git a/pxr/base/arch/stackTrace.cpp b/pxr/base/arch/stackTrace.cpp
+index dcc1dfd46..c11aabeb1 100644
+--- a/pxr/base/arch/stackTrace.cpp
++++ b/pxr/base/arch/stackTrace.cpp
+@@ -583,7 +583,6 @@ nonLockingLinux__execve (const char *file,
+                          char *const argv[],
+                          char *const envp[])
+ {
+-#if defined(ARCH_BITS_64)
+     /*
+      * We make a direct system call here, because we can't find an
+      * execve which corresponds with the non-locking fork we call
+@@ -594,7 +593,27 @@ nonLockingLinux__execve (const char *file,
+      * hangs in a threaded app.  (We use the non-locking fork to get
+      * around problems with forking when we have had memory
+      * corruption.)  whew.
+-     *
++     */
++
++    unsigned long result;
++
++#if defined (__aarch64__)
++    {
++        register long __file_result asm ("x0") = (long)file;
++        register char* const* __argv asm ("x1") = argv;
++        register char* const* __envp asm ("x2") = envp;
++        register long __num_execve asm ("x8") = 221;
++        __asm__ __volatile__ (
++            "svc 0"
++            : "=r" (__file_result)
++            : "r"(__num_execve), "r" (__file_result), "r" (__argv), "r" (__envp)
++            : "memory"
++        );
++        result = __file_result;
++    }
++#elif defined(ARCH_CPU_INTEL) && defined(ARCH_BITS_64)
++
++    /*
+      * %rdi, %rsi, %rdx, %rcx, %r8, %r9 are args 0-5
+      * syscall clobbers %rcx and %r11
+      *
+@@ -603,7 +622,6 @@ nonLockingLinux__execve (const char *file,
+      * constraints to gcc.
+      */
+-    unsigned long result;
+     __asm__ __volatile__ (
+         "mov    %0, %%rdi    \n\t"
+         "mov    %%rcx, %%rsi \n\t"
+@@ -614,6 +632,9 @@ nonLockingLinux__execve (const char *file,
+         : "0" (file), "c" (argv), "d" (envp)
+         : "memory", "cc", "r11"
+     );
++#else
++#error Unknown architecture
++#endif
+     if (result >= 0xfffffffffffff000) {
+         errno = -result;
+@@ -621,9 +642,6 @@ nonLockingLinux__execve (const char *file,
+     }
+     return result;
+-#else
+-#error Unknown architecture
+-#endif
+ }
+ #endif
+
+From a1dffe02519bb3c6ccbbe8c6c58304da5db98995 Mon Sep 17 00:00:00 2001
+From: Tsahi Zidenberg <tsahee@amazon.com>
+Date: Sun, 15 Nov 2020 15:22:52 +0000
+Subject: [PATCH 2/2] timing: support aarch64/linux
+
+The aarch64 arch-timer is directly accessible to userspace via two
+registers:
+CNTVCT_EL0 - holds the current counter value
+CNTFRQ_EL0 - holds the counter frequency (in Hz)
+---
+ pxr/base/arch/timing.cpp | 6 ++++++
+ pxr/base/arch/timing.h   | 6 +++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/pxr/base/arch/timing.cpp b/pxr/base/arch/timing.cpp
+index 27ad58fed..9022950c1 100644
+--- a/pxr/base/arch/timing.cpp
++++ b/pxr/base/arch/timing.cpp
+@@ -59,6 +59,11 @@ ARCH_HIDDEN
+ void
+ Arch_InitTickTimer()
+ {
++#ifdef __aarch64__
++    uint64_t counter_hz;
++    __asm __volatile("mrs     %0, CNTFRQ_EL0" : "=&r" (counter_hz));
++    Arch_NanosecondsPerTick = double(1e9) / double(counter_hz);
++#else
+     // NOTE: Normally ifstream would be cleaner, but it causes crashes when
+     //       used in conjunction with DSOs and the Intel Compiler.
+     FILE *in;
+@@ -135,6 +140,7 @@ Arch_InitTickTimer()
+     }
+     Arch_NanosecondsPerTick = double(1e9) / double(cpuHz);
++#endif
+ }
+ #elif defined(ARCH_OS_WINDOWS)
+diff --git a/pxr/base/arch/timing.h b/pxr/base/arch/timing.h
+index 67ec0d15f..6dc3e85a0 100644
+--- a/pxr/base/arch/timing.h
++++ b/pxr/base/arch/timing.h
+@@ -36,7 +36,7 @@
+ /// \addtogroup group_arch_SystemFunctions
+ ///@{
+-#if defined(ARCH_OS_LINUX)
++#if defined(ARCH_OS_LINUX) && defined(ARCH_CPU_INTEL)
+ #include <x86intrin.h>
+ #elif defined(ARCH_OS_DARWIN)
+ #include <mach/mach_time.h>
+@@ -69,6 +69,10 @@ ArchGetTickTime()
+ #elif defined(ARCH_CPU_INTEL)
+     // On Intel we'll use the rdtsc instruction.
+     return __rdtsc();
++#elif defined (__aarch64__)
++    uint64_t result;
++    __asm __volatile("mrs     %0, CNTVCT_EL0" : "=&r" (result));
++    return result;
+ #else
+ #error Unknown architecture.
+ #endif
index 057c2155fb6794eb261aae621e9e899cbb7c8814..7e9858d92687f60c1cad2e830fe5bdef5078389e 100644 (file)
@@ -85,8 +85,8 @@ class VersionInfo:
         version_number = int(self._parse_header_file(blender_h, 'BLENDER_VERSION'))
         version_number_patch = int(self._parse_header_file(blender_h, 'BLENDER_VERSION_PATCH'))
         version_numbers = (version_number // 100, version_number % 100, version_number_patch)
-        self.short_version = "%d.%02d" % (version_numbers[0], version_numbers[1])
-        self.version = "%d.%02d.%d" % version_numbers
+        self.short_version = "%d.%d" % (version_numbers[0], version_numbers[1])
+        self.version = "%d.%d.%d" % version_numbers
         self.version_cycle = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE')
         self.hash = self._parse_header_file(buildinfo_h, 'BUILD_HASH')[1:-1]
 
index 7f7f2ae0fb3c8b0afa80954cae36b5439def265d..e6105a885f38f539ad2af2b0cc7fb97a4e71b08e 100644 (file)
@@ -34,7 +34,7 @@ FIND_PATH(EMBREE_INCLUDE_DIR
     include
 )
 
-IF(NOT (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")))
+IF(NOT (("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") OR (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))))
   SET(_embree_SIMD_COMPONENTS
     embree_sse42
     embree_avx
index 91881441c951378fa3bf77d19433bf21378d70c0..813ac013cdf3ea6d0a96ac0f1f9509a1c2e0e868 100644 (file)
@@ -923,10 +923,6 @@ function(get_blender_version)
   math(EXPR _out_version_major "${_out_version} / 100")
   math(EXPR _out_version_minor "${_out_version} % 100")
 
-  # Zero pad the minor version so `_out_version_minor` is always two characters.
-  # This is needed if the minor version is a single digit.
-  string(REGEX REPLACE "^([0-9])$" "0\\1" _out_version_minor "${_out_version_minor}")
-
   # output vars
   set(BLENDER_VERSION "${_out_version_major}.${_out_version_minor}" PARENT_SCOPE)
   set(BLENDER_VERSION_MAJOR "${_out_version_major}" PARENT_SCOPE)
index f9055f02bcf8883f09d41037880ef6d6602e01ac..201d2208486cd926a5fde73155133a33c980d189 100644 (file)
@@ -38,7 +38,7 @@ PROJECT_NAME           = Blender
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = "V2.93"
+PROJECT_NUMBER         = "V3.0"
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index 45910194244c1f25c7ff9fab455f6e1beefb165d..0b8795340adc49ea94af9573148af5464537fc13 100644 (file)
@@ -4,7 +4,9 @@ Simple Render Engine
 """
 
 import bpy
-import bgl
+import array
+import gpu
+from gpu_extras.presets import draw_texture_2d
 
 
 class CustomRenderEngine(bpy.types.RenderEngine):
@@ -100,8 +102,7 @@ class CustomRenderEngine(bpy.types.RenderEngine):
         dimensions = region.width, region.height
 
         # Bind shader that converts from scene linear to display space,
-        bgl.glEnable(bgl.GL_BLEND)
-        bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
+        gpu.state.blend_set('ALPHA_PREMULT')
         self.bind_display_space_shader(scene)
 
         if not self.draw_data or self.draw_data.dimensions != dimensions:
@@ -110,7 +111,7 @@ class CustomRenderEngine(bpy.types.RenderEngine):
         self.draw_data.draw()
 
         self.unbind_display_space_shader()
-        bgl.glDisable(bgl.GL_BLEND)
+        gpu.state.blend_set('NONE')
 
 
 class CustomDrawData:
@@ -119,68 +120,21 @@ class CustomDrawData:
         self.dimensions = dimensions
         width, height = dimensions
 
-        pixels = [0.1, 0.2, 0.1, 1.0] * width * height
-        pixels = bgl.Buffer(bgl.GL_FLOAT, width * height * 4, pixels)
+        pixels = width * height * array.array('f', [0.1, 0.2, 0.1, 1.0])
+        pixels = gpu.types.Buffer('FLOAT', width * height * 4, pixels)
 
         # Generate texture
-        self.texture = bgl.Buffer(bgl.GL_INT, 1)
-        bgl.glGenTextures(1, self.texture)
-        bgl.glActiveTexture(bgl.GL_TEXTURE0)
-        bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
-        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA16F, width, height, 0, bgl.GL_RGBA, bgl.GL_FLOAT, pixels)
-        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
-        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
-        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
+        self.texture = gpu.types.GPUTexture((width, height), format='RGBA16F', data=pixels)
 
-        # Bind shader that converts from scene linear to display space,
-        # use the scene's color management settings.
-        shader_program = bgl.Buffer(bgl.GL_INT, 1)
-        bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, shader_program)
-
-        # Generate vertex array
-        self.vertex_array = bgl.Buffer(bgl.GL_INT, 1)
-        bgl.glGenVertexArrays(1, self.vertex_array)
-        bgl.glBindVertexArray(self.vertex_array[0])
-
-        texturecoord_location = bgl.glGetAttribLocation(shader_program[0], "texCoord")
-        position_location = bgl.glGetAttribLocation(shader_program[0], "pos")
-
-        bgl.glEnableVertexAttribArray(texturecoord_location)
-        bgl.glEnableVertexAttribArray(position_location)
-
-        # Generate geometry buffers for drawing textured quad
-        position = [0.0, 0.0, width, 0.0, width, height, 0.0, height]
-        position = bgl.Buffer(bgl.GL_FLOAT, len(position), position)
-        texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
-        texcoord = bgl.Buffer(bgl.GL_FLOAT, len(texcoord), texcoord)
-
-        self.vertex_buffer = bgl.Buffer(bgl.GL_INT, 2)
-
-        bgl.glGenBuffers(2, self.vertex_buffer)
-        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[0])
-        bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, position, bgl.GL_STATIC_DRAW)
-        bgl.glVertexAttribPointer(position_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
-
-        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[1])
-        bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, texcoord, bgl.GL_STATIC_DRAW)
-        bgl.glVertexAttribPointer(texturecoord_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
-
-        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, 0)
-        bgl.glBindVertexArray(0)
+        # Note: This is just a didactic example.
+        # In this case it would be more convenient to fill the texture with:
+        # self.texture.clear('FLOAT', value=[0.1, 0.2, 0.1, 1.0])
 
     def __del__(self):
-        bgl.glDeleteBuffers(2, self.vertex_buffer)
-        bgl.glDeleteVertexArrays(1, self.vertex_array)
-        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
-        bgl.glDeleteTextures(1, self.texture)
+        del self.texture
 
     def draw(self):
-        bgl.glActiveTexture(bgl.GL_TEXTURE0)
-        bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
-        bgl.glBindVertexArray(self.vertex_array[0])
-        bgl.glDrawArrays(bgl.GL_TRIANGLE_FAN, 0, 4)
-        bgl.glBindVertexArray(0)
-        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
+        draw_texture_2d(self.texture, (0, 0), self.texture.width, self.texture.height)
 
 
 # RenderEngines also need to tell UI Panels that they are compatible with.
index e05290a9442988d9ccf9cec8c87d48b6efac2a51..b1a1ba827db323065fc8210313de83de7d720c87 100644 (file)
@@ -4,7 +4,6 @@ Mesh with Random Vertex Colors
 """
 import bpy
 import gpu
-import bgl
 import numpy as np
 from random import random
 from gpu_extras.batch import batch_for_shader
@@ -31,9 +30,10 @@ batch = batch_for_shader(
 
 
 def draw():
-    bgl.glEnable(bgl.GL_DEPTH_TEST)
+    gpu.state.depth_test_set('LESS_EQUAL')
+    gpu.state.depth_mask_set(True)
     batch.draw(shader)
-    bgl.glDisable(bgl.GL_DEPTH_TEST)
+    gpu.state.depth_mask_set(False)
 
 
 bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
index 69af65e163e5dd26ef3ceaba6667130f7e37d256..334a606055ab681e018f3708ab4ddff7dd003322 100644 (file)
@@ -6,11 +6,11 @@ To use this example you have to provide an image that should be displayed.
 """
 import bpy
 import gpu
-import bgl
 from gpu_extras.batch import batch_for_shader
 
 IMAGE_NAME = "Untitled"
 image = bpy.data.images[IMAGE_NAME]
+texture = gpu.texture.from_image(image)
 
 shader = gpu.shader.from_builtin('2D_IMAGE')
 batch = batch_for_shader(
@@ -21,16 +21,9 @@ batch = batch_for_shader(
     },
 )
 
-if image.gl_load():
-    raise Exception()
-
-
 def draw():
-    bgl.glActiveTexture(bgl.GL_TEXTURE0)
-    bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
-
     shader.bind()
-    shader.uniform_int("image", 0)
+    shader.uniform_sampler("image", texture)
     batch.draw(shader)
 
 
index 80cda45e690f9d04d6992754bcc6e9f6288568d2..01082e7b6fe16ea9055aa97a4ef1b7b6361b43f3 100644 (file)
@@ -9,7 +9,6 @@ Generate a texture using Offscreen Rendering
 """
 import bpy
 import gpu
-import bgl
 from mathutils import Matrix
 from gpu_extras.batch import batch_for_shader
 from gpu_extras.presets import draw_circle_2d
@@ -20,8 +19,8 @@ from gpu_extras.presets import draw_circle_2d
 offscreen = gpu.types.GPUOffScreen(512, 512)
 
 with offscreen.bind():
-    bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
-    bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
+    fb = gpu.state.active_framebuffer_get()
+    fb.clear(color=(0.0, 0.0, 0.0, 0.0))
     with gpu.matrix.push_pop():
         # reset matrices -> use normalized device coordinates [-1, 1]
         gpu.matrix.load_matrix(Matrix.Identity(4))
@@ -75,13 +74,10 @@ batch = batch_for_shader(
 
 
 def draw():
-    bgl.glActiveTexture(bgl.GL_TEXTURE0)
-    bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
-
     shader.bind()
     shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4))
     shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix)
-    shader.uniform_float("image", 0)
+    shader.uniform_sampler("image", offscreen.texture_color)
     batch.draw(shader)
 
 
index e67c601def96a0c1dadd6d3105d05638e1281972..664f14a23ca0ca1c619957f679dbf8e3144d7abd 100644 (file)
@@ -7,11 +7,10 @@ If it already exists, it will override the existing one.
 
 Currently almost all of the execution time is spent in the last line.
 In the future this will hopefully be solved by implementing the Python buffer protocol
-for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
+for :class:`gpu.types.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
 """
 import bpy
 import gpu
-import bgl
 import random
 from mathutils import Matrix
 from gpu_extras.presets import draw_circle_2d
@@ -25,8 +24,8 @@ RING_AMOUNT = 10
 offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
 
 with offscreen.bind():
-    bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
-    bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
+    fb = gpu.state.active_framebuffer_get()
+    fb.clear(color=(0.0, 0.0, 0.0, 0.0))
     with gpu.matrix.push_pop():
         # reset matrices -> use normalized device coordinates [-1, 1]
         gpu.matrix.load_matrix(Matrix.Identity(4))
@@ -37,9 +36,7 @@ with offscreen.bind():
                 (random.uniform(-1, 1), random.uniform(-1, 1)),
                 (1, 1, 1, 1), random.uniform(0.1, 1), 20)
 
-    buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
-    bgl.glReadBuffer(bgl.GL_BACK)
-    bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
+    buffer = fb.read_color(0, 0, WIDTH, HEIGHT, 4, 0, 'UBYTE')
 
 offscreen.free()
 
@@ -48,4 +45,6 @@ if not IMAGE_NAME in bpy.data.images:
     bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT)
 image = bpy.data.images[IMAGE_NAME]
 image.scale(WIDTH, HEIGHT)
+
+buffer.dimensions = WIDTH * HEIGHT * 4
 image.pixels = [v / 255 for v in buffer]
index a4db576ecc01309d5255f57bab9fe59a2ce83256..e358cb517bdfd96c73e54489da1d1e1b448d7abe 100644 (file)
@@ -7,7 +7,6 @@ You could also make this independent of a specific camera,
 but Blender does not expose good functions to create view and projection matrices yet.
 """
 import bpy
-import bgl
 import gpu
 from gpu_extras.presets import draw_texture_2d
 
@@ -34,8 +33,8 @@ def draw():
         view_matrix,
         projection_matrix)
 
-    bgl.glDisable(bgl.GL_DEPTH_TEST)
-    draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT)
+    gpu.state.depth_mask_set(False)
+    draw_texture_2d(offscreen.texture_color, (10, 10), WIDTH, HEIGHT)
 
 
 bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
diff --git a/doc/python_api/examples/mathutils.Matrix.LocRotScale.py b/doc/python_api/examples/mathutils.Matrix.LocRotScale.py
new file mode 100644 (file)
index 0000000..016a500
--- /dev/null
@@ -0,0 +1,5 @@
+# Compute local object transformation matrix:
+if obj.rotation_mode == 'QUATERNION':
+    matrix = mathutils.Matrix.LocRotScale(obj.location, obj.rotation_quaternion, obj.scale)
+else:
+    matrix = mathutils.Matrix.LocRotScale(obj.location, obj.rotation_euler, obj.scale)
index 26c7ccba27c5ba7438b059854d73851dbb7cf10b..84e09b97c1543b1ce701af9951aade581ec240c1 100644 (file)
@@ -14,10 +14,14 @@ mat_rot = mathutils.Matrix.Rotation(math.radians(45.0), 4, 'X')
 mat_out = mat_loc @ mat_rot @ mat_sca
 print(mat_out)
 
-# extract components back out of the matrix
+# extract components back out of the matrix as two vectors and a quaternion
 loc, rot, sca = mat_out.decompose()
 print(loc, rot, sca)
 
+# recombine extracted components
+mat_out2 = mathutils.Matrix.LocRotScale(loc, rot, sca)
+print(mat_out2)
+
 # it can also be useful to access components of a matrix directly
 mat = mathutils.Matrix()
 mat[0][0], mat[1][0], mat[2][0] = 0.0, 1.0, 2.0
index e5ff56063b567e37ec9ea70d333dda844c0ab609..df6e7297e2639d9917e4d610ee95504b8c65987f 100644 (file)
@@ -50,7 +50,8 @@ you should be able to find the poll function with no knowledge of C.
 
    Blender does have the functionality for poll functions to describe why they fail,
    but its currently not used much, if you're interested to help improve the API
-   feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails, e.g:
+   feel free to add calls to :class:`bpy.types.Operator.poll_message_set` (``CTX_wm_operator_poll_msg_set`` in C)
+   where its not obvious why poll fails, e.g:
 
       >>> bpy.ops.gpencil.draw()
       RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
index 107c233134e581746524d2e85ac585ba079fc915..032f8a86bd51c09cc5d8ad8a65b49a928b944753 100644 (file)
@@ -1036,7 +1036,6 @@ def pymodule2sphinx(basepath, module_name, module, title, module_all_extra):
 context_type_map = {
     # context_member: (RNA type, is_collection)
     "active_annotation_layer": ("GPencilLayer", False),
-    "active_base": ("ObjectBase", False),
     "active_bone": ("EditBone", False),
     "active_gpencil_frame": ("GreasePencilLayer", True),
     "active_gpencil_layer": ("GPencilLayer", True),
@@ -1556,8 +1555,8 @@ def pyrna2sphinx(basepath):
             fw(".. hlist::\n")
             fw("   :columns: 2\n\n")
 
-            # context does its own thing
-            # "active_base": ("ObjectBase", False),
+            # Context does its own thing.
+            # "active_object": ("Object", False),
             for ref_attr, (ref_type, ref_is_seq) in sorted(context_type_map.items()):
                 if ref_type == struct_id:
                     fw("   * :mod:`bpy.context.%s`\n" % ref_attr)
index 50a51ebe913e0c40f226e516878e5a7e7351f987..416ea25ee0c021b57849377cd612a38945a4ebf3 100644 (file)
@@ -322,7 +322,9 @@ static bool clg_ctx_filter_check(CLogContext *ctx, const char *identifier)
       if (flt->match[0] == '*' && flt->match[len - 1] == '*') {
         char *match = MEM_callocN(sizeof(char) * len - 1, __func__);
         memcpy(match, flt->match + 1, len - 2);
-        if (strstr(identifier, match) != NULL) {
+        const bool success = (strstr(identifier, match) != NULL);
+        MEM_freeN(match);
+        if (success) {
           return (bool)i;
         }
       }
index 67b852013f3ff4fa4a18d8e40dad401cecf6455a..7a1e5d62dd2f91a714f19c082144a2b987e72fd8 100644 (file)
@@ -71,6 +71,16 @@ if(WITH_CYCLES_STANDALONE)
   target_link_libraries(cycles ${LIBRARIES})
   cycles_target_link_libraries(cycles)
 
+  if(APPLE)
+    if(WITH_OPENCOLORIO)
+      set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework IOKit")
+    endif()
+    if(WITH_OPENIMAGEDENOISE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
+      # OpenImageDenoise uses BNNS from the Accelerate framework.
+      set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework Accelerate")
+    endif()
+  endif()
+
   if(UNIX AND NOT APPLE)
     set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
   endif()
index dfa696714fbb29bc867824f70a3d7953f5f1965c..d8398772a846f2365f5fdf6c31fb2e8c0f78710b 100644 (file)
@@ -19,16 +19,16 @@ from __future__ import annotations
 
 
 def _is_using_buggy_driver():
-    import bgl
+    import gpu
     # We need to be conservative here because in multi-GPU systems display card
     # might be quite old, but others one might be just good.
     #
     # So We shouldn't disable possible good dedicated cards just because display
     # card seems weak. And instead we only blacklist configurations which are
     # proven to cause problems.
-    if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
+    if gpu.platform.vendor_get() == "ATI Technologies Inc.":
         import re
-        version = bgl.glGetString(bgl.GL_VERSION)
+        version = gpu.platform.version_get()
         if version.endswith("Compatibility Profile Context"):
             # Old HD 4xxx and 5xxx series drivers did not have driver version
             # in the version string, but those cards do not quite work and
index dcf6e3cc949d5a9a014ad99143ee9326bedaef90..cb84013c5511f522ff2695d2120506eb82a74ab5 100644 (file)
@@ -564,10 +564,12 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
   if (!cancel && !motion) {
     sync_background_light(b_v3d, use_portal);
 
-    /* handle removed data and modified pointers */
+    /* Handle removed data and modified pointers, as this may free memory, delete Nodes in the
+     * right order to ensure that dependent data is freed after their users. Objects should be
+     * freed before particle systems and geometries. */
     light_map.post_sync();
-    geometry_map.post_sync();
     object_map.post_sync();
+    geometry_map.post_sync();
     particle_system_map.post_sync();
   }
 
index 4af8da402b188ee397e4a3b6d261d3fadb7474c3..9d0f9f29f9472b73461e7bea3144ca90df7c2905 100644 (file)
@@ -69,7 +69,8 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
       experimental(false),
       dicing_rate(1.0f),
       max_subdivisions(12),
-      progress(progress)
+      progress(progress),
+      has_updates_(true)
 {
   PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
   dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") :
@@ -84,7 +85,9 @@ BlenderSync::~BlenderSync()
 void BlenderSync::reset(BL::BlendData &b_data, BL::Scene &b_scene)
 {
   /* Update data and scene pointers in case they change in session reset,
-   * for example after undo. */
+   * for example after undo.
+   * Note that we do not modify the `has_updates_` flag here because the sync
+   * reset is also used during viewport navigation. */
   this->b_data = b_data;
   this->b_scene = b_scene;
 }
@@ -117,6 +120,8 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
     }
 
     if (dicing_prop_changed) {
+      has_updates_ = true;
+
       for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
         Geometry *geom = iter.second;
         if (geom->is_mesh()) {
@@ -133,6 +138,12 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
 
   /* Iterate over all IDs in this depsgraph. */
   for (BL::DepsgraphUpdate &b_update : b_depsgraph.updates) {
+    /* TODO(sergey): Can do more selective filter here. For example, ignore changes made to
+     * screen datablock. Note that sync_data() needs to be called after object deletion, and
+     * currently this is ensured by the scene ID tagged for update, which sets the `has_updates_`
+     * flag. */
+    has_updates_ = true;
+
     BL::ID b_id(b_update.id());
 
     /* Material */
@@ -227,6 +238,10 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
                             int height,
                             void **python_thread_state)
 {
+  if (!has_updates_) {
+    return;
+  }
+
   scoped_timer timer;
 
   BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
@@ -254,6 +269,8 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
   free_data_after_sync(b_depsgraph);
 
   VLOG(1) << "Total time spent synchronizing data: " << timer.get_time();
+
+  has_updates_ = false;
 }
 
 /* Integrator */
index a222c5e490e604e53f6ea3ee2e392ca952e4baba..15a10f2b46b0165438dda1ededbe607450d9ed33 100644 (file)
@@ -264,6 +264,12 @@ class BlenderSync {
   } view_layer;
 
   Progress &progress;
+
+ protected:
+  /* Indicates that `sync_recalc()` detected changes in the scene.
+   * If this flag is false then the data is considered to be up-to-date and will not be
+   * synchronized at all. */
+  bool has_updates_ = true;
 };
 
 CCL_NAMESPACE_END
index bb6027254f9da15819fbb93b81e0253a87fa3abf..01de0724cb2958ad52d5b316cabc02377cd44ccd 100644 (file)
@@ -960,14 +960,21 @@ class OptiXDevice : public CUDADevice {
         // Create OptiX denoiser handle on demand when it is first used
         OptixDenoiserOptions denoiser_options = {};
         assert(task.denoising.input_passes >= 1 && task.denoising.input_passes <= 3);
+#  if OPTIX_ABI_VERSION >= 47
+        denoiser_options.guideAlbedo = task.denoising.input_passes >= 2;
+        denoiser_options.guideNormal = task.denoising.input_passes >= 3;
+        check_result_optix_ret(optixDenoiserCreate(
+            context, OPTIX_DENOISER_MODEL_KIND_HDR, &denoiser_options, &denoiser));
+#  else
         denoiser_options.inputKind = static_cast<OptixDenoiserInputKind>(
             OPTIX_DENOISER_INPUT_RGB + (task.denoising.input_passes - 1));
-#  if OPTIX_ABI_VERSION < 28
+#    if OPTIX_ABI_VERSION < 28
         denoiser_options.pixelFormat = OPTIX_PIXEL_FORMAT_FLOAT3;
-#  endif
+#    endif
         check_result_optix_ret(optixDenoiserCreate(context, &denoiser_options, &denoiser));
         check_result_optix_ret(
             optixDenoiserSetModel(denoiser, OPTIX_DENOISER_MODEL_KIND_HDR, NULL, 0));
+#  endif
 
         // OptiX denoiser handle was created with the requested number of input passes
         denoiser_input_passes = task.denoising.input_passes;
@@ -1037,10 +1044,34 @@ class OptiXDevice : public CUDADevice {
 #  endif
       output_layers[0].format = OPTIX_PIXEL_FORMAT_FLOAT3;
 
+#  if OPTIX_ABI_VERSION >= 47
+      OptixDenoiserLayer image_layers = {};
+      image_layers.input = input_layers[0];
+      image_layers.output = output_layers[0];
+
+      OptixDenoiserGuideLayer guide_layers = {};
+      guide_layers.albedo = input_layers[1];
+      guide_layers.normal = input_layers[2];
+#  endif
+
       // Finally run denonising
       OptixDenoiserParams params = {};  // All parameters are disabled/zero
+#  if OPTIX_ABI_VERSION >= 47
       check_result_optix_ret(optixDenoiserInvoke(denoiser,
-                                                 0,
+                                                 NULL,
+                                                 &params,
+                                                 denoiser_state.device_pointer,
+                                                 scratch_offset,
+                                                 &guide_layers,
+                                                 &image_layers,
+                                                 1,
+                                                 overlap_offset.x,
+                                                 overlap_offset.y,
+                                                 denoiser_state.device_pointer + scratch_offset,
+                                                 scratch_size));
+#  else
+      check_result_optix_ret(optixDenoiserInvoke(denoiser,
+                                                 NULL,
                                                  &params,
                                                  denoiser_state.device_pointer,
                                                  scratch_offset,
@@ -1051,6 +1082,7 @@ class OptiXDevice : public CUDADevice {
                                                  output_layers,
                                                  denoiser_state.device_pointer + scratch_offset,
                                                  scratch_size));
+#  endif
 
 #  if OPTIX_DENOISER_NO_PIXEL_STRIDE
       void *output_args[] = {&input_ptr,
index c926f6ab8ef267d83aa6ae220ec5917715e7ce75..57f25283f853ca895675e30b189d7e8937be8e6c 100644 (file)
@@ -367,9 +367,17 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT
       case SocketType::TRANSFORM_ARRAY:
         copy_array<Transform>(this, socket, &other, other_socket);
         break;
-      case SocketType::NODE_ARRAY:
+      case SocketType::NODE_ARRAY: {
         copy_array<void *>(this, socket, &other, other_socket);
+
+        array<Node *> &node_array = get_socket_value<array<Node *>>(this, socket);
+
+        for (Node *node : node_array) {
+          node->reference();
+        }
+
         break;
+      }
       default:
         assert(0);
         break;
@@ -379,6 +387,14 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT
     const void *src = ((char *)&other) + other_socket.struct_offset;
     void *dst = ((char *)this) + socket.struct_offset;
     memcpy(dst, src, socket.size());
+
+    if (socket.type == SocketType::NODE) {
+      Node *node = get_socket_value<Node *>(this, socket);
+
+      if (node) {
+        node->reference();
+      }
+    }
   }
 }
 
@@ -773,6 +789,26 @@ void Node::set_owner(const NodeOwner *owner_)
   owner = owner_;
 }
 
+void Node::dereference_all_used_nodes()
+{
+  foreach (const SocketType &socket, type->inputs) {
+    if (socket.type == SocketType::NODE) {
+      Node *node = get_socket_value<Node *>(this, socket);
+
+      if (node) {
+        node->dereference();
+      }
+    }
+    else if (socket.type == SocketType::NODE_ARRAY) {
+      const array<Node *> &nodes = get_socket_value<array<Node *>>(this, socket);
+
+      for (Node *node : nodes) {
+        node->dereference();
+      }
+    }
+  }
+}
+
 bool Node::socket_is_modified(const SocketType &input) const
 {
   return (socket_modified & input.modified_flag_bit) != 0;
@@ -803,6 +839,25 @@ template<typename T> void Node::set_if_different(const SocketType &input, T valu
   socket_modified |= input.modified_flag_bit;
 }
 
+void Node::set_if_different(const SocketType &input, Node *value)
+{
+  if (get_socket_value<Node *>(this, input) == value) {
+    return;
+  }
+
+  Node *old_node = get_socket_value<Node *>(this, input);
+  if (old_node) {
+    old_node->dereference();
+  }
+
+  if (value) {
+    value->reference();
+  }
+
+  get_socket_value<Node *>(this, input) = value;
+  socket_modified |= input.modified_flag_bit;
+}
+
 template<typename T> void Node::set_if_different(const SocketType &input, array<T> &value)
 {
   if (!socket_is_modified(input)) {
@@ -815,6 +870,27 @@ template<typename T> void Node::set_if_different(const SocketType &input, array<
   socket_modified |= input.modified_flag_bit;
 }
 
+void Node::set_if_different(const SocketType &input, array<Node *> &value)
+{
+  if (!socket_is_modified(input)) {
+    if (get_socket_value<array<Node *>>(this, input) == value) {
+      return;
+    }
+  }
+
+  array<Node *> &old_nodes = get_socket_value<array<Node *>>(this, input);
+  for (Node *old_node : old_nodes) {
+    old_node->dereference();
+  }
+
+  for (Node *new_node : value) {
+    new_node->reference();
+  }
+
+  get_socket_value<array<Node *>>(this, input).steal_data(value);
+  socket_modified |= input.modified_flag_bit;
+}
+
 void Node::print_modified_sockets() const
 {
   printf("Node : %s\n", name.c_str());
index 2fc9a1e028163f7847d4318919326eee7059b818..aa365baeccdeed4aa04c8025ac64af24f011d838 100644 (file)
@@ -177,8 +177,32 @@ struct Node {
   const NodeOwner *get_owner() const;
   void set_owner(const NodeOwner *owner_);
 
+  int reference_count() const
+  {
+    return ref_count;
+  }
+
+  void reference()
+  {
+    ref_count += 1;
+  }
+
+  void dereference()
+  {
+    ref_count -= 1;
+  }
+
+  /* Set the reference count to zero. This should only be called when we know for sure that the
+   * Node is not used by anyone else. For now, this is only the case when "deleting" shaders, as
+   * they are never actually deleted. */
+  void clear_reference_count()
+  {
+    ref_count = 0;
+  }
+
  protected:
   const NodeOwner *owner;
+  int ref_count{0};
 
   template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
   {
@@ -189,7 +213,19 @@ struct Node {
 
   template<typename T> void set_if_different(const SocketType &input, T value);
 
+  /* Explicit overload for Node sockets so we can handle reference counting. The old Node is
+   * dereferenced, and the new one is referenced. */
+  void set_if_different(const SocketType &input, Node *value);
+
   template<typename T> void set_if_different(const SocketType &input, array<T> &value);
+
+  /* Explicit overload for Node sockets so we can handle reference counting. The old Nodes are
+   * dereferenced, and the new ones are referenced. */
+  void set_if_different(const SocketType &input, array<Node *> &value);
+
+  /* Call this function in derived classes' destructors to ensure that used Nodes are dereferenced
+   * properly. */
+  void dereference_all_used_nodes();
 };
 
 CCL_NAMESPACE_END
index f6b4b963a7afcf7c81c2c95f29a2986fd6360787..ea0f16c923399f770bb6f806aa368fd63d367fd9 100644 (file)
@@ -93,6 +93,7 @@ set(SRC_BVH_HEADERS
   bvh/bvh_local.h
   bvh/bvh_traversal.h
   bvh/bvh_types.h
+  bvh/bvh_util.h
   bvh/bvh_volume.h
   bvh/bvh_volume_all.h
   bvh/bvh_embree.h
index 3049f243ae9e17e75ab8680340b9608ac5fc5ad1..3a3f38539c5ddd4d09d7bb26856ba27ee27c62e8 100644 (file)
 #  include "kernel/bvh/bvh_embree.h"
 #endif
 
-CCL_NAMESPACE_BEGIN
-
 #include "kernel/bvh/bvh_types.h"
+#include "kernel/bvh/bvh_util.h"
+
+CCL_NAMESPACE_BEGIN
 
 #ifndef __KERNEL_OPTIX__
 
@@ -533,97 +534,4 @@ ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
 }
 #endif /* __VOLUME_RECORD_ALL__ */
 
-/* Ray offset to avoid self intersection.
- *
- * This function should be used to compute a modified ray start position for
- * rays leaving from a surface. */
-
-ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
-{
-#ifdef __INTERSECTION_REFINE__
-  const float epsilon_f = 1e-5f;
-  /* ideally this should match epsilon_f, but instancing and motion blur
-   * precision makes it problematic */
-  const float epsilon_test = 1.0f;
-  const int epsilon_i = 32;
-
-  float3 res;
-
-  /* x component */
-  if (fabsf(P.x) < epsilon_test) {
-    res.x = P.x + Ng.x * epsilon_f;
-  }
-  else {
-    uint ix = __float_as_uint(P.x);
-    ix += ((ix ^ __float_as_uint(Ng.x)) >> 31) ? -epsilon_i : epsilon_i;
-    res.x = __uint_as_float(ix);
-  }
-
-  /* y component */
-  if (fabsf(P.y) < epsilon_test) {
-    res.y = P.y + Ng.y * epsilon_f;
-  }
-  else {
-    uint iy = __float_as_uint(P.y);
-    iy += ((iy ^ __float_as_uint(Ng.y)) >> 31) ? -epsilon_i : epsilon_i;
-    res.y = __uint_as_float(iy);
-  }
-
-  /* z component */
-  if (fabsf(P.z) < epsilon_test) {
-    res.z = P.z + Ng.z * epsilon_f;
-  }
-  else {
-    uint iz = __float_as_uint(P.z);
-    iz += ((iz ^ __float_as_uint(Ng.z)) >> 31) ? -epsilon_i : epsilon_i;
-    res.z = __uint_as_float(iz);
-  }
-
-  return res;
-#else
-  const float epsilon_f = 1e-4f;
-  return P + epsilon_f * Ng;
-#endif
-}
-
-#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
-/* ToDo: Move to another file? */
-ccl_device int intersections_compare(const void *a, const void *b)
-{
-  const Intersection *isect_a = (const Intersection *)a;
-  const Intersection *isect_b = (const Intersection *)b;
-
-  if (isect_a->t < isect_b->t)
-    return -1;
-  else if (isect_a->t > isect_b->t)
-    return 1;
-  else
-    return 0;
-}
-#endif
-
-#if defined(__SHADOW_RECORD_ALL__)
-ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
-{
-#  ifdef __KERNEL_GPU__
-  /* Use bubble sort which has more friendly memory pattern on GPU. */
-  bool swapped;
-  do {
-    swapped = false;
-    for (int j = 0; j < num_hits - 1; ++j) {
-      if (hits[j].t > hits[j + 1].t) {
-        struct Intersection tmp = hits[j];
-        hits[j] = hits[j + 1];
-        hits[j + 1] = tmp;
-        swapped = true;
-      }
-    }
-    --num_hits;
-  } while (swapped);
-#  else
-  qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-#  endif
-}
-#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
-
 CCL_NAMESPACE_END
index dccd257d2de6f2f4a0489012c1c319db1170cb83..2e94b1d7c37b552d555687239ff95aa6dad0c70a 100644 (file)
@@ -180,25 +180,10 @@ ccl_device_inline
 
               /* todo: optimize so primitive visibility flag indicates if
                * the primitive has a transparent shadow shader? */
-              int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
-              int shader = 0;
-
-#ifdef __HAIR__
-              if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
-#endif
-              {
-                shader = kernel_tex_fetch(__tri_shader, prim);
-              }
-#ifdef __HAIR__
-              else {
-                float4 str = kernel_tex_fetch(__curves, prim);
-                shader = __float_as_int(str.z);
-              }
-#endif
-              int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+              const int flags = intersection_get_shader_flags(kg, isect_array);
 
               /* if no transparent shadows, all light is blocked */
-              if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+              if (!(flags & SD_HAS_TRANSPARENT_SHADOW)) {
                 return true;
               }
               /* if maximum number of hits reached, block all light */
diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h
new file mode 100644 (file)
index 0000000..a694e4d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+CCL_NAMESPACE_BEGIN
+
+/* Ray offset to avoid self intersection.
+ *
+ * This function should be used to compute a modified ray start position for
+ * rays leaving from a surface. */
+
+ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
+{
+#ifdef __INTERSECTION_REFINE__
+  const float epsilon_f = 1e-5f;
+  /* ideally this should match epsilon_f, but instancing and motion blur
+   * precision makes it problematic */
+  const float epsilon_test = 1.0f;
+  const int epsilon_i = 32;
+
+  float3 res;
+
+  /* x component */
+  if (fabsf(P.x) < epsilon_test) {
+    res.x = P.x + Ng.x * epsilon_f;
+  }
+  else {
+    uint ix = __float_as_uint(P.x);
+    ix += ((ix ^ __float_as_uint(Ng.x)) >> 31) ? -epsilon_i : epsilon_i;
+    res.x = __uint_as_float(ix);
+  }
+
+  /* y component */
+  if (fabsf(P.y) < epsilon_test) {
+    res.y = P.y + Ng.y * epsilon_f;
+  }
+  else {
+    uint iy = __float_as_uint(P.y);
+    iy += ((iy ^ __float_as_uint(Ng.y)) >> 31) ? -epsilon_i : epsilon_i;
+    res.y = __uint_as_float(iy);
+  }
+
+  /* z component */
+  if (fabsf(P.z) < epsilon_test) {
+    res.z = P.z + Ng.z * epsilon_f;
+  }
+  else {
+    uint iz = __float_as_uint(P.z);
+    iz += ((iz ^ __float_as_uint(Ng.z)) >> 31) ? -epsilon_i : epsilon_i;
+    res.z = __uint_as_float(iz);
+  }
+
+  return res;
+#else
+  const float epsilon_f = 1e-4f;
+  return P + epsilon_f * Ng;
+#endif
+}
+
+#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
+/* ToDo: Move to another file? */
+ccl_device int intersections_compare(const void *a, const void *b)
+{
+  const Intersection *isect_a = (const Intersection *)a;
+  const Intersection *isect_b = (const Intersection *)b;
+
+  if (isect_a->t < isect_b->t)
+    return -1;
+  else if (isect_a->t > isect_b->t)
+    return 1;
+  else
+    return 0;
+}
+#endif
+
+#if defined(__SHADOW_RECORD_ALL__)
+ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
+{
+  kernel_assert(num_hits > 0);
+
+#  ifdef __KERNEL_GPU__
+  /* Use bubble sort which has more friendly memory pattern on GPU. */
+  bool swapped;
+  do {
+    swapped = false;
+    for (int j = 0; j < num_hits - 1; ++j) {
+      if (hits[j].t > hits[j + 1].t) {
+        struct Intersection tmp = hits[j];
+        hits[j] = hits[j + 1];
+        hits[j + 1] = tmp;
+        swapped = true;
+      }
+    }
+    --num_hits;
+  } while (swapped);
+#  else
+  qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+#  endif
+}
+#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
+
+/* Utility to quickly get a shader flags from an intersection. */
+
+ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals *ccl_restrict kg,
+                                                         const Intersection *isect)
+{
+  const int prim = kernel_tex_fetch(__prim_index, isect->prim);
+  int shader = 0;
+
+#ifdef __HAIR__
+  if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE)
+#endif
+  {
+    shader = kernel_tex_fetch(__tri_shader, prim);
+  }
+#ifdef __HAIR__
+  else {
+    float4 str = kernel_tex_fetch(__curves, prim);
+    shader = __float_as_int(str.z);
+  }
+#endif
+
+  return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+}
+
+ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict kg,
+                                                   const Intersection *isect)
+{
+  const int prim = kernel_tex_fetch(__prim_index, isect->prim);
+  int shader = 0;
+
+#ifdef __HAIR__
+  if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE)
+#endif
+  {
+    shader = kernel_tex_fetch(__tri_shader, prim);
+  }
+#ifdef __HAIR__
+  else {
+    float4 str = kernel_tex_fetch(__curves, prim);
+    shader = __float_as_int(str.z);
+  }
+#endif
+
+  return shader & SHADER_MASK;
+}
+
+CCL_NAMESPACE_END
index 5681510fc25dff5e6055246a5c37d0e2a84d8435..dd2390808ea00f31c78d3055c3c15ffb335bc05e 100644 (file)
@@ -65,7 +65,6 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg,
   uint visibility = path_state_ray_visibility(kg, state);
 
   if (path_state_ao_bounce(kg, state)) {
-    visibility = PATH_RAY_SHADOW;
     ray->t = kernel_data.background.ao_distance;
   }
 
@@ -416,7 +415,13 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
         break;
       }
       else if (path_state_ao_bounce(kg, state)) {
-        break;
+        if (intersection_get_shader_flags(kg, &isect) &
+            (SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
+          state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+        }
+        else {
+          break;
+        }
       }
 
       /* Setup shader data. */
@@ -554,7 +559,13 @@ ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg,
         break;
       }
       else if (path_state_ao_bounce(kg, state)) {
-        break;
+        if (intersection_get_shader_flags(kg, &isect) &
+            (SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
+          state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+        }
+        else {
+          break;
+        }
       }
 
       /* Setup shader data. */
index c661d77edb1f74ba1f640e2fadf0a7eeaa85f08d..74fa2826cd43f21759915093d6e86f7ced003b3a 100644 (file)
@@ -891,6 +891,8 @@ enum ShaderDataFlag {
   SD_HAS_CONSTANT_EMISSION = (1 << 27),
   /* Needs to access attributes for volume rendering */
   SD_NEED_VOLUME_ATTRIBUTES = (1 << 28),
+  /* Shader has emission */
+  SD_HAS_EMISSION = (1 << 29),
 
   SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME |
                      SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR |
index c67919b375a35a8f1e79246edff07e7129fcd51c..feead27c5ca192e30ae89495873ac3775ca29983 100644 (file)
@@ -24,6 +24,7 @@ set(INC_SYS
 
 set(SRC
   alembic.cpp
+  alembic_read.cpp
   attribute.cpp
   background.cpp
   bake.cpp
@@ -67,6 +68,7 @@ set(SRC
 
 set(SRC_HEADERS
   alembic.h
+  alembic_read.h
   attribute.h
   bake.h
   background.h
index c3a7b20f512ef2bec63ec38961603d38dc814722..cf345ee075d6193306d9c53ee425d6faffc4341a 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "render/alembic.h"
 
+#include "render/alembic_read.h"
 #include "render/camera.h"
 #include "render/curves.h"
 #include "render/mesh.h"
@@ -34,7 +35,48 @@ using namespace Alembic::AbcGeom;
 
 CCL_NAMESPACE_BEGIN
 
-/* TODO(@kevindietrich): motion blur support */
+/* TODO(kevindietrich): motion blur support. */
+
+template<typename SchemaType>
+static vector<FaceSetShaderIndexPair> parse_face_sets_for_shader_assignment(
+    SchemaType &schema, const array<Node *> &used_shaders)
+{
+  vector<FaceSetShaderIndexPair> result;
+
+  std::vector<std::string> face_set_names;
+  schema.getFaceSetNames(face_set_names);
+
+  if (face_set_names.empty()) {
+    return result;
+  }
+
+  for (const std::string &face_set_name : face_set_names) {
+    int shader_index = 0;
+
+    for (Node *node : used_shaders) {
+      if (node->name == face_set_name) {
+        break;
+      }
+
+      ++shader_index;
+    }
+
+    if (shader_index >= used_shaders.size()) {
+      /* use the first shader instead if none was found */
+      shader_index = 0;
+    }
+
+    const Alembic::AbcGeom::IFaceSet face_set = schema.getFaceSet(face_set_name);
+
+    if (!face_set.valid()) {
+      continue;
+    }
+
+    result.push_back({face_set, shader_index});
+  }
+
+  return result;
+}
 
 void CachedData::clear()
 {
@@ -54,7 +96,7 @@ void CachedData::clear()
   subd_start_corner.clear();
   transforms.clear();
   triangles.clear();
-  triangles_loops.clear();
+  uv_loops.clear();
   vertices.clear();
 
   for (CachedAttribute &attr : attributes) {
@@ -101,7 +143,7 @@ bool CachedData::is_constant() const
   CHECK_IF_CONSTANT(subd_start_corner)
   CHECK_IF_CONSTANT(transforms)
   CHECK_IF_CONSTANT(triangles)
-  CHECK_IF_CONSTANT(triangles_loops)
+  CHECK_IF_CONSTANT(uv_loops)
   CHECK_IF_CONSTANT(vertices)
 
   for (const CachedAttribute &attr : attributes) {
@@ -140,7 +182,7 @@ void CachedData::invalidate_last_loaded_time(bool attributes_only)
   subd_start_corner.invalidate_last_loaded_time();
   transforms.invalidate_last_loaded_time();
   triangles.invalidate_last_loaded_time();
-  triangles_loops.invalidate_last_loaded_time();
+  uv_loops.invalidate_last_loaded_time();
   vertices.invalidate_last_loaded_time();
 }
 
@@ -161,7 +203,7 @@ void CachedData::set_time_sampling(TimeSampling time_sampling)
   subd_start_corner.set_time_sampling(time_sampling);
   transforms.set_time_sampling(time_sampling);
   triangles.set_time_sampling(time_sampling);
-  triangles_loops.set_time_sampling(time_sampling);
+  uv_loops.set_time_sampling(time_sampling);
   vertices.set_time_sampling(time_sampling);
 
   for (CachedAttribute &attr : attributes) {
@@ -169,36 +211,6 @@ void CachedData::set_time_sampling(TimeSampling time_sampling)
   }
 }
 
-/* get the sample times to load data for the given the start and end frame of the procedural */
-static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
-                                               const TimeSampling &time_sampling,
-                                               size_t num_samples)
-{
-  set<chrono_t> result;
-
-  if (num_samples < 2) {
-    result.insert(0.0);
-    return result;
-  }
-
-  double start_frame = (double)(proc->get_start_frame() / proc->get_frame_rate());
-  double end_frame = (double)((proc->get_end_frame() + 1) / proc->get_frame_rate());
-
-  size_t start_index = time_sampling.getFloorIndex(start_frame, num_samples).first;
-  size_t end_index = time_sampling.getCeilIndex(end_frame, num_samples).first;
-
-  for (size_t i = start_index; i < end_index; ++i) {
-    result.insert(time_sampling.getSampleTime(i));
-  }
-
-  return result;
-}
-
-static float3 make_float3_from_yup(const V3f &v)
-{
-  return make_float3(v.x, -v.z, v.y);
-}
-
 static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
 {
   V3d scale, shear, rotation, translation;
@@ -366,249 +378,6 @@ static Transform make_transform(const M44d &a, float scale)
   return trans;
 }
 
-static void add_uvs(AlembicProcedural *proc,
-                    const IV2fGeomParam &uvs,
-                    CachedData &cached_data,
-                    Progress &progress)
-{
-  if (uvs.getScope() != kFacevaryingScope) {
-    return;
-  }
-
-  const TimeSamplingPtr time_sampling_ptr = uvs.getTimeSampling();
-
-  TimeSampling time_sampling;
-  if (time_sampling_ptr) {
-    time_sampling = *time_sampling_ptr;
-  }
-
-  std::string name = Alembic::Abc::GetSourceName(uvs.getMetaData());
-
-  /* According to the convention, primary UVs should have had their name
-   * set using Alembic::Abc::SetSourceName, but you can't expect everyone
-   * to follow it! :) */
-  if (name.empty()) {
-    name = uvs.getName();
-  }
-
-  CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(name), time_sampling);
-  attr.std = ATTR_STD_UV;
-
-  ccl::set<chrono_t> times = get_relevant_sample_times(proc, time_sampling, uvs.getNumSamples());
-
-  /* Keys used to determine if the UVs do actually change over time. */
-  ArraySample::Key previous_indices_key;
-  ArraySample::Key previous_values_key;
-
-  foreach (chrono_t time, times) {
-    if (progress.get_cancel()) {
-      return;
-    }
-
-    const ISampleSelector iss = ISampleSelector(time);
-    const IV2fGeomParam::Sample uvsample = uvs.getIndexedValue(iss);
-
-    if (!uvsample.valid()) {
-      continue;
-    }
-
-    const array<int3> *triangles =
-        cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
-    const array<int3> *triangles_loops =
-        cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null();
-
-    if (!triangles || !triangles_loops) {
-      continue;
-    }
-
-    array<char> data;
-    data.resize(triangles->size() * 3 * sizeof(float2));
-
-    float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
-
-    const ArraySample::Key indices_key = uvsample.getIndices()->getKey();
-    const ArraySample::Key values_key = uvsample.getVals()->getKey();
-
-    if (indices_key == previous_indices_key && values_key == previous_values_key) {
-      attr.data.reuse_data_for_last_time(time);
-    }
-    else {
-      const unsigned int *indices = uvsample.getIndices()->get();
-      const V2f *values = uvsample.getVals()->get();
-
-      for (const int3 &loop : *triangles_loops) {
-        unsigned int v0 = indices[loop.x];
-        unsigned int v1 = indices[loop.y];
-        unsigned int v2 = indices[loop.z];
-
-        data_float2[0] = make_float2(values[v0][0], values[v0][1]);
-        data_float2[1] = make_float2(values[v1][0], values[v1][1]);
-        data_float2[2] = make_float2(values[v2][0], values[v2][1]);
-        data_float2 += 3;
-      }
-
-      attr.data.add_data(data, time);
-    }
-
-    previous_indices_key = indices_key;
-    previous_values_key = values_key;
-  }
-}
-
-static void add_normals(const Int32ArraySamplePtr face_indices,
-                        const IN3fGeomParam &normals,
-                        double time,
-                        CachedData &cached_data)
-{
-  switch (normals.getScope()) {
-    case kFacevaryingScope: {
-      const ISampleSelector iss = ISampleSelector(time);
-      const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
-
-      if (!sample.valid()) {
-        return;
-      }
-
-      CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
-                                                                    *normals.getTimeSampling());
-      attr.std = ATTR_STD_VERTEX_NORMAL;
-
-      const array<float3> *vertices =
-          cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
-
-      if (!vertices) {
-        return;
-      }
-
-      array<char> data;
-      data.resize(vertices->size() * sizeof(float3));
-
-      float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
-
-      const int *face_indices_array = face_indices->get();
-      const N3fArraySamplePtr values = sample.getVals();
-
-      for (size_t i = 0; i < face_indices->size(); ++i) {
-        int point_index = face_indices_array[i];
-        data_float3[point_index] = make_float3_from_yup(values->get()[i]);
-      }
-
-      attr.data.add_data(data, time);
-      break;
-    }
-    case kVaryingScope:
-    case kVertexScope: {
-      const ISampleSelector iss = ISampleSelector(time);
-      const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
-
-      if (!sample.valid()) {
-        return;
-      }
-
-      CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
-                                                                    *normals.getTimeSampling());
-      attr.std = ATTR_STD_VERTEX_NORMAL;
-
-      const array<float3> *vertices =
-          cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
-
-      if (!vertices) {
-        return;
-      }
-
-      array<char> data;
-      data.resize(vertices->size() * sizeof(float3));
-
-      float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
-
-      const Imath::V3f *values = sample.getVals()->get();
-
-      for (size_t i = 0; i < vertices->size(); ++i) {
-        data_float3[i] = make_float3_from_yup(values[i]);
-      }
-
-      attr.data.add_data(data, time);
-
-      break;
-    }
-    default: {
-      break;
-    }
-  }
-}
-
-static void add_positions(const P3fArraySamplePtr positions, double time, CachedData &cached_data)
-{
-  if (!positions) {
-    return;
-  }
-
-  array<float3> vertices;
-  vertices.reserve(positions->size());
-
-  for (size_t i = 0; i < positions->size(); i++) {
-    V3f f = positions->get()[i];
-    vertices.push_back_reserved(make_float3_from_yup(f));
-  }
-
-  cached_data.vertices.add_data(vertices, time);
-}
-
-static void add_triangles(const Int32ArraySamplePtr face_counts,
-                          const Int32ArraySamplePtr face_indices,
-                          double time,
-                          CachedData &cached_data,
-                          const array<int> &polygon_to_shader)
-{
-  if (!face_counts || !face_indices) {
-    return;
-  }
-
-  const size_t num_faces = face_counts->size();
-  const int *face_counts_array = face_counts->get();
-  const int *face_indices_array = face_indices->get();
-
-  size_t num_triangles = 0;
-  for (size_t i = 0; i < face_counts->size(); i++) {
-    num_triangles += face_counts_array[i] - 2;
-  }
-
-  array<int> shader;
-  array<int3> triangles;
-  array<int3> triangles_loops;
-  shader.reserve(num_triangles);
-  triangles.reserve(num_triangles);
-  triangles_loops.reserve(num_triangles);
-  int index_offset = 0;
-
-  for (size_t i = 0; i < num_faces; i++) {
-    int current_shader = 0;
-
-    if (!polygon_to_shader.empty()) {
-      current_shader = polygon_to_shader[i];
-    }
-
-    for (int j = 0; j < face_counts_array[i] - 2; j++) {
-      int v0 = face_indices_array[index_offset];
-      int v1 = face_indices_array[index_offset + j + 1];
-      int v2 = face_indices_array[index_offset + j + 2];
-
-      shader.push_back_reserved(current_shader);
-
-      /* Alembic orders the loops following the RenderMan convention, so need to go in reverse. */
-      triangles.push_back_reserved(make_int3(v2, v1, v0));
-      triangles_loops.push_back_reserved(
-          make_int3(index_offset + j + 2, index_offset + j + 1, index_offset));
-    }
-
-    index_offset += face_counts_array[i];
-  }
-
-  cached_data.triangles.add_data(triangles, time);
-  cached_data.triangles_loops.add_data(triangles_loops, time);
-  cached_data.shader.add_data(shader, time);
-}
-
 NODE_DEFINE(AlembicObject)
 {
   NodeType *type = NodeType::add("alembic_object", create);
@@ -648,398 +417,137 @@ bool AlembicObject::has_data_loaded() const
   return data_loaded;
 }
 
-void AlembicObject::update_shader_attributes(const ICompoundProperty &arb_geom_params,
-                                             Progress &progress)
-{
-  AttributeRequestSet requested_attributes = get_requested_attributes();
-
-  foreach (const AttributeRequest &attr, requested_attributes.requests) {
-    if (progress.get_cancel()) {
-      return;
-    }
-
-    bool attr_exists = false;
-    foreach (CachedData::CachedAttribute &cached_attr, cached_data.attributes) {
-      if (cached_attr.name == attr.name) {
-        attr_exists = true;
-        break;
-      }
-    }
-
-    if (attr_exists) {
-      continue;
-    }
-
-    read_attribute(arb_geom_params, attr.name, progress);
-  }
-
-  cached_data.invalidate_last_loaded_time(true);
-  need_shader_update = false;
-}
-
-template<typename SchemaType>
-void AlembicObject::read_face_sets(SchemaType &schema,
-                                   array<int> &polygon_to_shader,
-                                   ISampleSelector sample_sel)
+void AlembicObject::load_data_in_cache(CachedData &cached_data,
+                                       AlembicProcedural *proc,
+                                       IPolyMeshSchema &schema,
+                                       Progress &progress)
 {
-  std::vector<std::string> face_sets;
-  schema.getFaceSetNames(face_sets);
-
-  if (face_sets.empty()) {
-    return;
-  }
-
-  const Int32ArraySamplePtr face_counts = schema.getFaceCountsProperty().getValue();
-
-  polygon_to_shader.resize(face_counts->size());
-
-  foreach (const std::string &face_set_name, face_sets) {
-    int shader_index = 0;
-
-    foreach (Node *node, get_used_shaders()) {
-      if (node->name == face_set_name) {
-        break;
-      }
-
-      ++shader_index;
-    }
-
-    if (shader_index >= get_used_shaders().size()) {
-      /* use the first shader instead if none was found */
-      shader_index = 0;
-    }
-
-    const IFaceSet face_set = schema.getFaceSet(face_set_name);
-
-    if (!face_set.valid()) {
-      continue;
-    }
-
-    const IFaceSetSchema face_schem = face_set.getSchema();
-    const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
-    const Int32ArraySamplePtr group_faces = face_sample.getFaces();
-    const size_t num_group_faces = group_faces->size();
-
-    for (size_t l = 0; l < num_group_faces; l++) {
-      size_t pos = (*group_faces)[l];
-
-      if (pos >= polygon_to_shader.size()) {
-        continue;
-      }
-
-      polygon_to_shader[pos] = shader_index;
-    }
-  }
-}
-
-void AlembicObject::load_all_data(AlembicProcedural *proc,
-                                  IPolyMeshSchema &schema,
-                                  Progress &progress)
-{
-  cached_data.clear();
-
   /* Only load data for the original Geometry. */
   if (instance_of) {
     return;
   }
 
-  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
-  cached_data.set_time_sampling(*time_sampling);
-
-  const IN3fGeomParam &normals = schema.getNormalsParam();
-
-  ccl::set<chrono_t> times = get_relevant_sample_times(
-      proc, *time_sampling, schema.getNumSamples());
-
-  /* Key used to determine if the triangles change over time, if the key is the same as the
-   * last one, we can avoid creating a new entry in the cache and simply point to the last
-   * frame. */
-  ArraySample::Key previous_key;
-
-  /* read topology */
-  foreach (chrono_t time, times) {
-    if (progress.get_cancel()) {
-      return;
-    }
-
-    const ISampleSelector iss = ISampleSelector(time);
-    const IPolyMeshSchema::Sample sample = schema.getValue(iss);
-
-    add_positions(sample.getPositions(), time, cached_data);
-
-    /* Only copy triangles for other frames if the topology is changing over time as well. */
-    if (schema.getTopologyVariance() != kHomogenousTopology || cached_data.triangles.size() == 0) {
-      const ArraySample::Key key = sample.getFaceIndices()->getKey();
-
-      if (key == previous_key) {
-        cached_data.triangles.reuse_data_for_last_time(time);
-        cached_data.triangles_loops.reuse_data_for_last_time(time);
-        cached_data.shader.reuse_data_for_last_time(time);
-      }
-      else {
-        /* start by reading the face sets (per face shader), as we directly split polygons to
-         * triangles
-         */
-        array<int> polygon_to_shader;
-        read_face_sets(schema, polygon_to_shader, iss);
-
-        add_triangles(
-            sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader);
-      }
+  cached_data.clear();
 
-      previous_key = key;
-    }
+  PolyMeshSchemaData data;
+  data.topology_variance = schema.getTopologyVariance();
+  data.time_sampling = schema.getTimeSampling();
+  data.positions = schema.getPositionsProperty();
+  data.face_counts = schema.getFaceCountsProperty();
+  data.face_indices = schema.getFaceIndicesProperty();
+  data.normals = schema.getNormalsParam();
+  data.num_samples = schema.getNumSamples();
+  data.shader_face_sets = parse_face_sets_for_shader_assignment(schema, get_used_shaders());
 
-    if (normals.valid()) {
-      add_normals(sample.getFaceIndices(), normals, time, cached_data);
-    }
-  }
+  read_geometry_data(proc, cached_data, data, progress);
 
   if (progress.get_cancel()) {
     return;
   }
 
-  update_shader_attributes(schema.getArbGeomParams(), progress);
+  /* Use the schema as the base compound property to also be able to look for top level properties.
+   */
+  read_attributes(
+      proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
 
   if (progress.get_cancel()) {
     return;
   }
 
-  const IV2fGeomParam &uvs = schema.getUVsParam();
-
-  if (uvs.valid()) {
-    add_uvs(proc, uvs, cached_data, progress);
-  }
-
+  cached_data.invalidate_last_loaded_time(true);
   data_loaded = true;
 }
 
-void AlembicObject::load_all_data(AlembicProcedural *proc, ISubDSchema &schema, Progress &progress)
+void AlembicObject::load_data_in_cache(CachedData &cached_data,
+                                       AlembicProcedural *proc,
+                                       ISubDSchema &schema,
+                                       Progress &progress)
 {
-  cached_data.clear();
-
   /* Only load data for the original Geometry. */
   if (instance_of) {
     return;
   }
 
-  AttributeRequestSet requested_attributes = get_requested_attributes();
-
-  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
-  cached_data.set_time_sampling(*time_sampling);
-
-  ccl::set<chrono_t> times = get_relevant_sample_times(
-      proc, *time_sampling, schema.getNumSamples());
-
-  /* read topology */
-  foreach (chrono_t time, times) {
-    if (progress.get_cancel()) {
-      return;
-    }
-
-    const ISampleSelector iss = ISampleSelector(time);
-    const ISubDSchema::Sample sample = schema.getValue(iss);
-
-    add_positions(sample.getPositions(), time, cached_data);
-
-    const Int32ArraySamplePtr face_counts = sample.getFaceCounts();
-    const Int32ArraySamplePtr face_indices = sample.getFaceIndices();
-
-    /* start by reading the face sets (per face shader) */
-    array<int> polygon_to_shader;
-    read_face_sets(schema, polygon_to_shader, iss);
-
-    /* read faces */
-    array<int> subd_start_corner;
-    array<int> shader;
-    array<int> subd_num_corners;
-    array<bool> subd_smooth;
-    array<int> subd_ptex_offset;
-    array<int> subd_face_corners;
-
-    const size_t num_faces = face_counts->size();
-    const int *face_counts_array = face_counts->get();
-    const int *face_indices_array = face_indices->get();
-
-    int num_ngons = 0;
-    int num_corners = 0;
-    for (size_t i = 0; i < face_counts->size(); i++) {
-      num_ngons += (face_counts_array[i] == 4 ? 0 : 1);
-      num_corners += face_counts_array[i];
-    }
-
-    subd_start_corner.reserve(num_faces);
-    subd_num_corners.reserve(num_faces);
-    subd_smooth.reserve(num_faces);
-    subd_ptex_offset.reserve(num_faces);
-    shader.reserve(num_faces);
-    subd_face_corners.reserve(num_corners);
-
-    int start_corner = 0;
-    int current_shader = 0;
-    int ptex_offset = 0;
-
-    for (size_t i = 0; i < face_counts->size(); i++) {
-      num_corners = face_counts_array[i];
-
-      if (!polygon_to_shader.empty()) {
-        current_shader = polygon_to_shader[i];
-      }
-
-      subd_start_corner.push_back_reserved(start_corner);
-      subd_num_corners.push_back_reserved(num_corners);
-
-      for (int j = 0; j < num_corners; ++j) {
-        subd_face_corners.push_back_reserved(face_indices_array[start_corner + j]);
-      }
-
-      shader.push_back_reserved(current_shader);
-      subd_smooth.push_back_reserved(1);
-      subd_ptex_offset.push_back_reserved(ptex_offset);
-
-      ptex_offset += (num_corners == 4 ? 1 : num_corners);
-
-      start_corner += num_corners;
-    }
-
-    cached_data.shader.add_data(shader, time);
-    cached_data.subd_start_corner.add_data(subd_start_corner, time);
-    cached_data.subd_num_corners.add_data(subd_num_corners, time);
-    cached_data.subd_smooth.add_data(subd_smooth, time);
-    cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time);
-    cached_data.subd_face_corners.add_data(subd_face_corners, time);
-    cached_data.num_ngons.add_data(num_ngons, time);
-
-    /* read creases */
-    Int32ArraySamplePtr creases_length = sample.getCreaseLengths();
-    Int32ArraySamplePtr creases_indices = sample.getCreaseIndices();
-    FloatArraySamplePtr creases_sharpnesses = sample.getCreaseSharpnesses();
-
-    if (creases_length && creases_indices && creases_sharpnesses) {
-      array<int> creases_edge;
-      array<float> creases_weight;
-
-      creases_edge.reserve(creases_sharpnesses->size() * 2);
-      creases_weight.reserve(creases_sharpnesses->size());
-
-      int length_offset = 0;
-      int weight_offset = 0;
-      for (size_t c = 0; c < creases_length->size(); ++c) {
-        const int crease_length = creases_length->get()[c];
-
-        for (size_t j = 0; j < crease_length - 1; ++j) {
-          creases_edge.push_back_reserved(creases_indices->get()[length_offset + j]);
-          creases_edge.push_back_reserved(creases_indices->get()[length_offset + j + 1]);
-          creases_weight.push_back_reserved(creases_sharpnesses->get()[weight_offset++]);
-        }
-
-        length_offset += crease_length;
-      }
-
-      cached_data.subd_creases_edge.add_data(creases_edge, time);
-      cached_data.subd_creases_weight.add_data(creases_weight, time);
-    }
-  }
+  cached_data.clear();
 
-  /* TODO(@kevindietrich) : attributes, need test files */
+  SubDSchemaData data;
+  data.time_sampling = schema.getTimeSampling();
+  data.num_samples = schema.getNumSamples();
+  data.topology_variance = schema.getTopologyVariance();
+  data.face_counts = schema.getFaceCountsProperty();
+  data.face_indices = schema.getFaceIndicesProperty();
+  data.positions = schema.getPositionsProperty();
+  data.face_varying_interpolate_boundary = schema.getFaceVaryingInterpolateBoundaryProperty();
+  data.face_varying_propagate_corners = schema.getFaceVaryingPropagateCornersProperty();
+  data.interpolate_boundary = schema.getInterpolateBoundaryProperty();
+  data.crease_indices = schema.getCreaseIndicesProperty();
+  data.crease_lengths = schema.getCreaseLengthsProperty();
+  data.crease_sharpnesses = schema.getCreaseSharpnessesProperty();
+  data.corner_indices = schema.getCornerIndicesProperty();
+  data.corner_sharpnesses = schema.getCornerSharpnessesProperty();
+  data.holes = schema.getHolesProperty();
+  data.subdivision_scheme = schema.getSubdivisionSchemeProperty();
+  data.velocities = schema.getVelocitiesProperty();
+  data.shader_face_sets = parse_face_sets_for_shader_assignment(schema, get_used_shaders());
+
+  read_geometry_data(proc, cached_data, data, progress);
 
   if (progress.get_cancel()) {
     return;
   }
 
+  /* Use the schema as the base compound property to also be able to look for top level properties.
+   */
+  read_attributes(
+      proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
+
+  cached_data.invalidate_last_loaded_time(true);
   data_loaded = true;
 }
 
-void AlembicObject::load_all_data(AlembicProcedural *proc,
-                                  const ICurvesSchema &schema,
-                                  Progress &progress,
-                                  float default_radius)
+void AlembicObject::load_data_in_cache(CachedData &cached_data,
+                                       AlembicProcedural *proc,
+                                       const ICurvesSchema &schema,
+                                       Progress &progress)
 {
-  cached_data.clear();
-
   /* Only load data for the original Geometry. */
   if (instance_of) {
     return;
   }
 
-  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
-  cached_data.set_time_sampling(*time_sampling);
-
-  ccl::set<chrono_t> times = get_relevant_sample_times(
-      proc, *time_sampling, schema.getNumSamples());
-
-  foreach (chrono_t time, times) {
-    if (progress.get_cancel()) {
-      return;
-    }
-
-    const ISampleSelector iss = ISampleSelector(time);
-    const ICurvesSchema::Sample sample = schema.getValue(iss);
-
-    const Int32ArraySamplePtr curves_num_vertices = sample.getCurvesNumVertices();
-    const P3fArraySamplePtr position = sample.getPositions();
-
-    const IFloatGeomParam widths_param = schema.getWidthsParam();
-    FloatArraySamplePtr radiuses;
-
-    if (widths_param.valid()) {
-      IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(iss);
-      radiuses = wsample.getVals();
-    }
-
-    const bool do_radius = (radiuses != nullptr) && (radiuses->size() > 1);
-    float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] : default_radius;
-
-    array<float3> curve_keys;
-    array<float> curve_radius;
-    array<int> curve_first_key;
-    array<int> curve_shader;
-
-    const bool is_homogenous = schema.getTopologyVariance() == kHomogenousTopology;
-
-    curve_keys.reserve(position->size());
-    curve_radius.reserve(position->size());
-    curve_first_key.reserve(curves_num_vertices->size());
-    curve_shader.reserve(curves_num_vertices->size());
-
-    int offset = 0;
-    for (size_t i = 0; i < curves_num_vertices->size(); i++) {
-      const int num_vertices = curves_num_vertices->get()[i];
-
-      for (int j = 0; j < num_vertices; j++) {
-        const V3f &f = position->get()[offset + j];
-        curve_keys.push_back_reserved(make_float3_from_yup(f));
-
-        if (do_radius) {
-          radius = (*radiuses)[offset + j];
-        }
-
-        curve_radius.push_back_reserved(radius * radius_scale);
-      }
-
-      if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
-        curve_first_key.push_back_reserved(offset);
-        curve_shader.push_back_reserved(0);
-      }
-
-      offset += num_vertices;
-    }
+  cached_data.clear();
 
-    cached_data.curve_keys.add_data(curve_keys, time);
-    cached_data.curve_radius.add_data(curve_radius, time);
+  CurvesSchemaData data;
+  data.positions = schema.getPositionsProperty();
+  data.position_weights = schema.getPositionWeightsProperty();
+  data.normals = schema.getNormalsParam();
+  data.knots = schema.getKnotsProperty();
+  data.orders = schema.getOrdersProperty();
+  data.widths = schema.getWidthsParam();
+  data.velocities = schema.getVelocitiesProperty();
+  data.time_sampling = schema.getTimeSampling();
+  data.topology_variance = schema.getTopologyVariance();
+  data.num_samples = schema.getNumSamples();
+  data.num_vertices = schema.getNumVerticesProperty();
+  data.default_radius = proc->get_default_radius();
+  data.radius_scale = get_radius_scale();
+
+  read_geometry_data(proc, cached_data, data, progress);
 
-    if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
-      cached_data.curve_first_key.add_data(curve_first_key, time);
-      cached_data.curve_shader.add_data(curve_shader, time);
-    }
+  if (progress.get_cancel()) {
+    return;
   }
 
-  // TODO(@kevindietrich): attributes, need example files
+  /* Use the schema as the base compound property to also be able to look for top level properties.
+   */
+  read_attributes(
+      proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
 
+  cached_data.invalidate_last_loaded_time(true);
   data_loaded = true;
 }
 
-void AlembicObject::setup_transform_cache(float scale)
+void AlembicObject::setup_transform_cache(CachedData &cached_data, float scale)
 {
   cached_data.transforms.clear();
   cached_data.transforms.invalidate_last_loaded_time();
@@ -1102,188 +610,6 @@ AttributeRequestSet AlembicObject::get_requested_attributes()
   return requested_attributes;
 }
 
-void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params,
-                                   const ustring &attr_name,
-                                   Progress &progress)
-{
-  const PropertyHeader *prop = arb_geom_params.getPropertyHeader(attr_name.c_str());
-
-  if (prop == nullptr) {
-    return;
-  }
-
-  if (IV2fProperty::matches(prop->getMetaData()) && Alembic::AbcGeom::isUV(*prop)) {
-    const IV2fGeomParam &param = IV2fGeomParam(arb_geom_params, prop->getName());
-
-    CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
-                                                                       *param.getTimeSampling());
-
-    for (size_t i = 0; i < param.getNumSamples(); ++i) {
-      if (progress.get_cancel()) {
-        return;
-      }
-
-      ISampleSelector iss = ISampleSelector(index_t(i));
-
-      IV2fGeomParam::Sample sample;
-      param.getIndexed(sample, iss);
-
-      const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
-
-      if (param.getScope() == kFacevaryingScope) {
-        V2fArraySamplePtr values = sample.getVals();
-        UInt32ArraySamplePtr indices = sample.getIndices();
-
-        attribute.std = ATTR_STD_NONE;
-        attribute.element = ATTR_ELEMENT_CORNER;
-        attribute.type_desc = TypeFloat2;
-
-        const array<int3> *triangles =
-            cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
-        const array<int3> *triangles_loops =
-            cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null();
-
-        if (!triangles || !triangles_loops) {
-          return;
-        }
-
-        array<char> data;
-        data.resize(triangles->size() * 3 * sizeof(float2));
-
-        float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
-
-        for (const int3 &loop : *triangles_loops) {
-          unsigned int v0 = (*indices)[loop.x];
-          unsigned int v1 = (*indices)[loop.y];
-          unsigned int v2 = (*indices)[loop.z];
-
-          data_float2[0] = make_float2((*values)[v0][0], (*values)[v0][1]);
-          data_float2[1] = make_float2((*values)[v1][0], (*values)[v1][1]);
-          data_float2[2] = make_float2((*values)[v2][0], (*values)[v2][1]);
-          data_float2 += 3;
-        }
-
-        attribute.data.set_time_sampling(*param.getTimeSampling());
-        attribute.data.add_data(data, time);
-      }
-    }
-  }
-  else if (IC3fProperty::matches(prop->getMetaData())) {
-    const IC3fGeomParam &param = IC3fGeomParam(arb_geom_params, prop->getName());
-
-    CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
-                                                                       *param.getTimeSampling());
-
-    for (size_t i = 0; i < param.getNumSamples(); ++i) {
-      if (progress.get_cancel()) {
-        return;
-      }
-
-      ISampleSelector iss = ISampleSelector(index_t(i));
-
-      IC3fGeomParam::Sample sample;
-      param.getIndexed(sample, iss);
-
-      const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
-
-      C3fArraySamplePtr values = sample.getVals();
-
-      attribute.std = ATTR_STD_NONE;
-
-      if (param.getScope() == kVaryingScope) {
-        attribute.element = ATTR_ELEMENT_CORNER_BYTE;
-        attribute.type_desc = TypeRGBA;
-
-        const array<int3> *triangles =
-            cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
-
-        if (!triangles) {
-          return;
-        }
-
-        array<char> data;
-        data.resize(triangles->size() * 3 * sizeof(uchar4));
-
-        uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data());
-
-        int offset = 0;
-        for (const int3 &tri : *triangles) {
-          Imath::C3f v = (*values)[tri.x];
-          data_uchar4[offset + 0] = color_float_to_byte(make_float3(v.x, v.y, v.z));
-
-          v = (*values)[tri.y];
-          data_uchar4[offset + 1] = color_float_to_byte(make_float3(v.x, v.y, v.z));
-
-          v = (*values)[tri.z];
-          data_uchar4[offset + 2] = color_float_to_byte(make_float3(v.x, v.y, v.z));
-
-          offset += 3;
-        }
-
-        attribute.data.set_time_sampling(*param.getTimeSampling());
-        attribute.data.add_data(data, time);
-      }
-    }
-  }
-  else if (IC4fProperty::matches(prop->getMetaData())) {
-    const IC4fGeomParam &param = IC4fGeomParam(arb_geom_params, prop->getName());
-
-    CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
-                                                                       *param.getTimeSampling());
-
-    for (size_t i = 0; i < param.getNumSamples(); ++i) {
-      if (progress.get_cancel()) {
-        return;
-      }
-
-      ISampleSelector iss = ISampleSelector(index_t(i));
-
-      IC4fGeomParam::Sample sample;
-      param.getIndexed(sample, iss);
-
-      const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
-
-      C4fArraySamplePtr values = sample.getVals();
-
-      attribute.std = ATTR_STD_NONE;
-
-      if (param.getScope() == kVaryingScope) {
-        attribute.element = ATTR_ELEMENT_CORNER_BYTE;
-        attribute.type_desc = TypeRGBA;
-
-        const array<int3> *triangles =
-            cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
-
-        if (!triangles) {
-          return;
-        }
-
-        array<char> data;
-        data.resize(triangles->size() * 3 * sizeof(uchar4));
-
-        uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data());
-
-        int offset = 0;
-        for (const int3 &tri : *triangles) {
-          Imath::C4f v = (*values)[tri.x];
-          data_uchar4[offset + 0] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
-
-          v = (*values)[tri.y];
-          data_uchar4[offset + 1] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
-
-          v = (*values)[tri.z];
-          data_uchar4[offset + 2] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
-
-          offset += 3;
-        }
-
-        attribute.data.set_time_sampling(*param.getTimeSampling());
-        attribute.data.add_data(data, time);
-      }
-    }
-  }
-}
-
 /* Update existing attributes and remove any attribute not in the cached_data, those attributes
  * were added by Cycles (e.g. face normals) */
 static void update_attributes(AttributeSet &attributes, CachedData &cached_data, double frame_time)
@@ -1291,7 +617,11 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data,
   set<Attribute *> cached_attributes;
 
   for (CachedData::CachedAttribute &attribute : cached_data.attributes) {
-    const array<char> *attr_data = attribute.data.data_for_time(frame_time).get_data_or_null();
+    const CacheLookupResult<array<char>> result = attribute.data.data_for_time(frame_time);
+
+    if (result.has_no_data_for_time()) {
+      continue;
+    }
 
     Attribute *attr = nullptr;
     if (attribute.std != ATTR_STD_NONE) {
@@ -1304,18 +634,19 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data,
 
     cached_attributes.insert(attr);
 
-    if (!attr_data) {
-      /* no new data */
+    if (!result.has_new_data()) {
       continue;
     }
 
+    const ccl::array<char> &attr_data = result.get_data();
+
     /* weak way of detecting if the topology has changed
      * todo: reuse code from device_update patch */
-    if (attr->buffer.size() != attr_data->size()) {
-      attr->buffer.resize(attr_data->size());
+    if (attr->buffer.size() != attr_data.size()) {
+      attr->buffer.resize(attr_data.size());
     }
 
-    memcpy(attr->data(), attr_data->data(), attr_data->size());
+    memcpy(attr->data(), attr_data.data(), attr_data.size());
     attr->modified = true;
   }
 
@@ -1476,6 +807,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
       read_subd(object, frame_time);
     }
 
+    object->need_shader_update = false;
     object->clear_modified();
   }
 
@@ -1960,12 +1292,17 @@ void AlembicProcedural::build_caches(Progress &progress)
       if (!object->has_data_loaded()) {
         IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
         IPolyMeshSchema schema = polymesh.getSchema();
-        object->load_all_data(this, schema, progress);
+        object->load_data_in_cache(object->get_cached_data(), this, schema, progress);
       }
       else if (object->need_shader_update) {
         IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
         IPolyMeshSchema schema = polymesh.getSchema();
-        object->update_shader_attributes(schema.getArbGeomParams(), progress);
+        read_attributes(this,
+                        object->get_cached_data(),
+                        schema,
+                        schema.getUVsParam(),
+                        object->get_requested_attributes(),
+                        progress);
       }
     }
     else if (object->schema_type == AlembicObject::CURVES) {
@@ -1973,24 +1310,29 @@ void AlembicProcedural::build_caches(Progress &progress)
           object->radius_scale_is_modified()) {
         ICurves curves(object->iobject, Alembic::Abc::kWrapExisting);
         ICurvesSchema schema = curves.getSchema();
-        object->load_all_data(this, schema, progress, default_radius);
+        object->load_data_in_cache(object->get_cached_data(), this, schema, progress);
       }
     }
     else if (object->schema_type == AlembicObject::SUBD) {
       if (!object->has_data_loaded()) {
         ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
         ISubDSchema schema = subd_mesh.getSchema();
-        object->load_all_data(this, schema, progress);
+        object->load_data_in_cache(object->get_cached_data(), this, schema, progress);
       }
       else if (object->need_shader_update) {
         ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
         ISubDSchema schema = subd_mesh.getSchema();
-        object->update_shader_attributes(schema.getArbGeomParams(), progress);
+        read_attributes(this,
+                        object->get_cached_data(),
+                        schema,
+                        schema.getUVsParam(),
+                        object->get_requested_attributes(),
+                        progress);
       }
     }
 
     if (scale_is_modified() || object->get_cached_data().transforms.size() == 0) {
-      object->setup_transform_cache(scale);
+      object->setup_transform_cache(object->get_cached_data(), scale);
     }
   }
 }
index 3bbd10fad610542e790560203eae8471ee11a64e..61c0e40fe4a534cda40acbb59e2292e97a241f7e 100644 (file)
@@ -152,6 +152,10 @@ template<typename T> class DataStore {
   double last_loaded_time = std::numeric_limits<double>::max();
 
  public:
+  /* Keys used to compare values. */
+  Alembic::AbcCoreAbstract::ArraySample::Key key1;
+  Alembic::AbcCoreAbstract::ArraySample::Key key2;
+
   void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_)
   {
     time_sampling = time_sampling_;
@@ -225,6 +229,11 @@ template<typename T> class DataStore {
     index_data_map.push_back({time, data_index.source_time, data_index.index});
   }
 
+  void add_no_data(double time)
+  {
+    index_data_map.push_back({time, time, -1ul});
+  }
+
   bool is_constant() const
   {
     return data.size() <= 1;
@@ -284,7 +293,7 @@ struct CachedData {
   DataStore<array<int3>> triangles{};
   /* triangle "loops" are the polygons' vertices indices used for indexing face varying attributes
    * (like UVs) */
-  DataStore<array<int3>> triangles_loops{};
+  DataStore<array<int>> uv_loops{};
   DataStore<array<int>> shader{};
 
   /* subd data */
@@ -362,16 +371,18 @@ class AlembicObject : public Node {
   void set_object(Object *object);
   Object *get_object();
 
-  void load_all_data(AlembicProcedural *proc,
-                     Alembic::AbcGeom::IPolyMeshSchema &schema,
-                     Progress &progress);
-  void load_all_data(AlembicProcedural *proc,
-                     Alembic::AbcGeom::ISubDSchema &schema,
-                     Progress &progress);
-  void load_all_data(AlembicProcedural *proc,
-                     const Alembic::AbcGeom::ICurvesSchema &schema,
-                     Progress &progress,
-                     float default_radius);
+  void load_data_in_cache(CachedData &cached_data,
+                          AlembicProcedural *proc,
+                          Alembic::AbcGeom::IPolyMeshSchema &schema,
+                          Progress &progress);
+  void load_data_in_cache(CachedData &cached_data,
+                          AlembicProcedural *proc,
+                          Alembic::AbcGeom::ISubDSchema &schema,
+                          Progress &progress);
+  void load_data_in_cache(CachedData &cached_data,
+                          AlembicProcedural *proc,
+                          const Alembic::AbcGeom::ICurvesSchema &schema,
+                          Progress &progress);
 
   bool has_data_loaded() const;
 
@@ -397,33 +408,21 @@ class AlembicObject : public Node {
 
   CachedData &get_cached_data()
   {
-    return cached_data;
+    return cached_data_;
   }
 
   bool is_constant() const
   {
-    return cached_data.is_constant();
+    return cached_data_.is_constant();
   }
 
   Object *object = nullptr;
 
   bool data_loaded = false;
 
-  CachedData cached_data;
-
-  void update_shader_attributes(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
-                                Progress &progress);
-
-  void read_attribute(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
-                      const ustring &attr_name,
-                      Progress &progress);
-
-  template<typename SchemaType>
-  void read_face_sets(SchemaType &schema,
-                      array<int> &polygon_to_shader,
-                      Alembic::AbcGeom::ISampleSelector sample_sel);
+  CachedData cached_data_;
 
-  void setup_transform_cache(float scale);
+  void setup_transform_cache(CachedData &cached_data, float scale);
 
   AttributeRequestSet get_requested_attributes();
 };
diff --git a/intern/cycles/render/alembic_read.cpp b/intern/cycles/render/alembic_read.cpp
new file mode 100644 (file)
index 0000000..4d09c40
--- /dev/null
@@ -0,0 +1,1007 @@
+/*
+ * Copyright 2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/alembic_read.h"
+
+#include "render/alembic.h"
+#include "render/mesh.h"
+
+#include "util/util_progress.h"
+
+#ifdef WITH_ALEMBIC
+
+using namespace Alembic::AbcGeom;
+
+CCL_NAMESPACE_BEGIN
+
+static float3 make_float3_from_yup(const V3f &v)
+{
+  return make_float3(v.x, -v.z, v.y);
+}
+
+/* get the sample times to load data for the given the start and end frame of the procedural */
+static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
+                                               const TimeSampling &time_sampling,
+                                               size_t num_samples)
+{
+  set<chrono_t> result;
+
+  if (num_samples < 2) {
+    result.insert(0.0);
+    return result;
+  }
+
+  // load the data for the entire animation
+  const double start_frame = static_cast<double>(proc->get_start_frame());
+  const double end_frame = static_cast<double>(proc->get_end_frame());
+
+  const double frame_rate = static_cast<double>(proc->get_frame_rate());
+  const double start_time = start_frame / frame_rate;
+  const double end_time = (end_frame + 1) / frame_rate;
+
+  const size_t start_index = time_sampling.getFloorIndex(start_time, num_samples).first;
+  const size_t end_index = time_sampling.getCeilIndex(end_time, num_samples).first;
+
+  for (size_t i = start_index; i < end_index; ++i) {
+    result.insert(time_sampling.getSampleTime(i));
+  }
+
+  return result;
+}
+
+/* Main function to read data, this will iterate over all the relevant sample times for the
+ * duration of the requested animation, and call the DataReadingFunc for each of those sample time.
+ */
+template<typename Params, typename DataReadingFunc>
+static void read_data_loop(AlembicProcedural *proc,
+                           CachedData &cached_data,
+                           const Params &params,
+                           DataReadingFunc &&func,
+                           Progress &progress)
+{
+  const std::set<chrono_t> times = get_relevant_sample_times(
+      proc, *params.time_sampling, params.num_samples);
+
+  cached_data.set_time_sampling(*params.time_sampling);
+
+  for (chrono_t time : times) {
+    if (progress.get_cancel()) {
+      return;
+    }
+
+    func(cached_data, params, time);
+  }
+}
+
+/* Polygon Mesh Geometries. */
+
+/* Compute the vertex normals in case none are present in the IPolyMeshSchema, this is mostly used
+ * to avoid computing them in the GeometryManager in order to speed up data updates. */
+static void compute_vertex_normals(CachedData &cache, double current_time)
+{
+  if (cache.vertices.size() == 0) {
+    return;
+  }
+
+  CachedData::CachedAttribute &attr_normal = cache.add_attribute(
+      ustring("N"), cache.vertices.get_time_sampling());
+  attr_normal.std = ATTR_STD_VERTEX_NORMAL;
+  attr_normal.element = ATTR_ELEMENT_VERTEX;
+  attr_normal.type_desc = TypeNormal;
+
+  const array<float3> *vertices =
+      cache.vertices.data_for_time_no_check(current_time).get_data_or_null();
+  const array<int3> *triangles =
+      cache.triangles.data_for_time_no_check(current_time).get_data_or_null();
+
+  if (!vertices || !triangles) {
+    attr_normal.data.add_no_data(current_time);
+    return;
+  }
+
+  array<char> attr_data(vertices->size() * sizeof(float3));
+  float3 *attr_ptr = reinterpret_cast<float3 *>(attr_data.data());
+  memset(attr_ptr, 0, vertices->size() * sizeof(float3));
+
+  for (size_t t = 0; t < triangles->size(); ++t) {
+    const int3 tri_int3 = triangles->data()[t];
+    Mesh::Triangle tri{};
+    tri.v[0] = tri_int3[0];
+    tri.v[1] = tri_int3[1];
+    tri.v[2] = tri_int3[2];
+
+    const float3 tri_N = tri.compute_normal(vertices->data());
+
+    for (int v = 0; v < 3; ++v) {
+      attr_ptr[tri_int3[v]] += tri_N;
+    }
+  }
+
+  for (size_t v = 0; v < vertices->size(); ++v) {
+    attr_ptr[v] = normalize(attr_ptr[v]);
+  }
+
+  attr_normal.data.add_data(attr_data, current_time);
+}
+
+static void add_normals(const Int32ArraySamplePtr face_indices,
+                        const IN3fGeomParam &normals,
+                        double time,
+                        CachedData &cached_data)
+{
+  switch (normals.getScope()) {
+    case kFacevaryingScope: {
+      const ISampleSelector iss = ISampleSelector(time);
+      const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
+
+      if (!sample.valid()) {
+        return;
+      }
+
+      CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
+                                                                    *normals.getTimeSampling());
+      attr.std = ATTR_STD_VERTEX_NORMAL;
+
+      const array<float3> *vertices =
+          cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
+
+      if (!vertices) {
+        return;
+      }
+
+      array<char> data;
+      data.resize(vertices->size() * sizeof(float3));
+
+      float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
+
+      const int *face_indices_array = face_indices->get();
+      const N3fArraySamplePtr values = sample.getVals();
+
+      for (size_t i = 0; i < face_indices->size(); ++i) {
+        int point_index = face_indices_array[i];
+        data_float3[point_index] = make_float3_from_yup(values->get()[i]);
+      }
+
+      attr.data.add_data(data, time);
+      break;
+    }
+    case kVaryingScope:
+    case kVertexScope: {
+      const ISampleSelector iss = ISampleSelector(time);
+      const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
+
+      if (!sample.valid()) {
+        return;
+      }
+
+      CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
+                                                                    *normals.getTimeSampling());
+      attr.std = ATTR_STD_VERTEX_NORMAL;
+
+      const array<float3> *vertices =
+          cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
+
+      if (!vertices) {
+        return;
+      }
+
+      array<char> data;
+      data.resize(vertices->size() * sizeof(float3));
+
+      float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
+
+      const Imath::V3f *values = sample.getVals()->get();
+
+      for (size_t i = 0; i < vertices->size(); ++i) {
+        data_float3[i] = make_float3_from_yup(values[i]);
+      }
+
+      attr.data.add_data(data, time);
+
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+}
+
+static void add_positions(const P3fArraySamplePtr positions, double time, CachedData &cached_data)
+{
+  if (!positions) {
+    return;
+  }
+
+  array<float3> vertices;
+  vertices.reserve(positions->size());
+
+  for (size_t i = 0; i < positions->size(); i++) {
+    V3f f = positions->get()[i];
+    vertices.push_back_reserved(make_float3_from_yup(f));
+  }
+
+  cached_data.vertices.add_data(vertices, time);
+}
+
+static void add_triangles(const Int32ArraySamplePtr face_counts,
+                          const Int32ArraySamplePtr face_indices,
+                          double time,
+                          CachedData &cached_data,
+                          const array<int> &polygon_to_shader)
+{
+  if (!face_counts || !face_indices) {
+    return;
+  }
+
+  const size_t num_faces = face_counts->size();
+  const int *face_counts_array = face_counts->get();
+  const int *face_indices_array = face_indices->get();
+
+  size_t num_triangles = 0;
+  for (size_t i = 0; i < face_counts->size(); i++) {
+    num_triangles += face_counts_array[i] - 2;
+  }
+
+  array<int> shader;
+  array<int3> triangles;
+  array<int> uv_loops;
+  shader.reserve(num_triangles);
+  triangles.reserve(num_triangles);
+  uv_loops.reserve(num_triangles * 3);
+  int index_offset = 0;
+
+  for (size_t i = 0; i < num_faces; i++) {
+    int current_shader = 0;
+
+    if (!polygon_to_shader.empty()) {
+      current_shader = polygon_to_shader[i];
+    }
+
+    for (int j = 0; j < face_counts_array[i] - 2; j++) {
+      int v0 = face_indices_array[index_offset];
+      int v1 = face_indices_array[index_offset + j + 1];
+      int v2 = face_indices_array[index_offset + j + 2];
+
+      shader.push_back_reserved(current_shader);
+
+      /* Alembic orders the loops following the RenderMan convention, so need to go in reverse. */
+      triangles.push_back_reserved(make_int3(v2, v1, v0));
+      uv_loops.push_back_reserved(index_offset + j + 2);
+      uv_loops.push_back_reserved(index_offset + j + 1);
+      uv_loops.push_back_reserved(index_offset);
+    }
+
+    index_offset += face_counts_array[i];
+  }
+
+  cached_data.triangles.add_data(triangles, time);
+  cached_data.uv_loops.add_data(uv_loops, time);
+  cached_data.shader.add_data(shader, time);
+}
+
+static array<int> compute_polygon_to_shader_map(
+    const Int32ArraySamplePtr &face_counts,
+    const vector<FaceSetShaderIndexPair> &face_set_shader_index,
+    ISampleSelector sample_sel)
+{
+  if (face_set_shader_index.empty()) {
+    return {};
+  }
+
+  if (!face_counts) {
+    return {};
+  }
+
+  if (face_counts->size() == 0) {
+    return {};
+  }
+
+  array<int> polygon_to_shader(face_counts->size());
+
+  for (const FaceSetShaderIndexPair &pair : face_set_shader_index) {
+    const IFaceSet &face_set = pair.face_set;
+    const IFaceSetSchema face_schem = face_set.getSchema();
+    const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
+    const Int32ArraySamplePtr group_faces = face_sample.getFaces();
+    const size_t num_group_faces = group_faces->size();
+
+    for (size_t l = 0; l < num_group_faces; l++) {
+      size_t pos = (*group_faces)[l];
+
+      if (pos >= polygon_to_shader.size()) {
+        continue;
+      }
+
+      polygon_to_shader[pos] = pair.shader_index;
+    }
+  }
+
+  return polygon_to_shader;
+}
+
+static void read_poly_mesh_geometry(CachedData &cached_data,
+                                    const PolyMeshSchemaData &data,
+                                    chrono_t time)
+{
+  const ISampleSelector iss = ISampleSelector(time);
+
+  add_positions(data.positions.getValue(iss), time, cached_data);
+
+  const Int32ArraySamplePtr face_counts = data.face_counts.getValue(iss);
+  const Int32ArraySamplePtr face_indices = data.face_indices.getValue(iss);
+
+  /* Only copy triangles for other frames if the topology is changing over time as well. */
+  if (data.topology_variance != kHomogeneousTopology || cached_data.triangles.size() == 0) {
+    bool do_triangles = true;
+
+    /* Compare key with last one to check whether the topology changed. */
+    if (cached_data.triangles.size() > 0) {
+      const ArraySample::Key key = face_indices->getKey();
+
+      if (key == cached_data.triangles.key1) {
+        do_triangles = false;
+      }
+
+      cached_data.triangles.key1 = key;
+    }
+
+    if (do_triangles) {
+      const array<int> polygon_to_shader = compute_polygon_to_shader_map(
+          face_counts, data.shader_face_sets, iss);
+      add_triangles(face_counts, face_indices, time, cached_data, polygon_to_shader);
+    }
+    else {
+      cached_data.triangles.reuse_data_for_last_time(time);
+      cached_data.uv_loops.reuse_data_for_last_time(time);
+      cached_data.shader.reuse_data_for_last_time(time);
+    }
+
+    /* Initialize the first key. */
+    if (data.topology_variance != kHomogeneousTopology && cached_data.triangles.size() == 1) {
+      cached_data.triangles.key1 = face_indices->getKey();
+    }
+  }
+
+  if (data.normals.valid()) {
+    add_normals(face_indices, data.normals, time, cached_data);
+  }
+  else {
+    compute_vertex_normals(cached_data, time);
+  }
+}
+
+void read_geometry_data(AlembicProcedural *proc,
+                        CachedData &cached_data,
+                        const PolyMeshSchemaData &data,
+                        Progress &progress)
+{
+  read_data_loop(proc, cached_data, data, read_poly_mesh_geometry, progress);
+}
+
+/* Subdivision Geometries */
+
+static void add_subd_polygons(CachedData &cached_data, const SubDSchemaData &data, chrono_t time)
+{
+  const ISampleSelector iss = ISampleSelector(time);
+
+  const Int32ArraySamplePtr face_counts = data.face_counts.getValue(iss);
+  const Int32ArraySamplePtr face_indices = data.face_indices.getValue(iss);
+
+  array<int> subd_start_corner;
+  array<int> shader;
+  array<int> subd_num_corners;
+  array<bool> subd_smooth;
+  array<int> subd_ptex_offset;
+  array<int> subd_face_corners;
+  array<int> uv_loops;