18dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel/*
28dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * Copyright 2015 Google Inc.
38dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel *
48dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * Use of this source code is governed by a BSD-style license that can be
58dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * found in the LICENSE file.
68dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel */
78dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
88dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel#include "glsl/GrGLSLProgramBuilder.h"
98dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
1094efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrCaps.h"
11fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "GrPipeline.h"
1294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrShaderCaps.h"
13739c5bf111baf977fe418a24fa00ce260989ee9aBrian Salomon#include "GrTexturePriv.h"
14fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLFragmentProcessor.h"
15fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLGeometryProcessor.h"
169f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel#include "glsl/GrGLSLVarying.h"
17fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLXferProcessor.h"
18fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
198dcdedc4a087ea46ce1e2458d335d60918e56310egdanielconst int GrGLSLProgramBuilder::kVarsPerBlock = 8;
208dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
210e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielGrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
220e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                           const GrPrimitiveProcessor& primProc,
233865711259e25a90a1d72480f848863ada202067Ethan Nicholas                                           GrProgramDesc* desc)
248dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    : fVS(this)
258dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    , fGS(this)
2628f45b949acc746849100fbe112ee5280f0594c9cdalton    , fFS(this)
278dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    , fStageIndex(-1)
280e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    , fPipeline(pipeline)
290e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    , fPrimProc(primProc)
300e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    , fDesc(desc)
31fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    , fGeometryProcessor(nullptr)
329c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    , fXferProcessor(nullptr)
339c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    , fNumVertexSamplers(0)
349c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    , fNumGeometrySamplers(0)
35f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    , fNumFragmentSamplers(0)
36f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    , fNumVertexImageStorages(0)
37f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    , fNumGeometryImageStorages(0)
38f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    , fNumFragmentImageStorages(0) {
399c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton}
409c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton
419c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdaltonvoid GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
429c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton                                      uint32_t featureBit,
439c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton                                      const char* extensionName) {
449c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    if (shaders & kVertex_GrShaderFlag) {
459c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        fVS.addFeature(featureBit, extensionName);
469c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
479c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    if (shaders & kGeometry_GrShaderFlag) {
48276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        SkASSERT(this->primitiveProcessor().willUseGeoShader());
499c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        fGS.addFeature(featureBit, extensionName);
509c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
519c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    if (shaders & kFragment_GrShaderFlag) {
529c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        fFS.addFeature(featureBit, extensionName);
539c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
54fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
55fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
56fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielbool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
579c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton                                               GrGLSLExpr4* inputCoverage) {
58fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // First we loop over all of the installed processors and collect coord transforms.  These will
59fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
60fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
61fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
62fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
63fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
64a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    this->emitAndInstallFragProcs(inputColor, inputCoverage);
6542c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon    this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
6642c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon    this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
679c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton
68f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    return this->checkSamplerCounts() && this->checkImageStorageCounts();
69fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
70fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
71fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
72fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  GrGLSLExpr4* outputColor,
73fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  GrGLSLExpr4* outputCoverage) {
74fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Program builders have a bit of state we need to clear with each effect
75fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    AutoStageAdvance adv(this);
76fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    this->nameExpression(outputColor, "outputColor");
77fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    this->nameExpression(outputCoverage, "outputCoverage");
78fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
799b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck    const char* distanceVectorName = nullptr;
809b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck    if (this->fPipeline.usesDistanceVectorField() && proc.implementsDistanceVector()) {
8105a4cf59591024d838b204bb0f6fac42598ead28robertphillips        // Each individual user (FP) of the distance vector must be able to handle having this
8205a4cf59591024d838b204bb0f6fac42598ead28robertphillips        // variable be undeclared. There is no single default value that will yield a reasonable
8305a4cf59591024d838b204bb0f6fac42598ead28robertphillips        // result for all users.
849b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck        distanceVectorName = fFS.distanceVectorName();
85ee92063f9e1a28e301fe6cdc804dca0ccc837f67dvonbeck        fFS.codeAppend( "// Normalized vector to the closest geometric edge (in device space)\n");
8684bca78ab462314ec48614ff50315f28d5467149dvonbeck        fFS.codeAppend( "// Distance to the edge encoded in the z-component\n");
876c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth        fFS.codeAppendf("vec4 %s;", distanceVectorName);
889b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck    }
899b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck
90936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
91936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    GrShaderFlags rtAdjustVisibility = kVertex_GrShaderFlag;
92936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    if (proc.willUseGeoShader()) {
93936f81b95882be2e171a623b3116cc2ff408c813csmartdalton        rtAdjustVisibility |= kGeometry_GrShaderFlag;
94936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    }
95936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
96936f81b95882be2e171a623b3116cc2ff408c813csmartdalton                                                                          kVec4f_GrSLType,
97936f81b95882be2e171a623b3116cc2ff408c813csmartdalton                                                                          kHigh_GrSLPrecision,
98936f81b95882be2e171a623b3116cc2ff408c813csmartdalton                                                                          "rtAdjustment");
99936f81b95882be2e171a623b3116cc2ff408c813csmartdalton    const char* rtAdjustName =
100936f81b95882be2e171a623b3116cc2ff408c813csmartdalton        this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
101936f81b95882be2e171a623b3116cc2ff408c813csmartdalton
102fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Enclose custom code in a block to avoid namespace conflicts
103fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkString openBrace;
104fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
105fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend(openBrace.c_str());
106fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
107fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
108fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkASSERT(!fGeometryProcessor);
10994efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    fGeometryProcessor = proc.createGLSLInstance(*this->shaderCaps());
110fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
111f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<4, SamplerHandle>      texSamplers(proc.numTextureSamplers());
112f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<2, SamplerHandle>      bufferSamplers(proc.numBuffers());
113f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages());
114f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    this->emitSamplersAndImageStorages(proc, &texSamplers, &bufferSamplers, &imageStorages);
115fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
116a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
117a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon                                                                       &fTransformedCoordVars);
118fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    GrGLSLGeometryProcessor::EmitArgs args(&fVS,
119276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton                                           proc.willUseGeoShader() ? &fGS : nullptr,
120fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           &fFS,
121fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           this->varyingHandler(),
122fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           this->uniformHandler(),
12394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon                                           this->shaderCaps(),
124fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           proc,
125fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           outputColor->c_str(),
126fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           outputCoverage->c_str(),
1279b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck                                           distanceVectorName,
128936f81b95882be2e171a623b3116cc2ff408c813csmartdalton                                           rtAdjustName,
12909aa1fce69b214714171db12c341aebd78dd29eaegdaniel                                           texSamplers.begin(),
13009aa1fce69b214714171db12c341aebd78dd29eaegdaniel                                           bufferSamplers.begin(),
131f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                           imageStorages.begin(),
132a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon                                           &transformHandler);
133fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fGeometryProcessor->emitCode(args);
134fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
135fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // We have to check that effects and the code they emit are consistent, ie if an effect
136fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // asks for dst color, then the emit code needs to follow suit
13787332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkDEBUGCODE(verify(proc);)
138fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
139fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend("}");
140fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
141fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
142a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomonvoid GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
143a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    int transformedCoordVarsIdx = 0;
144a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    GrGLSLExpr4** inOut = &color;
145a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
146a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        if (i == this->pipeline().numColorFragmentProcessors()) {
147a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon            inOut = &coverage;
148a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        }
149fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        GrGLSLExpr4 output;
150fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
151a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output);
152a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        GrFragmentProcessor::Iter iter(&fp);
153a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        while (const GrFragmentProcessor* fp = iter.next()) {
154a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon            transformedCoordVarsIdx += fp->numCoordTransforms();
155a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        }
156a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        **inOut = output;
157fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
158fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
159fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
160fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel// TODO Processors cannot output zeros because an empty string is all 1s
161fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel// the fix is to allow effects to take the GrGLSLExpr4 directly
162fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
163fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  int index,
164a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon                                                  int transformedCoordVarsIdx,
165fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  const GrGLSLExpr4& input,
166fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  GrGLSLExpr4* output) {
167fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Program builders have a bit of state we need to clear with each effect
168fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    AutoStageAdvance adv(this);
169fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    this->nameExpression(output, "output");
170fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
171fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Enclose custom code in a block to avoid namespace conflicts
172fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkString openBrace;
173fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
174fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend(openBrace.c_str());
175fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
176fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
177fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
1780bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon    SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers());
179b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers());
180f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages());
181b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    GrFragmentProcessor::Iter iter(&fp);
182b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    while (const GrFragmentProcessor* subFP = iter.next()) {
183f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &bufferSamplerArray,
184f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                           &imageStorageArray);
185b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    }
186fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
187a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
188a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
189b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
190b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon    GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin());
191f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin());
192fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    GrGLSLFragmentProcessor::EmitArgs args(&fFS,
193fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           this->uniformHandler(),
19494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon                                           this->shaderCaps(),
195fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           fp,
196fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           output->c_str(),
197fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                           input.isOnes() ? nullptr : input.c_str(),
198a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon                                           coords,
199b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon                                           textureSamplers,
200b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon                                           bufferSamplers,
201f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                           imageStorages,
2029b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck                                           this->primitiveProcessor().implementsDistanceVector());
2039b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck
204fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fragProc->emitCode(args);
205fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
206fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // We have to check that effects and the code they emit are consistent, ie if an effect
207fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // asks for dst color, then the emit code needs to follow suit
20887332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkDEBUGCODE(verify(fp);)
209fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFragmentProcessors.push_back(fragProc);
210fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
211fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend("}");
212fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
213fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
214fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
215fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                                  const GrGLSLExpr4& colorIn,
21642c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon                                                  const GrGLSLExpr4& coverageIn) {
217fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Program builders have a bit of state we need to clear with each effect
218fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    AutoStageAdvance adv(this);
219fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
220fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkASSERT(!fXferProcessor);
221fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fXferProcessor = xp.createGLSLInstance();
222fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
223fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Enable dual source secondary output if we have one
224fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    if (xp.hasSecondaryOutput()) {
225fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        fFS.enableSecondaryOutput();
226fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
227fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
22894efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
229fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        fFS.enableCustomOutput();
230fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
231fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
232fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkString openBrace;
233fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
234fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend(openBrace.c_str());
235fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
236f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<4, SamplerHandle>      texSamplers(xp.numTextureSamplers());
237f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<2, SamplerHandle>      bufferSamplers(xp.numBuffers());
238f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages());
239f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray);
240fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
241fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    GrGLSLXferProcessor::EmitArgs args(&fFS,
242fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                       this->uniformHandler(),
24394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon                                       this->shaderCaps(),
244fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                       xp, colorIn.c_str(),
2458c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                       coverageIn.c_str(),
246fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                       fFS.getPrimaryColorOutputName(),
247fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                                       fFS.getSecondaryColorOutputName(),
24809aa1fce69b214714171db12c341aebd78dd29eaegdaniel                                       texSamplers.begin(),
24909aa1fce69b214714171db12c341aebd78dd29eaegdaniel                                       bufferSamplers.begin(),
25042c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon                                       imageStorageArray.begin());
251fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fXferProcessor->emitCode(args);
252fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
253fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // We have to check that effects and the code they emit are consistent, ie if an effect
254fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // asks for dst color, then the emit code needs to follow suit
25587332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkDEBUGCODE(verify(xp);)
256fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppend("}");
257fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
258fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
259f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonvoid GrGLSLProgramBuilder::emitSamplersAndImageStorages(
260f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        const GrProcessor& processor,
261f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        SkTArray<SamplerHandle>* outTexSamplerHandles,
262f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        SkTArray<SamplerHandle>* outBufferSamplerHandles,
263f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        SkTArray<ImageStorageHandle>* outImageStorageHandles) {
2649c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    SkString name;
2650bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon    int numTextureSamplers = processor.numTextureSamplers();
2660bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon    for (int t = 0; t < numTextureSamplers; ++t) {
2670bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon        const GrProcessor::TextureSampler& sampler = processor.textureSampler(t);
268f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        name.printf("TextureSampler_%d", outTexSamplerHandles->count());
269db4183d227b764b219e9e314dd5387ded4c38797Brian Salomon        GrSLType samplerType = sampler.texture()->texturePriv().samplerType();
270990dbc88796f656418bcc4c196df30ed9bef6345egdaniel        if (kTextureExternalSampler_GrSLType == samplerType) {
27194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon            const char* externalFeatureString =
27294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon                    this->shaderCaps()->externalTextureExtensionString();
2739c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton            // We shouldn't ever create a GrGLTexture that requires external sampler type
2749c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton            SkASSERT(externalFeatureString);
275db4183d227b764b219e9e314dd5387ded4c38797Brian Salomon            this->addFeature(sampler.visibility(),
2769c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton                             1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
2779c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton                             externalFeatureString);
2789c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        }
279f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        this->emitSampler(samplerType, sampler.texture()->config(), name.c_str(),
280f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                          sampler.visibility(), outTexSamplerHandles);
281f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
28274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    }
28374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton
28474b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    if (int numBuffers = processor.numBuffers()) {
28594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        SkASSERT(this->shaderCaps()->texelBufferSupport());
28674b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
28774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton
28874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        for (int b = 0; b < numBuffers; ++b) {
289b014cca49d684886ec9813d4b47d126bfa48cf4eBrian Salomon            const GrProcessor::BufferAccess& access = processor.bufferAccess(b);
290f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            name.printf("BufferSampler_%d", outBufferSamplerHandles->count());
2912245803fcdabbbf216519ef708e1ec84e197e1fbcsmartdalton            this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
292f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                              access.visibility(), outBufferSamplerHandles);
29374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton            texelBufferVisibility |= access.visibility();
29474b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        }
29574b8d323323c8533e3e5cc7719e0bd127aacd829cdalton
29694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        if (const char* extension = this->shaderCaps()->texelBufferExtensionString()) {
29774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton            this->addFeature(texelBufferVisibility,
29874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton                             1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature,
29974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton                             extension);
30074b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        }
30174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    }
302f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    int numImageStorages = processor.numImageStorages();
303f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    for (int i = 0; i < numImageStorages; ++i) {
304f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        const GrProcessor::ImageStorageAccess& imageStorageAccess = processor.imageStorageAccess(i);
305f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        name.printf("Image_%d", outImageStorageHandles->count());
306f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        this->emitImageStorage(imageStorageAccess, name.c_str(), outImageStorageHandles);
307f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
30874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton}
30974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton
31074b8d323323c8533e3e5cc7719e0bd127aacd829cdaltonvoid GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
31174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton                                       GrPixelConfig config,
31274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton                                       const char* name,
31374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton                                       GrShaderFlags visibility,
314f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                       SkTArray<SamplerHandle>* outSamplerHandles) {
31574b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    if (visibility & kVertex_GrShaderFlag) {
31674b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        ++fNumVertexSamplers;
31774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    }
31874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    if (visibility & kGeometry_GrShaderFlag) {
31974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        SkASSERT(this->primitiveProcessor().willUseGeoShader());
32074b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        ++fNumGeometrySamplers;
32174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    }
32274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton    if (visibility & kFragment_GrShaderFlag) {
32374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton        ++fNumFragmentSamplers;
3249c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
32594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
32694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
327f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    outSamplerHandles->emplace_back(this->uniformHandler()->addSampler(visibility,
328f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                                                       swizzle,
329f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                                                       samplerType,
330f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                                                       precision,
331f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                                                       name));
332f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon}
333f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
334f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonvoid GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAccess& access,
335f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                            const char* name,
336f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                            SkTArray<ImageStorageHandle>* outImageStorageHandles) {
337f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    if (access.visibility() & kVertex_GrShaderFlag) {
338f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        ++fNumVertexImageStorages;
339f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
340f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    if (access.visibility() & kGeometry_GrShaderFlag) {
341f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        SkASSERT(this->primitiveProcessor().willUseGeoShader());
342f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        ++fNumGeometryImageStorages;
343f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
344f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    if (access.visibility() & kFragment_GrShaderFlag) {
345f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        ++fNumFragmentImageStorages;
346f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
347f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    GrSLType uniformType = access.texture()->texturePriv().imageStorageType();
348f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    ImageStorageHandle handle = this->uniformHandler()->addImageStorage(access.visibility(),
349f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon         uniformType, access.format(), access.memoryModel(), access.restrict(), access.ioType(),
350f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon         name);
351f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    outImageStorageHandles->emplace_back(handle);
3529c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton}
3539c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton
354fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
355fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // Swizzle the fragment shader outputs if necessary.
356fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    GrSwizzle swizzle;
3573865711259e25a90a1d72480f848863ada202067Ethan Nicholas    swizzle.setFromKey(this->desc()->header().fOutputSwizzle);
358fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    if (swizzle != GrSwizzle::RGBA()) {
359fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
360fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                        fFS.getPrimaryColorOutputName(),
361fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                        swizzle.c_str());
362fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        if (hasSecondaryOutput) {
363fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel            fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(),
364fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                            fFS.getSecondaryColorOutputName(),
365fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel                            swizzle.c_str());
366fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        }
367fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
368fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
369fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
3709c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdaltonbool GrGLSLProgramBuilder::checkSamplerCounts() {
3711edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    const GrShaderCaps& shaderCaps = *this->shaderCaps();
3721edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumVertexSamplers > shaderCaps.maxVertexSamplers()) {
3739c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n");
3749c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        return false;
3759c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
3761edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumGeometrySamplers > shaderCaps.maxGeometrySamplers()) {
3779c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n");
3789c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        return false;
3799c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
3801edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) {
3819c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
3829c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        return false;
3839c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
3849c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    // If the same sampler is used in two different shaders, it counts as two combined samplers.
3859c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers;
3861edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (numCombinedSamplers > shaderCaps.maxCombinedSamplers()) {
3879c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n");
3889c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton        return false;
3899c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    }
3909c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton    return true;
3919c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton}
3929c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton
393f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonbool GrGLSLProgramBuilder::checkImageStorageCounts() {
3941edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    const GrShaderCaps& shaderCaps = *this->shaderCaps();
3951edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumVertexImageStorages > shaderCaps.maxVertexImageStorages()) {
396f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        GrCapsDebugf(this->caps(), "Program would use too many vertex images\n");
397f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        return false;
398f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
3991edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumGeometryImageStorages > shaderCaps.maxGeometryImageStorages()) {
400f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        GrCapsDebugf(this->caps(), "Program would use too many geometry images\n");
401f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        return false;
402f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
4031edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (fNumFragmentImageStorages > shaderCaps.maxFragmentImageStorages()) {
404f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        GrCapsDebugf(this->caps(), "Program would use too many fragment images\n");
405f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        return false;
406f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
407f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    // If the same image is used in two different shaders, it counts as two combined images.
408f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages +
409f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        fNumFragmentImageStorages;
4101edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    if (numCombinedImages > shaderCaps.maxCombinedImageStorages()) {
411f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        GrCapsDebugf(this->caps(), "Program would use too many combined images\n");
412f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        return false;
413f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
414f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    return true;
415f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon}
416f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
41787332103c605dc3e0f76c0d1250a76c4ff71fddccdalton#ifdef SK_DEBUG
418fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
41987332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
420fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
421fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
422fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
42387332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
424fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
425fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
426fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
427fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
42887332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
4298dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel}
43087332103c605dc3e0f76c0d1250a76c4ff71fddccdalton#endif
4318dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
4328dcdedc4a087ea46ce1e2458d335d60918e56310egdanielvoid GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
4338dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    if ('\0' == prefix) {
4348dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel        *out = name;
4358dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    } else {
4368dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel        out->printf("%c%s", prefix, name);
4378dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    }
4388dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    if (mangle) {
4398dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel        if (out->endsWith('_')) {
4408dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel            // Names containing "__" are reserved.
4418dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel            out->append("x");
4428dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel        }
4438dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel        out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
4448dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel    }
4458dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel}
4468dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
447fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
448fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // create var to hold stage result.  If we already have a valid output name, just use that
449fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // otherwise create a new mangled one.  This name is only valid if we are reordering stages
450fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    // and have to tell stage exactly where to put its output.
451fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    SkString outName;
452fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    if (output->isValid()) {
453fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        outName = output->c_str();
454fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    } else {
455fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        this->nameVariable(&outName, '\0', baseName);
456fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
457fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    fFS.codeAppendf("vec4 %s;", outName.c_str());
458fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    *output = outName;
459fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
460fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
4615e58ceea8569f0d90ff7e3daf5de2def50407212cdaltonvoid GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
4627ea439b2203855db97330b25945b87dd4b170b8begdaniel    this->uniformHandler()->appendUniformDecls(visibility, out);
4637ea439b2203855db97330b25945b87dd4b170b8begdaniel}
4647ea439b2203855db97330b25945b87dd4b170b8begdaniel
465941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
4667ea439b2203855db97330b25945b87dd4b170b8begdaniel        SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
4677ea439b2203855db97330b25945b87dd4b170b8begdaniel        GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
4687ea439b2203855db97330b25945b87dd4b170b8begdaniel        fUniformHandles.fRTHeightUni =
4695e58ceea8569f0d90ff7e3daf5de2def50407212cdalton            uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
4707ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
471941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas                                                    name, false, 0, nullptr);
4728dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel}
4738dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel
474fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::cleanupFragmentProcessors() {
475fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    for (int i = 0; i < fFragmentProcessors.count(); ++i) {
476fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel        delete fFragmentProcessors[i];
477fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel    }
478fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel}
479fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel
4809f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdanielvoid GrGLSLProgramBuilder::finalizeShaders() {
4819f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel    this->varyingHandler()->finalize();
4825e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fVS.finalize(kVertex_GrShaderFlag);
483276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    if (this->primitiveProcessor().willUseGeoShader()) {
48494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        SkASSERT(this->shaderCaps()->geometryShaderSupport());
485276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        fGS.finalize(kGeometry_GrShaderFlag);
486276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    }
4875e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fFS.finalize(kFragment_GrShaderFlag);
4889f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel}
489