blob: 9ac6ab7626d935c9bf12508270ef2b1cd76cf0a9 [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"
Brian Salomon99938a82016-11-21 13:41:08 -050012#include "GrShaderVar.h"
egdaniel09aa1fc2016-04-20 07:09:46 -070013#include "glsl/GrGLSLUniformHandler.h"
egdaniel574a4c12015-11-02 06:22:44 -080014#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
Brian Salomonf9f45122016-11-29 11:59:17 -050028 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
Greg Danielbc5d4d72017-05-05 10:28:42 -040029 using TexelBufferHandle = GrGLSLUniformHandler::TexelBufferHandle;
Brian Salomonf9f45122016-11-29 11:59:17 -050030 using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
egdaniel09aa1fc2016-04-20 07:09:46 -070031
joshualitt30ba4362014-08-21 20:18:45 -070032 /** 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
Brian Salomon101b8442016-11-18 11:58:54 -050034 order of the result depends on the GrProcessor::TextureSampler associated with the
35 SamplerHandle.
egdaniel7dc4bd02015-10-29 07:57:01 -070036 */
joshualitt30ba4362014-08-21 20:18:45 -070037 void appendTextureLookup(SkString* out,
egdaniel09aa1fc2016-04-20 07:09:46 -070038 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070039 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040040 GrSLType coordType = kHalf2_GrSLType) const;
joshualitt30ba4362014-08-21 20:18:45 -070041
cdaltonf8a6ce82016-04-11 13:02:05 -070042 /** Version of above that appends the result to the shader code instead.*/
egdaniel09aa1fc2016-04-20 07:09:46 -070043 void appendTextureLookup(SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070044 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040045 GrSLType coordType = kHalf2_GrSLType,
brianosman77320db2016-09-07 08:09:10 -070046 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
joshualitt30ba4362014-08-21 20:18:45 -070047
48
49 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
Ethan Nicholasf7b88202017-09-18 14:10:39 -040050 always a half4. modulation and the swizzle specified by SamplerHandle must both be
51 half4 or half. If modulation is "" or nullptr it this function acts as though
egdaniel7dc4bd02015-10-29 07:57:01 -070052 appendTextureLookup were called. */
joshualitt30ba4362014-08-21 20:18:45 -070053 void appendTextureLookupAndModulate(const char* modulation,
egdaniel09aa1fc2016-04-20 07:09:46 -070054 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070055 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040056 GrSLType coordType = kHalf2_GrSLType,
brianosman77320db2016-09-07 08:09:10 -070057 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);
joshualitt30ba4362014-08-21 20:18:45 -070068
cdaltonf8a6ce82016-04-11 13:02:05 -070069 /** 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. */
Greg Danielbc5d4d72017-05-05 10:28:42 -040072 void appendTexelFetch(SkString* out, TexelBufferHandle, const char* coordExpr) const;
cdaltonf8a6ce82016-04-11 13:02:05 -070073
74 /** Version of above that appends the result to the shader code instead.*/
Greg Danielbc5d4d72017-05-05 10:28:42 -040075 void appendTexelFetch(TexelBufferHandle, const char* coordExpr);
cdaltonf8a6ce82016-04-11 13:02:05 -070076
Brian Salomonf9f45122016-11-29 11:59:17 -050077 /** 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
joshualitt30ba4362014-08-21 20:18:45 -070082 /**
ethannicholas5961bc92016-10-12 06:39:56 -070083 * Adds a constant declaration to the top of the shader.
cdaltond36f2c42016-02-11 14:10:38 -080084 */
ethannicholas5961bc92016-10-12 06:39:56 -070085 void defineConstant(const char* type, const char* name, const char* value) {
86 this->definitions().appendf("const %s %s = %s;\n", type, name, value);
cdaltond36f2c42016-02-11 14:10:38 -080087 }
88
ethannicholas5961bc92016-10-12 06:39:56 -070089 void defineConstant(const char* name, int value) {
90 this->definitions().appendf("const int %s = %i;\n", name, value);
cdaltond36f2c42016-02-11 14:10:38 -080091 }
92
ethannicholas5961bc92016-10-12 06:39:56 -070093 void defineConstant(const char* name, float value) {
94 this->definitions().appendf("const float %s = %f;\n", name, value);
95 }
96
97 void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
98 this->definitions().appendf("const %s %s = ", type, name);
cdaltond36f2c42016-02-11 14:10:38 -080099 va_list args;
ethannicholas5961bc92016-10-12 06:39:56 -0700100 va_start(args, fmt);
101 this->definitions().appendVAList(fmt, args);
cdaltond36f2c42016-02-11 14:10:38 -0800102 va_end(args);
ethannicholas5961bc92016-10-12 06:39:56 -0700103 this->definitions().append(";\n");
cdaltond36f2c42016-02-11 14:10:38 -0800104 }
105
csmartdalton75864b02017-02-09 09:47:21 -0500106 void declareGlobal(const GrShaderVar&);
107
cdaltond36f2c42016-02-11 14:10:38 -0800108 /**
egdaniel57d3b032015-11-13 11:57:27 -0800109 * Called by GrGLSLProcessors to add code to one of the shaders.
joshualitt30ba4362014-08-21 20:18:45 -0700110 */
111 void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
112 va_list args;
113 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800114 this->code().appendVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700115 va_end(args);
116 }
117
joshualitt43466a12015-02-13 17:18:27 -0800118 void codeAppend(const char* str) { this->code().append(str); }
joshualitt30ba4362014-08-21 20:18:45 -0700119
120 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
121 va_list args;
122 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800123 this->code().prependVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700124 va_end(args);
125 }
126
egdanielb2f94d12014-08-29 10:08:36 -0700127 /**
128 * Appends a variable declaration to one of the shaders
129 */
Brian Salomon99938a82016-11-21 13:41:08 -0500130 void declAppend(const GrShaderVar& var);
egdanielb2f94d12014-08-29 10:08:36 -0700131
joshualitt30ba4362014-08-21 20:18:45 -0700132 /** Emits a helper function outside of main() in the fragment shader. */
133 void emitFunction(GrSLType returnType,
134 const char* name,
135 int argCnt,
Brian Salomon99938a82016-11-21 13:41:08 -0500136 const GrShaderVar* args,
joshualitt30ba4362014-08-21 20:18:45 -0700137 const char* body,
138 SkString* outName);
139
140 /*
egdaniel574a4c12015-11-02 06:22:44 -0800141 * Combines the various parts of the shader to create a single finalized shader string.
142 */
143 void finalize(uint32_t visibility);
144
145 /*
joshualitt30ba4362014-08-21 20:18:45 -0700146 * Get parent builder for adding uniforms
147 */
egdaniel8dcdedc2015-11-11 06:27:20 -0800148 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
joshualitt30ba4362014-08-21 20:18:45 -0700149
150 /**
joshualitt47bb3822014-10-07 16:43:25 -0700151 * Helper for begining and ending a block in the shader code.
joshualitt30ba4362014-08-21 20:18:45 -0700152 */
153 class ShaderBlock {
154 public:
egdaniel2d721d32015-11-11 13:06:05 -0800155 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
bsalomon49f085d2014-09-05 13:34:00 -0700156 SkASSERT(builder);
joshualitt30ba4362014-08-21 20:18:45 -0700157 fBuilder->codeAppend("{");
158 }
159
160 ~ShaderBlock() {
161 fBuilder->codeAppend("}");
162 }
163 private:
egdaniel2d721d32015-11-11 13:06:05 -0800164 GrGLSLShaderBuilder* fBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700165 };
joshualitt47bb3822014-10-07 16:43:25 -0700166
joshualitt30ba4362014-08-21 20:18:45 -0700167protected:
Brian Salomon99938a82016-11-21 13:41:08 -0500168 typedef GrTAllocator<GrShaderVar> VarArray;
joshualitt47bb3822014-10-07 16:43:25 -0700169 void appendDecls(const VarArray& vars, SkString* out) const;
joshualitt30ba4362014-08-21 20:18:45 -0700170
cdaltonc08f1962016-02-12 12:14:06 -0800171 /**
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,
cdalton74b8d322016-04-11 14:47:28 -0700179 kTexelBuffer_GLSLPrivateFeature,
cdaltonc08f1962016-02-12 12:14:06 -0800180 kFramebufferFetch_GLSLPrivateFeature,
181 kNoPerspectiveInterpolation_GLSLPrivateFeature,
cdalton33ad7012016-02-22 07:55:44 -0800182 kSampleVariables_GLSLPrivateFeature,
183 kSampleMaskOverrideCoverage_GLSLPrivateFeature,
184 kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature
cdaltonc08f1962016-02-12 12:14:06 -0800185 };
186
joshualitt30ba4362014-08-21 20:18:45 -0700187 /*
joshualitt30ba4362014-08-21 20:18:45 -0700188 * A general function which enables an extension in a shader if the feature bit is not present
cdalton33ad7012016-02-22 07:55:44 -0800189 *
190 * @return true if the feature bit was not yet present, false otherwise.
joshualitt30ba4362014-08-21 20:18:45 -0700191 */
cdalton33ad7012016-02-22 07:55:44 -0800192 bool addFeature(uint32_t featureBit, const char* extensionName);
joshualitt30ba4362014-08-21 20:18:45 -0700193
cdaltone4017d82015-05-06 11:48:56 -0700194 enum InterfaceQualifier {
csmartdalton276cc412016-11-21 11:55:00 -0700195 kIn_InterfaceQualifier,
cdaltone4017d82015-05-06 11:48:56 -0700196 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
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