From 754f4e98d94d7c9ed76cd128cf983f9323a1885b Mon Sep 17 00:00:00 2001 From: robertphillips Date: Thu, 18 Sep 2014 13:52:08 -0700 Subject: [PATCH] Add counting of some GL calls I would like this facility for tracking FBO switch improvements. R=bsalomon@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/553583008 --- include/gpu/GrConfig.h | 4 + include/gpu/GrContext.h | 24 ++++ src/gpu/GrContext.cpp | 7 ++ src/gpu/GrGpu.h | 4 + src/gpu/gl/GrGpuGL.cpp | 41 ++++--- src/gpu/gl/GrGpuGL.h | 4 +- .../gl/builders/GrGLFragmentShaderBuilder.cpp | 5 +- .../gl/builders/GrGLGeometryShaderBuilder.cpp | 4 +- .../gl/builders/GrGLShaderStringBuilder.cpp | 110 +++++++++--------- src/gpu/gl/builders/GrGLShaderStringBuilder.h | 4 +- .../gl/builders/GrGLVertexShaderBuilder.cpp | 5 +- tools/PictureBenchmark.h | 1 + tools/bench_pictures_main.cpp | 14 +++ tools/render_pictures_main.cpp | 11 ++ 14 files changed, 160 insertions(+), 78 deletions(-) diff --git a/include/gpu/GrConfig.h b/include/gpu/GrConfig.h index 80897a07bd..86ad63ad6e 100644 --- a/include/gpu/GrConfig.h +++ b/include/gpu/GrConfig.h @@ -36,6 +36,10 @@ #define GR_CACHE_STATS 0 #endif +#if !defined(GR_GPU_STATS) +#define GR_GPU_STATS 0 +#endif + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index dd15767534..f9c78ffbe3 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -960,6 +960,30 @@ public: void printCacheStats() const; #endif + class GPUStats { + public: +#if GR_GPU_STATS + GPUStats() { this->reset(); } + + void reset() { fRenderTargetBinds = 0; fShaderCompilations = 0; } + + int renderTargetBinds() const { return fRenderTargetBinds; } + void incRenderTargetBinds() { fRenderTargetBinds++; } + int shaderCompilations() const { return fShaderCompilations; } + void incShaderCompilations() { fShaderCompilations++; } + private: + int fRenderTargetBinds; + int fShaderCompilations; +#else + void incRenderTargetBinds() {} + void incShaderCompilations() {} +#endif + }; + +#if GR_GPU_STATS + const GPUStats* gpuStats() const; +#endif + private: // Used to indicate whether a draw should be performed immediately or queued in fDrawBuffer. enum BufferedDraw { diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index e208cddec4..eb8455adbb 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1941,3 +1941,10 @@ void GrContext::printCacheStats() const { fResourceCache->printStats(); } #endif + +#if GR_GPU_STATS +const GrContext::GPUStats* GrContext::gpuStats() const { + return fGpu->gpuStats(); +} +#endif + diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 9ceb706db8..54fe471c88 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -327,6 +327,8 @@ public: return kDrawPath_DrawType == type || kDrawPaths_DrawType == type; } + GrContext::GPUStats* gpuStats() { return &fGPUStats; } + protected: DrawType PrimTypeToDrawType(GrPrimitiveType type) { switch (type) { @@ -364,6 +366,8 @@ protected: GrClipMaskManager fClipMaskManager; + GrContext::GPUStats fGPUStats; + struct GeometryPoolState { const GrVertexBuffer* fPoolVertexBuffer; int fPoolStartVertex; diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 5d4bd8b7b7..ebc34572fe 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -870,6 +870,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height, width, height)) { goto FAILED; } + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID)); GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, @@ -884,6 +885,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height, fGLContext.caps()->markConfigAsValidColorAttachment(desc->fConfig); } } + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID)); if (this->glCaps().usesImplicitMSAAResolve() && desc->fSampleCnt > 0) { @@ -1245,6 +1247,7 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar GrGLuint rb = glsb->renderbufferID(); fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, @@ -1438,6 +1441,7 @@ void GrGpuGL::discard(GrRenderTarget* renderTarget) { GrGLRenderTarget* glRT = static_cast(renderTarget); if (renderTarget->getUniqueID() != fHWBoundRenderTargetUniqueID) { fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID())); } switch (this->glCaps().invalidateFBType()) { @@ -1601,6 +1605,7 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, case GrGLRenderTarget::kCanResolve_ResolveType: this->onResolveRenderTarget(tgt); // we don't track the state of the READ FBO ID. + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID())); break; @@ -1698,6 +1703,7 @@ void GrGpuGL::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) uint32_t rtID = target->getUniqueID(); if (fHWBoundRenderTargetUniqueID != rtID) { + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID())); #ifdef SK_DEBUG // don't do this check in Chromium -- this is causing @@ -1800,6 +1806,8 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { // Some extensions automatically resolves the texture when it is read. if (this->glCaps().usesMSAARenderBuffers()) { SkASSERT(rt->textureFBOID() != rt->renderFBOID()); + fGPUStats.incRenderTargetBinds(); + fGPUStats.incRenderTargetBinds(); GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID())); GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID())); // make sure we go through flushRenderTarget() since we've modified @@ -2363,38 +2371,37 @@ inline bool can_copy_texsubimage(const GrSurface* dst, } } +} + // If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is // relative to is output. -inline GrGLuint bind_surface_as_fbo(const GrGLInterface* gl, - GrSurface* surface, - GrGLenum fboTarget, - GrGLIRect* viewport) { +GrGLuint GrGpuGL::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport) { GrGLRenderTarget* rt = static_cast(surface->asRenderTarget()); GrGLuint tempFBOID; if (NULL == rt) { SkASSERT(surface->asTexture()); GrGLuint texID = static_cast(surface->asTexture())->textureID(); - GR_GL_CALL(gl, GenFramebuffers(1, &tempFBOID)); - GR_GL_CALL(gl, BindFramebuffer(fboTarget, tempFBOID)); - GR_GL_CALL(gl, FramebufferTexture2D(fboTarget, - GR_GL_COLOR_ATTACHMENT0, - GR_GL_TEXTURE_2D, - texID, - 0)); + GR_GL_CALL(this->glInterface(), GenFramebuffers(1, &tempFBOID)); + fGPUStats.incRenderTargetBinds(); + GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, tempFBOID)); + GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, + GR_GL_COLOR_ATTACHMENT0, + GR_GL_TEXTURE_2D, + texID, + 0)); viewport->fLeft = 0; viewport->fBottom = 0; viewport->fWidth = surface->width(); viewport->fHeight = surface->height(); } else { tempFBOID = 0; - GR_GL_CALL(gl, BindFramebuffer(fboTarget, rt->renderFBOID())); + fGPUStats.incRenderTargetBinds(); + GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID())); *viewport = rt->getViewport(); } return tempFBOID; } -} - void GrGpuGL::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) { // Check for format issues with glCopyTexSubImage2D if (kGLES_GrGLStandard == this->glStandard() && this->glCaps().bgraIsInternalFormat() && @@ -2432,7 +2439,7 @@ bool GrGpuGL::onCopySurface(GrSurface* dst, (!wouldNeedTempFBO || !inheritedCouldCopy)) { GrGLuint srcFBO; GrGLIRect srcVP; - srcFBO = bind_surface_as_fbo(this->glInterface(), src, GR_GL_FRAMEBUFFER, &srcVP); + srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP); GrGLTexture* dstTex = static_cast(dst->asTexture()); SkASSERT(dstTex); // We modified the bound FBO @@ -2475,8 +2482,8 @@ bool GrGpuGL::onCopySurface(GrSurface* dst, GrGLuint srcFBO; GrGLIRect dstVP; GrGLIRect srcVP; - dstFBO = bind_surface_as_fbo(this->glInterface(), dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP); - srcFBO = bind_surface_as_fbo(this->glInterface(), src, GR_GL_READ_FRAMEBUFFER, &srcVP); + dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP); + srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP); // We modified the bound FBO fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; GrGLIRect srcGLRect; diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index a8130d8099..06a0e3bf2e 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -150,7 +150,7 @@ private: bool insideClip) SK_OVERRIDE; virtual bool flushGraphicsState(DrawType, const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE; - // GrDrawTarget ovverides + // GrDrawTarget overrides virtual void didAddGpuTraceMarker() SK_OVERRIDE; virtual void didRemoveGpuTraceMarker() SK_OVERRIDE; @@ -267,6 +267,8 @@ private: GrGLuint texID, GrGLRenderTarget::Desc* desc); + GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport); + GrGLContext fGLContext; // GL program-related state diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index 182ebfb70f..730ce04b3e 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -231,8 +231,9 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, fragShaderSrc.append(fCode); fragShaderSrc.append("}\n"); - GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), - programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc); + GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, + GR_GL_FRAGMENT_SHADER, fragShaderSrc, + gpu->gpuStats()); if (!fragShaderId) { return false; } diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp index 6cdf2f93e0..117497b9ee 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp @@ -61,7 +61,9 @@ bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId, "\tEndPrimitive();\n"); geomShaderSrc.append("}\n"); GrGLuint geomShaderId = - GrGLCompileAndAttachShader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc); + GrGLCompileAndAttachShader(glCtx, programId, + GR_GL_GEOMETRY_SHADER, geomShaderSrc, + fProgramBuilder->gpu()->gpuStats()); if (!geomShaderId) { return false; } diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp index dff8c7e684..6406451014 100644 --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp @@ -20,66 +20,68 @@ SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, - const SkString& shaderSrc) { + const SkString& shaderSrc, + GrContext::GPUStats* gpuStats) { const GrGLInterface* gli = glCtx.interface(); - GrGLuint shaderId; - GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); - if (0 == shaderId) { - return 0; - } + GrGLuint shaderId; + GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); + if (0 == shaderId) { + return 0; + } - #ifdef SK_DEBUG - SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false); - const GrGLchar* sourceStr = prettySource.c_str(); - GrGLint sourceLength = static_cast(prettySource.size()); - #else - GrGLint sourceLength = static_cast(shaderSrc.size()); - const GrGLchar* sourceStr = shaderSrc.c_str(); - #endif - GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); - GR_GL_CALL(gli, CompileShader(shaderId)); +#ifdef SK_DEBUG + SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false); + const GrGLchar* sourceStr = prettySource.c_str(); + GrGLint sourceLength = static_cast(prettySource.size()); +#else + GrGLint sourceLength = static_cast(shaderSrc.size()); + const GrGLchar* sourceStr = shaderSrc.c_str(); +#endif + GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); + gpuStats->incShaderCompilations(); + GR_GL_CALL(gli, CompileShader(shaderId)); - // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. - bool checkCompiled = !glCtx.isChromium(); - #ifdef SK_DEBUG - checkCompiled = true; - #endif - if (checkCompiled) { - GrGLint compiled = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); + // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. + bool checkCompiled = !glCtx.isChromium(); +#ifdef SK_DEBUG + checkCompiled = true; +#endif + if (checkCompiled) { + GrGLint compiled = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); - if (!compiled) { - GrGLint infoLen = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); - SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger - if (infoLen > 0) { - // retrieve length even though we don't need it to workaround bug in Chromium cmd - // buffer param validation. - GrGLsizei length = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, - &length, (char*)log.get())); - GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); - GrPrintf("\n%s", log.get()); - } - SkDEBUGFAIL("Shader compilation failed!"); - GR_GL_CALL(gli, DeleteShader(shaderId)); - return 0; - } - } + if (!compiled) { + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); + SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger + if (infoLen > 0) { + // retrieve length even though we don't need it to workaround bug in Chromium cmd + // buffer param validation. + GrGLsizei length = GR_GL_INIT_ZERO; + GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, + &length, (char*)log.get())); + GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + GrPrintf("\n%s", log.get()); + } + SkDEBUGFAIL("Shader compilation failed!"); + GR_GL_CALL(gli, DeleteShader(shaderId)); + return 0; + } + } - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", - TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); - if (c_PrintShaders) { - GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); - GrPrintf("\n"); - } + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", + TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); + if (c_PrintShaders) { + GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + GrPrintf("\n"); + } - // Attach the shader, but defer deletion until after we have linked the program. - // This works around a bug in the Android emulator's GLES2 wrapper which - // will immediately delete the shader object and free its memory even though it's - // attached to a program, which then causes glLinkProgram to fail. - GR_GL_CALL(gli, AttachShader(programId, shaderId)); + // Attach the shader, but defer deletion until after we have linked the program. + // This works around a bug in the Android emulator's GLES2 wrapper which + // will immediately delete the shader object and free its memory even though it's + // attached to a program, which then causes glLinkProgram to fail. + GR_GL_CALL(gli, AttachShader(programId, shaderId)); - return shaderId; + return shaderId; } diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h index 8c18fa570a..ab8734f7c6 100644 --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.h +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h @@ -9,12 +9,14 @@ #define GrGLShaderStringBuilder_DEFINED #include "GrAllocator.h" +#include "GrContext.h" #include "gl/GrGLContext.h" #include "SkTypes.h" GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, - const SkString& shaderSrc); + const SkString& shaderSrc, + GrContext::GPUStats* gpuStats); #endif diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index 9e666ad3da..ad61465941 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -120,9 +120,10 @@ bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId, fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc); vertShaderSrc.append("void main() {"); vertShaderSrc.append(fCode); - vertShaderSrc.append("}"); + vertShaderSrc.append("}\n"); GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId, - GR_GL_VERTEX_SHADER, vertShaderSrc); + GR_GL_VERTEX_SHADER, vertShaderSrc, + gpu->gpuStats()); if (!vertShaderId) { return false; } diff --git a/tools/PictureBenchmark.h b/tools/PictureBenchmark.h index 1ddd18ea16..2b1ccb5383 100644 --- a/tools/PictureBenchmark.h +++ b/tools/PictureBenchmark.h @@ -49,6 +49,7 @@ public: bool preprocess() const { return fPreprocess; } PictureRenderer* setRenderer(PictureRenderer*); + PictureRenderer* renderer() { return fRenderer; } void setTimerResultType(TimerData::Result resultType) { fTimerResult = resultType; } diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp index 2eda73c40f..ade93fc3e6 100644 --- a/tools/bench_pictures_main.cpp +++ b/tools/bench_pictures_main.cpp @@ -54,6 +54,11 @@ DEFINE_bool(trackDeferredCaching, false, "Only meaningful with --deferImageDecod "SK_LAZY_CACHE_STATS set to true. Report percentage of cache hits when using " "deferred image decoding."); +#if GR_GPU_STATS +DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " + "Report some GPU call statistics."); +#endif + DEFINE_bool(preprocess, false, "If true, perform device specific preprocessing before timing."); // Buildbot-specific parameters @@ -476,6 +481,15 @@ int tool_main(int argc, char** argv) { (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses)); } #endif + +#if GR_GPU_STATS + if (FLAGS_gpuStats && benchmark.renderer()->isUsingGpuDevice()) { + GrContext* ctx = benchmark.renderer()->getGrContext(); + SkDebugf("RenderTarget Binds: %d\n", ctx->gpuStats()->renderTargetBinds()); + SkDebugf("Shader Compilations: %d\n", ctx->gpuStats()->shaderCompilations()); + } +#endif + gWriter.end(); return 0; } diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp index 4fb83521c8..d7a213cb47 100644 --- a/tools/render_pictures_main.cpp +++ b/tools/render_pictures_main.cpp @@ -36,6 +36,10 @@ DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo "Requires --validate."); DEFINE_string(mismatchPath, "", "Write images for tests that failed due to " "pixel mismatches into this directory."); +#if GR_GPU_STATS +DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " + "Report some GPU call statistics."); +#endif DEFINE_bool(preprocess, false, "If true, perform device specific preprocessing before rendering."); DEFINE_string(readJsonSummaryPath, "", "JSON file to read image expectations from."); DECLARE_string(readPath); @@ -496,6 +500,13 @@ int tool_main(int argc, char** argv) { #endif } #endif +#if GR_GPU_STATS + if (FLAGS_gpuStats && renderer->isUsingGpuDevice()) { + GrContext* ctx = renderer->getGrContext(); + SkDebugf("RenderTarget Binds: %d\n", ctx->gpuStats()->renderTargetBinds()); + SkDebugf("Shader Compilations: %d\n", ctx->gpuStats()->shaderCompilations()); + } +#endif #endif if (FLAGS_writeJsonSummaryPath.count() == 1) { // If there were any descriptions on the command line, insert them now. -- 2.34.1