blob: c830fad95e27327b584757536b6ec2b45f4eadbc [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
joshualitt8072caa2015-02-12 14:20:52 -08009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrShaderCaps.h"
Brian Osmanac9be9d2019-05-01 10:29:34 -040022#include "src/gpu/GrShaderUtils.h"
Brian Salomon3ec1f542019-06-17 17:54:57 +000023#include "src/gpu/GrSwizzle.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#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"
joshualitt30ba4362014-08-21 20:18:45 -070032
joshualitt30ba4362014-08-21 20:18:45 -070033#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
Robert Phillipsd0fe8752019-01-31 14:13:59 -050036GrGLProgram* GrGLProgramBuilder::CreateProgram(GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
37 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050038 const GrTextureProxy* const primProcProxies[],
Brian Salomonff168d92018-06-23 15:17:27 -040039 const GrPipeline& pipeline,
Ethan Nicholas38657112017-02-09 17:01:22 -050040 GrProgramDesc* desc,
egdaniel0e1853c2016-03-17 11:35:45 -070041 GrGLGpu* gpu) {
Brian Salomon7eae3e02018-08-07 14:02:38 +000042 SkASSERT(!pipeline.isBad());
Robert Phillipsa91e0b72017-05-01 13:12:20 -040043
Derek Sollenberger488f0d62017-03-03 15:48:33 -050044 ATRACE_ANDROID_FRAMEWORK("Shader Compile");
bsalomon3318ee72015-03-16 11:56:29 -070045 GrAutoLocaleSetter als("C");
46
joshualitt47bb3822014-10-07 16:43:25 -070047 // create a builder. This will be handed off to effects so they can use it to add
48 // uniforms, varyings, textures, etc
Robert Phillipsd0fe8752019-01-31 14:13:59 -050049 GrGLProgramBuilder builder(gpu, renderTarget, origin,
50 pipeline, primProc, primProcProxies, desc);
joshualitt47bb3822014-10-07 16:43:25 -070051
Robert Phillips9da87e02019-02-04 13:26:26 -050052 auto persistentCache = gpu->getContext()->priv().getPersistentCache();
Ethan Nicholas8d058832019-01-07 10:49:58 -050053 if (persistentCache) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040054 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
Robert Phillips0c4b7b12018-03-06 08:20:37 -050055 builder.fCached = persistentCache->load(*key);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040056 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
57 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
58 // to skip the SkSL->GLSL step on a cache hit.
59 }
Ethan Nicholas2983f402017-05-08 09:36:08 -040060 if (!builder.emitAndInstallProcs()) {
halcanary96fcdcc2015-08-27 07:41:13 -070061 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070062 }
egdanielc1e71012016-01-20 07:53:51 -080063 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070064}
65
joshualitt47bb3822014-10-07 16:43:25 -070066/////////////////////////////////////////////////////////////////////////////
67
egdaniel0e1853c2016-03-17 11:35:45 -070068GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
Robert Phillipsd0fe8752019-01-31 14:13:59 -050069 GrRenderTarget* renderTarget,
70 GrSurfaceOrigin origin,
egdaniel0e1853c2016-03-17 11:35:45 -070071 const GrPipeline& pipeline,
72 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050073 const GrTextureProxy* const primProcProxies[],
Ethan Nicholas38657112017-02-09 17:01:22 -050074 GrProgramDesc* desc)
Robert Phillipsd0fe8752019-01-31 14:13:59 -050075 : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
Brian Salomon802cb312018-06-08 18:05:20 -040076 , fGpu(gpu)
77 , fVaryingHandler(this)
78 , fUniformHandler(this)
Brian Salomon92be2f72018-06-19 14:33:47 -040079 , fVertexAttributeCnt(0)
80 , fInstanceAttributeCnt(0)
Brian Salomon802cb312018-06-08 18:05:20 -040081 , fVertexStride(0)
82 , fInstanceStride(0) {}
joshualitt30ba4362014-08-21 20:18:45 -070083
egdanielfa896322016-01-13 12:19:30 -080084const GrCaps* GrGLProgramBuilder::caps() const {
85 return fGpu->caps();
86}
87
Brian Osmanac9be9d2019-05-01 10:29:34 -040088bool GrGLProgramBuilder::compileAndAttachShaders(const SkSL::String& glsl,
egdaniel574a4c12015-11-02 06:22:44 -080089 GrGLuint programId,
90 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050091 SkTDArray<GrGLuint>* shaderIds,
Brian Osman5e7fbfd2019-05-03 13:13:35 -040092 const SkSL::Program::Inputs& inputs,
93 GrContextOptions::ShaderErrorHandler* errHandler) {
egdaniel574a4c12015-11-02 06:22:44 -080094 GrGLGpu* gpu = this->gpu();
95 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
96 programId,
97 type,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040098 glsl,
Brian Osman8518f2e2019-05-01 14:13:41 -040099 gpu->stats(),
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400100 errHandler);
egdaniel574a4c12015-11-02 06:22:44 -0800101 if (!shaderId) {
102 return false;
103 }
104
105 *shaderIds->append() = shaderId;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400106 if (inputs.fFlipY) {
Ethan Nicholas38657112017-02-09 17:01:22 -0500107 GrProgramDesc* d = this->desc();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500108 d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(this->origin()));
Ethan Nicholas38657112017-02-09 17:01:22 -0500109 }
egdaniel574a4c12015-11-02 06:22:44 -0800110
111 return true;
112}
113
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400114void 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) {
Brian Osman4a3f5c82018-09-18 16:16:38 -0400122 fAttributes[i].fCPUType = a.cpuType();
123 fAttributes[i].fGPUType = a.gpuType();
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400124 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;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500133 for (const auto& attr : primProc.vertexAttributes()) {
134 addAttr(i++, attr, &fVertexStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400135 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500136 SkASSERT(fVertexStride == primProc.vertexStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400137 fInstanceStride = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500138 for (const auto& attr : primProc.instanceAttributes()) {
139 addAttr(i++, attr, &fInstanceStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400140 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500141 SkASSERT(fInstanceStride == primProc.instanceStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400142}
143
Ethan Nicholascd700e92018-08-24 16:43:57 -0400144void 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
Brian Osmana085a412019-04-25 09:44:43 -0400153static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
154static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
155
Ethan Nicholas8d058832019-01-07 10:49:58 -0500156void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
Brian Osmana085a412019-04-25 09:44:43 -0400157 const SkSL::String shaders[], bool isSkSL) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500158 if (!this->gpu()->getContext()->priv().getPersistentCache()) {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500159 return;
160 }
161 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
162 if (fGpu->glCaps().programBinarySupport()) {
163 // binary cache
164 GrGLsizei length = 0;
165 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
166 if (length > 0) {
Brian Osman6b797fe2019-04-08 13:56:36 -0400167 SkWriter32 writer;
168 writer.writePad(&inputs, sizeof(inputs));
169 writer.write32(length);
170
171 void* binary = writer.reservePad(length);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500172 GrGLenum binaryFormat;
Brian Osman6b797fe2019-04-08 13:56:36 -0400173 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary));
174 writer.write32(binaryFormat);
175
176 auto data = writer.snapshotAsData();
177 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500178 }
179 } else {
180 // source cache
Brian Osmana085a412019-04-25 09:44:43 -0400181 auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
182 shaders, &inputs, 1);
Brian Osman6b797fe2019-04-08 13:56:36 -0400183 this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500184 }
185}
186
joshualitt47bb3822014-10-07 16:43:25 -0700187GrGLProgram* GrGLProgramBuilder::finalize() {
Brian Osman39c08ac2017-07-26 09:36:09 -0400188 TRACE_EVENT0("skia", TRACE_FUNC);
Ryan Macnak38a10ad2017-07-10 10:36:34 -0700189
joshualitt47bb3822014-10-07 16:43:25 -0700190 // verify we can get a program id
191 GrGLuint programID;
192 GL_CALL_RET(programID, CreateProgram());
193 if (0 == programID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700194 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700195 }
196
Ethan Nicholas06d55fb2017-11-08 09:48:50 -0500197 if (this->gpu()->glCaps().programBinarySupport() &&
Brian Osman064729e2019-06-18 17:22:59 -0400198 this->gpu()->glCaps().programParameterSupport() &&
Robert Phillips9da87e02019-02-04 13:26:26 -0500199 this->gpu()->getContext()->priv().getPersistentCache()) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400200 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
201 }
202
egdaniel9f1d4152016-02-10 09:50:38 -0800203 this->finalizeShaders();
204
joshualitt47bb3822014-10-07 16:43:25 -0700205 // compile shaders and bind attributes / uniforms
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400206 auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400207 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500208 SkSL::Program::Settings settings;
209 settings.fCaps = this->gpu()->glCaps().shaderCaps();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500210 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
Robert Phillipsc1541ae2019-02-04 12:05:37 -0500211 settings.fSharpenTextures =
Robert Phillips9da87e02019-02-04 13:26:26 -0500212 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
Brian Salomondc092132018-04-04 10:14:16 -0400213 settings.fFragColorIsInOut = this->fragColorIsInOut();
214
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500215 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700216 SkTDArray<GrGLuint> shadersToDelete;
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500217 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
218 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
219#ifdef SK_DEBUG
220 checkLinked = true;
221#endif
Ethan Nicholas8d058832019-01-07 10:49:58 -0500222 bool cached = fCached.get() != nullptr;
Brian Osman6b797fe2019-04-08 13:56:36 -0400223 SkSL::String glsl[kGrShaderTypeCount];
Brian Osmancbc33b82019-04-19 14:16:19 -0400224 SkSL::String* sksl[kGrShaderTypeCount] = {
225 &fVS.fCompilerString,
226 &fGS.fCompilerString,
227 &fFS.fCompilerString,
228 };
229#if GR_TEST_UTILS
230 SkSL::String cached_sksl[kGrShaderTypeCount];
231#endif
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400232 if (cached) {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500233 if (fGpu->glCaps().programBinarySupport()) {
234 // binary cache hit, just hand the binary to GL
Brian Osmane6ef03d2019-04-11 14:38:27 -0400235 SkReader32 reader(fCached->data(), fCached->size());
Brian Osman6b797fe2019-04-08 13:56:36 -0400236 reader.read(&inputs, sizeof(inputs));
237 GrGLsizei length = reader.readInt();
238 const void* binary = reader.skip(length);
239 GrGLenum binaryFormat = reader.readU32();
Ethan Nicholas8d058832019-01-07 10:49:58 -0500240 GrGLClearErr(this->gpu()->glInterface());
241 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
Brian Osman6b797fe2019-04-08 13:56:36 -0400242 ProgramBinary(programID, binaryFormat, const_cast<void*>(binary),
243 length));
Ethan Nicholas8d058832019-01-07 10:49:58 -0500244 if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
245 if (checkLinked) {
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400246 cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500247 }
248 if (cached) {
249 this->addInputVars(inputs);
250 this->computeCountsAndStrides(programID, primProc, false);
251 }
252 } else {
253 cached = false;
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400254 }
Brian Osmancbc33b82019-04-19 14:16:19 -0400255#if GR_TEST_UTILS
256 } else if (fGpu->getContext()->priv().options().fCacheSKSL) {
Brian Osmana085a412019-04-25 09:44:43 -0400257 // Only switch to the stored SkSL if it unpacks correctly
258 if (kSKSL_Tag == GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
259 cached_sksl,
260 &inputs, 1)) {
261 for (int i = 0; i < kGrShaderTypeCount; ++i) {
262 sksl[i] = &cached_sksl[i];
263 }
Brian Osmancbc33b82019-04-19 14:16:19 -0400264 }
265#endif
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400266 } else {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500267 // source cache hit, we don't need to compile the SkSL->GLSL
Brian Osmana085a412019-04-25 09:44:43 -0400268 // It's unlikely, but if we get the wrong kind of shader back, don't use the strings
269 if (kGLSL_Tag != GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
270 glsl,
271 &inputs, 1)) {
272 for (int i = 0; i < kGrShaderTypeCount; ++i) {
273 glsl[i].clear();
274 }
275 }
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400276 }
277 }
Ethan Nicholas8d058832019-01-07 10:49:58 -0500278 if (!cached || !fGpu->glCaps().programBinarySupport()) {
279 // either a cache miss, or we can't store binaries in the cache
Brian Osman6b797fe2019-04-08 13:56:36 -0400280 if (glsl[kFragment_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400281 // Don't have cached GLSL, need to compile SkSL->GLSL
Ethan Nicholas8d058832019-01-07 10:49:58 -0500282 if (fFS.fForceHighPrecision) {
283 settings.fForceHighPrecision = true;
284 }
285 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
Brian Osmanac9be9d2019-05-01 10:29:34 -0400286 SkSL::Program::kFragment_Kind,
Brian Osmancbc33b82019-04-19 14:16:19 -0400287 *sksl[kFragment_GrShaderType],
Ethan Nicholas8d058832019-01-07 10:49:58 -0500288 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400289 &glsl[kFragment_GrShaderType],
290 errorHandler);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500291 if (!fs) {
292 this->cleanupProgram(programID, shadersToDelete);
293 return nullptr;
294 }
295 inputs = fs->fInputs;
Brian Osmanf71b0702019-04-03 13:04:16 -0400296 this->addInputVars(inputs);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500297 } else {
298 // we've pulled GLSL and inputs from the cache, but still need to do some setup
299 this->addInputVars(inputs);
300 this->computeCountsAndStrides(programID, primProc, false);
egdaniel8dcdedc2015-11-11 06:27:20 -0800301 }
Brian Osmanac9be9d2019-05-01 10:29:34 -0400302 if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400303 GR_GL_FRAGMENT_SHADER, &shadersToDelete, inputs,
304 errorHandler)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400305 this->cleanupProgram(programID, shadersToDelete);
306 return nullptr;
307 }
308
Brian Osman6b797fe2019-04-08 13:56:36 -0400309 if (glsl[kVertex_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400310 // Don't have cached GLSL, need to compile SkSL->GLSL
311 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
Brian Osmanac9be9d2019-05-01 10:29:34 -0400312 SkSL::Program::kVertex_Kind,
Brian Osmancbc33b82019-04-19 14:16:19 -0400313 *sksl[kVertex_GrShaderType],
Brian Osmanf71b0702019-04-03 13:04:16 -0400314 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400315 &glsl[kVertex_GrShaderType],
316 errorHandler);
Brian Osmanf71b0702019-04-03 13:04:16 -0400317 if (!vs) {
318 this->cleanupProgram(programID, shadersToDelete);
319 return nullptr;
320 }
321 }
Brian Osmanac9be9d2019-05-01 10:29:34 -0400322 if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400323 GR_GL_VERTEX_SHADER, &shadersToDelete, inputs,
324 errorHandler)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400325 this->cleanupProgram(programID, shadersToDelete);
326 return nullptr;
327 }
328
329 // NVPR actually requires a vertex shader to compile
330 bool useNvpr = primProc.isPathRendering();
331 if (!useNvpr) {
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400332 this->computeCountsAndStrides(programID, primProc, true);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400333 }
334
335 if (primProc.willUseGeoShader()) {
Brian Osman6b797fe2019-04-08 13:56:36 -0400336 if (glsl[kGeometry_GrShaderType].empty()) {
Brian Osmanf71b0702019-04-03 13:04:16 -0400337 // Don't have cached GLSL, need to compile SkSL->GLSL
338 std::unique_ptr<SkSL::Program> gs;
339 gs = GrSkSLtoGLSL(gpu()->glContext(),
Brian Osmanac9be9d2019-05-01 10:29:34 -0400340 SkSL::Program::kGeometry_Kind,
Brian Osmancbc33b82019-04-19 14:16:19 -0400341 *sksl[kGeometry_GrShaderType],
Brian Osmanf71b0702019-04-03 13:04:16 -0400342 settings,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400343 &glsl[kGeometry_GrShaderType],
344 errorHandler);
Brian Osmanf71b0702019-04-03 13:04:16 -0400345 if (!gs) {
346 this->cleanupProgram(programID, shadersToDelete);
347 return nullptr;
348 }
349 }
Brian Osmanac9be9d2019-05-01 10:29:34 -0400350 if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400351 GR_GL_GEOMETRY_SHADER, &shadersToDelete, inputs,
352 errorHandler)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400353 this->cleanupProgram(programID, shadersToDelete);
354 return nullptr;
355 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400356 }
357 this->bindProgramResourceLocations(programID);
358
359 GL_CALL(LinkProgram(programID));
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500360 if (checkLinked) {
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400361 if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500362 GL_CALL(DeleteProgram(programID));
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500363 return nullptr;
Brian Salomone334c592017-05-15 11:00:58 -0400364 }
Brian Salomone334c592017-05-15 11:00:58 -0400365 }
joshualittfe1233c2014-10-07 12:16:35 -0700366 }
kkinnunen7aedda52015-06-29 23:01:28 -0700367 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700368
joshualitt47bb3822014-10-07 16:43:25 -0700369 this->cleanupShaders(shadersToDelete);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500370 if (!cached) {
Brian Osmana085a412019-04-25 09:44:43 -0400371 bool isSkSL = false;
Brian Osmancbc33b82019-04-19 14:16:19 -0400372#if GR_TEST_UTILS
373 if (fGpu->getContext()->priv().options().fCacheSKSL) {
374 for (int i = 0; i < kGrShaderTypeCount; ++i) {
Brian Osmanac9be9d2019-05-01 10:29:34 -0400375 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
Brian Osmancbc33b82019-04-19 14:16:19 -0400376 }
Brian Osmana085a412019-04-25 09:44:43 -0400377 isSkSL = true;
Brian Osmancbc33b82019-04-19 14:16:19 -0400378 }
379#endif
Brian Osmana085a412019-04-25 09:44:43 -0400380 this->storeShaderInCache(inputs, programID, glsl, isSkSL);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400381 }
joshualitt47bb3822014-10-07 16:43:25 -0700382 return this->createProgram(programID);
383}
384
kkinnunen7aedda52015-06-29 23:01:28 -0700385void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800386 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700387
egdaniel8dcdedc2015-11-11 06:27:20 -0800388 const GrGLCaps& caps = this->gpu()->glCaps();
389 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
390 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800391 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800392 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500393 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800394 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800395 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800396 }
joshualittd8dd47b2015-09-11 11:45:01 -0700397
398 // handle NVPR separable varyings
399 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
400 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
401 return;
402 }
egdaniel0eafe792015-11-20 14:01:22 -0800403 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700404 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800405 GL_CALL(BindFragmentInputLocation(programID, i,
406 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
407 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700408 }
joshualitt47bb3822014-10-07 16:43:25 -0700409}
410
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400411bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
412 GrContextOptions::ShaderErrorHandler* errorHandler,
413 SkSL::String* sksl[], const SkSL::String glsl[]) {
joshualitt47bb3822014-10-07 16:43:25 -0700414 GrGLint linked = GR_GL_INIT_ZERO;
415 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
416 if (!linked) {
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400417 SkSL::String allShaders;
418 if (sksl) {
419 allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
420 if (!sksl[kGeometry_GrShaderType]->empty()) {
421 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
422 }
423 allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
424 }
425 if (glsl) {
426 allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
427 if (!glsl[kGeometry_GrShaderType].empty()) {
428 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
429 }
430 allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
431 }
joshualitt47bb3822014-10-07 16:43:25 -0700432 GrGLint infoLen = GR_GL_INIT_ZERO;
433 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
434 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
435 if (infoLen > 0) {
436 // retrieve length even though we don't need it to workaround
437 // bug in chrome cmd buffer param validation.
438 GrGLsizei length = GR_GL_INIT_ZERO;
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400439 GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700440 }
Brian Osman5e7fbfd2019-05-03 13:13:35 -0400441 errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
joshualitt47bb3822014-10-07 16:43:25 -0700442 }
443 return SkToBool(linked);
444}
445
kkinnunen7aedda52015-06-29 23:01:28 -0700446void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800447 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700448
449 // handle NVPR separable varyings
450 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800451 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700452 return;
453 }
egdaniel0eafe792015-11-20 14:01:22 -0800454 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700455 for (int i = 0; i < count; ++i) {
456 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800457 GL_CALL_RET(location, GetProgramResourceLocation(
458 programID,
459 GR_GL_FRAGMENT_INPUT,
460 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
461 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700462 }
joshualitt30ba4362014-08-21 20:18:45 -0700463}
464
joshualitt47bb3822014-10-07 16:43:25 -0700465void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
466 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800467 this->cleanupShaders(shaderIDs);
joshualitt47bb3822014-10-07 16:43:25 -0700468}
469void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
470 for (int i = 0; i < shaderIDs.count(); ++i) {
Brian Salomon802cb312018-06-08 18:05:20 -0400471 GL_CALL(DeleteShader(shaderIDs[i]));
joshualitt47bb3822014-10-07 16:43:25 -0700472 }
473}
474
475GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800476 return new GrGLProgram(fGpu,
egdaniel7ea439b2015-12-03 09:20:44 -0800477 fUniformHandles,
478 programID,
479 fUniformHandler.fUniforms,
egdaniel09aa1fc2016-04-20 07:09:46 -0700480 fUniformHandler.fSamplers,
egdaniel0eafe792015-11-20 14:01:22 -0800481 fVaryingHandler.fPathProcVaryingInfos,
Robert Phillips369e8b72017-08-01 16:13:04 -0400482 std::move(fGeometryProcessor),
483 std::move(fXferProcessor),
Brian Salomon4d3f5172018-06-07 14:42:52 -0400484 std::move(fFragmentProcessors),
Brian Salomon802cb312018-06-08 18:05:20 -0400485 fFragmentProcessorCnt,
486 std::move(fAttributes),
Brian Salomon92be2f72018-06-19 14:33:47 -0400487 fVertexAttributeCnt,
488 fInstanceAttributeCnt,
Brian Salomon802cb312018-06-08 18:05:20 -0400489 fVertexStride,
490 fInstanceStride);
joshualitt47bb3822014-10-07 16:43:25 -0700491}