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