blob: 9d3cc48cbc6851c0dd6624677960e49726a53337 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/SkTDArray.h"
12#include "src/gpu/GrAllocator.h"
13#include "src/gpu/GrShaderVar.h"
14#include "src/gpu/glsl/GrGLSLUniformHandler.h"
15#include "src/sksl/SkSLString.h"
joshualitt30ba4362014-08-21 20:18:45 -070016
17#include <stdarg.h>
18
brianosman77320db2016-09-07 08:09:10 -070019class GrGLSLColorSpaceXformHelper;
20
joshualitt30ba4362014-08-21 20:18:45 -070021/**
22 base class for all shaders builders
23*/
egdaniel2d721d32015-11-11 13:06:05 -080024class GrGLSLShaderBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070025public:
egdaniel2d721d32015-11-11 13:06:05 -080026 GrGLSLShaderBuilder(GrGLSLProgramBuilder* program);
27 virtual ~GrGLSLShaderBuilder() {}
joshualitt30ba4362014-08-21 20:18:45 -070028
Brian Salomonf9f45122016-11-29 11:59:17 -050029 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
egdaniel09aa1fc2016-04-20 07:09:46 -070030
joshualitt30ba4362014-08-21 20:18:45 -070031 /** 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
Brian Salomon101b8442016-11-18 11:58:54 -050033 order of the result depends on the GrProcessor::TextureSampler associated with the
34 SamplerHandle.
egdaniel7dc4bd02015-10-29 07:57:01 -070035 */
joshualitt30ba4362014-08-21 20:18:45 -070036 void appendTextureLookup(SkString* out,
egdaniel09aa1fc2016-04-20 07:09:46 -070037 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070038 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040039 GrSLType coordType = kHalf2_GrSLType) const;
joshualitt30ba4362014-08-21 20:18:45 -070040
cdaltonf8a6ce82016-04-11 13:02:05 -070041 /** Version of above that appends the result to the shader code instead.*/
egdaniel09aa1fc2016-04-20 07:09:46 -070042 void appendTextureLookup(SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070043 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040044 GrSLType coordType = kHalf2_GrSLType,
brianosman77320db2016-09-07 08:09:10 -070045 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
joshualitt30ba4362014-08-21 20:18:45 -070046
47
48 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
Ethan Nicholasf7b88202017-09-18 14:10:39 -040049 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
egdaniel7dc4bd02015-10-29 07:57:01 -070051 appendTextureLookup were called. */
joshualitt30ba4362014-08-21 20:18:45 -070052 void appendTextureLookupAndModulate(const char* modulation,
egdaniel09aa1fc2016-04-20 07:09:46 -070053 SamplerHandle,
joshualitt30ba4362014-08-21 20:18:45 -070054 const char* coordName,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040055 GrSLType coordType = kHalf2_GrSLType,
brianosman77320db2016-09-07 08:09:10 -070056 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);
joshualitt30ba4362014-08-21 20:18:45 -070067
joshualitt30ba4362014-08-21 20:18:45 -070068 /**
ethannicholas5961bc92016-10-12 06:39:56 -070069 * Adds a constant declaration to the top of the shader.
cdaltond36f2c42016-02-11 14:10:38 -080070 */
ethannicholas5961bc92016-10-12 06:39:56 -070071 void defineConstant(const char* type, const char* name, const char* value) {
72 this->definitions().appendf("const %s %s = %s;\n", type, name, value);
cdaltond36f2c42016-02-11 14:10:38 -080073 }
74
ethannicholas5961bc92016-10-12 06:39:56 -070075 void defineConstant(const char* name, int value) {
76 this->definitions().appendf("const int %s = %i;\n", name, value);
cdaltond36f2c42016-02-11 14:10:38 -080077 }
78
ethannicholas5961bc92016-10-12 06:39:56 -070079 void defineConstant(const char* name, float value) {
80 this->definitions().appendf("const float %s = %f;\n", name, value);
81 }
82
83 void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
84 this->definitions().appendf("const %s %s = ", type, name);
cdaltond36f2c42016-02-11 14:10:38 -080085 va_list args;
ethannicholas5961bc92016-10-12 06:39:56 -070086 va_start(args, fmt);
87 this->definitions().appendVAList(fmt, args);
cdaltond36f2c42016-02-11 14:10:38 -080088 va_end(args);
ethannicholas5961bc92016-10-12 06:39:56 -070089 this->definitions().append(";\n");
cdaltond36f2c42016-02-11 14:10:38 -080090 }
91
csmartdalton75864b02017-02-09 09:47:21 -050092 void declareGlobal(const GrShaderVar&);
93
cdaltond36f2c42016-02-11 14:10:38 -080094 /**
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
Ethan Nicholas00543112018-07-31 09:44:36 -0400106 void codeAppend(const char* str, size_t length) { this->code().append(str, length); }
107
joshualitt30ba4362014-08-21 20:18:45 -0700108 void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
109 va_list args;
110 va_start(args, format);
joshualitt43466a12015-02-13 17:18:27 -0800111 this->code().prependVAList(format, args);
joshualitt30ba4362014-08-21 20:18:45 -0700112 va_end(args);
113 }
114
egdanielb2f94d12014-08-29 10:08:36 -0700115 /**
116 * Appends a variable declaration to one of the shaders
117 */
Brian Salomon99938a82016-11-21 13:41:08 -0500118 void declAppend(const GrShaderVar& var);
egdanielb2f94d12014-08-29 10:08:36 -0700119
joshualitt30ba4362014-08-21 20:18:45 -0700120 /** Emits a helper function outside of main() in the fragment shader. */
121 void emitFunction(GrSLType returnType,
122 const char* name,
123 int argCnt,
Brian Salomon99938a82016-11-21 13:41:08 -0500124 const GrShaderVar* args,
joshualitt30ba4362014-08-21 20:18:45 -0700125 const char* body,
126 SkString* outName);
127
128 /*
egdaniel574a4c12015-11-02 06:22:44 -0800129 * Combines the various parts of the shader to create a single finalized shader string.
130 */
131 void finalize(uint32_t visibility);
132
133 /*
joshualitt30ba4362014-08-21 20:18:45 -0700134 * Get parent builder for adding uniforms
135 */
egdaniel8dcdedc2015-11-11 06:27:20 -0800136 GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
joshualitt30ba4362014-08-21 20:18:45 -0700137
138 /**
joshualitt47bb3822014-10-07 16:43:25 -0700139 * Helper for begining and ending a block in the shader code.
joshualitt30ba4362014-08-21 20:18:45 -0700140 */
141 class ShaderBlock {
142 public:
egdaniel2d721d32015-11-11 13:06:05 -0800143 ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
bsalomon49f085d2014-09-05 13:34:00 -0700144 SkASSERT(builder);
joshualitt30ba4362014-08-21 20:18:45 -0700145 fBuilder->codeAppend("{");
146 }
147
148 ~ShaderBlock() {
149 fBuilder->codeAppend("}");
150 }
151 private:
egdaniel2d721d32015-11-11 13:06:05 -0800152 GrGLSLShaderBuilder* fBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700153 };
joshualitt47bb3822014-10-07 16:43:25 -0700154
joshualitt30ba4362014-08-21 20:18:45 -0700155protected:
Brian Salomon99938a82016-11-21 13:41:08 -0500156 typedef GrTAllocator<GrShaderVar> VarArray;
joshualitt47bb3822014-10-07 16:43:25 -0700157 void appendDecls(const VarArray& vars, SkString* out) const;
joshualitt30ba4362014-08-21 20:18:45 -0700158
cdaltonc08f1962016-02-12 12:14:06 -0800159 /**
160 * Features that should only be enabled internally by the builders.
161 */
162 enum GLSLPrivateFeature {
163 kFragCoordConventions_GLSLPrivateFeature,
164 kBlendEquationAdvanced_GLSLPrivateFeature,
165 kBlendFuncExtended_GLSLPrivateFeature,
cdaltonc08f1962016-02-12 12:14:06 -0800166 kFramebufferFetch_GLSLPrivateFeature,
167 kNoPerspectiveInterpolation_GLSLPrivateFeature,
Chris Daltond31b5e72019-02-26 18:02:16 -0700168 kSampleVariables_GLSLPrivateFeature,
169 kLastGLSLPrivateFeature = kSampleVariables_GLSLPrivateFeature
cdaltonc08f1962016-02-12 12:14:06 -0800170 };
171
joshualitt30ba4362014-08-21 20:18:45 -0700172 /*
joshualitt30ba4362014-08-21 20:18:45 -0700173 * A general function which enables an extension in a shader if the feature bit is not present
cdalton33ad7012016-02-22 07:55:44 -0800174 *
175 * @return true if the feature bit was not yet present, false otherwise.
joshualitt30ba4362014-08-21 20:18:45 -0700176 */
cdalton33ad7012016-02-22 07:55:44 -0800177 bool addFeature(uint32_t featureBit, const char* extensionName);
joshualitt30ba4362014-08-21 20:18:45 -0700178
cdaltone4017d82015-05-06 11:48:56 -0700179 enum InterfaceQualifier {
csmartdalton276cc412016-11-21 11:55:00 -0700180 kIn_InterfaceQualifier,
cdaltone4017d82015-05-06 11:48:56 -0700181 kOut_InterfaceQualifier,
182 kLastInterfaceQualifier = kOut_InterfaceQualifier
183 };
184
185 /*
186 * A low level function to build default layout qualifiers.
187 *
188 * e.g. layout(param1, param2, ...) out;
189 *
190 * GLSL allows default layout qualifiers for in, out, and uniform.
191 */
192 void addLayoutQualifier(const char* param, InterfaceQualifier);
193
194 void compileAndAppendLayoutQualifiers();
195
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000196 void nextStage() {
197 fShaderStrings.push_back();
198 fCodeIndex++;
199 }
200
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400201 void deleteStage() {
202 fShaderStrings.pop_back();
203 fCodeIndex--;
204 }
205
joshualitt43466a12015-02-13 17:18:27 -0800206 SkString& extensions() { return fShaderStrings[kExtensions]; }
cdaltond36f2c42016-02-11 14:10:38 -0800207 SkString& definitions() { return fShaderStrings[kDefinitions]; }
joshualitt43466a12015-02-13 17:18:27 -0800208 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
cdaltone4017d82015-05-06 11:48:56 -0700209 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
joshualitt43466a12015-02-13 17:18:27 -0800210 SkString& uniforms() { return fShaderStrings[kUniforms]; }
211 SkString& inputs() { return fShaderStrings[kInputs]; }
212 SkString& outputs() { return fShaderStrings[kOutputs]; }
213 SkString& functions() { return fShaderStrings[kFunctions]; }
214 SkString& main() { return fShaderStrings[kMain]; }
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000215 SkString& code() { return fShaderStrings[fCodeIndex]; }
egdaniel574a4c12015-11-02 06:22:44 -0800216
217 virtual void onFinalize() = 0;
joshualitt43466a12015-02-13 17:18:27 -0800218
219 enum {
joshualitt43466a12015-02-13 17:18:27 -0800220 kExtensions,
cdaltond36f2c42016-02-11 14:10:38 -0800221 kDefinitions,
joshualitt43466a12015-02-13 17:18:27 -0800222 kPrecisionQualifier,
cdaltone4017d82015-05-06 11:48:56 -0700223 kLayoutQualifiers,
joshualitt43466a12015-02-13 17:18:27 -0800224 kUniforms,
225 kInputs,
226 kOutputs,
227 kFunctions,
228 kMain,
229 kCode,
Brian Osman389b4b22019-03-18 16:45:25 -0400230
231 kPrealloc = kCode + 6, // 6 == Reasonable upper bound on number of processor stages
joshualitt43466a12015-02-13 17:18:27 -0800232 };
233
egdaniel8dcdedc2015-11-11 06:27:20 -0800234 GrGLSLProgramBuilder* fProgramBuilder;
Brian Osman6c431d52019-04-15 16:31:54 -0400235 SkSL::String fCompilerString;
Brian Osman389b4b22019-03-18 16:45:25 -0400236 SkSTArray<kPrealloc, SkString> fShaderStrings;
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000237 SkString fCode;
238 SkString fFunctions;
239 SkString fExtensions;
joshualitt30ba4362014-08-21 20:18:45 -0700240
241 VarArray fInputs;
242 VarArray fOutputs;
243 uint32_t fFeaturesAddedMask;
cdaltone4017d82015-05-06 11:48:56 -0700244 SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
joshualitt43466a12015-02-13 17:18:27 -0800245 int fCodeIndex;
246 bool fFinalized;
247
Chris Dalton4c239342018-04-05 18:43:40 -0600248 friend class GrCCCoverageProcessor; // to access code().
egdanielfa896322016-01-13 12:19:30 -0800249 friend class GrGLSLProgramBuilder;
joshualitt43466a12015-02-13 17:18:27 -0800250 friend class GrGLProgramBuilder;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400251 friend class GrDawnProgramBuilder;
cdaltonc08f1962016-02-12 12:14:06 -0800252 friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.
kkinnunen7aedda52015-06-29 23:01:28 -0700253 friend class GrGLPathProgramBuilder; // to access fInputs.
egdaniel22281c12016-03-23 13:49:40 -0700254 friend class GrVkPipelineStateBuilder;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400255 friend class GrMtlPipelineStateBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700256};
joshualitt30ba4362014-08-21 20:18:45 -0700257#endif