From f613c4c0953ebaf993ecd55b12bab9cf2196dac4 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Mon, 29 Nov 2021 15:06:22 +0000 Subject: Cycles: MetalRT support (kernel side) This patch adds MetalRT support to Cycles kernel code. It is mostly additive in nature or confined to Metal-specific code, however there are a few areas where this interacts with other code: - MetalRT closely follows the Optix implementation, and in some cases (notably handling of transforms) it makes sense to extend Optix special-casing to MetalRT. For these generalisations we now have `__KERNEL_GPU_RAYTRACING__` instead of `__KERNEL_OPTIX__`. - MetalRT doesn't support primitive offsetting (as with `primitiveIndexOffset` in Optix), so we define and populate a new kernel texture, `__object_prim_offset`, containing per-object primitive / curve-segment offsets. This is referenced and applied in MetalRT intersection handlers. - Two new BVH layout enum values have been added: `BVH_LAYOUT_METAL` and `BVH_LAYOUT_MULTI_METAL_EMBREE` for XPU mode). Some host-side enum case handling has been updated where it is trivial to do so. Ref T92212 Reviewed By: brecht Maniphest Tasks: T92212 Differential Revision: https://developer.blender.org/D13353 --- intern/cycles/scene/geometry.cpp | 6 ++++-- intern/cycles/scene/object.cpp | 29 +++++++++++++++++++++++++++++ intern/cycles/scene/object.h | 1 + intern/cycles/scene/scene.cpp | 7 +++++++ intern/cycles/scene/scene.h | 1 + 5 files changed, 42 insertions(+), 2 deletions(-) (limited to 'intern/cycles/scene') diff --git a/intern/cycles/scene/geometry.cpp b/intern/cycles/scene/geometry.cpp index bf426fc49f6..346b030817f 100644 --- a/intern/cycles/scene/geometry.cpp +++ b/intern/cycles/scene/geometry.cpp @@ -165,7 +165,8 @@ int Geometry::motion_step(float time) const bool Geometry::need_build_bvh(BVHLayout layout) const { return is_instanced() || layout == BVH_LAYOUT_OPTIX || layout == BVH_LAYOUT_MULTI_OPTIX || - layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE; + layout == BVH_LAYOUT_METAL || layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE || + layout == BVH_LAYOUT_MULTI_METAL_EMBREE; } bool Geometry::is_instanced() const @@ -1247,7 +1248,8 @@ void GeometryManager::device_update_bvh(Device *device, VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; const bool can_refit = scene->bvh != nullptr && - (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX); + (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX || + bparams.bvh_layout == BVHLayout::BVH_LAYOUT_METAL); BVH *bvh = scene->bvh; if (!scene->bvh) { diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index 69a2365f17c..bf224a81af5 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -530,6 +530,34 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s } } +void ObjectManager::device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene) +{ + BVHLayoutMask layout_mask = device->get_bvh_layout_mask(); + if (layout_mask != BVH_LAYOUT_METAL && layout_mask != BVH_LAYOUT_MULTI_METAL_EMBREE) { + return; + } + + /* On MetalRT, primitive / curve segment offsets can't be baked at BVH build time. Intersection + * handlers need to apply the offset manually. */ + uint *object_prim_offset = dscene->object_prim_offset.alloc(scene->objects.size()); + foreach (Object *ob, scene->objects) { + uint32_t prim_offset = 0; + if (Geometry *const geom = ob->geometry) { + if (geom->geometry_type == Geometry::HAIR) { + prim_offset = ((Hair *const)geom)->curve_segment_offset; + } + else { + prim_offset = geom->prim_offset; + } + } + uint obj_index = ob->get_device_index(); + object_prim_offset[obj_index] = prim_offset; + } + + dscene->object_prim_offset.copy_to_device(); + dscene->object_prim_offset.clear_modified(); +} + void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) { UpdateObjectTransformState state; @@ -840,6 +868,7 @@ void ObjectManager::device_free(Device *, DeviceScene *dscene, bool force_free) dscene->object_motion.free_if_need_realloc(force_free); dscene->object_flag.free_if_need_realloc(force_free); dscene->object_volume_step.free_if_need_realloc(force_free); + dscene->object_prim_offset.free_if_need_realloc(force_free); } void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) diff --git a/intern/cycles/scene/object.h b/intern/cycles/scene/object.h index f6dc57ee8b9..f983b58b59c 100644 --- a/intern/cycles/scene/object.h +++ b/intern/cycles/scene/object.h @@ -155,6 +155,7 @@ class ObjectManager { void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); void device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress); + void device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene); void device_update_flags(Device *device, DeviceScene *dscene, diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index 4230abe9a1b..452b5215836 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -69,6 +69,7 @@ DeviceScene::DeviceScene(Device *device) object_motion(device, "__object_motion", MEM_GLOBAL), object_flag(device, "__object_flag", MEM_GLOBAL), object_volume_step(device, "__object_volume_step", MEM_GLOBAL), + object_prim_offset(device, "__object_prim_offset", MEM_GLOBAL), camera_motion(device, "__camera_motion", MEM_GLOBAL), attributes_map(device, "__attributes_map", MEM_GLOBAL), attributes_float(device, "__attributes_float", MEM_GLOBAL), @@ -309,6 +310,12 @@ void Scene::device_update(Device *device_, Progress &progress) progress.set_status("Updating Objects Flags"); object_manager->device_update_flags(device, &dscene, this, progress); + if (progress.get_cancel() || device->have_error()) + return; + + progress.set_status("Updating Primitive Offsets"); + object_manager->device_update_prim_offsets(device, &dscene, this); + if (progress.get_cancel() || device->have_error()) return; diff --git a/intern/cycles/scene/scene.h b/intern/cycles/scene/scene.h index 4af05349dd3..f8f672a079a 100644 --- a/intern/cycles/scene/scene.h +++ b/intern/cycles/scene/scene.h @@ -100,6 +100,7 @@ class DeviceScene { device_vector object_motion; device_vector object_flag; device_vector object_volume_step; + device_vector object_prim_offset; /* cameras */ device_vector camera_motion; -- cgit v1.2.3