summaryrefslogtreecommitdiff
path: root/tools/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx')
-rw-r--r--tools/gfx/gfx.slang24
-rw-r--r--tools/gfx/persistent-shader-cache.cpp316
-rw-r--r--tools/gfx/persistent-shader-cache.h99
-rw-r--r--tools/gfx/renderer-shared.cpp94
-rw-r--r--tools/gfx/renderer-shared.h27
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;