1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrGLGpu.h" 9 10 #include "builders/GrGLProgramBuilder.h" 11 #include "GrProcessor.h" 12 #include "GrProgramDesc.h" 13 #include "GrGLPathRendering.h" 14 #include "glsl/GrGLSLFragmentProcessor.h" 15 #include "glsl/GrGLSLProgramDataManager.h" 16 #include "SkTSearch.h" 17 18 #ifdef PROGRAM_CACHE_STATS 19 // Display program cache usage 20 static const bool c_DisplayCache{false}; 21 #endif 22 23 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 24 25 struct GrGLGpu::ProgramCache::Entry { 26 Entry(sk_sp<GrGLProgram> program) : fProgram(std::move(program)) {} 27 28 sk_sp<GrGLProgram> fProgram; 29 }; 30 31 GrGLGpu::ProgramCache::ProgramCache(GrGLGpu* gpu) 32 : fMap(kMaxEntries) 33 , fGpu(gpu) 34 #ifdef PROGRAM_CACHE_STATS 35 , fTotalRequests(0) 36 , fCacheMisses(0) 37 , fHashMisses(0) 38 #endif 39 {} 40 41 GrGLGpu::ProgramCache::~ProgramCache() { 42 // dump stats 43 #ifdef PROGRAM_CACHE_STATS 44 if (c_DisplayCache) { 45 SkDebugf("--- Program Cache ---\n"); 46 SkDebugf("Total requests: %d\n", fTotalRequests); 47 SkDebugf("Cache misses: %d\n", fCacheMisses); 48 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 49 100.f * fCacheMisses / fTotalRequests : 50 0.f); 51 int cacheHits = fTotalRequests - fCacheMisses; 52 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); 53 SkDebugf("---------------------\n"); 54 } 55 #endif 56 } 57 58 void GrGLGpu::ProgramCache::abandon() { 59 #ifdef PROGRAM_CACHE_STATS 60 fTotalRequests = 0; 61 fCacheMisses = 0; 62 fHashMisses = 0; 63 #endif 64 65 fMap.foreach([](std::unique_ptr<Entry>* e) { 66 (*e)->fProgram->abandon(); 67 }); 68 fMap.reset(); 69 } 70 71 GrGLProgram* GrGLGpu::ProgramCache::refProgram(GrGLGpu* gpu, 72 GrRenderTarget* renderTarget, 73 GrSurfaceOrigin origin, 74 const GrPrimitiveProcessor& primProc, 75 const GrTextureProxy* const primProcProxies[], 76 const GrPipeline& pipeline, 77 bool isPoints) { 78 #ifdef PROGRAM_CACHE_STATS 79 ++fTotalRequests; 80 #endif 81 82 // Get GrGLProgramDesc 83 GrProgramDesc desc; 84 if (!GrProgramDesc::Build(&desc, renderTarget, primProc, isPoints, pipeline, gpu)) { 85 GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n"); 86 return nullptr; 87 } 88 std::unique_ptr<Entry>* entry = fMap.find(desc); 89 if (!entry) { 90 // Didn't find an origin-independent version, check with the specific origin 91 desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin)); 92 entry = fMap.find(desc); 93 } 94 if (!entry) { 95 // We have a cache miss 96 #ifdef PROGRAM_CACHE_STATS 97 ++fCacheMisses; 98 #endif 99 GrGLProgram* program = GrGLProgramBuilder::CreateProgram(renderTarget, origin, 100 primProc, primProcProxies, 101 pipeline, &desc, fGpu); 102 if (nullptr == program) { 103 return nullptr; 104 } 105 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(sk_sp<GrGLProgram>(program)))); 106 } 107 108 return SkRef((*entry)->fProgram.get()); 109 } 110