blob: f59edb4553b07ffa528549e436286c3d01a00850 [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 /**
ethannicholas5961bc92016-10-12 06:39:56 -070075 * Adds a constant declaration to the top of the shader.
cdaltond36f2c42016-02-11 14:10:38 -080076 */
ethannicholas5961bc92016-10-12 06:39:56 -070077 void defineConstant(const char* type, const char* name, const char* value) {
78 this->definitions().appendf("const %s %s = %s;\n", type, name, value);
cdaltond36f2c42016-02-11 14:10:38 -080079 }
80
ethannicholas5961bc92016-10-12 06:39:56 -070081 void defineConstant(const char* name, int value) {
82 this->definitions().appendf("const int %s = %i;\n", name, value);
cdaltond36f2c42016-02-11 14:10:38 -080083 }
84
ethannicholas5961bc92016-10-12 06:39:56 -070085 void defineConstant(const char* name, float value) {
86 this->definitions().appendf("const float %s = %f;\n", name, value);
87 }
88
89 void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
90 this->definitions().appendf("const %s %s = ", type, name);
cdaltond36f2c42016-02-11 14:10:38 -080091 va_list args;
ethannicholas5961bc92016-10-12 06:39:56 -070092 va_start(args, fmt);
93 this->definitions().appendVAList(fmt, args);
cdaltond36f2c42016-02-11 14:10:38 -080094 va_end(args);
ethannicholas5961bc92016-10-12 06:39:56 -070095 this->definitions().append(";\n");
cdaltond36f2c42016-02-11 14:10:38 -080096 }
97
98 /**
egdaniel57d3b032015-11-13 11:57:27 -080099 * Called by GrGLSLProcessors to add code to one of the shaders.
joshualitt30ba4362014-08-21 20:18:45 -0700100 */
101 void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
102 va_list args;
103 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800104 this->code().appendVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700105 va_end(args);
106 }
107
joshualitt43466a12015-02-13 17:18:27 -0800108 void codeAppend(const char* str) { this->code().append(str); }
joshualitt30ba4362014-08-21 20:18:45 -0700109
110 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
111 va_list args;
112 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800113 this->code().prependVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700114 va_end(args);
115 }
116
egdanielb2f94d12014-08-29 10:08:36 -0700117 /**
118 * Appends a variable declaration to one of the shaders
119 */
egdaniel0d3f0612015-10-21 10:45:48 -0700120 void declAppend(const GrGLSLShaderVar& var);
egdanielb2f94d12014-08-29 10:08:36 -0700121
cdalton1f50acf2016-04-11 11:30:50 -0700122 /**
123 * Appends a precision qualifier followed by a space, if relevant for the GLSL version.
124 */
125 void appendPrecisionModifier(GrSLPrecision);
126
joshualitt30ba4362014-08-21 20:18:45 -0700127 /** Emits a helper function outside of main() in the fragment shader. */
128 void emitFunction(GrSLType returnType,
129 const char* name,
130 int argCnt,
egdaniel0d3f0612015-10-21 10:45:48 -0700131 const GrGLSLShaderVar* args,
joshualitt30ba4362014-08-21 20:18:45 -0700132 const char* body,
133 SkString* outName);
134
135 /*
egdaniel574a4c12015-11-02 06:22:44 -0800136 * Combines the various parts of the shader to create a single finalized shader string.
137 */
138 void finalize(uint32_t visibility);
139
140 /*
joshualitt30ba4362014-08-21 20:18:45 -0700141 * Get parent builder for adding uniforms
142 */
egdaniel8dcdedc2015-11-11 06:27:20 -0800143 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
joshualitt30ba4362014-08-21 20:18:45 -0700144
145 /**
joshualitt47bb3822014-10-07 16:43:25 -0700146 * Helper for begining and ending a block in the shader code.
joshualitt30ba4362014-08-21 20:18:45 -0700147 */
148 class ShaderBlock {
149 public:
egdaniel2d721d32015-11-11 13:06:05 -0800150 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
bsalomon49f085d2014-09-05 13:34:00 -0700151 SkASSERT(builder);
joshualitt30ba4362014-08-21 20:18:45 -0700152 fBuilder->codeAppend("{");
153 }
154
155 ~ShaderBlock() {
156 fBuilder->codeAppend("}");
157 }
158 private:
egdaniel2d721d32015-11-11 13:06:05 -0800159 GrGLSLShaderBuilder* fBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700160 };
joshualitt47bb3822014-10-07 16:43:25 -0700161
joshualitt30ba4362014-08-21 20:18:45 -0700162protected:
egdaniel0d3f0612015-10-21 10:45:48 -0700163 typedef GrTAllocator<GrGLSLShaderVar> VarArray;
joshualitt47bb3822014-10-07 16:43:25 -0700164 void appendDecls(const VarArray& vars, SkString* out) const;
joshualitt30ba4362014-08-21 20:18:45 -0700165
cdaltonc08f1962016-02-12 12:14:06 -0800166 /**
167 * Features that should only be enabled internally by the builders.
168 */
169 enum GLSLPrivateFeature {
170 kFragCoordConventions_GLSLPrivateFeature,
171 kBlendEquationAdvanced_GLSLPrivateFeature,
172 kBlendFuncExtended_GLSLPrivateFeature,
173 kExternalTexture_GLSLPrivateFeature,
cdalton74b8d322016-04-11 14:47:28 -0700174 kTexelBuffer_GLSLPrivateFeature,
cdaltonc08f1962016-02-12 12:14:06 -0800175 kFramebufferFetch_GLSLPrivateFeature,
176 kNoPerspectiveInterpolation_GLSLPrivateFeature,
cdalton33ad7012016-02-22 07:55:44 -0800177 kSampleVariables_GLSLPrivateFeature,
178 kSampleMaskOverrideCoverage_GLSLPrivateFeature,
179 kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature
cdaltonc08f1962016-02-12 12:14:06 -0800180 };
181
joshualitt30ba4362014-08-21 20:18:45 -0700182 /*
joshualitt30ba4362014-08-21 20:18:45 -0700183 * A general function which enables an extension in a shader if the feature bit is not present
cdalton33ad7012016-02-22 07:55:44 -0800184 *
185 * @return true if the feature bit was not yet present, false otherwise.
joshualitt30ba4362014-08-21 20:18:45 -0700186 */
cdalton33ad7012016-02-22 07:55:44 -0800187 bool addFeature(uint32_t featureBit, const char* extensionName);
joshualitt30ba4362014-08-21 20:18:45 -0700188
cdaltone4017d82015-05-06 11:48:56 -0700189 enum 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
cdaltonf8a6ce82016-04-11 13:02:05 -0700205 /* Appends any swizzling we may need to get from some backend internal format to the format used
206 * in GrPixelConfig. If this is implemented by the GrGpu object, then swizzle will be rgba. For
207 * shader prettiness we omit the swizzle rather than appending ".rgba".
208 */
209 void appendTextureSwizzle(SkString* out, GrPixelConfig) const;
210
joshualitt43466a12015-02-13 17:18:27 -0800211 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 }
joshualittb8a82f22015-02-13 16:31:46 -0800217
joshualitt43466a12015-02-13 17:18:27 -0800218 SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
219 SkString& extensions() { return fShaderStrings[kExtensions]; }
cdaltond36f2c42016-02-11 14:10:38 -0800220 SkString& definitions() { return fShaderStrings[kDefinitions]; }
joshualitt43466a12015-02-13 17:18:27 -0800221 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
cdaltone4017d82015-05-06 11:48:56 -0700222 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
joshualitt43466a12015-02-13 17:18:27 -0800223 SkString& uniforms() { return fShaderStrings[kUniforms]; }
224 SkString& inputs() { return fShaderStrings[kInputs]; }
225 SkString& outputs() { return fShaderStrings[kOutputs]; }
226 SkString& functions() { return fShaderStrings[kFunctions]; }
227 SkString& main() { return fShaderStrings[kMain]; }
228 SkString& code() { return fShaderStrings[fCodeIndex]; }
egdaniel574a4c12015-11-02 06:22:44 -0800229
230 virtual void onFinalize() = 0;
joshualitt43466a12015-02-13 17:18:27 -0800231
232 enum {
233 kVersionDecl,
234 kExtensions,
cdaltond36f2c42016-02-11 14:10:38 -0800235 kDefinitions,
joshualitt43466a12015-02-13 17:18:27 -0800236 kPrecisionQualifier,
cdaltone4017d82015-05-06 11:48:56 -0700237 kLayoutQualifiers,
joshualitt43466a12015-02-13 17:18:27 -0800238 kUniforms,
239 kInputs,
240 kOutputs,
241 kFunctions,
242 kMain,
243 kCode,
244 };
245
egdaniel8dcdedc2015-11-11 06:27:20 -0800246 GrGLSLProgramBuilder* fProgramBuilder;
joshualitt43466a12015-02-13 17:18:27 -0800247 SkSTArray<kCode, const char*, true> fCompilerStrings;
248 SkSTArray<kCode, int, true> fCompilerStringLengths;
249 SkSTArray<kCode, SkString> fShaderStrings;
joshualitt30ba4362014-08-21 20:18:45 -0700250 SkString fCode;
251 SkString fFunctions;
252 SkString fExtensions;
253
254 VarArray fInputs;
255 VarArray fOutputs;
256 uint32_t fFeaturesAddedMask;
cdaltone4017d82015-05-06 11:48:56 -0700257 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
joshualitt43466a12015-02-13 17:18:27 -0800258 int fCodeIndex;
259 bool fFinalized;
260
egdanielfa896322016-01-13 12:19:30 -0800261 friend class GrGLSLProgramBuilder;
joshualitt43466a12015-02-13 17:18:27 -0800262 friend class GrGLProgramBuilder;
cdaltonc08f1962016-02-12 12:14:06 -0800263 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.
kkinnunen7aedda52015-06-29 23:01:28 -0700264 friend class GrGLPathProgramBuilder; // to access fInputs.
egdaniel22281c12016-03-23 13:49:40 -0700265 friend class GrVkPipelineStateBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700266};
joshualitt30ba4362014-08-21 20:18:45 -0700267#endif