2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
10 #include "src/gpu/ganesh/gl/GrGLGpu.h"
12 #include "include/gpu/GrContextOptions.h"
13 #include "include/gpu/GrDirectContext.h"
14 #include "src/gpu/ganesh/GrDirectContextPriv.h"
15 #include "src/gpu/ganesh/GrFragmentProcessor.h"
16 #include "src/gpu/ganesh/GrProcessor.h"
17 #include "src/gpu/ganesh/GrProgramDesc.h"
18 #include "src/gpu/ganesh/gl/builders/GrGLProgramBuilder.h"
20 struct GrGLGpu::ProgramCache::Entry {
21 Entry(sk_sp<GrGLProgram> program)
22 : fProgram(std::move(program)) {}
24 Entry(const GrGLPrecompiledProgram& precompiledProgram)
25 : fPrecompiledProgram(precompiledProgram) {}
27 sk_sp<GrGLProgram> fProgram;
28 GrGLPrecompiledProgram fPrecompiledProgram;
31 GrGLGpu::ProgramCache::ProgramCache(int runtimeProgramCacheSize)
32 : fMap(runtimeProgramCacheSize) {
35 GrGLGpu::ProgramCache::~ProgramCache() {}
37 void GrGLGpu::ProgramCache::abandon() {
38 fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) {
40 (*e)->fProgram->abandon();
47 void GrGLGpu::ProgramCache::reset() {
51 sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
52 const GrProgramInfo& programInfo) {
53 const GrCaps* caps = dContext->priv().caps();
55 GrProgramDesc desc = caps->makeDesc(/*renderTarget*/nullptr, programInfo);
56 if (!desc.isValid()) {
57 GrCapsDebugf(caps, "Failed to gl program descriptor!\n");
61 Stats::ProgramCacheResult stat;
62 sk_sp<GrGLProgram> tmp = this->findOrCreateProgramImpl(dContext, desc, programInfo, &stat);
64 fStats.incNumInlineCompilationFailures();
66 fStats.incNumInlineProgramCacheResult(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);
78 fStats.incNumPreCompilationFailures();
80 fStats.incNumPreProgramCacheResult(*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,
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();
104 fStats.incNumPartialCompilationSuccesses();
105 *stat = Stats::ProgramCacheResult::kPartial;
107 // We have a cache miss
108 sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(dContext, desc, programInfo);
110 fStats.incNumCompilationFailures();
113 fStats.incNumCompilationSuccesses();
114 entry = fMap.insert(desc, std::make_unique<Entry>(std::move(program)));
115 *stat = Stats::ProgramCacheResult::kMiss;
118 return (*entry)->fProgram;
121 bool GrGLGpu::ProgramCache::precompileShader(GrDirectContext* dContext,
123 const SkData& data) {
125 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
129 std::unique_ptr<Entry>* entry = fMap.find(desc);
131 // We've already seen/compiled this shader
135 GrGLPrecompiledProgram precompiledProgram;
136 if (!GrGLProgramBuilder::PrecompileProgram(dContext, &precompiledProgram, data)) {
140 fMap.insert(desc, std::make_unique<Entry>(precompiledProgram));