Skip to content

Commit 4aa78fd

Browse files
committed
Classify toolchain include roots
1 parent a75f581 commit 4aa78fd

9 files changed

Lines changed: 196 additions & 71 deletions

File tree

cmake/common.cmake

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,10 +1259,10 @@ struct DeviceConfigCaps
12591259
if(NOT NBL_EMBED_BUILTIN_RESOURCES)
12601260
list(APPEND REQUIRED_OPTIONS
12611261
-no-nbl-builtins
1262-
-I "${NBL_ROOT_PATH}/include"
1263-
-I "${NBL_ROOT_PATH}/3rdparty/dxc/dxc/external/SPIRV-Headers/include"
1264-
-I "${NBL_ROOT_PATH}/3rdparty/boost/superproject/libs/preprocessor/include"
1265-
-I "${NBL_ROOT_PATH_BINARY}/src/nbl/device/include"
1262+
-isystem "${NBL_ROOT_PATH}/include"
1263+
-isystem "${NBL_ROOT_PATH}/3rdparty/dxc/dxc/external/SPIRV-Headers/include"
1264+
-isystem "${NBL_ROOT_PATH}/3rdparty/boost/superproject/libs/preprocessor/include"
1265+
-isystem "${NBL_ROOT_PATH_BINARY}/src/nbl/device/include"
12661266
)
12671267
endif()
12681268

@@ -1307,7 +1307,8 @@ struct DeviceConfigCaps
13071307
)
13081308

13091309
target_sources(${IMPL_TARGET} PUBLIC ${INCLUDE_FILE})
1310-
set_source_files_properties(${INCLUDE_FILE} PROPERTIES
1310+
set_source_files_properties(${INCLUDE_FILE} PROPERTIES
1311+
GENERATED TRUE
13111312
HEADER_FILE_ONLY ON
13121313
VS_TOOL_OVERRIDE None
13131314
)

include/nbl/asset/utils/IShaderCompiler.h

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted
2828
public:
2929
IShaderCompiler(core::smart_refctd_ptr<system::ISystem>&& system);
3030

31+
enum class IncludeRootOrigin : uint8_t
32+
{
33+
User,
34+
Builtin,
35+
Generated
36+
};
37+
38+
enum class HeaderClass : uint8_t
39+
{
40+
User,
41+
System
42+
};
43+
44+
struct IncludeClassification
45+
{
46+
IncludeRootOrigin origin = IncludeRootOrigin::User;
47+
HeaderClass headerClass = HeaderClass::User;
48+
};
49+
3150
class NBL_API2 IIncludeLoader : public core::IReferenceCounted
3251
{
3352
public:
@@ -36,6 +55,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted
3655
system::path absolutePath = {};
3756
std::string contents = {};
3857
core::blake3_hash_t hash = {}; // TODO: we're not yet using IFile::getPrecomputedHash(), so for builtins we can maybe use that in the future
58+
IncludeClassification classification = {};
3959
// Could be used in the future for early rejection of cache hit
4060
//nbl::system::IFileBase::time_point_t lastWriteTime = {};
4161

@@ -78,7 +98,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted
7898
public:
7999
struct SSessionCache
80100
{
81-
enum class E_LOOKUP_RESULT : uint8_t
101+
enum class LookupResult : uint8_t
82102
{
83103
Miss,
84104
Missing,
@@ -88,7 +108,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted
88108
explicit SSessionCache(const bool threadSafe = false) : threadSafe(threadSafe) {}
89109

90110
void clear();
91-
E_LOOKUP_RESULT lookup(const std::string& key, IIncludeLoader::found_t& result) const;
111+
LookupResult lookup(const std::string& key, IIncludeLoader::found_t& result) const;
92112
void store(const std::string& key, IIncludeLoader::found_t result);
93113

94114
bool threadSafe = false;
@@ -112,23 +132,41 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted
112132

113133
inline core::smart_refctd_ptr<CFileSystemIncludeLoader> getDefaultFileSystemLoader() const { return m_defaultFileSystemLoader; }
114134

115-
void addSearchPath(const std::string& searchPath, const core::smart_refctd_ptr<IIncludeLoader>& loader);
135+
void addSearchPath(const std::string& searchPath, const core::smart_refctd_ptr<IIncludeLoader>& loader, IncludeClassification classification = {});
136+
137+
void addGenerator(const core::smart_refctd_ptr<IIncludeGenerator>& generator, IncludeClassification classification = {IncludeRootOrigin::Generated,HeaderClass::System});
116138

117-
void addGenerator(const core::smart_refctd_ptr<IIncludeGenerator>& generator);
139+
bool isKnownGlobalInclude(std::string_view includeName) const;
140+
IIncludeLoader::found_t classifyFound(IIncludeLoader::found_t found) const;
118141

119142
protected:
120143
IIncludeLoader::found_t trySearchPaths(const std::string& includeName, bool needHash) const;
121144

122145
IIncludeLoader::found_t tryIncludeGenerators(const std::string& includeName) const;
146+
void registerHeaderRoot(std::string rootPath, IncludeClassification classification);
123147

124148
struct LoaderSearchPath
125149
{
126150
core::smart_refctd_ptr<IIncludeLoader> loader = nullptr;
127151
std::string searchPath = {};
152+
IncludeClassification classification = {};
153+
};
154+
155+
struct GeneratorEntry
156+
{
157+
core::smart_refctd_ptr<IIncludeGenerator> generator = nullptr;
158+
IncludeClassification classification = {IncludeRootOrigin::Generated,HeaderClass::System};
159+
};
160+
161+
struct HeaderRoot
162+
{
163+
std::string path = {};
164+
IncludeClassification classification = {};
128165
};
129166

130167
std::vector<LoaderSearchPath> m_loaders;
131-
std::vector<core::smart_refctd_ptr<IIncludeGenerator>> m_generators;
168+
std::vector<GeneratorEntry> m_generators;
169+
std::vector<HeaderRoot> m_headerRoots;
132170
core::smart_refctd_ptr<CFileSystemIncludeLoader> m_defaultFileSystemLoader;
133171
};
134172

include/nbl/system/ISystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ class NBL_API2 ISystem : public core::IReferenceCounted
144144
void unmountBuiltins();
145145
bool areBuiltinsMounted() const;
146146
size_t getMountedBuiltinArchiveCount() const;
147+
core::vector<system::path> getBuiltinMountAliases() const;
147148
inline size_t getMountedArchiveCount() const { return m_cachedArchiveFiles.getSize(); }
148149

149150
//

src/nbl/asset/utils/IShaderCompiler.cpp

Lines changed: 100 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
654671
template<typename Func>
655672
auto 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

718735
IShaderCompiler::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

817845
auto 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+
877952
core::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

Comments
 (0)