diff options
Diffstat (limited to 'tools/gfx')
| -rw-r--r-- | tools/gfx/gfx.slang | 24 | ||||
| -rw-r--r-- | tools/gfx/persistent-shader-cache.cpp | 316 | ||||
| -rw-r--r-- | tools/gfx/persistent-shader-cache.h | 99 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 94 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.h | 27 |
5 files changed, 63 insertions, 497 deletions
diff --git a/tools/gfx/gfx.slang b/tools/gfx/gfx.slang index b4bd76470..3d75e3b40 100644 --- a/tools/gfx/gfx.slang +++ b/tools/gfx/gfx.slang @@ -1712,15 +1712,10 @@ struct SlangDesc struct ShaderCacheDesc { - // The filename for the file the cache's state should be saved to or loaded from. - NativeString cacheFilename = "cache.txt"; - // The root directory for the shader cache. + // The root directory for the shader cache. If not set, shader cache is disabled. NativeString shaderCachePath; - // The file system for loading cached shader kernels. The layer does not maintain a strong reference to the object, - // instead the user is responsible for holding the object alive during the lifetime of an `IDevice`. - void* shaderCacheFileSystem = nullptr; // The maximum number of entries stored in the cache. - GfxCount entryCountLimit = 0; + GfxCount maxEntryCount = 0; }; struct DeviceInteropHandles @@ -1934,6 +1929,21 @@ interface IDevice Result getTextureRowAlignment(out Size outAlignment); }; +struct ShaderCacheStats +{ + GfxCount hitCount; + GfxCount missCount; + GfxCount entryCount; +}; + +[COM("715bdf26-5135-11eb-AE93-02-42-AC-13-00-02")] +interface IShaderCache +{ + Result clearShaderCache(); + Result getShaderCacheStats(out ShaderCacheStats outStats); + Result resetShaderCacheStats(); +}; + #define SLANG_GFX_IMPORT [DllImport("gfx")] /// Checks if format is compressed SLANG_GFX_IMPORT bool gfxIsCompressedFormat(Format format); diff --git a/tools/gfx/persistent-shader-cache.cpp b/tools/gfx/persistent-shader-cache.cpp deleted file mode 100644 index 7dc64632b..000000000 --- a/tools/gfx/persistent-shader-cache.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// slang-shader-cache-index.cpp -#include "persistent-shader-cache.h" - -#include "../../source/core/slang-io.h" -#include "../../source/core/slang-string-util.h" -#include "../../source/core/slang-file-system.h" - -#include "../../source/core/slang-char-util.h" - -#include <chrono> - -namespace gfx -{ - -using namespace std::chrono; - -PersistentShaderCache::PersistentShaderCache(const IDevice::ShaderCacheDesc& inDesc) -{ - desc = inDesc; - - // If a path is provided, we will want our underlying file system to be initialized using that path. - if (desc.shaderCachePath) - { - if (!desc.shaderCacheFileSystem) - { - // Only a path was provided, so we get a mutable file system - // using OSFileSystem::getMutableSingleton. - desc.shaderCacheFileSystem = OSFileSystem::getMutableSingleton(); - } - desc.shaderCacheFileSystem = new RelativeFileSystem(desc.shaderCacheFileSystem, desc.shaderCachePath); - } - - // If our shader cache has an underlying file system, check if it's mutable. If so, store a pointer - // to the mutable version for operations which require writing to disk. - if (desc.shaderCacheFileSystem) - { - desc.shaderCacheFileSystem->queryInterface(ISlangMutableFileSystem::getTypeGuid(), (void**)mutableShaderCacheFileSystem.writeRef()); - } - - loadCacheFromFile(); -} - -PersistentShaderCache::~PersistentShaderCache() -{ - if (isMemoryFileSystem) - { - saveCacheToMemory(); - } -} - -// Load a previous cache index saved to disk. If not found, create a new cache index -// and save it to disk as filename. -void PersistentShaderCache::loadCacheFromFile() -{ - // We will need to combine the filename with the cache path in order to have the correct - // file path for initializing the stream. This needs to be done separately because there - // is no guarantee that the underlying file system is mutable. - String filePath; - if (mutableShaderCacheFileSystem) - { - ComPtr<ISlangBlob> fullPath; - if (SLANG_FAILED(mutableShaderCacheFileSystem->getPath(PathKind::OperatingSystem, desc.cacheFilename, fullPath.writeRef()))) - { - // If we fail to obtain a physical file path, then this must be a MemoryFileSystem. In this case, file streams - // will not work as they require the file to be on disk, so we will rely on a fall back implementation. - isMemoryFileSystem = true; - loadCacheFromMemory(); - return; - } - filePath = String((char*)fullPath->getBufferPointer()); - } - else - { - filePath = Path::combine(String(desc.shaderCachePath), String(desc.cacheFilename)); - } - - if (SLANG_FAILED(indexStream.init(filePath, FileMode::Open, FileAccess::ReadWrite, FileShare::ReadWrite))) - { - // If we failed to open a stream to the file, then the file does not yet exist on disk. - // We will create the index file if our underlying file system is mutable. - if (mutableShaderCacheFileSystem) - { - indexStream.init(filePath, FileMode::Create, FileAccess::ReadWrite, FileShare::ReadWrite); - } - return; - } - else - { - const auto start = indexStream.getPosition(); - indexStream.seek(SeekOrigin::End, 0); - const auto end = indexStream.getPosition(); - indexStream.seek(SeekOrigin::Start, 0); - const Index numEntries = (Index)(end - start) / sizeof(ShaderCacheEntry); - - if (desc.entryCountLimit > 0 && numEntries > desc.entryCountLimit) - { - // If the size limit for the current cache is smaller than the cache that produced the file we're trying to - // load, re-create the entire file. - // - // FileStream does not currently have any methods for truncating an existing file, so in this case, our cache - // index would no longer accurately reflect the state of our cache due to the extra now-garbage lines present. - // While this has no impact on cache operation, it could be problematic for debugging purposes, etc. - indexStream.close(); - indexStream.init(filePath, FileMode::Create, FileAccess::ReadWrite, FileShare::ReadWrite); - return; - } - else - { - // The cache index is not guaranteed to be ordered by most recent access, so we need a temporary list to store - // all the entries in order to sort them before filling in our linked list. - List<ShaderCacheEntry> tempEntries; - tempEntries.setCount(numEntries); - size_t bytesRead; - indexStream.read(tempEntries.getBuffer(), sizeof(ShaderCacheEntry) * numEntries, bytesRead); - - // We will need to sort tempEntries by last accessed time before we can add entries to our linked list. - tempEntries.quickSort(tempEntries.getBuffer(), 0, tempEntries.getCount() - 1, [](ShaderCacheEntry a, ShaderCacheEntry b) { return a.lastAccessedTime > b.lastAccessedTime; }); - for (auto& entry : tempEntries) - { - // If we reach this point, then the current cache is at least the same size in entries as the cache - // that produced the index we're reading in, so we don't need to check if we're exceeding capacity. - auto entryIndexNode = orderedEntries.AddLast(entries.getCount()); - entries.add(entry); - keyToEntry.Add(entry.dependencyBasedDigest, entryIndexNode); - } - } - } -} - -ShaderCacheEntry* PersistentShaderCache::findEntry(const DigestType& key, ISlangBlob** outCompiledCode) -{ - LinkedNode<Index>* entryIndexNode; - if (!keyToEntry.TryGetValue(key, entryIndexNode)) - { - // The key was not found in the cache, so we return nullptr. - *outCompiledCode = nullptr; - return nullptr; - } - - // If the key is found, load the stored contents from disk. We then move the corresponding - // entry to the front of the linked list and update the cache file on disk - desc.shaderCacheFileSystem->loadFile(key.toString().getBuffer(), outCompiledCode); - auto index = entryIndexNode->Value; - entries[index].lastAccessedTime = (double)high_resolution_clock::now().time_since_epoch().count(); - if (orderedEntries.FirstNode() != entryIndexNode) - { - orderedEntries.RemoveFromList(entryIndexNode); - orderedEntries.AddFirst(entryIndexNode); - if (mutableShaderCacheFileSystem && !isMemoryFileSystem) - { - auto offset = index * sizeof(ShaderCacheEntry); - indexStream.seek(SeekOrigin::Start, offset + 2 * sizeof(DigestType)); - indexStream.write(&entries[index].lastAccessedTime, sizeof(double)); - indexStream.flush(); - } - } - return &entries[index]; -} - -void PersistentShaderCache::addEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* compiledCode) -{ - if (!mutableShaderCacheFileSystem) - { - // Should not save new entries if the underlying file system isn't mutable. - return; - } - - // Check that we do not exceed the cache's size limit by adding another entry. If so, - // remove the least recently used entry first. - // - // In theory, the cache could be more than just one entry over the entry count limit. - // However, this is impossible in practice because we fully re-create the entry list - // and cache index file if the size of the current cache is smaller than the cache - // that generated the index file we loaded. In any case, the initial number of entries - // in the cache will always be fewer than the size limit and this check will be hit - // on the first entry added that exceeds the cache's size. - Index index = entries.getCount(); - if (desc.entryCountLimit > 0 && orderedEntries.Count() >= desc.entryCountLimit) - { - index = deleteLRUEntry(); - } - - auto lastAccessedTime = (double)high_resolution_clock::now().time_since_epoch().count(); - - ShaderCacheEntry entry = { dependencyDigest, contentsDigest, lastAccessedTime }; - auto entryNode = orderedEntries.AddFirst(index); - if (index == entries.getCount()) - { - // No entries were removed, so we can tack this entry on at the end. - entries.add(entry); - } - else - { - // An entry was deleted, so we overwrite that slot with the new entry. - entries[index] = entry; - } - keyToEntry.Add(dependencyDigest, entryNode); - - mutableShaderCacheFileSystem->saveFileBlob(dependencyDigest.toString().getBuffer(), compiledCode); - - if (!isMemoryFileSystem) - { - indexStream.seek(SeekOrigin::End, 0); - indexStream.write(&entry, sizeof(ShaderCacheEntry)); - indexStream.flush(); - } -} - -void PersistentShaderCache::updateEntry( - const DigestType& dependencyDigest, - const DigestType& contentsDigest, - ISlangBlob* updatedCode) -{ - if (!mutableShaderCacheFileSystem) - { - // Updating entries requires saving to disk in order to overwrite the old shader file - // on disk, so we return if the underlying file system isn't mutable. - return; - } - - // Unlike in addEntry(), we only update the contents digest here because the last accessed time will have already - // been updated while finding the entry. - auto entryIndexNode = *keyToEntry.TryGetValue(dependencyDigest); - auto index = entryIndexNode->Value; - entries[index].contentsBasedDigest = contentsDigest; - mutableShaderCacheFileSystem->saveFileBlob(dependencyDigest.toString().getBuffer(), updatedCode); - - if (!isMemoryFileSystem) - { - auto offset = index * sizeof(ShaderCacheEntry); - indexStream.seek(SeekOrigin::Start, offset + sizeof(DigestType)); - indexStream.write(&contentsDigest, sizeof(DigestType)); - indexStream.flush(); - } -} - -Index PersistentShaderCache::deleteLRUEntry() -{ - if (!mutableShaderCacheFileSystem) - { - // This is here as a safety precaution but should never be hit as - // addEntry() and its memory-based equivalent are the only functions - // that should call this. - return -1; - } - - auto lruEntry = orderedEntries.LastNode(); - auto index = lruEntry->Value; - auto shaderKey = entries[index].dependencyBasedDigest; - - keyToEntry.Remove(shaderKey); - mutableShaderCacheFileSystem->remove(shaderKey.toString().getBuffer()); - - orderedEntries.Delete(lruEntry); - return index; -} - -// An in-memory file system cannot utilize file streaming to update the index file in place. -// Consequently, the cache index file is updated once on exit and is guaranteed to maintain the -// correct order of entries from most to least recently used. However, any kind of interruption -// in program execution that results in the cache destructor not being called will result in an -// inaccurate cache index. -// -// These currently assume that the underlying file system must be a MemoryFileSystem as this is the -// only in-memory file system that currently exists in Slang, which is guaranteed to be mutable. -// Mutability checks will need to be added if this changes in the future. -void PersistentShaderCache::loadCacheFromMemory() -{ - ComPtr<ISlangBlob> indexBlob; - if (SLANG_FAILED(mutableShaderCacheFileSystem->loadFile(desc.cacheFilename, indexBlob.writeRef()))) - { - mutableShaderCacheFileSystem->saveFile(desc.cacheFilename, nullptr, 0); - return; - } - - auto indexString = UnownedStringSlice((char*)indexBlob->getBufferPointer()); - - List<UnownedStringSlice> lines; - StringUtil::calcLines(indexString, lines); - for (auto line : lines) - { - List<UnownedStringSlice> entryFields; - StringUtil::split(line, ' ', entryFields); - if (entryFields.getCount() != 2) - continue; - - ShaderCacheEntry entry; - entry.dependencyBasedDigest = DigestType(entryFields[0]); - entry.contentsBasedDigest = DigestType(entryFields[1]); - entry.lastAccessedTime = 0; - - auto entryNode = orderedEntries.AddLast(entries.getCount()); - entries.add(entry); - keyToEntry.Add(entry.dependencyBasedDigest, entryNode); - - if (desc.entryCountLimit > 0 && orderedEntries.Count() == desc.entryCountLimit) - break; - } -} - -void PersistentShaderCache::saveCacheToMemory() -{ - StringBuilder indexSb; - for (auto& entryIndex : orderedEntries) - { - auto entry = entries[entryIndex]; - indexSb << entry.dependencyBasedDigest.toString(); - indexSb << " "; - indexSb << entry.contentsBasedDigest.toString(); - indexSb << "\n"; - } - - mutableShaderCacheFileSystem->saveFile(desc.cacheFilename, indexSb.getBuffer(), indexSb.getLength()); -} - -} diff --git a/tools/gfx/persistent-shader-cache.h b/tools/gfx/persistent-shader-cache.h deleted file mode 100644 index 530d50a58..000000000 --- a/tools/gfx/persistent-shader-cache.h +++ /dev/null @@ -1,99 +0,0 @@ -// slang-shader-cache-index.h -#pragma once -#include "../../slang.h" -#include "../../slang-gfx.h" -#include "../../slang-com-ptr.h" - -#include "../../source/core/slang-string.h" -#include "../../source/core/slang-dictionary.h" -#include "../../source/core/slang-linked-list.h" -#include "../../source/core/slang-stream.h" -#include "../../source/core/slang-crypto.h" - -namespace gfx -{ - -using namespace Slang; - -using DigestType = MD5::Digest; - -struct ShaderCacheEntry -{ - DigestType dependencyBasedDigest; - DigestType contentsBasedDigest; - double lastAccessedTime; - - bool operator==(const ShaderCacheEntry& rhs) - { - return dependencyBasedDigest == rhs.dependencyBasedDigest - && contentsBasedDigest == rhs.contentsBasedDigest - && lastAccessedTime == rhs.lastAccessedTime; - } - - uint32_t getHashCode() - { - return dependencyBasedDigest.getHashCode(); - } -}; - -class PersistentShaderCache : public RefObject -{ -public: - PersistentShaderCache(const IDevice::ShaderCacheDesc& inDesc); - ~PersistentShaderCache(); - - // Fetch the cache entry corresponding to the provided key. If found, move the entry to - // the front of entries and return the entry and the corresponding compiled code in - // outCompiledCode. Else, return nullptr. - ShaderCacheEntry* findEntry(const DigestType& key, ISlangBlob** outCompiledCode); - - // Add an entry to the cache with the provided key and contents hashes. If - // adding an entry causes the cache to exceed size limitations, this will also - // delete the least recently used entry. - void addEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* compiledCode); - - // Update the contents hash for the specified entry in the cache and update the - // corresponding file on disk. - void updateEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* updatedCode); - -private: - // Load a previous cache index saved to disk. If not found, create a new cache index - // and save it to disk as filename. - void loadCacheFromFile(); - - // Delete the last entry (the least recently used) from entries, remove its key/value pair - // from keyToEntry, and remove the corresponding file on disk. Returns the index in 'entries' - // of the removed entry so addEntry() can overwrite the corresponding entry in 'entries' - // with the new entry. This should only be called by addEntry() when the cache reaches maximum capacity. - Index deleteLRUEntry(); - - // Without access to a physical file path, in-memory file systems cannot leverage file streams and - // need to fall back on a different implementation for loading and saving the cache to memory. - void loadCacheFromMemory(); - void saveCacheToMemory(); - - // The shader cache's description. - IDevice::ShaderCacheDesc desc; - - // The underlying file system used for the shader cache. - ComPtr<ISlangMutableFileSystem> mutableShaderCacheFileSystem = nullptr; - bool isMemoryFileSystem = false; - - // A file stream to the index file opened during cache load. This will only - // exist for a cache that exists on-disk. - FileStream indexStream; - - // Dictionary mapping each shader's key to its corresponding node (entry) in the - // linked list 'orderedEntries'. - Dictionary<DigestType, LinkedNode<Index>*> keyToEntry; - - // Linked list containing the corresponding indices in 'entries' for entries in the - // shader cache ordered from most to least recently used. - LinkedList<Index> orderedEntries; - - // List of entries in the shader cache. This list is not guaranteed to be in order of recency - // as the main and fall back implementations handle outputting to the file differently. - List<ShaderCacheEntry> entries; -}; - -} diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 3397b325e..4a8fd04b6 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -27,7 +27,7 @@ const Slang::Guid GfxGUID::IID_IResource = SLANG_UUID_IResource; const Slang::Guid GfxGUID::IID_IBufferResource = SLANG_UUID_IBufferResource; const Slang::Guid GfxGUID::IID_ITextureResource = SLANG_UUID_ITextureResource; const Slang::Guid GfxGUID::IID_IDevice = SLANG_UUID_IDevice; -const Slang::Guid GfxGUID::IID_IShaderCacheStatistics = SLANG_UUID_IShaderCacheStatistics; +const Slang::Guid GfxGUID::IID_IShaderCache = SLANG_UUID_IShaderCache; const Slang::Guid GfxGUID::IID_IShaderObject = SLANG_UUID_IShaderObject; const Slang::Guid GfxGUID::IID_IRenderPassLayout = SLANG_UUID_IRenderPassLayout; @@ -343,48 +343,19 @@ Result RendererBase::getEntryPointCodeFromShaderCache( return program->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); } - // Produce a string which we can use to query the shader cache by combining two separate hashes which - // together comprise all the compilation arguments for this program. - ComPtr<slang::ISession> session; - getSlangSession(session.writeRef()); - - ComPtr<ISlangBlob> shaderKeyBlob; - program->computeDependencyBasedHash(entryPointIndex, targetIndex, shaderKeyBlob.writeRef()); - DigestType shaderKey(shaderKeyBlob); - - // Produce a hash using the AST for this program - This is needed to check whether a cache entry is effectively dirty, - // or to save along with the compiled code into an entry so the entry can be checked if fetched later on. - ComPtr<ISlangBlob> contentsHashBlob; - program->computeContentsBasedHash(contentsHashBlob.writeRef()); - DigestType contentsHash(contentsHashBlob); + // Hash all relevant state for generating the entry point shader code to use as a key + // for the shader cache. + ComPtr<ISlangBlob> hashBlob; + program->getEntryPointHash(entryPointIndex, targetIndex, hashBlob.writeRef()); + PersistentCache::Key cacheKey(hashBlob); + // Query the shader cache. ComPtr<ISlangBlob> codeBlob; - - // Query the shader cache index for an entry with shaderKey as its key. - auto entry = persistentShaderCache->findEntry(shaderKey, codeBlob.writeRef()); - if (entry && contentsHash == entry->contentsBasedDigest) + if (persistentShaderCache->readEntry(cacheKey, codeBlob.writeRef()) != SLANG_OK) { - // We found the entry in the cache, and the entry's contents are up-to-date. Nothing else needs to be done. - shaderCacheHitCount++; - } - else - { - // There are two possibilities: the entry does not exist in the cache, or the entry's contents are out-of-date. - // Both will require calling getEntryPointCode() in order to fetch the correct compiled code, so we'll do that now. + // No cached entry found. Generate the code and add it to the cache. SLANG_RETURN_ON_FAIL(program->getEntryPointCode(entryPointIndex, targetIndex, codeBlob.writeRef(), outDiagnostics)); - - // If the entry was not found in the cache, let's add it. Otherwise, the entry's contents were out-of-date, so let's - // update the entry with the updated contents. - if (!entry) - { - persistentShaderCache->addEntry(shaderKey, contentsHash, codeBlob); - shaderCacheMissCount++; - } - else - { - persistentShaderCache->updateEntry(shaderKey, contentsHash, codeBlob); - shaderCacheEntryDirtyCount++; - } + persistentShaderCache->writeEntry(cacheKey, codeBlob); } *outCode = codeBlob.detach(); @@ -393,9 +364,10 @@ Result RendererBase::getEntryPointCodeFromShaderCache( SlangResult RendererBase::queryInterface(SlangUUID const& uuid, void** outObject) { - if (uuid == GfxGUID::IID_IShaderCacheStatistics) + // Only return the shader cache interface if it is enabled. + if (uuid == GfxGUID::IID_IShaderCache && persistentShaderCache) { - *outObject = static_cast<IShaderCacheStatistics*>(this); + *outObject = static_cast<IShaderCache*>(this); addRef(); return SLANG_OK; } @@ -413,12 +385,13 @@ IDevice* gfx::RendererBase::getInterface(const Guid& guid) SLANG_NO_THROW Result SLANG_MCALL RendererBase::initialize(const Desc& desc) { - auto cacheDesc = desc.shaderCache; - // We only want to initialize the shader cache if either a shader cache path or file system - // was provided. - if (cacheDesc.shaderCachePath || cacheDesc.shaderCacheFileSystem) + // We only want to initialize the shader cache if a shader cache path was provided. + if (desc.shaderCache.shaderCachePath) { - persistentShaderCache = new PersistentShaderCache(desc.shaderCache); + PersistentCache::Desc cacheDesc; + cacheDesc.directory = desc.shaderCache.shaderCachePath; + cacheDesc.maxEntryCount = desc.shaderCache.maxEntryCount; + persistentShaderCache = new PersistentCache(cacheDesc); } if (desc.apiCommandDispatcher) @@ -751,26 +724,31 @@ Result RendererBase::getShaderObjectLayout( return SLANG_OK; } -GfxCount RendererBase::getCacheMissCount() +Result RendererBase::clearShaderCache() { - return shaderCacheMissCount; + SLANG_ASSERT(persistentShaderCache); + return persistentShaderCache->clear(); } -GfxCount RendererBase::getCacheHitCount() +Result RendererBase::getShaderCacheStats(ShaderCacheStats* outStats) { - return shaderCacheHitCount; -} + SLANG_ASSERT(persistentShaderCache); + if (!outStats) + { + return SLANG_E_INVALID_ARG; + } -GfxCount RendererBase::getCacheEntryDirtyCount() -{ - return shaderCacheEntryDirtyCount; + const auto& stats = persistentShaderCache->getStats(); + outStats->entryCount = (GfxCount)stats.entryCount; + outStats->hitCount = (GfxCount)stats.hitCount; + outStats->missCount = (GfxCount)stats.missCount; + return SLANG_OK; } -Result RendererBase::resetCacheStatistics() +Result RendererBase::resetShaderCacheStats() { - shaderCacheMissCount = 0; - shaderCacheHitCount = 0; - shaderCacheEntryDirtyCount = 0; + SLANG_ASSERT(persistentShaderCache); + persistentShaderCache->resetStats(); return SLANG_OK; } diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index 01111e292..c7137f0fa 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -4,8 +4,7 @@ #include "slang-context.h" #include "core/slang-basic.h" #include "core/slang-com-object.h" - -#include "persistent-shader-cache.h" +#include "core/slang-persistent-cache.h" #include "resource-desc-utils.h" @@ -28,7 +27,7 @@ struct GfxGUID static const Slang::Guid IID_ITextureResource; static const Slang::Guid IID_IInputLayout; static const Slang::Guid IID_IDevice; - static const Slang::Guid IID_IShaderCacheStatistics; + static const Slang::Guid IID_IShaderCache; static const Slang::Guid IID_IShaderObjectLayout; static const Slang::Guid IID_IShaderObject; static const Slang::Guid IID_IRenderPassLayout; @@ -1214,7 +1213,7 @@ public: // Renderer implementation shared by all platforms. // Responsible for shader compilation, specialization and caching. -class RendererBase : public IDevice, public IShaderCacheStatistics, public Slang::ComObject +class RendererBase : public IDevice, public IShaderCache, public Slang::ComObject { friend class ShaderObjectBase; public: @@ -1354,27 +1353,21 @@ public: ShaderObjectLayoutBase* layout, IShaderObject** outObject) = 0; + public: + // IShaderCache interface + virtual SLANG_NO_THROW Result SLANG_MCALL clearShaderCache() SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getShaderCacheStats(ShaderCacheStats* outStats) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL resetShaderCacheStats() SLANG_OVERRIDE; + protected: virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc); protected: Slang::List<Slang::String> m_features; - -public: - virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheMissCount() override; - virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheHitCount() override; - virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheEntryDirtyCount() override; - virtual SLANG_NO_THROW Result SLANG_MCALL resetCacheStatistics() override; - -protected: - GfxCount shaderCacheMissCount = 0; - GfxCount shaderCacheHitCount = 0; - GfxCount shaderCacheEntryDirtyCount = 0; - public: SlangContext slangContext; ShaderCache shaderCache; - RefPtr<PersistentShaderCache> persistentShaderCache = nullptr; + Slang::RefPtr<Slang::PersistentCache> persistentShaderCache; Slang::Dictionary<slang::TypeLayoutReflection*, Slang::RefPtr<ShaderObjectLayoutBase>> m_shaderObjectLayoutCache; Slang::ComPtr<IPipelineCreationAPIDispatcher> m_pipelineCreationAPIDispatcher; |
