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