• 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 <memory>
9 
10 #include "src/gpu/gl/GrGLGpu.h"
11 
12 #include "include/gpu/GrContextOptions.h"
13 #include "include/gpu/GrDirectContext.h"
14 #include "src/gpu/GrDirectContextPriv.h"
15 #include "src/gpu/GrFragmentProcessor.h"
16 #include "src/gpu/GrProcessor.h"
17 #include "src/gpu/GrProgramDesc.h"
18 #include "src/gpu/gl/builders/GrGLProgramBuilder.h"
19 
20 struct GrGLGpu::ProgramCache::Entry {
EntryGrGLGpu::ProgramCache::Entry21     Entry(sk_sp<GrGLProgram> program)
22         : fProgram(std::move(program)) {}
23 
EntryGrGLGpu::ProgramCache::Entry24     Entry(const GrGLPrecompiledProgram& precompiledProgram)
25         : fPrecompiledProgram(precompiledProgram) {}
26 
27     sk_sp<GrGLProgram> fProgram;
28     GrGLPrecompiledProgram fPrecompiledProgram;
29 };
30 
ProgramCache(int runtimeProgramCacheSize)31 GrGLGpu::ProgramCache::ProgramCache(int runtimeProgramCacheSize)
32     : fMap(runtimeProgramCacheSize) {
33 }
34 
~ProgramCache()35 GrGLGpu::ProgramCache::~ProgramCache() {}
36 
abandon()37 void GrGLGpu::ProgramCache::abandon() {
38     fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) {
39         if ((*e)->fProgram) {
40             (*e)->fProgram->abandon();
41         }
42     });
43 
44     this->reset();
45 }
46 
reset()47 void GrGLGpu::ProgramCache::reset() {
48     fMap.reset();
49 }
50 
findOrCreateProgram(GrDirectContext * dContext,const GrProgramInfo & programInfo)51 sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
52                                                               const GrProgramInfo& programInfo) {
53     const GrCaps* caps = dContext->priv().caps();
54 
55     GrProgramDesc desc = caps->makeDesc(/*renderTarget*/nullptr, programInfo);
56     if (!desc.isValid()) {
57         GrCapsDebugf(caps, "Failed to gl program descriptor!\n");
58         return nullptr;
59     }
60 
61     Stats::ProgramCacheResult stat;
62     sk_sp<GrGLProgram> tmp = this->findOrCreateProgramImpl(dContext, desc, programInfo, &stat);
63     if (!tmp) {
64         fStats.incNumInlineCompilationFailures();
65     } else {
66         fStats.incNumInlineProgramCacheResult(stat);
67     }
68 
69     return tmp;
70 }
71 
findOrCreateProgram(GrDirectContext * dContext,const GrProgramDesc & desc,const GrProgramInfo & programInfo,Stats::ProgramCacheResult * stat)72 sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
73                                                               const GrProgramDesc& desc,
74                                                               const GrProgramInfo& programInfo,
75                                                               Stats::ProgramCacheResult* stat) {
76     sk_sp<GrGLProgram> tmp = this->findOrCreateProgramImpl(dContext, desc, programInfo, stat);
77     if (!tmp) {
78         fStats.incNumPreCompilationFailures();
79     } else {
80         fStats.incNumPreProgramCacheResult(*stat);
81     }
82 
83     return tmp;
84 }
85 
findOrCreateProgramImpl(GrDirectContext * dContext,const GrProgramDesc & desc,const GrProgramInfo & programInfo,Stats::ProgramCacheResult * stat)86 sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgramImpl(GrDirectContext* dContext,
87                                                                   const GrProgramDesc& desc,
88                                                                   const GrProgramInfo& programInfo,
89                                                                   Stats::ProgramCacheResult* stat) {
90     *stat = Stats::ProgramCacheResult::kHit;
91     std::unique_ptr<Entry>* entry = fMap.find(desc);
92     if (entry && !(*entry)->fProgram) {
93         // We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding
94         const GrGLPrecompiledProgram* precompiledProgram = &((*entry)->fPrecompiledProgram);
95         SkASSERT(precompiledProgram->fProgramID != 0);
96         (*entry)->fProgram = GrGLProgramBuilder::CreateProgram(dContext, desc, programInfo,
97                                                                precompiledProgram);
98         if (!(*entry)->fProgram) {
99             // Should we purge the program ID from the cache at this point?
100             SkDEBUGFAIL("Couldn't create program from precompiled program");
101             fStats.incNumCompilationFailures();
102             return nullptr;
103         }
104         fStats.incNumPartialCompilationSuccesses();
105         *stat = Stats::ProgramCacheResult::kPartial;
106     } else if (!entry) {
107         // We have a cache miss
108         sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(dContext, desc, programInfo);
109         if (!program) {
110             fStats.incNumCompilationFailures();
111             return nullptr;
112         }
113         fStats.incNumCompilationSuccesses();
114         entry = fMap.insert(desc, std::make_unique<Entry>(std::move(program)));
115         *stat = Stats::ProgramCacheResult::kMiss;
116     }
117 
118     return (*entry)->fProgram;
119 }
120 
precompileShader(GrDirectContext * dContext,const SkData & key,const SkData & data)121 bool GrGLGpu::ProgramCache::precompileShader(GrDirectContext* dContext,
122                                              const SkData& key,
123                                              const SkData& data) {
124     GrProgramDesc desc;
125     if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
126         return false;
127     }
128 
129     std::unique_ptr<Entry>* entry = fMap.find(desc);
130     if (entry) {
131         // We've already seen/compiled this shader
132         return true;
133     }
134 
135     GrGLPrecompiledProgram precompiledProgram;
136     if (!GrGLProgramBuilder::PrecompileProgram(dContext, &precompiledProgram, data)) {
137         return false;
138     }
139 
140     fMap.insert(desc, std::make_unique<Entry>(precompiledProgram));
141     return true;
142 }
143