Path: blob/master/thirdparty/embree/kernels/common/scene.cpp
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#include "scene.h"45#include "../../common/tasking/taskscheduler.h"67#include "../bvh/bvh4_factory.h"8#include "../bvh/bvh8_factory.h"910#include "../../common/algorithms/parallel_reduce.h"1112#if defined(EMBREE_SYCL_SUPPORT)13# include "../sycl/rthwif_embree_builder.h"14#endif151617namespace embree18{1920struct TaskGroup {21/*! global lock step task scheduler */22#if defined(TASKING_INTERNAL)23MutexSys schedulerMutex;24Ref<TaskScheduler> scheduler;25#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION26tbb::isolated_task_group group;27#elif defined(TASKING_TBB)28tbb::task_group group;29#elif defined(TASKING_PPL)30concurrency::task_group group;31#endif32};3334/* error raising rtcIntersect and rtcOccluded functions */35void missing_rtcCommit() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed"); }36void invalid_rtcIntersect1() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect and rtcOccluded not enabled"); }37void invalid_rtcIntersect4() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect4 and rtcOccluded4 not enabled"); }38void invalid_rtcIntersect8() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect8 and rtcOccluded8 not enabled"); }39void invalid_rtcIntersect16() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect16 and rtcOccluded16 not enabled"); }40void invalid_rtcIntersectN() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectN and rtcOccludedN not enabled"); }4142Scene::Scene (Device* device)43: device(device),44scene_device(nullptr),45flags_modified(true), enabled_geometry_types(0),46scene_flags(RTC_SCENE_FLAG_NONE),47quality_flags(RTC_BUILD_QUALITY_MEDIUM),48modified(true),49maxTimeSegments(0),50#if defined(EMBREE_SYCL_SUPPORT)51geometries_device(nullptr),52geometry_data_device(nullptr),53num_geometries(0),54geometry_data_byte_size(0),55offsets(nullptr),56geometries_host(nullptr),57geometry_data_host(nullptr),58#endif59taskGroup(new TaskGroup()),60progressInterface(this), progress_monitor_function(nullptr), progress_monitor_ptr(nullptr), progress_monitor_counter(0)61{62device->refInc();6364intersectors = Accel::Intersectors(missing_rtcCommit);6566/* use proper device and context for SYCL allocations */67#if defined(EMBREE_SYCL_SUPPORT)68if (dynamic_cast<DeviceGPU*>(device))69accelBuffer = AccelBuffer(device);70#endif7172/* one can overwrite flags through device for debugging */73if (device->quality_flags != -1)74quality_flags = (RTCBuildQuality) device->quality_flags;75if (device->scene_flags != -1)76scene_flags = (RTCSceneFlags) device->scene_flags;77}7879Scene::~Scene() noexcept80{81#if defined(EMBREE_SYCL_SUPPORT)82if (geometry_data_device) {83device->free(geometry_data_device);84}85if (geometries_device) {86device->free(geometries_device);87}88if (scene_device) {89device->free(scene_device);90}91if (offsets) {92device->free(offsets);93}94if (geometries_host) {95device->free(geometries_host);96}97if (geometry_data_host) {98device->free(geometry_data_host);99}100#endif101102device->refDec();103}104105void Scene::printStatistics()106{107/* calculate maximum number of time segments */108unsigned max_time_steps = 0;109for (size_t i=0; i<size(); i++) {110if (!get(i)) continue;111max_time_steps = max(max_time_steps,get(i)->numTimeSteps);112}113114/* initialize vectors*/115std::vector<size_t> statistics[Geometry::GTY_END];116for (size_t i=0; i<Geometry::GTY_END; i++)117statistics[i].resize(max_time_steps);118119/* gather statistics */120for (size_t i=0; i<size(); i++)121{122if (!get(i)) continue;123int ty = get(i)->getType();124assert(ty<Geometry::GTY_END);125int timesegments = get(i)->numTimeSegments();126assert((unsigned int)timesegments < max_time_steps);127statistics[ty][timesegments] += get(i)->size();128}129130/* print statistics */131std::cout << std::setw(23) << "segments" << ": ";132for (size_t t=0; t<max_time_steps; t++)133std::cout << std::setw(10) << t;134std::cout << std::endl;135136std::cout << "-------------------------";137for (size_t t=0; t<max_time_steps; t++)138std::cout << "----------";139std::cout << std::endl;140141for (size_t p=0; p<Geometry::GTY_END; p++)142{143if (std::string(Geometry::gtype_names[p]) == "") continue;144std::cout << std::setw(23) << Geometry::gtype_names[p] << ": ";145for (size_t t=0; t<max_time_steps; t++)146std::cout << std::setw(10) << statistics[p][t];147std::cout << std::endl;148}149}150151void Scene::createTriangleAccel()152{153#if defined(EMBREE_GEOMETRY_TRIANGLE)154155if (device->tri_accel == "default")156{157if (quality_flags != RTC_BUILD_QUALITY_LOW)158{159int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();160switch (mode) {161case /*0b00*/ 0:162#if defined (EMBREE_TARGET_SIMD8)163if (device->canUseAVX())164{165if (quality_flags == RTC_BUILD_QUALITY_HIGH)166accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));167else168accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));169}170else171#endif172{173if (quality_flags == RTC_BUILD_QUALITY_HIGH)174accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));175else176accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));177}178break;179180case /*0b01*/ 1:181#if defined (EMBREE_TARGET_SIMD8)182if (device->canUseAVX())183accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));184else185#endif186accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));187188break;189case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;190case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;191}192}193else /* dynamic */194{195#if defined (EMBREE_TARGET_SIMD8)196if (device->canUseAVX())197{198int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();199switch (mode) {200case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;201case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;202case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;203case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;204}205}206else207#endif208{209int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();210switch (mode) {211case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;212case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;213case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;214case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;215}216}217}218}219else if (device->tri_accel == "bvh4.triangle4") accels_add(device->bvh4_factory->BVH4Triangle4 (this));220else if (device->tri_accel == "bvh4.triangle4v") accels_add(device->bvh4_factory->BVH4Triangle4v(this));221else if (device->tri_accel == "bvh4.triangle4i") accels_add(device->bvh4_factory->BVH4Triangle4i(this));222else if (device->tri_accel == "qbvh4.triangle4i") accels_add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));223224#if defined (EMBREE_TARGET_SIMD8)225else if (device->tri_accel == "bvh8.triangle4") accels_add(device->bvh8_factory->BVH8Triangle4 (this));226else if (device->tri_accel == "bvh8.triangle4v") accels_add(device->bvh8_factory->BVH8Triangle4v(this));227else if (device->tri_accel == "bvh8.triangle4i") accels_add(device->bvh8_factory->BVH8Triangle4i(this));228else if (device->tri_accel == "qbvh8.triangle4i") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4i(this));229else if (device->tri_accel == "qbvh8.triangle4") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4(this));230#endif231else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);232#endif233234}235236void Scene::createTriangleMBAccel()237{238#if defined(EMBREE_GEOMETRY_TRIANGLE)239240if (device->tri_accel_mb == "default")241{242int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();243244#if defined (EMBREE_TARGET_SIMD8)245if (device->canUseAVX2()) // BVH8 reduces performance on AVX only-machines246{247switch (mode) {248case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;249case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;250case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;251case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;252}253}254else255#endif256{257switch (mode) {258case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;259case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;260case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;261case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;262}263}264}265else if (device->tri_accel_mb == "bvh4.triangle4imb") accels_add(device->bvh4_factory->BVH4Triangle4iMB(this));266else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels_add(device->bvh4_factory->BVH4Triangle4vMB(this));267#if defined (EMBREE_TARGET_SIMD8)268else if (device->tri_accel_mb == "bvh8.triangle4imb") accels_add(device->bvh8_factory->BVH8Triangle4iMB(this));269else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels_add(device->bvh8_factory->BVH8Triangle4vMB(this));270#endif271else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur triangle acceleration structure "+device->tri_accel_mb);272#endif273}274275void Scene::createQuadAccel()276{277#if defined(EMBREE_GEOMETRY_QUAD)278279if (device->quad_accel == "default")280{281if (quality_flags != RTC_BUILD_QUALITY_LOW)282{283/* static */284int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();285switch (mode) {286case /*0b00*/ 0:287#if defined (EMBREE_TARGET_SIMD8)288if (device->canUseAVX())289{290if (quality_flags == RTC_BUILD_QUALITY_HIGH)291accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));292else293accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));294}295else296#endif297{298if (quality_flags == RTC_BUILD_QUALITY_HIGH)299accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));300else301accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));302}303break;304305case /*0b01*/ 1:306#if defined (EMBREE_TARGET_SIMD8)307if (device->canUseAVX())308accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));309else310#endif311accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));312break;313314case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST)); break;315case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;316}317}318else /* dynamic */319{320#if defined (EMBREE_TARGET_SIMD8)321if (device->canUseAVX())322{323int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();324switch (mode) {325case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;326case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;327case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;328case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;329}330}331else332#endif333{334int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();335switch (mode) {336case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;337case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;338case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;339case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;340}341}342}343}344else if (device->quad_accel == "bvh4.quad4v") accels_add(device->bvh4_factory->BVH4Quad4v(this));345else if (device->quad_accel == "bvh4.quad4i") accels_add(device->bvh4_factory->BVH4Quad4i(this));346else if (device->quad_accel == "qbvh4.quad4i") accels_add(device->bvh4_factory->BVH4QuantizedQuad4i(this));347348#if defined (EMBREE_TARGET_SIMD8)349else if (device->quad_accel == "bvh8.quad4v") accels_add(device->bvh8_factory->BVH8Quad4v(this));350else if (device->quad_accel == "bvh8.quad4i") accels_add(device->bvh8_factory->BVH8Quad4i(this));351else if (device->quad_accel == "qbvh8.quad4i") accels_add(device->bvh8_factory->BVH8QuantizedQuad4i(this));352#endif353else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad acceleration structure "+device->quad_accel);354#endif355}356357void Scene::createQuadMBAccel()358{359#if defined(EMBREE_GEOMETRY_QUAD)360361if (device->quad_accel_mb == "default")362{363int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();364switch (mode) {365case /*0b00*/ 0:366#if defined (EMBREE_TARGET_SIMD8)367if (device->canUseAVX())368accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));369else370#endif371accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));372break;373374case /*0b01*/ 1:375#if defined (EMBREE_TARGET_SIMD8)376if (device->canUseAVX())377accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));378else379#endif380accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));381break;382383case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;384case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;385}386}387else if (device->quad_accel_mb == "bvh4.quad4imb") accels_add(device->bvh4_factory->BVH4Quad4iMB(this));388#if defined (EMBREE_TARGET_SIMD8)389else if (device->quad_accel_mb == "bvh8.quad4imb") accels_add(device->bvh8_factory->BVH8Quad4iMB(this));390#endif391else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);392#endif393}394395void Scene::createHairAccel()396{397#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)398399if (device->hair_accel == "default")400{401int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();402#if defined (EMBREE_TARGET_SIMD8)403if (device->canUseAVX2()) // only enable on HSW machines, for SNB this codepath is slower404{405switch (mode) {406case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST)); break;407case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::ROBUST)); break;408case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST)); break;409case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::ROBUST)); break;410}411}412else413#endif414{415switch (mode) {416case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST)); break;417case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::ROBUST)); break;418case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST)); break;419case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::ROBUST)); break;420}421}422}423else if (device->hair_accel == "bvh4obb.virtualcurve4v" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST));424else if (device->hair_accel == "bvh4obb.virtualcurve4i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST));425#if defined (EMBREE_TARGET_SIMD8)426else if (device->hair_accel == "bvh8obb.virtualcurve8v" ) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST));427else if (device->hair_accel == "bvh4obb.virtualcurve8i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST));428#endif429else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown hair acceleration structure "+device->hair_accel);430#endif431}432433void Scene::createHairMBAccel()434{435#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)436437if (device->hair_accel_mb == "default")438{439#if defined (EMBREE_TARGET_SIMD8)440if (device->canUseAVX2()) // only enable on HSW machines, on SNB this codepath is slower441{442if (isRobustAccel()) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::ROBUST));443else accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));444}445else446#endif447{448if (isRobustAccel()) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::ROBUST));449else accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));450}451}452else if (device->hair_accel_mb == "bvh4.virtualcurve4imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));453454#if defined (EMBREE_TARGET_SIMD8)455else if (device->hair_accel_mb == "bvh4.virtualcurve8imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));456else if (device->hair_accel_mb == "bvh8.virtualcurve8imb") accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));457#endif458else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);459#endif460}461462void Scene::createSubdivAccel()463{464#if defined(EMBREE_GEOMETRY_SUBDIVISION)465if (device->subdiv_accel == "default") {466accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));467}468else if (device->subdiv_accel == "bvh4.grid.eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));469else if (device->subdiv_accel == "bvh4.subdivpatch1eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));470else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv accel "+device->subdiv_accel);471#endif472}473474void Scene::createSubdivMBAccel()475{476#if defined(EMBREE_GEOMETRY_SUBDIVISION)477if (device->subdiv_accel_mb == "default") {478accels_add(device->bvh4_factory->BVH4SubdivPatch1MB(this));479}480else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv mblur accel "+device->subdiv_accel_mb);481#endif482}483484void Scene::createUserGeometryAccel()485{486#if defined(EMBREE_GEOMETRY_USER)487488if (device->object_accel == "default")489{490#if defined (EMBREE_TARGET_SIMD8)491if (device->canUseAVX() && !isCompactAccel())492{493if (quality_flags != RTC_BUILD_QUALITY_LOW) {494accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::STATIC));495} else {496accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));497}498}499else500#endif501{502if (quality_flags != RTC_BUILD_QUALITY_LOW) {503accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::STATIC));504} else {505accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));506}507}508}509else if (device->object_accel == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometry(this));510#if defined (EMBREE_TARGET_SIMD8)511else if (device->object_accel == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometry(this));512#endif513else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);514#endif515}516517void Scene::createUserGeometryMBAccel()518{519#if defined(EMBREE_GEOMETRY_USER)520521if (device->object_accel_mb == "default" ) {522#if defined (EMBREE_TARGET_SIMD8)523if (device->canUseAVX() && !isCompactAccel())524accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));525else526#endif527accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));528}529else if (device->object_accel_mb == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));530#if defined (EMBREE_TARGET_SIMD8)531else if (device->object_accel_mb == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));532#endif533else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);534#endif535}536537void Scene::createInstanceAccel()538{539#if defined(EMBREE_GEOMETRY_INSTANCE)540541// if (device->object_accel == "default")542{543#if defined (EMBREE_TARGET_SIMD8)544if (device->canUseAVX() && !isCompactAccel()) {545if (quality_flags != RTC_BUILD_QUALITY_LOW) {546accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC));547} else {548accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));549}550}551else552#endif553{554if (quality_flags != RTC_BUILD_QUALITY_LOW) {555accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC));556} else {557accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));558}559}560}561// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);562#endif563}564565void Scene::createInstanceMBAccel()566{567#if defined(EMBREE_GEOMETRY_INSTANCE)568569//if (device->instance_accel_mb == "default")570{571#if defined (EMBREE_TARGET_SIMD8)572if (device->canUseAVX() && !isCompactAccel())573accels_add(device->bvh8_factory->BVH8InstanceMB(this, false));574else575#endif576accels_add(device->bvh4_factory->BVH4InstanceMB(this, false));577}578//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);579#endif580}581582void Scene::createInstanceExpensiveAccel()583{584#if defined(EMBREE_GEOMETRY_INSTANCE)585// if (device->object_accel == "default")586{587#if defined (EMBREE_TARGET_SIMD8)588if (device->canUseAVX() && !isCompactAccel()) {589if (quality_flags != RTC_BUILD_QUALITY_LOW) {590accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC));591} else {592accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));593}594}595else596#endif597{598if (quality_flags != RTC_BUILD_QUALITY_LOW) {599accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC));600} else {601accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));602}603}604}605// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);606#endif607}608609void Scene::createInstanceExpensiveMBAccel()610{611#if defined(EMBREE_GEOMETRY_INSTANCE)612//if (device->instance_accel_mb == "default")613{614#if defined (EMBREE_TARGET_SIMD8)615if (device->canUseAVX() && !isCompactAccel())616accels_add(device->bvh8_factory->BVH8InstanceMB(this, true));617else618#endif619accels_add(device->bvh4_factory->BVH4InstanceMB(this, true));620}621//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);622#endif623}624625void Scene::createInstanceArrayAccel()626{627#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)628629// if (device->object_accel == "default")630{631#if defined (EMBREE_TARGET_SIMD8)632if (device->canUseAVX() && !isCompactAccel()) {633if (quality_flags != RTC_BUILD_QUALITY_LOW) {634accels_add(device->bvh8_factory->BVH8InstanceArray(this, BVHFactory::BuildVariant::STATIC));635} else {636accels_add(device->bvh8_factory->BVH8InstanceArray(this, BVHFactory::BuildVariant::DYNAMIC));637}638}639else640#endif641{642if (quality_flags != RTC_BUILD_QUALITY_LOW) {643accels_add(device->bvh4_factory->BVH4InstanceArray(this, BVHFactory::BuildVariant::STATIC));644} else {645accels_add(device->bvh4_factory->BVH4InstanceArray(this, BVHFactory::BuildVariant::DYNAMIC));646}647}648}649// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);650#endif651}652653void Scene::createInstanceArrayMBAccel()654{655#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)656657//if (device->instance_accel_mb == "default")658{659#if defined (EMBREE_TARGET_SIMD8)660if (device->canUseAVX() && !isCompactAccel())661accels_add(device->bvh8_factory->BVH8InstanceArrayMB(this));662else663#endif664accels_add(device->bvh4_factory->BVH4InstanceArrayMB(this));665}666//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);667#endif668}669670671void Scene::createGridAccel()672{673#if defined(EMBREE_GEOMETRY_GRID)674675BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST;676677if (device->grid_accel == "default")678{679#if defined (EMBREE_TARGET_SIMD8)680if (device->canUseAVX() && !isCompactAccel())681{682accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));683}684else685#endif686{687accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));688}689}690else if (device->grid_accel == "bvh4.grid") accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));691#if defined (EMBREE_TARGET_SIMD8)692else if (device->grid_accel == "bvh8.grid") accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));693#endif694else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid accel "+device->grid_accel);695#endif696697}698699void Scene::createGridMBAccel()700{701#if defined(EMBREE_GEOMETRY_GRID)702703if (device->grid_accel_mb == "default")704{705accels_add(device->bvh4_factory->BVH4GridMB(this,BVHFactory::BuildVariant::STATIC));706}707else if (device->grid_accel_mb == "bvh4mb.grid") accels_add(device->bvh4_factory->BVH4GridMB(this));708else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid mb accel "+device->grid_accel);709#endif710711}712713void Scene::clear() {714}715716unsigned Scene::bind(unsigned geomID, Ref<Geometry> geometry)717{718Lock<MutexSys> lock(geometriesMutex);719if (geomID == RTC_INVALID_GEOMETRY_ID) {720geomID = id_pool.allocate();721if (geomID == RTC_INVALID_GEOMETRY_ID)722throw_RTCError(RTC_ERROR_INVALID_OPERATION,"too many geometries inside scene");723}724else725{726if (!id_pool.add(geomID))727throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID provided");728}729if (geomID >= geometries.size()) {730geometries.resize(geomID+1);731vertices.resize(geomID+1);732geometryModCounters_.resize(geomID+1);733}734geometries[geomID] = geometry;735geometryModCounters_[geomID] = 0;736if (geometry->isEnabled()) {737setModified ();738}739return geomID;740}741742void Scene::detachGeometry(size_t geomID)743{744Lock<MutexSys> lock(geometriesMutex);745746if (geomID >= geometries.size())747throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID");748749Ref<Geometry>& geometry = geometries[geomID];750if (geometry == null)751throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");752753setModified ();754accels_deleteGeometry(unsigned(geomID));755id_pool.deallocate((unsigned)geomID);756geometries[geomID] = null;757vertices[geomID] = nullptr;758geometryModCounters_[geomID] = 0;759}760761void Scene::build_cpu_accels()762{763/* select acceleration structures to build */764unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();765766if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)767{768accels_init();769770/* we need to make all geometries modified, otherwise two level builder will771not rebuild currently not modified geometries */772parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {773geometryModCounters_[i] = 0;774});775776if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();777if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();778if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();779if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();780if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();781if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();782if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();783if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();784if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();785if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();786if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();787if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();788if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();789if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();790if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();791if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();792if (getNumPrimitives(Geometry::MTY_INSTANCE_ARRAY,false)) createInstanceArrayAccel();793if (getNumPrimitives(Geometry::MTY_INSTANCE_ARRAY,true)) createInstanceArrayMBAccel();794795flags_modified = false;796enabled_geometry_types = new_enabled_geometry_types;797}798799/* select fast code path if no filter function is present */800accels_select(hasFilterFunction());801802/* build all hierarchies of this scene */803accels_build();804805/* make static geometry immutable */806if (!isDynamicAccel()) {807accels_immutable();808flags_modified = true; // in non-dynamic mode we have to re-create accels809}810811if (device->verbosity(2)) {812std::cout << "created scene intersector" << std::endl;813accels_print(2);814std::cout << "selected scene intersector" << std::endl;815intersectors.print(2);816}817}818819void Scene::build_gpu_accels()820{821#if defined(EMBREE_SYCL_SUPPORT)822accelBuffer.build(this);823bounds = LBBox<embree::Vec3fa>(accelBuffer.getBounds());824#endif825}826827void Scene::commit_task ()828{829checkIfModifiedAndSet();830if (!isModified()) return;831832833/* print scene statistics */834if (device->verbosity(2))835printStatistics();836837progress_monitor_counter = 0;838839/* gather scene stats and call preCommit function of each geometry */840this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),841[this](const range<size_t>& r)->GeometryCounts842{843GeometryCounts c;844for (auto i=r.begin(); i<r.end(); ++i)845{846if (geometries[i] && geometries[i]->isEnabled())847{848geometries[i]->preCommit();849geometries[i]->addElementsToCount (c);850c.numFilterFunctions += (int) geometries[i]->hasArgumentFilterFunctions();851c.numFilterFunctions += (int) geometries[i]->hasGeometryFilterFunctions();852}853}854return c;855},856std::plus<GeometryCounts>()857);858859/* calculate maximal number of motion blur time segments in scene */860maxTimeSegments = 1;861for (size_t geomID=0; geomID<size(); geomID++)862{863Geometry* geom = get(geomID);864if (geom == nullptr) continue;865maxTimeSegments = std::max(maxTimeSegments, geom->numTimeSegments());866}867868#if defined(EMBREE_SYCL_SUPPORT)869DeviceGPU* gpu_device = dynamic_cast<DeviceGPU*>(device);870if (gpu_device)871build_gpu_accels();872else873#endif874build_cpu_accels();875876/* call postCommit function of each geometry */877parallel_for(geometries.size(), [&] ( const size_t i ) {878if (geometries[i] && geometries[i]->isEnabled()) {879geometries[i]->postCommit();880vertices[i] = geometries[i]->getCompactVertexArray();881geometryModCounters_[i] = geometries[i]->getModCounter();882}883});884885setModified(false);886}887888void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)889{890if (quality_flags == quality_flags_i) return;891quality_flags = quality_flags_i;892flags_modified = true;893}894895RTCBuildQuality Scene::getBuildQuality() const {896return quality_flags;897}898899void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)900{901if (scene_flags == scene_flags_i) return;902scene_flags = scene_flags_i;903flags_modified = true;904}905906RTCSceneFlags Scene::getSceneFlags() const {907return scene_flags;908}909910#if defined(EMBREE_SYCL_SUPPORT)911sycl::event Scene::commit (bool join, sycl::queue queue)912{913commit_internal(join);914return syncWithDevice(queue);915}916#endif917918void Scene::commit (bool join)919{920commit_internal(join);921922#if defined(EMBREE_SYCL_SUPPORT)923syncWithDevice();924#endif925}926927Scene* Scene::getTraversable() {928#if defined(EMBREE_SYCL_SUPPORT)929if(device->is_gpu()) {930return scene_device;931}932#endif933return this;934}935936#if defined(TASKING_INTERNAL)937938void Scene::commit_internal (bool join)939{940Lock<MutexSys> buildLock(buildMutex,false);941942/* allocates own taskscheduler for each build */943Ref<TaskScheduler> scheduler = nullptr;944{945Lock<MutexSys> lock(taskGroup->schedulerMutex);946scheduler = taskGroup->scheduler;947if (scheduler == null) {948buildLock.lock();949taskGroup->scheduler = scheduler = new TaskScheduler;950}951}952953/* worker threads join build */954if (!buildLock.isLocked())955{956if (!join)957throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");958959scheduler->join();960return;961}962963/* initiate build */964//try {965TaskScheduler::TaskGroupContext context;966scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(taskGroup->schedulerMutex); taskGroup->scheduler = nullptr; }, &context, 1, !join);967//}968//catch (...) {969// accels_clear();970// Lock<MutexSys> lock(taskGroup->schedulerMutex);971// taskGroup->scheduler = nullptr;972// throw;973//}974}975976#endif977978#if defined(TASKING_TBB)979980void Scene::commit_internal (bool join)981{982#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)983if (join)984throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");985#endif986987/* try to obtain build lock */988Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());989990/* join hierarchy build */991if (!lock.isLocked())992{993#if !TASKING_TBB_USE_TASK_ISOLATION994if (!join)995throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");996#endif997998do {999device->execute(join, [&](){ taskGroup->group.wait(); });10001001pause_cpu();1002yield();1003} while (!buildMutex.try_lock());10041005buildMutex.unlock();1006return;1007}10081009/* for best performance set FTZ and DAZ flags in the MXCSR control and status register */1010const unsigned int mxcsr = _mm_getcsr();1011_mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));10121013try {1014#if TBB_INTERFACE_VERSION_MAJOR < 81015tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);1016#else1017tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );1018#endif1019//ctx.set_priority(tbb::priority_high);1020device->execute(join, [&]()1021{1022taskGroup->group.run([&]{1023tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);1024});1025taskGroup->group.wait();1026});10271028/* reset MXCSR register again */1029_mm_setcsr(mxcsr);1030}1031catch (...)1032{1033/* reset MXCSR register again */1034_mm_setcsr(mxcsr);10351036accels_clear();1037throw;1038}1039}1040#endif10411042#if defined(TASKING_PPL)10431044void Scene::commit_internal (bool join)1045{1046#if defined(TASKING_PPL)1047if (join)1048throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");1049#endif10501051/* try to obtain build lock */1052Lock<MutexSys> lock(buildMutex);10531054checkIfModifiedAndSet ();1055if (!isModified()) {1056return;1057}10581059/* for best performance set FTZ and DAZ flags in the MXCSR control and status register */1060const unsigned int mxcsr = _mm_getcsr();1061_mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));10621063try {10641065taskGroup->group.run([&]{1066concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });1067});1068taskGroup->group.wait();10691070/* reset MXCSR register again */1071_mm_setcsr(mxcsr);1072}1073catch (...)1074{1075/* reset MXCSR register again */1076_mm_setcsr(mxcsr);10771078accels_clear();1079throw;1080}10811082}1083#endif10841085void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)1086{1087progress_monitor_function = func;1088progress_monitor_ptr = ptr;1089}10901091void Scene::progressMonitor(double dn)1092{1093if (progress_monitor_function) {1094size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));1095if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {1096throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");1097}1098}1099}11001101}110211031104