Flutter Engine
The Flutter Engine
GrGLSLShaderBuilder.cpp
Go to the documentation of this file.
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 */
8
10#include "modules/skcms/skcms.h"
12#include "src/gpu/Blend.h"
13#include "src/gpu/Swizzle.h"
19#include "src/sksl/SkSLGLSL.h"
20
21using namespace skia_private;
22
24 : fProgramBuilder(program)
25 , fInputs(GrGLSLProgramBuilder::kVarsPerBlock)
26 , fOutputs(GrGLSLProgramBuilder::kVarsPerBlock)
27 , fFeaturesAddedMask(0)
28 , fCodeIndex(kCode)
29 , fFinalized(false)
30 , fTmpVariableCounter(0) {
31 // We push back some placeholder pointers which will later become our header
32 for (int i = 0; i <= kCode; i++) {
34 }
35
36 this->main() = "void main() {";
37}
38
40 SkString tempDecl;
41 var.appendDecl(fProgramBuilder->shaderCaps(), &tempDecl);
42 this->codeAppendf("%s;", tempDecl.c_str());
43}
44
46 v.appendDecl(this->getProgramBuilder()->shaderCaps(), &this->definitions());
47 this->definitions().append(";");
48}
49
51 return fProgramBuilder->nameVariable(/*prefix=*/'\0', baseName);
52}
53
55 const char* mangledName,
57 this->functions().appendf("%s %s(", SkSLTypeString(returnType), mangledName);
58 for (size_t i = 0; i < args.size(); ++i) {
59 if (i > 0) {
60 this->functions().append(", ");
61 }
62 args[i].appendDecl(fProgramBuilder->shaderCaps(), &this->functions());
63 }
64
65 this->functions().append(")");
66}
67
69 const char* mangledName,
71 const char* body) {
72 this->appendFunctionDecl(returnType, mangledName, args);
73 this->functions().appendf(" {\n"
74 "%s"
75 "}\n\n", body);
76}
77
78void GrGLSLShaderBuilder::emitFunction(const char* declaration, const char* body) {
79 this->functions().appendf("%s {\n"
80 "%s"
81 "}\n\n", declaration, body);
82}
83
85 const char* mangledName,
87 this->appendFunctionDecl(returnType, mangledName, args);
88 this->functions().append(";\n");
89}
90
91void GrGLSLShaderBuilder::emitFunctionPrototype(const char* declaration) {
92 this->functions().appendf("%s\n", declaration);
93}
94
95static inline void append_texture_swizzle(SkString* out, skgpu::Swizzle swizzle) {
96 if (swizzle != skgpu::Swizzle::RGBA()) {
97 out->appendf(".%s", swizzle.asString().c_str());
98 }
99}
100
102 SamplerHandle samplerHandle,
103 const char* coordName) const {
104 const char* sampler = fProgramBuilder->samplerVariable(samplerHandle);
105 out->appendf("sample(%s, %s)", sampler, coordName);
107}
108
110 const char* coordName,
111 GrGLSLColorSpaceXformHelper* colorXformHelper) {
112 SkString lookup;
113 this->appendTextureLookup(&lookup, samplerHandle, coordName);
114 this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
115}
116
118 const char* dst,
120 SamplerHandle samplerHandle,
121 const char* coordName,
122 GrGLSLColorSpaceXformHelper* colorXformHelper) {
123 if (!dst) {
124 dst = "half4(1)";
125 }
126 SkString lookup;
127 this->codeAppendf("%s(", skgpu::BlendFuncName(mode));
128 this->appendTextureLookup(&lookup, samplerHandle, coordName);
129 this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
130 this->codeAppendf(", %s)", dst);
131}
132
134 const char* input = fProgramBuilder->inputSamplerVariable(samplerHandle);
136 load.appendf("subpassLoad(%s)", input);
138 this->codeAppend(load.c_str());
139}
140
142 const char* srcColor,
143 GrGLSLColorSpaceXformHelper* colorXformHelper) {
144 if (!colorXformHelper || colorXformHelper->isNoop()) {
145 *out = srcColor;
146 return;
147 }
148
150
151 // We define up to three helper functions, to keep things clearer. One for the source transfer
152 // function, one for the (inverse) destination transfer function, and one for the gamut xform.
153 // Any combination of these may be present, although some configurations are much more likely.
154
155 auto emitTFFunc = [this, &uniformHandler](const char* name,
156 GrGLSLProgramDataManager::UniformHandle uniform,
157 skcms_TFType tfType) {
158 const GrShaderVar gTFArgs[] = { GrShaderVar("x", SkSLType::kFloat) };
159 const char* coeffs = uniformHandler->getUniformCStr(uniform);
160 SkString body;
161 // Temporaries to make evaluation line readable. We always use the sRGBish names, so the
162 // PQ and HLG math is confusing.
163 body.appendf("float G = %s[0];", coeffs);
164 body.appendf("float A = %s[1];", coeffs);
165 body.appendf("float B = %s[2];", coeffs);
166 body.appendf("float C = %s[3];", coeffs);
167 body.appendf("float D = %s[4];", coeffs);
168 body.appendf("float E = %s[5];", coeffs);
169 body.appendf("float F = %s[6];", coeffs);
170 body.append("float s = sign(x);");
171 body.append("x = abs(x);");
172 switch (tfType) {
174 body.append("x = (x < D) ? (C * x) + F : pow(A * x + B, G) + E;");
175 break;
177 body.append("x = pow(max(A + B * pow(x, C), 0) / (D + E * pow(x, C)), F);");
178 break;
180 body.append("x = (x*A <= 1) ? pow(x*A, B) : exp((x-E)*C) + D; x *= (F+1);");
181 break;
183 body.append("x /= (F+1); x = (x <= 1) ? A * pow(x, B) : C * log(x - D) + E;");
184 break;
185 default:
186 SkASSERT(false);
187 break;
188 }
189 body.append("return s * x;");
190 SkString funcName = this->getMangledFunctionName(name);
191 this->emitFunction(SkSLType::kFloat, funcName.c_str(), {gTFArgs, std::size(gTFArgs)},
192 body.c_str());
193 return funcName;
194 };
195
196 SkString srcTFFuncName;
197 if (colorXformHelper->applySrcTF()) {
198 srcTFFuncName = emitTFFunc("src_tf", colorXformHelper->srcTFUniform(),
199 colorXformHelper->srcTFType());
200 }
201
202 SkString dstTFFuncName;
203 if (colorXformHelper->applyDstTF()) {
204 dstTFFuncName = emitTFFunc("dst_tf", colorXformHelper->dstTFUniform(),
205 colorXformHelper->dstTFType());
206 }
207
208 SkString gamutXformFuncName;
209 if (colorXformHelper->applyGamutXform()) {
210 const GrShaderVar gGamutXformArgs[] = { GrShaderVar("color", SkSLType::kFloat4) };
211 const char* xform = uniformHandler->getUniformCStr(colorXformHelper->gamutXformUniform());
212 SkString body;
213 body.appendf("color.rgb = (%s * color.rgb);", xform);
214 body.append("return color;");
215 gamutXformFuncName = this->getMangledFunctionName("gamut_xform");
216 this->emitFunction(SkSLType::kFloat4, gamutXformFuncName.c_str(),
217 {gGamutXformArgs, std::size(gGamutXformArgs)}, body.c_str());
218 }
219
220 // Now define a wrapper function that applies all the intermediate steps
221 {
222 const GrShaderVar gColorXformArgs[] = { GrShaderVar("color", SkSLType::kFloat4) };
223 SkString body;
224 if (colorXformHelper->applyUnpremul()) {
225 body.append("color = unpremul(color);");
226 }
227 if (colorXformHelper->applySrcTF()) {
228 body.appendf("color.r = %s(color.r);", srcTFFuncName.c_str());
229 body.appendf("color.g = %s(color.g);", srcTFFuncName.c_str());
230 body.appendf("color.b = %s(color.b);", srcTFFuncName.c_str());
231 }
232 if (colorXformHelper->applyGamutXform()) {
233 body.appendf("color = %s(color);", gamutXformFuncName.c_str());
234 }
235 if (colorXformHelper->applyDstTF()) {
236 body.appendf("color.r = %s(color.r);", dstTFFuncName.c_str());
237 body.appendf("color.g = %s(color.g);", dstTFFuncName.c_str());
238 body.appendf("color.b = %s(color.b);", dstTFFuncName.c_str());
239 }
240 if (colorXformHelper->applyPremul()) {
241 body.append("color.rgb *= color.a;");
242 }
243 body.append("return half4(color);");
244 SkString colorXformFuncName = this->getMangledFunctionName("color_xform");
245 this->emitFunction(SkSLType::kHalf4, colorXformFuncName.c_str(),
246 {gColorXformArgs, std::size(gColorXformArgs)}, body.c_str());
247 out->appendf("%s(%s)", colorXformFuncName.c_str(), srcColor);
248 }
249}
250
252 GrGLSLColorSpaceXformHelper* colorXformHelper) {
253 SkString xform;
254 this->appendColorGamutXform(&xform, srcColor, colorXformHelper);
255 this->codeAppend(xform.c_str());
256}
257
258bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
259 if (featureBit & fFeaturesAddedMask) {
260 return false;
261 }
262 this->extensions().appendf("#extension %s: require\n", extensionName);
263 fFeaturesAddedMask |= featureBit;
264 return true;
265}
266
268 for (const auto& v : vars.items()) {
269 v.appendDecl(fProgramBuilder->shaderCaps(), out);
270 out->append(";\n");
271 }
272}
273
277 fLayoutParams[interface].push_back() = param;
278}
279
281 static const char* interfaceQualifierNames[] = {
282 "in",
283 "out"
284 };
285
286 for (int interface = 0; interface <= kLastInterfaceQualifier; ++interface) {
287 const TArray<SkString>& params = fLayoutParams[interface];
288 if (params.empty()) {
289 continue;
290 }
291 this->layoutQualifiers().appendf("layout(%s", params[0].c_str());
292 for (int i = 1; i < params.size(); ++i) {
293 this->layoutQualifiers().appendf(", %s", params[i].c_str());
294 }
295 this->layoutQualifiers().appendf(") %s;\n", interfaceQualifierNames[interface]);
296 }
297
300 static_assert(std::size(interfaceQualifierNames) == kLastInterfaceQualifier + 1);
301}
302
303void GrGLSLShaderBuilder::finalize(uint32_t visibility) {
306 SkASSERT(visibility);
308 this->appendDecls(fInputs, &this->inputs());
309 this->appendDecls(fOutputs, &this->outputs());
310 this->onFinalize();
311 // append the 'footer' to code
312 this->code().append("}");
313
314 for (int i = 0; i <= fCodeIndex; i++) {
316 }
317
318 fFinalized = true;
319}
static void append_texture_swizzle(SkString *out, skgpu::Swizzle swizzle)
GrShaderFlags
Definition: GrTypesPriv.h:284
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
const char * SkSLTypeString(SkSLType t)
SkSLType
SI T load(const P *ptr)
Definition: Transform_inl.h:98
GrGLSLProgramDataManager::UniformHandle gamutXformUniform() const
GrGLSLProgramDataManager::UniformHandle srcTFUniform() const
GrGLSLProgramDataManager::UniformHandle dstTFUniform() const
SkString nameVariable(char prefix, const char *name, bool mangle=true)
virtual GrGLSLUniformHandler * uniformHandler()=0
const char * samplerVariable(SamplerHandle handle) const
skgpu::Swizzle samplerSwizzle(SamplerHandle handle) const
const GrShaderCaps * shaderCaps() const
const char * inputSamplerVariable(SamplerHandle handle) const
skgpu::Swizzle inputSamplerSwizzle(SamplerHandle handle) const
void appendUniformDecls(GrShaderFlags visibility, SkString *) const
virtual void onFinalize()=0
void emitFunction(SkSLType returnType, const char *mangledName, SkSpan< const GrShaderVar > args, const char *body)
void appendDecls(const VarArray &vars, SkString *out) const
void addLayoutQualifier(const char *param, InterfaceQualifier)
GrGLSLUniformHandler::SamplerHandle SamplerHandle
void declareGlobal(const GrShaderVar &)
GrGLSLShaderBuilder(GrGLSLProgramBuilder *program)
this code().appendVAList(format
void declAppend(const GrShaderVar &var)
bool addFeature(uint32_t featureBit, const char *extensionName)
void finalize(uint32_t visibility)
void codeAppend(const char *str)
void appendColorGamutXform(SkString *out, const char *srcColor, GrGLSLColorSpaceXformHelper *colorXformHelper)
this definitions().appendVAList(fmt
skia_private::STArray< kPrealloc, SkString > fShaderStrings
void appendTextureLookup(SkString *out, SamplerHandle, const char *coordName) const
SkString getMangledFunctionName(const char *baseName)
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
void appendInputLoad(SamplerHandle)
GrGLSLProgramBuilder * fProgramBuilder
void appendFunctionDecl(SkSLType returnType, const char *mangledName, SkSpan< const GrShaderVar > args)
skia_private::STArray< 1, SkString > fLayoutParams[kLastInterfaceQualifier+1]
void appendTextureLookupAndBlend(const char *dst, SkBlendMode, SamplerHandle, const char *coordName, GrGLSLColorSpaceXformHelper *colorXformHelper=nullptr)
GrGLSLProgramBuilder * getProgramBuilder()
void emitFunctionPrototype(SkSLType returnType, const char *mangledName, SkSpan< const GrShaderVar > args)
virtual const char * getUniformCStr(UniformHandle u) const =0
void appendDecl(const GrShaderCaps *, SkString *out) const
Definition: GrShaderVar.cpp:23
void append(const char text[])
Definition: SkString.h:203
const char * c_str() const
Definition: SkString.h:133
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
SkString asString() const
Definition: Swizzle.cpp:46
static constexpr Swizzle RGBA()
Definition: Swizzle.h:66
const EmbeddedViewParams * params
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
const char * BlendFuncName(SkBlendMode mode)
Definition: Blend.cpp:18
Definition: __init__.py:1
skcms_TFType
Definition: skcms_public.h:54
@ skcms_TFType_HLGish
Definition: skcms_public.h:58
@ skcms_TFType_sRGBish
Definition: skcms_public.h:56
@ skcms_TFType_HLGinvish
Definition: skcms_public.h:59
@ skcms_TFType_PQish
Definition: skcms_public.h:57
bool mustEnableAdvBlendEqs() const
Definition: SkSLUtil.h:39
SkSL::GLSLGeneration fGLSLGeneration
Definition: SkSLUtil.h:82