Extend --writeShaders to output SPIR-V
Changed the python script to operate on all shaders in the directory,
handling SPIR-V appropriately, and collating data across backends.
Made the output CSV, so that it imports into spreadsheets directly
(and handles missing columns cleanly).
Removed all the JSON digest logic - this was overkill at the moment,
and it made it tricky once we were combining information from GL and
Vulkan. Also, the hit count data was probably misleading - it didn't
count hits at the program cache level, just the persistent cache.
Change-Id: If354cde943c96f84e7bcc20a137afefca3b59358
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/207960
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/tools/gpu/MemoryCache.cpp b/tools/gpu/MemoryCache.cpp
index beef9ed..2cc4102 100644
--- a/tools/gpu/MemoryCache.cpp
+++ b/tools/gpu/MemoryCache.cpp
@@ -8,9 +8,11 @@
#include "GrPersistentCacheUtils.h"
#include "MemoryCache.h"
#include "SkBase64.h"
-#include "SkJSONWriter.h"
#include "SkMD5.h"
-#include "SkTHash.h"
+
+#if defined(SK_VULKAN)
+#include "vk/GrVkGpu.h"
+#endif
// Change this to 1 to log cache hits/misses/stores using SkDebugf.
#define LOG_MEMORY_CACHE 0
@@ -59,47 +61,53 @@
}
void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
- if (GrBackendApi::kOpenGL != api) {
- // TODO: Add SPIRV support, too.
+ if (GrBackendApi::kOpenGL != api && GrBackendApi::kVulkan != api) {
return;
}
- // Default extensions detected by the Mali Offline Compiler
- const char* extensions[kGrShaderTypeCount] = { "vert", "geom", "frag" };
-
- // For now, we only dump fragment shaders. They are the biggest factor in performance, and
- // the shaders for other stages tend to be heavily reused.
- SkString jsonPath = SkStringPrintf("%s/%s.json", path, extensions[kFragment_GrShaderType]);
- SkFILEWStream jsonFile(jsonPath.c_str());
- SkJSONWriter writer(&jsonFile, SkJSONWriter::Mode::kPretty);
- writer.beginArray();
-
for (auto it = fMap.begin(); it != fMap.end(); ++it) {
SkMD5 hash;
- hash.write(it->first.fKey->bytes(), it->first.fKey->size());
+ size_t bytesToHash = it->first.fKey->size();
+#if defined(SK_VULKAN)
+ if (GrBackendApi::kVulkan == api) {
+ // Vulkan stores two kinds of data in the cache (shaders and pipelines). The last four
+ // bytes of the key identify which one we have. We only want to extract shaders.
+ // Additionally, we don't want to hash the tag bytes, so we get the same keys as GL,
+ // which is good for cross-checking code generation and performance.
+ GrVkGpu::PersistentCacheKeyType vkKeyType;
+ SkASSERT(bytesToHash >= sizeof(vkKeyType));
+ bytesToHash -= sizeof(vkKeyType);
+ memcpy(&vkKeyType, it->first.fKey->bytes() + bytesToHash, sizeof(vkKeyType));
+ if (vkKeyType != GrVkGpu::kShader_PersistentCacheKeyType) {
+ continue;
+ }
+ }
+#endif
+ hash.write(it->first.fKey->bytes(), bytesToHash);
SkMD5::Digest digest = hash.finish();
SkString md5;
for (int i = 0; i < 16; ++i) {
md5.appendf("%02x", digest.data[i]);
}
- // Write [ hash, hitCount ] to JSON digest
- writer.beginArray(nullptr, false);
- writer.appendString(md5.c_str());
- writer.appendS32(it->second.fHitCount);
- writer.endArray();
+ SkSL::Program::Inputs inputsIgnored[kGrShaderTypeCount];
+ SkSL::String shaders[kGrShaderTypeCount];
+ const SkData* data = it->second.fData.get();
+ const char* ext;
+ if (GrBackendApi::kOpenGL == api) {
+ ext = "frag";
+ GrPersistentCacheUtils::UnpackCachedGLSL(data, inputsIgnored, shaders);
+ } else if (GrBackendApi::kVulkan == api) {
+ // Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
+ // run glslang on the input.
+ ext = "spv";
+ GrPersistentCacheUtils::UnpackCachedSPIRV(data, shaders, inputsIgnored);
+ }
- SkSL::Program::Inputs inputsIgnored;
- SkSL::String glsl[kGrShaderTypeCount];
- GrPersistentCacheUtils::UnpackCachedGLSL(it->second.fData.get(), &inputsIgnored, glsl);
-
- SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(),
- extensions[kFragment_GrShaderType]);
+ SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
SkFILEWStream file(filename.c_str());
- file.write(glsl[kFragment_GrShaderType].c_str(), glsl[kFragment_GrShaderType].size());
+ file.write(shaders[kFragment_GrShaderType].c_str(), shaders[kFragment_GrShaderType].size());
}
-
- writer.endArray();
}
} // namespace sk_gpu_test