Store VkPipelineCache to ShaderCache
Store vulkan pipeline cache in ShaderCache. Avoid writing to disk
unless pipeline cache size has changed or there was a new shader
compilation.
Test: Ran app startup test. Ran Calc app.
Bug: 122659224
Change-Id: Ie54ea8f0ee9c87387c310b369b2350310e20fa13
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 562a3b2..1661905 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -23,6 +23,7 @@
#include "FileBlobCache.h"
#include "Properties.h"
#include "utils/TraceUtils.h"
+#include <GrContext.h>
namespace android {
namespace uirenderer {
@@ -168,6 +169,24 @@
const void* value = data.data();
BlobCache* bc = getBlobCacheLocked();
+ if (mInStoreVkPipelineInProgress) {
+ if (mOldPipelineCacheSize == -1) {
+ // Record the initial pipeline cache size stored in the file.
+ mOldPipelineCacheSize = bc->get(key.data(), keySize, nullptr, 0);
+ }
+ if (mNewPipelineCacheSize != -1 && mNewPipelineCacheSize == valueSize) {
+ // There has not been change in pipeline cache size. Stop trying to save.
+ mTryToStorePipelineCache = false;
+ return;
+ }
+ mNewPipelineCacheSize = valueSize;
+ } else {
+ mCacheDirty = true;
+ // If there are new shaders compiled, we probably have new pipeline state too.
+ // Store pipeline cache on the next flush.
+ mNewPipelineCacheSize = -1;
+ mTryToStorePipelineCache = true;
+ }
bc->set(key.data(), keySize, value, valueSize);
if (!mSavePending && mDeferredSaveDelay > 0) {
@@ -175,12 +194,31 @@
std::thread deferredSaveThread([this]() {
sleep(mDeferredSaveDelay);
std::lock_guard<std::mutex> lock(mMutex);
- saveToDiskLocked();
+ // Store file on disk if there a new shader or Vulkan pipeline cache size changed.
+ if (mCacheDirty || mNewPipelineCacheSize != mOldPipelineCacheSize) {
+ saveToDiskLocked();
+ mOldPipelineCacheSize = mNewPipelineCacheSize;
+ mTryToStorePipelineCache = false;
+ mCacheDirty = false;
+ }
});
deferredSaveThread.detach();
}
}
+void ShaderCache::onVkFrameFlushed(GrContext* context) {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (!mInitialized || !mTryToStorePipelineCache) {
+ return;
+ }
+ }
+ mInStoreVkPipelineInProgress = true;
+ context->storeVkPipelineCacheData();
+ mInStoreVkPipelineInProgress = false;
+}
+
} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index d41aadb..0898017 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -75,6 +75,13 @@
*/
void store(const SkData& key, const SkData& data) override;
+ /**
+ * "onVkFrameFlushed" tries to store Vulkan pipeline cache state.
+ * Pipeline cache is saved on disk only if the size of the data has changed or there was
+ * a new shader compiled.
+ */
+ void onVkFrameFlushed(GrContext* context);
+
private:
// Creation and (the lack of) destruction is handled internally.
ShaderCache();
@@ -167,6 +174,33 @@
mutable std::mutex mMutex;
/**
+ * If set to "true", the next call to onVkFrameFlushed, will invoke
+ * GrCanvas::storeVkPipelineCacheData. This does not guarantee that data will be stored on disk.
+ */
+ bool mTryToStorePipelineCache = true;
+
+ /**
+ * This flag is used by "ShaderCache::store" to distinguish between shader data and
+ * Vulkan pipeline data.
+ */
+ bool mInStoreVkPipelineInProgress = false;
+
+ /**
+ * "mNewPipelineCacheSize" has the size of the new Vulkan pipeline cache data. It is used
+ * to prevent unnecessary disk writes, if the pipeline cache size has not changed.
+ */
+ size_t mNewPipelineCacheSize = -1;
+ /**
+ * "mOldPipelineCacheSize" has the size of the Vulkan pipeline cache data stored on disk.
+ */
+ size_t mOldPipelineCacheSize = -1;
+
+ /**
+ * "mCacheDirty" is true when there is new shader cache data, which is not saved to disk.
+ */
+ bool mCacheDirty = false;
+
+ /**
* "sCache" is the singleton ShaderCache object.
*/
static ShaderCache sCache;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 1d3a244..b9aae98 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -23,6 +23,7 @@
#include "VkInteropFunctorDrawable.h"
#include "renderstate/RenderState.h"
#include "renderthread/Frame.h"
+#include "ShaderCache.h"
#include <SkSurface.h>
#include <SkTypes.h>
@@ -73,6 +74,7 @@
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer);
+ ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
layerUpdateQueue->clear();
// Draw visual debugging features