blob: a6ff96dd1b08e52540b96bc0507a33da62c3fd1f [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
egdaniel2d721d32015-11-11 13:06:05 -08008#ifndef GrGLSLShaderBuilder_DEFINED
9#define GrGLSLShaderBuilder_DEFINED
joshualitt30ba4362014-08-21 20:18:45 -070010
egdaniel574a4c12015-11-02 06:22:44 -080011#include "GrAllocator.h"
egdaniel09aa1fc2016-04-20 07:09:46 -070012#include "glsl/GrGLSLUniformHandler.h"
egdaniel574a4c12015-11-02 06:22:44 -080013#include "glsl/GrGLSLShaderVar.h"
14#include "SkTDArray.h"
joshualitt30ba4362014-08-21 20:18:45 -070015
16#include <stdarg.h>
17
brianosman77320db2016-09-07 08:09:10 -070018class GrGLSLColorSpaceXformHelper;
19
joshualitt30ba4362014-08-21 20:18:45 -070020/**
21 base class for all shaders builders
22*/
egdaniel2d721d32015-11-11 13:06:05 -080023class GrGLSLShaderBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070024public:
egdaniel2d721d32015-11-11 13:06:05 -080025 GrGLSLShaderBuilder(GrGLSLProgramBuilder* program);
26 virtual ~GrGLSLShaderBuilder() {}
joshualitt30ba4362014-08-21 20:18:45 -070027
egdaniel09aa1fc2016-04-20 07:09:46 -070028 typedef GrGLSLUniformHandler::SamplerHandle SamplerHandle;
29
joshualitt30ba4362014-08-21 20:18:45 -070030 /** 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
cdalton3f6f76f2016-04-11 12:18:09 -070032 order of the result depends on the GrTextureAccess associated with the GrGLSLSampler.
egdaniel7dc4bd02015-10-29 07:57:01 -070033 */
joshualitt30ba4362014-08-21 20:18:45 -070034 void appendTextureLookup(SkString* out,
egdaniel09aa1fc2016-04-20 07:09:46 -070035 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070036 const char* coordName,
37 GrSLType coordType = kVec2f_GrSLType) const;
38
cdaltonf8a6ce82016-04-11 13:02:05 -070039 /** Version of above that appends the result to the shader code instead.*/
egdaniel09aa1fc2016-04-20 07:09:46 -070040 void appendTextureLookup(SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070041 const char* coordName,
brianosman77320db2016-09-07 08:09:10 -070042 GrSLType coordType = kVec2f_GrSLType,
43 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
joshualitt30ba4362014-08-21 20:18:45 -070044
45
46 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
cdalton3f6f76f2016-04-11 12:18:09 -070047 always a vec4. modulation and the swizzle specified by GrGLSLSampler must both be
egdaniel7dc4bd02015-10-29 07:57:01 -070048 vec4 or float. If modulation is "" or nullptr it this function acts as though
49 appendTextureLookup were called. */
joshualitt30ba4362014-08-21 20:18:45 -070050 void appendTextureLookupAndModulate(const char* modulation,
egdaniel09aa1fc2016-04-20 07:09:46 -070051 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070052 const char* coordName,
brianosman77320db2016-09-07 08:09:10 -070053 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);
joshualitt30ba4362014-08-21 20:18:45 -070065
cdaltonf8a6ce82016-04-11 13:02:05 -070066 /** 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. */
egdaniel09aa1fc2016-04-20 07:09:46 -070069 void appendTexelFetch(SkString* out, SamplerHandle, const char* coordExpr) const;
cdaltonf8a6ce82016-04-11 13:02:05 -070070
71 /** Version of above that appends the result to the shader code instead.*/
egdaniel09aa1fc2016-04-20 07:09:46 -070072 void appendTexelFetch(SamplerHandle, const char* coordExpr);
cdaltonf8a6ce82016-04-11 13:02:05 -070073
joshualitt30ba4362014-08-21 20:18:45 -070074 /**
fmalitad214d6a2016-09-30 08:05:24 -070075 * Adds a #define directive to the top of the shader.
cdaltond36f2c42016-02-11 14:10:38 -080076 */
fmalitad214d6a2016-09-30 08:05:24 -070077 void define(const char* macro, const char* replacement) {
78 this->definitions().appendf("#define %s %s\n", macro, replacement);
cdaltond36f2c42016-02-11 14:10:38 -080079 }
80
fmalitad214d6a2016-09-30 08:05:24 -070081 void define(const char* macro, int replacement) {
82 this->definitions().appendf("#define %s %i\n", macro, replacement);
cdaltond36f2c42016-02-11 14:10:38 -080083 }
84
fmalitad214d6a2016-09-30 08:05:24 -070085 void definef(const char* macro, const char* replacement, ...) {
86 this->definitions().appendf("#define %s ", macro);
cdaltond36f2c42016-02-11 14:10:38 -080087 va_list args;
fmalitad214d6a2016-09-30 08:05:24 -070088 va_start(args, replacement);
89 this->definitions().appendVAList(replacement, args);
cdaltond36f2c42016-02-11 14:10:38 -080090 va_end(args);
fmalitad214d6a2016-09-30 08:05:24 -070091 this->definitions().append("\n");
cdaltond36f2c42016-02-11 14:10:38 -080092 }
93
94 /**
egdaniel57d3b032015-11-13 11:57:27 -080095 * Called by GrGLSLProcessors to add code to one of the shaders.
joshualitt30ba4362014-08-21 20:18:45 -070096 */
97 void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
98 va_list args;
99 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800100 this->code().appendVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700101 va_end(args);
102 }
103
joshualitt43466a12015-02-13 17:18:27 -0800104 void codeAppend(const char* str) { this->code().append(str); }
joshualitt30ba4362014-08-21 20:18:45 -0700105
106 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
107 va_list args;
108 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800109 this->code().prependVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700110 va_end(args);
111 }
112
egdanielb2f94d12014-08-29 10:08:36 -0700113 /**
114 * Appends a variable declaration to one of the shaders
115 */
egdaniel0d3f0612015-10-21 10:45:48 -0700116 void declAppend(const GrGLSLShaderVar& var);
egdanielb2f94d12014-08-29 10:08:36 -0700117
cdalton1f50acf2016-04-11 11:30:50 -0700118 /**
119 * Appends a precision qualifier followed by a space, if relevant for the GLSL version.
120 */
121 void appendPrecisionModifier(GrSLPrecision);
122
joshualitt30ba4362014-08-21 20:18:45 -0700123 /** Emits a helper function outside of main() in the fragment shader. */
124 void emitFunction(GrSLType returnType,
125 const char* name,
126 int argCnt,
egdaniel0d3f0612015-10-21 10:45:48 -0700127 const GrGLSLShaderVar* args,
joshualitt30ba4362014-08-21 20:18:45 -0700128 const char* body,
129 SkString* outName);
130
131 /*
egdaniel574a4c12015-11-02 06:22:44 -0800132 * Combines the various parts of the shader to create a single finalized shader string.
133 */
134 void finalize(uint32_t visibility);
135
136 /*
joshualitt30ba4362014-08-21 20:18:45 -0700137 * Get parent builder for adding uniforms
138 */
egdaniel8dcdedc2015-11-11 06:27:20 -0800139 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
joshualitt30ba4362014-08-21 20:18:45 -0700140
141 /**
joshualitt47bb3822014-10-07 16:43:25 -0700142 * Helper for begining and ending a block in the shader code.
joshualitt30ba4362014-08-21 20:18:45 -0700143 */
144 class ShaderBlock {
145 public:
egdaniel2d721d32015-11-11 13:06:05 -0800146 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
bsalomon49f085d2014-09-05 13:34:00 -0700147 SkASSERT(builder);
joshualitt30ba4362014-08-21 20:18:45 -0700148 fBuilder->codeAppend("{");
149 }
150
151 ~ShaderBlock() {
152 fBuilder->codeAppend("}");
153 }
154 private:
egdaniel2d721d32015-11-11 13:06:05 -0800155 GrGLSLShaderBuilder* fBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700156 };
joshualitt47bb3822014-10-07 16:43:25 -0700157
joshualitt30ba4362014-08-21 20:18:45 -0700158protected:
egdaniel0d3f0612015-10-21 10:45:48 -0700159 typedef GrTAllocator<GrGLSLShaderVar> VarArray;
joshualitt47bb3822014-10-07 16:43:25 -0700160 void appendDecls(const VarArray& vars, SkString* out) const;
joshualitt30ba4362014-08-21 20:18:45 -0700161
cdaltonc08f1962016-02-12 12:14:06 -0800162 /**
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,
cdalton74b8d322016-04-11 14:47:28 -0700170 kTexelBuffer_GLSLPrivateFeature,
cdaltonc08f1962016-02-12 12:14:06 -0800171 kFramebufferFetch_GLSLPrivateFeature,
172 kNoPerspectiveInterpolation_GLSLPrivateFeature,
cdalton33ad7012016-02-22 07:55:44 -0800173 kSampleVariables_GLSLPrivateFeature,
174 kSampleMaskOverrideCoverage_GLSLPrivateFeature,
175 kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature
cdaltonc08f1962016-02-12 12:14:06 -0800176 };
177
joshualitt30ba4362014-08-21 20:18:45 -0700178 /*
joshualitt30ba4362014-08-21 20:18:45 -0700179 * A general function which enables an extension in a shader if the feature bit is not present
cdalton33ad7012016-02-22 07:55:44 -0800180 *
181 * @return true if the feature bit was not yet present, false otherwise.
joshualitt30ba4362014-08-21 20:18:45 -0700182 */
cdalton33ad7012016-02-22 07:55:44 -0800183 bool addFeature(uint32_t featureBit, const char* extensionName);
joshualitt30ba4362014-08-21 20:18:45 -0700184
cdaltone4017d82015-05-06 11:48:56 -0700185 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
cdaltonf8a6ce82016-04-11 13:02:05 -0700201 /* 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
joshualitt43466a12015-02-13 17:18:27 -0800207 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 }
joshualittb8a82f22015-02-13 16:31:46 -0800213
joshualitt43466a12015-02-13 17:18:27 -0800214 SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
215 SkString& extensions() { return fShaderStrings[kExtensions]; }
cdaltond36f2c42016-02-11 14:10:38 -0800216 SkString& definitions() { return fShaderStrings[kDefinitions]; }
joshualitt43466a12015-02-13 17:18:27 -0800217 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
cdaltone4017d82015-05-06 11:48:56 -0700218 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
joshualitt43466a12015-02-13 17:18:27 -0800219 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]; }
egdaniel574a4c12015-11-02 06:22:44 -0800225
226 virtual void onFinalize() = 0;
joshualitt43466a12015-02-13 17:18:27 -0800227
228 enum {
229 kVersionDecl,
230 kExtensions,
cdaltond36f2c42016-02-11 14:10:38 -0800231 kDefinitions,
joshualitt43466a12015-02-13 17:18:27 -0800232 kPrecisionQualifier,
cdaltone4017d82015-05-06 11:48:56 -0700233 kLayoutQualifiers,
joshualitt43466a12015-02-13 17:18:27 -0800234 kUniforms,
235 kInputs,
236 kOutputs,
237 kFunctions,
238 kMain,
239 kCode,
240 };
241
egdaniel8dcdedc2015-11-11 06:27:20 -0800242 GrGLSLProgramBuilder* fProgramBuilder;
joshualitt43466a12015-02-13 17:18:27 -0800243 SkSTArray<kCode, const char*, true> fCompilerStrings;
244 SkSTArray<kCode, int, true> fCompilerStringLengths;
245 SkSTArray<kCode, SkString> fShaderStrings;
joshualitt30ba4362014-08-21 20:18:45 -0700246 SkString fCode;
247 SkString fFunctions;
248 SkString fExtensions;
249
250 VarArray fInputs;
251 VarArray fOutputs;
252 uint32_t fFeaturesAddedMask;
cdaltone4017d82015-05-06 11:48:56 -0700253 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
joshualitt43466a12015-02-13 17:18:27 -0800254 int fCodeIndex;
255 bool fFinalized;
256
egdanielfa896322016-01-13 12:19:30 -0800257 friend class GrGLSLProgramBuilder;
joshualitt43466a12015-02-13 17:18:27 -0800258 friend class GrGLProgramBuilder;
cdaltonc08f1962016-02-12 12:14:06 -0800259 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.
kkinnunen7aedda52015-06-29 23:01:28 -0700260 friend class GrGLPathProgramBuilder; // to access fInputs.
egdaniel22281c12016-03-23 13:49:40 -0700261 friend class GrVkPipelineStateBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700262};
joshualitt30ba4362014-08-21 20:18:45 -0700263#endif