1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC 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 8*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLModule.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLConstructorSplat.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLExpression.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLFunctionDefinition.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLLiteral.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgramElement.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLSwizzle.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLType.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/transform/SkSLProgramWriter.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/transform/SkSLTransform.h" 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 20*c8dee2aaSAndroid Build Coastguard Worker #include <utility> 21*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL { 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker class Context; 26*c8dee2aaSAndroid Build Coastguard Worker ReplaceSplatCastsWithSwizzles(const Context & context,Module & module)27*c8dee2aaSAndroid Build Coastguard Workervoid Transform::ReplaceSplatCastsWithSwizzles(const Context& context, Module& module) { 28*c8dee2aaSAndroid Build Coastguard Worker class SwizzleWriter : public ProgramWriter { 29*c8dee2aaSAndroid Build Coastguard Worker public: 30*c8dee2aaSAndroid Build Coastguard Worker SwizzleWriter(const Context& ctx) : fContext(ctx) {} 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override { 33*c8dee2aaSAndroid Build Coastguard Worker if (INHERITED::visitExpressionPtr(expr)) { 34*c8dee2aaSAndroid Build Coastguard Worker return true; 35*c8dee2aaSAndroid Build Coastguard Worker } 36*c8dee2aaSAndroid Build Coastguard Worker if (expr->is<ConstructorSplat>()) { 37*c8dee2aaSAndroid Build Coastguard Worker // If the argument is a literal, only allow floats. The swizzled-literal syntax only 38*c8dee2aaSAndroid Build Coastguard Worker // works properly for floats. 39*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Expression>& arg = expr->as<ConstructorSplat>().argument(); 40*c8dee2aaSAndroid Build Coastguard Worker if (!arg->is<Literal>() || (arg->type().isFloat() && arg->type().highPrecision())) { 41*c8dee2aaSAndroid Build Coastguard Worker // Synthesize a splat like `.xxxx`, matching the column count of the splat. 42*c8dee2aaSAndroid Build Coastguard Worker ComponentArray components; 43*c8dee2aaSAndroid Build Coastguard Worker components.push_back_n(expr->type().columns(), SwizzleComponent::X); 44*c8dee2aaSAndroid Build Coastguard Worker 45*c8dee2aaSAndroid Build Coastguard Worker // Replace the splat expression with the swizzle. 46*c8dee2aaSAndroid Build Coastguard Worker expr = Swizzle::MakeExact(fContext, expr->position(), std::move(arg), 47*c8dee2aaSAndroid Build Coastguard Worker std::move(components)); 48*c8dee2aaSAndroid Build Coastguard Worker } 49*c8dee2aaSAndroid Build Coastguard Worker } 50*c8dee2aaSAndroid Build Coastguard Worker return false; 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker 53*c8dee2aaSAndroid Build Coastguard Worker const Context& fContext; 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = ProgramWriter; 56*c8dee2aaSAndroid Build Coastguard Worker }; 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker for (std::unique_ptr<ProgramElement>& pe : module.fElements) { 59*c8dee2aaSAndroid Build Coastguard Worker if (pe->is<FunctionDefinition>()) { 60*c8dee2aaSAndroid Build Coastguard Worker SwizzleWriter writer{context}; 61*c8dee2aaSAndroid Build Coastguard Worker writer.visitStatementPtr(pe->as<FunctionDefinition>().body()); 62*c8dee2aaSAndroid Build Coastguard Worker } 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker } 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker } // namespace SkSL 67