@@ -651,6 +651,23 @@ std::string normalizeIncludeLookupName(const std::string& includeName)
651651 return includeName.substr (1ull );
652652}
653653
654+ std::string normalizeClassifiedRootPath (std::string value)
655+ {
656+ std::replace (value.begin (), value.end (), ' \\ ' , ' /' );
657+ while (value.size () > 1ull && value.back () == ' /' )
658+ value.pop_back ();
659+ if (value.size () > 2ull && value.front () == ' /' && value[1ull ] != ' /' )
660+ value.erase (value.begin ());
661+ return value;
662+ }
663+
664+ bool pathHasRegisteredRoot (std::string_view path, std::string_view root)
665+ {
666+ if (root.empty () || path.size () < root.size () || path.substr (0ull , root.size ()) != root)
667+ return false ;
668+ return path.size () == root.size () || path[root.size ()] == ' /' ;
669+ }
670+
654671template <typename Func>
655672auto withSessionCacheLock (IShaderCompiler::CIncludeFinder::SSessionCache* cache, Func&& func) -> decltype(func())
656673{
@@ -688,18 +705,18 @@ void IShaderCompiler::CIncludeFinder::SSessionCache::clear()
688705 });
689706}
690707
691- auto IShaderCompiler::CIncludeFinder::SSessionCache::lookup (const std::string& key, IIncludeLoader::found_t & result) const -> E_LOOKUP_RESULT
708+ auto IShaderCompiler::CIncludeFinder::SSessionCache::lookup (const std::string& key, IIncludeLoader::found_t & result) const -> LookupResult
692709{
693- return withSessionCacheLock (const_cast <SSessionCache*>(this ), [&]() -> E_LOOKUP_RESULT
710+ return withSessionCacheLock (const_cast <SSessionCache*>(this ), [&]() -> LookupResult
694711 {
695712 if (const auto foundIt = found.find (key); foundIt != found.end ())
696713 {
697714 result = foundIt->second ;
698- return E_LOOKUP_RESULT ::Found;
715+ return LookupResult ::Found;
699716 }
700717 if (missing.contains (key))
701- return E_LOOKUP_RESULT ::Missing;
702- return E_LOOKUP_RESULT ::Miss;
718+ return LookupResult ::Missing;
719+ return LookupResult ::Miss;
703720 });
704721}
705722
@@ -716,9 +733,11 @@ void IShaderCompiler::CIncludeFinder::SSessionCache::store(const std::string& ke
716733}
717734
718735IShaderCompiler::CIncludeFinder::CIncludeFinder (core::smart_refctd_ptr<system::ISystem>&& system)
719- : m_defaultFileSystemLoader(core::make_smart_refctd_ptr<CFileSystemIncludeLoader>(std::move (system)))
736+ : m_defaultFileSystemLoader(core::make_smart_refctd_ptr<CFileSystemIncludeLoader>(core::smart_refctd_ptr (system)))
720737{
721738 addSearchPath (" " , m_defaultFileSystemLoader);
739+ for (const auto & builtinRoot : system->getBuiltinMountAliases ())
740+ registerHeaderRoot (builtinRoot.generic_string (), {IncludeRootOrigin::Builtin,HeaderClass::System});
722741}
723742
724743// ! includes within <>
@@ -730,13 +749,13 @@ auto IShaderCompiler::CIncludeFinder::getIncludeStandard(const system::path& req
730749 const auto lookupName = normalizeIncludeLookupName (includeName);
731750 const auto cacheKey = makeIncludeSessionCacheKey (requestingSourceDir, lookupName, needHash, ' S' );
732751 IShaderCompiler::IIncludeLoader::found_t retVal;
733- switch (sessionCache ? sessionCache->lookup (cacheKey, retVal) : SSessionCache::E_LOOKUP_RESULT ::Miss)
752+ switch (sessionCache ? sessionCache->lookup (cacheKey, retVal) : SSessionCache::LookupResult ::Miss)
734753 {
735- case SSessionCache::E_LOOKUP_RESULT ::Found:
754+ case SSessionCache::LookupResult ::Found:
736755 return retVal;
737- case SSessionCache::E_LOOKUP_RESULT ::Missing:
756+ case SSessionCache::LookupResult ::Missing:
738757 return {};
739- case SSessionCache::E_LOOKUP_RESULT ::Miss:
758+ case SSessionCache::LookupResult ::Miss:
740759 break ;
741760 }
742761
@@ -747,6 +766,8 @@ auto IShaderCompiler::CIncludeFinder::getIncludeStandard(const system::path& req
747766 else retVal = m_defaultFileSystemLoader->getInclude (requestingSourceDir.string (), lookupName, needHash);
748767
749768
769+ retVal = classifyFound (std::move (retVal));
770+
750771 if (needHash && retVal && retVal.hash == core::blake3_hash_t {})
751772 {
752773 core::blake3_hasher hasher;
@@ -766,20 +787,22 @@ auto IShaderCompiler::CIncludeFinder::getIncludeRelative(const system::path& req
766787 const auto lookupName = normalizeIncludeLookupName (includeName);
767788 const auto cacheKey = makeIncludeSessionCacheKey (requestingSourceDir, lookupName, needHash, ' R' );
768789 IShaderCompiler::IIncludeLoader::found_t retVal;
769- switch (sessionCache ? sessionCache->lookup (cacheKey, retVal) : SSessionCache::E_LOOKUP_RESULT ::Miss)
790+ switch (sessionCache ? sessionCache->lookup (cacheKey, retVal) : SSessionCache::LookupResult ::Miss)
770791 {
771- case SSessionCache::E_LOOKUP_RESULT ::Found:
792+ case SSessionCache::LookupResult ::Found:
772793 return retVal;
773- case SSessionCache::E_LOOKUP_RESULT ::Missing:
794+ case SSessionCache::LookupResult ::Missing:
774795 return {};
775- case SSessionCache::E_LOOKUP_RESULT ::Miss:
796+ case SSessionCache::LookupResult ::Miss:
776797 break ;
777798 }
778799
779800 if (auto contents = m_defaultFileSystemLoader->getInclude (requestingSourceDir.string (), lookupName, needHash))
780801 retVal = std::move (contents);
781802 else retVal = std::move (trySearchPaths (lookupName, needHash));
782803
804+ retVal = classifyFound (std::move (retVal));
805+
783806 if (needHash && retVal && retVal.hash == core::blake3_hash_t {})
784807 {
785808 core::blake3_hasher hasher;
@@ -791,27 +814,32 @@ auto IShaderCompiler::CIncludeFinder::getIncludeRelative(const system::path& req
791814 return retVal;
792815}
793816
794- void IShaderCompiler::CIncludeFinder::addSearchPath (const std::string& searchPath, const core::smart_refctd_ptr<IIncludeLoader>& loader)
817+ void IShaderCompiler::CIncludeFinder::addSearchPath (const std::string& searchPath, const core::smart_refctd_ptr<IIncludeLoader>& loader, IncludeClassification classification )
795818{
796819 if (!loader)
797820 return ;
798- m_loaders.emplace_back (LoaderSearchPath{ loader, searchPath });
821+ auto normalizedSearchPath = normalizeClassifiedRootPath (searchPath);
822+ if (!normalizedSearchPath.empty ())
823+ registerHeaderRoot (normalizedSearchPath, classification);
824+ m_loaders.emplace_back (LoaderSearchPath{ loader, std::move (normalizedSearchPath), classification });
799825}
800826
801- void IShaderCompiler::CIncludeFinder::addGenerator (const core::smart_refctd_ptr<IIncludeGenerator>& generatorToAdd)
827+ void IShaderCompiler::CIncludeFinder::addGenerator (const core::smart_refctd_ptr<IIncludeGenerator>& generatorToAdd, IncludeClassification classification )
802828{
803829 if (!generatorToAdd)
804830 return ;
805831
832+ registerHeaderRoot (std::string (generatorToAdd->getPrefix ()), classification);
833+
806834 // this will find the place of first generator with prefix <= generatorToAdd or end
807835 auto found = std::lower_bound (m_generators.begin (), m_generators.end (), generatorToAdd->getPrefix (),
808- [](const core::smart_refctd_ptr<IIncludeGenerator> & generator, const std::string_view& value)
836+ [](const GeneratorEntry & generator, const std::string_view& value)
809837 {
810- auto element = generator->getPrefix ();
838+ auto element = generator. generator ->getPrefix ();
811839 return element.compare (value) > 0 ; // first to return false is lower_bound -> first element that is <= value
812840 });
813841
814- m_generators.insert (found, generatorToAdd);
842+ m_generators.insert (found, GeneratorEntry{ generatorToAdd, classification } );
815843}
816844
817845auto IShaderCompiler::CIncludeFinder::trySearchPaths (const std::string& includeName, bool needHash) const -> IIncludeLoader::found_t
@@ -848,23 +876,23 @@ auto IShaderCompiler::CIncludeFinder::tryIncludeGenerators(const std::string& in
848876 while (!path.empty () && path.root_name ().empty () && end != m_generators.end ())
849877 {
850878 auto begin = std::lower_bound (end, m_generators.end (), path.string (),
851- [&standardizePrefix](const core::smart_refctd_ptr<IIncludeGenerator> & generator, const std::string& value)
879+ [&standardizePrefix](const GeneratorEntry & generator, const std::string& value)
852880 {
853- const auto element = standardizePrefix (generator->getPrefix ());
881+ const auto element = standardizePrefix (generator. generator ->getPrefix ());
854882 return element.compare (value) > 0 ; // first to return false is lower_bound -> first element that is <= value
855883 });
856884
857885 // search from new beginning to real end
858886 end = std::upper_bound (begin, m_generators.end (), path.string (),
859- [&standardizePrefix](const std::string& value, const core::smart_refctd_ptr<IIncludeGenerator> & generator)
887+ [&standardizePrefix](const std::string& value, const GeneratorEntry & generator)
860888 {
861- const auto element = standardizePrefix (generator->getPrefix ());
889+ const auto element = standardizePrefix (generator. generator ->getPrefix ());
862890 return value.compare (element) > 0 ; // first to return true is upper_bound -> first element that is < value
863891 });
864892
865893 for (auto generatorIt = begin; generatorIt != end; generatorIt++)
866894 {
867- if (auto contents = (* generatorIt) ->getInclude (includeName))
895+ if (auto contents = generatorIt-> generator ->getInclude (includeName))
868896 return contents;
869897 }
870898
@@ -874,6 +902,53 @@ auto IShaderCompiler::CIncludeFinder::tryIncludeGenerators(const std::string& in
874902 return {};
875903}
876904
905+ bool IShaderCompiler::CIncludeFinder::isKnownGlobalInclude (std::string_view includeName) const
906+ {
907+ const auto normalizedIncludeName = normalizeClassifiedRootPath (std::string (includeName));
908+ return std::any_of (m_headerRoots.begin (), m_headerRoots.end (), [&](const HeaderRoot& root)
909+ {
910+ return root.classification .headerClass == HeaderClass::System && pathHasRegisteredRoot (normalizedIncludeName, root.path );
911+ });
912+ }
913+
914+ auto IShaderCompiler::CIncludeFinder::classifyFound (IIncludeLoader::found_t found) const -> IIncludeLoader::found_t
915+ {
916+ if (!found)
917+ return found;
918+
919+ const auto normalizedPath = normalizeClassifiedRootPath (found.absolutePath .generic_string ());
920+ size_t bestMatchLength = 0ull ;
921+ for (const auto & root : m_headerRoots)
922+ {
923+ if (root.path .size () <= bestMatchLength)
924+ continue ;
925+ if (!pathHasRegisteredRoot (normalizedPath, root.path ))
926+ continue ;
927+ found.classification = root.classification ;
928+ bestMatchLength = root.path .size ();
929+ }
930+ return found;
931+ }
932+
933+ void IShaderCompiler::CIncludeFinder::registerHeaderRoot (std::string rootPath, IncludeClassification classification)
934+ {
935+ rootPath = normalizeClassifiedRootPath (std::move (rootPath));
936+ if (rootPath.empty ())
937+ return ;
938+
939+ const auto found = std::find_if (m_headerRoots.begin (), m_headerRoots.end (), [&](const HeaderRoot& entry)
940+ {
941+ return entry.path == rootPath;
942+ });
943+ if (found != m_headerRoots.end ())
944+ {
945+ found->classification = classification;
946+ return ;
947+ }
948+
949+ m_headerRoots.push_back ({ std::move (rootPath),classification });
950+ }
951+
877952core::smart_refctd_ptr<asset::IShader> IShaderCompiler::CCache::find (const SEntry& mainFile, const IShaderCompiler::CIncludeFinder* finder) const
878953{
879954 const auto found = find_impl (mainFile, finder);
0 commit comments