1 /* 2 * Copyright 2014 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 #ifndef GrGLSLShaderBuilder_DEFINED 9 #define GrGLSLShaderBuilder_DEFINED 10 11 #include "GrAllocator.h" 12 #include "GrShaderVar.h" 13 #include "glsl/GrGLSLUniformHandler.h" 14 #include "SkTDArray.h" 15 16 #include <stdarg.h> 17 18 class GrGLSLColorSpaceXformHelper; 19 20 /** 21 base class for all shaders builders 22 */ 23 class GrGLSLShaderBuilder { 24 public: 25 GrGLSLShaderBuilder(GrGLSLProgramBuilder* program); ~GrGLSLShaderBuilder()26 virtual ~GrGLSLShaderBuilder() {} 27 28 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; 29 using TexelBufferHandle = GrGLSLUniformHandler::TexelBufferHandle; 30 using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle; 31 32 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or 33 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle 34 order of the result depends on the GrProcessor::TextureSampler associated with the 35 SamplerHandle. 36 */ 37 void appendTextureLookup(SkString* out, 38 SamplerHandle, 39 const char* coordName, 40 GrSLType coordType = kVec2f_GrSLType) const; 41 42 /** Version of above that appends the result to the shader code instead.*/ 43 void appendTextureLookup(SamplerHandle, 44 const char* coordName, 45 GrSLType coordType = kVec2f_GrSLType, 46 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); 47 48 49 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is 50 always a vec4. modulation and the swizzle specified by SamplerHandle must both be 51 vec4 or float. If modulation is "" or nullptr it this function acts as though 52 appendTextureLookup were called. */ 53 void appendTextureLookupAndModulate(const char* modulation, 54 SamplerHandle, 55 const char* coordName, 56 GrSLType coordType = kVec2f_GrSLType, 57 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); 58 59 /** Adds a helper function to facilitate color gamut transformation, and produces code that 60 returns the srcColor transformed into a new gamut (via multiplication by the xform from 61 colorXformHelper). Premultiplied sources are also handled correctly (colorXformHelper 62 determines if the source is premultipled or not). */ 63 void appendColorGamutXform(SkString* out, const char* srcColor, 64 GrGLSLColorSpaceXformHelper* colorXformHelper); 65 66 /** Version of above that appends the result to the shader code instead. */ 67 void appendColorGamutXform(const char* srcColor, GrGLSLColorSpaceXformHelper* colorXformHelper); 68 69 /** Fetches an unfiltered texel from a sampler at integer coordinates. coordExpr must match the 70 dimensionality of the sampler and must be within the sampler's range. coordExpr is emitted 71 exactly once, so expressions like "idx++" are acceptable. */ 72 void appendTexelFetch(SkString* out, TexelBufferHandle, const char* coordExpr) const; 73 74 /** Version of above that appends the result to the shader code instead.*/ 75 void appendTexelFetch(TexelBufferHandle, const char* coordExpr); 76 77 /** Creates a string of shader code that performs an image load. */ 78 void appendImageStorageLoad(SkString* out, ImageStorageHandle, const char* coordExpr); 79 /** Version of above that appends the result to the shader code instead. */ 80 void appendImageStorageLoad(ImageStorageHandle, const char* coordExpr); 81 82 /** 83 * Adds a constant declaration to the top of the shader. 84 */ defineConstant(const char * type,const char * name,const char * value)85 void defineConstant(const char* type, const char* name, const char* value) { 86 this->definitions().appendf("const %s %s = %s;\n", type, name, value); 87 } 88 defineConstant(const char * name,int value)89 void defineConstant(const char* name, int value) { 90 this->definitions().appendf("const int %s = %i;\n", name, value); 91 } 92 defineConstant(const char * name,float value)93 void defineConstant(const char* name, float value) { 94 this->definitions().appendf("const float %s = %f;\n", name, value); 95 } 96 defineConstantf(const char * type,const char * name,const char * fmt,...)97 void defineConstantf(const char* type, const char* name, const char* fmt, ...) { 98 this->definitions().appendf("const %s %s = ", type, name); 99 va_list args; 100 va_start(args, fmt); 101 this->definitions().appendVAList(fmt, args); 102 va_end(args); 103 this->definitions().append(";\n"); 104 } 105 106 void declareGlobal(const GrShaderVar&); 107 108 /** 109 * Called by GrGLSLProcessors to add code to one of the shaders. 110 */ codeAppendf(const char format[],...)111 void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 112 va_list args; 113 va_start(args, format); 114 this->code().appendVAList(format, args); 115 va_end(args); 116 } 117 codeAppend(const char * str)118 void codeAppend(const char* str) { this->code().append(str); } 119 codePrependf(const char format[],...)120 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 121 va_list args; 122 va_start(args, format); 123 this->code().prependVAList(format, args); 124 va_end(args); 125 } 126 127 /** 128 * Appends a variable declaration to one of the shaders 129 */ 130 void declAppend(const GrShaderVar& var); 131 132 /** Emits a helper function outside of main() in the fragment shader. */ 133 void emitFunction(GrSLType returnType, 134 const char* name, 135 int argCnt, 136 const GrShaderVar* args, 137 const char* body, 138 SkString* outName); 139 140 /* 141 * Combines the various parts of the shader to create a single finalized shader string. 142 */ 143 void finalize(uint32_t visibility); 144 145 /* 146 * Get parent builder for adding uniforms 147 */ getProgramBuilder()148 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; } 149 150 /** 151 * Helper for begining and ending a block in the shader code. 152 */ 153 class ShaderBlock { 154 public: ShaderBlock(GrGLSLShaderBuilder * builder)155 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) { 156 SkASSERT(builder); 157 fBuilder->codeAppend("{"); 158 } 159 ~ShaderBlock()160 ~ShaderBlock() { 161 fBuilder->codeAppend("}"); 162 } 163 private: 164 GrGLSLShaderBuilder* fBuilder; 165 }; 166 167 protected: 168 typedef GrTAllocator<GrShaderVar> VarArray; 169 void appendDecls(const VarArray& vars, SkString* out) const; 170 171 /** 172 * Features that should only be enabled internally by the builders. 173 */ 174 enum GLSLPrivateFeature { 175 kFragCoordConventions_GLSLPrivateFeature, 176 kBlendEquationAdvanced_GLSLPrivateFeature, 177 kBlendFuncExtended_GLSLPrivateFeature, 178 kExternalTexture_GLSLPrivateFeature, 179 kTexelBuffer_GLSLPrivateFeature, 180 kFramebufferFetch_GLSLPrivateFeature, 181 kNoPerspectiveInterpolation_GLSLPrivateFeature, 182 kSampleVariables_GLSLPrivateFeature, 183 kSampleMaskOverrideCoverage_GLSLPrivateFeature, 184 kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature 185 }; 186 187 /* 188 * A general function which enables an extension in a shader if the feature bit is not present 189 * 190 * @return true if the feature bit was not yet present, false otherwise. 191 */ 192 bool addFeature(uint32_t featureBit, const char* extensionName); 193 194 enum InterfaceQualifier { 195 kIn_InterfaceQualifier, 196 kOut_InterfaceQualifier, 197 kLastInterfaceQualifier = kOut_InterfaceQualifier 198 }; 199 200 /* 201 * A low level function to build default layout qualifiers. 202 * 203 * e.g. layout(param1, param2, ...) out; 204 * 205 * GLSL allows default layout qualifiers for in, out, and uniform. 206 */ 207 void addLayoutQualifier(const char* param, InterfaceQualifier); 208 209 void compileAndAppendLayoutQualifiers(); 210 nextStage()211 void nextStage() { 212 fShaderStrings.push_back(); 213 fCompilerStrings.push_back(this->code().c_str()); 214 fCompilerStringLengths.push_back((int)this->code().size()); 215 fCodeIndex++; 216 } 217 versionDecl()218 SkString& versionDecl() { return fShaderStrings[kVersionDecl]; } extensions()219 SkString& extensions() { return fShaderStrings[kExtensions]; } definitions()220 SkString& definitions() { return fShaderStrings[kDefinitions]; } precisionQualifier()221 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } layoutQualifiers()222 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; } uniforms()223 SkString& uniforms() { return fShaderStrings[kUniforms]; } inputs()224 SkString& inputs() { return fShaderStrings[kInputs]; } outputs()225 SkString& outputs() { return fShaderStrings[kOutputs]; } functions()226 SkString& functions() { return fShaderStrings[kFunctions]; } main()227 SkString& main() { return fShaderStrings[kMain]; } code()228 SkString& code() { return fShaderStrings[fCodeIndex]; } 229 230 virtual void onFinalize() = 0; 231 232 enum { 233 kVersionDecl, 234 kExtensions, 235 kDefinitions, 236 kPrecisionQualifier, 237 kLayoutQualifiers, 238 kUniforms, 239 kInputs, 240 kOutputs, 241 kFunctions, 242 kMain, 243 kCode, 244 }; 245 246 GrGLSLProgramBuilder* fProgramBuilder; 247 SkSTArray<kCode, const char*, true> fCompilerStrings; 248 SkSTArray<kCode, int, true> fCompilerStringLengths; 249 SkSTArray<kCode, SkString> fShaderStrings; 250 SkString fCode; 251 SkString fFunctions; 252 SkString fExtensions; 253 254 VarArray fInputs; 255 VarArray fOutputs; 256 uint32_t fFeaturesAddedMask; 257 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1]; 258 int fCodeIndex; 259 bool fFinalized; 260 261 friend class GrGLSLProgramBuilder; 262 friend class GrGLProgramBuilder; 263 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature. 264 friend class GrGLPathProgramBuilder; // to access fInputs. 265 friend class GrVkPipelineStateBuilder; 266 }; 267 #endif 268