1/* 2 * Copyright 2020 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "include/sksl/DSLCore.h" 9 10#include "include/private/SkSLDefines.h" 11#include "include/sksl/DSLSymbols.h" 12#include "include/sksl/DSLVar.h" 13#include "src/sksl/SkSLCompiler.h" 14#include "src/sksl/SkSLThreadContext.h" 15#include "src/sksl/dsl/priv/DSLWriter.h" 16#include "src/sksl/ir/SkSLBlock.h" 17#include "src/sksl/ir/SkSLBreakStatement.h" 18#include "src/sksl/ir/SkSLContinueStatement.h" 19#include "src/sksl/ir/SkSLDiscardStatement.h" 20#include "src/sksl/ir/SkSLDoStatement.h" 21#include "src/sksl/ir/SkSLExtension.h" 22#include "src/sksl/ir/SkSLField.h" 23#include "src/sksl/ir/SkSLForStatement.h" 24#include "src/sksl/ir/SkSLFunctionCall.h" 25#include "src/sksl/ir/SkSLIfStatement.h" 26#include "src/sksl/ir/SkSLInterfaceBlock.h" 27#include "src/sksl/ir/SkSLModifiersDeclaration.h" 28#include "src/sksl/ir/SkSLReturnStatement.h" 29#include "src/sksl/ir/SkSLStructDefinition.h" 30#include "src/sksl/ir/SkSLSwitchStatement.h" 31#include "src/sksl/ir/SkSLSwizzle.h" 32#include "src/sksl/ir/SkSLTernaryExpression.h" 33#include "src/sksl/transform/SkSLTransform.h" 34 35namespace SkSL { 36 37namespace dsl { 38 39void Start(SkSL::Compiler* compiler, ProgramKind kind) { 40 Start(compiler, kind, ProgramSettings()); 41} 42 43void Start(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings) { 44 ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings, 45 compiler->moduleForProgramKind(kind), /*isModule=*/false)); 46} 47 48void StartModule(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings, 49 SkSL::ParsedModule baseModule) { 50 ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings, 51 baseModule, /*isModule=*/true)); 52} 53 54void End() { 55 SkASSERTF(!ThreadContext::InFragmentProcessor(), 56 "more calls to StartFragmentProcessor than to EndFragmentProcessor"); 57 ThreadContext::SetInstance(nullptr); 58} 59 60ErrorReporter& GetErrorReporter() { 61 return ThreadContext::GetErrorReporter(); 62} 63 64void SetErrorReporter(ErrorReporter* errorReporter) { 65 SkASSERT(errorReporter); 66 ThreadContext::SetErrorReporter(errorReporter); 67} 68 69class DSLCore { 70public: 71 static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) { 72 ThreadContext& instance = ThreadContext::Instance(); 73 SkSL::Compiler& compiler = *instance.fCompiler; 74 const SkSL::Context& context = *compiler.fContext; 75 // Variables defined in the pre-includes need their declaring elements added to the program 76 if (!instance.fConfig->fIsBuiltinCode && context.fIntrinsics) { 77 Transform::FindAndDeclareBuiltinVariables(context, instance.fConfig->fKind, 78 instance.fSharedElements); 79 } 80 Pool* pool = instance.fPool.get(); 81 auto result = std::make_unique<SkSL::Program>(std::move(source), 82 std::move(instance.fConfig), 83 compiler.fContext, 84 std::move(instance.fProgramElements), 85 std::move(instance.fSharedElements), 86 std::move(instance.fModifiersPool), 87 std::move(compiler.fSymbolTable), 88 std::move(instance.fPool), 89 instance.fInputs); 90 bool success = false; 91 if (!compiler.finalize(*result)) { 92 // Do not return programs that failed to compile. 93 } else if (!compiler.optimize(*result)) { 94 // Do not return programs that failed to optimize. 95 } else { 96 // We have a successful program! 97 success = true; 98 } 99 if (!success) { 100 ThreadContext::ReportErrors(PositionInfo()); 101 } 102 if (pool) { 103 pool->detachFromThread(); 104 } 105 SkASSERT(instance.fProgramElements.empty()); 106 SkASSERT(!ThreadContext::SymbolTable()); 107 return success ? std::move(result) : nullptr; 108 } 109 110 static DSLGlobalVar sk_FragColor() { 111 return DSLGlobalVar("sk_FragColor"); 112 } 113 114 static DSLGlobalVar sk_FragCoord() { 115 return DSLGlobalVar("sk_FragCoord"); 116 } 117 118 static DSLExpression sk_Position() { 119 return DSLExpression(Symbol("sk_Position")); 120 } 121 122 template <typename... Args> 123 static DSLPossibleExpression Call(const char* name, Args... args) { 124 SkSL::ExpressionArray argArray; 125 argArray.reserve_back(sizeof...(args)); 126 127 // in C++17, we could just do: 128 // (argArray.push_back(args.release()), ...); 129 int unused[] = {0, (static_cast<void>(argArray.push_back(args.release())), 0)...}; 130 static_cast<void>(unused); 131 132 return SkSL::FunctionCall::Convert(ThreadContext::Context(), /*line=*/-1, 133 ThreadContext::Compiler().convertIdentifier(-1, name), std::move(argArray)); 134 } 135 136 static DSLStatement Break(PositionInfo pos) { 137 return SkSL::BreakStatement::Make(pos.line()); 138 } 139 140 static DSLStatement Continue(PositionInfo pos) { 141 return SkSL::ContinueStatement::Make(pos.line()); 142 } 143 144 static void Declare(const DSLModifiers& modifiers) { 145 ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>( 146 ThreadContext::Modifiers(modifiers.fModifiers))); 147 } 148 149 static DSLStatement Declare(DSLVar& var, PositionInfo pos) { 150 if (var.fDeclared) { 151 ThreadContext::ReportError("variable has already been declared", pos); 152 } 153 var.fDeclared = true; 154 return DSLWriter::Declaration(var); 155 } 156 157 static DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) { 158 StatementArray statements; 159 for (DSLVar& v : vars) { 160 statements.push_back(Declare(v, pos).release()); 161 } 162 return SkSL::Block::MakeUnscoped(pos.line(), std::move(statements)); 163 } 164 165 static void Declare(DSLGlobalVar& var, PositionInfo pos) { 166 if (var.fDeclared) { 167 ThreadContext::ReportError("variable has already been declared", pos); 168 } 169 var.fDeclared = true; 170 std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var); 171 if (stmt) { 172 if (!stmt->isEmpty()) { 173 ThreadContext::ProgramElements().push_back( 174 std::make_unique<SkSL::GlobalVarDeclaration>(std::move(stmt))); 175 } 176 } else if (var.fName == SkSL::Compiler::FRAGCOLOR_NAME) { 177 // sk_FragColor can end up with a null declaration despite no error occurring due to 178 // specific treatment in the compiler. Ignore the null and just grab the existing 179 // variable from the symbol table. 180 const SkSL::Symbol* alreadyDeclared = (*ThreadContext::SymbolTable())[var.fName]; 181 if (alreadyDeclared && alreadyDeclared->is<Variable>()) { 182 var.fVar = &alreadyDeclared->as<Variable>(); 183 var.fInitialized = true; 184 } 185 } 186 } 187 188 static void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) { 189 for (DSLGlobalVar& v : vars) { 190 Declare(v, pos); 191 } 192 } 193 194 static DSLStatement Discard(PositionInfo pos) { 195 return SkSL::DiscardStatement::Make(pos.line()); 196 } 197 198 static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) { 199 return DoStatement::Convert(ThreadContext::Context(), stmt.release(), test.release()); 200 } 201 202 static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test, 203 DSLExpression next, DSLStatement stmt, PositionInfo pos) { 204 return ForStatement::Convert(ThreadContext::Context(), pos.line(), 205 initializer.releaseIfPossible(), test.releaseIfPossible(), 206 next.releaseIfPossible(), stmt.release(), 207 ThreadContext::SymbolTable()); 208 } 209 210 static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, 211 bool isStatic) { 212 return IfStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic, test.release(), 213 ifTrue.release(), ifFalse.releaseIfPossible()); 214 } 215 216 static void FindRTAdjust(SkSL::InterfaceBlock& intf, PositionInfo pos) { 217 const std::vector<SkSL::Type::Field>& fields = 218 intf.variable().type().componentType().fields(); 219 const Context& context = ThreadContext::Context(); 220 for (size_t i = 0; i < fields.size(); ++i) { 221 const SkSL::Type::Field& f = fields[i]; 222 if (f.fName == SkSL::Compiler::RTADJUST_NAME) { 223 if (*f.fType == *context.fTypes.fFloat4) { 224 ThreadContext::RTAdjustData& rtAdjust = ThreadContext::RTAdjustState(); 225 rtAdjust.fInterfaceBlock = &intf.variable(); 226 rtAdjust.fFieldIndex = i; 227 } else { 228 ThreadContext::ReportError("sk_RTAdjust must have type 'float4'", pos); 229 } 230 break; 231 } 232 } 233 } 234 235 static DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName, 236 SkTArray<DSLField> fields, skstd::string_view varName, 237 int arraySize, PositionInfo pos) { 238 // We need to create a new struct type for the interface block, but we don't want it in the 239 // symbol table. Since dsl::Struct automatically sticks it in the symbol table, we create it 240 // the old fashioned way with MakeStructType. 241 std::vector<SkSL::Type::Field> skslFields; 242 skslFields.reserve(fields.count()); 243 for (const DSLField& field : fields) { 244 const SkSL::Type* baseType = &field.fType.skslType(); 245 if (baseType->isArray()) { 246 baseType = &baseType->componentType(); 247 } 248 SkSL::VarDeclaration::ErrorCheck(ThreadContext::Context(), pos.line(), 249 field.fModifiers.fModifiers, baseType, Variable::Storage::kInterfaceBlock); 250 GetErrorReporter().reportPendingErrors(field.fPosition); 251 skslFields.push_back(SkSL::Type::Field(field.fModifiers.fModifiers, field.fName, 252 &field.fType.skslType())); 253 } 254 const SkSL::Type* structType = ThreadContext::SymbolTable()->takeOwnershipOfSymbol( 255 SkSL::Type::MakeStructType(pos.line(), typeName, std::move(skslFields))); 256 DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType); 257 DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(), 258 pos); 259 // Interface blocks can't be declared, so we always need to mark the var declared ourselves. 260 // We do this only when fDSLMarkVarDeclared is false, so we don't double-declare it. 261 if (!ThreadContext::Settings().fDSLMarkVarsDeclared) { 262 DSLWriter::MarkDeclared(var); 263 } 264 const SkSL::Variable* skslVar = DSLWriter::Var(var); 265 if (skslVar) { 266 auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(), 267 *skslVar, typeName, varName, arraySize, ThreadContext::SymbolTable()); 268 FindRTAdjust(*intf, pos); 269 ThreadContext::ProgramElements().push_back(std::move(intf)); 270 if (varName.empty()) { 271 const std::vector<SkSL::Type::Field>& structFields = structType->fields(); 272 for (size_t i = 0; i < structFields.size(); ++i) { 273 ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(), 274 skslVar, 275 i)); 276 } 277 } else { 278 AddToSymbolTable(var); 279 } 280 } 281 GetErrorReporter().reportPendingErrors(pos); 282 return var; 283 } 284 285 static DSLStatement Return(DSLExpression value, PositionInfo pos) { 286 // Note that because Return is called before the function in which it resides exists, at 287 // this point we do not know the function's return type. We therefore do not check for 288 // errors, or coerce the value to the correct type, until the return statement is actually 289 // added to a function. (This is done in FunctionDefinition::Convert.) 290 return SkSL::ReturnStatement::Make(pos.line(), value.releaseIfPossible()); 291 } 292 293 static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, 294 PositionInfo pos) { 295 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(), 296 ComponentArray{a}), 297 pos); 298 } 299 300 static DSLExpression Swizzle(DSLExpression base, 301 SkSL::SwizzleComponent::Type a, 302 SkSL::SwizzleComponent::Type b, 303 PositionInfo pos) { 304 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(), 305 ComponentArray{a, b}), 306 pos); 307 } 308 309 static DSLExpression Swizzle(DSLExpression base, 310 SkSL::SwizzleComponent::Type a, 311 SkSL::SwizzleComponent::Type b, 312 SkSL::SwizzleComponent::Type c, 313 PositionInfo pos) { 314 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(), 315 ComponentArray{a, b, c}), 316 pos); 317 } 318 319 static DSLExpression Swizzle(DSLExpression base, 320 SkSL::SwizzleComponent::Type a, 321 SkSL::SwizzleComponent::Type b, 322 SkSL::SwizzleComponent::Type c, 323 SkSL::SwizzleComponent::Type d, 324 PositionInfo pos) { 325 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(), 326 ComponentArray{a,b,c,d}), 327 pos); 328 } 329 330 static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue, 331 DSLExpression ifFalse) { 332 return TernaryExpression::Convert(ThreadContext::Context(), test.release(), 333 ifTrue.release(), ifFalse.release()); 334 } 335 336 static DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, 337 bool isStatic) { 338 ExpressionArray values; 339 values.reserve_back(cases.count()); 340 StatementArray caseBlocks; 341 caseBlocks.reserve_back(cases.count()); 342 for (DSLCase& c : cases) { 343 values.push_back(c.fValue.releaseIfPossible()); 344 caseBlocks.push_back(SkSL::Block::Make(/*line=*/-1, 345 std::move(c.fStatements), /*symbols=*/nullptr, /*isScope=*/false)); 346 } 347 return SwitchStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic, 348 value.release(), std::move(values), std::move(caseBlocks), 349 ThreadContext::SymbolTable()); 350 } 351 352 static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) { 353 return ForStatement::ConvertWhile(ThreadContext::Context(), /*line=*/-1, test.release(), 354 stmt.release(), ThreadContext::SymbolTable()); 355 } 356}; 357 358std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) { 359 return DSLCore::ReleaseProgram(std::move(source)); 360} 361 362DSLGlobalVar sk_FragColor() { 363 return DSLCore::sk_FragColor(); 364} 365 366DSLGlobalVar sk_FragCoord() { 367 return DSLCore::sk_FragCoord(); 368} 369 370DSLExpression sk_Position() { 371 return DSLCore::sk_Position(); 372} 373 374void AddExtension(skstd::string_view name, PositionInfo pos) { 375 ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name)); 376 ThreadContext::ReportErrors(pos); 377} 378 379DSLStatement Break(PositionInfo pos) { 380 return DSLCore::Break(pos); 381} 382 383DSLStatement Continue(PositionInfo pos) { 384 return DSLCore::Continue(pos); 385} 386 387void Declare(const DSLModifiers& modifiers, PositionInfo pos) { 388 SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind; 389 if (kind != ProgramKind::kFragment && 390 kind != ProgramKind::kVertex) { 391 ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program", 392 pos); 393 return; 394 } 395 DSLCore::Declare(modifiers); 396} 397 398// Logically, we'd want the variable's initial value to appear on here in Declare, since that 399// matches how we actually write code (and in fact that was what our first attempt looked like). 400// Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear 401// as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out 402// of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the 403// variable's initial value is unknown at the point of reference. There are probably some other 404// issues with this as well, but it is particularly dangerous when x is const, since SkSL will 405// expect its value to be known when it is referenced and will end up asserting, dereferencing a 406// null pointer, or possibly doing something else awful. 407// 408// So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is 409// always executed in the correct order. 410DSLStatement Declare(DSLVar& var, PositionInfo pos) { 411 return DSLCore::Declare(var, pos); 412} 413 414DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) { 415 return DSLCore::Declare(vars, pos); 416} 417 418void Declare(DSLGlobalVar& var, PositionInfo pos) { 419 DSLCore::Declare(var, pos); 420} 421 422void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) { 423 DSLCore::Declare(vars, pos); 424} 425 426DSLStatement Discard(PositionInfo pos) { 427 if (ThreadContext::GetProgramConfig()->fKind != ProgramKind::kFragment) { 428 ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos); 429 } 430 return DSLCore::Discard(pos); 431} 432 433DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) { 434 return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos); 435} 436 437DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next, 438 DSLStatement stmt, PositionInfo pos) { 439 return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next), 440 std::move(stmt), pos), pos); 441} 442 443DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) { 444 return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse), 445 /*isStatic=*/false), 446 pos); 447} 448 449DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName, 450 SkTArray<DSLField> fields, skstd::string_view varName, int arraySize, 451 PositionInfo pos) { 452 SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind; 453 if (kind != ProgramKind::kFragment && 454 kind != ProgramKind::kVertex) { 455 ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos); 456 return DSLGlobalVar(); 457 } 458 return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos); 459} 460 461DSLStatement Return(DSLExpression expr, PositionInfo pos) { 462 return DSLCore::Return(std::move(expr), pos); 463} 464 465DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse, 466 PositionInfo pos) { 467 return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)), 468 pos); 469} 470 471DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, 472 PositionInfo pos) { 473 return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse), 474 /*isStatic=*/true), 475 pos); 476} 477 478DSLPossibleStatement PossibleStaticSwitch(DSLExpression value, SkTArray<DSLCase> cases) { 479 return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true); 480} 481 482DSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) { 483 return DSLStatement(PossibleStaticSwitch(std::move(value), std::move(cases)), pos); 484} 485 486DSLPossibleStatement PossibleSwitch(DSLExpression value, SkTArray<DSLCase> cases) { 487 return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false); 488} 489 490DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) { 491 return DSLStatement(PossibleSwitch(std::move(value), std::move(cases)), pos); 492} 493 494DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) { 495 return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos); 496} 497 498DSLExpression Abs(DSLExpression x, PositionInfo pos) { 499 return DSLExpression(DSLCore::Call("abs", std::move(x)), pos); 500} 501 502DSLExpression All(DSLExpression x, PositionInfo pos) { 503 return DSLExpression(DSLCore::Call("all", std::move(x)), pos); 504} 505 506DSLExpression Any(DSLExpression x, PositionInfo pos) { 507 return DSLExpression(DSLCore::Call("any", std::move(x)), pos); 508} 509 510DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos) { 511 return DSLExpression(DSLCore::Call("atan", std::move(y_over_x)), pos); 512} 513 514DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos) { 515 return DSLExpression(DSLCore::Call("atan", std::move(y), std::move(x)), pos); 516} 517 518DSLExpression Ceil(DSLExpression x, PositionInfo pos) { 519 return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos); 520} 521 522DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) { 523 return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos); 524} 525 526DSLExpression Cos(DSLExpression x, PositionInfo pos) { 527 return DSLExpression(DSLCore::Call("cos", std::move(x)), pos); 528} 529 530DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) { 531 return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos); 532} 533 534DSLExpression Degrees(DSLExpression x, PositionInfo pos) { 535 return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos); 536} 537 538DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) { 539 return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos); 540} 541 542DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) { 543 return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos); 544} 545 546DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) { 547 return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos); 548} 549 550DSLExpression Exp(DSLExpression x, PositionInfo pos) { 551 return DSLExpression(DSLCore::Call("exp", std::move(x)), pos); 552} 553 554DSLExpression Exp2(DSLExpression x, PositionInfo pos) { 555 return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos); 556} 557 558DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) { 559 return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)), 560 pos); 561} 562 563DSLExpression Fract(DSLExpression x, PositionInfo pos) { 564 return DSLExpression(DSLCore::Call("fract", std::move(x)), pos); 565} 566 567DSLExpression Floor(DSLExpression x, PositionInfo pos) { 568 return DSLExpression(DSLCore::Call("floor", std::move(x)), pos); 569} 570 571DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) { 572 return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos); 573} 574 575DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) { 576 return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos); 577} 578 579DSLExpression Inverse(DSLExpression x, PositionInfo pos) { 580 return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos); 581} 582 583DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) { 584 return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos); 585} 586 587DSLExpression Length(DSLExpression x, PositionInfo pos) { 588 return DSLExpression(DSLCore::Call("length", std::move(x)), pos); 589} 590 591DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) { 592 return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos); 593} 594 595DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) { 596 return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos); 597} 598 599DSLExpression Log(DSLExpression x, PositionInfo pos) { 600 return DSLExpression(DSLCore::Call("log", std::move(x)), pos); 601} 602 603DSLExpression Log2(DSLExpression x, PositionInfo pos) { 604 return DSLExpression(DSLCore::Call("log2", std::move(x)), pos); 605} 606 607DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) { 608 return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos); 609} 610 611DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) { 612 return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos); 613} 614 615DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) { 616 return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos); 617} 618 619DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) { 620 return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos); 621} 622 623DSLExpression Normalize(DSLExpression x, PositionInfo pos) { 624 return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos); 625} 626 627DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) { 628 return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos); 629} 630 631DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) { 632 return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos); 633} 634 635DSLExpression Radians(DSLExpression x, PositionInfo pos) { 636 return DSLExpression(DSLCore::Call("radians", std::move(x)), pos); 637} 638 639DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) { 640 return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos); 641} 642 643DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) { 644 return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos); 645} 646 647DSLExpression Round(DSLExpression x, PositionInfo pos) { 648 return DSLExpression(DSLCore::Call("round", std::move(x)), pos); 649} 650 651DSLExpression Saturate(DSLExpression x, PositionInfo pos) { 652 return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos); 653} 654 655DSLExpression Sign(DSLExpression x, PositionInfo pos) { 656 return DSLExpression(DSLCore::Call("sign", std::move(x)), pos); 657} 658 659DSLExpression Sin(DSLExpression x, PositionInfo pos) { 660 return DSLExpression(DSLCore::Call("sin", std::move(x)), pos); 661} 662 663DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x, 664 PositionInfo pos) { 665 return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2), 666 std::move(x)), 667 pos); 668} 669 670DSLExpression Sqrt(DSLExpression x, PositionInfo pos) { 671 return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos); 672} 673 674DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) { 675 return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos); 676} 677 678DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, 679 PositionInfo pos) { 680 return DSLCore::Swizzle(std::move(base), a, pos); 681} 682 683DSLExpression Swizzle(DSLExpression base, 684 SkSL::SwizzleComponent::Type a, 685 SkSL::SwizzleComponent::Type b, 686 PositionInfo pos) { 687 return DSLCore::Swizzle(std::move(base), a, b, pos); 688} 689 690DSLExpression Swizzle(DSLExpression base, 691 SkSL::SwizzleComponent::Type a, 692 SkSL::SwizzleComponent::Type b, 693 SkSL::SwizzleComponent::Type c, 694 PositionInfo pos) { 695 return DSLCore::Swizzle(std::move(base), a, b, c, pos); 696} 697 698DSLExpression Swizzle(DSLExpression base, 699 SkSL::SwizzleComponent::Type a, 700 SkSL::SwizzleComponent::Type b, 701 SkSL::SwizzleComponent::Type c, 702 SkSL::SwizzleComponent::Type d, 703 PositionInfo pos) { 704 return DSLCore::Swizzle(std::move(base), a, b, c, d, pos); 705} 706 707DSLExpression Tan(DSLExpression x, PositionInfo pos) { 708 return DSLExpression(DSLCore::Call("tan", std::move(x)), pos); 709} 710 711DSLExpression Unpremul(DSLExpression x, PositionInfo pos) { 712 return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos); 713} 714 715} // namespace dsl 716 717} // namespace SkSL 718