blob: 53fd5453e9725e851734ffe22dd743753275c731 [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
John Stilesfbd050b2020-08-03 13:21:46 -04008#include <memory>
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/gl/GrGLGpu.h"
epoger@google.comec3ed6a2011-07-28 14:26:00 +000011
Brian Osman172bb442019-09-06 10:16:02 -040012#include "include/gpu/GrContextOptions.h"
Adlai Holler3d0359a2020-07-09 15:35:55 -040013#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -040014#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrProcessor.h"
16#include "src/gpu/GrProgramDesc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
18#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000019
bsalomon861e1032014-12-16 07:33:49 -080020struct GrGLGpu::ProgramCache::Entry {
Brian Osmaned58e002019-09-06 14:42:43 -040021 Entry(sk_sp<GrGLProgram> program)
22 : fProgram(std::move(program)) {}
23
24 Entry(const GrGLPrecompiledProgram& precompiledProgram)
25 : fPrecompiledProgram(precompiledProgram) {}
halcanary9d524f22016-03-29 09:03:52 -070026
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050027 sk_sp<GrGLProgram> fProgram;
Brian Osmaned58e002019-09-06 14:42:43 -040028 GrGLPrecompiledProgram fPrecompiledProgram;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000029};
junov@google.comf93e7172011-03-31 21:26:24 +000030
Robert Phillips962708f2021-03-03 14:42:04 -050031GrGLGpu::ProgramCache::ProgramCache(int runtimeProgramCacheSize)
32 : fMap(runtimeProgramCacheSize) {
33}
jvanverth@google.com94878772013-03-12 16:00:54 +000034
Brian Osmane9d9a322019-09-03 13:59:36 -040035GrGLGpu::ProgramCache::~ProgramCache() {}
junov@google.comf93e7172011-03-31 21:26:24 +000036
egdaniel22281c12016-03-23 13:49:40 -070037void GrGLGpu::ProgramCache::abandon() {
Robert Phillipsf6a0b452020-02-18 14:26:46 -050038 fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) {
Brian Osmaned58e002019-09-06 14:42:43 -040039 if ((*e)->fProgram) {
40 (*e)->fProgram->abandon();
41 }
Brian Osman0b8bb882019-04-12 11:47:19 -040042 });
43
44 this->reset();
45}
46
47void GrGLGpu::ProgramCache::reset() {
Robert Phillips752e08b2018-06-22 09:48:38 -040048 fMap.reset();
joshualitt8fd844f2015-12-02 13:36:47 -080049}
50
Robert Phillips962708f2021-03-03 14:42:04 -050051sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
52 GrRenderTarget* renderTarget,
Stephen Whiteb1857852020-02-07 15:33:23 +000053 const GrProgramInfo& programInfo) {
Robert Phillips962708f2021-03-03 14:42:04 -050054 const GrCaps* caps = dContext->priv().caps();
Robert Phillipsf272bea2019-10-17 08:56:16 -040055
Robert Phillips962708f2021-03-03 14:42:04 -050056 GrProgramDesc desc = caps->makeDesc(renderTarget, programInfo);
Robert Phillips03e4c952019-11-26 16:20:22 -050057 if (!desc.isValid()) {
Robert Phillips962708f2021-03-03 14:42:04 -050058 GrCapsDebugf(caps, "Failed to gl program descriptor!\n");
egdaniel0e1853c2016-03-17 11:35:45 -070059 return nullptr;
60 }
Brian Osmane11dfd32019-07-23 10:29:41 -040061
Robert Phillips19f466d2020-02-26 10:27:07 -050062 Stats::ProgramCacheResult stat;
Robert Phillips962708f2021-03-03 14:42:04 -050063 sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(dContext, renderTarget, desc,
64 programInfo, &stat);
Robert Phillips19f466d2020-02-26 10:27:07 -050065 if (!tmp) {
Robert Phillipsae67c522021-03-03 11:03:38 -050066 fStats.incNumInlineCompilationFailures();
Robert Phillips19f466d2020-02-26 10:27:07 -050067 } else {
Robert Phillipsae67c522021-03-03 11:03:38 -050068 fStats.incNumInlineProgramCacheResult(stat);
Robert Phillips19f466d2020-02-26 10:27:07 -050069 }
70
71 return tmp;
Robert Phillips979b2232020-02-20 10:47:29 -050072}
73
Robert Phillips962708f2021-03-03 14:42:04 -050074sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
Robert Phillips22970172021-03-22 11:26:45 -040075 const GrProgramDesc& desc,
76 const GrProgramInfo& programInfo,
77 Stats::ProgramCacheResult* stat) {
78 sk_sp<GrGLProgram> tmp = this->findOrCreateProgram(dContext, nullptr, desc, programInfo, stat);
79 if (!tmp) {
80 fStats.incNumPreCompilationFailures();
81 } else {
82 fStats.incNumPreProgramCacheResult(*stat);
83 }
84
85 return tmp;
86}
87
88sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext,
Robert Phillips962708f2021-03-03 14:42:04 -050089 GrRenderTarget* renderTarget,
Robert Phillips979b2232020-02-20 10:47:29 -050090 const GrProgramDesc& desc,
Robert Phillips19f466d2020-02-26 10:27:07 -050091 const GrProgramInfo& programInfo,
92 Stats::ProgramCacheResult* stat) {
93 *stat = Stats::ProgramCacheResult::kHit;
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050094 std::unique_ptr<Entry>* entry = fMap.find(desc);
Brian Osmaned58e002019-09-06 14:42:43 -040095 if (entry && !(*entry)->fProgram) {
96 // We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding
97 const GrGLPrecompiledProgram* precompiledProgram = &((*entry)->fPrecompiledProgram);
98 SkASSERT(precompiledProgram->fProgramID != 0);
Robert Phillips962708f2021-03-03 14:42:04 -050099 (*entry)->fProgram = GrGLProgramBuilder::CreateProgram(dContext, renderTarget, desc,
Stephen Whiteb1857852020-02-07 15:33:23 +0000100 programInfo, precompiledProgram);
101 if (!(*entry)->fProgram) {
Brian Osmaned58e002019-09-06 14:42:43 -0400102 // Should we purge the program ID from the cache at this point?
103 SkDEBUGFAIL("Couldn't create program from precompiled program");
Robert Phillipsae67c522021-03-03 11:03:38 -0500104 fStats.incNumCompilationFailures();
Brian Osmaned58e002019-09-06 14:42:43 -0400105 return nullptr;
106 }
Robert Phillipsae67c522021-03-03 11:03:38 -0500107 fStats.incNumPartialCompilationSuccesses();
Robert Phillips19f466d2020-02-26 10:27:07 -0500108 *stat = Stats::ProgramCacheResult::kPartial;
Brian Osmaned58e002019-09-06 14:42:43 -0400109 } else if (!entry) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000110 // We have a cache miss
Robert Phillips962708f2021-03-03 14:42:04 -0500111 sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(dContext, renderTarget,
Stephen Whiteb1857852020-02-07 15:33:23 +0000112 desc, programInfo);
113 if (!program) {
Robert Phillipsae67c522021-03-03 11:03:38 -0500114 fStats.incNumCompilationFailures();
halcanary96fcdcc2015-08-27 07:41:13 -0700115 return nullptr;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000116 }
Robert Phillipsae67c522021-03-03 11:03:38 -0500117 fStats.incNumCompilationSuccesses();
John Stilesfbd050b2020-08-03 13:21:46 -0400118 entry = fMap.insert(desc, std::make_unique<Entry>(std::move(program)));
Robert Phillips19f466d2020-02-26 10:27:07 -0500119 *stat = Stats::ProgramCacheResult::kMiss;
junov@google.comf93e7172011-03-31 21:26:24 +0000120 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000121
Stephen Whiteb1857852020-02-07 15:33:23 +0000122 return (*entry)->fProgram;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000123}
Brian Osmaned58e002019-09-06 14:42:43 -0400124
Robert Phillips962708f2021-03-03 14:42:04 -0500125bool GrGLGpu::ProgramCache::precompileShader(GrDirectContext* dContext,
126 const SkData& key,
127 const SkData& data) {
Brian Osmaned58e002019-09-06 14:42:43 -0400128 GrProgramDesc desc;
129 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
130 return false;
131 }
132
133 std::unique_ptr<Entry>* entry = fMap.find(desc);
134 if (entry) {
135 // We've already seen/compiled this shader
136 return true;
137 }
138
139 GrGLPrecompiledProgram precompiledProgram;
Robert Phillips962708f2021-03-03 14:42:04 -0500140 if (!GrGLProgramBuilder::PrecompileProgram(dContext, &precompiledProgram, data)) {
Brian Osmaned58e002019-09-06 14:42:43 -0400141 return false;
142 }
143
John Stilesfbd050b2020-08-03 13:21:46 -0400144 fMap.insert(desc, std::make_unique<Entry>(precompiledProgram));
Brian Osmaned58e002019-09-06 14:42:43 -0400145 return true;
146}