blob: dab80f04a4c8251b27b90e57ee7c528d155f3be5 [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
junov@google.comf93e7172011-03-31 21:26:24 +00006 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/gl/GrGLGpu.h"
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
Brian Osman172bb442019-09-06 10:16:02 -040010#include "include/gpu/GrContextOptions.h"
Adlai Holler3d0359a2020-07-09 15:35:55 -040011#include "include/gpu/GrDirectContext.h"
Brian Osman172bb442019-09-06 10:16:02 -040012#include "src/gpu/GrContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrProcessor.h"
14#include "src/gpu/GrProgramDesc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
16#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000017
bsalomon861e1032014-12-16 07:33:49 -080018struct GrGLGpu::ProgramCache::Entry {
Brian Osmaned58e002019-09-06 14:42:43 -040019 Entry(sk_sp<GrGLProgram> program)
20 : fProgram(std::move(program)) {}
21
22 Entry(const GrGLPrecompiledProgram& precompiledProgram)
23 : fPrecompiledProgram(precompiledProgram) {}
halcanary9d524f22016-03-29 09:03:52 -070024
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050025 sk_sp<GrGLProgram> fProgram;
Brian Osmaned58e002019-09-06 14:42:43 -040026 GrGLPrecompiledProgram fPrecompiledProgram;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000027};
junov@google.comf93e7172011-03-31 21:26:24 +000028
bsalomon861e1032014-12-16 07:33:49 -080029GrGLGpu::ProgramCache::ProgramCache(GrGLGpu* gpu)
Brian Osman172bb442019-09-06 10:16:02 -040030 : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
Brian Osmane9d9a322019-09-03 13:59:36 -040031 , fGpu(gpu) {}
jvanverth@google.com94878772013-03-12 16:00:54 +000032
Brian Osmane9d9a322019-09-03 13:59:36 -040033GrGLGpu::ProgramCache::~ProgramCache() {}
junov@google.comf93e7172011-03-31 21:26:24 +000034
egdaniel22281c12016-03-23 13:49:40 -070035void GrGLGpu::ProgramCache::abandon() {
Robert Phillipsf6a0b452020-02-18 14:26:46 -050036 fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) {
Brian Osmaned58e002019-09-06 14:42:43 -040037 if ((*e)->fProgram) {
38 (*e)->fProgram->abandon();
39 }
Brian Osman0b8bb882019-04-12 11:47:19 -040040 });
41
42 this->reset();
43}
44
45void GrGLGpu::ProgramCache::reset() {
Robert Phillips752e08b2018-06-22 09:48:38 -040046 fMap.reset();
joshualitt8fd844f2015-12-02 13:36:47 -080047}
48
Stephen Whiteb1857852020-02-07 15:33:23 +000049sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrRenderTarget* renderTarget,
50 const GrProgramInfo& programInfo) {
51 const GrCaps& caps = *fGpu->caps();
Robert Phillipsf272bea2019-10-17 08:56:16 -040052
Robert Phillips03e4c952019-11-26 16:20:22 -050053 GrProgramDesc desc = caps.makeDesc(renderTarget, programInfo);
54 if (!desc.isValid()) {
Robert Phillipsf6a0b452020-02-18 14:26:46 -050055 GrCapsDebugf(&caps, "Failed to gl program descriptor!\n");
egdaniel0e1853c2016-03-17 11:35:45 -070056 return nullptr;
57 }
Brian Osmane11dfd32019-07-23 10:29:41 -040058
Robert Phillips19f466d2020-02-26 10:27:07 -050059 Stats::ProgramCacheResult stat;
60 sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(renderTarget, desc, programInfo, &stat);
61 if (!tmp) {
62 fGpu->fStats.incNumInlineCompilationFailures();
63 } else {
64 fGpu->fStats.incNumInlineProgramCacheResult(stat);
65 }
66
67 return tmp;
Robert Phillips979b2232020-02-20 10:47:29 -050068}
69
70sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrRenderTarget* renderTarget,
71 const GrProgramDesc& desc,
Robert Phillips19f466d2020-02-26 10:27:07 -050072 const GrProgramInfo& programInfo,
73 Stats::ProgramCacheResult* stat) {
74 *stat = Stats::ProgramCacheResult::kHit;
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050075 std::unique_ptr<Entry>* entry = fMap.find(desc);
Brian Osmaned58e002019-09-06 14:42:43 -040076 if (entry && !(*entry)->fProgram) {
77 // We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding
78 const GrGLPrecompiledProgram* precompiledProgram = &((*entry)->fPrecompiledProgram);
79 SkASSERT(precompiledProgram->fProgramID != 0);
Stephen Whiteb1857852020-02-07 15:33:23 +000080 (*entry)->fProgram = GrGLProgramBuilder::CreateProgram(fGpu, renderTarget, desc,
81 programInfo, precompiledProgram);
82 if (!(*entry)->fProgram) {
Brian Osmaned58e002019-09-06 14:42:43 -040083 // Should we purge the program ID from the cache at this point?
84 SkDEBUGFAIL("Couldn't create program from precompiled program");
Robert Phillips19f466d2020-02-26 10:27:07 -050085 fGpu->fStats.incNumCompilationFailures();
Brian Osmaned58e002019-09-06 14:42:43 -040086 return nullptr;
87 }
Robert Phillips19f466d2020-02-26 10:27:07 -050088 fGpu->fStats.incNumPartialCompilationSuccesses();
89 *stat = Stats::ProgramCacheResult::kPartial;
Brian Osmaned58e002019-09-06 14:42:43 -040090 } else if (!entry) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000091 // We have a cache miss
Stephen Whiteb1857852020-02-07 15:33:23 +000092 sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(fGpu, renderTarget,
93 desc, programInfo);
94 if (!program) {
Robert Phillips19f466d2020-02-26 10:27:07 -050095 fGpu->fStats.incNumCompilationFailures();
halcanary96fcdcc2015-08-27 07:41:13 -070096 return nullptr;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000097 }
Robert Phillips19f466d2020-02-26 10:27:07 -050098 fGpu->fStats.incNumCompilationSuccesses();
Stephen Whiteb1857852020-02-07 15:33:23 +000099 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(std::move(program))));
Robert Phillips19f466d2020-02-26 10:27:07 -0500100 *stat = Stats::ProgramCacheResult::kMiss;
junov@google.comf93e7172011-03-31 21:26:24 +0000101 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000102
Stephen Whiteb1857852020-02-07 15:33:23 +0000103 return (*entry)->fProgram;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000104}
Brian Osmaned58e002019-09-06 14:42:43 -0400105
106bool GrGLGpu::ProgramCache::precompileShader(const SkData& key, const SkData& data) {
107 GrProgramDesc desc;
108 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
109 return false;
110 }
111
112 std::unique_ptr<Entry>* entry = fMap.find(desc);
113 if (entry) {
114 // We've already seen/compiled this shader
115 return true;
116 }
117
118 GrGLPrecompiledProgram precompiledProgram;
119 if (!GrGLProgramBuilder::PrecompileProgram(&precompiledProgram, fGpu, data)) {
120 return false;
121 }
122
123 fMap.insert(desc, std::unique_ptr<Entry>(new Entry(precompiledProgram)));
124 return true;
125}