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/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
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.fRTHeight) {
151 this->addRTHeightUniform(SKSL_RTHEIGHT_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
finalize(const GrGLPrecompiledProgram * precompiledProgram)208 sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
209 TRACE_EVENT0("skia.shaders", TRACE_FUNC);
210
211 // verify we can get a program id
212 GrGLuint programID;
213 if (precompiledProgram) {
214 programID = precompiledProgram->fProgramID;
215 } else {
216 GL_CALL_RET(programID, CreateProgram());
217 }
218 if (0 == programID) {
219 return nullptr;
220 }
221
222 if (this->gpu()->glCaps().programBinarySupport() &&
223 this->gpu()->glCaps().programParameterSupport() &&
224 this->gpu()->getContext()->priv().getPersistentCache() &&
225 !precompiledProgram) {
226 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
227 }
228
229 this->finalizeShaders();
230
231 // compile shaders and bind attributes / uniforms
232 auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
233 const GrGeometryProcessor& geomProc = this->geometryProcessor();
234 SkSL::Program::Settings settings;
235 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
236 settings.fSharpenTextures =
237 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
238 settings.fFragColorIsInOut = this->fragColorIsInOut();
239
240 SkSL::Program::Inputs inputs;
241 SkTDArray<GrGLuint> shadersToDelete;
242
243 bool checkLinked = !fGpu->glCaps().skipErrorChecks();
244
245 bool cached = fCached.get() != nullptr;
246 bool usedProgramBinaries = false;
247 SkSL::String glsl[kGrShaderTypeCount];
248 SkSL::String* sksl[kGrShaderTypeCount] = {
249 &fVS.fCompilerString,
250 &fGS.fCompilerString,
251 &fFS.fCompilerString,
252 };
253 SkSL::String cached_sksl[kGrShaderTypeCount];
254 if (precompiledProgram) {
255 // This is very similar to when we get program binaries. We even set that flag, as it's
256 // used to prevent other compile work later, and to force re-querying uniform locations.
257 this->addInputVars(precompiledProgram->fInputs);
258 this->computeCountsAndStrides(programID, geomProc, false);
259 usedProgramBinaries = true;
260 } else if (cached) {
261 TRACE_EVENT0_ALWAYS("skia.shaders", "cache_hit");
262 SkReadBuffer reader(fCached->data(), fCached->size());
263 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
264
265 switch (shaderType) {
266 case kGLPB_Tag: {
267 // Program binary cache hit. We may opt not to use this if we don't trust program
268 // binaries on this driver
269 if (!fGpu->glCaps().programBinarySupport()) {
270 cached = false;
271 break;
272 }
273 reader.readPad32(&inputs, sizeof(inputs));
274 GrGLenum binaryFormat = reader.readUInt();
275 GrGLsizei length = reader.readInt();
276 const void* binary = reader.skip(length);
277 if (!reader.isValid()) {
278 break;
279 }
280 this->gpu()->clearErrorsAndCheckForOOM();
281 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
282 ProgramBinary(programID, binaryFormat,
283 const_cast<void*>(binary), length));
284 if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) {
285 if (checkLinked) {
286 cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
287 }
288 if (cached) {
289 this->addInputVars(inputs);
290 this->computeCountsAndStrides(programID, geomProc, false);
291 }
292 } else {
293 cached = false;
294 }
295 usedProgramBinaries = cached;
296 break;
297 }
298
299 case kGLSL_Tag:
300 // Source cache hit, we don't need to compile the SkSL->GLSL
301 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
302 break;
303
304 case kSKSL_Tag:
305 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
306 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
307 for (int i = 0; i < kGrShaderTypeCount; ++i) {
308 sksl[i] = &cached_sksl[i];
309 }
310 }
311 break;
312
313 default:
314 // We got something invalid, so pretend it wasn't there
315 reader.validate(false);
316 break;
317 }
318 if (!reader.isValid()) {
319 cached = false;
320 }
321 }
322 if (!usedProgramBinaries) {
323 TRACE_EVENT0_ALWAYS("skia.shaders", "cache_miss");
324 // Either a cache miss, or we got something other than binaries from the cache
325
326 /*
327 Fragment Shader
328 */
329 if (glsl[kFragment_GrShaderType].empty()) {
330 // Don't have cached GLSL, need to compile SkSL->GLSL
331 if (fFS.fForceHighPrecision) {
332 settings.fForceHighPrecision = true;
333 }
334 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(this->gpu(),
335 SkSL::ProgramKind::kFragment,
336 *sksl[kFragment_GrShaderType],
337 settings,
338 &glsl[kFragment_GrShaderType],
339 errorHandler);
340 if (!fs) {
341 cleanup_program(fGpu, programID, shadersToDelete);
342 return nullptr;
343 }
344 inputs = fs->fInputs;
345 }
346
347 this->addInputVars(inputs);
348 if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
349 GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
350 cleanup_program(fGpu, programID, shadersToDelete);
351 return nullptr;
352 }
353
354 /*
355 Vertex Shader
356 */
357 if (glsl[kVertex_GrShaderType].empty()) {
358 // Don't have cached GLSL, need to compile SkSL->GLSL
359 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(this->gpu(),
360 SkSL::ProgramKind::kVertex,
361 *sksl[kVertex_GrShaderType],
362 settings,
363 &glsl[kVertex_GrShaderType],
364 errorHandler);
365 if (!vs) {
366 cleanup_program(fGpu, programID, shadersToDelete);
367 return nullptr;
368 }
369 }
370 if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
371 GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
372 cleanup_program(fGpu, programID, shadersToDelete);
373 return nullptr;
374 }
375
376 // This also binds vertex attribute locations.
377 this->computeCountsAndStrides(programID, geomProc, true);
378
379 /*
380 Tessellation Shaders
381 */
382 if (fProgramInfo.geomProc().willUseTessellationShaders()) {
383 // Tessellation shaders are not currently supported by SkSL. So here, we temporarily
384 // generate GLSL strings directly using back door methods on GrGeometryProcessor, and
385 // pass those raw strings on to the driver.
386 SkString versionAndExtensionDecls;
387 versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
388 if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
389 versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
390 }
391
392 SkString tessControlShader = fGeometryProcessor->getTessControlShaderGLSL(
393 geomProc, versionAndExtensionDecls.c_str(), fUniformHandler,
394 *this->shaderCaps());
395 if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
396 GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
397 errorHandler)) {
398 cleanup_program(fGpu, programID, shadersToDelete);
399 return nullptr;
400 }
401
402 SkString tessEvaluationShader = fGeometryProcessor->getTessEvaluationShaderGLSL(
403 geomProc, versionAndExtensionDecls.c_str(), fUniformHandler,
404 *this->shaderCaps());
405 if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
406 GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
407 errorHandler)) {
408 cleanup_program(fGpu, programID, shadersToDelete);
409 return nullptr;
410 }
411 }
412
413 /*
414 Geometry Shader
415 */
416 if (geomProc.willUseGeoShader()) {
417 if (glsl[kGeometry_GrShaderType].empty()) {
418 // Don't have cached GLSL, need to compile SkSL->GLSL
419 std::unique_ptr<SkSL::Program> gs;
420 gs = GrSkSLtoGLSL(this->gpu(),
421 SkSL::ProgramKind::kGeometry,
422 *sksl[kGeometry_GrShaderType],
423 settings,
424 &glsl[kGeometry_GrShaderType],
425 errorHandler);
426 if (!gs) {
427 cleanup_program(fGpu, programID, shadersToDelete);
428 return nullptr;
429 }
430 }
431 if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
432 GR_GL_GEOMETRY_SHADER, &shadersToDelete,
433 errorHandler)) {
434 cleanup_program(fGpu, programID, shadersToDelete);
435 return nullptr;
436 }
437 }
438 this->bindProgramResourceLocations(programID);
439
440 {
441 TRACE_EVENT0_ALWAYS("skia.shaders", "driver_link_program");
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 }
451 this->resolveProgramResourceLocations(programID, usedProgramBinaries);
452
453 cleanup_shaders(fGpu, shadersToDelete);
454
455 // We temporarily can't cache tessellation shaders while using back door GLSL.
456 //
457 // We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
458 // much point in doing so.
459 if (!cached && !geomProc.willUseTessellationShaders() && !precompiledProgram) {
460 // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
461 // GLSL mechanism is removed.
462 (void)&GrGLSLGeometryProcessor::getTessControlShaderGLSL;
463 bool isSkSL = false;
464 if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
465 GrContextOptions::ShaderCacheStrategy::kSkSL) {
466 for (int i = 0; i < kGrShaderTypeCount; ++i) {
467 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
468 }
469 isSkSL = true;
470 }
471 this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
472 }
473 return this->createProgram(programID);
474 }
475
bindProgramResourceLocations(GrGLuint programID)476 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
477 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
478
479 const GrGLCaps& caps = this->gpu()->glCaps();
480 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
481 GL_CALL(BindFragDataLocation(programID, 0,
482 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
483 }
484 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
485 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
486 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
487 }
488 }
489
checkLinkStatus(GrGLuint programID,GrContextOptions::ShaderErrorHandler * errorHandler,SkSL::String * sksl[],const SkSL::String glsl[])490 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
491 GrContextOptions::ShaderErrorHandler* errorHandler,
492 SkSL::String* sksl[], const SkSL::String glsl[]) {
493 GrGLint linked = GR_GL_INIT_ZERO;
494 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
495 if (!linked) {
496 SkSL::String allShaders;
497 if (sksl) {
498 allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
499 if (!sksl[kGeometry_GrShaderType]->empty()) {
500 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
501 }
502 allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
503 }
504 if (glsl) {
505 allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
506 if (!glsl[kGeometry_GrShaderType].empty()) {
507 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
508 }
509 allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
510 }
511 GrGLint infoLen = GR_GL_INIT_ZERO;
512 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
513 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
514 if (infoLen > 0) {
515 // retrieve length even though we don't need it to workaround
516 // bug in chrome cmd buffer param validation.
517 GrGLsizei length = GR_GL_INIT_ZERO;
518 GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
519 }
520 errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
521 }
522 return SkToBool(linked);
523 }
524
resolveProgramResourceLocations(GrGLuint programID,bool force)525 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
526 fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
527 }
528
createProgram(GrGLuint programID)529 sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
530 return GrGLProgram::Make(fGpu,
531 fUniformHandles,
532 programID,
533 fUniformHandler.fUniforms,
534 fUniformHandler.fSamplers,
535 std::move(fGeometryProcessor),
536 std::move(fXferProcessor),
537 std::move(fFPImpls),
538 std::move(fAttributes),
539 fVertexAttributeCnt,
540 fInstanceAttributeCnt,
541 fVertexStride,
542 fInstanceStride);
543 }
544
PrecompileProgram(GrDirectContext * dContext,GrGLPrecompiledProgram * precompiledProgram,const SkData & cachedData)545 bool GrGLProgramBuilder::PrecompileProgram(GrDirectContext* dContext,
546 GrGLPrecompiledProgram* precompiledProgram,
547 const SkData& cachedData) {
548 SkReadBuffer reader(cachedData.data(), cachedData.size());
549 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
550 if (shaderType != kSKSL_Tag) {
551 // TODO: Support GLSL, and maybe even program binaries, too?
552 return false;
553 }
554
555 GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
556
557 const GrGLInterface* gl = glGpu->glInterface();
558 auto errorHandler = dContext->priv().getShaderErrorHandler();
559
560 SkSL::Program::Settings settings;
561 settings.fSharpenTextures = dContext->priv().options().fSharpenMipmappedTextures;
562 GrPersistentCacheUtils::ShaderMetadata meta;
563 meta.fSettings = &settings;
564
565 SkSL::String shaders[kGrShaderTypeCount];
566 SkSL::Program::Inputs inputs;
567 if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
568 return false;
569 }
570
571 GrGLuint programID;
572 GR_GL_CALL_RET(gl, programID, CreateProgram());
573 if (0 == programID) {
574 return false;
575 }
576
577 SkTDArray<GrGLuint> shadersToDelete;
578
579 auto compileShader = [&](SkSL::ProgramKind kind, const SkSL::String& sksl, GrGLenum type) {
580 SkSL::String glsl;
581 auto program = GrSkSLtoGLSL(glGpu, kind, sksl, settings, &glsl, errorHandler);
582 if (!program) {
583 return false;
584 }
585
586 if (GrGLuint shaderID = GrGLCompileAndAttachShader(glGpu->glContext(), programID, type,
587 glsl, glGpu->pipelineBuilder()->stats(),
588 errorHandler)) {
589 shadersToDelete.push_back(shaderID);
590 return true;
591 } else {
592 return false;
593 }
594 };
595
596 if (!compileShader(SkSL::ProgramKind::kFragment,
597 shaders[kFragment_GrShaderType],
598 GR_GL_FRAGMENT_SHADER) ||
599 !compileShader(SkSL::ProgramKind::kVertex,
600 shaders[kVertex_GrShaderType],
601 GR_GL_VERTEX_SHADER) ||
602 (!shaders[kGeometry_GrShaderType].empty() &&
603 !compileShader(SkSL::ProgramKind::kGeometry,
604 shaders[kGeometry_GrShaderType],
605 GR_GL_GEOMETRY_SHADER))) {
606 cleanup_program(glGpu, programID, shadersToDelete);
607 return false;
608 }
609
610 for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
611 GR_GL_CALL(glGpu->glInterface(), BindAttribLocation(programID, i,
612 meta.fAttributeNames[i].c_str()));
613 }
614
615 const GrGLCaps& caps = glGpu->glCaps();
616 if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
617 GR_GL_CALL(glGpu->glInterface(),
618 BindFragDataLocation(programID, 0,
619 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
620 }
621 if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
622 GR_GL_CALL(glGpu->glInterface(),
623 BindFragDataLocationIndexed(programID, 0, 1,
624 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
625 }
626
627 GR_GL_CALL(glGpu->glInterface(), LinkProgram(programID));
628 GrGLint linked = GR_GL_INIT_ZERO;
629 GR_GL_CALL(glGpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
630 if (!linked) {
631 cleanup_program(glGpu, programID, shadersToDelete);
632 return false;
633 }
634
635 cleanup_shaders(glGpu, shadersToDelete);
636
637 precompiledProgram->fProgramID = programID;
638 precompiledProgram->fInputs = inputs;
639 return true;
640 }
641