/* * Copyright 2024 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/sksl/SkSLModule.h" #include "src/sksl/ir/SkSLConstructorSplat.h" #include "src/sksl/ir/SkSLExpression.h" #include "src/sksl/ir/SkSLFunctionDefinition.h" #include "src/sksl/ir/SkSLLiteral.h" #include "src/sksl/ir/SkSLProgramElement.h" #include "src/sksl/ir/SkSLSwizzle.h" #include "src/sksl/ir/SkSLType.h" #include "src/sksl/transform/SkSLProgramWriter.h" #include "src/sksl/transform/SkSLTransform.h" #include #include #include namespace SkSL { class Context; void Transform::ReplaceSplatCastsWithSwizzles(const Context& context, Module& module) { class SwizzleWriter : public ProgramWriter { public: SwizzleWriter(const Context& ctx) : fContext(ctx) {} bool visitExpressionPtr(std::unique_ptr& expr) override { if (INHERITED::visitExpressionPtr(expr)) { return true; } if (expr->is()) { // If the argument is a literal, only allow floats. The swizzled-literal syntax only // works properly for floats. std::unique_ptr& arg = expr->as().argument(); if (!arg->is() || (arg->type().isFloat() && arg->type().highPrecision())) { // Synthesize a splat like `.xxxx`, matching the column count of the splat. ComponentArray components; components.push_back_n(expr->type().columns(), SwizzleComponent::X); // Replace the splat expression with the swizzle. expr = Swizzle::MakeExact(fContext, expr->position(), std::move(arg), std::move(components)); } } return false; } const Context& fContext; using INHERITED = ProgramWriter; }; for (std::unique_ptr& pe : module.fElements) { if (pe->is()) { SwizzleWriter writer{context}; writer.visitStatementPtr(pe->as().body()); } } } } // namespace SkSL