• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 "glsl/GrGLSLProgramBuilder.h"
9 
10 #include "GrCaps.h"
11 #include "GrPipeline.h"
12 #include "GrRenderTarget.h"
13 #include "GrShaderCaps.h"
14 #include "GrTexturePriv.h"
15 #include "glsl/GrGLSLFragmentProcessor.h"
16 #include "glsl/GrGLSLGeometryProcessor.h"
17 #include "glsl/GrGLSLVarying.h"
18 #include "glsl/GrGLSLXferProcessor.h"
19 #include "SkSLCompiler.h"
20 
21 const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
22 
GrGLSLProgramBuilder(GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,GrProgramDesc * desc)23 GrGLSLProgramBuilder::GrGLSLProgramBuilder(GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
24                                            const GrPrimitiveProcessor& primProc,
25                                            const GrTextureProxy* const primProcProxies[],
26                                            const GrPipeline& pipeline,
27                                            GrProgramDesc* desc)
28         : fVS(this)
29         , fGS(this)
30         , fFS(this)
31         , fStageIndex(-1)
32         , fRenderTarget(renderTarget)
33         , fOrigin(origin)
34         , fPipeline(pipeline)
35         , fPrimProc(primProc)
36         , fPrimProcProxies(primProcProxies)
37         , fDesc(desc)
38         , fGeometryProcessor(nullptr)
39         , fXferProcessor(nullptr)
40         , fNumFragmentSamplers(0) {}
41 
addFeature(GrShaderFlags shaders,uint32_t featureBit,const char * extensionName)42 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
43                                       uint32_t featureBit,
44                                       const char* extensionName) {
45     if (shaders & kVertex_GrShaderFlag) {
46         fVS.addFeature(featureBit, extensionName);
47     }
48     if (shaders & kGeometry_GrShaderFlag) {
49         SkASSERT(this->primitiveProcessor().willUseGeoShader());
50         fGS.addFeature(featureBit, extensionName);
51     }
52     if (shaders & kFragment_GrShaderFlag) {
53         fFS.addFeature(featureBit, extensionName);
54     }
55 }
56 
emitAndInstallProcs()57 bool GrGLSLProgramBuilder::emitAndInstallProcs() {
58     // First we loop over all of the installed processors and collect coord transforms.  These will
59     // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
60     SkString inputColor;
61     SkString inputCoverage;
62     this->emitAndInstallPrimProc(&inputColor, &inputCoverage);
63     this->emitAndInstallFragProcs(&inputColor, &inputCoverage);
64     this->emitAndInstallXferProc(inputColor, inputCoverage);
65     this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
66 
67     return this->checkSamplerCounts();
68 }
69 
emitAndInstallPrimProc(SkString * outputColor,SkString * outputCoverage)70 void GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor,
71                                                   SkString* outputCoverage) {
72     const GrPrimitiveProcessor& proc = this->primitiveProcessor();
73     const GrTextureProxy* const* primProcProxies = this->primProcProxies();
74 
75     // Program builders have a bit of state we need to clear with each effect
76     AutoStageAdvance adv(this);
77     this->nameExpression(outputColor, "outputColor");
78     this->nameExpression(outputCoverage, "outputCoverage");
79 
80     SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
81     GrShaderFlags rtAdjustVisibility;
82     if (proc.willUseGeoShader()) {
83         rtAdjustVisibility = kGeometry_GrShaderFlag;
84     } else {
85         rtAdjustVisibility = kVertex_GrShaderFlag;
86     }
87     fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
88                                                                      rtAdjustVisibility,
89                                                                      kFloat4_GrSLType,
90                                                                      SkSL::Compiler::RTADJUST_NAME);
91     const char* rtAdjustName =
92         this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
93 
94     // Enclose custom code in a block to avoid namespace conflicts
95     SkString openBrace;
96     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
97     fFS.codeAppend(openBrace.c_str());
98     fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
99 
100     SkASSERT(!fGeometryProcessor);
101     fGeometryProcessor.reset(proc.createGLSLInstance(*this->shaderCaps()));
102 
103     SkAutoSTMalloc<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
104     for (int i = 0; i < proc.numTextureSamplers(); ++i) {
105         SkString name;
106         name.printf("TextureSampler_%d", i);
107         const auto& sampler = proc.textureSampler(i);
108         const GrTexture* texture = primProcProxies[i]->peekTexture();
109         SkASSERT(sampler.textureType() == texture->texturePriv().textureType());
110         SkASSERT(sampler.config() == texture->config());
111         texSamplers[i] = this->emitSampler(texture,
112                                            sampler.samplerState(),
113                                            name.c_str());
114     }
115 
116     GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
117                                                                        &fTransformedCoordVars);
118     GrGLSLGeometryProcessor::EmitArgs args(&fVS,
119                                            proc.willUseGeoShader() ? &fGS : nullptr,
120                                            &fFS,
121                                            this->varyingHandler(),
122                                            this->uniformHandler(),
123                                            this->shaderCaps(),
124                                            proc,
125                                            outputColor->c_str(),
126                                            outputCoverage->c_str(),
127                                            rtAdjustName,
128                                            texSamplers.get(),
129                                            &transformHandler);
130     fGeometryProcessor->emitCode(args);
131 
132     // We have to check that effects and the code they emit are consistent, ie if an effect
133     // asks for dst color, then the emit code needs to follow suit
134     SkDEBUGCODE(verify(proc);)
135 
136     fFS.codeAppend("}");
137 }
138 
emitAndInstallFragProcs(SkString * color,SkString * coverage)139 void GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) {
140     int transformedCoordVarsIdx = 0;
141     SkString** inOut = &color;
142     SkSTArray<8, std::unique_ptr<GrGLSLFragmentProcessor>> glslFragmentProcessors;
143     for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
144         if (i == this->pipeline().numColorFragmentProcessors()) {
145             inOut = &coverage;
146         }
147         SkString output;
148         const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
149         output = this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, output,
150                                               &glslFragmentProcessors);
151         GrFragmentProcessor::Iter iter(&fp);
152         while (const GrFragmentProcessor* fp = iter.next()) {
153             transformedCoordVarsIdx += fp->numCoordTransforms();
154         }
155         **inOut = output;
156     }
157     fFragmentProcessorCnt = glslFragmentProcessors.count();
158     fFragmentProcessors.reset(new std::unique_ptr<GrGLSLFragmentProcessor>[fFragmentProcessorCnt]);
159     for (int i = 0; i < fFragmentProcessorCnt; ++i) {
160         fFragmentProcessors[i] = std::move(glslFragmentProcessors[i]);
161     }
162 }
163 
164 // TODO Processors cannot output zeros because an empty string is all 1s
165 // the fix is to allow effects to take the SkString directly
emitAndInstallFragProc(const GrFragmentProcessor & fp,int index,int transformedCoordVarsIdx,const SkString & input,SkString output,SkTArray<std::unique_ptr<GrGLSLFragmentProcessor>> * glslFragmentProcessors)166 SkString GrGLSLProgramBuilder::emitAndInstallFragProc(
167         const GrFragmentProcessor& fp,
168         int index,
169         int transformedCoordVarsIdx,
170         const SkString& input,
171         SkString output,
172         SkTArray<std::unique_ptr<GrGLSLFragmentProcessor>>* glslFragmentProcessors) {
173     SkASSERT(input.size());
174     // Program builders have a bit of state we need to clear with each effect
175     AutoStageAdvance adv(this);
176     this->nameExpression(&output, "output");
177 
178     // Enclose custom code in a block to avoid namespace conflicts
179     SkString openBrace;
180     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
181     fFS.codeAppend(openBrace.c_str());
182 
183     GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
184 
185     SkSTArray<4, SamplerHandle> texSamplers;
186     GrFragmentProcessor::Iter fpIter(&fp);
187     int samplerIdx = 0;
188     while (const auto* subFP = fpIter.next()) {
189         for (int i = 0; i < subFP->numTextureSamplers(); ++i) {
190             SkString name;
191             name.printf("TextureSampler_%d", samplerIdx++);
192             const auto& sampler = subFP->textureSampler(i);
193             texSamplers.emplace_back(this->emitSampler(sampler.peekTexture(),
194                                                        sampler.samplerState(),
195                                                        name.c_str()));
196         }
197     }
198 
199     const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
200     GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
201     GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin());
202     GrGLSLFragmentProcessor::EmitArgs args(&fFS,
203                                            this->uniformHandler(),
204                                            this->shaderCaps(),
205                                            fp,
206                                            output.c_str(),
207                                            input.c_str(),
208                                            coords,
209                                            textureSamplers);
210 
211     fragProc->emitCode(args);
212 
213     // We have to check that effects and the code they emit are consistent, ie if an effect
214     // asks for dst color, then the emit code needs to follow suit
215     SkDEBUGCODE(verify(fp);)
216     glslFragmentProcessors->emplace_back(fragProc);
217 
218     fFS.codeAppend("}");
219     return output;
220 }
221 
emitAndInstallXferProc(const SkString & colorIn,const SkString & coverageIn)222 void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
223                                                   const SkString& coverageIn) {
224     // Program builders have a bit of state we need to clear with each effect
225     AutoStageAdvance adv(this);
226 
227     SkASSERT(!fXferProcessor);
228     const GrXferProcessor& xp = fPipeline.getXferProcessor();
229     fXferProcessor.reset(xp.createGLSLInstance());
230 
231     // Enable dual source secondary output if we have one
232     if (xp.hasSecondaryOutput()) {
233         fFS.enableSecondaryOutput();
234     }
235 
236     if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
237         fFS.enableCustomOutput();
238     }
239 
240     SkString openBrace;
241     openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
242     fFS.codeAppend(openBrace.c_str());
243 
244     SamplerHandle dstTextureSamplerHandle;
245     GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;
246 
247     if (GrTexture* dstTexture = fPipeline.peekDstTexture()) {
248         // GrProcessor::TextureSampler sampler(dstTexture);
249         SkString name("DstTextureSampler");
250         dstTextureSamplerHandle =
251                 this->emitSampler(dstTexture, GrSamplerState(), "DstTextureSampler");
252         dstTextureOrigin = fPipeline.dstTextureProxy()->origin();
253         SkASSERT(dstTexture->texturePriv().textureType() != GrTextureType::kExternal);
254     }
255 
256     SkString finalInColor;
257     if (colorIn.size()) {
258         if (this->desc()->header().fClampBlendInput) {
259             finalInColor.printf("saturate(%s)", colorIn.c_str());
260         } else {
261             finalInColor = colorIn;
262         }
263     } else {
264         finalInColor = "float4(1)";
265     }
266 
267     GrGLSLXferProcessor::EmitArgs args(&fFS,
268                                        this->uniformHandler(),
269                                        this->shaderCaps(),
270                                        xp,
271                                        finalInColor.c_str(),
272                                        coverageIn.size() ? coverageIn.c_str() : "float4(1)",
273                                        fFS.getPrimaryColorOutputName(),
274                                        fFS.getSecondaryColorOutputName(),
275                                        dstTextureSamplerHandle,
276                                        dstTextureOrigin);
277     fXferProcessor->emitCode(args);
278 
279     // We have to check that effects and the code they emit are consistent, ie if an effect
280     // asks for dst color, then the emit code needs to follow suit
281     SkDEBUGCODE(verify(xp);)
282     fFS.codeAppend("}");
283 }
284 
emitSampler(const GrTexture * texture,const GrSamplerState & state,const char * name)285 GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(const GrTexture* texture,
286                                                                       const GrSamplerState& state,
287                                                                       const char* name) {
288     ++fNumFragmentSamplers;
289     return this->uniformHandler()->addSampler(texture, state, name, this->shaderCaps());
290 }
291 
emitFSOutputSwizzle(bool hasSecondaryOutput)292 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
293     // Swizzle the fragment shader outputs if necessary.
294     GrSwizzle swizzle;
295     swizzle.setFromKey(this->desc()->header().fOutputSwizzle);
296     if (swizzle != GrSwizzle::RGBA()) {
297         fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
298                         fFS.getPrimaryColorOutputName(),
299                         swizzle.c_str());
300         if (hasSecondaryOutput) {
301             fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(),
302                             fFS.getSecondaryColorOutputName(),
303                             swizzle.c_str());
304         }
305     }
306 }
307 
checkSamplerCounts()308 bool GrGLSLProgramBuilder::checkSamplerCounts() {
309     const GrShaderCaps& shaderCaps = *this->shaderCaps();
310     if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) {
311         GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
312         return false;
313     }
314     return true;
315 }
316 
317 #ifdef SK_DEBUG
verify(const GrPrimitiveProcessor & gp)318 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
319     SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
320     SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == gp.requestedFeatures());
321 }
322 
verify(const GrFragmentProcessor & fp)323 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
324     SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
325     SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == fp.requestedFeatures());
326 }
327 
verify(const GrXferProcessor & xp)328 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
329     SkASSERT(xp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly);
330     SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == xp.requestedFeatures());
331 }
332 #endif
333 
nameVariable(SkString * out,char prefix,const char * name,bool mangle)334 void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
335     if ('\0' == prefix) {
336         *out = name;
337     } else {
338         out->printf("%c%s", prefix, name);
339     }
340     if (mangle) {
341         if (out->endsWith('_')) {
342             // Names containing "__" are reserved.
343             out->append("x");
344         }
345         out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
346     }
347 }
348 
nameExpression(SkString * output,const char * baseName)349 void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) {
350     // create var to hold stage result.  If we already have a valid output name, just use that
351     // otherwise create a new mangled one.  This name is only valid if we are reordering stages
352     // and have to tell stage exactly where to put its output.
353     SkString outName;
354     if (output->size()) {
355         outName = output->c_str();
356     } else {
357         this->nameVariable(&outName, '\0', baseName);
358     }
359     fFS.codeAppendf("half4 %s;", outName.c_str());
360     *output = outName;
361 }
362 
appendUniformDecls(GrShaderFlags visibility,SkString * out) const363 void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
364     this->uniformHandler()->appendUniformDecls(visibility, out);
365 }
366 
addRTWidthUniform(const char * name)367 void GrGLSLProgramBuilder::addRTWidthUniform(const char* name) {
368         SkASSERT(!fUniformHandles.fRTWidthUni.isValid());
369         GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
370         fUniformHandles.fRTWidthUni =
371             uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag, kHalf_GrSLType, name,
372                                                     false, 0, nullptr);
373 }
374 
addRTHeightUniform(const char * name)375 void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
376         SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
377         GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
378         fUniformHandles.fRTHeightUni =
379             uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag, kHalf_GrSLType, name,
380                                                     false, 0, nullptr);
381 }
382 
finalizeShaders()383 void GrGLSLProgramBuilder::finalizeShaders() {
384     this->varyingHandler()->finalize();
385     fVS.finalize(kVertex_GrShaderFlag);
386     if (this->primitiveProcessor().willUseGeoShader()) {
387         SkASSERT(this->shaderCaps()->geometryShaderSupport());
388         fGS.finalize(kGeometry_GrShaderFlag);
389     }
390     fFS.finalize(kFragment_GrShaderFlag);
391 }
392