Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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,
119 SkBlendMode mode,
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
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++) {
315 fCompilerString.append(fShaderStrings[i].c_str(), fShaderStrings[i].size());
316 }
317
318 fFinalized = true;
319}
static void append_texture_swizzle(SkString *out, skgpu::Swizzle swizzle)
GrShaderFlags
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
const char * SkSLTypeString(SkSLType t)
SkSLType
SI T load(const P *ptr)
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
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
const char * name
Definition fuchsia.cc:50
const char * BlendFuncName(SkBlendMode mode)
Definition Blend.cpp:18
skcms_TFType
@ skcms_TFType_HLGish
@ skcms_TFType_sRGBish
@ skcms_TFType_HLGinvish
@ skcms_TFType_PQish
bool mustEnableAdvBlendEqs() const
Definition SkSLUtil.h:39
SkSL::GLSLGeneration fGLSLGeneration
Definition SkSLUtil.h:82