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