1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkStringView.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCpu.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOpts.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLCompiler.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLFileOutputStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLStringStream.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLUtil.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLCodeGenTypes.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLGLSLCodeGenerator.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLHLSLCodeGenerator.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLMetalCodeGenerator.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLRasterPipelineCodeGenerator.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLSPIRVCodeGenerator.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLSPIRVValidator.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLWGSLCodeGenerator.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLWGSLValidator.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLFunctionDeclaration.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgram.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLVarDeclarations.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/tracing/SkSLDebugTracePriv.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkShaderUtils.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "tools/skslc/ProcessWorklist.h"
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker #include "spirv-tools/libspirv.hpp"
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker #include <fstream>
37*c8dee2aaSAndroid Build Coastguard Worker #include <limits.h>
38*c8dee2aaSAndroid Build Coastguard Worker #include <optional>
39*c8dee2aaSAndroid Build Coastguard Worker #include <stdarg.h>
40*c8dee2aaSAndroid Build Coastguard Worker #include <stdio.h>
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_COMPILE_WITH_GN)
43*c8dee2aaSAndroid Build Coastguard Worker namespace SkOpts {
44*c8dee2aaSAndroid Build Coastguard Worker size_t raster_pipeline_highp_stride = 1;
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker
SkDebugf(const char format[],...)47*c8dee2aaSAndroid Build Coastguard Worker void SkDebugf(const char format[], ...) {
48*c8dee2aaSAndroid Build Coastguard Worker va_list args;
49*c8dee2aaSAndroid Build Coastguard Worker va_start(args, format);
50*c8dee2aaSAndroid Build Coastguard Worker vfprintf(stderr, format, args);
51*c8dee2aaSAndroid Build Coastguard Worker va_end(args);
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker #endif
54*c8dee2aaSAndroid Build Coastguard Worker
as_SkWStream(SkSL::OutputStream & s)55*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkWStream> as_SkWStream(SkSL::OutputStream& s) {
56*c8dee2aaSAndroid Build Coastguard Worker struct Adapter : public SkWStream {
57*c8dee2aaSAndroid Build Coastguard Worker public:
58*c8dee2aaSAndroid Build Coastguard Worker Adapter(SkSL::OutputStream& out) : fOut(out), fBytesWritten(0) {}
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker bool write(const void* buffer, size_t size) override {
61*c8dee2aaSAndroid Build Coastguard Worker fOut.write(buffer, size);
62*c8dee2aaSAndroid Build Coastguard Worker fBytesWritten += size;
63*c8dee2aaSAndroid Build Coastguard Worker return true;
64*c8dee2aaSAndroid Build Coastguard Worker }
65*c8dee2aaSAndroid Build Coastguard Worker void flush() override {}
66*c8dee2aaSAndroid Build Coastguard Worker size_t bytesWritten() const override { return fBytesWritten; }
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker private:
69*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& fOut;
70*c8dee2aaSAndroid Build Coastguard Worker size_t fBytesWritten;
71*c8dee2aaSAndroid Build Coastguard Worker };
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<Adapter>(s);
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker
consume_suffix(std::string * str,const char suffix[])76*c8dee2aaSAndroid Build Coastguard Worker static bool consume_suffix(std::string* str, const char suffix[]) {
77*c8dee2aaSAndroid Build Coastguard Worker if (!skstd::ends_with(*str, suffix)) {
78*c8dee2aaSAndroid Build Coastguard Worker return false;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker str->resize(str->length() - strlen(suffix));
81*c8dee2aaSAndroid Build Coastguard Worker return true;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker class ShaderCapsTestFactory : public SkSL::ShaderCapsFactory {
85*c8dee2aaSAndroid Build Coastguard Worker public:
AddAndTrueToLoopCondition()86*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* AddAndTrueToLoopCondition() {
87*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = []{
88*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
89*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
90*c8dee2aaSAndroid Build Coastguard Worker caps->fAddAndTrueToLoopCondition = true;
91*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
92*c8dee2aaSAndroid Build Coastguard Worker }();
93*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker
CannotUseFractForNegativeValues()96*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* CannotUseFractForNegativeValues() {
97*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
98*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
99*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
100*c8dee2aaSAndroid Build Coastguard Worker caps->fCanUseFractForNegativeValues = false;
101*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
102*c8dee2aaSAndroid Build Coastguard Worker }();
103*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
CannotUseFragCoord()106*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* CannotUseFragCoord() {
107*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
108*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
109*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
110*c8dee2aaSAndroid Build Coastguard Worker caps->fCanUseFragCoord = false;
111*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
112*c8dee2aaSAndroid Build Coastguard Worker }();
113*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
CannotUseMinAndAbsTogether()116*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* CannotUseMinAndAbsTogether() {
117*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
118*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
119*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
120*c8dee2aaSAndroid Build Coastguard Worker caps->fCanUseMinAndAbsTogether = false;
121*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
122*c8dee2aaSAndroid Build Coastguard Worker }();
123*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker
CannotUseVoidInSequenceExpressions()126*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* CannotUseVoidInSequenceExpressions() {
127*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
128*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
129*c8dee2aaSAndroid Build Coastguard Worker caps->fCanUseVoidInSequenceExpressions = false;
130*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
131*c8dee2aaSAndroid Build Coastguard Worker }();
132*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker
DualSourceBlending()136*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* DualSourceBlending() {
137*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
138*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
139*c8dee2aaSAndroid Build Coastguard Worker caps->fDualSourceBlendingSupport = true;
140*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
141*c8dee2aaSAndroid Build Coastguard Worker }();
142*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker
EmulateAbsIntFunction()145*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* EmulateAbsIntFunction() {
146*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
147*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
148*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
149*c8dee2aaSAndroid Build Coastguard Worker caps->fEmulateAbsIntFunction = true;
150*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
151*c8dee2aaSAndroid Build Coastguard Worker }();
152*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker
FramebufferFetchSupport()155*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* FramebufferFetchSupport() {
156*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
157*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
158*c8dee2aaSAndroid Build Coastguard Worker caps->fFBFetchSupport = true;
159*c8dee2aaSAndroid Build Coastguard Worker caps->fFBFetchColorName = "FramebufferFragColor"; // a nice, backend-neutral name
160*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
161*c8dee2aaSAndroid Build Coastguard Worker }();
162*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker
MustDeclareFragmentFrontFacing()165*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* MustDeclareFragmentFrontFacing() {
166*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
167*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
168*c8dee2aaSAndroid Build Coastguard Worker caps->fMustDeclareFragmentFrontFacing = true;
169*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
170*c8dee2aaSAndroid Build Coastguard Worker }();
171*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
MustForceNegatedAtanParamToFloat()174*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* MustForceNegatedAtanParamToFloat() {
175*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
176*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
177*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
178*c8dee2aaSAndroid Build Coastguard Worker caps->fMustForceNegatedAtanParamToFloat = true;
179*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
180*c8dee2aaSAndroid Build Coastguard Worker }();
181*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker
MustForceNegatedLdexpParamToMultiply()184*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* MustForceNegatedLdexpParamToMultiply() {
185*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
186*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
187*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
188*c8dee2aaSAndroid Build Coastguard Worker caps->fMustForceNegatedLdexpParamToMultiply = true;
189*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
190*c8dee2aaSAndroid Build Coastguard Worker }();
191*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker
MustGuardDivisionEvenAfterExplicitZeroCheck()194*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* MustGuardDivisionEvenAfterExplicitZeroCheck() {
195*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
196*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
197*c8dee2aaSAndroid Build Coastguard Worker caps->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
198*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
199*c8dee2aaSAndroid Build Coastguard Worker }();
200*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker
NoBuiltinDeterminantSupport()203*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* NoBuiltinDeterminantSupport() {
204*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
205*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
206*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
207*c8dee2aaSAndroid Build Coastguard Worker caps->fBuiltinDeterminantSupport = false;
208*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
209*c8dee2aaSAndroid Build Coastguard Worker }();
210*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker
NoBuiltinFMASupport()213*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* NoBuiltinFMASupport() {
214*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
215*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
216*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
217*c8dee2aaSAndroid Build Coastguard Worker caps->fBuiltinFMASupport = false;
218*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
219*c8dee2aaSAndroid Build Coastguard Worker }();
220*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
NoExternalTextureSupport()223*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* NoExternalTextureSupport() {
224*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
225*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
226*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
227*c8dee2aaSAndroid Build Coastguard Worker caps->fExternalTextureSupport = false;
228*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
229*c8dee2aaSAndroid Build Coastguard Worker }();
230*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker
RemovePowWithConstantExponent()233*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* RemovePowWithConstantExponent() {
234*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
235*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
236*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
237*c8dee2aaSAndroid Build Coastguard Worker caps->fRemovePowWithConstantExponent = true;
238*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
239*c8dee2aaSAndroid Build Coastguard Worker }();
240*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker
RewriteDoWhileLoops()243*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* RewriteDoWhileLoops() {
244*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
245*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
246*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
247*c8dee2aaSAndroid Build Coastguard Worker caps->fRewriteDoWhileLoops = true;
248*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
249*c8dee2aaSAndroid Build Coastguard Worker }();
250*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker
RewriteMatrixComparisons()253*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* RewriteMatrixComparisons() {
254*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
255*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
256*c8dee2aaSAndroid Build Coastguard Worker caps->fRewriteMatrixComparisons = true;
257*c8dee2aaSAndroid Build Coastguard Worker caps->fUsesPrecisionModifiers = true;
258*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
259*c8dee2aaSAndroid Build Coastguard Worker }();
260*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker
RewriteMatrixVectorMultiply()263*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* RewriteMatrixVectorMultiply() {
264*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
265*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
266*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
267*c8dee2aaSAndroid Build Coastguard Worker caps->fRewriteMatrixVectorMultiply = true;
268*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
269*c8dee2aaSAndroid Build Coastguard Worker }();
270*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker
RewriteSwitchStatements()273*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* RewriteSwitchStatements() {
274*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
275*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
276*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
277*c8dee2aaSAndroid Build Coastguard Worker caps->fRewriteSwitchStatements = true;
278*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
279*c8dee2aaSAndroid Build Coastguard Worker }();
280*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
281*c8dee2aaSAndroid Build Coastguard Worker }
282*c8dee2aaSAndroid Build Coastguard Worker
SampleMaskSupport()283*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* SampleMaskSupport() {
284*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
285*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
286*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
287*c8dee2aaSAndroid Build Coastguard Worker caps->fShaderDerivativeSupport = true;
288*c8dee2aaSAndroid Build Coastguard Worker caps->fSampleMaskSupport = true;
289*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
290*c8dee2aaSAndroid Build Coastguard Worker }();
291*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker
ShaderDerivativeExtensionString()294*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* ShaderDerivativeExtensionString() {
295*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
296*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
297*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
298*c8dee2aaSAndroid Build Coastguard Worker caps->fShaderDerivativeSupport = true;
299*c8dee2aaSAndroid Build Coastguard Worker caps->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
300*c8dee2aaSAndroid Build Coastguard Worker caps->fUsesPrecisionModifiers = true;
301*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
302*c8dee2aaSAndroid Build Coastguard Worker }();
303*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
304*c8dee2aaSAndroid Build Coastguard Worker }
305*c8dee2aaSAndroid Build Coastguard Worker
UnfoldShortCircuitAsTernary()306*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* UnfoldShortCircuitAsTernary() {
307*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
308*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
309*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
310*c8dee2aaSAndroid Build Coastguard Worker caps->fUnfoldShortCircuitAsTernary = true;
311*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
312*c8dee2aaSAndroid Build Coastguard Worker }();
313*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker
UsesPrecisionModifiers()316*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* UsesPrecisionModifiers() {
317*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
318*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
319*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 400";
320*c8dee2aaSAndroid Build Coastguard Worker caps->fUsesPrecisionModifiers = true;
321*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
322*c8dee2aaSAndroid Build Coastguard Worker }();
323*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
324*c8dee2aaSAndroid Build Coastguard Worker }
325*c8dee2aaSAndroid Build Coastguard Worker
Version110()326*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* Version110() {
327*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
328*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
329*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 110";
330*c8dee2aaSAndroid Build Coastguard Worker caps->fGLSLGeneration = SkSL::GLSLGeneration::k110;
331*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
332*c8dee2aaSAndroid Build Coastguard Worker }();
333*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker
Version450Core()336*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* Version450Core() {
337*c8dee2aaSAndroid Build Coastguard Worker static const SkSL::ShaderCaps* sCaps = [] {
338*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::ShaderCaps> caps = MakeShaderCaps();
339*c8dee2aaSAndroid Build Coastguard Worker caps->fVersionDeclString = "#version 450 core";
340*c8dee2aaSAndroid Build Coastguard Worker return caps.release();
341*c8dee2aaSAndroid Build Coastguard Worker }();
342*c8dee2aaSAndroid Build Coastguard Worker return sCaps;
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker };
345*c8dee2aaSAndroid Build Coastguard Worker
346*c8dee2aaSAndroid Build Coastguard Worker // Given a string containing an SkSL program, searches for a #pragma settings comment, like so:
347*c8dee2aaSAndroid Build Coastguard Worker // /*#pragma settings Default Sharpen*/
348*c8dee2aaSAndroid Build Coastguard Worker // The passed-in Settings object will be updated accordingly. Any number of options can be provided.
detect_shader_settings(const std::string & text,SkSL::ProgramSettings * settings,const SkSL::ShaderCaps ** caps,std::unique_ptr<SkSL::DebugTracePriv> * debugTrace)349*c8dee2aaSAndroid Build Coastguard Worker static bool detect_shader_settings(const std::string& text,
350*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramSettings* settings,
351*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps** caps,
352*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::DebugTracePriv>* debugTrace) {
353*c8dee2aaSAndroid Build Coastguard Worker using Factory = ShaderCapsTestFactory;
354*c8dee2aaSAndroid Build Coastguard Worker
355*c8dee2aaSAndroid Build Coastguard Worker // Find a matching comment and isolate the name portion.
356*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kPragmaSettings[] = "/*#pragma settings ";
357*c8dee2aaSAndroid Build Coastguard Worker const char* settingsPtr = strstr(text.c_str(), kPragmaSettings);
358*c8dee2aaSAndroid Build Coastguard Worker if (settingsPtr != nullptr) {
359*c8dee2aaSAndroid Build Coastguard Worker // Subtract one here in order to preserve the leading space, which is necessary to allow
360*c8dee2aaSAndroid Build Coastguard Worker // consumeSuffix to find the first item.
361*c8dee2aaSAndroid Build Coastguard Worker settingsPtr += strlen(kPragmaSettings) - 1;
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker const char* settingsEnd = strstr(settingsPtr, "*/");
364*c8dee2aaSAndroid Build Coastguard Worker if (settingsEnd != nullptr) {
365*c8dee2aaSAndroid Build Coastguard Worker std::string settingsText{settingsPtr, size_t(settingsEnd - settingsPtr)};
366*c8dee2aaSAndroid Build Coastguard Worker
367*c8dee2aaSAndroid Build Coastguard Worker // Apply settings as requested. Since they can come in any order, repeat until we've
368*c8dee2aaSAndroid Build Coastguard Worker // consumed them all.
369*c8dee2aaSAndroid Build Coastguard Worker for (;;) {
370*c8dee2aaSAndroid Build Coastguard Worker const size_t startingLength = settingsText.length();
371*c8dee2aaSAndroid Build Coastguard Worker
372*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " AddAndTrueToLoopCondition")) {
373*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::AddAndTrueToLoopCondition();
374*c8dee2aaSAndroid Build Coastguard Worker }
375*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " CannotUseFractForNegativeValues")) {
376*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::CannotUseFractForNegativeValues();
377*c8dee2aaSAndroid Build Coastguard Worker }
378*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " CannotUseFragCoord")) {
379*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::CannotUseFragCoord();
380*c8dee2aaSAndroid Build Coastguard Worker }
381*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " CannotUseMinAndAbsTogether")) {
382*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::CannotUseMinAndAbsTogether();
383*c8dee2aaSAndroid Build Coastguard Worker }
384*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " CannotUseVoidInSequenceExpressions")) {
385*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::CannotUseVoidInSequenceExpressions();
386*c8dee2aaSAndroid Build Coastguard Worker }
387*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " DualSourceBlending")) {
388*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::DualSourceBlending();
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " Default")) {
391*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::Default();
392*c8dee2aaSAndroid Build Coastguard Worker }
393*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " EmulateAbsIntFunction")) {
394*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::EmulateAbsIntFunction();
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " FramebufferFetchSupport")) {
397*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::FramebufferFetchSupport();
398*c8dee2aaSAndroid Build Coastguard Worker }
399*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " MustGuardDivisionEvenAfterExplicitZeroCheck")) {
400*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::MustGuardDivisionEvenAfterExplicitZeroCheck();
401*c8dee2aaSAndroid Build Coastguard Worker }
402*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " MustDeclareFragmentFrontFacing")) {
403*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::MustDeclareFragmentFrontFacing();
404*c8dee2aaSAndroid Build Coastguard Worker }
405*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " MustForceNegatedAtanParamToFloat")) {
406*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::MustForceNegatedAtanParamToFloat();
407*c8dee2aaSAndroid Build Coastguard Worker }
408*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " MustForceNegatedLdexpParamToMultiply")) {
409*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::MustForceNegatedLdexpParamToMultiply();
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoBuiltinDeterminantSupport")) {
412*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::NoBuiltinDeterminantSupport();
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoBuiltinFMASupport")) {
415*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::NoBuiltinFMASupport();
416*c8dee2aaSAndroid Build Coastguard Worker }
417*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoExternalTextureSupport")) {
418*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::NoExternalTextureSupport();
419*c8dee2aaSAndroid Build Coastguard Worker }
420*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " RemovePowWithConstantExponent")) {
421*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::RemovePowWithConstantExponent();
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " RewriteDoWhileLoops")) {
424*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::RewriteDoWhileLoops();
425*c8dee2aaSAndroid Build Coastguard Worker }
426*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " RewriteSwitchStatements")) {
427*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::RewriteSwitchStatements();
428*c8dee2aaSAndroid Build Coastguard Worker }
429*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " RewriteMatrixVectorMultiply")) {
430*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::RewriteMatrixVectorMultiply();
431*c8dee2aaSAndroid Build Coastguard Worker }
432*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " RewriteMatrixComparisons")) {
433*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::RewriteMatrixComparisons();
434*c8dee2aaSAndroid Build Coastguard Worker }
435*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " ShaderDerivativeExtensionString")) {
436*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::ShaderDerivativeExtensionString();
437*c8dee2aaSAndroid Build Coastguard Worker }
438*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " UnfoldShortCircuitAsTernary")) {
439*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::UnfoldShortCircuitAsTernary();
440*c8dee2aaSAndroid Build Coastguard Worker }
441*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " UsesPrecisionModifiers")) {
442*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::UsesPrecisionModifiers();
443*c8dee2aaSAndroid Build Coastguard Worker }
444*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " Version110")) {
445*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::Version110();
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " Version450Core")) {
448*c8dee2aaSAndroid Build Coastguard Worker *caps = Factory::Version450Core();
449*c8dee2aaSAndroid Build Coastguard Worker }
450*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " AllowNarrowingConversions")) {
451*c8dee2aaSAndroid Build Coastguard Worker settings->fAllowNarrowingConversions = true;
452*c8dee2aaSAndroid Build Coastguard Worker }
453*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " ForceHighPrecision")) {
454*c8dee2aaSAndroid Build Coastguard Worker settings->fForceHighPrecision = true;
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoInline")) {
457*c8dee2aaSAndroid Build Coastguard Worker settings->fInlineThreshold = 0;
458*c8dee2aaSAndroid Build Coastguard Worker }
459*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoOptimize")) {
460*c8dee2aaSAndroid Build Coastguard Worker settings->fOptimize = false;
461*c8dee2aaSAndroid Build Coastguard Worker settings->fInlineThreshold = 0;
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " NoRTFlip")) {
464*c8dee2aaSAndroid Build Coastguard Worker settings->fForceNoRTFlip = true;
465*c8dee2aaSAndroid Build Coastguard Worker }
466*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " InlineThresholdMax")) {
467*c8dee2aaSAndroid Build Coastguard Worker settings->fInlineThreshold = INT_MAX;
468*c8dee2aaSAndroid Build Coastguard Worker }
469*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " Sharpen")) {
470*c8dee2aaSAndroid Build Coastguard Worker settings->fSharpenTextures = true;
471*c8dee2aaSAndroid Build Coastguard Worker }
472*c8dee2aaSAndroid Build Coastguard Worker if (consume_suffix(&settingsText, " DebugTrace")) {
473*c8dee2aaSAndroid Build Coastguard Worker settings->fOptimize = false;
474*c8dee2aaSAndroid Build Coastguard Worker *debugTrace = std::make_unique<SkSL::DebugTracePriv>();
475*c8dee2aaSAndroid Build Coastguard Worker }
476*c8dee2aaSAndroid Build Coastguard Worker
477*c8dee2aaSAndroid Build Coastguard Worker if (settingsText.empty()) {
478*c8dee2aaSAndroid Build Coastguard Worker break;
479*c8dee2aaSAndroid Build Coastguard Worker }
480*c8dee2aaSAndroid Build Coastguard Worker if (settingsText.length() == startingLength) {
481*c8dee2aaSAndroid Build Coastguard Worker printf("Unrecognized #pragma settings: %s\n", settingsText.c_str());
482*c8dee2aaSAndroid Build Coastguard Worker return false;
483*c8dee2aaSAndroid Build Coastguard Worker }
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker }
486*c8dee2aaSAndroid Build Coastguard Worker }
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker return true;
489*c8dee2aaSAndroid Build Coastguard Worker }
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker /**
492*c8dee2aaSAndroid Build Coastguard Worker * Displays a usage banner; used when the command line arguments don't make sense.
493*c8dee2aaSAndroid Build Coastguard Worker */
show_usage()494*c8dee2aaSAndroid Build Coastguard Worker static void show_usage() {
495*c8dee2aaSAndroid Build Coastguard Worker printf("usage: skslc <input> <output> <flags>\n"
496*c8dee2aaSAndroid Build Coastguard Worker " skslc <worklist>\n"
497*c8dee2aaSAndroid Build Coastguard Worker "\n"
498*c8dee2aaSAndroid Build Coastguard Worker "Allowed flags:\n"
499*c8dee2aaSAndroid Build Coastguard Worker "--settings: honor embedded /*#pragma settings*/ comments.\n"
500*c8dee2aaSAndroid Build Coastguard Worker "--nosettings: ignore /*#pragma settings*/ comments\n");
501*c8dee2aaSAndroid Build Coastguard Worker }
502*c8dee2aaSAndroid Build Coastguard Worker
set_flag(std::optional<bool> * flag,const char * name,bool value)503*c8dee2aaSAndroid Build Coastguard Worker static bool set_flag(std::optional<bool>* flag, const char* name, bool value) {
504*c8dee2aaSAndroid Build Coastguard Worker if (flag->has_value()) {
505*c8dee2aaSAndroid Build Coastguard Worker printf("%s flag was specified multiple times\n", name);
506*c8dee2aaSAndroid Build Coastguard Worker return false;
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker *flag = value;
509*c8dee2aaSAndroid Build Coastguard Worker return true;
510*c8dee2aaSAndroid Build Coastguard Worker }
511*c8dee2aaSAndroid Build Coastguard Worker
512*c8dee2aaSAndroid Build Coastguard Worker /**
513*c8dee2aaSAndroid Build Coastguard Worker * Handle a single input.
514*c8dee2aaSAndroid Build Coastguard Worker */
process_command(SkSpan<std::string> args)515*c8dee2aaSAndroid Build Coastguard Worker static ResultCode process_command(SkSpan<std::string> args) {
516*c8dee2aaSAndroid Build Coastguard Worker std::optional<bool> honorSettings;
517*c8dee2aaSAndroid Build Coastguard Worker std::vector<std::string> paths;
518*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 1; i < args.size(); ++i) {
519*c8dee2aaSAndroid Build Coastguard Worker const std::string& arg = args[i];
520*c8dee2aaSAndroid Build Coastguard Worker if (arg == "--settings") {
521*c8dee2aaSAndroid Build Coastguard Worker if (!set_flag(&honorSettings, "settings", true)) {
522*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
523*c8dee2aaSAndroid Build Coastguard Worker }
524*c8dee2aaSAndroid Build Coastguard Worker } else if (arg == "--nosettings") {
525*c8dee2aaSAndroid Build Coastguard Worker if (!set_flag(&honorSettings, "settings", false)) {
526*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker } else if (!skstd::starts_with(arg, "--")) {
529*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(arg);
530*c8dee2aaSAndroid Build Coastguard Worker } else {
531*c8dee2aaSAndroid Build Coastguard Worker show_usage();
532*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
533*c8dee2aaSAndroid Build Coastguard Worker }
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker if (paths.size() != 2) {
536*c8dee2aaSAndroid Build Coastguard Worker show_usage();
537*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
538*c8dee2aaSAndroid Build Coastguard Worker }
539*c8dee2aaSAndroid Build Coastguard Worker
540*c8dee2aaSAndroid Build Coastguard Worker if (!honorSettings.has_value()) {
541*c8dee2aaSAndroid Build Coastguard Worker honorSettings = true;
542*c8dee2aaSAndroid Build Coastguard Worker }
543*c8dee2aaSAndroid Build Coastguard Worker
544*c8dee2aaSAndroid Build Coastguard Worker const std::string& inputPath = paths[0];
545*c8dee2aaSAndroid Build Coastguard Worker const std::string& outputPath = paths[1];
546*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramKind kind;
547*c8dee2aaSAndroid Build Coastguard Worker if (skstd::ends_with(inputPath, ".vert")) {
548*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kVertex;
549*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".frag") || skstd::ends_with(inputPath, ".sksl")) {
550*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kFragment;
551*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".mvert")) {
552*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kMeshVertex;
553*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".mfrag")) {
554*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kMeshFragment;
555*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".compute")) {
556*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kCompute;
557*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".rtb")) {
558*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kRuntimeBlender;
559*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".rtcf")) {
560*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kRuntimeColorFilter;
561*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".rts")) {
562*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kRuntimeShader;
563*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(inputPath, ".privrts")) {
564*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kPrivateRuntimeShader;
565*c8dee2aaSAndroid Build Coastguard Worker } else {
566*c8dee2aaSAndroid Build Coastguard Worker printf("input filename must end in '.vert', '.frag', '.mvert', '.mfrag', '.compute', "
567*c8dee2aaSAndroid Build Coastguard Worker "'.rtb', '.rtcf', '.rts', '.privrts', or '.sksl'\n");
568*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
569*c8dee2aaSAndroid Build Coastguard Worker }
570*c8dee2aaSAndroid Build Coastguard Worker
571*c8dee2aaSAndroid Build Coastguard Worker std::ifstream in(inputPath);
572*c8dee2aaSAndroid Build Coastguard Worker std::string text((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
573*c8dee2aaSAndroid Build Coastguard Worker if (in.rdstate()) {
574*c8dee2aaSAndroid Build Coastguard Worker printf("error reading '%s'\n", inputPath.c_str());
575*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
576*c8dee2aaSAndroid Build Coastguard Worker }
577*c8dee2aaSAndroid Build Coastguard Worker
578*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramSettings settings;
579*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* caps = SkSL::ShaderCapsFactory::Standalone();
580*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::DebugTracePriv> debugTrace;
581*c8dee2aaSAndroid Build Coastguard Worker if (*honorSettings) {
582*c8dee2aaSAndroid Build Coastguard Worker if (!detect_shader_settings(text, &settings, &caps, &debugTrace)) {
583*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kInputError;
584*c8dee2aaSAndroid Build Coastguard Worker }
585*c8dee2aaSAndroid Build Coastguard Worker }
586*c8dee2aaSAndroid Build Coastguard Worker
587*c8dee2aaSAndroid Build Coastguard Worker // This tells the compiler where the rt-flip uniform will live should it be required. For
588*c8dee2aaSAndroid Build Coastguard Worker // testing purposes we don't care where that is, but the compiler will report an error if we
589*c8dee2aaSAndroid Build Coastguard Worker // leave them at their default invalid values, or if the offset overlaps another uniform.
590*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipOffset = 16384;
591*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipSet = 0;
592*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipBinding = 0;
593*c8dee2aaSAndroid Build Coastguard Worker
594*c8dee2aaSAndroid Build Coastguard Worker auto emitCompileError = [&](const char* errorText) {
595*c8dee2aaSAndroid Build Coastguard Worker // Overwrite the compiler output, if any, with an error message.
596*c8dee2aaSAndroid Build Coastguard Worker SkSL::FileOutputStream errorStream(outputPath.c_str());
597*c8dee2aaSAndroid Build Coastguard Worker errorStream.writeText("### Compilation failed:\n\n");
598*c8dee2aaSAndroid Build Coastguard Worker errorStream.writeText(errorText);
599*c8dee2aaSAndroid Build Coastguard Worker errorStream.close();
600*c8dee2aaSAndroid Build Coastguard Worker // Also emit the error directly to stdout.
601*c8dee2aaSAndroid Build Coastguard Worker puts(errorText);
602*c8dee2aaSAndroid Build Coastguard Worker };
603*c8dee2aaSAndroid Build Coastguard Worker
604*c8dee2aaSAndroid Build Coastguard Worker auto compileProgram = [&](const auto& writeFn) -> ResultCode {
605*c8dee2aaSAndroid Build Coastguard Worker SkSL::FileOutputStream out(outputPath.c_str());
606*c8dee2aaSAndroid Build Coastguard Worker SkSL::Compiler compiler;
607*c8dee2aaSAndroid Build Coastguard Worker if (!out.isValid()) {
608*c8dee2aaSAndroid Build Coastguard Worker printf("error writing '%s'\n", outputPath.c_str());
609*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kOutputError;
610*c8dee2aaSAndroid Build Coastguard Worker }
611*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
612*c8dee2aaSAndroid Build Coastguard Worker if (!program || !writeFn(compiler, caps, *program, out)) {
613*c8dee2aaSAndroid Build Coastguard Worker out.close();
614*c8dee2aaSAndroid Build Coastguard Worker emitCompileError(compiler.errorText().c_str());
615*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kCompileError;
616*c8dee2aaSAndroid Build Coastguard Worker }
617*c8dee2aaSAndroid Build Coastguard Worker if (!out.close()) {
618*c8dee2aaSAndroid Build Coastguard Worker printf("error writing '%s'\n", outputPath.c_str());
619*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kOutputError;
620*c8dee2aaSAndroid Build Coastguard Worker }
621*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kSuccess;
622*c8dee2aaSAndroid Build Coastguard Worker };
623*c8dee2aaSAndroid Build Coastguard Worker
624*c8dee2aaSAndroid Build Coastguard Worker auto compileProgramAsRuntimeShader = [&](const auto& writeFn) -> ResultCode {
625*c8dee2aaSAndroid Build Coastguard Worker if (kind == SkSL::ProgramKind::kVertex) {
626*c8dee2aaSAndroid Build Coastguard Worker emitCompileError("Runtime shaders do not support vertex programs\n");
627*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kCompileError;
628*c8dee2aaSAndroid Build Coastguard Worker }
629*c8dee2aaSAndroid Build Coastguard Worker if (kind == SkSL::ProgramKind::kFragment) {
630*c8dee2aaSAndroid Build Coastguard Worker // Handle .sksl and .frag programs as runtime shaders.
631*c8dee2aaSAndroid Build Coastguard Worker kind = SkSL::ProgramKind::kPrivateRuntimeShader;
632*c8dee2aaSAndroid Build Coastguard Worker }
633*c8dee2aaSAndroid Build Coastguard Worker return compileProgram(writeFn);
634*c8dee2aaSAndroid Build Coastguard Worker };
635*c8dee2aaSAndroid Build Coastguard Worker
636*c8dee2aaSAndroid Build Coastguard Worker if (skstd::ends_with(outputPath, ".spirv")) {
637*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler& compiler,
638*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
639*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
640*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
641*c8dee2aaSAndroid Build Coastguard Worker return SkSL::ToSPIRV(program, shaderCaps, out, SkSL::ValidateSPIRVAndDissassemble);
642*c8dee2aaSAndroid Build Coastguard Worker });
643*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".asm.frag") ||
644*c8dee2aaSAndroid Build Coastguard Worker skstd::ends_with(outputPath, ".asm.vert") ||
645*c8dee2aaSAndroid Build Coastguard Worker skstd::ends_with(outputPath, ".asm.comp")) {
646*c8dee2aaSAndroid Build Coastguard Worker return compileProgram(
647*c8dee2aaSAndroid Build Coastguard Worker [](SkSL::Compiler& compiler,
648*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
649*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
650*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
651*c8dee2aaSAndroid Build Coastguard Worker // Compile program to SPIR-V assembly in a string-stream.
652*c8dee2aaSAndroid Build Coastguard Worker SkSL::StringStream assembly;
653*c8dee2aaSAndroid Build Coastguard Worker if (!SkSL::ToSPIRV(program,
654*c8dee2aaSAndroid Build Coastguard Worker shaderCaps,
655*c8dee2aaSAndroid Build Coastguard Worker assembly,
656*c8dee2aaSAndroid Build Coastguard Worker SkSL::ValidateSPIRVAndDissassemble)) {
657*c8dee2aaSAndroid Build Coastguard Worker return false;
658*c8dee2aaSAndroid Build Coastguard Worker }
659*c8dee2aaSAndroid Build Coastguard Worker // Convert the string-stream to a SPIR-V disassembly.
660*c8dee2aaSAndroid Build Coastguard Worker spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
661*c8dee2aaSAndroid Build Coastguard Worker const std::string& spirv(assembly.str());
662*c8dee2aaSAndroid Build Coastguard Worker std::string disassembly;
663*c8dee2aaSAndroid Build Coastguard Worker uint32_t options = spvtools::SpirvTools::kDefaultDisassembleOption;
664*c8dee2aaSAndroid Build Coastguard Worker options |= SPV_BINARY_TO_TEXT_OPTION_INDENT;
665*c8dee2aaSAndroid Build Coastguard Worker if (!tools.Disassemble((const uint32_t*)spirv.data(),
666*c8dee2aaSAndroid Build Coastguard Worker spirv.size() / 4,
667*c8dee2aaSAndroid Build Coastguard Worker &disassembly,
668*c8dee2aaSAndroid Build Coastguard Worker options)) {
669*c8dee2aaSAndroid Build Coastguard Worker return false;
670*c8dee2aaSAndroid Build Coastguard Worker }
671*c8dee2aaSAndroid Build Coastguard Worker // Finally, write the disassembly to our output stream.
672*c8dee2aaSAndroid Build Coastguard Worker out.write(disassembly.data(), disassembly.size());
673*c8dee2aaSAndroid Build Coastguard Worker return true;
674*c8dee2aaSAndroid Build Coastguard Worker });
675*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".glsl")) {
676*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler& compiler,
677*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
678*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
679*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
680*c8dee2aaSAndroid Build Coastguard Worker return SkSL::ToGLSL(program, shaderCaps, out, SkSL::PrettyPrint::kYes);
681*c8dee2aaSAndroid Build Coastguard Worker });
682*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".metal")) {
683*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler& compiler,
684*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
685*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
686*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
687*c8dee2aaSAndroid Build Coastguard Worker return SkSL::ToMetal(program, shaderCaps, out, SkSL::PrettyPrint::kYes);
688*c8dee2aaSAndroid Build Coastguard Worker });
689*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".hlsl")) {
690*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler& compiler,
691*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
692*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
693*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
694*c8dee2aaSAndroid Build Coastguard Worker return SkSL::ToHLSL(program, shaderCaps, out, SkSL::ValidateSPIRVAndDissassemble);
695*c8dee2aaSAndroid Build Coastguard Worker });
696*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".wgsl")) {
697*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler& compiler,
698*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
699*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
700*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
701*c8dee2aaSAndroid Build Coastguard Worker return SkSL::ToWGSL(program,
702*c8dee2aaSAndroid Build Coastguard Worker shaderCaps,
703*c8dee2aaSAndroid Build Coastguard Worker out,
704*c8dee2aaSAndroid Build Coastguard Worker SkSL::PrettyPrint::kYes,
705*c8dee2aaSAndroid Build Coastguard Worker SkSL::IncludeSyntheticCode::kYes,
706*c8dee2aaSAndroid Build Coastguard Worker SkSL::ValidateWGSL);
707*c8dee2aaSAndroid Build Coastguard Worker });
708*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".skrp")) {
709*c8dee2aaSAndroid Build Coastguard Worker settings.fMaxVersionAllowed = SkSL::Version::k300;
710*c8dee2aaSAndroid Build Coastguard Worker return compileProgramAsRuntimeShader([&](SkSL::Compiler& compiler,
711*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
712*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
713*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
714*c8dee2aaSAndroid Build Coastguard Worker SkSL::DebugTracePriv skrpDebugTrace;
715*c8dee2aaSAndroid Build Coastguard Worker const SkSL::FunctionDeclaration* main = program.getFunction("main");
716*c8dee2aaSAndroid Build Coastguard Worker if (!main) {
717*c8dee2aaSAndroid Build Coastguard Worker compiler.errorReporter().error({}, "code has no entrypoint");
718*c8dee2aaSAndroid Build Coastguard Worker return false;
719*c8dee2aaSAndroid Build Coastguard Worker }
720*c8dee2aaSAndroid Build Coastguard Worker bool wantTraceOps = (debugTrace != nullptr);
721*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSL::RP::Program> rasterProg = SkSL::MakeRasterPipelineProgram(
722*c8dee2aaSAndroid Build Coastguard Worker program, *main->definition(), &skrpDebugTrace, wantTraceOps);
723*c8dee2aaSAndroid Build Coastguard Worker if (!rasterProg) {
724*c8dee2aaSAndroid Build Coastguard Worker compiler.errorReporter().error({}, "code is not supported");
725*c8dee2aaSAndroid Build Coastguard Worker return false;
726*c8dee2aaSAndroid Build Coastguard Worker }
727*c8dee2aaSAndroid Build Coastguard Worker rasterProg->dump(as_SkWStream(out).get(), /*writeInstructionCount=*/true);
728*c8dee2aaSAndroid Build Coastguard Worker return true;
729*c8dee2aaSAndroid Build Coastguard Worker });
730*c8dee2aaSAndroid Build Coastguard Worker } else if (skstd::ends_with(outputPath, ".stage")) {
731*c8dee2aaSAndroid Build Coastguard Worker return compileProgram([](SkSL::Compiler&,
732*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ShaderCaps* shaderCaps,
733*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program& program,
734*c8dee2aaSAndroid Build Coastguard Worker SkSL::OutputStream& out) {
735*c8dee2aaSAndroid Build Coastguard Worker class Callbacks : public SkSL::PipelineStage::Callbacks {
736*c8dee2aaSAndroid Build Coastguard Worker public:
737*c8dee2aaSAndroid Build Coastguard Worker std::string getMangledName(const char* name) override {
738*c8dee2aaSAndroid Build Coastguard Worker return std::string(name) + "_0";
739*c8dee2aaSAndroid Build Coastguard Worker }
740*c8dee2aaSAndroid Build Coastguard Worker
741*c8dee2aaSAndroid Build Coastguard Worker std::string declareUniform(const SkSL::VarDeclaration* decl) override {
742*c8dee2aaSAndroid Build Coastguard Worker fOutput += decl->description();
743*c8dee2aaSAndroid Build Coastguard Worker return std::string(decl->var()->name());
744*c8dee2aaSAndroid Build Coastguard Worker }
745*c8dee2aaSAndroid Build Coastguard Worker
746*c8dee2aaSAndroid Build Coastguard Worker void defineFunction(const char* decl, const char* body, bool /*isMain*/) override {
747*c8dee2aaSAndroid Build Coastguard Worker fOutput += std::string(decl) + '{' + body + '}';
748*c8dee2aaSAndroid Build Coastguard Worker }
749*c8dee2aaSAndroid Build Coastguard Worker
750*c8dee2aaSAndroid Build Coastguard Worker void declareFunction(const char* decl) override { fOutput += decl; }
751*c8dee2aaSAndroid Build Coastguard Worker
752*c8dee2aaSAndroid Build Coastguard Worker void defineStruct(const char* definition) override { fOutput += definition; }
753*c8dee2aaSAndroid Build Coastguard Worker
754*c8dee2aaSAndroid Build Coastguard Worker void declareGlobal(const char* declaration) override { fOutput += declaration; }
755*c8dee2aaSAndroid Build Coastguard Worker
756*c8dee2aaSAndroid Build Coastguard Worker std::string sampleShader(int index, std::string coords) override {
757*c8dee2aaSAndroid Build Coastguard Worker return "child_" + std::to_string(index) + ".eval(" + coords + ')';
758*c8dee2aaSAndroid Build Coastguard Worker }
759*c8dee2aaSAndroid Build Coastguard Worker
760*c8dee2aaSAndroid Build Coastguard Worker std::string sampleColorFilter(int index, std::string color) override {
761*c8dee2aaSAndroid Build Coastguard Worker return "child_" + std::to_string(index) + ".eval(" + color + ')';
762*c8dee2aaSAndroid Build Coastguard Worker }
763*c8dee2aaSAndroid Build Coastguard Worker
764*c8dee2aaSAndroid Build Coastguard Worker std::string sampleBlender(int index, std::string src, std::string dst) override {
765*c8dee2aaSAndroid Build Coastguard Worker return "child_" + std::to_string(index) + ".eval(" + src + ", " + dst + ')';
766*c8dee2aaSAndroid Build Coastguard Worker }
767*c8dee2aaSAndroid Build Coastguard Worker
768*c8dee2aaSAndroid Build Coastguard Worker std::string toLinearSrgb(std::string color) override {
769*c8dee2aaSAndroid Build Coastguard Worker return "toLinearSrgb(" + color + ')';
770*c8dee2aaSAndroid Build Coastguard Worker }
771*c8dee2aaSAndroid Build Coastguard Worker std::string fromLinearSrgb(std::string color) override {
772*c8dee2aaSAndroid Build Coastguard Worker return "fromLinearSrgb(" + color + ')';
773*c8dee2aaSAndroid Build Coastguard Worker }
774*c8dee2aaSAndroid Build Coastguard Worker
775*c8dee2aaSAndroid Build Coastguard Worker std::string fOutput;
776*c8dee2aaSAndroid Build Coastguard Worker };
777*c8dee2aaSAndroid Build Coastguard Worker // The .stage output looks almost like valid SkSL, but not quite.
778*c8dee2aaSAndroid Build Coastguard Worker // The PipelineStageGenerator bridges the gap between the SkSL in `program`,
779*c8dee2aaSAndroid Build Coastguard Worker // and the C++ FP builder API (see GrSkSLFP). In that API, children don't need
780*c8dee2aaSAndroid Build Coastguard Worker // to be declared (so they don't emit declarations here). Children are sampled
781*c8dee2aaSAndroid Build Coastguard Worker // by index, not name - so all children here are just "child_N".
782*c8dee2aaSAndroid Build Coastguard Worker // The input color and coords have names in the original SkSL (as parameters to
783*c8dee2aaSAndroid Build Coastguard Worker // main), but those are ignored here. References to those variables become
784*c8dee2aaSAndroid Build Coastguard Worker // "_coords" and "_inColor". At runtime, those variable names are irrelevant
785*c8dee2aaSAndroid Build Coastguard Worker // when the new SkSL is emitted inside the FP - references to those variables
786*c8dee2aaSAndroid Build Coastguard Worker // are replaced with strings from EmitArgs, and might be varyings or differently
787*c8dee2aaSAndroid Build Coastguard Worker // named parameters.
788*c8dee2aaSAndroid Build Coastguard Worker Callbacks callbacks;
789*c8dee2aaSAndroid Build Coastguard Worker SkSL::PipelineStage::ConvertProgram(program, "_coords", "_inColor",
790*c8dee2aaSAndroid Build Coastguard Worker "_canvasColor", &callbacks);
791*c8dee2aaSAndroid Build Coastguard Worker out.writeString(SkShaderUtils::PrettyPrint(callbacks.fOutput));
792*c8dee2aaSAndroid Build Coastguard Worker return true;
793*c8dee2aaSAndroid Build Coastguard Worker });
794*c8dee2aaSAndroid Build Coastguard Worker } else {
795*c8dee2aaSAndroid Build Coastguard Worker printf("expected output path to end with one of: .glsl, .html, .metal, .hlsl, .wgsl, "
796*c8dee2aaSAndroid Build Coastguard Worker ".spirv, .asm.vert, .asm.frag, .asm.comp, .skrp, .stage (got '%s')\n",
797*c8dee2aaSAndroid Build Coastguard Worker outputPath.c_str());
798*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kConfigurationError;
799*c8dee2aaSAndroid Build Coastguard Worker }
800*c8dee2aaSAndroid Build Coastguard Worker return ResultCode::kSuccess;
801*c8dee2aaSAndroid Build Coastguard Worker }
802*c8dee2aaSAndroid Build Coastguard Worker
main(int argc,const char ** argv)803*c8dee2aaSAndroid Build Coastguard Worker int main(int argc, const char** argv) {
804*c8dee2aaSAndroid Build Coastguard Worker if (argc == 2) {
805*c8dee2aaSAndroid Build Coastguard Worker // Worklists are the only two-argument case for skslc, and we don't intend to support
806*c8dee2aaSAndroid Build Coastguard Worker // nested worklists, so we can process them here.
807*c8dee2aaSAndroid Build Coastguard Worker return (int)ProcessWorklist(argv[1], process_command);
808*c8dee2aaSAndroid Build Coastguard Worker } else {
809*c8dee2aaSAndroid Build Coastguard Worker // Process non-worklist inputs.
810*c8dee2aaSAndroid Build Coastguard Worker std::vector<std::string> args;
811*c8dee2aaSAndroid Build Coastguard Worker for (int index=0; index<argc; ++index) {
812*c8dee2aaSAndroid Build Coastguard Worker args.push_back(argv[index]);
813*c8dee2aaSAndroid Build Coastguard Worker }
814*c8dee2aaSAndroid Build Coastguard Worker
815*c8dee2aaSAndroid Build Coastguard Worker return (int)process_command(args);
816*c8dee2aaSAndroid Build Coastguard Worker }
817*c8dee2aaSAndroid Build Coastguard Worker }
818