blob: 4495b80b4c5edb3dbea13510f78478ff68529426 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
2 * Copyright 2014 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
joshualitt8072caa2015-02-12 14:20:52 -08009
Adlai Holler3d0359a2020-07-09 15:35:55 -040010#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkATrace.h"
12#include "src/core/SkAutoMalloc.h"
Brian Osman9e4e4c72020-06-10 07:19:34 -040013#include "src/core/SkReadBuffer.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkTraceEvent.h"
Brian Osman9e4e4c72020-06-10 07:19:34 -040015#include "src/core/SkWriteBuffer.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrAutoLocaleSetter.h"
Adlai Hollera0693042020-10-14 11:23:11 -040017#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrPersistentCacheUtils.h"
19#include "src/gpu/GrProgramDesc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrShaderCaps.h"
Brian Osmanac9be9d2019-05-01 10:29:34 -040021#include "src/gpu/GrShaderUtils.h"
Brian Salomon3ec1f542019-06-17 17:54:57 +000022#include "src/gpu/GrSwizzle.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/gl/GrGLGpu.h"
24#include "src/gpu/gl/GrGLProgram.h"
25#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
John Stilesfbd050b2020-08-03 13:21:46 -040026
27#include <memory>
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/gpu/gl/builders/GrGLShaderStringBuilder.h"
29#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
30#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
31#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
32#include "src/gpu/glsl/GrGLSLXferProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070033
joshualitt30ba4362014-08-21 20:18:45 -070034#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
35#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
36
Brian Osmaned58e002019-09-06 14:42:43 -040037static void cleanup_shaders(GrGLGpu* gpu, const SkTDArray<GrGLuint>& shaderIDs) {
38 for (int i = 0; i < shaderIDs.count(); ++i) {
39 GR_GL_CALL(gpu->glInterface(), DeleteShader(shaderIDs[i]));
40 }
41}
42
43static void cleanup_program(GrGLGpu* gpu, GrGLuint programID,
44 const SkTDArray<GrGLuint>& shaderIDs) {
45 GR_GL_CALL(gpu->glInterface(), DeleteProgram(programID));
46 cleanup_shaders(gpu, shaderIDs);
47}
48
Stephen Whiteb1857852020-02-07 15:33:23 +000049sk_sp<GrGLProgram> GrGLProgramBuilder::CreateProgram(
Robert Phillips962708f2021-03-03 14:42:04 -050050 GrDirectContext* dContext,
Stephen Whiteb1857852020-02-07 15:33:23 +000051 GrRenderTarget* renderTarget,
52 const GrProgramDesc& desc,
53 const GrProgramInfo& programInfo,
Brian Osmaned58e002019-09-06 14:42:43 -040054 const GrGLPrecompiledProgram* precompiledProgram) {
Brian Osmand010f652021-02-24 13:59:39 -050055 TRACE_EVENT0_ALWAYS("skia.gpu", "shader_compile");
bsalomon3318ee72015-03-16 11:56:29 -070056 GrAutoLocaleSetter als("C");
57
Robert Phillips962708f2021-03-03 14:42:04 -050058 GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
59
joshualitt47bb3822014-10-07 16:43:25 -070060 // create a builder. This will be handed off to effects so they can use it to add
61 // uniforms, varyings, textures, etc
Robert Phillips962708f2021-03-03 14:42:04 -050062 GrGLProgramBuilder builder(glGpu, renderTarget, desc, programInfo);
joshualitt47bb3822014-10-07 16:43:25 -070063
Robert Phillips962708f2021-03-03 14:42:04 -050064 auto persistentCache = dContext->priv().getPersistentCache();
Brian Osmaned58e002019-09-06 14:42:43 -040065 if (persistentCache && !precompiledProgram) {
Stephen Whiteb1857852020-02-07 15:33:23 +000066 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
Robert Phillips0c4b7b12018-03-06 08:20:37 -050067 builder.fCached = persistentCache->load(*key);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040068 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
69 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
70 // to skip the SkSL->GLSL step on a cache hit.
71 }
Ethan Nicholas2983f402017-05-08 09:36:08 -040072 if (!builder.emitAndInstallProcs()) {
halcanary96fcdcc2015-08-27 07:41:13 -070073 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070074 }
Brian Osmaned58e002019-09-06 14:42:43 -040075 return builder.finalize(precompiledProgram);
joshualitt47bb3822014-10-07 16:43:25 -070076}
77
joshualitt47bb3822014-10-07 16:43:25 -070078/////////////////////////////////////////////////////////////////////////////
79
egdaniel0e1853c2016-03-17 11:35:45 -070080GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
Robert Phillipsd0fe8752019-01-31 14:13:59 -050081 GrRenderTarget* renderTarget,
Stephen Whiteb1857852020-02-07 15:33:23 +000082 const GrProgramDesc& desc,
83 const GrProgramInfo& programInfo)
84 : INHERITED(renderTarget, desc, programInfo)
Brian Salomon802cb312018-06-08 18:05:20 -040085 , fGpu(gpu)
86 , fVaryingHandler(this)
87 , fUniformHandler(this)
Brian Salomon92be2f72018-06-19 14:33:47 -040088 , fVertexAttributeCnt(0)
89 , fInstanceAttributeCnt(0)
Brian Salomon802cb312018-06-08 18:05:20 -040090 , fVertexStride(0)
91 , fInstanceStride(0) {}
joshualitt30ba4362014-08-21 20:18:45 -070092
egdanielfa896322016-01-13 12:19:30 -080093const GrCaps* GrGLProgramBuilder::caps() const {
94 return fGpu->caps();
95}
96
Ethan Nicholasee9cb6a2021-02-02 11:59:09 -050097SkSL::Compiler* GrGLProgramBuilder::shaderCompiler() const {
98 return fGpu->shaderCompiler();
99}
100
Brian Osmanac9be9d2019-05-01 10:29:34 -0400101bool GrGLProgramBuilder::compileAndAttachShaders(const SkSL::String& glsl,
egdaniel574a4c12015-11-02 06:22:44 -0800102 GrGLuint programId,
103 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500104 SkTDArray<GrGLuint>* shaderIds,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400105 GrContextOptions::ShaderErrorHandler* errHandler) {
egdaniel574a4c12015-11-02 06:22:44 -0800106 GrGLGpu* gpu = this->gpu();
107 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
108 programId,
109 type,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400110 glsl,
Robert Phillipsae67c522021-03-03 11:03:38 -0500111 gpu->pipelineBuilder()->stats(),
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400112 errHandler);
egdaniel574a4c12015-11-02 06:22:44 -0800113 if (!shaderId) {
114 return false;
115 }
116
117 *shaderIds->append() = shaderId;
egdaniel574a4c12015-11-02 06:22:44 -0800118 return true;
119}
120
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400121void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
122 const GrPrimitiveProcessor& primProc,
123 bool bindAttribLocations) {
124 fVertexAttributeCnt = primProc.numVertexAttributes();
125 fInstanceAttributeCnt = primProc.numInstanceAttributes();
John Stilesfbd050b2020-08-03 13:21:46 -0400126 fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
127 fVertexAttributeCnt + fInstanceAttributeCnt);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400128 auto addAttr = [&](int i, const auto& a, size_t* stride) {
Brian Osman4a3f5c82018-09-18 16:16:38 -0400129 fAttributes[i].fCPUType = a.cpuType();
130 fAttributes[i].fGPUType = a.gpuType();
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400131 fAttributes[i].fOffset = *stride;
132 *stride += a.sizeAlign4();
133 fAttributes[i].fLocation = i;
134 if (bindAttribLocations) {
135 GL_CALL(BindAttribLocation(programID, i, a.name()));
136 }
137 };
138 fVertexStride = 0;
139 int i = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500140 for (const auto& attr : primProc.vertexAttributes()) {
141 addAttr(i++, attr, &fVertexStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400142 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500143 SkASSERT(fVertexStride == primProc.vertexStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400144 fInstanceStride = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500145 for (const auto& attr : primProc.instanceAttributes()) {
146 addAttr(i++, attr, &fInstanceStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400147 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500148 SkASSERT(fInstanceStride == primProc.instanceStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400149}
150
Ethan Nicholascd700e92018-08-24 16:43:57 -0400151void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
152 if (inputs.fRTWidth) {
153 this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
154 }
155 if (inputs.fRTHeight) {
156 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
157 }
158}
159
Brian Osmana085a412019-04-25 09:44:43 -0400160static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
161static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
Brian Osmana66081d2019-09-03 14:59:26 -0400162static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
Brian Osmana085a412019-04-25 09:44:43 -0400163
Ethan Nicholas8d058832019-01-07 10:49:58 -0500164void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
Brian Osmaned58e002019-09-06 14:42:43 -0400165 const SkSL::String shaders[], bool isSkSL,
Brian Osman4524e842019-09-24 16:03:41 -0400166 SkSL::Program::Settings* settings) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500167 if (!this->gpu()->getContext()->priv().getPersistentCache()) {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500168 return;
169 }
Stephen Whiteb1857852020-02-07 15:33:23 +0000170 sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().keyLength());
Brian Osmane23c03d2021-03-05 14:58:25 -0500171 SkString description = GrProgramDesc::Describe(fRenderTarget, fProgramInfo, *fGpu->caps());
Ethan Nicholas8d058832019-01-07 10:49:58 -0500172 if (fGpu->glCaps().programBinarySupport()) {
173 // binary cache
174 GrGLsizei length = 0;
175 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
176 if (length > 0) {
Brian Osman9e4e4c72020-06-10 07:19:34 -0400177 SkBinaryWriteBuffer writer;
178 writer.writeInt(GrPersistentCacheUtils::kCurrentVersion);
179 writer.writeUInt(kGLPB_Tag);
Brian Osmana66081d2019-09-03 14:59:26 -0400180
Brian Osman9e4e4c72020-06-10 07:19:34 -0400181 writer.writePad32(&inputs, sizeof(inputs));
Brian Osman6b797fe2019-04-08 13:56:36 -0400182
Brian Osman9e4e4c72020-06-10 07:19:34 -0400183 SkAutoSMalloc<2048> binary(length);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500184 GrGLenum binaryFormat;
Brian Osman9e4e4c72020-06-10 07:19:34 -0400185 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
186
187 writer.writeUInt(binaryFormat);
188 writer.writeInt(length);
189 writer.writePad32(binary.get(), length);
Brian Osman6b797fe2019-04-08 13:56:36 -0400190
191 auto data = writer.snapshotAsData();
Brian Osmanf0de96f2021-02-26 13:54:11 -0500192 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500193 }
194 } else {
Brian Osman4524e842019-09-24 16:03:41 -0400195 // source cache, plus metadata to allow for a complete precompile
196 GrPersistentCacheUtils::ShaderMetadata meta;
197 meta.fSettings = settings;
198 meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
199 meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
200 for (const auto& attr : this->primitiveProcessor().vertexAttributes()) {
201 meta.fAttributeNames.emplace_back(attr.name());
202 }
203 for (const auto& attr : this->primitiveProcessor().instanceAttributes()) {
204 meta.fAttributeNames.emplace_back(attr.name());
205 }
206
Brian Osmana085a412019-04-25 09:44:43 -0400207 auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
Brian Osman4524e842019-09-24 16:03:41 -0400208 shaders, &inputs, 1, &meta);
Brian Osmanf0de96f2021-02-26 13:54:11 -0500209 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500210 }
211}
212
Stephen Whiteb1857852020-02-07 15:33:23 +0000213sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
Brian Salomon5f394272019-07-02 14:07:49 -0400214 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
Ryan Macnak38a10ad2017-07-10 10:36:34 -0700215
joshualitt47bb3822014-10-07 16:43:25 -0700216 // verify we can get a program id
217 GrGLuint programID;
Brian Osmaned58e002019-09-06 14:42:43 -0400218 if (precompiledProgram) {
219 programID = precompiledProgram->fProgramID;
220 } else {
221 GL_CALL_RET(programID, CreateProgram());
222 }
joshualitt47bb3822014-10-07 16:43:25 -0700223 if (0 == programID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700224 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700225 }
226
Ethan Nicholas06d55fb2017-11-08 09:48:50 -0500227 if (this->gpu()->glCaps().programBinarySupport() &&
Brian Osman064729e2019-06-18 17:22:59 -0400228 this->gpu()->glCaps().programParameterSupport() &&
Brian Osmaned58e002019-09-06 14:42:43 -0400229 this->gpu()->getContext()->priv().getPersistentCache() &&
230 !precompiledProgram) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400231 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
232 }
233
egdaniel9f1d4152016-02-10 09:50:38 -0800234 this->finalizeShaders();
235
joshualitt47bb3822014-10-07 16:43:25 -0700236 // compile shaders and bind attributes / uniforms
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400237 auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400238 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500239 SkSL::Program::Settings settings;
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500240 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
Robert Phillipsc1541ae2019-02-04 12:05:37 -0500241 settings.fSharpenTextures =
Robert Phillips9da87e02019-02-04 13:26:26 -0500242 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
Brian Salomondc092132018-04-04 10:14:16 -0400243 settings.fFragColorIsInOut = this->fragColorIsInOut();
244
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500245 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700246 SkTDArray<GrGLuint> shadersToDelete;
Brian Salomond8575452020-02-25 12:13:29 -0500247
248 bool checkLinked = !fGpu->glCaps().skipErrorChecks();
249
Ethan Nicholas8d058832019-01-07 10:49:58 -0500250 bool cached = fCached.get() != nullptr;
Brian Osman2c60a382019-06-26 15:19:30 -0400251 bool usedProgramBinaries = false;
Brian Osman6b797fe2019-04-08 13:56:36 -0400252 SkSL::String glsl[kGrShaderTypeCount];
Brian Osmancbc33b82019-04-19 14:16:19 -0400253 SkSL::String* sksl[kGrShaderTypeCount] = {
254 &fVS.fCompilerString,
255 &fGS.fCompilerString,
256 &fFS.fCompilerString,
257 };
Brian Osmancbc33b82019-04-19 14:16:19 -0400258 SkSL::String cached_sksl[kGrShaderTypeCount];
Brian Osmaned58e002019-09-06 14:42:43 -0400259 if (precompiledProgram) {
260 // This is very similar to when we get program binaries. We even set that flag, as it's
261 // used to prevent other compile work later, and to force re-querying uniform locations.
262 this->addInputVars(precompiledProgram->fInputs);
Brian Osman4524e842019-09-24 16:03:41 -0400263 this->computeCountsAndStrides(programID, primProc, false);
Brian Osmaned58e002019-09-06 14:42:43 -0400264 usedProgramBinaries = true;
265 } else if (cached) {
Brian Osmand010f652021-02-24 13:59:39 -0500266 TRACE_EVENT0_ALWAYS("skia.gpu", "cache_hit");
Brian Osman9e4e4c72020-06-10 07:19:34 -0400267 SkReadBuffer reader(fCached->data(), fCached->size());
Brian Osman1facd5e2020-03-16 16:21:24 -0400268 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
Brian Osmana66081d2019-09-03 14:59:26 -0400269
270 switch (shaderType) {
271 case kGLPB_Tag: {
272 // Program binary cache hit. We may opt not to use this if we don't trust program
273 // binaries on this driver
274 if (!fGpu->glCaps().programBinarySupport()) {
275 cached = false;
276 break;
Ethan Nicholas8d058832019-01-07 10:49:58 -0500277 }
Brian Osman9e4e4c72020-06-10 07:19:34 -0400278 reader.readPad32(&inputs, sizeof(inputs));
279 GrGLenum binaryFormat = reader.readUInt();
280 GrGLsizei length = reader.readInt();
Brian Osmana66081d2019-09-03 14:59:26 -0400281 const void* binary = reader.skip(length);
Brian Osman9e4e4c72020-06-10 07:19:34 -0400282 if (!reader.isValid()) {
283 break;
284 }
Brian Salomon24069eb2020-06-24 10:19:52 -0400285 this->gpu()->clearErrorsAndCheckForOOM();
Brian Osmana66081d2019-09-03 14:59:26 -0400286 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
287 ProgramBinary(programID, binaryFormat,
288 const_cast<void*>(binary), length));
Brian Salomon24069eb2020-06-24 10:19:52 -0400289 if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) {
Brian Osmana66081d2019-09-03 14:59:26 -0400290 if (checkLinked) {
291 cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
292 }
293 if (cached) {
294 this->addInputVars(inputs);
295 this->computeCountsAndStrides(programID, primProc, false);
296 }
297 } else {
298 cached = false;
Ethan Nicholas8d058832019-01-07 10:49:58 -0500299 }
Brian Osmana66081d2019-09-03 14:59:26 -0400300 usedProgramBinaries = cached;
301 break;
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400302 }
Brian Osmana66081d2019-09-03 14:59:26 -0400303
304 case kGLSL_Tag:
305 // Source cache hit, we don't need to compile the SkSL->GLSL
306 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
307 break;
308
309 case kSKSL_Tag:
310 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
Brian Osman9e4e4c72020-06-10 07:19:34 -0400311 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
312 for (int i = 0; i < kGrShaderTypeCount; ++i) {
313 sksl[i] = &cached_sksl[i];
314 }
Brian Osmana085a412019-04-25 09:44:43 -0400315 }
Brian Osmana66081d2019-09-03 14:59:26 -0400316 break;
Brian Osman43f443f2020-06-05 11:11:36 -0400317
318 default:
319 // We got something invalid, so pretend it wasn't there
Brian Osman9e4e4c72020-06-10 07:19:34 -0400320 reader.validate(false);
Brian Osman43f443f2020-06-05 11:11:36 -0400321 break;
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400322 }
Brian Osman9e4e4c72020-06-10 07:19:34 -0400323 if (!reader.isValid()) {
324 cached = false;
325 }
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400326 }
Brian Osmana66081d2019-09-03 14:59:26 -0400327 if (!usedProgramBinaries) {
Brian Osmand010f652021-02-24 13:59:39 -0500328 TRACE_EVENT0_ALWAYS("skia.gpu", "cache_miss");
Brian Osmanf7924452019-09-24 10:44:37 -0400329 // Either a cache miss, or we got something other than binaries from the cache
330
331 /*
332 Fragment Shader
333 */
Brian Osman6b797fe2019-04-08 13:56:36 -0400334 if (glsl[kFragment_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400335 // Don't have cached GLSL, need to compile SkSL->GLSL
Ethan Nicholas8d058832019-01-07 10:49:58 -0500336 if (fFS.fForceHighPrecision) {
337 settings.fForceHighPrecision = true;
338 }
Brian Osman79719262020-11-23 14:54:33 -0500339 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(this->gpu(),
John Stilesdbd4e6f2021-02-16 13:29:15 -0500340 SkSL::ProgramKind::kFragment,
Brian Osmancbc33b82019-04-19 14:16:19 -0400341 *sksl[kFragment_GrShaderType],
Ethan Nicholas8d058832019-01-07 10:49:58 -0500342 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400343 &glsl[kFragment_GrShaderType],
344 errorHandler);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500345 if (!fs) {
Brian Osmaned58e002019-09-06 14:42:43 -0400346 cleanup_program(fGpu, programID, shadersToDelete);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500347 return nullptr;
348 }
349 inputs = fs->fInputs;
egdaniel8dcdedc2015-11-11 06:27:20 -0800350 }
Brian Osmanf7924452019-09-24 10:44:37 -0400351
352 this->addInputVars(inputs);
Brian Osmanac9be9d2019-05-01 10:29:34 -0400353 if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
Brian Osmane11dfd32019-07-23 10:29:41 -0400354 GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
Brian Osmaned58e002019-09-06 14:42:43 -0400355 cleanup_program(fGpu, programID, shadersToDelete);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400356 return nullptr;
357 }
358
Brian Osmanf7924452019-09-24 10:44:37 -0400359 /*
360 Vertex Shader
361 */
Brian Osman6b797fe2019-04-08 13:56:36 -0400362 if (glsl[kVertex_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400363 // Don't have cached GLSL, need to compile SkSL->GLSL
Brian Osman79719262020-11-23 14:54:33 -0500364 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(this->gpu(),
John Stilesdbd4e6f2021-02-16 13:29:15 -0500365 SkSL::ProgramKind::kVertex,
Brian Osmancbc33b82019-04-19 14:16:19 -0400366 *sksl[kVertex_GrShaderType],
Brian Osmanf71b0702019-04-03 13:04:16 -0400367 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400368 &glsl[kVertex_GrShaderType],
369 errorHandler);
Brian Osmanf71b0702019-04-03 13:04:16 -0400370 if (!vs) {
Brian Osmaned58e002019-09-06 14:42:43 -0400371 cleanup_program(fGpu, programID, shadersToDelete);
Brian Osmanf71b0702019-04-03 13:04:16 -0400372 return nullptr;
373 }
374 }
Brian Osmanac9be9d2019-05-01 10:29:34 -0400375 if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
Brian Osmane11dfd32019-07-23 10:29:41 -0400376 GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
Brian Osmaned58e002019-09-06 14:42:43 -0400377 cleanup_program(fGpu, programID, shadersToDelete);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400378 return nullptr;
379 }
380
Brian Osmanf7924452019-09-24 10:44:37 -0400381 // This also binds vertex attribute locations. NVPR doesn't really use vertices,
382 // even though it requires a vertex shader in the program.
383 if (!primProc.isPathRendering()) {
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400384 this->computeCountsAndStrides(programID, primProc, true);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400385 }
386
Brian Osmanf7924452019-09-24 10:44:37 -0400387 /*
Chris Dalton5a2f9622019-12-27 14:56:38 -0700388 Tessellation Shaders
389 */
390 if (fProgramInfo.primProc().willUseTessellationShaders()) {
391 // Tessellation shaders are not currently supported by SkSL. So here, we temporarily
392 // generate GLSL strings directly using back door methods on GrPrimitiveProcessor, and
393 // pass those raw strings on to the driver.
394 SkString versionAndExtensionDecls;
395 versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
396 if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
397 versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
398 }
399
400 SkString tessControlShader = primProc.getTessControlShaderGLSL(
Chris Dalton54c90932020-06-24 10:51:52 -0600401 fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
402 *this->shaderCaps());
Chris Dalton5a2f9622019-12-27 14:56:38 -0700403 if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
404 GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
405 errorHandler)) {
406 cleanup_program(fGpu, programID, shadersToDelete);
407 return nullptr;
408 }
409
410 SkString tessEvaluationShader = primProc.getTessEvaluationShaderGLSL(
Chris Dalton54c90932020-06-24 10:51:52 -0600411 fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
412 *this->shaderCaps());
Chris Dalton5a2f9622019-12-27 14:56:38 -0700413 if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
414 GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
415 errorHandler)) {
416 cleanup_program(fGpu, programID, shadersToDelete);
417 return nullptr;
418 }
419 }
420
421 /*
Brian Osmanf7924452019-09-24 10:44:37 -0400422 Geometry Shader
423 */
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400424 if (primProc.willUseGeoShader()) {
Brian Osman6b797fe2019-04-08 13:56:36 -0400425 if (glsl[kGeometry_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400426 // Don't have cached GLSL, need to compile SkSL->GLSL
427 std::unique_ptr<SkSL::Program> gs;
Brian Osman79719262020-11-23 14:54:33 -0500428 gs = GrSkSLtoGLSL(this->gpu(),
John Stilesdbd4e6f2021-02-16 13:29:15 -0500429 SkSL::ProgramKind::kGeometry,
Brian Osmancbc33b82019-04-19 14:16:19 -0400430 *sksl[kGeometry_GrShaderType],
Brian Osmanf71b0702019-04-03 13:04:16 -0400431 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400432 &glsl[kGeometry_GrShaderType],
433 errorHandler);
Brian Osmanf71b0702019-04-03 13:04:16 -0400434 if (!gs) {
Brian Osmaned58e002019-09-06 14:42:43 -0400435 cleanup_program(fGpu, programID, shadersToDelete);
Brian Osmanf71b0702019-04-03 13:04:16 -0400436 return nullptr;
437 }
438 }
Brian Osmanac9be9d2019-05-01 10:29:34 -0400439 if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
Brian Osmane11dfd32019-07-23 10:29:41 -0400440 GR_GL_GEOMETRY_SHADER, &shadersToDelete,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400441 errorHandler)) {
Brian Osmaned58e002019-09-06 14:42:43 -0400442 cleanup_program(fGpu, programID, shadersToDelete);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400443 return nullptr;
444 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400445 }
446 this->bindProgramResourceLocations(programID);
447
Leon Scrogginsb66214e2021-02-11 17:14:18 -0500448 {
Brian Osmand010f652021-02-24 13:59:39 -0500449 TRACE_EVENT0_ALWAYS("skia.gpu", "driver_link_program");
Leon Scrogginsb66214e2021-02-11 17:14:18 -0500450 GL_CALL(LinkProgram(programID));
451 if (checkLinked) {
452 if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
453 cleanup_program(fGpu, programID, shadersToDelete);
454 return nullptr;
455 }
Brian Salomone334c592017-05-15 11:00:58 -0400456 }
Brian Salomone334c592017-05-15 11:00:58 -0400457 }
joshualittfe1233c2014-10-07 12:16:35 -0700458 }
Brian Osman2c60a382019-06-26 15:19:30 -0400459 this->resolveProgramResourceLocations(programID, usedProgramBinaries);
joshualittdb0d3ca2014-10-07 12:42:26 -0700460
Brian Osmaned58e002019-09-06 14:42:43 -0400461 cleanup_shaders(fGpu, shadersToDelete);
Brian Osmane4c88bb2019-06-27 16:15:11 -0400462
Chris Dalton5a2f9622019-12-27 14:56:38 -0700463 // We temporarily can't cache tessellation shaders while using back door GLSL.
464 //
Brian Osmaned58e002019-09-06 14:42:43 -0400465 // We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
466 // much point in doing so.
Brian Osman0b22f3b2020-03-23 13:21:24 -0400467 if (!cached && !primProc.willUseTessellationShaders() && !precompiledProgram) {
Chris Dalton8dae7eb2019-12-27 22:20:55 -0700468 // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
469 // GLSL mechanism is removed.
470 (void)&GrPrimitiveProcessor::getTessControlShaderGLSL;
Brian Osmana085a412019-04-25 09:44:43 -0400471 bool isSkSL = false;
Brian Osmana66081d2019-09-03 14:59:26 -0400472 if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
473 GrContextOptions::ShaderCacheStrategy::kSkSL) {
Brian Osmancbc33b82019-04-19 14:16:19 -0400474 for (int i = 0; i < kGrShaderTypeCount; ++i) {
Brian Osmanac9be9d2019-05-01 10:29:34 -0400475 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
Brian Osmancbc33b82019-04-19 14:16:19 -0400476 }
Brian Osmana085a412019-04-25 09:44:43 -0400477 isSkSL = true;
Brian Osmancbc33b82019-04-19 14:16:19 -0400478 }
Brian Osman4524e842019-09-24 16:03:41 -0400479 this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400480 }
joshualitt47bb3822014-10-07 16:43:25 -0700481 return this->createProgram(programID);
482}
483
kkinnunen7aedda52015-06-29 23:01:28 -0700484void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800485 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700486
egdaniel8dcdedc2015-11-11 06:27:20 -0800487 const GrGLCaps& caps = this->gpu()->glCaps();
488 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
489 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800490 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800491 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500492 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800493 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800494 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800495 }
joshualittd8dd47b2015-09-11 11:45:01 -0700496
497 // handle NVPR separable varyings
498 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
499 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
500 return;
501 }
Michael Ludwig45191342020-03-24 12:29:39 -0400502 int i = 0;
503 for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
504 GL_CALL(BindFragmentInputLocation(programID, i, varying.fVariable.c_str()));
505 varying.fLocation = i;
506 ++i;
joshualittd8dd47b2015-09-11 11:45:01 -0700507 }
joshualitt47bb3822014-10-07 16:43:25 -0700508}
509
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400510bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
511 GrContextOptions::ShaderErrorHandler* errorHandler,
512 SkSL::String* sksl[], const SkSL::String glsl[]) {
joshualitt47bb3822014-10-07 16:43:25 -0700513 GrGLint linked = GR_GL_INIT_ZERO;
514 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
515 if (!linked) {
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400516 SkSL::String allShaders;
517 if (sksl) {
518 allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
519 if (!sksl[kGeometry_GrShaderType]->empty()) {
520 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
521 }
522 allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
523 }
524 if (glsl) {
525 allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
526 if (!glsl[kGeometry_GrShaderType].empty()) {
527 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
528 }
529 allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
530 }
joshualitt47bb3822014-10-07 16:43:25 -0700531 GrGLint infoLen = GR_GL_INIT_ZERO;
532 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
533 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
534 if (infoLen > 0) {
535 // retrieve length even though we don't need it to workaround
536 // bug in chrome cmd buffer param validation.
537 GrGLsizei length = GR_GL_INIT_ZERO;
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400538 GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700539 }
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400540 errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
joshualitt47bb3822014-10-07 16:43:25 -0700541 }
542 return SkToBool(linked);
543}
544
Brian Osman2c60a382019-06-26 15:19:30 -0400545void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
546 fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
joshualittd8dd47b2015-09-11 11:45:01 -0700547
548 // handle NVPR separable varyings
549 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800550 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700551 return;
552 }
Michael Ludwig45191342020-03-24 12:29:39 -0400553 for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700554 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800555 GL_CALL_RET(location, GetProgramResourceLocation(
556 programID,
557 GR_GL_FRAGMENT_INPUT,
Michael Ludwig45191342020-03-24 12:29:39 -0400558 varying.fVariable.c_str()));
559 varying.fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700560 }
joshualitt30ba4362014-08-21 20:18:45 -0700561}
562
Stephen Whiteb1857852020-02-07 15:33:23 +0000563sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
Robert Phillipsdf546db2020-05-29 09:42:54 -0400564 return GrGLProgram::Make(fGpu,
565 fUniformHandles,
566 programID,
567 fUniformHandler.fUniforms,
568 fUniformHandler.fSamplers,
569 fVaryingHandler.fPathProcVaryingInfos,
570 std::move(fGeometryProcessor),
571 std::move(fXferProcessor),
Brian Salomon17f95b12021-02-23 09:35:08 -0500572 std::move(fFPImpls),
Robert Phillipsdf546db2020-05-29 09:42:54 -0400573 std::move(fAttributes),
574 fVertexAttributeCnt,
575 fInstanceAttributeCnt,
576 fVertexStride,
577 fInstanceStride);
joshualitt47bb3822014-10-07 16:43:25 -0700578}
Brian Osmaned58e002019-09-06 14:42:43 -0400579
Robert Phillips962708f2021-03-03 14:42:04 -0500580bool GrGLProgramBuilder::PrecompileProgram(GrDirectContext* dContext,
581 GrGLPrecompiledProgram* precompiledProgram,
Brian Osmaned58e002019-09-06 14:42:43 -0400582 const SkData& cachedData) {
Brian Osman9e4e4c72020-06-10 07:19:34 -0400583 SkReadBuffer reader(cachedData.data(), cachedData.size());
Brian Osman1facd5e2020-03-16 16:21:24 -0400584 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
Brian Osmaned58e002019-09-06 14:42:43 -0400585 if (shaderType != kSKSL_Tag) {
586 // TODO: Support GLSL, and maybe even program binaries, too?
587 return false;
588 }
589
Robert Phillips962708f2021-03-03 14:42:04 -0500590 GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
591
592 const GrGLInterface* gl = glGpu->glInterface();
593 auto errorHandler = dContext->priv().getShaderErrorHandler();
Brian Osmaned58e002019-09-06 14:42:43 -0400594
595 SkSL::Program::Settings settings;
Robert Phillips962708f2021-03-03 14:42:04 -0500596 settings.fSharpenTextures = dContext->priv().options().fSharpenMipmappedTextures;
Brian Osman4524e842019-09-24 16:03:41 -0400597 GrPersistentCacheUtils::ShaderMetadata meta;
598 meta.fSettings = &settings;
Brian Osmaned58e002019-09-06 14:42:43 -0400599
600 SkSL::String shaders[kGrShaderTypeCount];
601 SkSL::Program::Inputs inputs;
Brian Osman9e4e4c72020-06-10 07:19:34 -0400602 if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
603 return false;
604 }
605
606 GrGLuint programID;
607 GR_GL_CALL_RET(gl, programID, CreateProgram());
608 if (0 == programID) {
609 return false;
610 }
611
612 SkTDArray<GrGLuint> shadersToDelete;
Brian Osmaned58e002019-09-06 14:42:43 -0400613
John Stilesdbd4e6f2021-02-16 13:29:15 -0500614 auto compileShader = [&](SkSL::ProgramKind kind, const SkSL::String& sksl, GrGLenum type) {
Brian Osmaned58e002019-09-06 14:42:43 -0400615 SkSL::String glsl;
Robert Phillips962708f2021-03-03 14:42:04 -0500616 auto program = GrSkSLtoGLSL(glGpu, kind, sksl, settings, &glsl, errorHandler);
Brian Osmaned58e002019-09-06 14:42:43 -0400617 if (!program) {
618 return false;
619 }
620
Robert Phillips962708f2021-03-03 14:42:04 -0500621 if (GrGLuint shaderID = GrGLCompileAndAttachShader(glGpu->glContext(), programID, type,
622 glsl, glGpu->pipelineBuilder()->stats(),
Robert Phillipsae67c522021-03-03 11:03:38 -0500623 errorHandler)) {
Brian Osmaned58e002019-09-06 14:42:43 -0400624 shadersToDelete.push_back(shaderID);
625 return true;
626 } else {
627 return false;
628 }
629 };
630
John Stilesdbd4e6f2021-02-16 13:29:15 -0500631 if (!compileShader(SkSL::ProgramKind::kFragment,
Brian Osmaned58e002019-09-06 14:42:43 -0400632 shaders[kFragment_GrShaderType],
633 GR_GL_FRAGMENT_SHADER) ||
John Stilesdbd4e6f2021-02-16 13:29:15 -0500634 !compileShader(SkSL::ProgramKind::kVertex,
Brian Osmaned58e002019-09-06 14:42:43 -0400635 shaders[kVertex_GrShaderType],
636 GR_GL_VERTEX_SHADER) ||
637 (!shaders[kGeometry_GrShaderType].empty() &&
John Stilesdbd4e6f2021-02-16 13:29:15 -0500638 !compileShader(SkSL::ProgramKind::kGeometry,
Brian Osmaned58e002019-09-06 14:42:43 -0400639 shaders[kGeometry_GrShaderType],
640 GR_GL_GEOMETRY_SHADER))) {
Robert Phillips962708f2021-03-03 14:42:04 -0500641 cleanup_program(glGpu, programID, shadersToDelete);
Brian Osmaned58e002019-09-06 14:42:43 -0400642 return false;
643 }
644
Brian Osman4524e842019-09-24 16:03:41 -0400645 for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
Robert Phillips962708f2021-03-03 14:42:04 -0500646 GR_GL_CALL(glGpu->glInterface(), BindAttribLocation(programID, i,
Brian Osman4524e842019-09-24 16:03:41 -0400647 meta.fAttributeNames[i].c_str()));
648 }
649
Robert Phillips962708f2021-03-03 14:42:04 -0500650 const GrGLCaps& caps = glGpu->glCaps();
Brian Osman4524e842019-09-24 16:03:41 -0400651 if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
Robert Phillips962708f2021-03-03 14:42:04 -0500652 GR_GL_CALL(glGpu->glInterface(),
653 BindFragDataLocation(programID, 0,
654 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
Brian Osman4524e842019-09-24 16:03:41 -0400655 }
656 if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
Robert Phillips962708f2021-03-03 14:42:04 -0500657 GR_GL_CALL(glGpu->glInterface(),
658 BindFragDataLocationIndexed(programID, 0, 1,
659 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
Brian Osman4524e842019-09-24 16:03:41 -0400660 }
661
Robert Phillips962708f2021-03-03 14:42:04 -0500662 GR_GL_CALL(glGpu->glInterface(), LinkProgram(programID));
Brian Osmaned58e002019-09-06 14:42:43 -0400663 GrGLint linked = GR_GL_INIT_ZERO;
Robert Phillips962708f2021-03-03 14:42:04 -0500664 GR_GL_CALL(glGpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
Brian Osmaned58e002019-09-06 14:42:43 -0400665 if (!linked) {
Robert Phillips962708f2021-03-03 14:42:04 -0500666 cleanup_program(glGpu, programID, shadersToDelete);
Brian Osmaned58e002019-09-06 14:42:43 -0400667 return false;
668 }
669
Robert Phillips962708f2021-03-03 14:42:04 -0500670 cleanup_shaders(glGpu, shadersToDelete);
Brian Osmaned58e002019-09-06 14:42:43 -0400671
672 precompiledProgram->fProgramID = programID;
673 precompiledProgram->fInputs = inputs;
674 return true;
675}