summaryrefslogtreecommitdiffstats
path: root/tools/gfx/renderer-shared.cpp
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-10-19 09:36:41 -0700
committerGitHub <noreply@github.com>2022-10-19 09:36:41 -0700
commitdec930150f42a22892e567c769a1c9e24e761fde (patch)
tree92eea81e0c5d08c2c5ff090e7ebb0c2030648912 /tools/gfx/renderer-shared.cpp
parent8add41a6e37994577d928bc312801ddfa1c33173 (diff)
PersistentShaderCache integration (#2453)
* Shader cache index integrated into RendererBase; Added test for cache eviction policy (which currently does not pass) * Restructured main if block in getEntryPointCodeFromShaderCache; Post-rebase cleanup * undo local testing only change * Fixed issues causing shader cache tests to fail * Edited gfx.slang to reflect structural changes to IDevice::Desc and to include ShaderCacheDesc; Modified how the cache is reading in the file from disk; Added a check to the cache eviction policy test that checks for correct order of entries in the cache as well as eight total expected output files for D3D12 and Vulkan * Removed line in gfx-unit-test.cpp for local testing * Edited .gitignore to ignore all shaders automatically generated by the shader cache tests and removed the test shaders that were previously added; Review changes, most notably with an overhaul of how the cache eviction policy test handles checking order of entries * Ran premake; Removed local testing specific line (again) * Removed expected comparison files from earlier commit; Ran premake * Edited premake5.lua to also ignore the auto-generated shader files from specific shader cache tests * Fixed weird indent in premake5.lua
Diffstat (limited to 'tools/gfx/renderer-shared.cpp')
-rw-r--r--tools/gfx/renderer-shared.cpp111
1 files changed, 28 insertions, 83 deletions
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp
index 48cd6907f..c7d7933a3 100644
--- a/tools/gfx/renderer-shared.cpp
+++ b/tools/gfx/renderer-shared.cpp
@@ -351,11 +351,8 @@ Result RendererBase::getEntryPointCodeFromShaderCache(
slang::IBlob** outCode,
slang::IBlob** outDiagnostics)
{
- // TODO: Need a way in filesystem to query both file size and file creation time, if cache size exceeds
- // specified maximum size (in bytes or files) then delete oldest files - cache eviction policy
-
- // Immediately call getEntryPointCode if no shader cache was provided on initialization
- if (!shaderCacheFileSystem)
+ // Immediately call getEntryPointCode if no shader cache has been initialized
+ if (!persistentShaderCache)
{
return program->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics);
}
@@ -365,75 +362,40 @@ Result RendererBase::getEntryPointCodeFromShaderCache(
ComPtr<slang::ISession> session;
getSlangSession(session.writeRef());
- slang::Digest shaderKeyHash;
- program->computeDependencyBasedHash(entryPointIndex, targetIndex, &shaderKeyHash);
-
- String shaderKey = DigestUtil::toString(shaderKeyHash);
+ slang::Digest shaderKey;
+ program->computeDependencyBasedHash(entryPointIndex, targetIndex, &shaderKey);
// 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.
- slang::Digest ASTHash;
- program->computeASTBasedHash(&ASTHash);
-
+ slang::Digest contentsHash;
+ program->computeASTBasedHash(&contentsHash);
+
ComPtr<ISlangBlob> codeBlob;
- // Query shaderCacheFileSystem for an entry whose key matches shaderFilename
- // - If we find it, then copy the file contents into memory and return in outCode
- auto result = shaderCacheFileSystem->loadFile(shaderKey.getBuffer(), codeBlob.writeRef());
-
- if (SLANG_FAILED(result))
+ // Query the shader cache index for an entry with shaderKey as its key.
+ auto entry = persistentShaderCache->findEntry(shaderKey, codeBlob.writeRef());
+ if (entry && contentsHash == entry->Value.astBasedDigest)
{
- // If we didn't find it, call program->getEntryPointCode() to get and return the code. We also
- // make sure to save a new entry in the shader cache.
- if (SLANG_SUCCEEDED(program->getEntryPointCode(entryPointIndex, targetIndex, codeBlob.writeRef(), outDiagnostics)))
- {
- if (mutableShaderCacheFileSystem)
- {
- updateCacheEntry(mutableShaderCacheFileSystem, codeBlob, shaderKey, ASTHash);
- }
-
- shaderCacheMissCount++;
- }
- else
- {
- // If getEntryPointCode() failed to fetch the code, we return SLANG_FAIL along with the diagnostics output
- // in outDiagnostics.
- return SLANG_FAIL;
- }
+ // We found the entry in the cache, and the entry's contents are up-to-date. Nothing else needs to be done.
+ shaderCacheHitCount++;
}
else
{
- // If the entry exists, we need to check that the entry isn't effectively dirty. Since we stored
- // the AST hash with the compiled code, we can determine this by comparing the stored hash with the
- // AST hash generated earlier.
- auto entryContents = codeBlob->getBufferPointer();
- auto hashSize = sizeof(slang::Digest);
- if (memcmp(ASTHash.values, entryContents, hashSize) != 0)
- {
- // The AST hash stored in the entry does not match the AST hash generated earlier, indicating
- // that the shader code has changed and the entry needs to be updated.
- if (SLANG_SUCCEEDED(program->getEntryPointCode(entryPointIndex, targetIndex, codeBlob.writeRef(), outDiagnostics)))
- {
- if (mutableShaderCacheFileSystem)
- {
- updateCacheEntry(mutableShaderCacheFileSystem, codeBlob, shaderKey, ASTHash);
- }
+ // 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.
+ SLANG_RETURN_ON_FAIL(program->getEntryPointCode(entryPointIndex, targetIndex, codeBlob.writeRef(), outDiagnostics));
- shaderCacheEntryDirtyCount++;
- }
- else
- {
- // If getEntryPointCode() failed to fetch the code, we return SLANG_FAIL along with the diagnostics output
- // in outDiagnostics.
- return SLANG_FAIL;
- }
+ // 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
{
- auto compiledCode = RawBlob::create((uint8_t*)codeBlob->getBufferPointer() + hashSize, codeBlob->getBufferSize() - hashSize);
- codeBlob = compiledCode;
-
- shaderCacheHitCount++;
+ persistentShaderCache->updateEntry(entry, shaderKey, contentsHash, codeBlob);
+ shaderCacheEntryDirtyCount++;
}
}
@@ -463,29 +425,12 @@ IDevice* gfx::RendererBase::getInterface(const Guid& guid)
SLANG_NO_THROW Result SLANG_MCALL RendererBase::initialize(const Desc& desc)
{
- // TODO: This logic for initalizing the shader cache has been replicated inside
- // the constructor for ShaderCacheIndex. Remove when ShaderCacheIndex is integrated in.
-
- // If a shader cache file system was provided, use the provided system.
- if (desc.shaderCacheFileSystem)
- {
- shaderCacheFileSystem = desc.shaderCacheFileSystem;
- }
- if (desc.shaderCachePath)
- {
- // Only a path was provided, create a RelativeFileSystem using the path
- if (!shaderCacheFileSystem)
- {
- shaderCacheFileSystem = OSFileSystem::getMutableSingleton();
- }
- shaderCacheFileSystem = new RelativeFileSystem(shaderCacheFileSystem, desc.shaderCachePath);
- }
-
- // If we initialized a file system for the shader cache, check if it's mutable. If so, store a pointer
- // to the mutable version in order to save new entries later.
- if (shaderCacheFileSystem)
+ 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)
{
- shaderCacheFileSystem->queryInterface(ISlangMutableFileSystem::getTypeGuid(), (void**)mutableShaderCacheFileSystem.writeRef());
+ persistentShaderCache = new PersistentShaderCache(desc.shaderCache);
}
if (desc.apiCommandDispatcher)