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