Home | History | Annotate | Download | only in glsl
      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 
     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 
     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 
     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 
     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 
    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
    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 
    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 
    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 
    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 
    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
    318 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
    319     SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    320     SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == gp.requestedFeatures());
    321 }
    322 
    323 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
    324     SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    325     SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == fp.requestedFeatures());
    326 }
    327 
    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 
    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 
    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 
    363 void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
    364     this->uniformHandler()->appendUniformDecls(visibility, out);
    365 }
    366 
    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 
    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 
    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