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