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