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