// ======================================================================== // // Copyright 2009-2017 Intel Corporation // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // // ======================================================================== // #include "state.h" #include "../common/lexers/streamfilters.h" namespace embree { State::ErrorHandler State::g_errorHandler; State::ErrorHandler::ErrorHandler() : thread_error(createTls()) {} State::ErrorHandler::~ErrorHandler() { Lock lock(errors_mutex); for (size_t i=0; i lock(errors_mutex); stored_error = new RTCError(RTC_NO_ERROR); thread_errors.push_back(stored_error); setTls(thread_error,stored_error); return stored_error; } State::State (bool singledevice) : enabled_cpu_features(getCPUFeatures()), enabled_builder_cpu_features(enabled_cpu_features) { tri_accel = "default"; tri_builder = "default"; tri_traverser = "default"; tri_accel_mb = "default"; tri_builder_mb = "default"; tri_traverser_mb = "default"; quad_accel = "default"; quad_builder = "default"; quad_traverser = "default"; quad_accel_mb = "default"; quad_builder_mb = "default"; quad_traverser_mb = "default"; line_accel = "default"; line_builder = "default"; line_traverser = "default"; line_accel_mb = "default"; line_builder_mb = "default"; line_traverser_mb = "default"; hair_accel = "default"; hair_builder = "default"; hair_traverser = "default"; hair_accel_mb = "default"; hair_builder_mb = "default"; hair_traverser_mb = "default"; object_accel = "default"; object_builder = "default"; object_accel_min_leaf_size = 1; object_accel_max_leaf_size = 1; object_accel_mb_min_leaf_size = 1; object_accel_mb_max_leaf_size = 1; max_spatial_split_replications = 2.0f; tessellation_cache_size = 128*1024*1024; /* large default cache size only for old mode single device mode */ #if defined(__X86_64__) if (singledevice) tessellation_cache_size = 1024*1024*1024; #else if (singledevice) tessellation_cache_size = 128*1024*1024; #endif subdiv_accel = "default"; subdiv_accel_mb = "default"; instancing_open_min = 0; instancing_block_size = 0; instancing_open_factor = 8.0f; instancing_open_max_depth = 32; instancing_open_max = 50000000; ignore_config_files = false; float_exceptions = false; scene_flags = -1; verbose = 0; benchmark = 0; numThreads = 0; #if TASKING_INTERNAL set_affinity = true; #else set_affinity = false; #endif /* per default enable affinity on KNL */ if (hasISA(AVX512KNL)) set_affinity = true; start_threads = false; error_function = nullptr; error_function2 = nullptr; error_function_userptr = nullptr; memory_monitor_function = nullptr; memory_monitor_function2 = nullptr; memory_monitor_userptr = nullptr; } State::~State() { } bool State::hasISA(const int isa) { return (enabled_cpu_features & isa) == isa; } void State::verify() { /* CPU has to support at least SSE2 */ if (!hasISA(SSE2)) throw_RTCError(RTC_UNSUPPORTED_CPU,"CPU does not support SSE2"); /* verify that calculations stay in range */ assert(rcp(min_rcp_input)*FLT_LARGE+FLT_LARGE < 0.01f*FLT_MAX); /* here we verify that CPP files compiled for a specific ISA only * call that same or lower ISA version of non-inlined class member * functions */ #if defined(DEBUG) assert(isa::getISA() == ISA); #if defined(__TARGET_SSE42__) assert(sse42::getISA() <= SSE42); #endif #if defined(__TARGET_AVX__) assert(avx::getISA() <= AVX); #endif #if defined(__TARGET_AVX2__) assert(avx2::getISA() <= AVX2); #endif #if defined (__TARGET_AVX512KNL__) assert(avx512knl::getISA() <= AVX512KNL); #endif #if defined (__TARGET_AVX512SKX__) assert(avx512skx::getISA() <= AVX512SKX); #endif #endif } const char* symbols[3] = { "=", ",", "|" }; bool State::parseFile(const FileName& fileName) { FILE* f = fopen(fileName.c_str(),"r"); if (!f) return false; Ref > file = new FileStream(f,fileName); std::vector syms; for (size_t i=0; i cin = new TokenStream(new LineCommentFilter(file,"#"), TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.", TokenStream::separators,syms); parse(cin); return true; } void State::parseString(const char* cfg) { if (cfg == nullptr) return; std::vector syms; for (size_t i=0; i cin = new TokenStream(new StrStream(cfg), TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.", TokenStream::separators,syms); parse(cin); } int string_to_cpufeatures(const std::string& isa) { if (isa == "sse" ) return SSE; else if (isa == "sse2") return SSE2; else if (isa == "sse3") return SSE3; else if (isa == "ssse3") return SSSE3; else if (isa == "sse41") return SSE41; else if (isa == "sse4.1") return SSE41; else if (isa == "sse42") return SSE42; else if (isa == "sse4.2") return SSE42; else if (isa == "avx") return AVX; else if (isa == "avxi") return AVXI; else if (isa == "avx2") return AVX2; else if (isa == "avx512knl") return AVX512KNL; else if (isa == "avx512skx") return AVX512SKX; else return SSE2; } void State::parse(Ref cin) { /* parse until end of stream */ while (cin->peek() != Token::Eof()) { const Token tok = cin->get(); if (tok == Token::Id("threads") && cin->trySymbol("=")) numThreads = cin->get().Int(); else if (tok == Token::Id("set_affinity")&& cin->trySymbol("=")) set_affinity = cin->get().Int(); else if (tok == Token::Id("affinity")&& cin->trySymbol("=")) set_affinity = cin->get().Int(); else if (tok == Token::Id("start_threads")&& cin->trySymbol("=")) start_threads = cin->get().Int(); else if (tok == Token::Id("isa") && cin->trySymbol("=")) { std::string isa = toLowerCase(cin->get().Identifier()); enabled_cpu_features = string_to_cpufeatures(isa); enabled_builder_cpu_features = enabled_cpu_features; } else if (tok == Token::Id("max_isa") && cin->trySymbol("=")) { std::string isa = toLowerCase(cin->get().Identifier()); enabled_cpu_features &= string_to_cpufeatures(isa); enabled_builder_cpu_features &= enabled_cpu_features; } else if (tok == Token::Id("max_builder_isa") && cin->trySymbol("=")) { std::string isa = toLowerCase(cin->get().Identifier()); enabled_builder_cpu_features &= string_to_cpufeatures(isa); } else if (tok == Token::Id("ignore_config_files") && cin->trySymbol("=")) ignore_config_files = cin->get().Int(); else if (tok == Token::Id("float_exceptions") && cin->trySymbol("=")) float_exceptions = cin->get().Int(); else if ((tok == Token::Id("tri_accel") || tok == Token::Id("accel")) && cin->trySymbol("=")) tri_accel = cin->get().Identifier(); else if ((tok == Token::Id("tri_builder") || tok == Token::Id("builder")) && cin->trySymbol("=")) tri_builder = cin->get().Identifier(); else if ((tok == Token::Id("tri_traverser") || tok == Token::Id("traverser")) && cin->trySymbol("=")) tri_traverser = cin->get().Identifier(); else if ((tok == Token::Id("tri_accel_mb") || tok == Token::Id("accel_mb")) && cin->trySymbol("=")) tri_accel_mb = cin->get().Identifier(); else if ((tok == Token::Id("tri_builder_mb") || tok == Token::Id("builder_mb")) && cin->trySymbol("=")) tri_builder_mb = cin->get().Identifier(); else if ((tok == Token::Id("tri_traverser_mb") || tok == Token::Id("traverser_mb")) && cin->trySymbol("=")) tri_traverser_mb = cin->get().Identifier(); else if ((tok == Token::Id("quad_accel")) && cin->trySymbol("=")) quad_accel = cin->get().Identifier(); else if ((tok == Token::Id("quad_builder")) && cin->trySymbol("=")) quad_builder = cin->get().Identifier(); else if ((tok == Token::Id("quad_traverser")) && cin->trySymbol("=")) quad_traverser = cin->get().Identifier(); else if ((tok == Token::Id("quad_accel_mb")) && cin->trySymbol("=")) quad_accel_mb = cin->get().Identifier(); else if ((tok == Token::Id("quad_builder_mb")) && cin->trySymbol("=")) quad_builder_mb = cin->get().Identifier(); else if ((tok == Token::Id("quad_traverser_mb")) && cin->trySymbol("=")) quad_traverser_mb = cin->get().Identifier(); else if ((tok == Token::Id("line_accel")) && cin->trySymbol("=")) line_accel = cin->get().Identifier(); else if ((tok == Token::Id("line_builder")) && cin->trySymbol("=")) line_builder = cin->get().Identifier(); else if ((tok == Token::Id("line_traverser")) && cin->trySymbol("=")) line_traverser = cin->get().Identifier(); else if ((tok == Token::Id("line_accel_mb")) && cin->trySymbol("=")) line_accel_mb = cin->get().Identifier(); else if ((tok == Token::Id("line_builder_mb")) && cin->trySymbol("=")) line_builder_mb = cin->get().Identifier(); else if ((tok == Token::Id("line_traverser_mb")) && cin->trySymbol("=")) line_traverser_mb = cin->get().Identifier(); else if (tok == Token::Id("hair_accel") && cin->trySymbol("=")) hair_accel = cin->get().Identifier(); else if (tok == Token::Id("hair_builder") && cin->trySymbol("=")) hair_builder = cin->get().Identifier(); else if (tok == Token::Id("hair_traverser") && cin->trySymbol("=")) hair_traverser = cin->get().Identifier(); else if (tok == Token::Id("hair_accel_mb") && cin->trySymbol("=")) hair_accel_mb = cin->get().Identifier(); else if (tok == Token::Id("hair_builder_mb") && cin->trySymbol("=")) hair_builder_mb = cin->get().Identifier(); else if (tok == Token::Id("hair_traverser_mb") && cin->trySymbol("=")) hair_traverser_mb = cin->get().Identifier(); else if (tok == Token::Id("object_accel") && cin->trySymbol("=")) object_accel = cin->get().Identifier(); else if (tok == Token::Id("object_builder") && cin->trySymbol("=")) object_builder = cin->get().Identifier(); else if (tok == Token::Id("object_accel_min_leaf_size") && cin->trySymbol("=")) object_accel_min_leaf_size = cin->get().Int(); else if (tok == Token::Id("object_accel_max_leaf_size") && cin->trySymbol("=")) object_accel_max_leaf_size = cin->get().Int(); else if (tok == Token::Id("object_accel_mb_min_leaf_size") && cin->trySymbol("=")) object_accel_mb_min_leaf_size = cin->get().Int(); else if (tok == Token::Id("object_accel_mb_max_leaf_size") && cin->trySymbol("=")) object_accel_mb_max_leaf_size = cin->get().Int(); else if (tok == Token::Id("instancing_open_min") && cin->trySymbol("=")) instancing_open_min = cin->get().Int(); else if (tok == Token::Id("instancing_block_size") && cin->trySymbol("=")) { instancing_block_size = cin->get().Int(); instancing_open_factor = 0.0f; } else if (tok == Token::Id("instancing_open_max_depth") && cin->trySymbol("=")) instancing_open_max_depth = cin->get().Int(); else if (tok == Token::Id("instancing_open_factor") && cin->trySymbol("=")) { instancing_block_size = 0; instancing_open_factor = cin->get().Float(); } else if (tok == Token::Id("instancing_open_max") && cin->trySymbol("=")) instancing_open_max = cin->get().Int(); else if (tok == Token::Id("subdiv_accel") && cin->trySymbol("=")) subdiv_accel = cin->get().Identifier(); else if (tok == Token::Id("subdiv_accel_mb") && cin->trySymbol("=")) subdiv_accel_mb = cin->get().Identifier(); else if (tok == Token::Id("verbose") && cin->trySymbol("=")) verbose = cin->get().Int(); else if (tok == Token::Id("benchmark") && cin->trySymbol("=")) benchmark = cin->get().Int(); else if (tok == Token::Id("flags")) { scene_flags = 0; if (cin->trySymbol("=")) { do { Token flag = cin->get(); if (flag == Token::Id("static") ) scene_flags |= RTC_SCENE_STATIC; else if (flag == Token::Id("dynamic")) scene_flags |= RTC_SCENE_DYNAMIC; else if (flag == Token::Id("compact")) scene_flags |= RTC_SCENE_COMPACT; else if (flag == Token::Id("coherent")) scene_flags |= RTC_SCENE_COHERENT; else if (flag == Token::Id("incoherent")) scene_flags |= RTC_SCENE_INCOHERENT; else if (flag == Token::Id("high_quality")) scene_flags |= RTC_SCENE_HIGH_QUALITY; else if (flag == Token::Id("robust")) scene_flags |= RTC_SCENE_ROBUST; } while (cin->trySymbol("|")); } } else if (tok == Token::Id("max_spatial_split_replications") && cin->trySymbol("=")) max_spatial_split_replications = cin->get().Float(); else if (tok == Token::Id("tessellation_cache_size") && cin->trySymbol("=")) tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f); else if (tok == Token::Id("cache_size") && cin->trySymbol("=")) tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f); cin->trySymbol(","); // optional , separator } } bool State::verbosity(size_t N) { return N <= verbose; } void State::print() { std::cout << "general:" << std::endl; std::cout << " build threads = " << numThreads << std::endl; std::cout << " start_threads = " << start_threads << std::endl; std::cout << " affinity = " << set_affinity << std::endl; std::cout << " verbosity = " << verbose << std::endl; std::cout << " cache_size = " << float(tessellation_cache_size)*1E-6 << " MB" << std::endl; std::cout << " max_spatial_split_replications = " << max_spatial_split_replications << std::endl; std::cout << "triangles:" << std::endl; std::cout << " accel = " << tri_accel << std::endl; std::cout << " builder = " << tri_builder << std::endl; std::cout << " traverser = " << tri_traverser << std::endl; std::cout << "motion blur triangles:" << std::endl; std::cout << " accel = " << tri_accel_mb << std::endl; std::cout << " builder = " << tri_builder_mb << std::endl; std::cout << " traverser = " << tri_traverser_mb << std::endl; std::cout << "quads:" << std::endl; std::cout << " accel = " << quad_accel << std::endl; std::cout << " builder = " << quad_builder << std::endl; std::cout << " traverser = " << quad_traverser << std::endl; std::cout << "motion blur quads:" << std::endl; std::cout << " accel = " << quad_accel_mb << std::endl; std::cout << " builder = " << quad_builder_mb << std::endl; std::cout << " traverser = " << quad_traverser_mb << std::endl; std::cout << "line segments:" << std::endl; std::cout << " accel = " << line_accel << std::endl; std::cout << " builder = " << line_builder << std::endl; std::cout << " traverser = " << line_traverser << std::endl; std::cout << "motion blur line segments:" << std::endl; std::cout << " accel = " << line_accel_mb << std::endl; std::cout << " builder = " << line_builder_mb << std::endl; std::cout << " traverser = " << line_traverser_mb << std::endl; std::cout << "hair:" << std::endl; std::cout << " accel = " << hair_accel << std::endl; std::cout << " builder = " << hair_builder << std::endl; std::cout << " traverser = " << hair_traverser << std::endl; std::cout << "motion blur hair:" << std::endl; std::cout << " accel = " << hair_accel_mb << std::endl; std::cout << " builder = " << hair_builder_mb << std::endl; std::cout << " traverser = " << hair_traverser_mb << std::endl; std::cout << "subdivision surfaces:" << std::endl; std::cout << " accel = " << subdiv_accel << std::endl; std::cout << "object_accel:" << std::endl; std::cout << " min_leaf_size = " << object_accel_min_leaf_size << std::endl; std::cout << " max_leaf_size = " << object_accel_max_leaf_size << std::endl; std::cout << "object_accel_mb:" << std::endl; std::cout << " min_leaf_size = " << object_accel_mb_min_leaf_size << std::endl; std::cout << " max_leaf_size = " << object_accel_mb_max_leaf_size << std::endl; } }