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