mirror of
https://github.com/godotengine/godot.git
synced 2024-12-27 11:24:59 +08:00
1035 lines
40 KiB
C++
1035 lines
40 KiB
C++
// Copyright 2009-2021 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#include "scene.h"
|
|
|
|
#include "../../common/tasking/taskscheduler.h"
|
|
|
|
#include "../bvh/bvh4_factory.h"
|
|
#include "../bvh/bvh8_factory.h"
|
|
|
|
#include "../../common/algorithms/parallel_reduce.h"
|
|
|
|
#if defined(EMBREE_SYCL_SUPPORT)
|
|
# include "../sycl/rthwif_embree_builder.h"
|
|
#endif
|
|
|
|
|
|
namespace embree
|
|
{
|
|
|
|
struct TaskGroup {
|
|
/*! global lock step task scheduler */
|
|
#if defined(TASKING_INTERNAL)
|
|
MutexSys schedulerMutex;
|
|
Ref<TaskScheduler> scheduler;
|
|
#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
|
|
tbb::isolated_task_group group;
|
|
#elif defined(TASKING_TBB)
|
|
tbb::task_group group;
|
|
#elif defined(TASKING_PPL)
|
|
concurrency::task_group group;
|
|
#endif
|
|
};
|
|
|
|
/* error raising rtcIntersect and rtcOccluded functions */
|
|
void missing_rtcCommit() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed"); }
|
|
void invalid_rtcIntersect1() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect and rtcOccluded not enabled"); }
|
|
void invalid_rtcIntersect4() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect4 and rtcOccluded4 not enabled"); }
|
|
void invalid_rtcIntersect8() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect8 and rtcOccluded8 not enabled"); }
|
|
void invalid_rtcIntersect16() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect16 and rtcOccluded16 not enabled"); }
|
|
void invalid_rtcIntersectN() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectN and rtcOccludedN not enabled"); }
|
|
|
|
Scene::Scene (Device* device)
|
|
: device(device),
|
|
flags_modified(true), enabled_geometry_types(0),
|
|
scene_flags(RTC_SCENE_FLAG_NONE),
|
|
quality_flags(RTC_BUILD_QUALITY_MEDIUM),
|
|
modified(true),
|
|
taskGroup(new TaskGroup()),
|
|
progressInterface(this), progress_monitor_function(nullptr), progress_monitor_ptr(nullptr), progress_monitor_counter(0)
|
|
{
|
|
device->refInc();
|
|
|
|
intersectors = Accel::Intersectors(missing_rtcCommit);
|
|
|
|
/* use proper device and context for SYCL allocations */
|
|
#if defined(EMBREE_SYCL_SUPPORT)
|
|
if (DeviceGPU* gpu_device = dynamic_cast<DeviceGPU*>(device))
|
|
hwaccel = AccelBuffer(AccelAllocator<char>(device,gpu_device->getGPUDevice(),gpu_device->getGPUContext()),0);
|
|
#endif
|
|
|
|
/* one can overwrite flags through device for debugging */
|
|
if (device->quality_flags != -1)
|
|
quality_flags = (RTCBuildQuality) device->quality_flags;
|
|
if (device->scene_flags != -1)
|
|
scene_flags = (RTCSceneFlags) device->scene_flags;
|
|
}
|
|
|
|
Scene::~Scene() noexcept
|
|
{
|
|
device->refDec();
|
|
}
|
|
|
|
void Scene::printStatistics()
|
|
{
|
|
/* calculate maximum number of time segments */
|
|
unsigned max_time_steps = 0;
|
|
for (size_t i=0; i<size(); i++) {
|
|
if (!get(i)) continue;
|
|
max_time_steps = max(max_time_steps,get(i)->numTimeSteps);
|
|
}
|
|
|
|
/* initialize vectors*/
|
|
std::vector<size_t> statistics[Geometry::GTY_END];
|
|
for (size_t i=0; i<Geometry::GTY_END; i++)
|
|
statistics[i].resize(max_time_steps);
|
|
|
|
/* gather statistics */
|
|
for (size_t i=0; i<size(); i++)
|
|
{
|
|
if (!get(i)) continue;
|
|
int ty = get(i)->getType();
|
|
assert(ty<Geometry::GTY_END);
|
|
int timesegments = get(i)->numTimeSegments();
|
|
assert((unsigned int)timesegments < max_time_steps);
|
|
statistics[ty][timesegments] += get(i)->size();
|
|
}
|
|
|
|
/* print statistics */
|
|
std::cout << std::setw(23) << "segments" << ": ";
|
|
for (size_t t=0; t<max_time_steps; t++)
|
|
std::cout << std::setw(10) << t;
|
|
std::cout << std::endl;
|
|
|
|
std::cout << "-------------------------";
|
|
for (size_t t=0; t<max_time_steps; t++)
|
|
std::cout << "----------";
|
|
std::cout << std::endl;
|
|
|
|
for (size_t p=0; p<Geometry::GTY_END; p++)
|
|
{
|
|
if (std::string(Geometry::gtype_names[p]) == "") continue;
|
|
std::cout << std::setw(23) << Geometry::gtype_names[p] << ": ";
|
|
for (size_t t=0; t<max_time_steps; t++)
|
|
std::cout << std::setw(10) << statistics[p][t];
|
|
std::cout << std::endl;
|
|
}
|
|
}
|
|
|
|
void Scene::createTriangleAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
|
|
|
if (device->tri_accel == "default")
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW)
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
{
|
|
if (quality_flags == RTC_BUILD_QUALITY_HIGH)
|
|
accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
|
|
else
|
|
accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags == RTC_BUILD_QUALITY_HIGH)
|
|
accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
|
|
else
|
|
accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
break;
|
|
|
|
case /*0b01*/ 1:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
|
|
break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else /* dynamic */
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (device->tri_accel == "bvh4.triangle4") accels_add(device->bvh4_factory->BVH4Triangle4 (this));
|
|
else if (device->tri_accel == "bvh4.triangle4v") accels_add(device->bvh4_factory->BVH4Triangle4v(this));
|
|
else if (device->tri_accel == "bvh4.triangle4i") accels_add(device->bvh4_factory->BVH4Triangle4i(this));
|
|
else if (device->tri_accel == "qbvh4.triangle4i") accels_add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));
|
|
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->tri_accel == "bvh8.triangle4") accels_add(device->bvh8_factory->BVH8Triangle4 (this));
|
|
else if (device->tri_accel == "bvh8.triangle4v") accels_add(device->bvh8_factory->BVH8Triangle4v(this));
|
|
else if (device->tri_accel == "bvh8.triangle4i") accels_add(device->bvh8_factory->BVH8Triangle4i(this));
|
|
else if (device->tri_accel == "qbvh8.triangle4i") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4i(this));
|
|
else if (device->tri_accel == "qbvh8.triangle4") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);
|
|
#endif
|
|
|
|
}
|
|
|
|
void Scene::createTriangleMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
|
|
|
if (device->tri_accel_mb == "default")
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX2()) // BVH8 reduces performance on AVX only-machines
|
|
{
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
}
|
|
else if (device->tri_accel_mb == "bvh4.triangle4imb") accels_add(device->bvh4_factory->BVH4Triangle4iMB(this));
|
|
else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels_add(device->bvh4_factory->BVH4Triangle4vMB(this));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->tri_accel_mb == "bvh8.triangle4imb") accels_add(device->bvh8_factory->BVH8Triangle4iMB(this));
|
|
else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels_add(device->bvh8_factory->BVH8Triangle4vMB(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur triangle acceleration structure "+device->tri_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createQuadAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_QUAD)
|
|
|
|
if (device->quad_accel == "default")
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW)
|
|
{
|
|
/* static */
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
{
|
|
if (quality_flags == RTC_BUILD_QUALITY_HIGH)
|
|
accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
|
|
else
|
|
accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags == RTC_BUILD_QUALITY_HIGH)
|
|
accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
|
|
else
|
|
accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
break;
|
|
|
|
case /*0b01*/ 1:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
break;
|
|
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else /* dynamic */
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (device->quad_accel == "bvh4.quad4v") accels_add(device->bvh4_factory->BVH4Quad4v(this));
|
|
else if (device->quad_accel == "bvh4.quad4i") accels_add(device->bvh4_factory->BVH4Quad4i(this));
|
|
else if (device->quad_accel == "qbvh4.quad4i") accels_add(device->bvh4_factory->BVH4QuantizedQuad4i(this));
|
|
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->quad_accel == "bvh8.quad4v") accels_add(device->bvh8_factory->BVH8Quad4v(this));
|
|
else if (device->quad_accel == "bvh8.quad4i") accels_add(device->bvh8_factory->BVH8Quad4i(this));
|
|
else if (device->quad_accel == "qbvh8.quad4i") accels_add(device->bvh8_factory->BVH8QuantizedQuad4i(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad acceleration structure "+device->quad_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createQuadMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_QUAD)
|
|
|
|
if (device->quad_accel_mb == "default")
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
switch (mode) {
|
|
case /*0b00*/ 0:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
|
|
break;
|
|
|
|
case /*0b01*/ 1:
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX())
|
|
accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
|
|
break;
|
|
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else if (device->quad_accel_mb == "bvh4.quad4imb") accels_add(device->bvh4_factory->BVH4Quad4iMB(this));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->quad_accel_mb == "bvh8.quad4imb") accels_add(device->bvh8_factory->BVH8Quad4iMB(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createHairAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
|
|
|
|
if (device->hair_accel == "default")
|
|
{
|
|
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX2()) // only enable on HSW machines, for SNB this codepath is slower
|
|
{
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
switch (mode) {
|
|
case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST)); break;
|
|
case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::ROBUST)); break;
|
|
}
|
|
}
|
|
}
|
|
else if (device->hair_accel == "bvh4obb.virtualcurve4v" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST));
|
|
else if (device->hair_accel == "bvh4obb.virtualcurve4i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->hair_accel == "bvh8obb.virtualcurve8v" ) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST));
|
|
else if (device->hair_accel == "bvh4obb.virtualcurve8i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown hair acceleration structure "+device->hair_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createHairMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
|
|
|
|
if (device->hair_accel_mb == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX2()) // only enable on HSW machines, on SNB this codepath is slower
|
|
{
|
|
if (isRobustAccel()) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::ROBUST));
|
|
else accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (isRobustAccel()) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::ROBUST));
|
|
else accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
|
|
}
|
|
}
|
|
else if (device->hair_accel_mb == "bvh4.virtualcurve4imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
|
|
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->hair_accel_mb == "bvh4.virtualcurve8imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
|
|
else if (device->hair_accel_mb == "bvh8.virtualcurve8imb") accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createSubdivAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_SUBDIVISION)
|
|
if (device->subdiv_accel == "default") {
|
|
accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
|
|
}
|
|
else if (device->subdiv_accel == "bvh4.grid.eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
|
|
else if (device->subdiv_accel == "bvh4.subdivpatch1eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv accel "+device->subdiv_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createSubdivMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_SUBDIVISION)
|
|
if (device->subdiv_accel_mb == "default") {
|
|
accels_add(device->bvh4_factory->BVH4SubdivPatch1MB(this));
|
|
}
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv mblur accel "+device->subdiv_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createUserGeometryAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_USER)
|
|
|
|
if (device->object_accel == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
}
|
|
else if (device->object_accel == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometry(this));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->object_accel == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometry(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createUserGeometryMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_USER)
|
|
|
|
if (device->object_accel_mb == "default" ) {
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
|
|
}
|
|
else if (device->object_accel_mb == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->object_accel_mb == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE)
|
|
|
|
// if (device->object_accel == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel()) {
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
}
|
|
// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE)
|
|
|
|
//if (device->instance_accel_mb == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
accels_add(device->bvh8_factory->BVH8InstanceMB(this, false));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4InstanceMB(this, false));
|
|
}
|
|
//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceExpensiveAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE)
|
|
// if (device->object_accel == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel()) {
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
}
|
|
// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceExpensiveMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE)
|
|
//if (device->instance_accel_mb == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
accels_add(device->bvh8_factory->BVH8InstanceMB(this, true));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4InstanceMB(this, true));
|
|
}
|
|
//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceArrayAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)
|
|
|
|
// if (device->object_accel == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel()) {
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh8_factory->BVH8InstanceArray(this, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh8_factory->BVH8InstanceArray(this, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (quality_flags != RTC_BUILD_QUALITY_LOW) {
|
|
accels_add(device->bvh4_factory->BVH4InstanceArray(this, BVHFactory::BuildVariant::STATIC));
|
|
} else {
|
|
accels_add(device->bvh4_factory->BVH4InstanceArray(this, BVHFactory::BuildVariant::DYNAMIC));
|
|
}
|
|
}
|
|
}
|
|
// else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
|
|
#endif
|
|
}
|
|
|
|
void Scene::createInstanceArrayMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)
|
|
|
|
//if (device->instance_accel_mb == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
accels_add(device->bvh8_factory->BVH8InstanceArrayMB(this));
|
|
else
|
|
#endif
|
|
accels_add(device->bvh4_factory->BVH4InstanceArrayMB(this));
|
|
}
|
|
//else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
|
|
#endif
|
|
}
|
|
|
|
|
|
void Scene::createGridAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_GRID)
|
|
|
|
BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST;
|
|
|
|
if (device->grid_accel == "default")
|
|
{
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
if (device->canUseAVX() && !isCompactAccel())
|
|
{
|
|
accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
|
|
}
|
|
}
|
|
else if (device->grid_accel == "bvh4.grid") accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
|
|
#if defined (EMBREE_TARGET_SIMD8)
|
|
else if (device->grid_accel == "bvh8.grid") accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
|
|
#endif
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid accel "+device->grid_accel);
|
|
#endif
|
|
|
|
}
|
|
|
|
void Scene::createGridMBAccel()
|
|
{
|
|
#if defined(EMBREE_GEOMETRY_GRID)
|
|
|
|
if (device->grid_accel_mb == "default")
|
|
{
|
|
accels_add(device->bvh4_factory->BVH4GridMB(this,BVHFactory::BuildVariant::STATIC));
|
|
}
|
|
else if (device->grid_accel_mb == "bvh4mb.grid") accels_add(device->bvh4_factory->BVH4GridMB(this));
|
|
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid mb accel "+device->grid_accel);
|
|
#endif
|
|
|
|
}
|
|
|
|
void Scene::clear() {
|
|
}
|
|
|
|
unsigned Scene::bind(unsigned geomID, Ref<Geometry> geometry)
|
|
{
|
|
Lock<MutexSys> lock(geometriesMutex);
|
|
if (geomID == RTC_INVALID_GEOMETRY_ID) {
|
|
geomID = id_pool.allocate();
|
|
if (geomID == RTC_INVALID_GEOMETRY_ID)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"too many geometries inside scene");
|
|
}
|
|
else
|
|
{
|
|
if (!id_pool.add(geomID))
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID provided");
|
|
}
|
|
if (geomID >= geometries.size()) {
|
|
geometries.resize(geomID+1);
|
|
vertices.resize(geomID+1);
|
|
geometryModCounters_.resize(geomID+1);
|
|
}
|
|
geometries[geomID] = geometry;
|
|
geometryModCounters_[geomID] = 0;
|
|
if (geometry->isEnabled()) {
|
|
setModified ();
|
|
}
|
|
return geomID;
|
|
}
|
|
|
|
void Scene::detachGeometry(size_t geomID)
|
|
{
|
|
Lock<MutexSys> lock(geometriesMutex);
|
|
|
|
if (geomID >= geometries.size())
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID");
|
|
|
|
Ref<Geometry>& geometry = geometries[geomID];
|
|
if (geometry == null)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");
|
|
|
|
setModified ();
|
|
accels_deleteGeometry(unsigned(geomID));
|
|
id_pool.deallocate((unsigned)geomID);
|
|
geometries[geomID] = null;
|
|
vertices[geomID] = nullptr;
|
|
geometryModCounters_[geomID] = 0;
|
|
}
|
|
|
|
void Scene::build_cpu_accels()
|
|
{
|
|
/* select acceleration structures to build */
|
|
unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
|
|
|
|
if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
|
|
{
|
|
accels_init();
|
|
|
|
/* we need to make all geometries modified, otherwise two level builder will
|
|
not rebuild currently not modified geometries */
|
|
parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {
|
|
geometryModCounters_[i] = 0;
|
|
});
|
|
|
|
if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();
|
|
if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();
|
|
if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();
|
|
if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();
|
|
if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();
|
|
if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();
|
|
if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();
|
|
if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();
|
|
if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();
|
|
if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();
|
|
if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();
|
|
if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_ARRAY,false)) createInstanceArrayAccel();
|
|
if (getNumPrimitives(Geometry::MTY_INSTANCE_ARRAY,true)) createInstanceArrayMBAccel();
|
|
|
|
flags_modified = false;
|
|
enabled_geometry_types = new_enabled_geometry_types;
|
|
}
|
|
|
|
/* select fast code path if no filter function is present */
|
|
accels_select(hasFilterFunction());
|
|
|
|
/* build all hierarchies of this scene */
|
|
accels_build();
|
|
|
|
/* make static geometry immutable */
|
|
if (!isDynamicAccel()) {
|
|
accels_immutable();
|
|
flags_modified = true; // in non-dynamic mode we have to re-create accels
|
|
}
|
|
|
|
if (device->verbosity(2)) {
|
|
std::cout << "created scene intersector" << std::endl;
|
|
accels_print(2);
|
|
std::cout << "selected scene intersector" << std::endl;
|
|
intersectors.print(2);
|
|
}
|
|
}
|
|
|
|
void Scene::build_gpu_accels()
|
|
{
|
|
#if defined(EMBREE_SYCL_SUPPORT)
|
|
const BBox3f aabb = rthwifBuild(this,hwaccel);
|
|
bounds = LBBox<embree::Vec3fa>(aabb);
|
|
hwaccel_bounds = aabb;
|
|
#endif
|
|
}
|
|
|
|
void Scene::commit_task ()
|
|
{
|
|
checkIfModifiedAndSet();
|
|
if (!isModified()) return;
|
|
|
|
/* print scene statistics */
|
|
if (device->verbosity(2))
|
|
printStatistics();
|
|
|
|
progress_monitor_counter = 0;
|
|
|
|
/* gather scene stats and call preCommit function of each geometry */
|
|
this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),
|
|
[this](const range<size_t>& r)->GeometryCounts
|
|
{
|
|
GeometryCounts c;
|
|
for (auto i=r.begin(); i<r.end(); ++i)
|
|
{
|
|
if (geometries[i] && geometries[i]->isEnabled())
|
|
{
|
|
geometries[i]->preCommit();
|
|
geometries[i]->addElementsToCount (c);
|
|
c.numFilterFunctions += (int) geometries[i]->hasArgumentFilterFunctions();
|
|
c.numFilterFunctions += (int) geometries[i]->hasGeometryFilterFunctions();
|
|
}
|
|
}
|
|
return c;
|
|
},
|
|
std::plus<GeometryCounts>()
|
|
);
|
|
|
|
#if defined(EMBREE_SYCL_SUPPORT)
|
|
if (DeviceGPU* gpu_device = dynamic_cast<DeviceGPU*>(device))
|
|
build_gpu_accels();
|
|
else
|
|
#endif
|
|
build_cpu_accels();
|
|
|
|
/* call postCommit function of each geometry */
|
|
parallel_for(geometries.size(), [&] ( const size_t i ) {
|
|
if (geometries[i] && geometries[i]->isEnabled()) {
|
|
geometries[i]->postCommit();
|
|
vertices[i] = geometries[i]->getCompactVertexArray();
|
|
geometryModCounters_[i] = geometries[i]->getModCounter();
|
|
}
|
|
});
|
|
|
|
setModified(false);
|
|
}
|
|
|
|
void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)
|
|
{
|
|
if (quality_flags == quality_flags_i) return;
|
|
quality_flags = quality_flags_i;
|
|
flags_modified = true;
|
|
}
|
|
|
|
RTCBuildQuality Scene::getBuildQuality() const {
|
|
return quality_flags;
|
|
}
|
|
|
|
void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)
|
|
{
|
|
if (scene_flags == scene_flags_i) return;
|
|
scene_flags = scene_flags_i;
|
|
flags_modified = true;
|
|
}
|
|
|
|
RTCSceneFlags Scene::getSceneFlags() const {
|
|
return scene_flags;
|
|
}
|
|
|
|
#if defined(TASKING_INTERNAL)
|
|
|
|
void Scene::commit (bool join)
|
|
{
|
|
Lock<MutexSys> buildLock(buildMutex,false);
|
|
|
|
/* allocates own taskscheduler for each build */
|
|
Ref<TaskScheduler> scheduler = nullptr;
|
|
{
|
|
Lock<MutexSys> lock(taskGroup->schedulerMutex);
|
|
scheduler = taskGroup->scheduler;
|
|
if (scheduler == null) {
|
|
buildLock.lock();
|
|
taskGroup->scheduler = scheduler = new TaskScheduler;
|
|
}
|
|
}
|
|
|
|
/* worker threads join build */
|
|
if (!buildLock.isLocked())
|
|
{
|
|
if (!join)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");
|
|
|
|
scheduler->join();
|
|
return;
|
|
}
|
|
|
|
/* initiate build */
|
|
// -- GODOT start --
|
|
// try {
|
|
TaskScheduler::TaskGroupContext context;
|
|
scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(taskGroup->schedulerMutex); taskGroup->scheduler = nullptr; }, &context, 1, !join);
|
|
// }
|
|
// catch (...) {
|
|
// accels_clear();
|
|
// Lock<MutexSys> lock(taskGroup->schedulerMutex);
|
|
// taskGroup->scheduler = nullptr;
|
|
// throw;
|
|
// }
|
|
// -- GODOT end --
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(TASKING_TBB)
|
|
|
|
void Scene::commit (bool join)
|
|
{
|
|
#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
|
|
if (join)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");
|
|
#endif
|
|
|
|
/* try to obtain build lock */
|
|
Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());
|
|
|
|
/* join hierarchy build */
|
|
if (!lock.isLocked())
|
|
{
|
|
#if !TASKING_TBB_USE_TASK_ISOLATION
|
|
if (!join)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");
|
|
#endif
|
|
|
|
do {
|
|
device->execute(join, [&](){ taskGroup->group.wait(); });
|
|
|
|
pause_cpu();
|
|
yield();
|
|
} while (!buildMutex.try_lock());
|
|
|
|
buildMutex.unlock();
|
|
return;
|
|
}
|
|
|
|
/* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
|
|
const unsigned int mxcsr = _mm_getcsr();
|
|
_mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
|
|
|
|
try {
|
|
#if TBB_INTERFACE_VERSION_MAJOR < 8
|
|
tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);
|
|
#else
|
|
tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );
|
|
#endif
|
|
//ctx.set_priority(tbb::priority_high);
|
|
device->execute(join, [&]()
|
|
{
|
|
taskGroup->group.run([&]{
|
|
tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
|
|
});
|
|
taskGroup->group.wait();
|
|
});
|
|
|
|
/* reset MXCSR register again */
|
|
_mm_setcsr(mxcsr);
|
|
}
|
|
catch (...)
|
|
{
|
|
/* reset MXCSR register again */
|
|
_mm_setcsr(mxcsr);
|
|
|
|
accels_clear();
|
|
throw;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if defined(TASKING_PPL)
|
|
|
|
void Scene::commit (bool join)
|
|
{
|
|
#if defined(TASKING_PPL)
|
|
if (join)
|
|
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");
|
|
#endif
|
|
|
|
/* try to obtain build lock */
|
|
Lock<MutexSys> lock(buildMutex);
|
|
|
|
checkIfModifiedAndSet ();
|
|
if (!isModified()) {
|
|
return;
|
|
}
|
|
|
|
/* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
|
|
const unsigned int mxcsr = _mm_getcsr();
|
|
_mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
|
|
|
|
try {
|
|
|
|
taskGroup->group.run([&]{
|
|
concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });
|
|
});
|
|
taskGroup->group.wait();
|
|
|
|
/* reset MXCSR register again */
|
|
_mm_setcsr(mxcsr);
|
|
}
|
|
catch (...)
|
|
{
|
|
/* reset MXCSR register again */
|
|
_mm_setcsr(mxcsr);
|
|
|
|
accels_clear();
|
|
throw;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)
|
|
{
|
|
progress_monitor_function = func;
|
|
progress_monitor_ptr = ptr;
|
|
}
|
|
|
|
void Scene::progressMonitor(double dn)
|
|
{
|
|
if (progress_monitor_function) {
|
|
size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));
|
|
if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {
|
|
throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");
|
|
}
|
|
}
|
|
}
|
|
}
|