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/ganesh/gl/builders/GrGLProgramBuilder.h"
9
10 #include "include/gpu/GrDirectContext.h"
11 #include "include/private/SkSLProgramKind.h"
12 #include "src/base/SkAutoMalloc.h"
13 #include "src/core/SkReadBuffer.h"
14 #include "src/core/SkTraceEvent.h"
15 #include "src/core/SkWriteBuffer.h"
16 #include "src/gpu/Swizzle.h"
17 #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
18 #include "src/gpu/ganesh/GrDirectContextPriv.h"
19 #include "src/gpu/ganesh/GrFragmentProcessor.h"
20 #include "src/gpu/ganesh/GrGeometryProcessor.h"
21 #include "src/gpu/ganesh/GrPersistentCacheUtils.h"
22 #include "src/gpu/ganesh/GrProgramDesc.h"
23 #include "src/gpu/ganesh/GrShaderCaps.h"
24 #include "src/gpu/ganesh/GrXferProcessor.h"
25 #include "src/gpu/ganesh/gl/GrGLGpu.h"
26 #include "src/gpu/ganesh/gl/GrGLProgram.h"
27 #include "src/gpu/ganesh/gl/builders/GrGLProgramBuilder.h"
28 #include "src/sksl/SkSLProgramSettings.h"
29 #include "src/utils/SkShaderUtils.h"
30
31 #include <memory>
32 #include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
33 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
34
35 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
36 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
37
cleanup_shaders(GrGLGpu * gpu,const SkTDArray<GrGLuint> & shaderIDs)38 static void cleanup_shaders(GrGLGpu* gpu, const SkTDArray<GrGLuint>& shaderIDs) {
39 for (int i = 0; i < shaderIDs.size(); ++i) {
40 GR_GL_CALL(gpu->glInterface(), DeleteShader(shaderIDs[i]));
41 }
42 }
43
cleanup_program(GrGLGpu * gpu,GrGLuint programID,const SkTDArray<GrGLuint> & shaderIDs)44 static void cleanup_program(GrGLGpu* gpu, GrGLuint programID,
45 const SkTDArray<GrGLuint>& shaderIDs) {
46 GR_GL_CALL(gpu->glInterface(), DeleteProgram(programID));
47 cleanup_shaders(gpu, shaderIDs);
48 }
49
CreateProgram(GrDirectContext * dContext,const GrProgramDesc & desc,const GrProgramInfo & programInfo,const GrGLPrecompiledProgram * precompiledProgram)50 sk_sp<GrGLProgram> GrGLProgramBuilder::CreateProgram(
51 GrDirectContext* dContext,
52 const GrProgramDesc& desc,
53 const GrProgramInfo& programInfo,
54 const GrGLPrecompiledProgram* precompiledProgram) {
55 TRACE_EVENT0_ALWAYS("skia.shaders", "shader_compile");
56 GrAutoLocaleSetter als("C");
57
58 GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
59
60 // create a builder. This will be handed off to effects so they can use it to add
61 // uniforms, varyings, textures, etc
62 GrGLProgramBuilder builder(glGpu, desc, programInfo);
63
64 auto persistentCache = dContext->priv().getPersistentCache();
65 if (persistentCache && !precompiledProgram) {
66 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
67 builder.fCached = persistentCache->load(*key);
68 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
69 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
70 // to skip the SkSL->GLSL step on a cache hit.
71 }
72 if (!builder.emitAndInstallProcs()) {
73 return nullptr;
74 }
75 return builder.finalize(precompiledProgram);
76 }
77
78 /////////////////////////////////////////////////////////////////////////////
79
GrGLProgramBuilder(GrGLGpu * gpu,const GrProgramDesc & desc,const GrProgramInfo & programInfo)80 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
81 const GrProgramDesc& desc,
82 const GrProgramInfo& programInfo)
83 : INHERITED(desc, programInfo)
84 , fGpu(gpu)
85 , fVaryingHandler(this)
86 , fUniformHandler(this)
87 , fVertexAttributeCnt(0)
88 , fInstanceAttributeCnt(0)
89 , fVertexStride(0)
90 , fInstanceStride(0) {}
91
caps() const92 const GrCaps* GrGLProgramBuilder::caps() const {
93 return fGpu->caps();
94 }
95
shaderCompiler() const96 SkSL::Compiler* GrGLProgramBuilder::shaderCompiler() const {
97 return fGpu->shaderCompiler();
98 }
99
compileAndAttachShaders(const std::string & glsl,GrGLuint programId,GrGLenum type,SkTDArray<GrGLuint> * shaderIds,GrContextOptions::ShaderErrorHandler * errHandler)100 bool GrGLProgramBuilder::compileAndAttachShaders(const std::string& glsl,
101 GrGLuint programId,
102 GrGLenum type,
103 SkTDArray<GrGLuint>* shaderIds,
104 GrContextOptions::ShaderErrorHandler* errHandler) {
105 GrGLGpu* gpu = this->gpu();
106 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
107 programId,
108 type,
109 glsl,
110 gpu->pipelineBuilder()->stats(),
111 errHandler);
112 if (!shaderId) {
113 return false;
114 }
115
116 *shaderIds->append() = shaderId;
117 return true;
118 }
119
computeCountsAndStrides(GrGLuint programID,const GrGeometryProcessor & geomProc,bool bindAttribLocations)120 void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
121 const GrGeometryProcessor& geomProc,
122 bool bindAttribLocations) {
123 fVertexAttributeCnt = geomProc.numVertexAttributes();
124 fInstanceAttributeCnt = geomProc.numInstanceAttributes();
125 fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
126 fVertexAttributeCnt + fInstanceAttributeCnt);
127 auto addAttr = [&](int i, const auto& a) {
128 fAttributes[i].fCPUType = a.cpuType();
129 fAttributes[i].fGPUType = a.gpuType();
130 fAttributes[i].fOffset = *a.offset();
131 fAttributes[i].fLocation = i;
132 if (bindAttribLocations) {
133 GL_CALL(BindAttribLocation(programID, i, a.name()));
134 }
135 };
136 fVertexStride = geomProc.vertexStride();
137 int i = 0;
138 for (auto attr : geomProc.vertexAttributes()) {
139 addAttr(i++, attr);
140 }
141 fInstanceStride = geomProc.instanceStride();
142 for (auto attr : geomProc.instanceAttributes()) {
143 addAttr(i++, attr);
144 }
145 SkASSERT(fInstanceStride == geomProc.instanceStride());
146 }
147
addInputVars(const SkSL::Program::Inputs & inputs)148 void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
149 if (inputs.fUseFlipRTUniform) {
150 this->addRTFlipUniform(SKSL_RTFLIP_NAME);
151 }
152 }
153
154 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
155 static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
156 static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
157
storeShaderInCache(const SkSL::Program::Inputs & inputs,GrGLuint programID,const std::string shaders[],bool isSkSL,SkSL::ProgramSettings * settings)158 void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
159 const std::string shaders[], bool isSkSL,
160 SkSL::ProgramSettings* 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 SkString description = GrProgramDesc::Describe(fProgramInfo, *fGpu->caps());
166 if (fGpu->glCaps().programBinarySupport()) {
167 // binary cache
168 GrGLsizei length = 0;
169 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
170 if (length > 0) {
171 SkBinaryWriteBuffer writer;
172 writer.writeInt(GrPersistentCacheUtils::GetCurrentVersion());
173 writer.writeUInt(kGLPB_Tag);
174
175 writer.writePad32(&inputs, sizeof(inputs));
176
177 SkAutoSMalloc<2048> binary(length);
178 GrGLenum binaryFormat;
179 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
180
181 writer.writeUInt(binaryFormat);
182 writer.writeInt(length);
183 writer.writePad32(binary.get(), length);
184
185 auto data = writer.snapshotAsData();
186 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
187 }
188 } else {
189 // source cache, plus metadata to allow for a complete precompile
190 GrPersistentCacheUtils::ShaderMetadata meta;
191 meta.fSettings = settings;
192 meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
193 for (auto attr : this->geometryProcessor().vertexAttributes()) {
194 meta.fAttributeNames.emplace_back(attr.name());
195 }
196 for (auto attr : this->geometryProcessor().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, description);
203 }
204 }
205
finalize(const GrGLPrecompiledProgram * precompiledProgram)206 sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
207 TRACE_EVENT0("skia.shaders", 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 GrGeometryProcessor& geomProc = this->geometryProcessor();
232 SkSL::ProgramSettings settings;
233 settings.fSharpenTextures = true;
234 settings.fFragColorIsInOut = this->fragColorIsInOut();
235
236 SkSL::Program::Inputs inputs;
237 SkTDArray<GrGLuint> shadersToDelete;
238
239 bool cached = fCached.get() != nullptr;
240 bool usedProgramBinaries = false;
241 std::string glsl[kGrShaderTypeCount];
242 const std::string* sksl[kGrShaderTypeCount] = {
243 &fVS.fCompilerString,
244 &fFS.fCompilerString,
245 };
246 std::string cached_sksl[kGrShaderTypeCount];
247 if (precompiledProgram) {
248 // This is very similar to when we get program binaries. We even set that flag, as it's
249 // used to prevent other compile work later, and to force re-querying uniform locations.
250 this->addInputVars(precompiledProgram->fInputs);
251 this->computeCountsAndStrides(programID, geomProc, false);
252 usedProgramBinaries = true;
253 } else if (cached) {
254 TRACE_EVENT0_ALWAYS("skia.shaders", "cache_hit");
255 SkReadBuffer reader(fCached->data(), fCached->size());
256 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
257
258 switch (shaderType) {
259 case kGLPB_Tag: {
260 // Program binary cache hit. We may opt not to use this if we don't trust program
261 // binaries on this driver
262 if (!fGpu->glCaps().programBinarySupport()) {
263 cached = false;
264 break;
265 }
266 reader.readPad32(&inputs, sizeof(inputs));
267 GrGLenum binaryFormat = reader.readUInt();
268 GrGLsizei length = reader.readInt();
269 const void* binary = reader.skip(length);
270 if (!reader.isValid()) {
271 break;
272 }
273 if (length <= 0 || !fGpu->glCaps().programBinaryFormatIsValid(binaryFormat)) {
274 cached = false;
275 break;
276 }
277 GL_CALL(ProgramBinary(programID, binaryFormat, const_cast<void*>(binary), length));
278 // Pass nullptr for the error handler. We don't want to treat this as a compile
279 // failure (we can still recover by compiling the program from source, below).
280 // Clients won't be directly notified, but they can infer this from the trace
281 // events, and from the traffic to the persistent cache.
282 cached = GrGLCheckLinkStatus(fGpu, programID,
283 /*errorHandler=*/nullptr, nullptr, nullptr);
284 if (cached) {
285 this->addInputVars(inputs);
286 this->computeCountsAndStrides(programID, geomProc, false);
287 }
288 usedProgramBinaries = cached;
289 break;
290 }
291
292 case kGLSL_Tag:
293 // Source cache hit, we don't need to compile the SkSL->GLSL
294 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
295 break;
296
297 case kSKSL_Tag:
298 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
299 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
300 for (int i = 0; i < kGrShaderTypeCount; ++i) {
301 sksl[i] = &cached_sksl[i];
302 }
303 }
304 break;
305
306 default:
307 // We got something invalid, so pretend it wasn't there
308 reader.validate(false);
309 break;
310 }
311 if (!reader.isValid()) {
312 cached = false;
313 }
314 }
315 if (!usedProgramBinaries) {
316 TRACE_EVENT0_ALWAYS("skia.shaders", "cache_miss");
317 // Either a cache miss, or we got something other than binaries from the cache
318
319 /*
320 Fragment Shader
321 */
322 if (glsl[kFragment_GrShaderType].empty()) {
323 // Don't have cached GLSL, need to compile SkSL->GLSL
324 if (fFS.fForceHighPrecision) {
325 settings.fForceHighPrecision = true;
326 }
327 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(this->gpu(),
328 SkSL::ProgramKind::kFragment,
329 *sksl[kFragment_GrShaderType],
330 settings,
331 &glsl[kFragment_GrShaderType],
332 errorHandler);
333 if (!fs) {
334 cleanup_program(fGpu, programID, shadersToDelete);
335 return nullptr;
336 }
337 inputs = fs->fInputs;
338 }
339
340 this->addInputVars(inputs);
341 if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
342 GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
343 cleanup_program(fGpu, programID, shadersToDelete);
344 return nullptr;
345 }
346
347 /*
348 Vertex Shader
349 */
350 if (glsl[kVertex_GrShaderType].empty()) {
351 // Don't have cached GLSL, need to compile SkSL->GLSL
352 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(this->gpu(),
353 SkSL::ProgramKind::kVertex,
354 *sksl[kVertex_GrShaderType],
355 settings,
356 &glsl[kVertex_GrShaderType],
357 errorHandler);
358 if (!vs) {
359 cleanup_program(fGpu, programID, shadersToDelete);
360 return nullptr;
361 }
362 }
363 if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
364 GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
365 cleanup_program(fGpu, programID, shadersToDelete);
366 return nullptr;
367 }
368
369 // This also binds vertex attribute locations.
370 this->computeCountsAndStrides(programID, geomProc, true);
371
372 this->bindProgramResourceLocations(programID);
373
374 {
375 TRACE_EVENT0_ALWAYS("skia.shaders", "driver_link_program");
376 GL_CALL(LinkProgram(programID));
377 if (!GrGLCheckLinkStatus(fGpu, programID, errorHandler, sksl, glsl)) {
378 cleanup_program(fGpu, programID, shadersToDelete);
379 return nullptr;
380 }
381 }
382 }
383 this->resolveProgramResourceLocations(programID, usedProgramBinaries);
384
385 cleanup_shaders(fGpu, shadersToDelete);
386
387 // We can't cache SkSL or GLSL if we were given a precompiled program, but there's not
388 // much point in doing so.
389 if (!cached && !precompiledProgram) {
390 bool isSkSL = false;
391 if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
392 GrContextOptions::ShaderCacheStrategy::kSkSL) {
393 for (int i = 0; i < kGrShaderTypeCount; ++i) {
394 glsl[i] = SkShaderUtils::PrettyPrint(*sksl[i]);
395 }
396 isSkSL = true;
397 }
398 this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
399 }
400 return this->createProgram(programID);
401 }
402
bindProgramResourceLocations(GrGLuint programID)403 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
404 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
405
406 const GrGLCaps& caps = this->gpu()->glCaps();
407 if (caps.bindFragDataLocationSupport()) {
408 SkASSERT(caps.shaderCaps()->mustDeclareFragmentShaderOutput());
409 GL_CALL(BindFragDataLocation(programID, 0,
410 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
411 if (fFS.hasSecondaryOutput()) {
412 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
413 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
414 }
415 }
416 }
417
resolveProgramResourceLocations(GrGLuint programID,bool force)418 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
419 fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
420 }
421
createProgram(GrGLuint programID)422 sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
423 return GrGLProgram::Make(fGpu,
424 fUniformHandles,
425 programID,
426 fUniformHandler.fUniforms,
427 fUniformHandler.fSamplers,
428 std::move(fGPImpl),
429 std::move(fXPImpl),
430 std::move(fFPImpls),
431 std::move(fAttributes),
432 fVertexAttributeCnt,
433 fInstanceAttributeCnt,
434 fVertexStride,
435 fInstanceStride);
436 }
437
PrecompileProgram(GrDirectContext * dContext,GrGLPrecompiledProgram * precompiledProgram,const SkData & cachedData)438 bool GrGLProgramBuilder::PrecompileProgram(GrDirectContext* dContext,
439 GrGLPrecompiledProgram* precompiledProgram,
440 const SkData& cachedData) {
441 SkReadBuffer reader(cachedData.data(), cachedData.size());
442 SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
443 if (shaderType != kSKSL_Tag) {
444 // TODO: Support GLSL, and maybe even program binaries, too?
445 return false;
446 }
447
448 GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
449
450 const GrGLInterface* gl = glGpu->glInterface();
451 auto errorHandler = dContext->priv().getShaderErrorHandler();
452
453 SkSL::ProgramSettings settings;
454 settings.fSharpenTextures = true;
455 GrPersistentCacheUtils::ShaderMetadata meta;
456 meta.fSettings = &settings;
457
458 std::string shaders[kGrShaderTypeCount];
459 SkSL::Program::Inputs inputs;
460 if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
461 return false;
462 }
463
464 GrGLuint programID;
465 GR_GL_CALL_RET(gl, programID, CreateProgram());
466 if (0 == programID) {
467 return false;
468 }
469
470 SkTDArray<GrGLuint> shadersToDelete;
471
472 auto compileShader = [&](SkSL::ProgramKind kind, const std::string& sksl, GrGLenum type) {
473 std::string glsl;
474 auto program = GrSkSLtoGLSL(glGpu, kind, sksl, settings, &glsl, errorHandler);
475 if (!program) {
476 return false;
477 }
478
479 if (GrGLuint shaderID = GrGLCompileAndAttachShader(glGpu->glContext(), programID, type,
480 glsl, glGpu->pipelineBuilder()->stats(),
481 errorHandler)) {
482 shadersToDelete.push_back(shaderID);
483 return true;
484 } else {
485 return false;
486 }
487 };
488
489 if (!compileShader(SkSL::ProgramKind::kFragment,
490 shaders[kFragment_GrShaderType],
491 GR_GL_FRAGMENT_SHADER) ||
492 !compileShader(SkSL::ProgramKind::kVertex,
493 shaders[kVertex_GrShaderType],
494 GR_GL_VERTEX_SHADER)) {
495 cleanup_program(glGpu, programID, shadersToDelete);
496 return false;
497 }
498
499 for (int i = 0; i < meta.fAttributeNames.size(); ++i) {
500 GR_GL_CALL(glGpu->glInterface(), BindAttribLocation(programID, i,
501 meta.fAttributeNames[i].c_str()));
502 }
503
504 const GrGLCaps& caps = glGpu->glCaps();
505 if (caps.bindFragDataLocationSupport()) {
506 SkASSERT(caps.shaderCaps()->mustDeclareFragmentShaderOutput());
507 GR_GL_CALL(glGpu->glInterface(),
508 BindFragDataLocation(programID, 0,
509 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
510
511 if (meta.fHasSecondaryColorOutput) {
512 GR_GL_CALL(glGpu->glInterface(),
513 BindFragDataLocationIndexed(programID, 0, 1,
514 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
515 }
516 }
517
518 GR_GL_CALL(glGpu->glInterface(), LinkProgram(programID));
519 GrGLint linked = GR_GL_INIT_ZERO;
520 GR_GL_CALL(glGpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
521 if (!linked) {
522 cleanup_program(glGpu, programID, shadersToDelete);
523 return false;
524 }
525
526 cleanup_shaders(glGpu, shadersToDelete);
527
528 precompiledProgram->fProgramID = programID;
529 precompiledProgram->fInputs = inputs;
530 return true;
531 }
532