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