1/*
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
8#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
9
10#include "include/gpu/GrDirectContext.h"
11#include "src/core/SkATrace.h"
12#include "src/core/SkAutoMalloc.h"
13#include "src/core/SkReadBuffer.h"
14#include "src/core/SkTraceEvent.h"
15#include "src/core/SkWriteBuffer.h"
16#include "src/gpu/GrAutoLocaleSetter.h"
17#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrPersistentCacheUtils.h"
19#include "src/gpu/GrProgramDesc.h"
20#include "src/gpu/GrShaderCaps.h"
21#include "src/gpu/GrShaderUtils.h"
22#include "src/gpu/GrSwizzle.h"
23#include "src/gpu/gl/GrGLGpu.h"
24#include "src/gpu/gl/GrGLProgram.h"
25#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
26
27#include <memory>
28#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"
33
34#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
37static 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
49sk_sp<GrGLProgram> GrGLProgramBuilder::CreateProgram(
50 GrGLGpu* gpu,
51 GrRenderTarget* renderTarget,
52 const GrProgramDesc& desc,
53 const GrProgramInfo& programInfo,
54 const GrGLPrecompiledProgram* precompiledProgram) {
55 ATRACE_ANDROID_FRAMEWORK_ALWAYS("shader_compile");
56 GrAutoLocaleSetter als("C");
57
58 // create a builder. This will be handed off to effects so they can use it to add
59 // uniforms, varyings, textures, etc
60 GrGLProgramBuilder builder(gpu, renderTarget, desc, programInfo);
61
62 auto persistentCache = gpu->getContext()->priv().getPersistentCache();
63 if (persistentCache && !precompiledProgram) {
64 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
65 builder.fCached = persistentCache->load(*key);
66 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
67 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
68 // to skip the SkSL->GLSL step on a cache hit.
69 }
70 if (!builder.emitAndInstallProcs()) {
71 return nullptr;
72 }
73 return builder.finalize(precompiledProgram);
74}
75
76/////////////////////////////////////////////////////////////////////////////
77
78GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
79 GrRenderTarget* renderTarget,
80 const GrProgramDesc& desc,
81 const GrProgramInfo& programInfo)
82 : INHERITED(renderTarget, desc, programInfo)
83 , fGpu(gpu)
84 , fVaryingHandler(this)
85 , fUniformHandler(this)
86 , fVertexAttributeCnt(0)
87 , fInstanceAttributeCnt(0)
88 , fVertexStride(0)
89 , fInstanceStride(0) {}
90
91const GrCaps* GrGLProgramBuilder::caps() const {
92 return fGpu->caps();
93}
94
95bool GrGLProgramBuilder::compileAndAttachShaders(const SkSL::String& glsl,
96 GrGLuint programId,
97 GrGLenum type,
98 SkTDArray<GrGLuint>* shaderIds,
99 GrContextOptions::ShaderErrorHandler* errHandler) {
100 GrGLGpu* gpu = this->gpu();
101 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
102 programId,
103 type,
104 glsl,
105 gpu->stats(),
106 errHandler);
107 if (!shaderId) {
108 return false;
109 }
110
111 *shaderIds->append() = shaderId;
112 return true;
113}
114
115void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
116 const GrPrimitiveProcessor& primProc,
117 bool bindAttribLocations) {
118 fVertexAttributeCnt = primProc.numVertexAttributes();
119 fInstanceAttributeCnt = primProc.numInstanceAttributes();
120 fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
121 fVertexAttributeCnt + fInstanceAttributeCnt);
122 auto addAttr = [&](int i, const auto& a, size_t* stride) {
123 fAttributes[i].fCPUType = a.cpuType();
124 fAttributes[i].fGPUType = a.gpuType();
125 fAttributes[i].fOffset = *stride;
126 *stride += a.sizeAlign4();
127 fAttributes[i].fLocation = i;
128 if (bindAttribLocations) {
129 GL_CALL(BindAttribLocation(programID, i, a.name()));
130 }
131 };
132 fVertexStride = 0;
133 int i = 0;
134 for (const auto& attr : primProc.vertexAttributes()) {
135 addAttr(i++, attr, &fVertexStride);
136 }
137 SkASSERT(fVertexStride == primProc.vertexStride());
138 fInstanceStride = 0;
139 for (const auto& attr : primProc.instanceAttributes()) {
140 addAttr(i++, attr, &fInstanceStride);
141 }
142 SkASSERT(fInstanceStride == primProc.instanceStride());
143}
144
145void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
146 if (inputs.fRTWidth) {
147 this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
148 }
149 if (inputs.fRTHeight) {
150 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
151 }
152}
153
154static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
155static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
156static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
157
158void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
159 const SkSL::String shaders[], bool isSkSL,
160 SkSL::Program::Settings* settings) {
161 if (!this->gpu()->getContext()->priv().getPersistentCache()) {
162 return;
163 }
164 sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().keyLength());
165 if (fGpu->glCaps().programBinarySupport()) {
166 // binary cache
167 GrGLsizei length = 0;
168 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
169 if (length > 0) {
170 SkBinaryWriteBuffer writer;
171 writer.writeInt(GrPersistentCacheUtils::kCurrentVersion);
172 writer.writeUInt(kGLPB_Tag);
173
174 writer.writePad32(&inputs, sizeof(inputs));
175
176 SkAutoSMalloc<2048> binary(length);
177 GrGLenum binaryFormat;
178 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
179
180 writer.writeUInt(binaryFormat);
181 writer.writeInt(length);
182 writer.writePad32(binary.get(), length);
183
184 auto data = writer.snapshotAsData();
185 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
186 }
187 } else {
188 // source cache, plus metadata to allow for a complete precompile
189 GrPersistentCacheUtils::ShaderMetadata meta;
190 meta.fSettings = settings;
191 meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
192 meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
193 for (const auto& attr : this->primitiveProcessor().vertexAttributes()) {
194 meta.fAttributeNames.emplace_back(attr.name());
195 }
196 for (const auto& attr : this->primitiveProcessor().instanceAttributes()) {
197 meta.fAttributeNames.emplace_back(attr.name());
198 }
199
200 auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
201 shaders, &inputs, 1, &meta);
202 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
203 }
204}
205
206sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
207 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
208
209 // verify we can get a program id
210 GrGLuint programID;
211 if (precompiledProgram) {
212 programID = precompiledProgram->fProgramID;
213 } else {
214 GL_CALL_RET(programID, CreateProgram());
215 }
216 if (0 == programID) {
217 return nullptr;
218 }
219
220 if (this->gpu()->glCaps().programBinarySupport() &&
221 this->gpu()->glCaps().programParameterSupport() &&
222 this->gpu()->getContext()->priv().getPersistentCache() &&
223 !precompiledProgram) {
224 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
225 }
226
227 this->finalizeShaders();
228
229 // compile shaders and bind attributes / uniforms
230 auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
231 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
232 SkSL::Program::Settings settings;
233 settings.fCaps = this->gpu()->glCaps().shaderCaps();
234 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
235 settings.fSharpenTextures =
236 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
237 settings.fFragColorIsInOut = this->fragColorIsInOut();
238
239 SkSL::Program::Inputs inputs;
240 SkTDArray<GrGLuint> shadersToDelete;
241
242 bool checkLinked = !fGpu->glCaps().skipErrorChecks();
243
244 bool cached = fCached.get() != nullptr;
245 bool usedProgramBinaries = false;
246 SkSL::String glsl[kGrShaderTypeCount];
247 SkSL::String* sksl[kGrShaderTypeCount] = {
248 &fVS.fCompilerString,
249 &fGS.fCompilerString,
250 &fFS.fCompilerString,
251 };
252 SkSL::String cached_sksl[kGrShaderTypeCount];
253 if (precompiledProgram) {
254 // This is very similar to when we get program binaries. We even set that flag, as it's
255 // used to prevent other compile work later, and to force re-querying uniform locations.
256 this->addInputVars(precompiledProgram->fInputs);
257 this->computeCountsAndStrides(programID, primProc, false);
258 usedProgramBinaries = true;
259 } else if (cached) {
260 ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_hit");
261 SkReadBuffer reader(fCached->data(), fCached->size());
262 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
263
264 switch (shaderType) {
265 case kGLPB_Tag: {
266 // Program binary cache hit. We may opt not to use this if we don't trust program
267 // binaries on this driver
268 if (!fGpu->glCaps().programBinarySupport()) {
269 cached = false;
270 break;
271 }
272 reader.readPad32(&inputs, sizeof(inputs));
273 GrGLenum binaryFormat = reader.readUInt();
274 GrGLsizei length = reader.readInt();
275 const void* binary = reader.skip(length);
276 if (!reader.isValid()) {
277 break;
278 }
279 this->gpu()->clearErrorsAndCheckForOOM();
280 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
281 ProgramBinary(programID, binaryFormat,
282 const_cast<void*>(binary), length));
283 if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) {
284 if (checkLinked) {
285 cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
286 }
287 if (cached) {
288 this->addInputVars(inputs);
289 this->computeCountsAndStrides(programID, primProc, false);
290 }
291 } else {
292 cached = false;
293 }
294 usedProgramBinaries = cached;
295 break;
296 }
297
298 case kGLSL_Tag:
299 // Source cache hit, we don't need to compile the SkSL->GLSL
300 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
301 break;
302
303 case kSKSL_Tag:
304 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
305 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
306 for (int i = 0; i < kGrShaderTypeCount; ++i) {
307 sksl[i] = &cached_sksl[i];
308 }
309 }
310 break;
311
312 default:
313 // We got something invalid, so pretend it wasn't there
314 reader.validate(false);
315 break;
316 }
317 if (!reader.isValid()) {
318 cached = false;
319 }
320 }
321 if (!usedProgramBinaries) {
322 ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_miss");
323 // Either a cache miss, or we got something other than binaries from the cache
324
325 /*
326 Fragment Shader
327 */
328 if (glsl[kFragment_GrShaderType].empty()) {
329 // Don't have cached GLSL, need to compile SkSL->GLSL
330 if (fFS.fForceHighPrecision) {
331 settings.fForceHighPrecision = true;
332 }
333 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
334 SkSL::Program::kFragment_Kind,
335 *sksl[kFragment_GrShaderType],
336 settings,
337 &glsl[kFragment_GrShaderType],
338 errorHandler);
339 if (!fs) {
340 cleanup_program(fGpu, programID, shadersToDelete);
341 return nullptr;
342 }
343 inputs = fs->fInputs;
344 }
345
346 this->addInputVars(inputs);
347 if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
348 GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
349 cleanup_program(fGpu, programID, shadersToDelete);
350 return nullptr;
351 }
352
353 /*
354 Vertex Shader
355 */
356 if (glsl[kVertex_GrShaderType].empty()) {
357 // Don't have cached GLSL, need to compile SkSL->GLSL
358 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
359 SkSL::Program::kVertex_Kind,
360 *sksl[kVertex_GrShaderType],
361 settings,
362 &glsl[kVertex_GrShaderType],
363 errorHandler);
364 if (!vs) {
365 cleanup_program(fGpu, programID, shadersToDelete);
366 return nullptr;
367 }
368 }
369 if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
370 GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
371 cleanup_program(fGpu, programID, shadersToDelete);
372 return nullptr;
373 }
374
375 // This also binds vertex attribute locations. NVPR doesn't really use vertices,
376 // even though it requires a vertex shader in the program.
377 if (!primProc.isPathRendering()) {
378 this->computeCountsAndStrides(programID, primProc, true);
379 }
380
381 /*
382 Tessellation Shaders
383 */
384 if (fProgramInfo.primProc().willUseTessellationShaders()) {
385 // Tessellation shaders are not currently supported by SkSL. So here, we temporarily
386 // generate GLSL strings directly using back door methods on GrPrimitiveProcessor, and
387 // pass those raw strings on to the driver.
388 SkString versionAndExtensionDecls;
389 versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
390 if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
391 versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
392 }
393
394 SkString tessControlShader = primProc.getTessControlShaderGLSL(
395 fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
396 *this->shaderCaps());
397 if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
398 GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
399 errorHandler)) {
400 cleanup_program(fGpu, programID, shadersToDelete);
401 return nullptr;
402 }
403
404 SkString tessEvaluationShader = primProc.getTessEvaluationShaderGLSL(
405 fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
406 *this->shaderCaps());
407 if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
408 GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
409 errorHandler)) {
410 cleanup_program(fGpu, programID, shadersToDelete);
411 return nullptr;
412 }
413 }
414
415 /*
416 Geometry Shader
417 */
418 if (primProc.willUseGeoShader()) {
419 if (glsl[kGeometry_GrShaderType].empty()) {
420 // Don't have cached GLSL, need to compile SkSL->GLSL
421 std::unique_ptr<SkSL::Program> gs;
422 gs = GrSkSLtoGLSL(gpu()->glContext(),
423 SkSL::Program::kGeometry_Kind,
424 *sksl[kGeometry_GrShaderType],
425 settings,
426 &glsl[kGeometry_GrShaderType],
427 errorHandler);
428 if (!gs) {
429 cleanup_program(fGpu, programID, shadersToDelete);
430 return nullptr;
431 }
432 }
433 if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
434 GR_GL_GEOMETRY_SHADER, &shadersToDelete,
435 errorHandler)) {
436 cleanup_program(fGpu, programID, shadersToDelete);
437 return nullptr;
438 }
439 }
440 this->bindProgramResourceLocations(programID);
441
442 GL_CALL(LinkProgram(programID));
443 if (checkLinked) {
444 if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
445 cleanup_program(fGpu, programID, shadersToDelete);
446 return nullptr;
447 }
448 }
449 }
450 this->resolveProgramResourceLocations(programID, usedProgramBinaries);
451
452 cleanup_shaders(fGpu, shadersToDelete);
453
454 // We temporarily can't cache tessellation shaders while using back door GLSL.
455 //
456 // We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
457 // much point in doing so.
458 if (!cached && !primProc.willUseTessellationShaders() && !precompiledProgram) {
459 // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
460 // GLSL mechanism is removed.
461 (void)&GrPrimitiveProcessor::getTessControlShaderGLSL;
462 bool isSkSL = false;
463 if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
464 GrContextOptions::ShaderCacheStrategy::kSkSL) {
465 for (int i = 0; i < kGrShaderTypeCount; ++i) {
466 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
467 }
468 isSkSL = true;
469 }
470 this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
471 }
472 return this->createProgram(programID);
473}
474
475void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
476 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
477
478 const GrGLCaps& caps = this->gpu()->glCaps();
479 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
480 GL_CALL(BindFragDataLocation(programID, 0,
481 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
482 }
483 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
484 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
485 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
486 }
487
488 // handle NVPR separable varyings
489 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
490 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
491 return;
492 }
493 int i = 0;
494 for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
495 GL_CALL(BindFragmentInputLocation(programID, i, varying.fVariable.c_str()));
496 varying.fLocation = i;
497 ++i;
498 }
499}
500
501bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
502 GrContextOptions::ShaderErrorHandler* errorHandler,
503 SkSL::String* sksl[], const SkSL::String glsl[]) {
504 GrGLint linked = GR_GL_INIT_ZERO;
505 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
506 if (!linked) {
507 SkSL::String allShaders;
508 if (sksl) {
509 allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
510 if (!sksl[kGeometry_GrShaderType]->empty()) {
511 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
512 }
513 allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
514 }
515 if (glsl) {
516 allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
517 if (!glsl[kGeometry_GrShaderType].empty()) {
518 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
519 }
520 allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
521 }
522 GrGLint infoLen = GR_GL_INIT_ZERO;
523 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
524 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
525 if (infoLen > 0) {
526 // retrieve length even though we don't need it to workaround
527 // bug in chrome cmd buffer param validation.
528 GrGLsizei length = GR_GL_INIT_ZERO;
529 GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
530 }
531 errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
532 }
533 return SkToBool(linked);
534}
535
536void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
537 fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
538
539 // handle NVPR separable varyings
540 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
541 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
542 return;
543 }
544 for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
545 GrGLint location;
546 GL_CALL_RET(location, GetProgramResourceLocation(
547 programID,
548 GR_GL_FRAGMENT_INPUT,
549 varying.fVariable.c_str()));
550 varying.fLocation = location;
551 }
552}
553
554sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
555 return GrGLProgram::Make(fGpu,
556 fUniformHandles,
557 programID,
558 fUniformHandler.fUniforms,
559 fUniformHandler.fSamplers,
560 fVaryingHandler.fPathProcVaryingInfos,
561 std::move(fGeometryProcessor),
562 std::move(fXferProcessor),
563 std::move(fFragmentProcessors),
564 std::move(fAttributes),
565 fVertexAttributeCnt,
566 fInstanceAttributeCnt,
567 fVertexStride,
568 fInstanceStride);
569}
570
571bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledProgram,
572 GrGLGpu* gpu,
573 const SkData& cachedData) {
574 SkReadBuffer reader(cachedData.data(), cachedData.size());
575 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
576 if (shaderType != kSKSL_Tag) {
577 // TODO: Support GLSL, and maybe even program binaries, too?
578 return false;
579 }
580
581 const GrGLInterface* gl = gpu->glInterface();
582 auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
583
584 SkSL::Program::Settings settings;
585 const GrGLCaps& caps = gpu->glCaps();
586 settings.fCaps = caps.shaderCaps();
587 settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
588 GrPersistentCacheUtils::ShaderMetadata meta;
589 meta.fSettings = &settings;
590
591 SkSL::String shaders[kGrShaderTypeCount];
592 SkSL::Program::Inputs inputs;
593 if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
594 return false;
595 }
596
597 GrGLuint programID;
598 GR_GL_CALL_RET(gl, programID, CreateProgram());
599 if (0 == programID) {
600 return false;
601 }
602
603 SkTDArray<GrGLuint> shadersToDelete;
604
605 auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) {
606 SkSL::String glsl;
607 auto program = GrSkSLtoGLSL(gpu->glContext(), kind, sksl, settings, &glsl, errorHandler);
608 if (!program) {
609 return false;
610 }
611
612 if (GrGLuint shaderID = GrGLCompileAndAttachShader(gpu->glContext(), programID, type, glsl,
613 gpu->stats(), errorHandler)) {
614 shadersToDelete.push_back(shaderID);
615 return true;
616 } else {
617 return false;
618 }
619 };
620
621 if (!compileShader(SkSL::Program::kFragment_Kind,
622 shaders[kFragment_GrShaderType],
623 GR_GL_FRAGMENT_SHADER) ||
624 !compileShader(SkSL::Program::kVertex_Kind,
625 shaders[kVertex_GrShaderType],
626 GR_GL_VERTEX_SHADER) ||
627 (!shaders[kGeometry_GrShaderType].empty() &&
628 !compileShader(SkSL::Program::kGeometry_Kind,
629 shaders[kGeometry_GrShaderType],
630 GR_GL_GEOMETRY_SHADER))) {
631 cleanup_program(gpu, programID, shadersToDelete);
632 return false;
633 }
634
635 for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
636 GR_GL_CALL(gpu->glInterface(), BindAttribLocation(programID, i,
637 meta.fAttributeNames[i].c_str()));
638 }
639
640 if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
641 GR_GL_CALL(gpu->glInterface(), BindFragDataLocation(programID, 0,
642 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
643 }
644 if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
645 GR_GL_CALL(gpu->glInterface(), BindFragDataLocationIndexed(programID, 0, 1,
646 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
647 }
648
649 GR_GL_CALL(gpu->glInterface(), LinkProgram(programID));
650 GrGLint linked = GR_GL_INIT_ZERO;
651 GR_GL_CALL(gpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
652 if (!linked) {
653 cleanup_program(gpu, programID, shadersToDelete);
654 return false;
655 }
656
657 cleanup_shaders(gpu, shadersToDelete);
658
659 precompiledProgram->fProgramID = programID;
660 precompiledProgram->fInputs = inputs;
661 return true;
662}
663