diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2022-10-19 09:36:41 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-19 09:36:41 -0700 |
| commit | dec930150f42a22892e567c769a1c9e24e761fde (patch) | |
| tree | 92eea81e0c5d08c2c5ff090e7ebb0c2030648912 /tools/gfx/renderer-shared.cpp | |
| parent | 8add41a6e37994577d928bc312801ddfa1c33173 (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.cpp | 111 |
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) |
