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 kLastGLSLPrivateFeature = kNoPerspectiveInterpolation_GLSLPrivateFeature 177 }; 178 179 /* 180 * A general function which enables an extension in a shader if the feature bit is not present 181 * 182 * @return true if the feature bit was not yet present, false otherwise. 183 */ 184 bool addFeature(uint32_t featureBit, const char* extensionName); 185 186 enum InterfaceQualifier { 187 kIn_InterfaceQualifier, 188 kOut_InterfaceQualifier, 189 kLastInterfaceQualifier = kOut_InterfaceQualifier 190 }; 191 192 /* 193 * A low level function to build default layout qualifiers. 194 * 195 * e.g. layout(param1, param2, ...) out; 196 * 197 * GLSL allows default layout qualifiers for in, out, and uniform. 198 */ 199 void addLayoutQualifier(const char* param, InterfaceQualifier); 200 201 void compileAndAppendLayoutQualifiers(); 202 203 void nextStage() { 204 fShaderStrings.push_back(); 205 fCompilerStrings.push_back(this->code().c_str()); 206 fCompilerStringLengths.push_back((int)this->code().size()); 207 fCodeIndex++; 208 } 209 210 SkString& versionDecl() { return fShaderStrings[kVersionDecl]; } 211 SkString& extensions() { return fShaderStrings[kExtensions]; } 212 SkString& definitions() { return fShaderStrings[kDefinitions]; } 213 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } 214 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; } 215 SkString& uniforms() { return fShaderStrings[kUniforms]; } 216 SkString& inputs() { return fShaderStrings[kInputs]; } 217 SkString& outputs() { return fShaderStrings[kOutputs]; } 218 SkString& functions() { return fShaderStrings[kFunctions]; } 219 SkString& main() { return fShaderStrings[kMain]; } 220 SkString& code() { return fShaderStrings[fCodeIndex]; } 221 222 virtual void onFinalize() = 0; 223 224 enum { 225 kVersionDecl, 226 kExtensions, 227 kDefinitions, 228 kPrecisionQualifier, 229 kLayoutQualifiers, 230 kUniforms, 231 kInputs, 232 kOutputs, 233 kFunctions, 234 kMain, 235 kCode, 236 }; 237 238 GrGLSLProgramBuilder* fProgramBuilder; 239 SkSTArray<kCode, const char*, true> fCompilerStrings; 240 SkSTArray<kCode, int, true> fCompilerStringLengths; 241 SkSTArray<kCode, SkString> fShaderStrings; 242 SkString fCode; 243 SkString fFunctions; 244 SkString fExtensions; 245 246 VarArray fInputs; 247 VarArray fOutputs; 248 uint32_t fFeaturesAddedMask; 249 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1]; 250 int fCodeIndex; 251 bool fFinalized; 252 253 friend class GrGLSLProgramBuilder; 254 friend class GrGLProgramBuilder; 255 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature. 256 friend class GrGLPathProgramBuilder; // to access fInputs. 257 friend class GrVkPipelineStateBuilder; 258 }; 259 #endif 260