Adds gpu stats for program cache
With the addition of the DDL program pre-compilation we need to know how it is working.
This CL also fixes some threading bugs.
Bug: skia:9455
Change-Id: I20da58a7f1b19685687fae1d159d4e0db8a4964d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273001
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkDeferredDisplayList.cpp b/src/core/SkDeferredDisplayList.cpp
index 112f577..f14aa54 100644
--- a/src/core/SkDeferredDisplayList.cpp
+++ b/src/core/SkDeferredDisplayList.cpp
@@ -23,12 +23,18 @@
sk_sp<LazyProxyData> lazyProxyData)
: fCharacterization(characterization)
#if SK_SUPPORT_GPU
- , fLazyProxyData(std::move(lazyProxyData))
+ , fLazyProxyData(std::move(lazyProxyData))
#endif
{
}
-SkDeferredDisplayList::~SkDeferredDisplayList() {}
+SkDeferredDisplayList::~SkDeferredDisplayList() {
+#if SK_SUPPORT_GPU && defined(SK_DEBUG)
+ for (auto& renderTask : fRenderTasks) {
+ SkASSERT(renderTask->unique());
+ }
+#endif
+}
//-------------------------------------------------------------------------------------------------
#if SK_SUPPORT_GPU
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index af1440b..6e919da 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -104,6 +104,12 @@
}
void GrDrawingManager::RenderTaskDAG::add(const SkTArray<sk_sp<GrRenderTask>>& renderTasks) {
+#ifdef SK_DEBUG
+ for (auto& renderTask : renderTasks) {
+ SkASSERT(renderTask->unique());
+ }
+#endif
+
fRenderTasks.push_back_n(renderTasks.count(), renderTasks.begin());
}
@@ -576,8 +582,9 @@
fActiveOpsTask = nullptr;
fDAG.swap(&ddl->fRenderTasks);
+ SkASSERT(!fDAG.numRenderTasks());
- for (auto renderTask : ddl->fRenderTasks) {
+ for (auto& renderTask : ddl->fRenderTasks) {
renderTask->prePrepare(fContext);
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 0eca489..d6b97a2 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -702,6 +702,19 @@
#if GR_TEST_UTILS
#if GR_GPU_STATS
+static const char* cache_result_to_str(int i) {
+ const char* kCacheResultStrings[GrGpu::Stats::kNumProgramCacheResults] = {
+ "hits",
+ "misses",
+ "partials"
+ };
+ static_assert(0 == (int) GrGpu::Stats::ProgramCacheResult::kHit);
+ static_assert(1 == (int) GrGpu::Stats::ProgramCacheResult::kMiss);
+ static_assert(2 == (int) GrGpu::Stats::ProgramCacheResult::kPartial);
+ static_assert(GrGpu::Stats::kNumProgramCacheResults == 3);
+ return kCacheResultStrings[i];
+}
+
void GrGpu::Stats::dump(SkString* out) {
out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
out->appendf("Shader Compilations: %d\n", fShaderCompilations);
@@ -712,6 +725,26 @@
out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
out->appendf("Number of draws: %d\n", fNumDraws);
out->appendf("Number of Scratch Textures reused %d\n", fNumScratchTexturesReused);
+
+ SkASSERT(fNumInlineCompilationFailures == 0);
+ out->appendf("Number of Inline compile failures %d\n", fNumInlineCompilationFailures);
+ for (int i = 0; i < Stats::kNumProgramCacheResults-1; ++i) {
+ out->appendf("Inline Program Cache %s %d\n", cache_result_to_str(i),
+ fInlineProgramCacheStats[i]);
+ }
+
+ SkASSERT(fNumPreCompilationFailures == 0);
+ out->appendf("Number of precompile failures %d\n", fNumPreCompilationFailures);
+ for (int i = 0; i < Stats::kNumProgramCacheResults-1; ++i) {
+ out->appendf("Precompile Program Cache %s %d\n", cache_result_to_str(i),
+ fPreProgramCacheStats[i]);
+ }
+
+ SkASSERT(fNumCompilationFailures == 0);
+ out->appendf("Total number of compilation failures %d\n", fNumCompilationFailures);
+ out->appendf("Total number of partial compilation successes %d\n",
+ fNumPartialCompilationSuccesses);
+ out->appendf("Total number of compilation successes %d\n", fNumCompilationSuccesses);
}
void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index c0a1bc1..aa10bd8 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -386,6 +386,16 @@
class Stats {
public:
+ enum class ProgramCacheResult {
+ kHit, // the program was found in the cache
+ kMiss, // the program was not found in the cache (and was, thus, compiled)
+ kPartial, // a precompiled version was found in the persistent cache
+
+ kLast = kPartial
+ };
+
+ static const int kNumProgramCacheResults = (int)ProgramCacheResult::kLast + 1;
+
#if GR_GPU_STATS
Stats() = default;
@@ -424,6 +434,35 @@
int numScratchTexturesReused() const { return fNumScratchTexturesReused; }
void incNumScratchTexturesReused() { ++fNumScratchTexturesReused; }
+ int numInlineCompilationFailures() const { return fNumInlineCompilationFailures; }
+ void incNumInlineCompilationFailures() { ++fNumInlineCompilationFailures; }
+
+ int numInlineProgramCacheResult(ProgramCacheResult stat) const {
+ return fInlineProgramCacheStats[(int) stat];
+ }
+ void incNumInlineProgramCacheResult(ProgramCacheResult stat) {
+ ++fInlineProgramCacheStats[(int) stat];
+ }
+
+ int numPreCompilationFailures() const { return fNumPreCompilationFailures; }
+ void incNumPreCompilationFailures() { ++fNumPreCompilationFailures; }
+
+ int numPreProgramCacheResult(ProgramCacheResult stat) const {
+ return fPreProgramCacheStats[(int) stat];
+ }
+ void incNumPreProgramCacheResult(ProgramCacheResult stat) {
+ ++fPreProgramCacheStats[(int) stat];
+ }
+
+ int numCompilationFailures() const { return fNumCompilationFailures; }
+ void incNumCompilationFailures() { ++fNumCompilationFailures; }
+
+ int numPartialCompilationSuccesses() const { return fNumPartialCompilationSuccesses; }
+ void incNumPartialCompilationSuccesses() { ++fNumPartialCompilationSuccesses; }
+
+ int numCompilationSuccesses() const { return fNumCompilationSuccesses; }
+ void incNumCompilationSuccesses() { ++fNumCompilationSuccesses; }
+
#if GR_TEST_UTILS
void dump(SkString*);
void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values);
@@ -440,6 +479,17 @@
int fNumFailedDraws = 0;
int fNumFinishFlushes = 0;
int fNumScratchTexturesReused = 0;
+
+ int fNumInlineCompilationFailures = 0;
+ int fInlineProgramCacheStats[kNumProgramCacheResults] = { 0 };
+
+ int fNumPreCompilationFailures = 0;
+ int fPreProgramCacheStats[kNumProgramCacheResults] = { 0 };
+
+ int fNumCompilationFailures = 0;
+ int fNumPartialCompilationSuccesses = 0;
+ int fNumCompilationSuccesses = 0;
+
#else
#if GR_TEST_UTILS
@@ -455,6 +505,13 @@
void incNumDraws() {}
void incNumFailedDraws() {}
void incNumFinishFlushes() {}
+ void incNumInlineCompilationFailures() {}
+ void incNumInlineProgramCacheResult(ProgramCacheResult stat) {}
+ void incNumPreCompilationFailures() {}
+ void incNumPreProgramCacheResult(ProgramCacheResult stat) {}
+ void incNumCompilationFailures() {}
+ void incNumPartialCompilationSuccesses() {}
+ void incNumCompilationSuccesses() {}
#endif
};
diff --git a/src/gpu/GrMemoryPool.cpp b/src/gpu/GrMemoryPool.cpp
index b2f627d..b5249e1 100644
--- a/src/gpu/GrMemoryPool.cpp
+++ b/src/gpu/GrMemoryPool.cpp
@@ -51,7 +51,7 @@
int n = fAllocatedIDs.count();
fAllocatedIDs.foreach([&i, n] (int32_t id) {
if (++i == 1) {
- SkDebugf("Leaked IDs (in no particular order): %d", id);
+ SkDebugf("Leaked %d IDs (in no particular order): %d%s", n, id, (n == i) ? "\n" : "");
} else if (i < 11) {
SkDebugf(", %d%s", id, (n == i ? "\n" : ""));
} else if (i == 11) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 315006b..de2c53f 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -333,7 +333,15 @@
sk_sp<GrGLProgram> findOrCreateProgram(GrRenderTarget*, const GrProgramInfo&);
sk_sp<GrGLProgram> findOrCreateProgram(const GrProgramDesc& desc,
const GrProgramInfo& programInfo) {
- return this->findOrCreateProgram(nullptr, desc, programInfo);
+ Stats::ProgramCacheResult stat;
+ sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(nullptr, desc, programInfo, &stat);
+ if (!tmp) {
+ fGpu->fStats.incNumPreCompilationFailures();
+ } else {
+ fGpu->fStats.incNumPreProgramCacheResult(stat);
+ }
+
+ return tmp;
}
bool precompileShader(const SkData& key, const SkData& data);
@@ -342,7 +350,8 @@
sk_sp<GrGLProgram> findOrCreateProgram(GrRenderTarget*,
const GrProgramDesc&,
- const GrProgramInfo&);
+ const GrProgramInfo&,
+ Stats::ProgramCacheResult*);
struct DescHash {
uint32_t operator()(const GrProgramDesc& desc) const {
diff --git a/src/gpu/gl/GrGLGpuProgramCache.cpp b/src/gpu/gl/GrGLGpuProgramCache.cpp
index 02c75a1..bf54a88 100644
--- a/src/gpu/gl/GrGLGpuProgramCache.cpp
+++ b/src/gpu/gl/GrGLGpuProgramCache.cpp
@@ -55,12 +55,22 @@
return nullptr;
}
- return this->findOrCreateProgram(renderTarget, desc, programInfo);
+ Stats::ProgramCacheResult stat;
+ sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(renderTarget, desc, programInfo, &stat);
+ if (!tmp) {
+ fGpu->fStats.incNumInlineCompilationFailures();
+ } else {
+ fGpu->fStats.incNumInlineProgramCacheResult(stat);
+ }
+
+ return tmp;
}
sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrRenderTarget* renderTarget,
const GrProgramDesc& desc,
- const GrProgramInfo& programInfo) {
+ const GrProgramInfo& programInfo,
+ Stats::ProgramCacheResult* stat) {
+ *stat = Stats::ProgramCacheResult::kHit;
std::unique_ptr<Entry>* entry = fMap.find(desc);
if (entry && !(*entry)->fProgram) {
// We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding
@@ -71,16 +81,22 @@
if (!(*entry)->fProgram) {
// Should we purge the program ID from the cache at this point?
SkDEBUGFAIL("Couldn't create program from precompiled program");
+ fGpu->fStats.incNumCompilationFailures();
return nullptr;
}
+ fGpu->fStats.incNumPartialCompilationSuccesses();
+ *stat = Stats::ProgramCacheResult::kPartial;
} else if (!entry) {
// We have a cache miss
sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(fGpu, renderTarget,
desc, programInfo);
if (!program) {
+ fGpu->fStats.incNumCompilationFailures();
return nullptr;
}
+ fGpu->fStats.incNumCompilationSuccesses();
entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(std::move(program))));
+ *stat = Stats::ProgramCacheResult::kMiss;
}
return (*entry)->fProgram;