Make all GrFragmentProcessors GL independent.
[platform/upstream/libSkiaSharp.git] / src / gpu / gl / builders / GrGLProgramBuilder.cpp
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 "GrGLProgramBuilder.h"
9
10 #include "GrAutoLocaleSetter.h"
11 #include "GrCoordTransform.h"
12 #include "GrGLProgramBuilder.h"
13 #include "GrTexture.h"
14 #include "SkRTConf.h"
15 #include "SkTraceEvent.h"
16 #include "gl/GrGLGeometryProcessor.h"
17 #include "gl/GrGLGpu.h"
18 #include "gl/GrGLProgram.h"
19 #include "gl/GrGLSLPrettyPrint.h"
20 #include "gl/GrGLXferProcessor.h"
21 #include "gl/builders/GrGLShaderStringBuilder.h"
22 #include "glsl/GrGLSLCaps.h"
23 #include "glsl/GrGLSLFragmentProcessor.h"
24 #include "glsl/GrGLSLProgramDataManager.h"
25 #include "glsl/GrGLSLTextureSampler.h"
26
27 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
28 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
29
30 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
31     GrAutoLocaleSetter als("C");
32
33     // create a builder.  This will be handed off to effects so they can use it to add
34     // uniforms, varyings, textures, etc
35     SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args));
36
37     GrGLProgramBuilder* pb = builder.get();
38
39     // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
40     // seed correctly here
41     GrGLSLExpr4 inputColor;
42     GrGLSLExpr4 inputCoverage;
43
44     if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) {
45         return nullptr;
46     }
47
48     return pb->finalize();
49 }
50
51 /////////////////////////////////////////////////////////////////////////////
52
53 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
54     : INHERITED(args)
55     , fGeometryProcessor(nullptr)
56     , fXferProcessor(nullptr)
57     , fGpu(gpu)
58     , fUniforms(kVarsPerBlock)
59     , fSamplerUniforms(4)
60     , fSeparableVaryingInfos(kVarsPerBlock) {
61 }
62
63 void GrGLProgramBuilder::addVarying(const char* name,
64                                     GrGLSLVarying* varying,
65                                     GrSLPrecision precision) {
66     SkASSERT(varying);
67     if (varying->vsVarying()) {
68         fVS.addVarying(name, precision, varying);
69     }
70     if (this->primitiveProcessor().willUseGeoShader()) {
71         fGS.addVarying(name, precision, varying);
72     }
73     if (varying->fsVarying()) {
74         fFS.addVarying(varying, precision);
75     }
76 }
77
78 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input,
79                                                  const char* output) {
80     GrSLType type = GrVertexAttribTypeToSLType(input->fType);
81     GrGLSLVertToFrag v(type);
82     this->addVarying(input->fName, &v);
83     fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
84     fFS.codeAppendf("%s = %s;", output, v.fsIn());
85 }
86
87 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVarying(
88                                                                         const char* name,
89                                                                         GrGLSLVertToFrag* v,
90                                                                         GrSLPrecision fsPrecision) {
91     // This call is not used for non-NVPR backends.
92     SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() &&
93              fArgs.fPrimitiveProcessor->isPathRendering() &&
94              !fArgs.fPrimitiveProcessor->willUseGeoShader() &&
95              fArgs.fPrimitiveProcessor->numAttribs() == 0);
96     this->addVarying(name, v, fsPrecision);
97     SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
98     varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back();
99     varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
100     return SeparableVaryingHandle(varyingInfo.fLocation);
101 }
102
103 GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformArray(
104                                                                 uint32_t visibility,
105                                                                 GrSLType type,
106                                                                 GrSLPrecision precision,
107                                                                 const char* name,
108                                                                 bool mangleName,
109                                                                 int count,
110                                                                 const char** outName) {
111     SkASSERT(name && strlen(name));
112     SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
113     SkASSERT(0 == (~kVisibilityMask & visibility));
114     SkASSERT(0 != visibility);
115     SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type));
116
117     UniformInfo& uni = fUniforms.push_back();
118     uni.fVariable.setType(type);
119     uni.fVariable.setTypeModifier(GrGLSLShaderVar::kUniform_TypeModifier);
120     // TODO this is a bit hacky, lets think of a better way.  Basically we need to be able to use
121     // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
122     // exactly what name it wants to use for the uniform view matrix.  If we prefix anythings, then
123     // the names will mismatch.  I think the correct solution is to have all GPs which need the
124     // uniform view matrix, they should upload the view matrix in their setData along with regular
125     // uniforms.
126     char prefix = 'u';
127     if ('u' == name[0]) {
128         prefix = '\0';
129     }
130     this->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
131     uni.fVariable.setArrayCount(count);
132     uni.fVisibility = visibility;
133     uni.fVariable.setPrecision(precision);
134
135     if (outName) {
136         *outName = uni.fVariable.c_str();
137     }
138     return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1);
139 }
140
141 void GrGLProgramBuilder::onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const {
142     for (int i = 0; i < fUniforms.count(); ++i) {
143         if (fUniforms[i].fVisibility & visibility) {
144             fUniforms[i].fVariable.appendDecl(this->glslCaps(), out);
145             out->append(";\n");
146         }
147     }
148 }
149
150 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const {
151     return this->fGpu->ctxInfo().caps()->glslCaps();
152 }
153
154 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
155     // First we loop over all of the installed processors and collect coord transforms.  These will
156     // be sent to the GrGLPrimitiveProcessor in its emitCode function
157     const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
158     int totalTextures = primProc.numTextures();
159     const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits();
160
161     for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
162         const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
163
164         if (!primProc.hasTransformedLocalCoords()) {
165             SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
166             processor.gatherCoordTransforms(&procCoords);
167         }
168
169         totalTextures += processor.numTextures();
170         if (totalTextures >= maxTextureUnits) {
171             GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n");
172             return false;
173         }
174     }
175
176     this->emitAndInstallProc(primProc, inputColor, inputCoverage);
177
178     fFragmentProcessors.reset(new GrGLInstalledFragProcs);
179     int numProcs = this->pipeline().numFragmentProcessors();
180     this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor);
181     this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs,
182                                   inputCoverage);
183     this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
184     return true;
185 }
186
187 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
188                                                  int numProcs,
189                                                  GrGLSLExpr4* inOut) {
190     for (int i = procOffset; i < numProcs; ++i) {
191         GrGLSLExpr4 output;
192         const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
193         this->emitAndInstallProc(fp, i, *inOut, &output);
194         *inOut = output;
195     }
196 }
197
198 void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
199     // create var to hold stage result.  If we already have a valid output name, just use that
200     // otherwise create a new mangled one.  This name is only valid if we are reordering stages
201     // and have to tell stage exactly where to put its output.
202     SkString outName;
203     if (output->isValid()) {
204         outName = output->c_str();
205     } else {
206         this->nameVariable(&outName, '\0', baseName);
207     }
208     fFS.codeAppendf("vec4 %s;", outName.c_str());
209     *output = outName;
210 }
211
212 // TODO Processors cannot output zeros because an empty string is all 1s
213 // the fix is to allow effects to take the GrGLSLExpr4 directly
214 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
215                                             int index,
216                                             const GrGLSLExpr4& input,
217                                             GrGLSLExpr4* output) {
218     // Program builders have a bit of state we need to clear with each effect
219     AutoStageAdvance adv(this);
220     this->nameExpression(output, "output");
221
222     // Enclose custom code in a block to avoid namespace conflicts
223     SkString openBrace;
224     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
225     fFS.codeAppend(openBrace.c_str());
226
227     this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str());
228
229     fFS.codeAppend("}");
230 }
231
232 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
233                                             GrGLSLExpr4* outputColor,
234                                             GrGLSLExpr4* outputCoverage) {
235     // Program builders have a bit of state we need to clear with each effect
236     AutoStageAdvance adv(this);
237     this->nameExpression(outputColor, "outputColor");
238     this->nameExpression(outputCoverage, "outputCoverage");
239
240     // Enclose custom code in a block to avoid namespace conflicts
241     SkString openBrace;
242     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
243     fFS.codeAppend(openBrace.c_str());
244     fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
245
246     this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
247
248     fFS.codeAppend("}");
249 }
250
251 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
252                                             int index,
253                                             const char* outColor,
254                                             const char* inColor) {
255     GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc;
256
257     ifp->fGLProc.reset(fp.createGLInstance());
258
259     SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures());
260     this->emitSamplers(fp, &samplers, ifp);
261
262     GrGLSLFragmentProcessor::EmitArgs args(this,
263                                            fp,
264                                            outColor,
265                                            inColor,
266                                            fOutCoords[index],
267                                            samplers);
268     ifp->fGLProc->emitCode(args);
269
270     // We have to check that effects and the code they emit are consistent, ie if an effect
271     // asks for dst color, then the emit code needs to follow suit
272     verify(fp);
273     fFragmentProcessors->fProcs.push_back(ifp);
274 }
275
276 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
277                                             const char* outColor,
278                                             const char* outCoverage) {
279     SkASSERT(!fGeometryProcessor);
280     fGeometryProcessor = new GrGLInstalledGeoProc;
281
282     fGeometryProcessor->fGLProc.reset(gp.createGLInstance(*fGpu->glCaps().glslCaps()));
283
284     SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures());
285     this->emitSamplers(gp, &samplers, fGeometryProcessor);
286
287     GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, samplers,
288                                          fCoordTransforms, &fOutCoords);
289     fGeometryProcessor->fGLProc->emitCode(args);
290
291     // We have to check that effects and the code they emit are consistent, ie if an effect
292     // asks for dst color, then the emit code needs to follow suit
293     verify(gp);
294 }
295
296 void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
297                                                 const GrGLSLExpr4& colorIn,
298                                                 const GrGLSLExpr4& coverageIn) {
299     // Program builders have a bit of state we need to clear with each effect
300     AutoStageAdvance adv(this);
301
302     SkASSERT(!fXferProcessor);
303     fXferProcessor = new GrGLInstalledXferProc;
304
305     fXferProcessor->fGLProc.reset(xp.createGLInstance());
306
307     // Enable dual source secondary output if we have one
308     if (xp.hasSecondaryOutput()) {
309         fFS.enableSecondaryOutput();
310     }
311
312     if (this->glslCaps()->mustDeclareFragmentShaderOutput()) {
313         fFS.enableCustomOutput();
314     }
315
316     SkString openBrace;
317     openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
318     fFS.codeAppend(openBrace.c_str());
319
320     SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures());
321     this->emitSamplers(xp, &samplers, fXferProcessor);
322
323     GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
324                                      fFS.getPrimaryColorOutputName(),
325                                      fFS.getSecondaryColorOutputName(), samplers);
326     fXferProcessor->fGLProc->emitCode(args);
327
328     // We have to check that effects and the code they emit are consistent, ie if an effect
329     // asks for dst color, then the emit code needs to follow suit
330     verify(xp);
331     fFS.codeAppend("}");
332 }
333
334 void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
335     SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
336 }
337
338 void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
339     SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
340 }
341
342 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
343     SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
344 }
345
346 template <class Proc>
347 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
348                                       GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
349                                       GrGLInstalledProc<Proc>* ip) {
350     SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();)
351     int numTextures = processor.numTextures();
352     UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
353     SkString name;
354     for (int t = 0; t < numTextures; ++t) {
355         name.printf("Sampler%d", t);
356         localSamplerUniforms[t] = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
357                                                    kSampler2D_GrSLType, kDefault_GrSLPrecision,
358                                                    name.c_str());
359         SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler,
360                                (localSamplerUniforms[t], processor.textureAccess(t)));
361     }
362 }
363
364 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
365                                                  GrGLuint programId,
366                                                  GrGLenum type,
367                                                  SkTDArray<GrGLuint>* shaderIds) {
368     GrGLGpu* gpu = this->gpu();
369     GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
370                                                    programId,
371                                                    type,
372                                                    shader.fCompilerStrings.begin(),
373                                                    shader.fCompilerStringLengths.begin(),
374                                                    shader.fCompilerStrings.count(),
375                                                    gpu->stats());
376
377     if (!shaderId) {
378         return false;
379     }
380
381     *shaderIds->append() = shaderId;
382
383     return true;
384 }
385
386 GrGLProgram* GrGLProgramBuilder::finalize() {
387     // verify we can get a program id
388     GrGLuint programID;
389     GL_CALL_RET(programID, CreateProgram());
390     if (0 == programID) {
391         return nullptr;
392     }
393
394     // compile shaders and bind attributes / uniforms
395     SkTDArray<GrGLuint> shadersToDelete;
396     fVS.finalize(kVertex_Visibility);
397     if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) {
398         this->cleanupProgram(programID, shadersToDelete);
399         return nullptr;
400     }
401
402     // NVPR actually requires a vertex shader to compile
403     bool useNvpr = primitiveProcessor().isPathRendering();
404     if (!useNvpr) {
405         const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
406
407         int vaCount = primProc.numAttribs();
408         for (int i = 0; i < vaCount; i++) {
409             GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
410         }
411     }
412
413     fFS.finalize(kFragment_Visibility);
414     if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) {
415         this->cleanupProgram(programID, shadersToDelete);
416         return nullptr;
417     }
418
419     this->bindProgramResourceLocations(programID);
420
421     GL_CALL(LinkProgram(programID));
422
423     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
424     bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
425 #ifdef SK_DEBUG
426     checkLinked = true;
427 #endif
428     if (checkLinked) {
429         checkLinkStatus(programID);
430     }
431     this->resolveProgramResourceLocations(programID);
432
433     this->cleanupShaders(shadersToDelete);
434
435     return this->createProgram(programID);
436 }
437
438 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
439     if (fGpu->glCaps().bindUniformLocationSupport()) {
440         int count = fUniforms.count();
441         for (int i = 0; i < count; ++i) {
442             GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
443             fUniforms[i].fLocation = i;
444         }
445     }
446
447     const GrGLCaps& caps = this->gpu()->glCaps();
448     if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
449         GL_CALL(BindFragDataLocation(programID, 0,
450                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
451     }
452     if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
453         GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
454                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
455     }
456
457     // handle NVPR separable varyings
458     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
459         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
460         return;
461     }
462     int count = fSeparableVaryingInfos.count();
463     for (int i = 0; i < count; ++i) {
464         GL_CALL(BindFragmentInputLocation(programID,
465                                           i,
466                                           fSeparableVaryingInfos[i].fVariable.c_str()));
467         fSeparableVaryingInfos[i].fLocation = i;
468     }
469 }
470
471 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
472     GrGLint linked = GR_GL_INIT_ZERO;
473     GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
474     if (!linked) {
475         GrGLint infoLen = GR_GL_INIT_ZERO;
476         GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
477         SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
478         if (infoLen > 0) {
479             // retrieve length even though we don't need it to workaround
480             // bug in chrome cmd buffer param validation.
481             GrGLsizei length = GR_GL_INIT_ZERO;
482             GL_CALL(GetProgramInfoLog(programID,
483                                       infoLen+1,
484                                       &length,
485                                       (char*)log.get()));
486             SkDebugf("%s", (char*)log.get());
487         }
488         SkDEBUGFAIL("Error linking program");
489         GL_CALL(DeleteProgram(programID));
490         programID = 0;
491     }
492     return SkToBool(linked);
493 }
494
495 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
496     if (!fGpu->glCaps().bindUniformLocationSupport()) {
497         int count = fUniforms.count();
498         for (int i = 0; i < count; ++i) {
499             GrGLint location;
500             GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
501             fUniforms[i].fLocation = location;
502         }
503     }
504
505     // handle NVPR separable varyings
506     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
507         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
508         return;
509     }
510     int count = fSeparableVaryingInfos.count();
511     for (int i = 0; i < count; ++i) {
512         GrGLint location;
513         GL_CALL_RET(location,
514                     GetProgramResourceLocation(programID,
515                                                GR_GL_FRAGMENT_INPUT,
516                                                fSeparableVaryingInfos[i].fVariable.c_str()));
517         fSeparableVaryingInfos[i].fLocation = location;
518     }
519 }
520
521 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
522     GL_CALL(DeleteProgram(programID));
523     cleanupShaders(shaderIDs);
524 }
525 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
526     for (int i = 0; i < shaderIDs.count(); ++i) {
527       GL_CALL(DeleteShader(shaderIDs[i]));
528     }
529 }
530
531 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
532     return new GrGLProgram(fGpu, this->desc(), fUniformHandles, programID, fUniforms,
533                            fSeparableVaryingInfos,
534                            fGeometryProcessor, fXferProcessor, fFragmentProcessors.get(),
535                            &fSamplerUniforms);
536 }
537
538 ///////////////////////////////////////////////////////////////////////////////////////////////////
539
540 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
541     int numProcs = fProcs.count();
542     for (int i = 0; i < numProcs; ++i) {
543         delete fProcs[i];
544     }
545 }