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 "GrShaderCaps.h"
     13 #include "GrTexturePriv.h"
     14 #include "glsl/GrGLSLFragmentProcessor.h"
     15 #include "glsl/GrGLSLGeometryProcessor.h"
     16 #include "glsl/GrGLSLVarying.h"
     17 #include "glsl/GrGLSLXferProcessor.h"
     18 
     19 const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
     20 
     21 GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
     22                                            const GrPrimitiveProcessor& primProc,
     23                                            GrProgramDesc* desc)
     24     : fVS(this)
     25     , fGS(this)
     26     , fFS(this)
     27     , fStageIndex(-1)
     28     , fPipeline(pipeline)
     29     , fPrimProc(primProc)
     30     , fDesc(desc)
     31     , fGeometryProcessor(nullptr)
     32     , fXferProcessor(nullptr)
     33     , fNumVertexSamplers(0)
     34     , fNumGeometrySamplers(0)
     35     , fNumFragmentSamplers(0)
     36     , fNumVertexImageStorages(0)
     37     , fNumGeometryImageStorages(0)
     38     , fNumFragmentImageStorages(0) {
     39 }
     40 
     41 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
     42                                       uint32_t featureBit,
     43                                       const char* extensionName) {
     44     if (shaders & kVertex_GrShaderFlag) {
     45         fVS.addFeature(featureBit, extensionName);
     46     }
     47     if (shaders & kGeometry_GrShaderFlag) {
     48         SkASSERT(this->primitiveProcessor().willUseGeoShader());
     49         fGS.addFeature(featureBit, extensionName);
     50     }
     51     if (shaders & kFragment_GrShaderFlag) {
     52         fFS.addFeature(featureBit, extensionName);
     53     }
     54 }
     55 
     56 bool GrGLSLProgramBuilder::emitAndInstallProcs() {
     57     // First we loop over all of the installed processors and collect coord transforms.  These will
     58     // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
     59     const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
     60 
     61     SkString inputColor;
     62     SkString inputCoverage;
     63     this->emitAndInstallPrimProc(primProc, &inputColor, &inputCoverage);
     64     this->emitAndInstallFragProcs(&inputColor, &inputCoverage);
     65     this->emitAndInstallXferProc(inputColor, inputCoverage);
     66     this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
     67 
     68     return this->checkSamplerCounts() && this->checkImageStorageCounts();
     69 }
     70 
     71 void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
     72                                                   SkString* outputColor,
     73                                                   SkString* outputCoverage) {
     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 = kVertex_GrShaderFlag;
     81     if (proc.willUseGeoShader()) {
     82         rtAdjustVisibility |= kGeometry_GrShaderFlag;
     83     }
     84     fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
     85                                                                           kVec4f_GrSLType,
     86                                                                           kHigh_GrSLPrecision,
     87                                                                           "rtAdjustment");
     88     const char* rtAdjustName =
     89         this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
     90 
     91     // Enclose custom code in a block to avoid namespace conflicts
     92     SkString openBrace;
     93     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
     94     fFS.codeAppend(openBrace.c_str());
     95     fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
     96 
     97     SkASSERT(!fGeometryProcessor);
     98     fGeometryProcessor = proc.createGLSLInstance(*this->shaderCaps());
     99 
    100     SkSTArray<4, SamplerHandle>      texSamplers(proc.numTextureSamplers());
    101     SkSTArray<2, TexelBufferHandle>  texelBuffers(proc.numBuffers());
    102     SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages());
    103     this->emitSamplersAndImageStorages(proc, &texSamplers, &texelBuffers, &imageStorages);
    104 
    105     GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
    106                                                                        &fTransformedCoordVars);
    107     GrGLSLGeometryProcessor::EmitArgs args(&fVS,
    108                                            proc.willUseGeoShader() ? &fGS : nullptr,
    109                                            &fFS,
    110                                            this->varyingHandler(),
    111                                            this->uniformHandler(),
    112                                            this->shaderCaps(),
    113                                            proc,
    114                                            outputColor->c_str(),
    115                                            outputCoverage->c_str(),
    116                                            rtAdjustName,
    117                                            texSamplers.begin(),
    118                                            texelBuffers.begin(),
    119                                            imageStorages.begin(),
    120                                            &transformHandler);
    121     fGeometryProcessor->emitCode(args);
    122 
    123     // We have to check that effects and the code they emit are consistent, ie if an effect
    124     // asks for dst color, then the emit code needs to follow suit
    125     SkDEBUGCODE(verify(proc);)
    126 
    127     fFS.codeAppend("}");
    128 }
    129 
    130 void GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) {
    131     int transformedCoordVarsIdx = 0;
    132     SkString** inOut = &color;
    133     for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
    134         if (i == this->pipeline().numColorFragmentProcessors()) {
    135             inOut = &coverage;
    136         }
    137         SkString output;
    138         const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
    139         output = this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, output);
    140         GrFragmentProcessor::Iter iter(&fp);
    141         while (const GrFragmentProcessor* fp = iter.next()) {
    142             transformedCoordVarsIdx += fp->numCoordTransforms();
    143         }
    144         **inOut = output;
    145     }
    146 }
    147 
    148 // TODO Processors cannot output zeros because an empty string is all 1s
    149 // the fix is to allow effects to take the SkString directly
    150 SkString GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
    151                                                       int index,
    152                                                       int transformedCoordVarsIdx,
    153                                                       const SkString& input,
    154                                                       SkString output) {
    155     SkASSERT(input.size());
    156     // Program builders have a bit of state we need to clear with each effect
    157     AutoStageAdvance adv(this);
    158     this->nameExpression(&output, "output");
    159 
    160     // Enclose custom code in a block to avoid namespace conflicts
    161     SkString openBrace;
    162     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
    163     fFS.codeAppend(openBrace.c_str());
    164 
    165     GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
    166 
    167     SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers());
    168     SkSTArray<2, TexelBufferHandle> texelBufferArray(fp.numBuffers());
    169     SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages());
    170     GrFragmentProcessor::Iter iter(&fp);
    171     while (const GrFragmentProcessor* subFP = iter.next()) {
    172         this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &texelBufferArray,
    173                                            &imageStorageArray);
    174     }
    175 
    176     const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
    177     GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
    178     GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
    179     GrGLSLFragmentProcessor::TexelBuffers texelBuffers(&fp, texelBufferArray.begin());
    180     GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin());
    181     GrGLSLFragmentProcessor::EmitArgs args(&fFS,
    182                                            this->uniformHandler(),
    183                                            this->shaderCaps(),
    184                                            fp,
    185                                            output.c_str(),
    186                                            input.c_str(),
    187                                            coords,
    188                                            textureSamplers,
    189                                            texelBuffers,
    190                                            imageStorages);
    191 
    192     fragProc->emitCode(args);
    193 
    194     // We have to check that effects and the code they emit are consistent, ie if an effect
    195     // asks for dst color, then the emit code needs to follow suit
    196     SkDEBUGCODE(verify(fp);)
    197     fFragmentProcessors.push_back(fragProc);
    198 
    199     fFS.codeAppend("}");
    200     return output;
    201 }
    202 
    203 void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
    204                                                   const SkString& coverageIn) {
    205     // Program builders have a bit of state we need to clear with each effect
    206     AutoStageAdvance adv(this);
    207 
    208     SkASSERT(!fXferProcessor);
    209     const GrXferProcessor& xp = fPipeline.getXferProcessor();
    210     fXferProcessor = xp.createGLSLInstance();
    211 
    212     // Enable dual source secondary output if we have one
    213     if (xp.hasSecondaryOutput()) {
    214         fFS.enableSecondaryOutput();
    215     }
    216 
    217     if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
    218         fFS.enableCustomOutput();
    219     }
    220 
    221     SkString openBrace;
    222     openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
    223     fFS.codeAppend(openBrace.c_str());
    224 
    225     SamplerHandle dstTextureSamplerHandle;
    226     GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;
    227 
    228     if (GrTexture* dstTexture = fPipeline.peekDstTexture()) {
    229         // GrProcessor::TextureSampler sampler(dstTexture);
    230         SkString name("DstTextureSampler");
    231         dstTextureSamplerHandle =
    232                 this->emitSampler(dstTexture->texturePriv().samplerType(), dstTexture->config(),
    233                                   "DstTextureSampler", kFragment_GrShaderFlag);
    234         dstTextureOrigin = dstTexture->origin();
    235         SkASSERT(kTextureExternalSampler_GrSLType != dstTexture->texturePriv().samplerType());
    236     }
    237 
    238     GrGLSLXferProcessor::EmitArgs args(&fFS,
    239                                        this->uniformHandler(),
    240                                        this->shaderCaps(),
    241                                        xp,
    242                                        colorIn.size() ? colorIn.c_str() : "vec4(1)",
    243                                        coverageIn.size() ? coverageIn.c_str() : "vec4(1)",
    244                                        fFS.getPrimaryColorOutputName(),
    245                                        fFS.getSecondaryColorOutputName(),
    246                                        dstTextureSamplerHandle,
    247                                        dstTextureOrigin);
    248     fXferProcessor->emitCode(args);
    249 
    250     // We have to check that effects and the code they emit are consistent, ie if an effect
    251     // asks for dst color, then the emit code needs to follow suit
    252     SkDEBUGCODE(verify(xp);)
    253     fFS.codeAppend("}");
    254 }
    255 
    256 void GrGLSLProgramBuilder::emitSamplersAndImageStorages(
    257         const GrResourceIOProcessor& processor,
    258         SkTArray<SamplerHandle>* outTexSamplerHandles,
    259         SkTArray<TexelBufferHandle>* outTexelBufferHandles,
    260         SkTArray<ImageStorageHandle>* outImageStorageHandles) {
    261     SkString name;
    262     int numTextureSamplers = processor.numTextureSamplers();
    263     for (int t = 0; t < numTextureSamplers; ++t) {
    264         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(t);
    265         name.printf("TextureSampler_%d", outTexSamplerHandles->count());
    266         GrSLType samplerType = sampler.peekTexture()->texturePriv().samplerType();
    267         if (kTextureExternalSampler_GrSLType == samplerType) {
    268             const char* externalFeatureString =
    269                     this->shaderCaps()->externalTextureExtensionString();
    270             // We shouldn't ever create a GrGLTexture that requires external sampler type
    271             SkASSERT(externalFeatureString);
    272             this->addFeature(sampler.visibility(),
    273                              1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
    274                              externalFeatureString);
    275         }
    276         outTexSamplerHandles->emplace_back(this->emitSampler(
    277                 samplerType, sampler.peekTexture()->config(), name.c_str(), sampler.visibility()));
    278     }
    279     if (int numBuffers = processor.numBuffers()) {
    280         SkASSERT(this->shaderCaps()->texelBufferSupport());
    281         GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
    282 
    283         for (int b = 0; b < numBuffers; ++b) {
    284             const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(b);
    285             name.printf("TexelBuffer_%d", outTexelBufferHandles->count());
    286             outTexelBufferHandles->emplace_back(
    287                     this->emitTexelBuffer(access.texelConfig(), name.c_str(), access.visibility()));
    288             texelBufferVisibility |= access.visibility();
    289         }
    290 
    291         if (const char* extension = this->shaderCaps()->texelBufferExtensionString()) {
    292             this->addFeature(texelBufferVisibility,
    293                              1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature,
    294                              extension);
    295         }
    296     }
    297     int numImageStorages = processor.numImageStorages();
    298     for (int i = 0; i < numImageStorages; ++i) {
    299         const GrResourceIOProcessor::ImageStorageAccess& imageStorageAccess =
    300                 processor.imageStorageAccess(i);
    301         name.printf("Image_%d", outImageStorageHandles->count());
    302         outImageStorageHandles->emplace_back(
    303                 this->emitImageStorage(imageStorageAccess, name.c_str()));
    304     }
    305 }
    306 
    307 void GrGLSLProgramBuilder::updateSamplerCounts(GrShaderFlags visibility) {
    308     if (visibility & kVertex_GrShaderFlag) {
    309         ++fNumVertexSamplers;
    310     }
    311     if (visibility & kGeometry_GrShaderFlag) {
    312         SkASSERT(this->primitiveProcessor().willUseGeoShader());
    313         ++fNumGeometrySamplers;
    314     }
    315     if (visibility & kFragment_GrShaderFlag) {
    316         ++fNumFragmentSamplers;
    317     }
    318 }
    319 
    320 GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
    321                                                                       GrPixelConfig config,
    322                                                                       const char* name,
    323                                                                       GrShaderFlags visibility) {
    324     this->updateSamplerCounts(visibility);
    325     GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
    326     GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
    327     return this->uniformHandler()->addSampler(visibility, swizzle, samplerType, precision, name);
    328 }
    329 
    330 GrGLSLProgramBuilder::TexelBufferHandle GrGLSLProgramBuilder::emitTexelBuffer(
    331         GrPixelConfig config, const char* name, GrShaderFlags visibility) {
    332     this->updateSamplerCounts(visibility);
    333     GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
    334     return this->uniformHandler()->addTexelBuffer(visibility, precision, name);
    335 }
    336 
    337 GrGLSLProgramBuilder::ImageStorageHandle GrGLSLProgramBuilder::emitImageStorage(
    338         const GrResourceIOProcessor::ImageStorageAccess& access, const char* name) {
    339     if (access.visibility() & kVertex_GrShaderFlag) {
    340         ++fNumVertexImageStorages;
    341     }
    342     if (access.visibility() & kGeometry_GrShaderFlag) {
    343         SkASSERT(this->primitiveProcessor().willUseGeoShader());
    344         ++fNumGeometryImageStorages;
    345     }
    346     if (access.visibility() & kFragment_GrShaderFlag) {
    347         ++fNumFragmentImageStorages;
    348     }
    349     GrSLType uniformType = access.proxy()->imageStorageType();
    350     return this->uniformHandler()->addImageStorage(access.visibility(), uniformType,
    351                                                    access.format(), access.memoryModel(),
    352                                                    access.restrict(), access.ioType(), name);
    353 }
    354 
    355 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
    356     // Swizzle the fragment shader outputs if necessary.
    357     GrSwizzle swizzle;
    358     swizzle.setFromKey(this->desc()->header().fOutputSwizzle);
    359     if (swizzle != GrSwizzle::RGBA()) {
    360         fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
    361                         fFS.getPrimaryColorOutputName(),
    362                         swizzle.c_str());
    363         if (hasSecondaryOutput) {
    364             fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(),
    365                             fFS.getSecondaryColorOutputName(),
    366                             swizzle.c_str());
    367         }
    368     }
    369 }
    370 
    371 bool GrGLSLProgramBuilder::checkSamplerCounts() {
    372     const GrShaderCaps& shaderCaps = *this->shaderCaps();
    373     if (fNumVertexSamplers > shaderCaps.maxVertexSamplers()) {
    374         GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n");
    375         return false;
    376     }
    377     if (fNumGeometrySamplers > shaderCaps.maxGeometrySamplers()) {
    378         GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n");
    379         return false;
    380     }
    381     if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) {
    382         GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
    383         return false;
    384     }
    385     // If the same sampler is used in two different shaders, it counts as two combined samplers.
    386     int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers;
    387     if (numCombinedSamplers > shaderCaps.maxCombinedSamplers()) {
    388         GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n");
    389         return false;
    390     }
    391     return true;
    392 }
    393 
    394 bool GrGLSLProgramBuilder::checkImageStorageCounts() {
    395     const GrShaderCaps& shaderCaps = *this->shaderCaps();
    396     if (fNumVertexImageStorages > shaderCaps.maxVertexImageStorages()) {
    397         GrCapsDebugf(this->caps(), "Program would use too many vertex images\n");
    398         return false;
    399     }
    400     if (fNumGeometryImageStorages > shaderCaps.maxGeometryImageStorages()) {
    401         GrCapsDebugf(this->caps(), "Program would use too many geometry images\n");
    402         return false;
    403     }
    404     if (fNumFragmentImageStorages > shaderCaps.maxFragmentImageStorages()) {
    405         GrCapsDebugf(this->caps(), "Program would use too many fragment images\n");
    406         return false;
    407     }
    408     // If the same image is used in two different shaders, it counts as two combined images.
    409     int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages +
    410         fNumFragmentImageStorages;
    411     if (numCombinedImages > shaderCaps.maxCombinedImageStorages()) {
    412         GrCapsDebugf(this->caps(), "Program would use too many combined images\n");
    413         return false;
    414     }
    415     return true;
    416 }
    417 
    418 #ifdef SK_DEBUG
    419 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
    420     SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
    421 }
    422 
    423 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
    424     SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
    425     SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
    426 }
    427 
    428 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
    429     SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
    430 }
    431 #endif
    432 
    433 void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
    434     if ('\0' == prefix) {
    435         *out = name;
    436     } else {
    437         out->printf("%c%s", prefix, name);
    438     }
    439     if (mangle) {
    440         if (out->endsWith('_')) {
    441             // Names containing "__" are reserved.
    442             out->append("x");
    443         }
    444         out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
    445     }
    446 }
    447 
    448 void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) {
    449     // create var to hold stage result.  If we already have a valid output name, just use that
    450     // otherwise create a new mangled one.  This name is only valid if we are reordering stages
    451     // and have to tell stage exactly where to put its output.
    452     SkString outName;
    453     if (output->size()) {
    454         outName = output->c_str();
    455     } else {
    456         this->nameVariable(&outName, '\0', baseName);
    457     }
    458     fFS.codeAppendf("vec4 %s;", outName.c_str());
    459     *output = outName;
    460 }
    461 
    462 void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
    463     this->uniformHandler()->appendUniformDecls(visibility, out);
    464 }
    465 
    466 void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
    467         SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
    468         GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
    469         fUniformHandles.fRTHeightUni =
    470             uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
    471                                                     kFloat_GrSLType, kDefault_GrSLPrecision,
    472                                                     name, false, 0, nullptr);
    473 }
    474 
    475 void GrGLSLProgramBuilder::cleanupFragmentProcessors() {
    476     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
    477         delete fFragmentProcessors[i];
    478     }
    479 }
    480 
    481 void GrGLSLProgramBuilder::finalizeShaders() {
    482     this->varyingHandler()->finalize();
    483     fVS.finalize(kVertex_GrShaderFlag);
    484     if (this->primitiveProcessor().willUseGeoShader()) {
    485         SkASSERT(this->shaderCaps()->geometryShaderSupport());
    486         fGS.finalize(kGeometry_GrShaderFlag);
    487     }
    488     fFS.finalize(kFragment_GrShaderFlag);
    489 }
    490