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