1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "state.h"
5#include "../../common/lexers/streamfilters.h"
6
7namespace embree
8{
9 MutexSys g_printMutex;
10
11 State::ErrorHandler State::g_errorHandler;
12
13 State::ErrorHandler::ErrorHandler()
14 : thread_error(createTls()) {}
15
16 State::ErrorHandler::~ErrorHandler()
17 {
18 Lock<MutexSys> lock(errors_mutex);
19 for (size_t i=0; i<thread_errors.size(); i++)
20 delete thread_errors[i];
21 destroyTls(tls: thread_error);
22 thread_errors.clear();
23 }
24
25 RTCError* State::ErrorHandler::error()
26 {
27 RTCError* stored_error = (RTCError*) getTls(tls: thread_error);
28 if (stored_error) return stored_error;
29
30 Lock<MutexSys> lock(errors_mutex);
31 stored_error = new RTCError(RTC_ERROR_NONE);
32 thread_errors.push_back(x: stored_error);
33 setTls(tls: thread_error,ptr: stored_error);
34 return stored_error;
35 }
36
37 State::State ()
38 : enabled_cpu_features(getCPUFeatures()),
39 enabled_builder_cpu_features(enabled_cpu_features),
40 frequency_level(FREQUENCY_SIMD256)
41 {
42 tri_accel = "default";
43 tri_builder = "default";
44 tri_traverser = "default";
45
46 tri_accel_mb = "default";
47 tri_builder_mb = "default";
48 tri_traverser_mb = "default";
49
50 quad_accel = "default";
51 quad_builder = "default";
52 quad_traverser = "default";
53
54 quad_accel_mb = "default";
55 quad_builder_mb = "default";
56 quad_traverser_mb = "default";
57
58 line_accel = "default";
59 line_builder = "default";
60 line_traverser = "default";
61
62 line_accel_mb = "default";
63 line_builder_mb = "default";
64 line_traverser_mb = "default";
65
66 hair_accel = "default";
67 hair_builder = "default";
68 hair_traverser = "default";
69
70 hair_accel_mb = "default";
71 hair_builder_mb = "default";
72 hair_traverser_mb = "default";
73
74 object_accel = "default";
75 object_builder = "default";
76 object_accel_min_leaf_size = 1;
77 object_accel_max_leaf_size = 1;
78
79 object_accel_mb = "default";
80 object_builder_mb = "default";
81 object_accel_mb_min_leaf_size = 1;
82 object_accel_mb_max_leaf_size = 1;
83
84 max_spatial_split_replications = 1.2f;
85 useSpatialPreSplits = false;
86
87 tessellation_cache_size = 128*1024*1024;
88
89 subdiv_accel = "default";
90 subdiv_accel_mb = "default";
91
92 grid_accel = "default";
93 grid_builder = "default";
94 grid_accel_mb = "default";
95 grid_builder_mb = "default";
96
97 instancing_open_min = 0;
98 instancing_block_size = 0;
99 instancing_open_factor = 8.0f;
100 instancing_open_max_depth = 32;
101 instancing_open_max = 50000000;
102
103 float_exceptions = false;
104 quality_flags = -1;
105 scene_flags = -1;
106 verbose = 0;
107 benchmark = 0;
108
109 numThreads = 0;
110 numUserThreads = 0;
111
112#if TASKING_INTERNAL
113 set_affinity = true;
114#else
115 set_affinity = false;
116#endif
117
118 start_threads = false;
119 enable_selockmemoryprivilege = false;
120#if defined(__LINUX__)
121 hugepages = true;
122#else
123 hugepages = false;
124#endif
125 hugepages_success = true;
126
127 alloc_main_block_size = 0;
128 alloc_num_main_slots = 0;
129 alloc_thread_block_size = 0;
130 alloc_single_thread_alloc = -1;
131
132 error_function = nullptr;
133 error_function_userptr = nullptr;
134
135 memory_monitor_function = nullptr;
136 memory_monitor_userptr = nullptr;
137 }
138
139 State::~State() {
140 }
141
142 bool State::hasISA(const int isa) {
143 return (enabled_cpu_features & isa) == isa;
144 }
145
146 bool State::checkISASupport() {
147 return (getCPUFeatures() & enabled_cpu_features) == enabled_cpu_features;
148 }
149
150 void State::verify()
151 {
152 /* verify that calculations stay in range */
153 assert(rcp(min_rcp_input)*FLT_LARGE+FLT_LARGE < 0.01f*FLT_MAX);
154
155 /* here we verify that CPP files compiled for a specific ISA only
156 * call that same or lower ISA version of non-inlined class member
157 * functions */
158#if defined(DEBUG)
159#if defined(EMBREE_TARGET_SSE2)
160 assert(sse2::getISA() <= SSE2);
161#endif
162#if defined(EMBREE_TARGET_SSE42)
163 assert(sse42::getISA() <= SSE42);
164#endif
165#if defined(EMBREE_TARGET_AVX)
166 assert(avx::getISA() <= AVX);
167#endif
168#if defined(EMBREE_TARGET_AVX2)
169 assert(avx2::getISA() <= AVX2);
170#endif
171#if defined (EMBREE_TARGET_AVX512)
172 assert(avx512::getISA() <= AVX512);
173#endif
174#endif
175 }
176
177 const char* symbols[3] = { "=", ",", "|" };
178
179 bool State::parseFile(const FileName& fileName)
180 {
181 FILE* f = fopen(filename: fileName.c_str(),modes: "r");
182 if (!f) return false;
183 Ref<Stream<int> > file = new FileStream(f,fileName);
184
185 std::vector<std::string> syms;
186 for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
187 syms.push_back(x: symbols[i]);
188
189 Ref<TokenStream> cin = new TokenStream(new LineCommentFilter(file,"#"),
190 TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
191 TokenStream::separators,syms);
192 parse(cin);
193 return true;
194 }
195
196 void State::parseString(const char* cfg)
197 {
198 if (cfg == nullptr) return;
199
200 std::vector<std::string> syms;
201 for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
202 syms.push_back(x: symbols[i]);
203
204 Ref<TokenStream> cin = new TokenStream(new StrStream(cfg),
205 TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
206 TokenStream::separators,syms);
207 parse(cin);
208 }
209
210 int string_to_cpufeatures(const std::string& isa)
211 {
212 if (isa == "sse" ) return SSE;
213 else if (isa == "sse2") return SSE2;
214 else if (isa == "sse3") return SSE3;
215 else if (isa == "ssse3") return SSSE3;
216 else if (isa == "sse41") return SSE41;
217 else if (isa == "sse4.1") return SSE41;
218 else if (isa == "sse42") return SSE42;
219 else if (isa == "sse4.2") return SSE42;
220 else if (isa == "avx") return AVX;
221 else if (isa == "avxi") return AVXI;
222 else if (isa == "avx2") return AVX2;
223 else if (isa == "avx512") return AVX512;
224 else return SSE2;
225 }
226
227 void State::parse(Ref<TokenStream> cin)
228 {
229 /* parse until end of stream */
230 while (cin->peek() != Token::Eof())
231 {
232 const Token tok = cin->get();
233
234 if (tok == Token::Id(str: "threads") && cin->trySymbol(symbol: "="))
235 numThreads = cin->get().Int();
236
237 else if (tok == Token::Id(str: "user_threads")&& cin->trySymbol(symbol: "="))
238 numUserThreads = cin->get().Int();
239
240 else if (tok == Token::Id(str: "set_affinity")&& cin->trySymbol(symbol: "="))
241 set_affinity = cin->get().Int();
242
243 else if (tok == Token::Id(str: "affinity")&& cin->trySymbol(symbol: "="))
244 set_affinity = cin->get().Int();
245
246 else if (tok == Token::Id(str: "start_threads")&& cin->trySymbol(symbol: "="))
247 start_threads = cin->get().Int();
248
249 else if (tok == Token::Id(str: "isa") && cin->trySymbol(symbol: "=")) {
250 std::string isa_str = toLowerCase(s: cin->get().Identifier());
251 enabled_cpu_features = string_to_cpufeatures(sse2: isa_str);
252 enabled_builder_cpu_features = enabled_cpu_features;
253 }
254
255 else if (tok == Token::Id(str: "max_isa") && cin->trySymbol(symbol: "=")) {
256 std::string isa_str = toLowerCase(s: cin->get().Identifier());
257 enabled_cpu_features &= string_to_cpufeatures(sse2: isa_str);
258 enabled_builder_cpu_features &= enabled_cpu_features;
259 }
260
261 else if (tok == Token::Id(str: "max_builder_isa") && cin->trySymbol(symbol: "=")) {
262 std::string isa_str = toLowerCase(s: cin->get().Identifier());
263 enabled_builder_cpu_features &= string_to_cpufeatures(sse2: isa_str);
264 }
265
266 else if (tok == Token::Id(str: "frequency_level") && cin->trySymbol(symbol: "=")) {
267 std::string freq = cin->get().Identifier();
268 if (freq == "simd128") frequency_level = FREQUENCY_SIMD128;
269 else if (freq == "simd256") frequency_level = FREQUENCY_SIMD256;
270 else if (freq == "simd512") frequency_level = FREQUENCY_SIMD512;
271 }
272
273 else if (tok == Token::Id(str: "enable_selockmemoryprivilege") && cin->trySymbol(symbol: "=")) {
274 enable_selockmemoryprivilege = cin->get().Int();
275 }
276 else if (tok == Token::Id(str: "hugepages") && cin->trySymbol(symbol: "=")) {
277 hugepages = cin->get().Int();
278 }
279
280 else if (tok == Token::Id(str: "float_exceptions") && cin->trySymbol(symbol: "="))
281 float_exceptions = cin->get().Int();
282
283 else if ((tok == Token::Id(str: "tri_accel") || tok == Token::Id(str: "accel")) && cin->trySymbol(symbol: "="))
284 tri_accel = cin->get().Identifier();
285 else if ((tok == Token::Id(str: "tri_builder") || tok == Token::Id(str: "builder")) && cin->trySymbol(symbol: "="))
286 tri_builder = cin->get().Identifier();
287 else if ((tok == Token::Id(str: "tri_traverser") || tok == Token::Id(str: "traverser")) && cin->trySymbol(symbol: "="))
288 tri_traverser = cin->get().Identifier();
289
290 else if ((tok == Token::Id(str: "tri_accel_mb") || tok == Token::Id(str: "accel_mb")) && cin->trySymbol(symbol: "="))
291 tri_accel_mb = cin->get().Identifier();
292 else if ((tok == Token::Id(str: "tri_builder_mb") || tok == Token::Id(str: "builder_mb")) && cin->trySymbol(symbol: "="))
293 tri_builder_mb = cin->get().Identifier();
294 else if ((tok == Token::Id(str: "tri_traverser_mb") || tok == Token::Id(str: "traverser_mb")) && cin->trySymbol(symbol: "="))
295 tri_traverser_mb = cin->get().Identifier();
296
297 else if ((tok == Token::Id(str: "quad_accel")) && cin->trySymbol(symbol: "="))
298 quad_accel = cin->get().Identifier();
299 else if ((tok == Token::Id(str: "quad_builder")) && cin->trySymbol(symbol: "="))
300 quad_builder = cin->get().Identifier();
301 else if ((tok == Token::Id(str: "quad_traverser")) && cin->trySymbol(symbol: "="))
302 quad_traverser = cin->get().Identifier();
303
304 else if ((tok == Token::Id(str: "quad_accel_mb")) && cin->trySymbol(symbol: "="))
305 quad_accel_mb = cin->get().Identifier();
306 else if ((tok == Token::Id(str: "quad_builder_mb")) && cin->trySymbol(symbol: "="))
307 quad_builder_mb = cin->get().Identifier();
308 else if ((tok == Token::Id(str: "quad_traverser_mb")) && cin->trySymbol(symbol: "="))
309 quad_traverser_mb = cin->get().Identifier();
310
311 else if ((tok == Token::Id(str: "line_accel")) && cin->trySymbol(symbol: "="))
312 line_accel = cin->get().Identifier();
313 else if ((tok == Token::Id(str: "line_builder")) && cin->trySymbol(symbol: "="))
314 line_builder = cin->get().Identifier();
315 else if ((tok == Token::Id(str: "line_traverser")) && cin->trySymbol(symbol: "="))
316 line_traverser = cin->get().Identifier();
317
318 else if ((tok == Token::Id(str: "line_accel_mb")) && cin->trySymbol(symbol: "="))
319 line_accel_mb = cin->get().Identifier();
320 else if ((tok == Token::Id(str: "line_builder_mb")) && cin->trySymbol(symbol: "="))
321 line_builder_mb = cin->get().Identifier();
322 else if ((tok == Token::Id(str: "line_traverser_mb")) && cin->trySymbol(symbol: "="))
323 line_traverser_mb = cin->get().Identifier();
324
325 else if (tok == Token::Id(str: "hair_accel") && cin->trySymbol(symbol: "="))
326 hair_accel = cin->get().Identifier();
327 else if (tok == Token::Id(str: "hair_builder") && cin->trySymbol(symbol: "="))
328 hair_builder = cin->get().Identifier();
329 else if (tok == Token::Id(str: "hair_traverser") && cin->trySymbol(symbol: "="))
330 hair_traverser = cin->get().Identifier();
331
332 else if (tok == Token::Id(str: "hair_accel_mb") && cin->trySymbol(symbol: "="))
333 hair_accel_mb = cin->get().Identifier();
334 else if (tok == Token::Id(str: "hair_builder_mb") && cin->trySymbol(symbol: "="))
335 hair_builder_mb = cin->get().Identifier();
336 else if (tok == Token::Id(str: "hair_traverser_mb") && cin->trySymbol(symbol: "="))
337 hair_traverser_mb = cin->get().Identifier();
338
339 else if (tok == Token::Id(str: "object_accel") && cin->trySymbol(symbol: "="))
340 object_accel = cin->get().Identifier();
341 else if (tok == Token::Id(str: "object_builder") && cin->trySymbol(symbol: "="))
342 object_builder = cin->get().Identifier();
343 else if (tok == Token::Id(str: "object_accel_min_leaf_size") && cin->trySymbol(symbol: "="))
344 object_accel_min_leaf_size = cin->get().Int();
345 else if (tok == Token::Id(str: "object_accel_max_leaf_size") && cin->trySymbol(symbol: "="))
346 object_accel_max_leaf_size = cin->get().Int();
347
348 else if (tok == Token::Id(str: "object_accel_mb") && cin->trySymbol(symbol: "="))
349 object_accel_mb = cin->get().Identifier();
350 else if (tok == Token::Id(str: "object_builder_mb") && cin->trySymbol(symbol: "="))
351 object_builder_mb = cin->get().Identifier();
352 else if (tok == Token::Id(str: "object_accel_mb_min_leaf_size") && cin->trySymbol(symbol: "="))
353 object_accel_mb_min_leaf_size = cin->get().Int();
354 else if (tok == Token::Id(str: "object_accel_mb_max_leaf_size") && cin->trySymbol(symbol: "="))
355 object_accel_mb_max_leaf_size = cin->get().Int();
356
357 else if (tok == Token::Id(str: "instancing_open_min") && cin->trySymbol(symbol: "="))
358 instancing_open_min = cin->get().Int();
359 else if (tok == Token::Id(str: "instancing_block_size") && cin->trySymbol(symbol: "=")) {
360 instancing_block_size = cin->get().Int();
361 instancing_open_factor = 0.0f;
362 }
363 else if (tok == Token::Id(str: "instancing_open_max_depth") && cin->trySymbol(symbol: "="))
364 instancing_open_max_depth = cin->get().Int();
365 else if (tok == Token::Id(str: "instancing_open_factor") && cin->trySymbol(symbol: "=")) {
366 instancing_block_size = 0;
367 instancing_open_factor = cin->get().Float();
368 }
369 else if (tok == Token::Id(str: "instancing_open_max") && cin->trySymbol(symbol: "="))
370 instancing_open_max = cin->get().Int();
371
372 else if (tok == Token::Id(str: "subdiv_accel") && cin->trySymbol(symbol: "="))
373 subdiv_accel = cin->get().Identifier();
374 else if (tok == Token::Id(str: "subdiv_accel_mb") && cin->trySymbol(symbol: "="))
375 subdiv_accel_mb = cin->get().Identifier();
376
377 else if (tok == Token::Id(str: "grid_accel") && cin->trySymbol(symbol: "="))
378 grid_accel = cin->get().Identifier();
379 else if (tok == Token::Id(str: "grid_accel_mb") && cin->trySymbol(symbol: "="))
380 grid_accel_mb = cin->get().Identifier();
381
382 else if (tok == Token::Id(str: "verbose") && cin->trySymbol(symbol: "="))
383 verbose = cin->get().Int();
384 else if (tok == Token::Id(str: "benchmark") && cin->trySymbol(symbol: "="))
385 benchmark = cin->get().Int();
386
387 else if (tok == Token::Id(str: "quality")) {
388 if (cin->trySymbol(symbol: "=")) {
389 Token flag = cin->get();
390 if (flag == Token::Id(str: "low")) quality_flags = RTC_BUILD_QUALITY_LOW;
391 else if (flag == Token::Id(str: "medium")) quality_flags = RTC_BUILD_QUALITY_MEDIUM;
392 else if (flag == Token::Id(str: "high")) quality_flags = RTC_BUILD_QUALITY_HIGH;
393 }
394 }
395
396 else if (tok == Token::Id(str: "scene_flags")) {
397 scene_flags = 0;
398 if (cin->trySymbol(symbol: "=")) {
399 do {
400 Token flag = cin->get();
401 if (flag == Token::Id(str: "dynamic") ) scene_flags |= RTC_SCENE_FLAG_DYNAMIC;
402 else if (flag == Token::Id(str: "compact")) scene_flags |= RTC_SCENE_FLAG_COMPACT;
403 else if (flag == Token::Id(str: "robust")) scene_flags |= RTC_SCENE_FLAG_ROBUST;
404 } while (cin->trySymbol(symbol: "|"));
405 }
406 }
407
408 else if (tok == Token::Id(str: "max_spatial_split_replications") && cin->trySymbol(symbol: "="))
409 max_spatial_split_replications = cin->get().Float();
410
411 else if (tok == Token::Id(str: "presplits") && cin->trySymbol(symbol: "="))
412 useSpatialPreSplits = cin->get().Int() != 0 ? true : false;
413
414 else if (tok == Token::Id(str: "tessellation_cache_size") && cin->trySymbol(symbol: "="))
415 tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
416 else if (tok == Token::Id(str: "cache_size") && cin->trySymbol(symbol: "="))
417 tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
418
419 else if (tok == Token::Id(str: "alloc_main_block_size") && cin->trySymbol(symbol: "="))
420 alloc_main_block_size = cin->get().Int();
421 else if (tok == Token::Id(str: "alloc_num_main_slots") && cin->trySymbol(symbol: "="))
422 alloc_num_main_slots = cin->get().Int();
423 else if (tok == Token::Id(str: "alloc_thread_block_size") && cin->trySymbol(symbol: "="))
424 alloc_thread_block_size = cin->get().Int();
425 else if (tok == Token::Id(str: "alloc_single_thread_alloc") && cin->trySymbol(symbol: "="))
426 alloc_single_thread_alloc = cin->get().Int();
427
428 cin->trySymbol(symbol: ","); // optional , separator
429 }
430 }
431
432 bool State::verbosity(size_t N) {
433 return N <= verbose;
434 }
435
436 void State::print()
437 {
438 std::cout << "general:" << std::endl;
439 std::cout << " build threads = " << numThreads << std::endl;
440 std::cout << " build user threads = " << numUserThreads << std::endl;
441 std::cout << " start_threads = " << start_threads << std::endl;
442 std::cout << " affinity = " << set_affinity << std::endl;
443 std::cout << " frequency_level = ";
444 switch (frequency_level) {
445 case FREQUENCY_SIMD128: std::cout << "simd128" << std::endl; break;
446 case FREQUENCY_SIMD256: std::cout << "simd256" << std::endl; break;
447 case FREQUENCY_SIMD512: std::cout << "simd512" << std::endl; break;
448 default: std::cout << "error" << std::endl; break;
449 }
450
451 std::cout << " hugepages = ";
452 if (!hugepages) std::cout << "disabled" << std::endl;
453 else if (hugepages_success) std::cout << "enabled" << std::endl;
454 else std::cout << "failed" << std::endl;
455
456 std::cout << " verbosity = " << verbose << std::endl;
457 std::cout << " cache_size = " << float(tessellation_cache_size)*1E-6 << " MB" << std::endl;
458 std::cout << " max_spatial_split_replications = " << max_spatial_split_replications << std::endl;
459
460 std::cout << "triangles:" << std::endl;
461 std::cout << " accel = " << tri_accel << std::endl;
462 std::cout << " builder = " << tri_builder << std::endl;
463 std::cout << " traverser = " << tri_traverser << std::endl;
464
465 std::cout << "motion blur triangles:" << std::endl;
466 std::cout << " accel = " << tri_accel_mb << std::endl;
467 std::cout << " builder = " << tri_builder_mb << std::endl;
468 std::cout << " traverser = " << tri_traverser_mb << std::endl;
469
470 std::cout << "quads:" << std::endl;
471 std::cout << " accel = " << quad_accel << std::endl;
472 std::cout << " builder = " << quad_builder << std::endl;
473 std::cout << " traverser = " << quad_traverser << std::endl;
474
475 std::cout << "motion blur quads:" << std::endl;
476 std::cout << " accel = " << quad_accel_mb << std::endl;
477 std::cout << " builder = " << quad_builder_mb << std::endl;
478 std::cout << " traverser = " << quad_traverser_mb << std::endl;
479
480 std::cout << "line segments:" << std::endl;
481 std::cout << " accel = " << line_accel << std::endl;
482 std::cout << " builder = " << line_builder << std::endl;
483 std::cout << " traverser = " << line_traverser << std::endl;
484
485 std::cout << "motion blur line segments:" << std::endl;
486 std::cout << " accel = " << line_accel_mb << std::endl;
487 std::cout << " builder = " << line_builder_mb << std::endl;
488 std::cout << " traverser = " << line_traverser_mb << std::endl;
489
490 std::cout << "hair:" << std::endl;
491 std::cout << " accel = " << hair_accel << std::endl;
492 std::cout << " builder = " << hair_builder << std::endl;
493 std::cout << " traverser = " << hair_traverser << std::endl;
494
495 std::cout << "motion blur hair:" << std::endl;
496 std::cout << " accel = " << hair_accel_mb << std::endl;
497 std::cout << " builder = " << hair_builder_mb << std::endl;
498 std::cout << " traverser = " << hair_traverser_mb << std::endl;
499
500 std::cout << "subdivision surfaces:" << std::endl;
501 std::cout << " accel = " << subdiv_accel << std::endl;
502
503 std::cout << "grids:" << std::endl;
504 std::cout << " accel = " << grid_accel << std::endl;
505 std::cout << " builder = " << grid_builder << std::endl;
506
507 std::cout << "motion blur grids:" << std::endl;
508 std::cout << " accel = " << grid_accel_mb << std::endl;
509 std::cout << " builder = " << grid_builder_mb << std::endl;
510
511 std::cout << "object_accel:" << std::endl;
512 std::cout << " min_leaf_size = " << object_accel_min_leaf_size << std::endl;
513 std::cout << " max_leaf_size = " << object_accel_max_leaf_size << std::endl;
514
515 std::cout << "object_accel_mb:" << std::endl;
516 std::cout << " min_leaf_size = " << object_accel_mb_min_leaf_size << std::endl;
517 std::cout << " max_leaf_size = " << object_accel_mb_max_leaf_size << std::endl;
518 }
519}
520

source code of qtquick3d/src/3rdparty/embree/kernels/common/state.cpp