• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/gpu/gl/GrGLGpu.h"
9 
10 #include "src/core/SkTSearch.h"
11 #include "src/gpu/GrProcessor.h"
12 #include "src/gpu/GrProgramDesc.h"
13 #include "src/gpu/gl/GrGLPathRendering.h"
14 #include "src/gpu/gl/builders/GrGLProgramBuilder.h"
15 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
16 #include "src/gpu/glsl/GrGLSLProgramDataManager.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 {
EntryGrGLGpu::ProgramCache::Entry26     Entry(sk_sp<GrGLProgram> program) : fProgram(std::move(program)) {}
27 
28     sk_sp<GrGLProgram> fProgram;
29 };
30 
ProgramCache(GrGLGpu * gpu)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 
~ProgramCache()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 
abandon()58 void GrGLGpu::ProgramCache::abandon() {
59     fMap.foreach([](std::unique_ptr<Entry>* e) {
60         (*e)->fProgram->abandon();
61     });
62 
63     this->reset();
64 }
65 
reset()66 void GrGLGpu::ProgramCache::reset() {
67 #ifdef PROGRAM_CACHE_STATS
68     fTotalRequests = 0;
69     fCacheMisses = 0;
70     fHashMisses = 0;
71 #endif
72 
73     fMap.reset();
74 }
75 
refProgram(GrGLGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,bool isPoints)76 GrGLProgram* GrGLGpu::ProgramCache::refProgram(GrGLGpu* gpu,
77                                                GrRenderTarget* renderTarget,
78                                                GrSurfaceOrigin origin,
79                                                const GrPrimitiveProcessor& primProc,
80                                                const GrTextureProxy* const primProcProxies[],
81                                                const GrPipeline& pipeline,
82                                                bool isPoints) {
83 #ifdef PROGRAM_CACHE_STATS
84     ++fTotalRequests;
85 #endif
86 
87     // Get GrGLProgramDesc
88     GrProgramDesc desc;
89     if (!GrProgramDesc::Build(&desc, renderTarget, primProc, isPoints, pipeline, gpu)) {
90         GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n");
91         return nullptr;
92     }
93     // If we knew the shader won't depend on origin, we could skip this (and use the same program
94     // for both origins). Instrumenting all fragment processors would be difficult and error prone.
95     desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
96 
97     std::unique_ptr<Entry>* entry = fMap.find(desc);
98     if (!entry) {
99         // We have a cache miss
100 #ifdef PROGRAM_CACHE_STATS
101         ++fCacheMisses;
102 #endif
103         GrGLProgram* program = GrGLProgramBuilder::CreateProgram(renderTarget, origin,
104                                                                  primProc, primProcProxies,
105                                                                  pipeline, &desc, fGpu);
106         if (nullptr == program) {
107             return nullptr;
108         }
109         entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(sk_sp<GrGLProgram>(program))));
110     }
111 
112     return SkRef((*entry)->fProgram.get());
113 }
114