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