device.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "device.h"
  4. #include "../hash.h"
  5. #include "scene_triangle_mesh.h"
  6. #include "scene_user_geometry.h"
  7. #include "scene_instance.h"
  8. #include "scene_curves.h"
  9. #include "scene_subdiv_mesh.h"
  10. #include "../subdiv/tessellation_cache.h"
  11. #include "acceln.h"
  12. #include "geometry.h"
  13. #include "../geometry/cylinder.h"
  14. #include "../bvh/bvh4_factory.h"
  15. #include "../bvh/bvh8_factory.h"
  16. #include "../../common/tasking/taskscheduler.h"
  17. #include "../../common/sys/alloc.h"
  18. namespace embree
  19. {
  20. /*! some global variables that can be set via rtcSetParameter1i for debugging purposes */
  21. ssize_t Device::debug_int0 = 0;
  22. ssize_t Device::debug_int1 = 0;
  23. ssize_t Device::debug_int2 = 0;
  24. ssize_t Device::debug_int3 = 0;
  25. DECLARE_SYMBOL2(RayStreamFilterFuncs,rayStreamFilterFuncs);
  26. static MutexSys g_mutex;
  27. static std::map<Device*,size_t> g_cache_size_map;
  28. static std::map<Device*,size_t> g_num_threads_map;
  29. Device::Device (const char* cfg)
  30. {
  31. /* check that CPU supports lowest ISA */
  32. if (!hasISA(ISA)) {
  33. throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support " ISA_STR);
  34. }
  35. /* set default frequency level for detected CPU */
  36. switch (getCPUModel()) {
  37. case CPU::UNKNOWN: frequency_level = FREQUENCY_SIMD256; break;
  38. case CPU::XEON_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
  39. case CPU::CORE_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
  40. case CPU::CORE_TIGER_LAKE: frequency_level = FREQUENCY_SIMD128; break;
  41. case CPU::CORE_COMET_LAKE: frequency_level = FREQUENCY_SIMD128; break;
  42. case CPU::CORE_CANNON_LAKE:frequency_level = FREQUENCY_SIMD128; break;
  43. case CPU::CORE_KABY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
  44. case CPU::XEON_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
  45. case CPU::CORE_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
  46. case CPU::XEON_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
  47. case CPU::CORE_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
  48. case CPU::XEON_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
  49. case CPU::CORE_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
  50. case CPU::XEON_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
  51. case CPU::CORE_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
  52. case CPU::SANDY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
  53. case CPU::NEHALEM: frequency_level = FREQUENCY_SIMD128; break;
  54. case CPU::CORE2: frequency_level = FREQUENCY_SIMD128; break;
  55. case CPU::CORE1: frequency_level = FREQUENCY_SIMD128; break;
  56. case CPU::XEON_PHI_KNIGHTS_MILL : frequency_level = FREQUENCY_SIMD512; break;
  57. case CPU::XEON_PHI_KNIGHTS_LANDING: frequency_level = FREQUENCY_SIMD512; break;
  58. #if defined(__APPLE__)
  59. case CPU::ARM: frequency_level = FREQUENCY_SIMD256; break; // Apple M1 supports high throughput for SIMD4
  60. #else
  61. case CPU::ARM: frequency_level = FREQUENCY_SIMD128; break;
  62. #endif
  63. }
  64. /* initialize global state */
  65. #if defined(EMBREE_CONFIG)
  66. State::parseString(EMBREE_CONFIG);
  67. #endif
  68. State::parseString(cfg);
  69. State::verify();
  70. /* check whether selected ISA is supported by the HW, as the user could have forced an unsupported ISA */
  71. if (!checkISASupport()) {
  72. throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support selected ISA");
  73. }
  74. /*! do some internal tests */
  75. assert(isa::Cylinder::verify());
  76. /*! enable huge page support if desired */
  77. #if defined(__WIN32__)
  78. if (State::enable_selockmemoryprivilege)
  79. State::hugepages_success &= win_enable_selockmemoryprivilege(State::verbosity(3));
  80. #endif
  81. State::hugepages_success &= os_init(State::hugepages,State::verbosity(3));
  82. /*! set tessellation cache size */
  83. setCacheSize( State::tessellation_cache_size );
  84. /*! enable some floating point exceptions to catch bugs */
  85. if (State::float_exceptions)
  86. {
  87. int exceptions = _MM_MASK_MASK;
  88. //exceptions &= ~_MM_MASK_INVALID;
  89. exceptions &= ~_MM_MASK_DENORM;
  90. exceptions &= ~_MM_MASK_DIV_ZERO;
  91. //exceptions &= ~_MM_MASK_OVERFLOW;
  92. //exceptions &= ~_MM_MASK_UNDERFLOW;
  93. //exceptions &= ~_MM_MASK_INEXACT;
  94. _MM_SET_EXCEPTION_MASK(exceptions);
  95. }
  96. /* print info header */
  97. if (State::verbosity(1))
  98. print();
  99. if (State::verbosity(2))
  100. State::print();
  101. /* register all algorithms */
  102. bvh4_factory = make_unique(new BVH4Factory(enabled_builder_cpu_features, enabled_cpu_features));
  103. #if defined(EMBREE_TARGET_SIMD8)
  104. bvh8_factory = make_unique(new BVH8Factory(enabled_builder_cpu_features, enabled_cpu_features));
  105. #endif
  106. /* setup tasking system */
  107. initTaskingSystem(numThreads);
  108. /* ray stream SOA to AOS conversion */
  109. #if defined(EMBREE_RAY_PACKETS)
  110. RayStreamFilterFuncsType rayStreamFilterFuncs;
  111. SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(enabled_cpu_features,rayStreamFilterFuncs);
  112. rayStreamFilters = rayStreamFilterFuncs();
  113. #endif
  114. }
  115. Device::~Device ()
  116. {
  117. setCacheSize(0);
  118. exitTaskingSystem();
  119. }
  120. std::string getEnabledTargets()
  121. {
  122. std::string v;
  123. #if defined(EMBREE_TARGET_SSE2)
  124. v += "SSE2 ";
  125. #endif
  126. #if defined(EMBREE_TARGET_SSE42)
  127. v += "SSE4.2 ";
  128. #endif
  129. #if defined(EMBREE_TARGET_AVX)
  130. v += "AVX ";
  131. #endif
  132. #if defined(EMBREE_TARGET_AVX2)
  133. v += "AVX2 ";
  134. #endif
  135. #if defined(EMBREE_TARGET_AVX512)
  136. v += "AVX512 ";
  137. #endif
  138. return v;
  139. }
  140. std::string getEmbreeFeatures()
  141. {
  142. std::string v;
  143. #if defined(EMBREE_RAY_MASK)
  144. v += "raymasks ";
  145. #endif
  146. #if defined (EMBREE_BACKFACE_CULLING)
  147. v += "backfaceculling ";
  148. #endif
  149. #if defined (EMBREE_BACKFACE_CULLING_CURVES)
  150. v += "backfacecullingcurves ";
  151. #endif
  152. #if defined(EMBREE_FILTER_FUNCTION)
  153. v += "intersection_filter ";
  154. #endif
  155. #if defined (EMBREE_COMPACT_POLYS)
  156. v += "compact_polys ";
  157. #endif
  158. return v;
  159. }
  160. void Device::print()
  161. {
  162. const int cpu_features = getCPUFeatures();
  163. std::cout << std::endl;
  164. std::cout << "Embree Ray Tracing Kernels " << RTC_VERSION_STRING << " (" << RTC_HASH << ")" << std::endl;
  165. std::cout << " Compiler : " << getCompilerName() << std::endl;
  166. std::cout << " Build : ";
  167. #if defined(DEBUG)
  168. std::cout << "Debug " << std::endl;
  169. #else
  170. std::cout << "Release " << std::endl;
  171. #endif
  172. std::cout << " Platform : " << getPlatformName() << std::endl;
  173. std::cout << " CPU : " << stringOfCPUModel(getCPUModel()) << " (" << getCPUVendor() << ")" << std::endl;
  174. std::cout << " Threads : " << getNumberOfLogicalThreads() << std::endl;
  175. std::cout << " ISA : " << stringOfCPUFeatures(cpu_features) << std::endl;
  176. std::cout << " Targets : " << supportedTargetList(cpu_features) << std::endl;
  177. const bool hasFTZ = _mm_getcsr() & _MM_FLUSH_ZERO_ON;
  178. const bool hasDAZ = _mm_getcsr() & _MM_DENORMALS_ZERO_ON;
  179. std::cout << " MXCSR : " << "FTZ=" << hasFTZ << ", DAZ=" << hasDAZ << std::endl;
  180. std::cout << " Config" << std::endl;
  181. std::cout << " Threads : " << (numThreads ? toString(numThreads) : std::string("default")) << std::endl;
  182. std::cout << " ISA : " << stringOfCPUFeatures(enabled_cpu_features) << std::endl;
  183. std::cout << " Targets : " << supportedTargetList(enabled_cpu_features) << " (supported)" << std::endl;
  184. std::cout << " " << getEnabledTargets() << " (compile time enabled)" << std::endl;
  185. std::cout << " Features: " << getEmbreeFeatures() << std::endl;
  186. std::cout << " Tasking : ";
  187. #if defined(TASKING_TBB)
  188. std::cout << "TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR << " ";
  189. #if TBB_INTERFACE_VERSION >= 12002
  190. std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << TBB_runtime_interface_version() << " ";
  191. #else
  192. std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version() << " ";
  193. #endif
  194. #endif
  195. #if defined(TASKING_INTERNAL)
  196. std::cout << "internal_tasking_system ";
  197. #endif
  198. #if defined(TASKING_PPL)
  199. std::cout << "PPL ";
  200. #endif
  201. std::cout << std::endl;
  202. /* check of FTZ and DAZ flags are set in CSR */
  203. if (!hasFTZ || !hasDAZ)
  204. {
  205. #if !defined(_DEBUG)
  206. if (State::verbosity(1))
  207. #endif
  208. {
  209. std::cout << std::endl;
  210. std::cout << "================================================================================" << std::endl;
  211. std::cout << " WARNING: \"Flush to Zero\" or \"Denormals are Zero\" mode not enabled " << std::endl
  212. << " in the MXCSR control and status register. This can have a severe " << std::endl
  213. << " performance impact. Please enable these modes for each application " << std::endl
  214. << " thread the following way:" << std::endl
  215. << std::endl
  216. << " #include \"xmmintrin.h\"" << std::endl
  217. << " #include \"pmmintrin.h\"" << std::endl
  218. << std::endl
  219. << " _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);" << std::endl
  220. << " _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);" << std::endl;
  221. std::cout << "================================================================================" << std::endl;
  222. std::cout << std::endl;
  223. }
  224. }
  225. std::cout << std::endl;
  226. }
  227. void Device::setDeviceErrorCode(RTCError error)
  228. {
  229. RTCError* stored_error = errorHandler.error();
  230. if (*stored_error == RTC_ERROR_NONE)
  231. *stored_error = error;
  232. }
  233. RTCError Device::getDeviceErrorCode()
  234. {
  235. RTCError* stored_error = errorHandler.error();
  236. RTCError error = *stored_error;
  237. *stored_error = RTC_ERROR_NONE;
  238. return error;
  239. }
  240. void Device::setThreadErrorCode(RTCError error)
  241. {
  242. RTCError* stored_error = g_errorHandler.error();
  243. if (*stored_error == RTC_ERROR_NONE)
  244. *stored_error = error;
  245. }
  246. RTCError Device::getThreadErrorCode()
  247. {
  248. RTCError* stored_error = g_errorHandler.error();
  249. RTCError error = *stored_error;
  250. *stored_error = RTC_ERROR_NONE;
  251. return error;
  252. }
  253. void Device::process_error(Device* device, RTCError error, const char* str)
  254. {
  255. /* store global error code when device construction failed */
  256. if (!device)
  257. return setThreadErrorCode(error);
  258. /* print error when in verbose mode */
  259. if (device->verbosity(1))
  260. {
  261. switch (error) {
  262. case RTC_ERROR_NONE : std::cerr << "Embree: No error"; break;
  263. case RTC_ERROR_UNKNOWN : std::cerr << "Embree: Unknown error"; break;
  264. case RTC_ERROR_INVALID_ARGUMENT : std::cerr << "Embree: Invalid argument"; break;
  265. case RTC_ERROR_INVALID_OPERATION: std::cerr << "Embree: Invalid operation"; break;
  266. case RTC_ERROR_OUT_OF_MEMORY : std::cerr << "Embree: Out of memory"; break;
  267. case RTC_ERROR_UNSUPPORTED_CPU : std::cerr << "Embree: Unsupported CPU"; break;
  268. default : std::cerr << "Embree: Invalid error code"; break;
  269. };
  270. if (str) std::cerr << ", (" << str << ")";
  271. std::cerr << std::endl;
  272. }
  273. /* call user specified error callback */
  274. if (device->error_function)
  275. device->error_function(device->error_function_userptr,error,str);
  276. /* record error code */
  277. device->setDeviceErrorCode(error);
  278. }
  279. void Device::memoryMonitor(ssize_t bytes, bool post)
  280. {
  281. if (State::memory_monitor_function && bytes != 0) {
  282. if (!State::memory_monitor_function(State::memory_monitor_userptr,bytes,post)) {
  283. if (bytes > 0) { // only throw exception when we allocate memory to never throw inside a destructor
  284. throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"memory monitor forced termination");
  285. }
  286. }
  287. }
  288. }
  289. size_t getMaxNumThreads()
  290. {
  291. size_t maxNumThreads = 0;
  292. for (std::map<Device*,size_t>::iterator i=g_num_threads_map.begin(); i != g_num_threads_map.end(); i++)
  293. maxNumThreads = max(maxNumThreads, (*i).second);
  294. if (maxNumThreads == 0)
  295. maxNumThreads = std::numeric_limits<size_t>::max();
  296. return maxNumThreads;
  297. }
  298. size_t getMaxCacheSize()
  299. {
  300. size_t maxCacheSize = 0;
  301. for (std::map<Device*,size_t>::iterator i=g_cache_size_map.begin(); i!= g_cache_size_map.end(); i++)
  302. maxCacheSize = max(maxCacheSize, (*i).second);
  303. return maxCacheSize;
  304. }
  305. void Device::setCacheSize(size_t bytes)
  306. {
  307. #if defined(EMBREE_GEOMETRY_SUBDIVISION)
  308. Lock<MutexSys> lock(g_mutex);
  309. if (bytes == 0) g_cache_size_map.erase(this);
  310. else g_cache_size_map[this] = bytes;
  311. size_t maxCacheSize = getMaxCacheSize();
  312. resizeTessellationCache(maxCacheSize);
  313. #endif
  314. }
  315. void Device::initTaskingSystem(size_t numThreads)
  316. {
  317. Lock<MutexSys> lock(g_mutex);
  318. if (numThreads == 0)
  319. g_num_threads_map[this] = std::numeric_limits<size_t>::max();
  320. else
  321. g_num_threads_map[this] = numThreads;
  322. /* create task scheduler */
  323. size_t maxNumThreads = getMaxNumThreads();
  324. TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
  325. #if USE_TASK_ARENA
  326. const size_t nThreads = min(maxNumThreads,TaskScheduler::threadCount());
  327. const size_t uThreads = min(max(numUserThreads,(size_t)1),nThreads);
  328. arena = make_unique(new tbb::task_arena((int)nThreads,(unsigned int)uThreads));
  329. #endif
  330. }
  331. void Device::exitTaskingSystem()
  332. {
  333. Lock<MutexSys> lock(g_mutex);
  334. g_num_threads_map.erase(this);
  335. /* terminate tasking system */
  336. if (g_num_threads_map.size() == 0) {
  337. TaskScheduler::destroy();
  338. }
  339. /* or configure new number of threads */
  340. else {
  341. size_t maxNumThreads = getMaxNumThreads();
  342. TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
  343. }
  344. #if USE_TASK_ARENA
  345. arena.reset();
  346. #endif
  347. }
  348. void Device::setProperty(const RTCDeviceProperty prop, ssize_t val)
  349. {
  350. /* hidden internal properties */
  351. switch ((size_t)prop)
  352. {
  353. case 1000000: debug_int0 = val; return;
  354. case 1000001: debug_int1 = val; return;
  355. case 1000002: debug_int2 = val; return;
  356. case 1000003: debug_int3 = val; return;
  357. }
  358. throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown writable property");
  359. }
  360. ssize_t Device::getProperty(const RTCDeviceProperty prop)
  361. {
  362. size_t iprop = (size_t)prop;
  363. /* get name of internal regression test */
  364. if (iprop >= 2000000 && iprop < 3000000)
  365. {
  366. RegressionTest* test = getRegressionTest(iprop-2000000);
  367. if (test) return (ssize_t) test->name.c_str();
  368. else return 0;
  369. }
  370. /* run internal regression test */
  371. if (iprop >= 3000000 && iprop < 4000000)
  372. {
  373. RegressionTest* test = getRegressionTest(iprop-3000000);
  374. if (test) return test->run();
  375. else return 0;
  376. }
  377. /* documented properties */
  378. switch (prop)
  379. {
  380. case RTC_DEVICE_PROPERTY_VERSION_MAJOR: return RTC_VERSION_MAJOR;
  381. case RTC_DEVICE_PROPERTY_VERSION_MINOR: return RTC_VERSION_MINOR;
  382. case RTC_DEVICE_PROPERTY_VERSION_PATCH: return RTC_VERSION_PATCH;
  383. case RTC_DEVICE_PROPERTY_VERSION : return RTC_VERSION;
  384. #if defined(EMBREE_TARGET_SIMD4) && defined(EMBREE_RAY_PACKETS)
  385. case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return hasISA(SSE2);
  386. #else
  387. case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return 0;
  388. #endif
  389. #if defined(EMBREE_TARGET_SIMD8) && defined(EMBREE_RAY_PACKETS)
  390. case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return hasISA(AVX);
  391. #else
  392. case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return 0;
  393. #endif
  394. #if defined(EMBREE_TARGET_SIMD16) && defined(EMBREE_RAY_PACKETS)
  395. case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return hasISA(AVX512);
  396. #else
  397. case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return 0;
  398. #endif
  399. #if defined(EMBREE_RAY_PACKETS)
  400. case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 1;
  401. #else
  402. case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 0;
  403. #endif
  404. #if defined(EMBREE_RAY_MASK)
  405. case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 1;
  406. #else
  407. case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 0;
  408. #endif
  409. #if defined(EMBREE_BACKFACE_CULLING)
  410. case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 1;
  411. #else
  412. case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 0;
  413. #endif
  414. #if defined(EMBREE_BACKFACE_CULLING_CURVES)
  415. case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 1;
  416. #else
  417. case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
  418. #endif
  419. #if defined(EMBREE_COMPACT_POLYS)
  420. case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
  421. #else
  422. case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 0;
  423. #endif
  424. #if defined(EMBREE_FILTER_FUNCTION)
  425. case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 1;
  426. #else
  427. case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 0;
  428. #endif
  429. #if defined(EMBREE_IGNORE_INVALID_RAYS)
  430. case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 1;
  431. #else
  432. case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 0;
  433. #endif
  434. #if defined(TASKING_INTERNAL)
  435. case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 0;
  436. #endif
  437. #if defined(TASKING_TBB)
  438. case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 1;
  439. #endif
  440. #if defined(TASKING_PPL)
  441. case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 2;
  442. #endif
  443. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  444. case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 1;
  445. #else
  446. case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 0;
  447. #endif
  448. #if defined(EMBREE_GEOMETRY_QUAD)
  449. case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 1;
  450. #else
  451. case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 0;
  452. #endif
  453. #if defined(EMBREE_GEOMETRY_CURVE)
  454. case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 1;
  455. #else
  456. case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 0;
  457. #endif
  458. #if defined(EMBREE_GEOMETRY_SUBDIVISION)
  459. case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 1;
  460. #else
  461. case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 0;
  462. #endif
  463. #if defined(EMBREE_GEOMETRY_USER)
  464. case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 1;
  465. #else
  466. case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 0;
  467. #endif
  468. #if defined(EMBREE_GEOMETRY_POINT)
  469. case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 1;
  470. #else
  471. case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 0;
  472. #endif
  473. #if defined(TASKING_PPL)
  474. case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
  475. #elif defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
  476. case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
  477. #else
  478. case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 1;
  479. #endif
  480. #if defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
  481. case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 1;
  482. #else
  483. case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 0;
  484. #endif
  485. default: throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown readable property"); break;
  486. };
  487. }
  488. }