Add gltestpersistentcache config that tests GrContextOption's cache.
Uses a new GPU sink that runs each test twice, once to populate the cache and then again with a new GrContext but a warmed cache. It verifies that the two generated images are the same. Change-Id: Iaba195a69751f14ea946afe7174228a813b83a63 Reviewed-on: https://skia-review.googlesource.com/140567 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
ba38320804
commit
00a5eb8c12
2
BUILD.gn
2
BUILD.gn
@ -1239,6 +1239,8 @@ if (skia_enable_tools) {
|
||||
sources = [
|
||||
"tools/gpu/GrContextFactory.cpp",
|
||||
"tools/gpu/GrTest.cpp",
|
||||
"tools/gpu/MemoryCache.cpp",
|
||||
"tools/gpu/MemoryCache.h",
|
||||
"tools/gpu/ProxyUtils.cpp",
|
||||
"tools/gpu/TestContext.cpp",
|
||||
"tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp",
|
||||
|
@ -862,11 +862,18 @@ static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLi
|
||||
return nullptr;
|
||||
}
|
||||
if (gpuConfig->getTestThreading()) {
|
||||
SkASSERT(!gpuConfig->getTestPersistentCache());
|
||||
return new GPUThreadTestingSink(
|
||||
contextType, contextOverrides, gpuConfig->getSurfType(),
|
||||
gpuConfig->getSamples(), gpuConfig->getUseDIText(),
|
||||
gpuConfig->getColorType(), gpuConfig->getAlphaType(),
|
||||
sk_ref_sp(gpuConfig->getColorSpace()), FLAGS_gpu_threading, grCtxOptions);
|
||||
} else if (gpuConfig->getTestPersistentCache()) {
|
||||
return new GPUPersistentCacheTestingSink(
|
||||
contextType, contextOverrides, gpuConfig->getSurfType(),
|
||||
gpuConfig->getSamples(), gpuConfig->getUseDIText(),
|
||||
gpuConfig->getColorType(), gpuConfig->getAlphaType(),
|
||||
sk_ref_sp(gpuConfig->getColorSpace()), FLAGS_gpu_threading, grCtxOptions);
|
||||
} else {
|
||||
return new GPUSink(contextType, contextOverrides, gpuConfig->getSurfType(),
|
||||
gpuConfig->getSamples(), gpuConfig->getUseDIText(),
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "../src/jumper/SkJumper.h"
|
||||
#include "DDLPromiseImageHelper.h"
|
||||
#include "DDLTileHelper.h"
|
||||
#include "GrBackendSurface.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpu.h"
|
||||
#include "MemoryCache.h"
|
||||
#include "Resources.h"
|
||||
#include "SkAndroidCodec.h"
|
||||
#include "SkAutoMalloc.h"
|
||||
@ -75,10 +79,6 @@
|
||||
|
||||
#include "../third_party/skcms/skcms.h"
|
||||
|
||||
#include "GrBackendSurface.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpu.h"
|
||||
|
||||
DEFINE_bool(multiPage, false, "For document-type backends, render the source"
|
||||
" into multiple pages");
|
||||
DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");
|
||||
@ -1486,7 +1486,12 @@ Error GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
|
||||
const GrContextOptions& baseOptions) const {
|
||||
GrContextOptions grOptions = baseOptions;
|
||||
|
||||
// We don't expect the src to mess with the persistent cache or the executor.
|
||||
SkDEBUGCODE(auto cache = grOptions.fPersistentCache);
|
||||
SkDEBUGCODE(auto exec = grOptions.fExecutor);
|
||||
src.modifyGrContextOptions(&grOptions);
|
||||
SkASSERT(cache == grOptions.fPersistentCache);
|
||||
SkASSERT(exec == grOptions.fExecutor);
|
||||
|
||||
GrContextFactory factory(grOptions);
|
||||
const SkISize size = src.size();
|
||||
@ -1617,6 +1622,47 @@ Error GPUThreadTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStre
|
||||
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||
|
||||
GPUPersistentCacheTestingSink::GPUPersistentCacheTestingSink(
|
||||
GrContextFactory::ContextType ct,
|
||||
GrContextFactory::ContextOverrides overrides,
|
||||
SkCommandLineConfigGpu::SurfType surfType,
|
||||
int samples,
|
||||
bool diText,
|
||||
SkColorType colorType,
|
||||
SkAlphaType alphaType,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
bool threaded,
|
||||
const GrContextOptions& grCtxOptions)
|
||||
: INHERITED(ct, overrides, surfType, samples, diText, colorType, alphaType,
|
||||
std::move(colorSpace), threaded, grCtxOptions) {}
|
||||
|
||||
Error GPUPersistentCacheTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
|
||||
SkString* log) const {
|
||||
// Draw twice, once with a cold cache, and again with a warm cache. Verify that we get the same
|
||||
// result.
|
||||
sk_gpu_test::MemoryCache memoryCache;
|
||||
GrContextOptions contextOptions = this->baseContextOptions();
|
||||
contextOptions.fPersistentCache = &memoryCache;
|
||||
|
||||
Error err = this->onDraw(src, dst, wStream, log, contextOptions);
|
||||
if (!err.isEmpty() || !dst) {
|
||||
return err;
|
||||
}
|
||||
|
||||
SkBitmap reference;
|
||||
SkString refLog;
|
||||
SkDynamicMemoryWStream refStream;
|
||||
memoryCache.resetNumCacheMisses();
|
||||
Error refErr = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
|
||||
if (!refErr.isEmpty()) {
|
||||
return refErr;
|
||||
}
|
||||
SkASSERT(memoryCache.numCacheMisses());
|
||||
|
||||
return compare_bitmaps(reference, *dst);
|
||||
}
|
||||
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||
static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
|
||||
if (src.size().isEmpty()) {
|
||||
return "Source has empty dimensions";
|
||||
|
@ -386,6 +386,26 @@ private:
|
||||
typedef GPUSink INHERITED;
|
||||
};
|
||||
|
||||
class GPUPersistentCacheTestingSink : public GPUSink {
|
||||
public:
|
||||
GPUPersistentCacheTestingSink(sk_gpu_test::GrContextFactory::ContextType,
|
||||
sk_gpu_test::GrContextFactory::ContextOverrides,
|
||||
SkCommandLineConfigGpu::SurfType surfType, int samples,
|
||||
bool diText, SkColorType colorType, SkAlphaType alphaType,
|
||||
sk_sp<SkColorSpace> colorSpace, bool threaded,
|
||||
const GrContextOptions& grCtxOptions);
|
||||
|
||||
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
||||
|
||||
const char* fileExtension() const override {
|
||||
// Suppress writing out results from this config - we just want to do our matching test
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef GPUSink INHERITED;
|
||||
};
|
||||
|
||||
class PDFSink : public Sink {
|
||||
public:
|
||||
PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
|
||||
|
@ -29,6 +29,7 @@ static const char defaultConfigs[] =
|
||||
|
||||
#undef DEFAULT_GPU_CONFIG
|
||||
|
||||
// clang-format off
|
||||
static const struct {
|
||||
const char* predefinedConfig;
|
||||
const char* backend;
|
||||
@ -67,6 +68,7 @@ static const struct {
|
||||
{ "gldft", "gpu", "api=gl,dit=true" },
|
||||
{ "glesdft", "gpu", "api=gles,dit=true" },
|
||||
{ "gltestthreading", "gpu", "api=gl,testThreading=true" },
|
||||
{ "gltestpersistentcache", "gpu", "api=gl,testPersistentCache=true" },
|
||||
{ "debuggl", "gpu", "api=debuggl" },
|
||||
{ "nullgl", "gpu", "api=nullgl" },
|
||||
{ "angle_d3d11_es2", "gpu", "api=angle_d3d11_es2" },
|
||||
@ -103,6 +105,7 @@ static const struct {
|
||||
,{ "mtlmsaa8", "gpu", "api=metal,samples=8" }
|
||||
#endif
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const char configHelp[] =
|
||||
"Options: 565 8888 srgb f16 nonrendering null pdf pdfa skp pipe svg xps";
|
||||
@ -118,63 +121,65 @@ static const char* config_help_fn() {
|
||||
}
|
||||
|
||||
static const char configExtendedHelp[] =
|
||||
"Extended form: 'backend(option=value,...)'\n\n"
|
||||
"Possible backends and options:\n"
|
||||
"\n"
|
||||
"gpu[api=string,color=string,dit=bool,nvpr=bool,inst=bool,samples=int]\n"
|
||||
"\tapi\ttype: string\trequired\n"
|
||||
"\t Select graphics API to use with gpu backend.\n"
|
||||
"\t Options:\n"
|
||||
"\t\tgl \t\t\tUse OpenGL.\n"
|
||||
"\t\tgles \t\t\tUse OpenGL ES.\n"
|
||||
"\t\tdebuggl \t\tUse debug OpenGL.\n"
|
||||
"\t\tnullgl \t\t\tUse null OpenGL.\n"
|
||||
"\t\tangle_d3d9_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n"
|
||||
"\t\tangle_d3d11_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n"
|
||||
"\t\tangle_d3d11_es3\t\tUse OpenGL ES3 on the ANGLE Direct3D11 backend.\n"
|
||||
"\t\tangle_gl_es2\t\tUse OpenGL ES2 on the ANGLE OpenGL backend.\n"
|
||||
"\t\tangle_gl_es3\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
|
||||
"\t\tcommandbuffer\t\tUse command buffer.\n"
|
||||
"\t\tmock\t\t\tUse mock context.\n"
|
||||
"Extended form: 'backend(option=value,...)'\n\n"
|
||||
"Possible backends and options:\n"
|
||||
"\n"
|
||||
"gpu[api=string,color=string,dit=bool,nvpr=bool,inst=bool,samples=int]\n"
|
||||
"\tapi\ttype: string\trequired\n"
|
||||
"\t Select graphics API to use with gpu backend.\n"
|
||||
"\t Options:\n"
|
||||
"\t\tgl \t\t\tUse OpenGL.\n"
|
||||
"\t\tgles \t\t\tUse OpenGL ES.\n"
|
||||
"\t\tdebuggl \t\tUse debug OpenGL.\n"
|
||||
"\t\tnullgl \t\t\tUse null OpenGL.\n"
|
||||
"\t\tangle_d3d9_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n"
|
||||
"\t\tangle_d3d11_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n"
|
||||
"\t\tangle_d3d11_es3\t\tUse OpenGL ES3 on the ANGLE Direct3D11 backend.\n"
|
||||
"\t\tangle_gl_es2\t\tUse OpenGL ES2 on the ANGLE OpenGL backend.\n"
|
||||
"\t\tangle_gl_es3\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
|
||||
"\t\tcommandbuffer\t\tUse command buffer.\n"
|
||||
"\t\tmock\t\t\tUse mock context.\n"
|
||||
#ifdef SK_VULKAN
|
||||
"\t\tvulkan\t\t\tUse Vulkan.\n"
|
||||
"\t\tvulkan\t\t\tUse Vulkan.\n"
|
||||
#endif
|
||||
#ifdef SK_METAL
|
||||
"\t\tmetal\t\t\tUse Metal.\n"
|
||||
"\t\tmetal\t\t\tUse Metal.\n"
|
||||
#endif
|
||||
"\tcolor\ttype: string\tdefault: 8888.\n"
|
||||
"\t Select framebuffer color format.\n"
|
||||
"\t Options:\n"
|
||||
"\t\t8888\t\t\tLinear 8888.\n"
|
||||
"\t\t888x\t\t\tLinear 888x.\n"
|
||||
"\t\t4444\t\t\tLinear 4444.\n"
|
||||
"\t\t565\t\t\tLinear 565.\n"
|
||||
"\t\t1010102\t\t\tLinear 1010102.\n"
|
||||
"\t\tsrgb\t\t\tsRGB 8888.\n"
|
||||
"\t\tesrgb\t\t\tsRGB 16-bit floating point.\n"
|
||||
"\t\tnarrow\t\t\tNarrow gamut 8888.\n"
|
||||
"\t\tenarrow\t\t\tNarrow gamut 16-bit floating point.\n"
|
||||
"\t\tf16\t\t\tLinearly blended 16-bit floating point.\n"
|
||||
"\tdit\ttype: bool\tdefault: false.\n"
|
||||
"\t Use device independent text.\n"
|
||||
"\tnvpr\ttype: bool\tdefault: false.\n"
|
||||
"\t Use NV_path_rendering OpenGL and OpenGL ES extension.\n"
|
||||
"\tsamples\ttype: int\tdefault: 0.\n"
|
||||
"\t Use multisampling with N samples.\n"
|
||||
"\tstencils\ttype: bool\tdefault: true.\n"
|
||||
"\t Allow the use of stencil buffers.\n"
|
||||
"\ttestThreading\ttype: bool\tdefault: false.\n"
|
||||
"\t Run with and without worker threads, check that results match.\n"
|
||||
"\tsurf\ttype: string\tdefault: default.\n"
|
||||
"\t Controls the type of backing store for SkSurfaces.\n"
|
||||
"\t Options:\n"
|
||||
"\t\tdefault\t\t\tA renderable texture created in Skia's resource cache.\n"
|
||||
"\t\tbetex\t\t\tA wrapped backend texture.\n"
|
||||
"\t\tbert\t\t\tA wrapped backend render target\n"
|
||||
"\n"
|
||||
"Predefined configs:\n\n"
|
||||
// Help text for pre-defined configs is auto-generated from gPredefinedConfigs
|
||||
;
|
||||
"\tcolor\ttype: string\tdefault: 8888.\n"
|
||||
"\t Select framebuffer color format.\n"
|
||||
"\t Options:\n"
|
||||
"\t\t8888\t\t\tLinear 8888.\n"
|
||||
"\t\t888x\t\t\tLinear 888x.\n"
|
||||
"\t\t4444\t\t\tLinear 4444.\n"
|
||||
"\t\t565\t\t\tLinear 565.\n"
|
||||
"\t\t1010102\t\t\tLinear 1010102.\n"
|
||||
"\t\tsrgb\t\t\tsRGB 8888.\n"
|
||||
"\t\tesrgb\t\t\tsRGB 16-bit floating point.\n"
|
||||
"\t\tnarrow\t\t\tNarrow gamut 8888.\n"
|
||||
"\t\tenarrow\t\t\tNarrow gamut 16-bit floating point.\n"
|
||||
"\t\tf16\t\t\tLinearly blended 16-bit floating point.\n"
|
||||
"\tdit\ttype: bool\tdefault: false.\n"
|
||||
"\t Use device independent text.\n"
|
||||
"\tnvpr\ttype: bool\tdefault: false.\n"
|
||||
"\t Use NV_path_rendering OpenGL and OpenGL ES extension.\n"
|
||||
"\tsamples\ttype: int\tdefault: 0.\n"
|
||||
"\t Use multisampling with N samples.\n"
|
||||
"\tstencils\ttype: bool\tdefault: true.\n"
|
||||
"\t Allow the use of stencil buffers.\n"
|
||||
"\ttestThreading\ttype: bool\tdefault: false.\n"
|
||||
"\t Run with and without worker threads, check that results match.\n"
|
||||
"\ttestPersistentCache\ttype: bool\tdefault: false.\n"
|
||||
"\t Run using a pre-warmed GrContextOption::fPersistentCache.\n"
|
||||
"\tsurf\ttype: string\tdefault: default.\n"
|
||||
"\t Controls the type of backing store for SkSurfaces.\n"
|
||||
"\t Options:\n"
|
||||
"\t\tdefault\t\t\tA renderable texture created in Skia's resource cache.\n"
|
||||
"\t\tbetex\t\t\tA wrapped backend texture.\n"
|
||||
"\t\tbert\t\t\tA wrapped backend render target\n"
|
||||
"\n"
|
||||
"Predefined configs:\n\n"
|
||||
// Help text for pre-defined configs is auto-generated from gPredefinedConfigs
|
||||
;
|
||||
|
||||
static const char* config_extended_help_fn() {
|
||||
static SkString helpString;
|
||||
@ -423,7 +428,7 @@ SkCommandLineConfigGpu::SkCommandLineConfigGpu(
|
||||
const SkString& tag, const SkTArray<SkString>& viaParts, ContextType contextType,
|
||||
bool useNVPR, bool useDIText, int samples, SkColorType colorType, SkAlphaType alphaType,
|
||||
sk_sp<SkColorSpace> colorSpace, bool useStencilBuffers, bool testThreading,
|
||||
SurfType surfType)
|
||||
bool testPersistentCache, SurfType surfType)
|
||||
: SkCommandLineConfig(tag, SkString("gpu"), viaParts)
|
||||
, fContextType(contextType)
|
||||
, fContextOverrides(ContextOverrides::kNone)
|
||||
@ -433,6 +438,7 @@ SkCommandLineConfigGpu::SkCommandLineConfigGpu(
|
||||
, fAlphaType(alphaType)
|
||||
, fColorSpace(std::move(colorSpace))
|
||||
, fTestThreading(testThreading)
|
||||
, fTestPersistentCache(testPersistentCache)
|
||||
, fSurfType(surfType) {
|
||||
if (useNVPR) {
|
||||
fContextOverrides |= ContextOverrides::kRequireNVPRSupport;
|
||||
@ -459,6 +465,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
|
||||
sk_sp<SkColorSpace> colorSpace = nullptr;
|
||||
bool useStencils = true;
|
||||
bool testThreading = false;
|
||||
bool testPersistentCache = false;
|
||||
SkCommandLineConfigGpu::SurfType surfType = SkCommandLineConfigGpu::SurfType::kDefault;
|
||||
|
||||
bool parseSucceeded = false;
|
||||
@ -475,16 +482,17 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
|
||||
extendedOptions.get_option_gpu_color("color", &colorType, &alphaType, &colorSpace) &&
|
||||
extendedOptions.get_option_bool("stencils", &useStencils) &&
|
||||
extendedOptions.get_option_bool("testThreading", &testThreading) &&
|
||||
extendedOptions.get_option_bool("testThreading", &testThreading) &&
|
||||
extendedOptions.get_option_bool("testPersistentCache", &testPersistentCache) &&
|
||||
extendedOptions.get_option_gpu_surf_type("surf", &surfType);
|
||||
|
||||
if (!validOptions) {
|
||||
// testing threading and the persistent cache are mutually exclusive.
|
||||
if (!validOptions || (testThreading && testPersistentCache)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new SkCommandLineConfigGpu(tag, vias, contextType, useNVPR, useDIText, samples,
|
||||
colorType, alphaType, colorSpace, useStencils, testThreading,
|
||||
surfType);
|
||||
testPersistentCache, surfType);
|
||||
}
|
||||
|
||||
SkCommandLineConfigSvg::SkCommandLineConfigSvg(const SkString& tag,
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
ContextType contextType, bool useNVPR, bool useDIText, int samples,
|
||||
SkColorType colorType, SkAlphaType alphaType,
|
||||
sk_sp<SkColorSpace> colorSpace, bool useStencilBuffers,
|
||||
bool testThreading, SurfType);
|
||||
bool testThreading, bool testPersistentCache, SurfType);
|
||||
|
||||
const SkCommandLineConfigGpu* asConfigGpu() const override { return this; }
|
||||
ContextType getContextType() const { return fContextType; }
|
||||
@ -73,6 +73,7 @@ public:
|
||||
SkAlphaType getAlphaType() const { return fAlphaType; }
|
||||
SkColorSpace* getColorSpace() const { return fColorSpace.get(); }
|
||||
bool getTestThreading() const { return fTestThreading; }
|
||||
bool getTestPersistentCache() const { return fTestPersistentCache; }
|
||||
SurfType getSurfType() const { return fSurfType; }
|
||||
|
||||
private:
|
||||
@ -84,6 +85,7 @@ private:
|
||||
SkAlphaType fAlphaType;
|
||||
sk_sp<SkColorSpace> fColorSpace;
|
||||
bool fTestThreading;
|
||||
bool fTestPersistentCache;
|
||||
SurfType fSurfType;
|
||||
};
|
||||
|
||||
|
56
tools/gpu/MemoryCache.cpp
Normal file
56
tools/gpu/MemoryCache.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "MemoryCache.h"
|
||||
#include "SkBase64.h"
|
||||
|
||||
// Change this to 1 to log cache hits/misses/stores using SkDebugf.
|
||||
#define LOG_MEMORY_CACHE 0
|
||||
|
||||
static SkString data_to_str(const SkData& data) {
|
||||
size_t encodeLength = SkBase64::Encode(data.data(), data.size(), nullptr);
|
||||
SkString str;
|
||||
str.resize(encodeLength);
|
||||
SkBase64::Encode(data.data(), data.size(), str.writable_str());
|
||||
static constexpr size_t kMaxLength = 60;
|
||||
static constexpr char kTail[] = "...";
|
||||
static const size_t kTailLen = strlen(kTail);
|
||||
bool overlength = encodeLength > kMaxLength;
|
||||
if (overlength) {
|
||||
str = SkString(str.c_str(), kMaxLength - kTailLen);
|
||||
str.append(kTail);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
namespace sk_gpu_test {
|
||||
|
||||
sk_sp<SkData> MemoryCache::load(const SkData& key) {
|
||||
auto result = fMap.find(key);
|
||||
if (result == fMap.end()) {
|
||||
if (LOG_MEMORY_CACHE) {
|
||||
SkDebugf("Load Key: %s\n\tNot Found.\n\n", data_to_str(key).c_str());
|
||||
}
|
||||
++fCacheMissCnt;
|
||||
return nullptr;
|
||||
}
|
||||
if (LOG_MEMORY_CACHE) {
|
||||
SkDebugf("Load Key: %s\n\tFound Data: %s\n\n", data_to_str(key).c_str(),
|
||||
data_to_str(*result->second).c_str());
|
||||
}
|
||||
return result->second;
|
||||
}
|
||||
|
||||
void MemoryCache::store(const SkData& key, const SkData& data) {
|
||||
if (LOG_MEMORY_CACHE) {
|
||||
SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
|
||||
data_to_str(data).c_str());
|
||||
}
|
||||
fMap[Key(key)] = SkData::MakeWithCopy(data.data(), data.size());
|
||||
}
|
||||
|
||||
} // namespace sk_gpu_test
|
62
tools/gpu/MemoryCache.h
Normal file
62
tools/gpu/MemoryCache.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef MemoryCache_DEFINED
|
||||
#define MemoryCache_DEFINED
|
||||
|
||||
#include <unordered_map>
|
||||
#include "GrContextOptions.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkData.h"
|
||||
|
||||
namespace sk_gpu_test {
|
||||
|
||||
/**
|
||||
* This class can be used to maintain an in memory record of all programs cached by GrContext.
|
||||
* It can be shared by multiple GrContexts so long as those GrContexts are created with the same
|
||||
* options and will have the same GrCaps (e.g. same backend, same GL context creation parameters,
|
||||
* ...).
|
||||
*/
|
||||
class MemoryCache : public GrContextOptions::PersistentCache {
|
||||
public:
|
||||
MemoryCache() = default;
|
||||
MemoryCache(const MemoryCache&) = delete;
|
||||
MemoryCache& operator=(const MemoryCache&) = delete;
|
||||
|
||||
sk_sp<SkData> load(const SkData& key) override;
|
||||
void store(const SkData& key, const SkData& data) override;
|
||||
int numCacheMisses() const { return fCacheMissCnt; }
|
||||
void resetNumCacheMisses() { fCacheMissCnt = 0; }
|
||||
|
||||
private:
|
||||
struct Key {
|
||||
Key() = default;
|
||||
Key(const SkData& key) : fKey(SkData::MakeWithCopy(key.data(), key.size())) {}
|
||||
Key(const Key& that) = default;
|
||||
Key& operator=(const Key&) = default;
|
||||
bool operator==(const Key& that) const {
|
||||
return that.fKey->size() == fKey->size() &&
|
||||
!memcmp(fKey->data(), that.fKey->data(), that.fKey->size());
|
||||
}
|
||||
sk_sp<const SkData> fKey;
|
||||
};
|
||||
|
||||
struct Hash {
|
||||
using argument_type = Key;
|
||||
using result_type = uint32_t;
|
||||
uint32_t operator()(const Key& key) const {
|
||||
return key.fKey ? SkOpts::hash_fn(key.fKey->data(), key.fKey->size(), 0) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
int fCacheMissCnt = 0;
|
||||
std::unordered_map<Key, sk_sp<SkData>, Hash> fMap;
|
||||
};
|
||||
|
||||
} // namespace sk_gpu_test
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user