diff options
| author | skallweitNV <64953474+skallweitNV@users.noreply.github.com> | 2022-12-12 19:25:48 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-12 10:25:48 -0800 |
| commit | c2dc1a86ed2f5e160749fe9f99b70db6c3e4d7a6 (patch) | |
| tree | ea65b9635d892917a2420688a27c38537c4758be /source | |
| parent | 8d359fc6133fa49d2d3b7f8bb4b37916e719c344 (diff) | |
Refactor shader cache (#2558)
* Fix a bug in Path::find
* Fix code formatting
* Fix LockFile and add LockFileGuard
* Add PersistentCache and unit test
* Replace file path dependency list with source file dependency list
* Add note on ordering in Module/FileDependencyList
* Remove old shader cache code
* Refactor shader cache implementation
* Temporarily skip unit tests reading/writing files
* Fix warning
* Reenable lock file test
* Rename shader cache tests and disable crashing test
* Testing
* Stop using Path::getCanonical
* Fix persistent cache lock and test
* Fix threading issues
* Move adding file dependency hashes to getEntryPointHash()
* Fix handling of #include files
* Allow specifying additional search paths for gfx testing device
* Work on shader cache tests
* Update project files
* Revive shader cache graphics tests
* Split graphics pipeline test
* Fix compilation
Diffstat (limited to 'source')
| -rw-r--r-- | source/core/slang-crypto.cpp | 14 | ||||
| -rw-r--r-- | source/core/slang-io.cpp | 2 | ||||
| -rw-r--r-- | source/core/slang-io.h | 27 | ||||
| -rw-r--r-- | source/core/slang-persistent-cache.cpp | 289 | ||||
| -rw-r--r-- | source/core/slang-persistent-cache.h | 91 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 29 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 158 | ||||
| -rw-r--r-- | source/slang/slang-preprocessor.cpp | 23 | ||||
| -rw-r--r-- | source/slang/slang-preprocessor.h | 2 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 229 |
10 files changed, 555 insertions, 309 deletions
diff --git a/source/core/slang-crypto.cpp b/source/core/slang-crypto.cpp index ece7b01e9..dfe246c7c 100644 --- a/source/core/slang-crypto.cpp +++ b/source/core/slang-crypto.cpp @@ -82,15 +82,19 @@ void MD5::update(const void* data, SlangInt size) saved_lo = m_lo; if ((m_lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + { m_hi++; + } m_hi += (uint32_t)size >> 29; used = saved_lo & 0x3f; - if (used) { + if (used) + { available = 64 - used; - if (size < available) { + if (size < available) + { ::memcpy(&m_buffer[used], data, size); return; } @@ -101,7 +105,8 @@ void MD5::update(const void* data, SlangInt size) processBlock(m_buffer, 64); } - if (size >= 64) { + if (size >= 64) + { data = processBlock(data, size & ~(SlangInt)0x3f); size &= 0x3f; } @@ -119,7 +124,8 @@ MD5::Digest MD5::finalize() available = 64 - used; - if (available < 8) { + if (available < 8) + { ::memset(&m_buffer[used], 0, available); processBlock(m_buffer, 64); used = 0; diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index d8ef48ee3..f2be44f4f 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -682,7 +682,7 @@ namespace Slang WIN32_FIND_DATAW fileData; HANDLE findHandle = FindFirstFileW(searchPath.toWString(), &fileData); - if (!findHandle) + if (findHandle == INVALID_HANDLE_VALUE) { return SLANG_E_NOT_FOUND; } diff --git a/source/core/slang-io.h b/source/core/slang-io.h index fc5cbfa9d..e766359ff 100644 --- a/source/core/slang-io.h +++ b/source/core/slang-io.h @@ -266,9 +266,9 @@ namespace Slang private: LockFile(const LockFile&) = delete; - LockFile(LockFile&) = delete; + LockFile(LockFile&&) = delete; LockFile& operator=(const LockFile&) = delete; - LockFile& operator=(const LockFile&&) = delete; + LockFile& operator=(LockFile&&) = delete; #if SLANG_WINDOWS_FAMILY void* m_fileHandle; @@ -278,6 +278,29 @@ namespace Slang bool m_isOpen; }; + class LockFileGuard + { + public: + LockFileGuard(LockFile& lockFile, LockFile::LockType lockType = LockFile::LockType::Exclusive) + : m_lockFile(lockFile) + { + m_lockFile.lock(lockType); + } + + ~LockFileGuard() + { + m_lockFile.unlock(); + } + + private: + LockFileGuard(const LockFileGuard&) = delete; + LockFileGuard(LockFileGuard&&) = delete; + LockFileGuard& operator=(const LockFileGuard&) = delete; + LockFileGuard& operator=(LockFileGuard&&) = delete; + + LockFile& m_lockFile; + }; + } #endif diff --git a/source/core/slang-persistent-cache.cpp b/source/core/slang-persistent-cache.cpp new file mode 100644 index 000000000..2b4113e16 --- /dev/null +++ b/source/core/slang-persistent-cache.cpp @@ -0,0 +1,289 @@ +#include "slang-persistent-cache.h" + +#include "../core/slang-io.h" +#include "../core/slang-stream.h" +#include "../core/slang-string-util.h" +#include "../core/slang-blob.h" + +namespace Slang +{ + +PersistentCache::PersistentCache(const Desc& desc) +{ + m_cacheDirectory = Path::simplify(desc.directory); + Path::createDirectory(m_cacheDirectory); + + m_lockFileName = Path::simplify(m_cacheDirectory + "/lock"); + m_indexFileName = Path::simplify(m_cacheDirectory + "/index"); + + m_lockFile.open(m_lockFileName); + + m_maxEntryCount = desc.maxEntryCount; + + resetStats(); + + initialize(); +} + +PersistentCache::~PersistentCache() +{ +} + +SlangResult PersistentCache::clear() +{ + if (!m_lockFile.isOpen()) + { + return SLANG_E_CANNOT_OPEN; + } + + // Acquire the exclusive lock. + std::lock_guard<std::mutex> mutexLock(m_mutex); + LockFileGuard fileLock(m_lockFile); + + struct Visitor : Path::Visitor + { + const String& directory; + const String& lockFileName; + + Visitor(const String& directory, const String& lockFileName) + : directory(directory) + , lockFileName(lockFileName) + {} + + void accept(Path::Type type, const UnownedStringSlice& fileName) SLANG_OVERRIDE + { + String fullPath = Path::simplify(directory + "/" + fileName);; + if (type == Path::Type::File && lockFileName != fullPath) + { + Path::remove(fullPath); + } + } + }; + + Visitor visitor(m_cacheDirectory, m_lockFileName); + Path::find(m_cacheDirectory, nullptr, &visitor); + + m_stats.entryCount = 0; + + return SLANG_OK; +} + +void PersistentCache::resetStats() +{ + m_stats.entryCount = 0; + m_stats.hitCount = 0; + m_stats.missCount = 0; +} + +SlangResult PersistentCache::readEntry(const Key& key, ISlangBlob** outData) +{ + // Be pessimistic and assume we have a cache miss. + ++m_stats.missCount; + + if (!m_lockFile.isOpen()) + { + return SLANG_E_CANNOT_OPEN; + } + + // Acquire the exclusive lock. + std::lock_guard<std::mutex> mutexLock(m_mutex); + LockFileGuard fileLock(m_lockFile); + + // Return if index does not exist. + if (!File::exists(m_indexFileName)) + { + return SLANG_E_NOT_FOUND; + } + + // Read the cache index. + CacheIndex cacheIndex; + SLANG_RETURN_ON_FAIL(readIndex(m_indexFileName, cacheIndex)); + + // Increase the age of all entries in the cache. + for (auto& entry : cacheIndex) + { + ++entry.age; + } + + // Find the entry. + Index entryIndex = cacheIndex.findFirstIndex([&key] (const CacheEntry& entry) { return entry.key == key; }); + if (entryIndex == -1) + { + return SLANG_E_NOT_FOUND; + } + + // Read the entry. + String entryFileName = getEntryFileName(key); + ScopedAllocation data; + SlangResult result = File::readAllBytes(entryFileName, data); + if (result == SLANG_OK) + { + --m_stats.missCount; + ++m_stats.hitCount; + cacheIndex[entryIndex].age = 0; + auto blob = RawBlob::moveCreate(data); + *outData = blob.detach(); + } + else + { + cacheIndex.removeAt(entryIndex); + } + + // Write the cache index. + SLANG_RETURN_ON_FAIL(writeIndex(m_indexFileName, cacheIndex)); + m_stats.entryCount = (Count)cacheIndex.getCount(); + + return result; +} + +SlangResult PersistentCache::writeEntry(const Key& key, ISlangBlob* data) +{ + SLANG_ASSERT(data); + + if (!m_lockFile.isOpen()) + { + return SLANG_E_CANNOT_OPEN; + } + + // Acquire the exclusive lock. + std::lock_guard<std::mutex> mutexLock(m_mutex); + LockFileGuard fileLock(m_lockFile); + + // Read the cache index. + // We ignore any errors when reading the index and just write a new one. + CacheIndex cacheIndex; + readIndex(m_indexFileName, cacheIndex); + + // Increase the age of all entries in the cache and get the index of + // the oldest entry. + Index oldestEntryIndex = -1; + uint32_t oldestEntryAge = 0; + for (Index entryIndex = 0; entryIndex < cacheIndex.getCount(); ++entryIndex) + { + auto& entry = cacheIndex[entryIndex]; + ++entry.age; + if (entry.age > oldestEntryAge) + { + oldestEntryIndex = entryIndex; + oldestEntryAge = entry.age; + } + } + + // Write the cache entry. + String entryFileName = getEntryFileName(key); + SLANG_RETURN_ON_FAIL(File::writeAllBytes(entryFileName, data->getBufferPointer(), data->getBufferSize())); + + // Update the index. + if (m_maxEntryCount > 0 && cacheIndex.getCount() >= m_maxEntryCount) + { + // Replace oldest entry. + SLANG_ASSERT(oldestEntryIndex >= 0); + File::remove(getEntryFileName(cacheIndex[oldestEntryIndex].key)); + cacheIndex[oldestEntryIndex] = CacheEntry{ key, 0 }; + } + else + { + // Add new entry. + cacheIndex.add(CacheEntry{ key, 0 }); + } + + // Write the cache index. + SlangResult result = writeIndex(m_indexFileName, cacheIndex); + if (result == SLANG_OK) + { + m_stats.entryCount = (Count)cacheIndex.getCount(); + } + else + { + // If writing the index failed, remove the entry file to avoid growing the cache. + Path::remove(entryFileName); + } + + return result; +} + +SlangResult PersistentCache::initialize() +{ + if (!m_lockFile.isOpen()) + { + return SLANG_E_CANNOT_OPEN; + } + + // Acquire the exclusive lock. + std::lock_guard<std::mutex> mutexLock(m_mutex); + LockFileGuard fileLock(m_lockFile); + + CacheIndex cacheIndex; + if (SLANG_SUCCEEDED(readIndex(m_indexFileName, cacheIndex))) + { + m_stats.entryCount = (Count)cacheIndex.getCount(); + } + + return SLANG_OK; +} + +String PersistentCache::getEntryFileName(const Key& key) +{ + StringBuilder str; + str << m_cacheDirectory << "/" << key.toString(); + return str; +} + +struct CacheIndexHeader +{ + char magic[4]; + uint32_t version; + uint32_t count; + uint32_t reserved; +}; + +static const char* kMagic = "SLS$"; +static const uint32_t kVersion = 1; + +SlangResult PersistentCache::readIndex(const String& fileName, CacheIndex& outIndex) +{ + FileStream fs; + SLANG_RETURN_ON_FAIL(fs.init(fileName, FileMode::Open)); + + // Get file size. + SLANG_RETURN_ON_FAIL(fs.seek(SeekOrigin::End, 0)); + size_t fileSize = (size_t)fs.getPosition(); + SLANG_RETURN_ON_FAIL(fs.seek(SeekOrigin::Start, 0)); + + CacheIndexHeader header; + SLANG_RETURN_ON_FAIL(fs.readExactly(&header, sizeof(header))); + if (::memcmp(header.magic, kMagic, 4) != 0 || header.version != kVersion) + { + return SLANG_E_INTERNAL_FAIL; + } + + // Return if payload does not have the right size. + if (header.count * sizeof(CacheEntry) != fileSize - sizeof(header)) + { + return SLANG_E_INTERNAL_FAIL; + } + + outIndex.setCount(header.count); + SLANG_RETURN_ON_FAIL(fs.readExactly(outIndex.getBuffer(), header.count * sizeof(CacheEntry))); + + return SLANG_OK; +} + +SlangResult PersistentCache::writeIndex(const String& fileName, const CacheIndex& index) +{ + FileStream fs; + SLANG_RETURN_ON_FAIL(fs.init(fileName, FileMode::Create)); + + CacheIndexHeader header; + ::memcpy(header.magic, kMagic, 4); + header.version = kVersion; + header.count = (uint32_t)index.getCount(); + header.reserved = 0; + SLANG_RETURN_ON_FAIL(fs.write(&header, sizeof(header))); + + SLANG_RETURN_ON_FAIL(fs.write(index.getBuffer(), index.getCount() * sizeof(CacheEntry))); + + return SLANG_OK; +} + +} diff --git a/source/core/slang-persistent-cache.h b/source/core/slang-persistent-cache.h new file mode 100644 index 000000000..db5ef0a2e --- /dev/null +++ b/source/core/slang-persistent-cache.h @@ -0,0 +1,91 @@ +#pragma once +#include "../../slang.h" +#include "../core/slang-crypto.h" +#include "../core/slang-io.h" +#include "../core/slang-string.h" + +#include <mutex> + +namespace Slang +{ + +/// Implements a simple persistent cache on the filesystem for storing key/value pairs. +/// Keys are SHA1 hashes and values are arbitrary blobs of data. +/// The cache is save for concurrent access from multiple threads/processes by using +/// a lock file within the cache directory. Furthermore, the cache implements a LRU +/// eviction policy. +class PersistentCache : public RefObject +{ +public: + struct Desc + { + // The root directory for the cache. + const char* directory = nullptr; + // The maximum number of entries stored in the cache. By default, there is no limit. + Count maxEntryCount = 0; + }; + + struct Stats + { + // Number of cache hits since last resetting the stats. + Count hitCount; + // Number of cache misses since last resetting the stats. + Count missCount; + // Current number of entries in the cache. + Count entryCount; + }; + + using Key = SHA1::Digest; + + PersistentCache(const Desc& desc); + ~PersistentCache(); + + /// Clear the contents of the cache by removing the cache index and all entry files. + SlangResult clear(); + + const Stats& getStats() const { return m_stats; } + void resetStats(); + + /// Read an entry from the cache. + /// Returns SLANG_OK if successful, SLANG_E_NOT_FOUND if the entry is not in the cache. + SlangResult readEntry(const Key& key, ISlangBlob** outData); + + /// Write an entry to the cache. + /// Returns SLANG_OK if successful. + SlangResult writeEntry(const Key& key, ISlangBlob* data); + +private: + struct CacheEntry + { + Key key; + uint32_t age; + }; + + using CacheIndex = List<CacheEntry>; + + SlangResult initialize(); + + String getEntryFileName(const Key& key); + + SlangResult readIndex(const String& fileName, CacheIndex& outIndex); + SlangResult writeIndex(const String& fileName, const CacheIndex& index); + + String m_cacheDirectory; + String m_lockFileName; + String m_indexFileName; + + // For exclusive locking we need both a mutex (acquired first) + // followed by a a file lock. The mutex is needed because on Linux + // the file lock is only locking between processes, not threads. + std::mutex m_mutex; + Slang::LockFile m_lockFile; + + Count m_maxEntryCount; + + Stats m_stats; + + // Used for unit tests. + friend struct PersistentCacheTest; +}; + +} diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index ce0ae4085..f2ebefb9d 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -223,14 +223,9 @@ namespace Slang visitor->visitEntryPoint(this, as<EntryPointSpecializationInfo>(specializationInfo)); } - void EntryPoint::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) + void EntryPoint::buildHash(DigestBuilder<SHA1>& builder) { - // CompositeComponentType will have already hashed the relevant entry point's name - // and file path dependencies, so we immediately return. SLANG_UNUSED(builder); - SLANG_UNUSED(entryPointIndex); } List<Module*> const& EntryPoint::getModuleDependencies() @@ -242,12 +237,12 @@ namespace Slang return empty; } - List<String> const& EntryPoint::getFilePathDependencies() + List<SourceFile*> const& EntryPoint::getFileDependencies() { if(auto module = getModule()) - return getModule()->getFilePathDependencies(); + return getModule()->getFileDependencies(); - static List<String> empty; + static List<SourceFile*> empty; return empty; } @@ -269,8 +264,8 @@ namespace Slang if (auto declaredWitness = as<DeclaredSubtypeWitness>(witness)) { auto declModule = getModule(declaredWitness->declRef.getDecl()); - m_moduleDependency.addDependency(declModule); - m_pathDependency.addDependency(declModule); + m_moduleDependencyList.addDependency(declModule); + m_fileDependencyList.addDependency(declModule); if (m_requirementSet.Add(declModule)) { m_requirements.add(declModule); @@ -301,12 +296,8 @@ namespace Slang return Super::getInterface(guid); } - void TypeConformance::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) + void TypeConformance::buildHash(DigestBuilder<SHA1>& builder) { - SLANG_UNUSED(entryPointIndex); - //TODO: Implement some kind of hashInto for Val then replace this auto subtypeWitness = m_subtypeWitness->toString(); @@ -316,12 +307,12 @@ namespace Slang List<Module*> const& TypeConformance::getModuleDependencies() { - return m_moduleDependency.getModuleList(); + return m_moduleDependencyList.getModuleList(); } - List<String> const& TypeConformance::getFilePathDependencies() + List<SourceFile*> const& TypeConformance::getFileDependencies() { - return m_pathDependency.getFilePathList(); + return m_fileDependencyList.getFileList(); } Index TypeConformance::getRequirementCount() { return m_requirements.getCount(); } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 692fefbe2..f377d4882 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -197,6 +197,7 @@ namespace Slang }; /// Tracks an ordered list of modules that something depends on. + /// TODO: Shader caching currently relies on this being in well defined order. struct ModuleDependencyList { public: @@ -216,15 +217,16 @@ namespace Slang HashSet<Module*> m_moduleSet; }; - /// Tracks an unordered list of filesystem paths that something depends on - struct FilePathDependencyList + /// Tracks an unordered list of source files that something depends on + /// TODO: Shader caching currently relies on this being in well defined order. + struct FileDependencyList { public: - /// Get the list of paths that are depended on. - List<String> const& getFilePathList() { return m_filePathList; } + /// Get the list of files that are depended on. + List<SourceFile*> const& getFileList() { return m_fileList; } - /// Add a path to the list, if it is not already present - void addDependency(String const& path); + /// Add a file to the list, if it is not already present + void addDependency(SourceFile* sourceFile); /// Add all of the paths that `module` depends on to the list void addDependency(Module* module); @@ -236,11 +238,11 @@ namespace Slang // multiple times from `getFilePathList`, but because // order isn't important, we could potentially do better // in terms of memory (at some cost in performance) by - // just sorting the `m_filePathList` every once in + // just sorting the `m_fileList` every once in // a while and then deduplicating. - List<String> m_filePathList; - HashSet<String> m_filePathSet; + List<SourceFile*> m_fileList; + HashSet<SourceFile*> m_fileSet; }; class EntryPoint; @@ -292,13 +294,12 @@ namespace Slang slang::IBlob** outDiagnostics) SLANG_OVERRIDE; /// ComponentType is the only class inheriting from IComponentType that provides a - /// meaningful implementation for these two functions. All others should forward these - /// and implement updateDependencyBasedHash and updateASTBasedHash instead. - SLANG_NO_THROW void SLANG_MCALL computeDependencyBasedHash( + /// meaningful implementation for this function. All others should forward these and + /// implement `buildHash`. + SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) SLANG_OVERRIDE; - SLANG_NO_THROW void SLANG_MCALL computeContentsBasedHash(slang::IBlob** outHash) SLANG_OVERRIDE; /// Get the linkage (aka "session" in the public API) for this component type. Linkage* getLinkage() { return m_linkage; } @@ -309,14 +310,7 @@ namespace Slang TargetProgram* getTargetProgram(TargetRequest* target); /// Update the hash builder with the dependencies for this component type. - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) = 0; - - /// Update the hash builder with the source contents for this component type. - /// Module should be the only derived ComponentType class which has a meaningful - /// implementation; all others should do nothing. - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) = 0; + virtual void buildHash(DigestBuilder<SHA1>& builder) = 0; /// Get the number of entry points linked into this component type. virtual Index getEntryPointCount() = 0; @@ -371,9 +365,9 @@ namespace Slang /// virtual List<Module*> const& getModuleDependencies() = 0; - /// Get the full list of filesystem paths this component type depends on. + /// Get the full list of source files this component type depends on. /// - virtual List<String> const& getFilePathDependencies() = 0; + virtual List<SourceFile*> const& getFileDependencies() = 0; /// Callback for use with `enumerateIRModules` typedef void (*EnumerateIRModulesCallback)(IRModule* irModule, void* userData); @@ -515,11 +509,7 @@ namespace Slang Linkage* linkage, List<RefPtr<ComponentType>> const& childComponents); - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override; + virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; List<RefPtr<ComponentType>> const& getChildComponents() { return m_childComponents; }; Index getChildComponentCount() { return m_childComponents.getCount(); } @@ -540,7 +530,7 @@ namespace Slang RefPtr<ComponentType> getRequirement(Index index) SLANG_OVERRIDE; List<Module*> const& getModuleDependencies() SLANG_OVERRIDE; - List<String> const& getFilePathDependencies() SLANG_OVERRIDE; + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE; class CompositeSpecializationInfo : public SpecializationInfo { @@ -584,7 +574,7 @@ namespace Slang List<ComponentType*> m_requirements; ModuleDependencyList m_moduleDependencyList; - FilePathDependencyList m_filePathDependencyList; + FileDependencyList m_fileDependencyList; }; /// A component type created by specializing another component type. @@ -597,14 +587,7 @@ namespace Slang List<SpecializationArg> const& specializationArgs, DiagnosticSink* sink); - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override - { - SLANG_UNUSED(hashBuilder); - } + virtual void buildHash(DigestBuilder<SHA1>& builer) SLANG_OVERRIDE; /// Get the base (unspecialized) component type that is being specialized. RefPtr<ComponentType> getBaseComponentType() { return m_base; } @@ -638,7 +621,7 @@ namespace Slang RefPtr<ComponentType> getRequirement(Index index) SLANG_OVERRIDE; List<Module*> const& getModuleDependencies() SLANG_OVERRIDE { return m_moduleDependencies; } - List<String> const& getFilePathDependencies() SLANG_OVERRIDE { return m_filePathDependencies; } + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE { return m_fileDependencies; } /// Get a list of tagged-union types referenced by the specialization parameters. List<TaggedUnionType*> const& getTaggedUnionTypes() { return m_taggedUnionTypes; } @@ -673,7 +656,7 @@ namespace Slang List<TaggedUnionType*> m_taggedUnionTypes; List<Module*> m_moduleDependencies; - List<String> m_filePathDependencies; + List<SourceFile*> m_fileDependencies; List<RefPtr<ComponentType>> m_requirements; }; @@ -748,9 +731,9 @@ namespace Slang { return m_base->getModuleDependencies(); } - List<String> const& getFilePathDependencies() SLANG_OVERRIDE + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE { - return m_base->getFilePathDependencies(); + return m_base->getFileDependencies(); } SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE @@ -790,14 +773,7 @@ namespace Slang void acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) SLANG_OVERRIDE; - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override - { - SLANG_UNUSED(hashBuilder); - } + virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; private: RefPtr<ComponentType> m_base; @@ -891,27 +867,15 @@ namespace Slang return Super::getEntryPointHostCallable(entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); } - SLANG_NO_THROW void SLANG_MCALL computeDependencyBasedHash( + SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) SLANG_OVERRIDE { - return Super::computeDependencyBasedHash(entryPointIndex, targetIndex, outHash); - } - - SLANG_NO_THROW void SLANG_MCALL computeContentsBasedHash(slang::IBlob** outHash) SLANG_OVERRIDE - { - return Super::computeContentsBasedHash(outHash); + return Super::getEntryPointHash(entryPointIndex, targetIndex, outHash); } - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override - { - SLANG_UNUSED(hashBuilder); - } + virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; /// Create an entry point that refers to the given function. static RefPtr<EntryPoint> create( @@ -948,7 +912,7 @@ namespace Slang /// but may also include modules that are required by its generic type arguments. /// List<Module*> const& getModuleDependencies() SLANG_OVERRIDE; // { return getModule()->getModuleDependencies(); } - List<String> const& getFilePathDependencies() SLANG_OVERRIDE; // { return getModule()->getFilePathDependencies(); } + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE; // { return getModule()->getFileDependencies(); } /// Create a dummy `EntryPoint` that is only usable for pass-through compilation. static RefPtr<EntryPoint> createDummyForPassThrough( @@ -1118,30 +1082,18 @@ namespace Slang entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); } - SLANG_NO_THROW void SLANG_MCALL computeDependencyBasedHash( + SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) SLANG_OVERRIDE { - return Super::computeDependencyBasedHash(entryPointIndex, targetIndex, outHash); - } - - SLANG_NO_THROW void SLANG_MCALL computeContentsBasedHash(slang::IBlob** outHash) SLANG_OVERRIDE - { - return Super::computeContentsBasedHash(outHash); + return Super::getEntryPointHash(entryPointIndex, targetIndex, outHash); } - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override - { - SLANG_UNUSED(hashBuilder); - } + virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; List<Module*> const& getModuleDependencies() SLANG_OVERRIDE; - List<String> const& getFilePathDependencies() SLANG_OVERRIDE; + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE; SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE { return 0; } @@ -1182,8 +1134,8 @@ namespace Slang DiagnosticSink* sink) SLANG_OVERRIDE; private: SubtypeWitness* m_subtypeWitness; - ModuleDependencyList m_moduleDependency; - FilePathDependencyList m_pathDependency; + ModuleDependencyList m_moduleDependencyList; + FileDependencyList m_fileDependencyList; List<RefPtr<Module>> m_requirements; HashSet<Module*> m_requirementSet; RefPtr<IRModule> m_irModule; @@ -1314,24 +1266,15 @@ namespace Slang // - SLANG_NO_THROW void SLANG_MCALL computeDependencyBasedHash( + SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) SLANG_OVERRIDE { - return Super::computeDependencyBasedHash(entryPointIndex, targetIndex, outHash); - } - - SLANG_NO_THROW void SLANG_MCALL computeContentsBasedHash(slang::IBlob** outHash) SLANG_OVERRIDE - { - return Super::computeContentsBasedHash(outHash); + return Super::getEntryPointHash(entryPointIndex, targetIndex, outHash); } - virtual void updateDependencyBasedHash( - DigestBuilder<MD5>& hashBuilder, - SlangInt entryPointIndex) override; - - virtual void updateContentsBasedHash(DigestBuilder<MD5>& hashBuilder) override; + virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; /// Create a module (initially empty). Module(Linkage* linkage, ASTBuilder* astBuilder = nullptr); @@ -1345,14 +1288,14 @@ namespace Slang /// Get the list of other modules this module depends on List<Module*> const& getModuleDependencyList() { return m_moduleDependencyList.getModuleList(); } - /// Get the list of filesystem paths this module depends on - List<String> const& getFilePathDependencyList() { return m_filePathDependencyList.getFilePathList(); } + /// Get the list of files this module depends on + List<SourceFile*> const& getFileDependencyList() { return m_fileDependencyList.getFileList(); } /// Register a module that this module depends on void addModuleDependency(Module* module); - /// Register a filesystem path that this module depends on - void addFilePathDependency(String const& path); + /// Register a source file that this module depends on + void addFileDependency(SourceFile* sourceFile); /// Set the AST for this module. /// @@ -1381,7 +1324,7 @@ namespace Slang RefPtr<ComponentType> getRequirement(Index index) SLANG_OVERRIDE; List<Module*> const& getModuleDependencies() SLANG_OVERRIDE { return m_moduleDependencyList.getModuleList(); } - List<String> const& getFilePathDependencies() SLANG_OVERRIDE { return m_filePathDependencyList.getFilePathList(); } + List<SourceFile*> const& getFileDependencies() SLANG_OVERRIDE { return m_fileDependencyList.getFileList(); } /// Given a mangled name finds the exported NodeBase associated with this module. /// If not found returns nullptr. @@ -1443,8 +1386,8 @@ namespace Slang // List of modules this module depends on ModuleDependencyList m_moduleDependencyList; - // List of filesystem paths this module depends on - FilePathDependencyList m_filePathDependencyList; + // List of source files this module depends on + FileDependencyList m_fileDependencyList; // Entry points that were defined in thsi module // @@ -1474,9 +1417,6 @@ namespace Slang // and m_mangledExportSymbols holds the NodeBase* values for each index. StringSlicePool m_mangledExportPool; List<NodeBase*> m_mangledExportSymbols; - - MD5::Digest lastModifiedDigest; - MD5::Digest contentsDigest; }; typedef Module LoadedModule; @@ -1768,12 +1708,10 @@ namespace Slang SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest( SlangCompileRequest** outCompileRequest) override; - // Updates the supplied has builder with linkage-related information, which includes preprocessor + // Updates the supplied builder with linkage-related information, which includes preprocessor // defines, the compiler version, and other compiler options. This is then merged with the hash // produced for the program to produce a key that can be used with the shader cache. - void updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt targetIndex); + void buildHash(DigestBuilder<SHA1>& builder, SlangInt targetIndex); void addTarget( slang::TargetDesc const& desc); diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp index fca8f5029..341e75ea4 100644 --- a/source/slang/slang-preprocessor.cpp +++ b/source/slang/slang-preprocessor.cpp @@ -32,9 +32,9 @@ void PreprocessorHandler::handleEndOfTranslationUnit(Preprocessor* preprocessor) SLANG_UNUSED(preprocessor); } -void PreprocessorHandler::handleFileDependency(String const& path) +void PreprocessorHandler::handleFileDependency(SourceFile* sourceFile) { - SLANG_UNUSED(path); + SLANG_UNUSED(sourceFile); } // In order to simplify the naming scheme, we will nest the implementaiton of the @@ -2966,15 +2966,6 @@ static SlangResult readFile( auto fileSystemExt = context->m_preprocessor->fileSystem; SLANG_RETURN_ON_FAIL(fileSystemExt->loadFile(path.getBuffer(), outBlob)); - // If we are running the preprocessor as part of compiling a - // specific module, then we must keep track of the file we've - // read as yet another file that the module will depend on. - // - if( auto handler = context->m_preprocessor->handler ) - { - handler->handleFileDependency(path); - } - return SLANG_OK; } @@ -3056,10 +3047,18 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) } sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob); - sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile); } + // If we are running the preprocessor as part of compiling a + // specific module, then we must keep track of the file we've + // read as yet another file that the module will depend on. + // + if (auto handler = context->m_preprocessor->handler) + { + handler->handleFileDependency(sourceFile); + } + // This is a new parse (even if it's a pre-existing source file), so create a new SourceView SourceView* sourceView = sourceManager->createSourceView(sourceFile, &filePathInfo, directiveLoc); diff --git a/source/slang/slang-preprocessor.h b/source/slang/slang-preprocessor.h index 4d7721d31..c37fd1607 100644 --- a/source/slang/slang-preprocessor.h +++ b/source/slang/slang-preprocessor.h @@ -28,7 +28,7 @@ using preprocessor::Preprocessor; struct PreprocessorHandler { virtual void handleEndOfTranslationUnit(Preprocessor* preprocessor); - virtual void handleFileDependency(String const& path); + virtual void handleFileDependency(SourceFile* sourceFile); }; /// Description of a preprocessor options/dependencies diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 3b2175fad..4f057bb21 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -1320,9 +1320,7 @@ SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::createCompileRequest( return SLANG_OK; } -void Linkage::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt targetIndex) +void Linkage::buildHash(DigestBuilder<SHA1>& builder, SlangInt targetIndex) { // Add the Slang compiler version to the hash auto version = String(getBuildTagString()); @@ -1346,29 +1344,39 @@ void Linkage::updateDependencyBasedHash( // Add the target specified by targetIndex auto targetReq = targets[targetIndex]; builder.append(targetReq->getTarget()); + builder.append(targetReq->getTargetProfile().raw); builder.append(targetReq->getTargetFlags()); builder.append(targetReq->getFloatingPointMode()); builder.append(targetReq->getLineDirectiveMode()); - builder.append(targetReq->shouldDumpIntermediates()); builder.append(targetReq->getForceGLSLScalarBufferLayout()); + builder.append(targetReq->getDefaultMatrixLayoutMode()); + builder.append(targetReq->shouldDumpIntermediates()); builder.append(targetReq->shouldTrackLiveness()); - auto targetProfile = targetReq->getTargetProfile(); - builder.append(targetProfile.getStage()); - builder.append(targetProfile.getVersion()); - builder.append(targetProfile.getFamily()); - - auto targetProfileName = String(targetProfile.getName()); - builder.append(targetProfileName); - auto cookedCapabilities = targetReq->getTargetCaps().getExpandedAtoms(); for (auto& capability : cookedCapabilities) { builder.append(capability); } + const PassThroughMode passThroughMode = getDownstreamCompilerRequiredForTarget(targetReq->getTarget()); + const SourceLanguage sourceLanguage = getDefaultSourceLanguageForDownstreamCompiler(passThroughMode); + + // Add prelude for the given downstream compiler. + ComPtr<ISlangBlob> prelude; + getGlobalSession()->getLanguagePrelude((SlangSourceLanguage)sourceLanguage, prelude.writeRef()); + if (prelude) + { + builder.append(prelude); + } + + // TODO: Downstream compilers (specifically dxc) can currently #include additional dependencies. + // This is currently the case for NVAPI headers included in the prelude. + // These dependencies are currently not picked up by the shader cache which is a significant issue. + // This can only be fixed by running the preprocessor in the slang compiler so dxc (or any other + // downstream compiler for that matter) isn't resolving any includes implicitly. + // Add the downstream compiler version (if it exists) to the hash - auto passThroughMode = getDownstreamCompilerRequiredForTarget(targetReq->getTarget()); auto downstreamCompiler = getSessionImpl()->getOrLoadDownstreamCompiler(passThroughMode, nullptr); if (downstreamCompiler) { @@ -1674,25 +1682,7 @@ void TranslationUnitRequest::_addSourceFile(SourceFile* sourceFile) { m_sourceFiles.add(sourceFile); - // We want to record that the compiled module has a dependency - // on the path of the source file, but we also need to account - // for cases where the user added a source string/blob without - // an associated path and/or wasn't from a file. - - auto pathInfo = sourceFile->getPathInfo(); - if (pathInfo.hasFoundPath()) - { - getModule()->addFilePathDependency(pathInfo.foundPath); - } - else - { - // No path exists for this source, so we generate a new string to use as a - // fake path in the list of file path dependencies. This is needed to account - // for non-file-based dependencies later when shader files are being hashed for - // the shader cache. - auto sourceHash = MD5::compute(sourceFile->getContent().begin(), sourceFile->getContent().getLength()); - getModule()->addFilePathDependency(sourceHash.toString()); - } + getModule()->addFileDependency(sourceFile); } List<SourceFile*> const& TranslationUnitRequest::getSourceFiles() @@ -1896,9 +1886,9 @@ protected: // by applications to decide when they need to "hot reload" // their shader code. // - void handleFileDependency(String const& path) SLANG_OVERRIDE + void handleFileDependency(SourceFile* sourceFile) SLANG_OVERRIDE { - m_module->addFilePathDependency(path); + m_module->addFileDependency(sourceFile); } // The second task that this handler deals with is detecting @@ -3200,23 +3190,23 @@ void ModuleDependencyList::_addDependency(Module* module) } // -// FilePathDependencyList +// FileDependencyList // -void FilePathDependencyList::addDependency(String const& path) +void FileDependencyList::addDependency(SourceFile* sourceFile) { - if(m_filePathSet.Contains(path)) + if(m_fileSet.Contains(sourceFile)) return; - m_filePathList.add(path); - m_filePathSet.Add(path); + m_fileList.add(sourceFile); + m_fileSet.Add(sourceFile); } -void FilePathDependencyList::addDependency(Module* module) +void FileDependencyList::addDependency(Module* module) { - for(auto& path : module->getFilePathDependencyList()) + for(SourceFile* sourceFile : module->getFileDependencyList()) { - addDependency(path); + addDependency(sourceFile); } } @@ -3247,75 +3237,20 @@ ISlangUnknown* Module::getInterface(const Guid& guid) return Super::getInterface(guid); } -void Module::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) +void Module::buildHash(DigestBuilder<SHA1>& builder) { - // CompositeComponentType will have already hashed this Module's file - // dependencies. SLANG_UNUSED(builder); - SLANG_UNUSED(entryPointIndex); -} - -void Module::updateContentsBasedHash(DigestBuilder<MD5>& builder) -{ - auto filePathDependencies = getFilePathDependencies(); - - DigestBuilder<MD5> lastModifiedBuilder; - auto statFailed = false; - for (auto file : filePathDependencies) - { - struct stat fileStatus; - auto res = stat(file.getBuffer(), &fileStatus); - if (res != 0) - { - statFailed = true; - break; - } - lastModifiedBuilder.append(fileStatus.st_mtime); - } - - MD5::Digest temp = lastModifiedBuilder.finalize(); - if (statFailed || temp != lastModifiedDigest) - { - // Either a stat() call failed, or changes were made to at least one of the file dependencies, - // so we will need to re-generate the contents digest and save the new digest. - DigestBuilder<MD5> contentsBuilder; - for (auto file : filePathDependencies) - { - List<uint8_t> fileContents; - if (SLANG_FAILED(File::readAllBytes(file, fileContents))) - { - // Failure to read the file means this is a digest for the contents of a source - // file which does not live on disk. - contentsBuilder.append(file); - } - else - { - contentsBuilder.append(fileContents); - } - } - contentsDigest = contentsBuilder.finalize(); - if (!statFailed) - { - // If no stat() calls failed, then we have a valid last modified digest and should - // update the one we have saved. - lastModifiedDigest = temp; - } - } - - builder.append(contentsDigest); } void Module::addModuleDependency(Module* module) { m_moduleDependencyList.addDependency(module); - m_filePathDependencyList.addDependency(module); + m_fileDependencyList.addDependency(module); } -void Module::addFilePathDependency(String const& path) +void Module::addFileDependency(SourceFile* sourceFile) { - m_filePathDependencyList.addDependency(path); + m_fileDependencyList.addDependency(sourceFile); } void Module::setModuleDecl(ModuleDecl* moduleDecl) @@ -3505,12 +3440,12 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointCode( return artifact->loadBlob(ArtifactKeep::Yes, outCode); } -SLANG_NO_THROW void SLANG_MCALL ComponentType::computeDependencyBasedHash( +SLANG_NO_THROW void SLANG_MCALL ComponentType::getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) { - DigestBuilder<MD5> builder; + DigestBuilder<SHA1> builder; // A note on enums that may be hashed in as part of the following two function calls: // @@ -3518,19 +3453,19 @@ SLANG_NO_THROW void SLANG_MCALL ComponentType::computeDependencyBasedHash( // the compiler, part of hashing the linkage is hashing in the compiler version. // Consequently, any encoding differences as a result of different compiler versions // will already be reflected in the resulting hash. - getLinkage()->updateDependencyBasedHash(builder, targetIndex); - updateDependencyBasedHash(builder, entryPointIndex); + getLinkage()->buildHash(builder, targetIndex); - // Add file path dependencies to the hash - all child components - // will have file path dependencies that are a subset of this list. - auto fileDeps = getFilePathDependencies(); - for (auto& file : fileDeps) + // Enumerate all file dependencies and add them to the hash. + for (SourceFile* sourceFile : getFileDependencies()) { - builder.append(file); + // TODO: We want to lazily evaluate & cache the source file digest + SHA1::Digest digest = SHA1::compute(sourceFile->getContent().begin(), sourceFile->getContent().getLength()); + builder.append(digest); } - // Add the name and name override for the specified entry point - // to the hash. + buildHash(builder); + + // Add the name and name override for the specified entry point to the hash. auto entryPointName = getEntryPoint(entryPointIndex)->getName()->text; builder.append(entryPointName); auto entryPointMangledName = getEntryPointMangledName(entryPointIndex); @@ -3542,14 +3477,6 @@ SLANG_NO_THROW void SLANG_MCALL ComponentType::computeDependencyBasedHash( *outHash = hash.detach(); } -SLANG_NO_THROW void SLANG_MCALL ComponentType::computeContentsBasedHash(slang::IBlob** outHash) -{ - DigestBuilder<MD5> builder; - updateContentsBasedHash(builder); - auto hash = builder.finalize().toBlob(); - *outHash = hash.detach(); -} - SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointHostCallable( int entryPointIndex, int targetIndex, @@ -3864,9 +3791,9 @@ CompositeComponentType::CompositeComponentType( { m_moduleDependencyList.addDependency(module); } - for(auto filePath : child->getFilePathDependencies()) + for(auto sourceFile : child->getFileDependencies()) { - m_filePathDependencyList.addDependency(filePath); + m_fileDependencyList.addDependency(sourceFile); } auto childRequirementCount = child->getRequirementCount(); @@ -3882,25 +3809,13 @@ CompositeComponentType::CompositeComponentType( } } -void CompositeComponentType::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) -{ - auto componentCount = getChildComponentCount(); - - for (Index i = 0; i < componentCount; ++i) - { - getChildComponent(i)->updateDependencyBasedHash(builder, entryPointIndex); - } -} - -void CompositeComponentType::updateContentsBasedHash(DigestBuilder<MD5>& builder) +void CompositeComponentType::buildHash(DigestBuilder<SHA1>& builder) { auto componentCount = getChildComponentCount(); for (Index i = 0; i < componentCount; ++i) { - getChildComponent(i)->updateContentsBasedHash(builder); + getChildComponent(i)->buildHash(builder); } } @@ -3959,9 +3874,9 @@ List<Module*> const& CompositeComponentType::getModuleDependencies() return m_moduleDependencyList.getModuleList(); } -List<String> const& CompositeComponentType::getFilePathDependencies() +List<SourceFile*> const& CompositeComponentType::getFileDependencies() { - return m_filePathDependencyList.getFilePathList(); + return m_fileDependencyList.getFileList(); } void CompositeComponentType::acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) @@ -4226,7 +4141,7 @@ SpecializedComponentType::SpecializedComponentType( // The starting point for our lists comes from the base component type. // m_moduleDependencies = base->getModuleDependencies(); - m_filePathDependencies = base->getFilePathDependencies(); + m_fileDependencies = base->getFileDependencies(); Index baseRequirementCount = base->getRequirementCount(); for( Index r = 0; r < baseRequirementCount; r++ ) @@ -4238,11 +4153,11 @@ SpecializedComponentType::SpecializedComponentType( // dependencies and requirements based on the modules that // were collected when looking at the specialization arguments. - // We want to avoid adding the same file path dependency more than once. + // We want to avoid adding the same file dependency more than once. // - HashSet<String> filePathDependencySet; - for(auto path : m_filePathDependencies) - filePathDependencySet.Add(path); + HashSet<SourceFile*> fileDependencySet; + for(SourceFile* sourceFile : m_fileDependencies) + fileDependencySet.Add(sourceFile); for(auto module : moduleCollector.m_modulesList) { @@ -4259,7 +4174,7 @@ SpecializedComponentType::SpecializedComponentType( m_requirements.add(module); // The speciialized component type will also have a dependency - // on all the file paths that any of the modules involved in + // on all the files that any of the modules involved in // it depend on (including those that are required but not // yet linked in). // @@ -4268,12 +4183,12 @@ SpecializedComponentType::SpecializedComponentType( // source files, so we want to include anything that could // affect the validity of generated code. // - for(auto path : module->getFilePathDependencies()) + for(SourceFile* sourceFile : module->getFileDependencies()) { - if(filePathDependencySet.Contains(path)) + if(fileDependencySet.Contains(sourceFile)) continue; - filePathDependencySet.Add(path); - m_filePathDependencies.add(path); + fileDependencySet.Add(sourceFile); + m_fileDependencies.add(sourceFile); } // Finalyl we also add the module for the specialization arguments @@ -4383,9 +4298,7 @@ SpecializedComponentType::SpecializedComponentType( collector.visitSpecialized(this); } -void SpecializedComponentType::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) +void SpecializedComponentType::buildHash(DigestBuilder<SHA1>& builder) { auto specializationArgCount = getSpecializationArgCount(); for (Index i = 0; i < specializationArgCount; ++i) @@ -4395,7 +4308,7 @@ void SpecializedComponentType::updateDependencyBasedHash( builder.append(argString); } - getBaseComponentType()->updateDependencyBasedHash(builder, entryPointIndex); + getBaseComponentType()->buildHash(builder); } void SpecializedComponentType::acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) @@ -4442,13 +4355,8 @@ void RenamedEntryPointComponentType::acceptVisitor( this, as<EntryPoint::EntryPointSpecializationInfo>(specializationInfo)); } -void RenamedEntryPointComponentType::updateDependencyBasedHash( - DigestBuilder<MD5>& builder, - SlangInt entryPointIndex) +void RenamedEntryPointComponentType::buildHash(DigestBuilder<SHA1>& builder) { - // CompositeComponentType will have already hashed the name override and file - // dependencies for this entry point. - SLANG_UNUSED(entryPointIndex); SLANG_UNUSED(builder); } @@ -5144,14 +5052,15 @@ int EndToEndCompileRequest::getDependencyFileCount() { auto frontEndReq = getFrontEndReq(); auto program = frontEndReq->getGlobalAndEntryPointsComponentType(); - return (int)program->getFilePathDependencies().getCount(); + return (int)program->getFileDependencies().getCount(); } char const* EndToEndCompileRequest::getDependencyFilePath(int index) { auto frontEndReq = getFrontEndReq(); auto program = frontEndReq->getGlobalAndEntryPointsComponentType(); - return program->getFilePathDependencies()[index].begin(); + SourceFile* sourceFile = program->getFileDependencies()[index]; + return sourceFile->getPathInfo().hasFileFoundPath() ? sourceFile->getPathInfo().foundPath.getBuffer() : "unknown"; } int EndToEndCompileRequest::getTranslationUnitCount() |
