Loading graphics/java/android/graphics/HardwareRenderer.java +9 −5 Original line number Diff line number Diff line Loading @@ -182,8 +182,9 @@ public class HardwareRenderer { /** * Name of the file that holds the shaders cache. */ private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache"; private static final String CACHE_PATH_OPENGL_SHADERS = "com.android.opengl.shaders_cache"; private static final String CACHE_PATH_SKIA_SHADERS = "com.android.skia.shaders_cache"; private static final String CACHE_PATH_SKIA_PIPELINES = "com.android.skia.pipelines_cache"; private static int sDensityDpi = 0; Loading Loading @@ -1296,8 +1297,10 @@ public class HardwareRenderer { * @hide */ public static void setupDiskCache(File cacheDir) { setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath()); setupPersistentGraphicsCache( new File(cacheDir, CACHE_PATH_OPENGL_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIA_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIA_PIPELINES).getAbsolutePath()); } /** @hide */ Loading Loading @@ -1595,7 +1598,8 @@ public class HardwareRenderer { protected static native boolean isWebViewOverlaysEnabled(); /** @hide */ protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile); protected static native void setupPersistentGraphicsCache( String openglShaderCachePath, String skiaShaderCachePath, String skiaPipelineCachePath); private static native void nRotateProcessStatsBuffer(); Loading libs/hwui/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -664,6 +664,8 @@ cc_defaults { "pipeline/skia/ATraceMemoryDump.cpp", "pipeline/skia/GLFunctorDrawable.cpp", "pipeline/skia/LayerDrawable.cpp", "pipeline/skia/PersistentGraphicsCache.cpp", "pipeline/skia/PipelineCache.cpp", "pipeline/skia/ShaderCache.cpp", "pipeline/skia/SkiaGpuPipeline.cpp", "pipeline/skia/SkiaMemoryTracer.cpp", Loading Loading @@ -814,6 +816,8 @@ cc_test { "tests/unit/MatrixTests.cpp", "tests/unit/OpBufferTests.cpp", "tests/unit/PathInterpolatorTests.cpp", "tests/unit/PersistentGraphicsCacheTests.cpp", "tests/unit/PipelineCacheTests.cpp", "tests/unit/RenderEffectCapabilityQueryTests.cpp", "tests/unit/RenderNodeDrawableTests.cpp", "tests/unit/RenderNodeTests.cpp", Loading libs/hwui/jni/android_graphics_HardwareRenderer.cpp +20 −12 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <media/NdkImageReader.h> #include <nativehelper/JNIPlatformHelp.h> #ifdef __ANDROID__ #include <pipeline/skia/PersistentGraphicsCache.h> #include <pipeline/skia/ShaderCache.h> #include <private/EGL/cache.h> #endif Loading Loading @@ -945,19 +946,25 @@ static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass cla } // ---------------------------------------------------------------------------- // Shaders // Persistent graphics cache // ---------------------------------------------------------------------------- static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, jstring diskCachePath, jstring skiaDiskCachePath) { static void android_view_ThreadedRenderer_setupPersistentGraphicsCache( JNIEnv* env, jobject clazz, jstring openglShaderCachePath, jstring skiaShaderCachePath, jstring skiaPipelineCachePath) { #ifdef __ANDROID__ const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); android::egl_set_cache_filename(cacheArray); env->ReleaseStringUTFChars(diskCachePath, cacheArray); const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL); uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray); env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray); const char* openglShaderCachePathArray = env->GetStringUTFChars(openglShaderCachePath, NULL); android::egl_set_cache_filename(openglShaderCachePathArray); env->ReleaseStringUTFChars(openglShaderCachePath, openglShaderCachePathArray); const char* skiaShaderCachePathArray = env->GetStringUTFChars(skiaShaderCachePath, NULL); uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaShaderCachePathArray); env->ReleaseStringUTFChars(skiaShaderCachePath, skiaShaderCachePathArray); const char* skiaPipelineCachePathArray = env->GetStringUTFChars(skiaPipelineCachePath, NULL); uirenderer::skiapipeline::PersistentGraphicsCache::get().initPipelineCache( skiaPipelineCachePathArray); env->ReleaseStringUTFChars(skiaPipelineCachePath, skiaPipelineCachePathArray); #endif } Loading Loading @@ -1025,8 +1032,9 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_dumpProfileInfo}, {"nDumpGlobalProfileInfo", "(Ljava/io/FileDescriptor;I)V", (void*)android_view_ThreadedRenderer_dumpGlobalProfileInfo}, {"setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)android_view_ThreadedRenderer_setupShadersDiskCache}, {"setupPersistentGraphicsCache", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void*)android_view_ThreadedRenderer_setupPersistentGraphicsCache}, {"nAddRenderNode", "(JJZ)V", (void*)android_view_ThreadedRenderer_addRenderNode}, {"nRemoveRenderNode", "(JJ)V", (void*)android_view_ThreadedRenderer_removeRenderNode}, {"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode}, Loading libs/hwui/pipeline/skia/PersistentGraphicsCache.cpp 0 → 100644 +156 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PersistentGraphicsCache.h" #include <SkData.h> #include <SkRefCnt.h> #include <SkString.h> #include <ganesh/GrDirectContext.h> #include <log/log.h> #include <cstddef> #include <memory> #include <string> #include <utility> #include "Properties.h" #include "ShaderCache.h" #ifdef __linux__ #include <com_android_graphics_hwui_flags.h> namespace hwui_flags = com::android::graphics::hwui::flags; #else // __linux__ namespace hwui_flags { constexpr bool separate_pipeline_cache() { return false; } } // namespace hwui_flags #endif // __linux__ namespace { constexpr size_t kMaxPipelineSizeBytes = 2 * 1024 * 1024; } // namespace namespace android { namespace uirenderer { namespace skiapipeline { PersistentGraphicsCache& PersistentGraphicsCache::get() { static PersistentGraphicsCache cache; return cache; } void PersistentGraphicsCache::initPipelineCache(std::string path, useconds_t writeThrottleInterval) { if (!hwui_flags::separate_pipeline_cache()) { return; } mPipelineCache = std::make_unique<PipelineCache>(std::move(path), writeThrottleInterval); } void PersistentGraphicsCache::onVkFrameFlushed(GrDirectContext* context) { class RealGrDirectContext : public GrDirectContextWrapper { private: GrDirectContext* mContext; public: RealGrDirectContext(GrDirectContext* context) : mContext(context) {} bool canDetectNewVkPipelineCacheData() const override { return mContext->canDetectNewVkPipelineCacheData(); } bool hasNewVkPipelineCacheData() const override { return mContext->hasNewVkPipelineCacheData(); } void storeVkPipelineCacheData(size_t maxSize) override { return mContext->storeVkPipelineCacheData(maxSize); } GrDirectContext* unwrap() const override { return mContext; } }; RealGrDirectContext wrapper(context); onVkFrameFlushed(&wrapper); } void PersistentGraphicsCache::onVkFrameFlushed(GrDirectContextWrapper* context) { if (!hwui_flags::separate_pipeline_cache()) { ShaderCache::get().onVkFrameFlushed(context->unwrap()); return; } mCanDetectNewVkPipelineCacheData = context->canDetectNewVkPipelineCacheData(); if (context->hasNewVkPipelineCacheData()) { context->storeVkPipelineCacheData(kMaxPipelineSizeBytes); } } sk_sp<SkData> PersistentGraphicsCache::load(const SkData& key) { if (!hwui_flags::separate_pipeline_cache()) { return ShaderCache::get().load(key); } if (mPipelineCache == nullptr) { LOG_ALWAYS_FATAL( "PersistentGraphicsCache::load: pipeline cache path was not initialized, aborting " "load"); return nullptr; } auto data = mPipelineCache->tryLoad(key); if (data != nullptr) { return data; } return ShaderCache::get().load(key); } void PersistentGraphicsCache::store(const SkData& key, const SkData& data, const SkString& description) { if (!hwui_flags::separate_pipeline_cache()) { ShaderCache::get().store(key, data, description); return; } if (mPipelineCache == nullptr) { LOG_ALWAYS_FATAL( "PersistentGraphicsCache::store: pipeline cache path was not initialized, aborting " "store"); return; } if (mPipelineCache->canStore(description)) { if (mCanDetectNewVkPipelineCacheData) { mPipelineCache->store(key, data); } else if (mLastPipelineCacheSize != data.size()) { mPipelineCache->store(key, data); mLastPipelineCacheSize = data.size(); } return; } ShaderCache::get().store(key, data, description); } } // namespace skiapipeline } // namespace uirenderer } // namespace android libs/hwui/pipeline/skia/PersistentGraphicsCache.h 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <ganesh/GrContextOptions.h> #include <ganesh/GrDirectContext.h> #include <sys/types.h> #include <cstddef> #include <memory> #include <string> #include "PipelineCache.h" namespace android { namespace uirenderer { namespace skiapipeline { // Delegate persistent cache operations to either the pipeline cache or the shader cache as // appropriate class PersistentGraphicsCache : public GrContextOptions::PersistentCache { static constexpr useconds_t kDefaultWriteThrottleInterval = 4 * 1000 * 1000; public: static PersistentGraphicsCache& get(); void initPipelineCache(std::string path, useconds_t writeThrottleInterval = kDefaultWriteThrottleInterval); void onVkFrameFlushed(GrDirectContext* context); sk_sp<SkData> load(const SkData& key) override; void store(const SkData& key, const SkData& data, const SkString& description) override; private: std::unique_ptr<PipelineCache> mPipelineCache; // Workarounds for devices without VK_EXT_pipeline_creation_cache_control bool mCanDetectNewVkPipelineCacheData; size_t mLastPipelineCacheSize; // Unit test infrastructure class GrDirectContextWrapper { public: virtual ~GrDirectContextWrapper() = default; virtual bool canDetectNewVkPipelineCacheData() const = 0; virtual bool hasNewVkPipelineCacheData() const = 0; virtual void storeVkPipelineCacheData(size_t maxSize) = 0; virtual GrDirectContext* unwrap() const = 0; }; void onVkFrameFlushed(GrDirectContextWrapper* context); friend class PersistentGraphicsCacheTestUtils; }; } // namespace skiapipeline } // namespace uirenderer } // namespace android Loading
graphics/java/android/graphics/HardwareRenderer.java +9 −5 Original line number Diff line number Diff line Loading @@ -182,8 +182,9 @@ public class HardwareRenderer { /** * Name of the file that holds the shaders cache. */ private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache"; private static final String CACHE_PATH_OPENGL_SHADERS = "com.android.opengl.shaders_cache"; private static final String CACHE_PATH_SKIA_SHADERS = "com.android.skia.shaders_cache"; private static final String CACHE_PATH_SKIA_PIPELINES = "com.android.skia.pipelines_cache"; private static int sDensityDpi = 0; Loading Loading @@ -1296,8 +1297,10 @@ public class HardwareRenderer { * @hide */ public static void setupDiskCache(File cacheDir) { setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath()); setupPersistentGraphicsCache( new File(cacheDir, CACHE_PATH_OPENGL_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIA_SHADERS).getAbsolutePath(), new File(cacheDir, CACHE_PATH_SKIA_PIPELINES).getAbsolutePath()); } /** @hide */ Loading Loading @@ -1595,7 +1598,8 @@ public class HardwareRenderer { protected static native boolean isWebViewOverlaysEnabled(); /** @hide */ protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile); protected static native void setupPersistentGraphicsCache( String openglShaderCachePath, String skiaShaderCachePath, String skiaPipelineCachePath); private static native void nRotateProcessStatsBuffer(); Loading
libs/hwui/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -664,6 +664,8 @@ cc_defaults { "pipeline/skia/ATraceMemoryDump.cpp", "pipeline/skia/GLFunctorDrawable.cpp", "pipeline/skia/LayerDrawable.cpp", "pipeline/skia/PersistentGraphicsCache.cpp", "pipeline/skia/PipelineCache.cpp", "pipeline/skia/ShaderCache.cpp", "pipeline/skia/SkiaGpuPipeline.cpp", "pipeline/skia/SkiaMemoryTracer.cpp", Loading Loading @@ -814,6 +816,8 @@ cc_test { "tests/unit/MatrixTests.cpp", "tests/unit/OpBufferTests.cpp", "tests/unit/PathInterpolatorTests.cpp", "tests/unit/PersistentGraphicsCacheTests.cpp", "tests/unit/PipelineCacheTests.cpp", "tests/unit/RenderEffectCapabilityQueryTests.cpp", "tests/unit/RenderNodeDrawableTests.cpp", "tests/unit/RenderNodeTests.cpp", Loading
libs/hwui/jni/android_graphics_HardwareRenderer.cpp +20 −12 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <media/NdkImageReader.h> #include <nativehelper/JNIPlatformHelp.h> #ifdef __ANDROID__ #include <pipeline/skia/PersistentGraphicsCache.h> #include <pipeline/skia/ShaderCache.h> #include <private/EGL/cache.h> #endif Loading Loading @@ -945,19 +946,25 @@ static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass cla } // ---------------------------------------------------------------------------- // Shaders // Persistent graphics cache // ---------------------------------------------------------------------------- static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, jstring diskCachePath, jstring skiaDiskCachePath) { static void android_view_ThreadedRenderer_setupPersistentGraphicsCache( JNIEnv* env, jobject clazz, jstring openglShaderCachePath, jstring skiaShaderCachePath, jstring skiaPipelineCachePath) { #ifdef __ANDROID__ const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); android::egl_set_cache_filename(cacheArray); env->ReleaseStringUTFChars(diskCachePath, cacheArray); const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL); uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray); env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray); const char* openglShaderCachePathArray = env->GetStringUTFChars(openglShaderCachePath, NULL); android::egl_set_cache_filename(openglShaderCachePathArray); env->ReleaseStringUTFChars(openglShaderCachePath, openglShaderCachePathArray); const char* skiaShaderCachePathArray = env->GetStringUTFChars(skiaShaderCachePath, NULL); uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaShaderCachePathArray); env->ReleaseStringUTFChars(skiaShaderCachePath, skiaShaderCachePathArray); const char* skiaPipelineCachePathArray = env->GetStringUTFChars(skiaPipelineCachePath, NULL); uirenderer::skiapipeline::PersistentGraphicsCache::get().initPipelineCache( skiaPipelineCachePathArray); env->ReleaseStringUTFChars(skiaPipelineCachePath, skiaPipelineCachePathArray); #endif } Loading Loading @@ -1025,8 +1032,9 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_dumpProfileInfo}, {"nDumpGlobalProfileInfo", "(Ljava/io/FileDescriptor;I)V", (void*)android_view_ThreadedRenderer_dumpGlobalProfileInfo}, {"setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)android_view_ThreadedRenderer_setupShadersDiskCache}, {"setupPersistentGraphicsCache", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void*)android_view_ThreadedRenderer_setupPersistentGraphicsCache}, {"nAddRenderNode", "(JJZ)V", (void*)android_view_ThreadedRenderer_addRenderNode}, {"nRemoveRenderNode", "(JJ)V", (void*)android_view_ThreadedRenderer_removeRenderNode}, {"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode}, Loading
libs/hwui/pipeline/skia/PersistentGraphicsCache.cpp 0 → 100644 +156 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PersistentGraphicsCache.h" #include <SkData.h> #include <SkRefCnt.h> #include <SkString.h> #include <ganesh/GrDirectContext.h> #include <log/log.h> #include <cstddef> #include <memory> #include <string> #include <utility> #include "Properties.h" #include "ShaderCache.h" #ifdef __linux__ #include <com_android_graphics_hwui_flags.h> namespace hwui_flags = com::android::graphics::hwui::flags; #else // __linux__ namespace hwui_flags { constexpr bool separate_pipeline_cache() { return false; } } // namespace hwui_flags #endif // __linux__ namespace { constexpr size_t kMaxPipelineSizeBytes = 2 * 1024 * 1024; } // namespace namespace android { namespace uirenderer { namespace skiapipeline { PersistentGraphicsCache& PersistentGraphicsCache::get() { static PersistentGraphicsCache cache; return cache; } void PersistentGraphicsCache::initPipelineCache(std::string path, useconds_t writeThrottleInterval) { if (!hwui_flags::separate_pipeline_cache()) { return; } mPipelineCache = std::make_unique<PipelineCache>(std::move(path), writeThrottleInterval); } void PersistentGraphicsCache::onVkFrameFlushed(GrDirectContext* context) { class RealGrDirectContext : public GrDirectContextWrapper { private: GrDirectContext* mContext; public: RealGrDirectContext(GrDirectContext* context) : mContext(context) {} bool canDetectNewVkPipelineCacheData() const override { return mContext->canDetectNewVkPipelineCacheData(); } bool hasNewVkPipelineCacheData() const override { return mContext->hasNewVkPipelineCacheData(); } void storeVkPipelineCacheData(size_t maxSize) override { return mContext->storeVkPipelineCacheData(maxSize); } GrDirectContext* unwrap() const override { return mContext; } }; RealGrDirectContext wrapper(context); onVkFrameFlushed(&wrapper); } void PersistentGraphicsCache::onVkFrameFlushed(GrDirectContextWrapper* context) { if (!hwui_flags::separate_pipeline_cache()) { ShaderCache::get().onVkFrameFlushed(context->unwrap()); return; } mCanDetectNewVkPipelineCacheData = context->canDetectNewVkPipelineCacheData(); if (context->hasNewVkPipelineCacheData()) { context->storeVkPipelineCacheData(kMaxPipelineSizeBytes); } } sk_sp<SkData> PersistentGraphicsCache::load(const SkData& key) { if (!hwui_flags::separate_pipeline_cache()) { return ShaderCache::get().load(key); } if (mPipelineCache == nullptr) { LOG_ALWAYS_FATAL( "PersistentGraphicsCache::load: pipeline cache path was not initialized, aborting " "load"); return nullptr; } auto data = mPipelineCache->tryLoad(key); if (data != nullptr) { return data; } return ShaderCache::get().load(key); } void PersistentGraphicsCache::store(const SkData& key, const SkData& data, const SkString& description) { if (!hwui_flags::separate_pipeline_cache()) { ShaderCache::get().store(key, data, description); return; } if (mPipelineCache == nullptr) { LOG_ALWAYS_FATAL( "PersistentGraphicsCache::store: pipeline cache path was not initialized, aborting " "store"); return; } if (mPipelineCache->canStore(description)) { if (mCanDetectNewVkPipelineCacheData) { mPipelineCache->store(key, data); } else if (mLastPipelineCacheSize != data.size()) { mPipelineCache->store(key, data); mLastPipelineCacheSize = data.size(); } return; } ShaderCache::get().store(key, data, description); } } // namespace skiapipeline } // namespace uirenderer } // namespace android
libs/hwui/pipeline/skia/PersistentGraphicsCache.h 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <ganesh/GrContextOptions.h> #include <ganesh/GrDirectContext.h> #include <sys/types.h> #include <cstddef> #include <memory> #include <string> #include "PipelineCache.h" namespace android { namespace uirenderer { namespace skiapipeline { // Delegate persistent cache operations to either the pipeline cache or the shader cache as // appropriate class PersistentGraphicsCache : public GrContextOptions::PersistentCache { static constexpr useconds_t kDefaultWriteThrottleInterval = 4 * 1000 * 1000; public: static PersistentGraphicsCache& get(); void initPipelineCache(std::string path, useconds_t writeThrottleInterval = kDefaultWriteThrottleInterval); void onVkFrameFlushed(GrDirectContext* context); sk_sp<SkData> load(const SkData& key) override; void store(const SkData& key, const SkData& data, const SkString& description) override; private: std::unique_ptr<PipelineCache> mPipelineCache; // Workarounds for devices without VK_EXT_pipeline_creation_cache_control bool mCanDetectNewVkPipelineCacheData; size_t mLastPipelineCacheSize; // Unit test infrastructure class GrDirectContextWrapper { public: virtual ~GrDirectContextWrapper() = default; virtual bool canDetectNewVkPipelineCacheData() const = 0; virtual bool hasNewVkPipelineCacheData() const = 0; virtual void storeVkPipelineCacheData(size_t maxSize) = 0; virtual GrDirectContext* unwrap() const = 0; }; void onVkFrameFlushed(GrDirectContextWrapper* context); friend class PersistentGraphicsCacheTestUtils; }; } // namespace skiapipeline } // namespace uirenderer } // namespace android