blob: f6890fd84210499fc2feafb75d49af742fde2366 [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
joshualitt47bb3822014-10-07 16:43:25 -07008#include "GrGLProgramBuilder.h"
joshualitt8072caa2015-02-12 14:20:52 -08009
bsalomon6f7f2012015-03-16 14:00:52 -070010#include "GrAutoLocaleSetter.h"
Robert Phillips9bee2e52017-05-29 12:37:20 -040011#include "GrContext.h"
Robert Phillips6be756b2018-01-16 15:07:54 -050012#include "GrContextPriv.h"
joshualitt47bb3822014-10-07 16:43:25 -070013#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070014#include "GrGLProgramBuilder.h"
egdaniel5d8f69f2016-09-07 07:24:12 -070015#include "GrProgramDesc.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050016#include "GrShaderCaps.h"
bsalomon7f9b2e42016-01-12 13:29:26 -080017#include "GrSwizzle.h"
Hal Canary95e3c052017-01-11 12:44:43 -050018#include "SkAutoMalloc.h"
Derek Sollenberger488f0d62017-03-03 15:48:33 -050019#include "SkATrace.h"
joshualitt30ba4362014-08-21 20:18:45 -070020#include "SkTraceEvent.h"
joshualitte7afc2d2015-09-11 10:44:13 -070021#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070022#include "gl/GrGLProgram.h"
egdaniel574a4c12015-11-02 06:22:44 -080023#include "gl/builders/GrGLShaderStringBuilder.h"
egdaniel64c47282015-11-13 06:54:19 -080024#include "glsl/GrGLSLFragmentProcessor.h"
egdaniele659a582015-11-13 09:55:43 -080025#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070026#include "glsl/GrGLSLProgramDataManager.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080027#include "glsl/GrGLSLXferProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070028
joshualitt30ba4362014-08-21 20:18:45 -070029#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
30#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
31
Brian Salomonff168d92018-06-23 15:17:27 -040032GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPrimitiveProcessor& primProc,
33 const GrPipeline& pipeline,
Ethan Nicholas38657112017-02-09 17:01:22 -050034 GrProgramDesc* desc,
egdaniel0e1853c2016-03-17 11:35:45 -070035 GrGLGpu* gpu) {
Brian Salomon7eae3e02018-08-07 14:02:38 +000036 SkASSERT(!pipeline.isBad());
Robert Phillipsa91e0b72017-05-01 13:12:20 -040037
Derek Sollenberger488f0d62017-03-03 15:48:33 -050038 ATRACE_ANDROID_FRAMEWORK("Shader Compile");
bsalomon3318ee72015-03-16 11:56:29 -070039 GrAutoLocaleSetter als("C");
40
joshualitt47bb3822014-10-07 16:43:25 -070041 // create a builder. This will be handed off to effects so they can use it to add
42 // uniforms, varyings, textures, etc
egdaniel0e1853c2016-03-17 11:35:45 -070043 GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);
joshualitt47bb3822014-10-07 16:43:25 -070044
Robert Phillips0c4b7b12018-03-06 08:20:37 -050045 auto persistentCache = gpu->getContext()->contextPriv().getPersistentCache();
46 if (persistentCache && gpu->glCaps().programBinarySupport()) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040047 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
Robert Phillips0c4b7b12018-03-06 08:20:37 -050048 builder.fCached = persistentCache->load(*key);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040049 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
50 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
51 // to skip the SkSL->GLSL step on a cache hit.
52 }
Ethan Nicholas2983f402017-05-08 09:36:08 -040053 if (!builder.emitAndInstallProcs()) {
halcanary96fcdcc2015-08-27 07:41:13 -070054 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070055 }
egdanielc1e71012016-01-20 07:53:51 -080056 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070057}
58
joshualitt47bb3822014-10-07 16:43:25 -070059/////////////////////////////////////////////////////////////////////////////
60
egdaniel0e1853c2016-03-17 11:35:45 -070061GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
62 const GrPipeline& pipeline,
63 const GrPrimitiveProcessor& primProc,
Ethan Nicholas38657112017-02-09 17:01:22 -050064 GrProgramDesc* desc)
Brian Salomonff168d92018-06-23 15:17:27 -040065 : INHERITED(primProc, pipeline, desc)
Brian Salomon802cb312018-06-08 18:05:20 -040066 , fGpu(gpu)
67 , fVaryingHandler(this)
68 , fUniformHandler(this)
Brian Salomon92be2f72018-06-19 14:33:47 -040069 , fVertexAttributeCnt(0)
70 , fInstanceAttributeCnt(0)
Brian Salomon802cb312018-06-08 18:05:20 -040071 , fVertexStride(0)
72 , fInstanceStride(0) {}
joshualitt30ba4362014-08-21 20:18:45 -070073
egdanielfa896322016-01-13 12:19:30 -080074const GrCaps* GrGLProgramBuilder::caps() const {
75 return fGpu->caps();
76}
77
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040078bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
79 int length,
egdaniel574a4c12015-11-02 06:22:44 -080080 GrGLuint programId,
81 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050082 SkTDArray<GrGLuint>* shaderIds,
83 const SkSL::Program::Settings& settings,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040084 const SkSL::Program::Inputs& inputs) {
egdaniel574a4c12015-11-02 06:22:44 -080085 GrGLGpu* gpu = this->gpu();
86 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
87 programId,
88 type,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040089 glsl,
90 length,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050091 gpu->stats(),
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040092 settings);
egdaniel574a4c12015-11-02 06:22:44 -080093 if (!shaderId) {
94 return false;
95 }
96
97 *shaderIds->append() = shaderId;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040098 if (inputs.fFlipY) {
Ethan Nicholas38657112017-02-09 17:01:22 -050099 GrProgramDesc* d = this->desc();
Robert Phillips7f861922018-01-30 13:13:42 +0000100 d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
101 this->pipeline().proxy()->origin()));
Ethan Nicholas38657112017-02-09 17:01:22 -0500102 d->finalize();
103 }
egdaniel574a4c12015-11-02 06:22:44 -0800104
105 return true;
106}
107
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400108bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
109 GrGLuint programId,
110 GrGLenum type,
111 SkTDArray<GrGLuint>* shaderIds,
112 const SkSL::Program::Settings& settings,
113 SkSL::Program::Inputs* outInputs) {
114 SkSL::String glsl;
115 std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(gpu()->glContext(), type,
116 shader.fCompilerStrings.begin(),
117 shader.fCompilerStringLengths.begin(),
118 shader.fCompilerStrings.count(),
119 settings,
120 &glsl);
121 *outInputs = program->fInputs;
122 return this->compileAndAttachShaders(glsl.c_str(),
123 glsl.size(),
124 programId,
125 type,
126 shaderIds,
127 settings,
128 *outInputs);
129}
130
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400131void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
132 const GrPrimitiveProcessor& primProc,
133 bool bindAttribLocations) {
134 fVertexAttributeCnt = primProc.numVertexAttributes();
135 fInstanceAttributeCnt = primProc.numInstanceAttributes();
136 fAttributes.reset(
137 new GrGLProgram::Attribute[fVertexAttributeCnt + fInstanceAttributeCnt]);
138 auto addAttr = [&](int i, const auto& a, size_t* stride) {
139 fAttributes[i].fType = a.type();
140 fAttributes[i].fOffset = *stride;
141 *stride += a.sizeAlign4();
142 fAttributes[i].fLocation = i;
143 if (bindAttribLocations) {
144 GL_CALL(BindAttribLocation(programID, i, a.name()));
145 }
146 };
147 fVertexStride = 0;
148 int i = 0;
149 for (; i < fVertexAttributeCnt; i++) {
150 addAttr(i, primProc.vertexAttribute(i), &fVertexStride);
151 SkASSERT(fAttributes[i].fOffset == primProc.debugOnly_vertexAttributeOffset(i));
152 }
153 SkASSERT(fVertexStride == primProc.debugOnly_vertexStride());
154 fInstanceStride = 0;
155 for (int j = 0; j < fInstanceAttributeCnt; j++, ++i) {
156 addAttr(i, primProc.instanceAttribute(j), &fInstanceStride);
157 SkASSERT(fAttributes[i].fOffset == primProc.debugOnly_instanceAttributeOffset(j));
158 }
159 SkASSERT(fInstanceStride == primProc.debugOnly_instanceStride());
160}
161
Ethan Nicholascd700e92018-08-24 16:43:57 -0400162void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
163 if (inputs.fRTWidth) {
164 this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
165 }
166 if (inputs.fRTHeight) {
167 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
168 }
169}
170
joshualitt47bb3822014-10-07 16:43:25 -0700171GrGLProgram* GrGLProgramBuilder::finalize() {
Brian Osman39c08ac2017-07-26 09:36:09 -0400172 TRACE_EVENT0("skia", TRACE_FUNC);
Ryan Macnak38a10ad2017-07-10 10:36:34 -0700173
joshualitt47bb3822014-10-07 16:43:25 -0700174 // verify we can get a program id
175 GrGLuint programID;
176 GL_CALL_RET(programID, CreateProgram());
177 if (0 == programID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700178 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700179 }
180
Ethan Nicholas06d55fb2017-11-08 09:48:50 -0500181 if (this->gpu()->glCaps().programBinarySupport() &&
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500182 this->gpu()->getContext()->contextPriv().getPersistentCache()) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400183 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
184 }
185
egdaniel9f1d4152016-02-10 09:50:38 -0800186 this->finalizeShaders();
187
joshualitt47bb3822014-10-07 16:43:25 -0700188 // compile shaders and bind attributes / uniforms
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400189 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500190 SkSL::Program::Settings settings;
191 settings.fCaps = this->gpu()->glCaps().shaderCaps();
Robert Phillips2890fbf2017-07-26 15:48:41 -0400192 settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
Brian Osman8a83ca42018-02-12 14:32:17 -0500193 settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
Brian Salomondc092132018-04-04 10:14:16 -0400194 settings.fFragColorIsInOut = this->fragColorIsInOut();
195
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500196 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700197 SkTDArray<GrGLuint> shadersToDelete;
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400198 bool cached = fGpu->glCaps().programBinarySupport() && nullptr != fCached.get();
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400199 if (cached) {
Ethan Nicholas907204f2017-11-14 14:35:57 -0500200 this->bindProgramResourceLocations(programID);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400201 // cache hit, just hand the binary to GL
202 const uint8_t* bytes = fCached->bytes();
203 size_t offset = 0;
204 memcpy(&inputs, bytes + offset, sizeof(inputs));
205 offset += sizeof(inputs);
206 int binaryFormat;
207 memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
208 offset += sizeof(binaryFormat);
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400209 GrGLClearErr(this->gpu()->glInterface());
210 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
211 ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
212 fCached->size() - offset));
213 if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400214 cached = this->checkLinkStatus(programID);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400215 if (cached) {
Ethan Nicholascd700e92018-08-24 16:43:57 -0400216 this->addInputVars(inputs);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400217 this->computeCountsAndStrides(programID, primProc, false);
218 }
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400219 } else {
220 cached = false;
221 }
222 }
223 if (!cached) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400224 // cache miss, compile shaders
225 if (fFS.fForceHighPrecision) {
226 settings.fForceHighPrecision = true;
egdaniel8dcdedc2015-11-11 06:27:20 -0800227 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400228 SkSL::String glsl;
229 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
230 GR_GL_FRAGMENT_SHADER,
231 fFS.fCompilerStrings.begin(),
232 fFS.fCompilerStringLengths.begin(),
233 fFS.fCompilerStrings.count(),
234 settings,
235 &glsl);
Brian Salomon7c934722018-06-01 14:42:53 -0400236 if (!fs) {
237 this->cleanupProgram(programID, shadersToDelete);
238 return nullptr;
239 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400240 inputs = fs->fInputs;
Ethan Nicholascd700e92018-08-24 16:43:57 -0400241 this->addInputVars(inputs);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400242 if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
243 GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
244 inputs)) {
245 this->cleanupProgram(programID, shadersToDelete);
246 return nullptr;
247 }
248
249 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
250 GR_GL_VERTEX_SHADER,
251 fVS.fCompilerStrings.begin(),
252 fVS.fCompilerStringLengths.begin(),
253 fVS.fCompilerStrings.count(),
254 settings,
255 &glsl);
Brian Salomon7c934722018-06-01 14:42:53 -0400256 if (!vs || !this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
257 GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
258 inputs)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400259 this->cleanupProgram(programID, shadersToDelete);
260 return nullptr;
261 }
262
263 // NVPR actually requires a vertex shader to compile
264 bool useNvpr = primProc.isPathRendering();
265 if (!useNvpr) {
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400266 this->computeCountsAndStrides(programID, primProc, true);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400267 }
268
269 if (primProc.willUseGeoShader()) {
270 std::unique_ptr<SkSL::Program> gs;
271 gs = GrSkSLtoGLSL(gpu()->glContext(),
272 GR_GL_GEOMETRY_SHADER,
273 fGS.fCompilerStrings.begin(),
274 fGS.fCompilerStringLengths.begin(),
275 fGS.fCompilerStrings.count(),
276 settings,
277 &glsl);
Brian Salomon7c934722018-06-01 14:42:53 -0400278 if (!gs || !this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
279 GR_GL_GEOMETRY_SHADER, &shadersToDelete,
280 settings, inputs)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400281 this->cleanupProgram(programID, shadersToDelete);
282 return nullptr;
283 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400284 }
285 this->bindProgramResourceLocations(programID);
286
287 GL_CALL(LinkProgram(programID));
joshualitt47bb3822014-10-07 16:43:25 -0700288 }
joshualitt30ba4362014-08-21 20:18:45 -0700289 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700290 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
joshualitt30ba4362014-08-21 20:18:45 -0700291#ifdef SK_DEBUG
292 checkLinked = true;
293#endif
294 if (checkLinked) {
Brian Salomone334c592017-05-15 11:00:58 -0400295 if (!this->checkLinkStatus(programID)) {
296 SkDebugf("VS:\n");
297 GrGLPrintShader(fGpu->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(),
298 fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(),
299 settings);
300 if (primProc.willUseGeoShader()) {
301 SkDebugf("\nGS:\n");
302 GrGLPrintShader(fGpu->glContext(), GR_GL_GEOMETRY_SHADER,
303 fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(),
304 fGS.fCompilerStrings.count(), settings);
305 }
306 SkDebugf("\nFS:\n");
307 GrGLPrintShader(fGpu->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(),
308 fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(),
309 settings);
Brian Salomone334c592017-05-15 11:00:58 -0400310 return nullptr;
311 }
joshualittfe1233c2014-10-07 12:16:35 -0700312 }
kkinnunen7aedda52015-06-29 23:01:28 -0700313 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700314
joshualitt47bb3822014-10-07 16:43:25 -0700315 this->cleanupShaders(shadersToDelete);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500316 if (!cached && this->gpu()->getContext()->contextPriv().getPersistentCache() &&
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400317 fGpu->glCaps().programBinarySupport()) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400318 GrGLsizei length = 0;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400319 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
Ethan Nicholas12b69ee2017-11-20 12:12:44 -0500320 if (length > 0) {
321 // store shader in cache
322 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
323 GrGLenum binaryFormat;
Mike Klein1d746202018-01-25 17:32:51 -0500324 std::unique_ptr<char[]> binary(new char[length]);
Ethan Nicholas12b69ee2017-11-20 12:12:44 -0500325 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
326 size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
Mike Klein1d746202018-01-25 17:32:51 -0500327 std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
Ethan Nicholas12b69ee2017-11-20 12:12:44 -0500328 size_t offset = 0;
329 memcpy(data.get() + offset, &inputs, sizeof(inputs));
330 offset += sizeof(inputs);
331 memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
332 offset += sizeof(binaryFormat);
333 memcpy(data.get() + offset, binary.get(), length);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500334 this->gpu()->getContext()->contextPriv().getPersistentCache()->store(
335 *key, *SkData::MakeWithoutCopy(data.get(), dataLength));
Ethan Nicholas12b69ee2017-11-20 12:12:44 -0500336 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400337 }
joshualitt47bb3822014-10-07 16:43:25 -0700338 return this->createProgram(programID);
339}
340
kkinnunen7aedda52015-06-29 23:01:28 -0700341void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800342 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700343
egdaniel8dcdedc2015-11-11 06:27:20 -0800344 const GrGLCaps& caps = this->gpu()->glCaps();
345 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
346 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800347 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800348 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500349 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800350 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800351 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800352 }
joshualittd8dd47b2015-09-11 11:45:01 -0700353
354 // handle NVPR separable varyings
355 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
356 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
357 return;
358 }
egdaniel0eafe792015-11-20 14:01:22 -0800359 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700360 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800361 GL_CALL(BindFragmentInputLocation(programID, i,
362 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
363 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700364 }
joshualitt47bb3822014-10-07 16:43:25 -0700365}
366
367bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
368 GrGLint linked = GR_GL_INIT_ZERO;
369 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
370 if (!linked) {
Brian Salomone334c592017-05-15 11:00:58 -0400371 SkDebugf("Program linking failed.\n");
joshualitt47bb3822014-10-07 16:43:25 -0700372 GrGLint infoLen = GR_GL_INIT_ZERO;
373 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
374 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
375 if (infoLen > 0) {
376 // retrieve length even though we don't need it to workaround
377 // bug in chrome cmd buffer param validation.
378 GrGLsizei length = GR_GL_INIT_ZERO;
379 GL_CALL(GetProgramInfoLog(programID,
380 infoLen+1,
381 &length,
382 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800383 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700384 }
joshualitt47bb3822014-10-07 16:43:25 -0700385 GL_CALL(DeleteProgram(programID));
386 programID = 0;
387 }
388 return SkToBool(linked);
389}
390
kkinnunen7aedda52015-06-29 23:01:28 -0700391void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800392 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700393
394 // handle NVPR separable varyings
395 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800396 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700397 return;
398 }
egdaniel0eafe792015-11-20 14:01:22 -0800399 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700400 for (int i = 0; i < count; ++i) {
401 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800402 GL_CALL_RET(location, GetProgramResourceLocation(
403 programID,
404 GR_GL_FRAGMENT_INPUT,
405 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
406 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700407 }
joshualitt30ba4362014-08-21 20:18:45 -0700408}
409
joshualitt47bb3822014-10-07 16:43:25 -0700410void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
411 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800412 this->cleanupShaders(shaderIDs);
joshualitt47bb3822014-10-07 16:43:25 -0700413}
414void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
415 for (int i = 0; i < shaderIDs.count(); ++i) {
Brian Salomon802cb312018-06-08 18:05:20 -0400416 GL_CALL(DeleteShader(shaderIDs[i]));
joshualitt47bb3822014-10-07 16:43:25 -0700417 }
418}
419
420GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800421 return new GrGLProgram(fGpu,
egdaniel7ea439b2015-12-03 09:20:44 -0800422 fUniformHandles,
423 programID,
424 fUniformHandler.fUniforms,
egdaniel09aa1fc2016-04-20 07:09:46 -0700425 fUniformHandler.fSamplers,
egdaniel0eafe792015-11-20 14:01:22 -0800426 fVaryingHandler.fPathProcVaryingInfos,
Robert Phillips369e8b72017-08-01 16:13:04 -0400427 std::move(fGeometryProcessor),
428 std::move(fXferProcessor),
Brian Salomon4d3f5172018-06-07 14:42:52 -0400429 std::move(fFragmentProcessors),
Brian Salomon802cb312018-06-08 18:05:20 -0400430 fFragmentProcessorCnt,
431 std::move(fAttributes),
Brian Salomon92be2f72018-06-19 14:33:47 -0400432 fVertexAttributeCnt,
433 fInstanceAttributeCnt,
Brian Salomon802cb312018-06-08 18:05:20 -0400434 fVertexStride,
435 fInstanceStride);
joshualitt47bb3822014-10-07 16:43:25 -0700436}