18dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel/* 28dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * Copyright 2015 Google Inc. 38dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * 48dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * Use of this source code is governed by a BSD-style license that can be 58dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel * found in the LICENSE file. 68dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel */ 78dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 88dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel#include "glsl/GrGLSLProgramBuilder.h" 98dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 1094efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrCaps.h" 11fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "GrPipeline.h" 1294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrShaderCaps.h" 13739c5bf111baf977fe418a24fa00ce260989ee9aBrian Salomon#include "GrTexturePriv.h" 14fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLFragmentProcessor.h" 15fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLGeometryProcessor.h" 169f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel#include "glsl/GrGLSLVarying.h" 17fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel#include "glsl/GrGLSLXferProcessor.h" 18fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 198dcdedc4a087ea46ce1e2458d335d60918e56310egdanielconst int GrGLSLProgramBuilder::kVarsPerBlock = 8; 208dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 210e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielGrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline, 220e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrPrimitiveProcessor& primProc, 233865711259e25a90a1d72480f848863ada202067Ethan Nicholas GrProgramDesc* desc) 248dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel : fVS(this) 258dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel , fGS(this) 2628f45b949acc746849100fbe112ee5280f0594c9cdalton , fFS(this) 278dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel , fStageIndex(-1) 280e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel , fPipeline(pipeline) 290e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel , fPrimProc(primProc) 300e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel , fDesc(desc) 31fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel , fGeometryProcessor(nullptr) 329c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton , fXferProcessor(nullptr) 339c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton , fNumVertexSamplers(0) 349c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton , fNumGeometrySamplers(0) 35f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon , fNumFragmentSamplers(0) 36f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon , fNumVertexImageStorages(0) 37f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon , fNumGeometryImageStorages(0) 38f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon , fNumFragmentImageStorages(0) { 399c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton} 409c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton 419c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdaltonvoid GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders, 429c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton uint32_t featureBit, 439c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton const char* extensionName) { 449c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton if (shaders & kVertex_GrShaderFlag) { 459c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton fVS.addFeature(featureBit, extensionName); 469c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 479c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton if (shaders & kGeometry_GrShaderFlag) { 48276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton SkASSERT(this->primitiveProcessor().willUseGeoShader()); 499c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton fGS.addFeature(featureBit, extensionName); 509c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 519c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton if (shaders & kFragment_GrShaderFlag) { 529c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton fFS.addFeature(featureBit, extensionName); 539c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 54fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 55fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 56fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielbool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, 579c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton GrGLSLExpr4* inputCoverage) { 58fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // First we loop over all of the installed processors and collect coord transforms. These will 59fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // be sent to the GrGLSLPrimitiveProcessor in its emitCode function 60fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); 61fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 62fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage); 63fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 64a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon this->emitAndInstallFragProcs(inputColor, inputCoverage); 6542c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage); 6642c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput()); 679c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton 68f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return this->checkSamplerCounts() && this->checkImageStorageCounts(); 69fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 70fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 71fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc, 72fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLExpr4* outputColor, 73fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLExpr4* outputCoverage) { 74fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Program builders have a bit of state we need to clear with each effect 75fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel AutoStageAdvance adv(this); 76fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->nameExpression(outputColor, "outputColor"); 77fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->nameExpression(outputCoverage, "outputCoverage"); 78fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 799b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck const char* distanceVectorName = nullptr; 809b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck if (this->fPipeline.usesDistanceVectorField() && proc.implementsDistanceVector()) { 8105a4cf59591024d838b204bb0f6fac42598ead28robertphillips // Each individual user (FP) of the distance vector must be able to handle having this 8205a4cf59591024d838b204bb0f6fac42598ead28robertphillips // variable be undeclared. There is no single default value that will yield a reasonable 8305a4cf59591024d838b204bb0f6fac42598ead28robertphillips // result for all users. 849b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck distanceVectorName = fFS.distanceVectorName(); 85ee92063f9e1a28e301fe6cdc804dca0ccc837f67dvonbeck fFS.codeAppend( "// Normalized vector to the closest geometric edge (in device space)\n"); 8684bca78ab462314ec48614ff50315f28d5467149dvonbeck fFS.codeAppend( "// Distance to the edge encoded in the z-component\n"); 876c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth fFS.codeAppendf("vec4 %s;", distanceVectorName); 889b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck } 899b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck 90936f81b95882be2e171a623b3116cc2ff408c813csmartdalton SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid()); 91936f81b95882be2e171a623b3116cc2ff408c813csmartdalton GrShaderFlags rtAdjustVisibility = kVertex_GrShaderFlag; 92936f81b95882be2e171a623b3116cc2ff408c813csmartdalton if (proc.willUseGeoShader()) { 93936f81b95882be2e171a623b3116cc2ff408c813csmartdalton rtAdjustVisibility |= kGeometry_GrShaderFlag; 94936f81b95882be2e171a623b3116cc2ff408c813csmartdalton } 95936f81b95882be2e171a623b3116cc2ff408c813csmartdalton fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility, 96936f81b95882be2e171a623b3116cc2ff408c813csmartdalton kVec4f_GrSLType, 97936f81b95882be2e171a623b3116cc2ff408c813csmartdalton kHigh_GrSLPrecision, 98936f81b95882be2e171a623b3116cc2ff408c813csmartdalton "rtAdjustment"); 99936f81b95882be2e171a623b3116cc2ff408c813csmartdalton const char* rtAdjustName = 100936f81b95882be2e171a623b3116cc2ff408c813csmartdalton this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni); 101936f81b95882be2e171a623b3116cc2ff408c813csmartdalton 102fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Enclose custom code in a block to avoid namespace conflicts 103fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkString openBrace; 104fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); 105fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend(openBrace.c_str()); 106fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); 107fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 108fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkASSERT(!fGeometryProcessor); 10994efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon fGeometryProcessor = proc.createGLSLInstance(*this->shaderCaps()); 110fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 111f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers()); 112f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers()); 113f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages()); 114f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->emitSamplersAndImageStorages(proc, &texSamplers, &bufferSamplers, &imageStorages); 115fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 116a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline, 117a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon &fTransformedCoordVars); 118fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLGeometryProcessor::EmitArgs args(&fVS, 119276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton proc.willUseGeoShader() ? &fGS : nullptr, 120fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel &fFS, 121fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->varyingHandler(), 122fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->uniformHandler(), 12394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon this->shaderCaps(), 124fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel proc, 125fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel outputColor->c_str(), 126fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel outputCoverage->c_str(), 1279b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck distanceVectorName, 128936f81b95882be2e171a623b3116cc2ff408c813csmartdalton rtAdjustName, 12909aa1fce69b214714171db12c341aebd78dd29eaegdaniel texSamplers.begin(), 13009aa1fce69b214714171db12c341aebd78dd29eaegdaniel bufferSamplers.begin(), 131f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon imageStorages.begin(), 132a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon &transformHandler); 133fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fGeometryProcessor->emitCode(args); 134fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 135fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // We have to check that effects and the code they emit are consistent, ie if an effect 136fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // asks for dst color, then the emit code needs to follow suit 13787332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkDEBUGCODE(verify(proc);) 138fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 139fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend("}"); 140fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 141fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 142a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomonvoid GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) { 143a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon int transformedCoordVarsIdx = 0; 144a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon GrGLSLExpr4** inOut = &color; 145a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) { 146a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon if (i == this->pipeline().numColorFragmentProcessors()) { 147a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon inOut = &coverage; 148a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon } 149fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLExpr4 output; 150fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); 151a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output); 152a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon GrFragmentProcessor::Iter iter(&fp); 153a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon while (const GrFragmentProcessor* fp = iter.next()) { 154a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon transformedCoordVarsIdx += fp->numCoordTransforms(); 155a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon } 156a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon **inOut = output; 157fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 158fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 159fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 160fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel// TODO Processors cannot output zeros because an empty string is all 1s 161fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel// the fix is to allow effects to take the GrGLSLExpr4 directly 162fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, 163fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel int index, 164a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon int transformedCoordVarsIdx, 165fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel const GrGLSLExpr4& input, 166fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLExpr4* output) { 167fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Program builders have a bit of state we need to clear with each effect 168fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel AutoStageAdvance adv(this); 169fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->nameExpression(output, "output"); 170fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 171fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Enclose custom code in a block to avoid namespace conflicts 172fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkString openBrace; 173fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); 174fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend(openBrace.c_str()); 175fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 176fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance(); 177fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 1780bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers()); 179b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers()); 180f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages()); 181b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon GrFragmentProcessor::Iter iter(&fp); 182b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon while (const GrFragmentProcessor* subFP = iter.next()) { 183f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &bufferSamplerArray, 184f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon &imageStorageArray); 185b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon } 186fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 187a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx; 188a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars); 189b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin()); 190b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin()); 191f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin()); 192fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLFragmentProcessor::EmitArgs args(&fFS, 193fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->uniformHandler(), 19494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon this->shaderCaps(), 195fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fp, 196fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel output->c_str(), 197fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel input.isOnes() ? nullptr : input.c_str(), 198a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon coords, 199b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon textureSamplers, 200b58a2b4919aa67ab5bab1d497f26671d704654b4bsalomon bufferSamplers, 201f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon imageStorages, 2029b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck this->primitiveProcessor().implementsDistanceVector()); 2039b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck 204fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fragProc->emitCode(args); 205fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 206fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // We have to check that effects and the code they emit are consistent, ie if an effect 207fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // asks for dst color, then the emit code needs to follow suit 20887332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkDEBUGCODE(verify(fp);) 209fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFragmentProcessors.push_back(fragProc); 210fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 211fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend("}"); 212fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 213fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 214fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, 215fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel const GrGLSLExpr4& colorIn, 21642c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon const GrGLSLExpr4& coverageIn) { 217fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Program builders have a bit of state we need to clear with each effect 218fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel AutoStageAdvance adv(this); 219fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 220fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkASSERT(!fXferProcessor); 221fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fXferProcessor = xp.createGLSLInstance(); 222fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 223fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Enable dual source secondary output if we have one 224fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel if (xp.hasSecondaryOutput()) { 225fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.enableSecondaryOutput(); 226fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 227fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 22894efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) { 229fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.enableCustomOutput(); 230fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 231fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 232fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkString openBrace; 233fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); 234fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend(openBrace.c_str()); 235fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 236f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<4, SamplerHandle> texSamplers(xp.numTextureSamplers()); 237f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<2, SamplerHandle> bufferSamplers(xp.numBuffers()); 238f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages()); 239f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray); 240fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 241fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrGLSLXferProcessor::EmitArgs args(&fFS, 242fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->uniformHandler(), 24394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon this->shaderCaps(), 244fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel xp, colorIn.c_str(), 2458c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon coverageIn.c_str(), 246fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.getPrimaryColorOutputName(), 247fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.getSecondaryColorOutputName(), 24809aa1fce69b214714171db12c341aebd78dd29eaegdaniel texSamplers.begin(), 24909aa1fce69b214714171db12c341aebd78dd29eaegdaniel bufferSamplers.begin(), 25042c456fd20bd45dd02f6d5eb0af7acf04341b1eeBrian Salomon imageStorageArray.begin()); 251fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fXferProcessor->emitCode(args); 252fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 253fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // We have to check that effects and the code they emit are consistent, ie if an effect 254fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // asks for dst color, then the emit code needs to follow suit 25587332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkDEBUGCODE(verify(xp);) 256fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppend("}"); 257fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 258fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 259f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonvoid GrGLSLProgramBuilder::emitSamplersAndImageStorages( 260f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon const GrProcessor& processor, 261f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkTArray<SamplerHandle>* outTexSamplerHandles, 262f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkTArray<SamplerHandle>* outBufferSamplerHandles, 263f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkTArray<ImageStorageHandle>* outImageStorageHandles) { 2649c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton SkString name; 2650bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon int numTextureSamplers = processor.numTextureSamplers(); 2660bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon for (int t = 0; t < numTextureSamplers; ++t) { 2670bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon const GrProcessor::TextureSampler& sampler = processor.textureSampler(t); 268f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon name.printf("TextureSampler_%d", outTexSamplerHandles->count()); 269db4183d227b764b219e9e314dd5387ded4c38797Brian Salomon GrSLType samplerType = sampler.texture()->texturePriv().samplerType(); 270990dbc88796f656418bcc4c196df30ed9bef6345egdaniel if (kTextureExternalSampler_GrSLType == samplerType) { 27194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon const char* externalFeatureString = 27294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon this->shaderCaps()->externalTextureExtensionString(); 2739c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton // We shouldn't ever create a GrGLTexture that requires external sampler type 2749c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton SkASSERT(externalFeatureString); 275db4183d227b764b219e9e314dd5387ded4c38797Brian Salomon this->addFeature(sampler.visibility(), 2769c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature, 2779c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton externalFeatureString); 2789c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 279f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->emitSampler(samplerType, sampler.texture()->config(), name.c_str(), 280f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon sampler.visibility(), outTexSamplerHandles); 281f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon 28274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 28374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton 28474b8d323323c8533e3e5cc7719e0bd127aacd829cdalton if (int numBuffers = processor.numBuffers()) { 28594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon SkASSERT(this->shaderCaps()->texelBufferSupport()); 28674b8d323323c8533e3e5cc7719e0bd127aacd829cdalton GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags; 28774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton 28874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton for (int b = 0; b < numBuffers; ++b) { 289b014cca49d684886ec9813d4b47d126bfa48cf4eBrian Salomon const GrProcessor::BufferAccess& access = processor.bufferAccess(b); 290f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon name.printf("BufferSampler_%d", outBufferSamplerHandles->count()); 2912245803fcdabbbf216519ef708e1ec84e197e1fbcsmartdalton this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(), 292f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon access.visibility(), outBufferSamplerHandles); 29374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton texelBufferVisibility |= access.visibility(); 29474b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 29574b8d323323c8533e3e5cc7719e0bd127aacd829cdalton 29694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon if (const char* extension = this->shaderCaps()->texelBufferExtensionString()) { 29774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton this->addFeature(texelBufferVisibility, 29874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton 1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature, 29974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton extension); 30074b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 30174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 302f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon int numImageStorages = processor.numImageStorages(); 303f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon for (int i = 0; i < numImageStorages; ++i) { 304f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon const GrProcessor::ImageStorageAccess& imageStorageAccess = processor.imageStorageAccess(i); 305f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon name.printf("Image_%d", outImageStorageHandles->count()); 306f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->emitImageStorage(imageStorageAccess, name.c_str(), outImageStorageHandles); 307f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 30874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton} 30974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton 31074b8d323323c8533e3e5cc7719e0bd127aacd829cdaltonvoid GrGLSLProgramBuilder::emitSampler(GrSLType samplerType, 31174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton GrPixelConfig config, 31274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton const char* name, 31374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton GrShaderFlags visibility, 314f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkTArray<SamplerHandle>* outSamplerHandles) { 31574b8d323323c8533e3e5cc7719e0bd127aacd829cdalton if (visibility & kVertex_GrShaderFlag) { 31674b8d323323c8533e3e5cc7719e0bd127aacd829cdalton ++fNumVertexSamplers; 31774b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 31874b8d323323c8533e3e5cc7719e0bd127aacd829cdalton if (visibility & kGeometry_GrShaderFlag) { 31974b8d323323c8533e3e5cc7719e0bd127aacd829cdalton SkASSERT(this->primitiveProcessor().willUseGeoShader()); 32074b8d323323c8533e3e5cc7719e0bd127aacd829cdalton ++fNumGeometrySamplers; 32174b8d323323c8533e3e5cc7719e0bd127aacd829cdalton } 32274b8d323323c8533e3e5cc7719e0bd127aacd829cdalton if (visibility & kFragment_GrShaderFlag) { 32374b8d323323c8533e3e5cc7719e0bd127aacd829cdalton ++fNumFragmentSamplers; 3249c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 32594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility); 32694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config); 327f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon outSamplerHandles->emplace_back(this->uniformHandler()->addSampler(visibility, 328f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon swizzle, 329f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon samplerType, 330f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon precision, 331f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon name)); 332f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon} 333f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon 334f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonvoid GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAccess& access, 335f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon const char* name, 336f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkTArray<ImageStorageHandle>* outImageStorageHandles) { 337f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (access.visibility() & kVertex_GrShaderFlag) { 338f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ++fNumVertexImageStorages; 339f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 340f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (access.visibility() & kGeometry_GrShaderFlag) { 341f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon SkASSERT(this->primitiveProcessor().willUseGeoShader()); 342f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ++fNumGeometryImageStorages; 343f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 344f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (access.visibility() & kFragment_GrShaderFlag) { 345f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ++fNumFragmentImageStorages; 346f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 347f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrSLType uniformType = access.texture()->texturePriv().imageStorageType(); 348f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ImageStorageHandle handle = this->uniformHandler()->addImageStorage(access.visibility(), 349f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon uniformType, access.format(), access.memoryModel(), access.restrict(), access.ioType(), 350f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon name); 351f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon outImageStorageHandles->emplace_back(handle); 3529c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton} 3539c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton 354fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { 355fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // Swizzle the fragment shader outputs if necessary. 356fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel GrSwizzle swizzle; 3573865711259e25a90a1d72480f848863ada202067Ethan Nicholas swizzle.setFromKey(this->desc()->header().fOutputSwizzle); 358fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel if (swizzle != GrSwizzle::RGBA()) { 359fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), 360fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.getPrimaryColorOutputName(), 361fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel swizzle.c_str()); 362fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel if (hasSecondaryOutput) { 363fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), 364fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.getSecondaryColorOutputName(), 365fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel swizzle.c_str()); 366fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 367fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 368fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 369fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 3709c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdaltonbool GrGLSLProgramBuilder::checkSamplerCounts() { 3711edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon const GrShaderCaps& shaderCaps = *this->shaderCaps(); 3721edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumVertexSamplers > shaderCaps.maxVertexSamplers()) { 3739c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n"); 3749c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton return false; 3759c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 3761edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumGeometrySamplers > shaderCaps.maxGeometrySamplers()) { 3779c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n"); 3789c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton return false; 3799c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 3801edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) { 3819c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n"); 3829c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton return false; 3839c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 3849c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton // If the same sampler is used in two different shaders, it counts as two combined samplers. 3859c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers; 3861edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (numCombinedSamplers > shaderCaps.maxCombinedSamplers()) { 3879c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n"); 3889c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton return false; 3899c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton } 3909c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton return true; 3919c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton} 3929c3f14327a38e79ab7d0cf30dfd9bf89676fde06cdalton 393f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomonbool GrGLSLProgramBuilder::checkImageStorageCounts() { 3941edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon const GrShaderCaps& shaderCaps = *this->shaderCaps(); 3951edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumVertexImageStorages > shaderCaps.maxVertexImageStorages()) { 396f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrCapsDebugf(this->caps(), "Program would use too many vertex images\n"); 397f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return false; 398f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 3991edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumGeometryImageStorages > shaderCaps.maxGeometryImageStorages()) { 400f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrCapsDebugf(this->caps(), "Program would use too many geometry images\n"); 401f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return false; 402f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 4031edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (fNumFragmentImageStorages > shaderCaps.maxFragmentImageStorages()) { 404f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrCapsDebugf(this->caps(), "Program would use too many fragment images\n"); 405f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return false; 406f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 407f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon // If the same image is used in two different shaders, it counts as two combined images. 408f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages + 409f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon fNumFragmentImageStorages; 4101edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon if (numCombinedImages > shaderCaps.maxCombinedImageStorages()) { 411f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon GrCapsDebugf(this->caps(), "Program would use too many combined images\n"); 412f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return false; 413f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 414f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon return true; 415f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon} 416f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon 41787332103c605dc3e0f76c0d1250a76c4ff71fddccdalton#ifdef SK_DEBUG 418fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { 41987332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures()); 420fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 421fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 422fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) { 42387332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures()); 424fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); 425fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 426fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 427fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) { 42887332103c605dc3e0f76c0d1250a76c4ff71fddccdalton SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures()); 4298dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel} 43087332103c605dc3e0f76c0d1250a76c4ff71fddccdalton#endif 4318dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 4328dcdedc4a087ea46ce1e2458d335d60918e56310egdanielvoid GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) { 4338dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel if ('\0' == prefix) { 4348dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel *out = name; 4358dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel } else { 4368dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel out->printf("%c%s", prefix, name); 4378dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel } 4388dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel if (mangle) { 4398dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel if (out->endsWith('_')) { 4408dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel // Names containing "__" are reserved. 4418dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel out->append("x"); 4428dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel } 4438dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str()); 4448dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel } 4458dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel} 4468dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 447fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { 448fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // create var to hold stage result. If we already have a valid output name, just use that 449fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // otherwise create a new mangled one. This name is only valid if we are reordering stages 450fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel // and have to tell stage exactly where to put its output. 451fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel SkString outName; 452fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel if (output->isValid()) { 453fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel outName = output->c_str(); 454fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } else { 455fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel this->nameVariable(&outName, '\0', baseName); 456fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 457fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel fFS.codeAppendf("vec4 %s;", outName.c_str()); 458fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel *output = outName; 459fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 460fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 4615e58ceea8569f0d90ff7e3daf5de2def50407212cdaltonvoid GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 4627ea439b2203855db97330b25945b87dd4b170b8begdaniel this->uniformHandler()->appendUniformDecls(visibility, out); 4637ea439b2203855db97330b25945b87dd4b170b8begdaniel} 4647ea439b2203855db97330b25945b87dd4b170b8begdaniel 465941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GrGLSLProgramBuilder::addRTHeightUniform(const char* name) { 4667ea439b2203855db97330b25945b87dd4b170b8begdaniel SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); 4677ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = this->uniformHandler(); 4687ea439b2203855db97330b25945b87dd4b170b8begdaniel fUniformHandles.fRTHeightUni = 4695e58ceea8569f0d90ff7e3daf5de2def50407212cdalton uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag, 4707ea439b2203855db97330b25945b87dd4b170b8begdaniel kFloat_GrSLType, kDefault_GrSLPrecision, 471941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas name, false, 0, nullptr); 4728dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel} 4738dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel 474fa8963252e122c5288c8e92b5ecc25a8fea21c3begdanielvoid GrGLSLProgramBuilder::cleanupFragmentProcessors() { 475fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel for (int i = 0; i < fFragmentProcessors.count(); ++i) { 476fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel delete fFragmentProcessors[i]; 477fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel } 478fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel} 479fa8963252e122c5288c8e92b5ecc25a8fea21c3begdaniel 4809f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdanielvoid GrGLSLProgramBuilder::finalizeShaders() { 4819f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel this->varyingHandler()->finalize(); 4825e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fVS.finalize(kVertex_GrShaderFlag); 483276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton if (this->primitiveProcessor().willUseGeoShader()) { 48494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon SkASSERT(this->shaderCaps()->geometryShaderSupport()); 485276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton fGS.finalize(kGeometry_GrShaderFlag); 486276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton } 4875e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fFS.finalize(kFragment_GrShaderFlag); 4889f1d4151ee35c1d2d4345fee2fbaf7b4210fb37degdaniel} 489