8#define SK_OPTS_NS skslc_standalone
34#include "spirv-tools/libspirv.hpp"
58 bool write(
const void*
buffer,
size_t size)
override {
60 fBytesWritten += size;
63 void flush()
override {}
64 size_t bytesWritten()
const override {
return fBytesWritten; }
71 return std::make_unique<Adapter>(
s);
78 str->resize(str->length() - strlen(suffix));
87 caps->fVersionDeclString =
"#version 400";
88 caps->fAddAndTrueToLoopCondition =
true;
89 return caps.release();
97 caps->fVersionDeclString =
"#version 400";
98 caps->fCanUseFractForNegativeValues =
false;
99 return caps.release();
107 caps->fVersionDeclString =
"#version 400";
108 caps->fCanUseFragCoord =
false;
109 return caps.release();
117 caps->fVersionDeclString =
"#version 400";
118 caps->fCanUseMinAndAbsTogether =
false;
119 return caps.release();
127 caps->fCanUseVoidInSequenceExpressions =
false;
128 return caps.release();
137 caps->fDualSourceBlendingSupport =
true;
138 return caps.release();
146 caps->fVersionDeclString =
"#version 400";
147 caps->fEmulateAbsIntFunction =
true;
148 return caps.release();
156 caps->fFBFetchSupport =
true;
157 caps->fFBFetchColorName =
"FramebufferFragColor";
158 return caps.release();
166 caps->fMustDeclareFragmentFrontFacing =
true;
167 return caps.release();
175 caps->fVersionDeclString =
"#version 400";
176 caps->fMustForceNegatedAtanParamToFloat =
true;
177 return caps.release();
185 caps->fVersionDeclString =
"#version 400";
186 caps->fMustForceNegatedLdexpParamToMultiply =
true;
187 return caps.release();
195 caps->fMustGuardDivisionEvenAfterExplicitZeroCheck =
true;
196 return caps.release();
204 caps->fVersionDeclString =
"#version 400";
205 caps->fBuiltinDeterminantSupport =
false;
206 return caps.release();
214 caps->fVersionDeclString =
"#version 400";
215 caps->fBuiltinFMASupport =
false;
216 return caps.release();
224 caps->fVersionDeclString =
"#version 400";
225 caps->fExternalTextureSupport =
false;
226 return caps.release();
234 caps->fVersionDeclString =
"#version 400";
235 caps->fRemovePowWithConstantExponent =
true;
236 return caps.release();
244 caps->fVersionDeclString =
"#version 400";
245 caps->fRewriteDoWhileLoops =
true;
246 return caps.release();
254 caps->fRewriteMatrixComparisons =
true;
255 caps->fUsesPrecisionModifiers =
true;
256 return caps.release();
264 caps->fVersionDeclString =
"#version 400";
265 caps->fRewriteMatrixVectorMultiply =
true;
266 return caps.release();
274 caps->fVersionDeclString =
"#version 400";
275 caps->fRewriteSwitchStatements =
true;
276 return caps.release();
284 caps->fVersionDeclString =
"#version 400";
285 caps->fShaderDerivativeSupport =
true;
286 caps->fSampleMaskSupport =
true;
287 return caps.release();
295 caps->fVersionDeclString =
"#version 400";
296 caps->fShaderDerivativeSupport =
true;
297 caps->fShaderDerivativeExtensionString =
"GL_OES_standard_derivatives";
298 caps->fUsesPrecisionModifiers =
true;
299 return caps.release();
307 caps->fVersionDeclString =
"#version 400";
308 caps->fUnfoldShortCircuitAsTernary =
true;
309 return caps.release();
317 caps->fVersionDeclString =
"#version 400";
318 caps->fUsesPrecisionModifiers =
true;
319 return caps.release();
327 caps->fVersionDeclString =
"#version 110";
329 return caps.release();
337 caps->fVersionDeclString =
"#version 450 core";
338 return caps.release();
350 std::unique_ptr<SkSL::DebugTracePriv>* debugTrace) {
354 static constexpr char kPragmaSettings[] =
"/*#pragma settings ";
355 const char* settingsPtr = strstr(
text.c_str(), kPragmaSettings);
356 if (settingsPtr !=
nullptr) {
359 settingsPtr += strlen(kPragmaSettings) - 1;
361 const char* settingsEnd = strstr(settingsPtr,
"*/");
362 if (settingsEnd !=
nullptr) {
363 std::string settingsText{settingsPtr, size_t(settingsEnd - settingsPtr)};
368 const size_t startingLength = settingsText.length();
370 if (
consume_suffix(&settingsText,
" AddAndTrueToLoopCondition")) {
371 *caps = Factory::AddAndTrueToLoopCondition();
373 if (
consume_suffix(&settingsText,
" CannotUseFractForNegativeValues")) {
374 *caps = Factory::CannotUseFractForNegativeValues();
377 *caps = Factory::CannotUseFragCoord();
379 if (
consume_suffix(&settingsText,
" CannotUseMinAndAbsTogether")) {
380 *caps = Factory::CannotUseMinAndAbsTogether();
382 if (
consume_suffix(&settingsText,
" CannotUseVoidInSequenceExpressions")) {
383 *caps = Factory::CannotUseVoidInSequenceExpressions();
386 *caps = Factory::DualSourceBlending();
389 *caps = Factory::Default();
392 *caps = Factory::EmulateAbsIntFunction();
395 *caps = Factory::FramebufferFetchSupport();
397 if (
consume_suffix(&settingsText,
" MustGuardDivisionEvenAfterExplicitZeroCheck")) {
398 *caps = Factory::MustGuardDivisionEvenAfterExplicitZeroCheck();
400 if (
consume_suffix(&settingsText,
" MustDeclareFragmentFrontFacing")) {
401 *caps = Factory::MustDeclareFragmentFrontFacing();
403 if (
consume_suffix(&settingsText,
" MustForceNegatedAtanParamToFloat")) {
404 *caps = Factory::MustForceNegatedAtanParamToFloat();
406 if (
consume_suffix(&settingsText,
" MustForceNegatedLdexpParamToMultiply")) {
407 *caps = Factory::MustForceNegatedLdexpParamToMultiply();
409 if (
consume_suffix(&settingsText,
" NoBuiltinDeterminantSupport")) {
410 *caps = Factory::NoBuiltinDeterminantSupport();
413 *caps = Factory::NoBuiltinFMASupport();
416 *caps = Factory::NoExternalTextureSupport();
418 if (
consume_suffix(&settingsText,
" RemovePowWithConstantExponent")) {
419 *caps = Factory::RemovePowWithConstantExponent();
422 *caps = Factory::RewriteDoWhileLoops();
425 *caps = Factory::RewriteSwitchStatements();
427 if (
consume_suffix(&settingsText,
" RewriteMatrixVectorMultiply")) {
428 *caps = Factory::RewriteMatrixVectorMultiply();
431 *caps = Factory::RewriteMatrixComparisons();
433 if (
consume_suffix(&settingsText,
" ShaderDerivativeExtensionString")) {
434 *caps = Factory::ShaderDerivativeExtensionString();
436 if (
consume_suffix(&settingsText,
" UnfoldShortCircuitAsTernary")) {
437 *caps = Factory::UnfoldShortCircuitAsTernary();
440 *caps = Factory::UsesPrecisionModifiers();
443 *caps = Factory::Version110();
446 *caps = Factory::Version450Core();
448 if (
consume_suffix(&settingsText,
" AllowNarrowingConversions")) {
449 settings->fAllowNarrowingConversions =
true;
452 settings->fForceHighPrecision =
true;
455 settings->fInlineThreshold = 0;
458 settings->fOptimize =
false;
459 settings->fInlineThreshold = 0;
462 settings->fForceNoRTFlip =
true;
465 settings->fInlineThreshold = INT_MAX;
468 settings->fSharpenTextures =
true;
471 settings->fOptimize =
false;
472 *debugTrace = std::make_unique<SkSL::DebugTracePriv>();
475 if (settingsText.empty()) {
478 if (settingsText.length() == startingLength) {
479 printf(
"Unrecognized #pragma settings: %s\n", settingsText.c_str());
493 printf(
"usage: skslc <input> <output> <flags>\n"
494 " skslc <worklist>\n"
497 "--settings: honor embedded /*#pragma settings*/ comments.\n"
498 "--nosettings: ignore /*#pragma settings*/ comments\n");
502 if (
flag->has_value()) {
503 printf(
"%s flag was specified multiple times\n",
name);
514 std::optional<bool> honorSettings;
515 std::vector<std::string> paths;
516 for (
size_t i = 1; i <
args.size(); ++i) {
517 const std::string& arg =
args[i];
518 if (arg ==
"--settings") {
519 if (!
set_flag(&honorSettings,
"settings",
true)) {
522 }
else if (arg ==
"--nosettings") {
523 if (!
set_flag(&honorSettings,
"settings",
false)) {
527 paths.push_back(arg);
533 if (paths.size() != 2) {
538 if (!honorSettings.has_value()) {
539 honorSettings =
true;
542 const std::string& inputPath = paths[0];
543 const std::string& outputPath = paths[1];
562 printf(
"input filename must end in '.vert', '.frag', '.mvert', '.mfrag', '.compute', "
563 "'.rtb', '.rtcf', '.rts' or '.sksl'\n");
567 std::ifstream in(inputPath);
568 std::string
text((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
570 printf(
"error reading '%s'\n", inputPath.c_str());
576 std::unique_ptr<SkSL::DebugTracePriv> debugTrace;
577 if (*honorSettings) {
586 settings.fRTFlipOffset = 16384;
587 settings.fRTFlipSet = 0;
588 settings.fRTFlipBinding = 0;
590 auto emitCompileError = [&](
const char* errorText) {
593 errorStream.
writeText(
"### Compilation failed:\n\n");
600 auto compileProgram = [&](
const auto& writeFn) ->
ResultCode {
603 if (!out.isValid()) {
604 printf(
"error writing '%s'\n", outputPath.c_str());
607 std::unique_ptr<SkSL::Program> program =
compiler.convertProgram(kind,
text, settings);
608 if (!program || !writeFn(
compiler, caps, *program, out)) {
610 emitCompileError(
compiler.errorText().c_str());
614 printf(
"error writing '%s'\n", outputPath.c_str());
620 auto compileProgramAsRuntimeShader = [&](
const auto& writeFn) ->
ResultCode {
622 emitCompileError(
"Runtime shaders do not support vertex programs\n");
629 return compileProgram(writeFn);
642 return compileProgram(
653 spvtools::SpirvTools
tools(SPV_ENV_VULKAN_1_0);
654 const std::string& spirv(assembly.
str());
655 std::string disassembly;
656 uint32_t
options = spvtools::SpirvTools::kDefaultDisassembleOption;
657 options |= SPV_BINARY_TO_TEXT_OPTION_INDENT;
658 if (!
tools.Disassemble((
const uint32_t*)spirv.data(),
665 out.write(disassembly.data(), disassembly.size());
669 return compileProgram(
675 return compileProgram(
681 return compileProgram(
687 return compileProgram(
701 compiler.errorReporter().
error({},
"code has no entrypoint");
704 bool wantTraceOps = (debugTrace !=
nullptr);
706 program, *
main->definition(), &skrpDebugTrace, wantTraceOps);
708 compiler.errorReporter().error({},
"code is not supported");
722 return std::string(
name) +
"_0";
727 return std::string(decl->
var()->
name());
730 void defineFunction(
const char* decl,
const char* body,
bool )
override {
731 fOutput += std::string(decl) +
'{' + body +
'}';
736 void defineStruct(
const char* definition)
override { fOutput += definition; }
738 void declareGlobal(
const char* declaration)
override { fOutput += declaration; }
740 std::string
sampleShader(
int index, std::string coords)
override {
741 return "child_" + std::to_string(index) +
".eval(" + coords +
')';
745 return "child_" + std::to_string(index) +
".eval(" +
color +
')';
748 std::string
sampleBlender(
int index, std::string src, std::string dst)
override {
749 return "child_" + std::to_string(index) +
".eval(" + src +
", " + dst +
')';
753 return "toLinearSrgb(" +
color +
')';
756 return "fromLinearSrgb(" +
color +
')';
774 "_canvasColor", &callbacks);
779 printf(
"expected output path to end with one of: .glsl, .html, .metal, .hlsl, .wgsl, "
780 ".spirv, .asm.vert, .asm.frag, .asm.comp, .skrp, .stage (got '%s')\n",
787int main(
int argc,
const char** argv) {
794 std::vector<std::string>
args;
795 for (
int index=0; index<argc; ++index) {
ResultCode ProcessWorklist(const char *worklistPath, const std::function< ResultCode(SkSpan< std::string > args)> &processCommandFn)
static const SkSL::ShaderCaps * Version110()
static const SkSL::ShaderCaps * UsesPrecisionModifiers()
static const SkSL::ShaderCaps * NoExternalTextureSupport()
static const SkSL::ShaderCaps * CannotUseFractForNegativeValues()
static const SkSL::ShaderCaps * MustForceNegatedLdexpParamToMultiply()
static const SkSL::ShaderCaps * UnfoldShortCircuitAsTernary()
static const SkSL::ShaderCaps * AddAndTrueToLoopCondition()
static const SkSL::ShaderCaps * CannotUseVoidInSequenceExpressions()
static const SkSL::ShaderCaps * RewriteSwitchStatements()
static const SkSL::ShaderCaps * NoBuiltinDeterminantSupport()
static const SkSL::ShaderCaps * MustForceNegatedAtanParamToFloat()
static const SkSL::ShaderCaps * RemovePowWithConstantExponent()
static const SkSL::ShaderCaps * Version450Core()
static const SkSL::ShaderCaps * MustGuardDivisionEvenAfterExplicitZeroCheck()
static const SkSL::ShaderCaps * NoBuiltinFMASupport()
static const SkSL::ShaderCaps * SampleMaskSupport()
static const SkSL::ShaderCaps * ShaderDerivativeExtensionString()
static const SkSL::ShaderCaps * RewriteMatrixComparisons()
static const SkSL::ShaderCaps * CannotUseMinAndAbsTogether()
static const SkSL::ShaderCaps * RewriteDoWhileLoops()
static const SkSL::ShaderCaps * RewriteMatrixVectorMultiply()
static const SkSL::ShaderCaps * EmulateAbsIntFunction()
static const SkSL::ShaderCaps * FramebufferFetchSupport()
static const SkSL::ShaderCaps * CannotUseFragCoord()
static const SkSL::ShaderCaps * MustDeclareFragmentFrontFacing()
static const SkSL::ShaderCaps * DualSourceBlending()
void writeText(const char *s) override
virtual std::string sampleShader(int index, std::string coords)=0
virtual std::string sampleBlender(int index, std::string src, std::string dst)=0
virtual void defineStruct(const char *definition)=0
virtual void declareFunction(const char *declaration)=0
virtual std::string toLinearSrgb(std::string color)=0
virtual void declareGlobal(const char *declaration)=0
virtual std::string sampleColorFilter(int index, std::string color)=0
virtual std::string fromLinearSrgb(std::string color)=0
virtual void defineFunction(const char *declaration, const char *body, bool isMain)=0
virtual std::string declareUniform(const VarDeclaration *)=0
virtual std::string getMangledName(const char *name)
static const ShaderCaps * Standalone()
static std::unique_ptr< ShaderCaps > MakeShaderCaps()
const std::string & str() const
std::string_view name() const
std::string description() const override
virtual bool write(const void *buffer, size_t size)=0
virtual size_t bytesWritten() const =0
FlutterSemanticsFlag flag
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
size_t raster_pipeline_highp_stride
void ConvertProgram(const Program &program, const char *sampleCoords, const char *inputColor, const char *destColor, Callbacks *callbacks)
bool ToSPIRV(Program &program, const ShaderCaps *caps, OutputStream &out)
bool ToWGSL(Program &program, const ShaderCaps *caps, OutputStream &out)
bool ToGLSL(Program &program, const ShaderCaps *caps, OutputStream &out)
bool ToMetal(Program &program, const ShaderCaps *caps, OutputStream &out)
bool ToHLSL(Program &program, const ShaderCaps *caps, OutputStream &out)
std::unique_ptr< RP::Program > MakeRasterPipelineProgram(const SkSL::Program &program, const FunctionDefinition &function, DebugTracePriv *debugTrace, bool writeTraceOps)
std::string PrettyPrint(const std::string &string)
constexpr bool starts_with(std::string_view str, std::string_view prefix)
constexpr bool ends_with(std::string_view str, std::string_view suffix)
const FunctionDeclaration * getFunction(const char *functionName) const
static std::unique_ptr< SkWStream > as_SkWStream(SkSL::OutputStream &s)
static ResultCode process_command(SkSpan< std::string > args)
static bool consume_suffix(std::string *str, const char suffix[])
void SkDebugf(const char format[],...)
static bool set_flag(std::optional< bool > *flag, const char *name, bool value)
static bool detect_shader_settings(const std::string &text, SkSL::ProgramSettings *settings, const SkSL::ShaderCaps **caps, std::unique_ptr< SkSL::DebugTracePriv > *debugTrace)