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 "include/private/SkTDArray.h" 12 #include "src/gpu/GrAllocator.h" 13 #include "src/gpu/GrShaderVar.h" 14 #include "src/gpu/glsl/GrGLSLUniformHandler.h" 15 #include "src/sksl/SkSLString.h" 16 17 #include <stdarg.h> 18 19 class GrGLSLColorSpaceXformHelper; 20 21 /** 22 base class for all shaders builders 23 */ 24 class GrGLSLShaderBuilder { 25 public: 26 GrGLSLShaderBuilder(GrGLSLProgramBuilder* program); ~GrGLSLShaderBuilder()27 virtual ~GrGLSLShaderBuilder() {} 28 29 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; 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 /** 69 * Adds a constant declaration to the top of the shader. 70 */ defineConstant(const char * type,const char * name,const char * value)71 void defineConstant(const char* type, const char* name, const char* value) { 72 this->definitions().appendf("const %s %s = %s;\n", type, name, value); 73 } 74 defineConstant(const char * name,int value)75 void defineConstant(const char* name, int value) { 76 this->definitions().appendf("const int %s = %i;\n", name, value); 77 } 78 defineConstant(const char * name,float value)79 void defineConstant(const char* name, float value) { 80 this->definitions().appendf("const float %s = %f;\n", name, value); 81 } 82 defineConstantf(const char * type,const char * name,const char * fmt,...)83 void defineConstantf(const char* type, const char* name, const char* fmt, ...) { 84 this->definitions().appendf("const %s %s = ", type, name); 85 va_list args; 86 va_start(args, fmt); 87 this->definitions().appendVAList(fmt, args); 88 va_end(args); 89 this->definitions().append(";\n"); 90 } 91 92 void declareGlobal(const GrShaderVar&); 93 94 /** 95 * Called by GrGLSLProcessors to add code to one of the shaders. 96 */ codeAppendf(const char format[],...)97 void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 98 va_list args; 99 va_start(args, format); 100 this->code().appendVAList(format, args); 101 va_end(args); 102 } 103 codeAppend(const char * str)104 void codeAppend(const char* str) { this->code().append(str); } 105 codeAppend(const char * str,size_t length)106 void codeAppend(const char* str, size_t length) { this->code().append(str, length); } 107 codePrependf(const char format[],...)108 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 109 va_list args; 110 va_start(args, format); 111 this->code().prependVAList(format, args); 112 va_end(args); 113 } 114 115 /** 116 * Appends a variable declaration to one of the shaders 117 */ 118 void declAppend(const GrShaderVar& var); 119 120 /** Emits a helper function outside of main() in the fragment shader. */ 121 void emitFunction(GrSLType returnType, 122 const char* name, 123 int argCnt, 124 const GrShaderVar* args, 125 const char* body, 126 SkString* outName); 127 128 /* 129 * Combines the various parts of the shader to create a single finalized shader string. 130 */ 131 void finalize(uint32_t visibility); 132 133 /* 134 * Get parent builder for adding uniforms 135 */ getProgramBuilder()136 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; } 137 138 /** 139 * Helper for begining and ending a block in the shader code. 140 */ 141 class ShaderBlock { 142 public: ShaderBlock(GrGLSLShaderBuilder * builder)143 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) { 144 SkASSERT(builder); 145 fBuilder->codeAppend("{"); 146 } 147 ~ShaderBlock()148 ~ShaderBlock() { 149 fBuilder->codeAppend("}"); 150 } 151 private: 152 GrGLSLShaderBuilder* fBuilder; 153 }; 154 155 protected: 156 typedef GrTAllocator<GrShaderVar> VarArray; 157 void appendDecls(const VarArray& vars, SkString* out) const; 158 159 /** 160 * Features that should only be enabled internally by the builders. 161 */ 162 enum GLSLPrivateFeature { 163 kFragCoordConventions_GLSLPrivateFeature, 164 kBlendEquationAdvanced_GLSLPrivateFeature, 165 kBlendFuncExtended_GLSLPrivateFeature, 166 kFramebufferFetch_GLSLPrivateFeature, 167 kNoPerspectiveInterpolation_GLSLPrivateFeature, 168 kSampleVariables_GLSLPrivateFeature, 169 kLastGLSLPrivateFeature = kSampleVariables_GLSLPrivateFeature 170 }; 171 172 /* 173 * A general function which enables an extension in a shader if the feature bit is not present 174 * 175 * @return true if the feature bit was not yet present, false otherwise. 176 */ 177 bool addFeature(uint32_t featureBit, const char* extensionName); 178 179 enum InterfaceQualifier { 180 kIn_InterfaceQualifier, 181 kOut_InterfaceQualifier, 182 kLastInterfaceQualifier = kOut_InterfaceQualifier 183 }; 184 185 /* 186 * A low level function to build default layout qualifiers. 187 * 188 * e.g. layout(param1, param2, ...) out; 189 * 190 * GLSL allows default layout qualifiers for in, out, and uniform. 191 */ 192 void addLayoutQualifier(const char* param, InterfaceQualifier); 193 194 void compileAndAppendLayoutQualifiers(); 195 nextStage()196 void nextStage() { 197 fShaderStrings.push_back(); 198 fCodeIndex++; 199 } 200 deleteStage()201 void deleteStage() { 202 fShaderStrings.pop_back(); 203 fCodeIndex--; 204 } 205 extensions()206 SkString& extensions() { return fShaderStrings[kExtensions]; } definitions()207 SkString& definitions() { return fShaderStrings[kDefinitions]; } precisionQualifier()208 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } layoutQualifiers()209 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; } uniforms()210 SkString& uniforms() { return fShaderStrings[kUniforms]; } inputs()211 SkString& inputs() { return fShaderStrings[kInputs]; } outputs()212 SkString& outputs() { return fShaderStrings[kOutputs]; } functions()213 SkString& functions() { return fShaderStrings[kFunctions]; } main()214 SkString& main() { return fShaderStrings[kMain]; } code()215 SkString& code() { return fShaderStrings[fCodeIndex]; } 216 217 virtual void onFinalize() = 0; 218 219 enum { 220 kExtensions, 221 kDefinitions, 222 kPrecisionQualifier, 223 kLayoutQualifiers, 224 kUniforms, 225 kInputs, 226 kOutputs, 227 kFunctions, 228 kMain, 229 kCode, 230 231 kPrealloc = kCode + 6, // 6 == Reasonable upper bound on number of processor stages 232 }; 233 234 GrGLSLProgramBuilder* fProgramBuilder; 235 SkSL::String fCompilerString; 236 SkSTArray<kPrealloc, SkString> fShaderStrings; 237 SkString fCode; 238 SkString fFunctions; 239 SkString fExtensions; 240 241 VarArray fInputs; 242 VarArray fOutputs; 243 uint32_t fFeaturesAddedMask; 244 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1]; 245 int fCodeIndex; 246 bool fFinalized; 247 248 friend class GrCCCoverageProcessor; // to access code(). 249 friend class GrGLSLProgramBuilder; 250 friend class GrGLProgramBuilder; 251 friend class GrDawnProgramBuilder; 252 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature. 253 friend class GrGLPathProgramBuilder; // to access fInputs. 254 friend class GrVkPipelineStateBuilder; 255 friend class GrMtlPipelineStateBuilder; 256 }; 257 #endif 258