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