blob: bf54a883980de7a0be97181b1dadcc864bbf77a5 [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"
11#include "src/gpu/GrContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrProcessor.h"
13#include "src/gpu/GrProgramDesc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
15#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000016
bsalomon861e1032014-12-16 07:33:49 -080017struct GrGLGpu::ProgramCache::Entry {
Brian Osmaned58e002019-09-06 14:42:43 -040018 Entry(sk_sp<GrGLProgram> program)
19 : fProgram(std::move(program)) {}
20
21 Entry(const GrGLPrecompiledProgram& precompiledProgram)
22 : fPrecompiledProgram(precompiledProgram) {}
halcanary9d524f22016-03-29 09:03:52 -070023
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050024 sk_sp<GrGLProgram> fProgram;
Brian Osmaned58e002019-09-06 14:42:43 -040025 GrGLPrecompiledProgram fPrecompiledProgram;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000026};
junov@google.comf93e7172011-03-31 21:26:24 +000027
bsalomon861e1032014-12-16 07:33:49 -080028GrGLGpu::ProgramCache::ProgramCache(GrGLGpu* gpu)
Brian Osman172bb442019-09-06 10:16:02 -040029 : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
Brian Osmane9d9a322019-09-03 13:59:36 -040030 , fGpu(gpu) {}
jvanverth@google.com94878772013-03-12 16:00:54 +000031
Brian Osmane9d9a322019-09-03 13:59:36 -040032GrGLGpu::ProgramCache::~ProgramCache() {}
junov@google.comf93e7172011-03-31 21:26:24 +000033
egdaniel22281c12016-03-23 13:49:40 -070034void GrGLGpu::ProgramCache::abandon() {
Robert Phillipsf6a0b452020-02-18 14:26:46 -050035 fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) {
Brian Osmaned58e002019-09-06 14:42:43 -040036 if ((*e)->fProgram) {
37 (*e)->fProgram->abandon();
38 }
Brian Osman0b8bb882019-04-12 11:47:19 -040039 });
40
41 this->reset();
42}
43
44void GrGLGpu::ProgramCache::reset() {
Robert Phillips752e08b2018-06-22 09:48:38 -040045 fMap.reset();
joshualitt8fd844f2015-12-02 13:36:47 -080046}
47
Stephen Whiteb1857852020-02-07 15:33:23 +000048sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrRenderTarget* renderTarget,
49 const GrProgramInfo& programInfo) {
50 const GrCaps& caps = *fGpu->caps();
Robert Phillipsf272bea2019-10-17 08:56:16 -040051
Robert Phillips03e4c952019-11-26 16:20:22 -050052 GrProgramDesc desc = caps.makeDesc(renderTarget, programInfo);
53 if (!desc.isValid()) {
Robert Phillipsf6a0b452020-02-18 14:26:46 -050054 GrCapsDebugf(&caps, "Failed to gl program descriptor!\n");
egdaniel0e1853c2016-03-17 11:35:45 -070055 return nullptr;
56 }
Brian Osmane11dfd32019-07-23 10:29:41 -040057
Robert Phillips19f466d2020-02-26 10:27:07 -050058 Stats::ProgramCacheResult stat;
59 sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(renderTarget, desc, programInfo, &stat);
60 if (!tmp) {
61 fGpu->fStats.incNumInlineCompilationFailures();
62 } else {
63 fGpu->fStats.incNumInlineProgramCacheResult(stat);
64 }
65
66 return tmp;
Robert Phillips979b2232020-02-20 10:47:29 -050067}
68
69sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrRenderTarget* renderTarget,
70 const GrProgramDesc& desc,
Robert Phillips19f466d2020-02-26 10:27:07 -050071 const GrProgramInfo& programInfo,
72 Stats::ProgramCacheResult* stat) {
73 *stat = Stats::ProgramCacheResult::kHit;
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050074 std::unique_ptr<Entry>* entry = fMap.find(desc);
Brian Osmaned58e002019-09-06 14:42:43 -040075 if (entry && !(*entry)->fProgram) {
76 // We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding
77 const GrGLPrecompiledProgram* precompiledProgram = &((*entry)->fPrecompiledProgram);
78 SkASSERT(precompiledProgram->fProgramID != 0);
Stephen Whiteb1857852020-02-07 15:33:23 +000079 (*entry)->fProgram = GrGLProgramBuilder::CreateProgram(fGpu, renderTarget, desc,
80 programInfo, precompiledProgram);
81 if (!(*entry)->fProgram) {
Brian Osmaned58e002019-09-06 14:42:43 -040082 // Should we purge the program ID from the cache at this point?
83 SkDEBUGFAIL("Couldn't create program from precompiled program");
Robert Phillips19f466d2020-02-26 10:27:07 -050084 fGpu->fStats.incNumCompilationFailures();
Brian Osmaned58e002019-09-06 14:42:43 -040085 return nullptr;
86 }
Robert Phillips19f466d2020-02-26 10:27:07 -050087 fGpu->fStats.incNumPartialCompilationSuccesses();
88 *stat = Stats::ProgramCacheResult::kPartial;
Brian Osmaned58e002019-09-06 14:42:43 -040089 } else if (!entry) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000090 // We have a cache miss
Stephen Whiteb1857852020-02-07 15:33:23 +000091 sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(fGpu, renderTarget,
92 desc, programInfo);
93 if (!program) {
Robert Phillips19f466d2020-02-26 10:27:07 -050094 fGpu->fStats.incNumCompilationFailures();
halcanary96fcdcc2015-08-27 07:41:13 -070095 return nullptr;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000096 }
Robert Phillips19f466d2020-02-26 10:27:07 -050097 fGpu->fStats.incNumCompilationSuccesses();
Stephen Whiteb1857852020-02-07 15:33:23 +000098 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(std::move(program))));
Robert Phillips19f466d2020-02-26 10:27:07 -050099 *stat = Stats::ProgramCacheResult::kMiss;
junov@google.comf93e7172011-03-31 21:26:24 +0000100 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000101
Stephen Whiteb1857852020-02-07 15:33:23 +0000102 return (*entry)->fProgram;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000103}
Brian Osmaned58e002019-09-06 14:42:43 -0400104
105bool GrGLGpu::ProgramCache::precompileShader(const SkData& key, const SkData& data) {
106 GrProgramDesc desc;
107 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
108 return false;
109 }
110
111 std::unique_ptr<Entry>* entry = fMap.find(desc);
112 if (entry) {
113 // We've already seen/compiled this shader
114 return true;
115 }
116
117 GrGLPrecompiledProgram precompiledProgram;
118 if (!GrGLProgramBuilder::PrecompileProgram(&precompiledProgram, fGpu, data)) {
119 return false;
120 }
121
122 fMap.insert(desc, std::unique_ptr<Entry>(new Entry(precompiledProgram)));
123 return true;
124}