Flutter Engine
The Flutter Engine
SkSLInterfaceBlock.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google Inc.
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
14#include "src/sksl/SkSLString.h"
22
23#include <cstddef>
24#include <cstdint>
25#include <optional>
26#include <utility>
27
28using namespace skia_private;
29
30namespace SkSL {
31
32enum class ProgramKind : int8_t;
33
35 // Unhook this InterfaceBlock from its associated Variable, since we're being deleted.
36 if (fVariable) {
37 fVariable->detachDeadInterfaceBlock();
38 }
39}
40
41static std::optional<int> find_rt_adjust_index(SkSpan<const Field> fields) {
42 for (size_t index = 0; index < fields.size(); ++index) {
43 const SkSL::Field& f = fields[index];
44 if (f.fName == SkSL::Compiler::RTADJUST_NAME) {
45 return index;
46 }
47 }
48
49 return std::nullopt;
50}
51
52std::unique_ptr<InterfaceBlock> InterfaceBlock::Convert(const Context& context,
54 const Modifiers& modifiers,
55 std::string_view typeName,
56 TArray<Field> fields,
57 std::string_view varName,
58 int arraySize) {
62 context.fErrors->error(pos, "interface blocks are not allowed in this kind of program");
63 return nullptr;
64 }
65 // Find sk_RTAdjust and error out if it's not of type `float4`.
66 std::optional<int> rtAdjustIndex = find_rt_adjust_index(fields);
67 if (rtAdjustIndex.has_value()) {
68 const Field& rtAdjustField = fields[*rtAdjustIndex];
69 if (!rtAdjustField.fType->matches(*context.fTypes.fFloat4)) {
70 context.fErrors->error(rtAdjustField.fPosition, "sk_RTAdjust must have type 'float4'");
71 return nullptr;
72 }
73 }
74 // Build a struct type corresponding to the passed-in fields.
75 const Type* baseType = context.fSymbolTable->add(context,
77 pos,
79 std::move(fields),
80 /*interfaceBlock=*/true));
81 // Array-ify the type if necessary.
82 const Type* type = baseType;
83 if (arraySize > 0) {
84 arraySize = type->convertArraySize(context, pos, pos, arraySize);
85 if (!arraySize) {
86 return nullptr;
87 }
88 type = context.fSymbolTable->addArrayDimension(context, type, arraySize);
89 }
90
91 // Error-check the interface block as if it were being declared as a global variable.
93 pos,
94 modifiers.fPosition,
95 modifiers.fLayout,
96 modifiers.fFlags,
97 type,
98 baseType,
100
101 // Create a global variable for the Interface Block.
102 std::unique_ptr<SkSL::Variable> var = SkSL::Variable::Convert(context,
103 pos,
104 modifiers.fPosition,
105 modifiers.fLayout,
106 modifiers.fFlags,
107 type,
108 pos,
109 varName,
111 return InterfaceBlock::Make(context,
112 pos,
113 context.fSymbolTable->takeOwnershipOfSymbol(std::move(var)));
114}
115
116std::unique_ptr<InterfaceBlock> InterfaceBlock::Make(const Context& context,
118 Variable* variable) {
122
124 SkSpan<const Field> fields = variable->type().componentType().fields();
125
126 if (variable->name().empty()) {
127 // This interface block is anonymous. Add each field to the top-level symbol table.
128 for (size_t i = 0; i < fields.size(); ++i) {
129 context.fSymbolTable->add(
130 context, std::make_unique<SkSL::FieldSymbol>(fields[i].fPosition, variable, i));
131 }
132 } else {
133 // Add the global variable to the top-level symbol table.
134 context.fSymbolTable->addWithoutOwnership(context, variable);
135 }
136
137 return std::make_unique<SkSL::InterfaceBlock>(pos, variable);
138}
139
140std::string InterfaceBlock::description() const {
141 std::string result = this->var()->layout().description() +
142 this->var()->modifierFlags().description() + ' ' +
143 std::string(this->typeName()) + " {\n";
144 const Type* structType = &this->var()->type();
145 if (structType->isArray()) {
146 structType = &structType->componentType();
147 }
148 for (const auto& f : structType->fields()) {
149 result += f.description() + "\n";
150 }
151 result += "}";
152 if (!this->instanceName().empty()) {
153 result += " " + std::string(this->instanceName());
154 if (this->arraySize() > 0) {
155 String::appendf(&result, "[%d]", this->arraySize());
156 }
157 }
158 return result + ";";
159}
160
161} // namespace SkSL
SkPoint pos
#define SkASSERT(cond)
Definition: SkAssert.h:116
GLenum type
const std::unique_ptr< Type > fFloat4
static constexpr const char RTADJUST_NAME[]
Definition: SkSLCompiler.h:72
const BuiltinTypes & fTypes
Definition: SkSLContext.h:30
ErrorReporter * fErrors
Definition: SkSLContext.h:36
SymbolTable * fSymbolTable
Definition: SkSLContext.h:48
ProgramConfig * fConfig
Definition: SkSLContext.h:33
void error(Position position, std::string_view msg)
Position fPosition
Definition: SkSLIRNode.h:109
static std::unique_ptr< InterfaceBlock > Make(const Context &context, Position pos, Variable *variable)
std::string description() const override
static std::unique_ptr< InterfaceBlock > Convert(const Context &context, Position pos, const Modifiers &modifiers, std::string_view typeName, skia_private::TArray< Field > fields, std::string_view varName, int arraySize)
std::string_view instanceName() const
Variable * var() const
std::string_view typeName() const
std::string description() const
void addWithoutOwnership(const Context &context, Symbol *symbol)
const Type * addArrayDimension(const Context &context, const Type *type, int arraySize)
T * takeOwnershipOfSymbol(std::unique_ptr< T > symbol)
T * add(const Context &context, std::unique_ptr< T > symbol)
std::string_view name() const
Definition: SkSLSymbol.h:51
const Type & type() const
Definition: SkSLSymbol.h:42
virtual bool isArray() const
Definition: SkSLType.h:532
virtual const Type & componentType() const
Definition: SkSLType.h:404
virtual bool isInterfaceBlock() const
Definition: SkSLType.h:544
virtual SkSpan< const Field > fields() const
Definition: SkSLType.h:469
bool matches(const Type &other) const
Definition: SkSLType.h:269
static std::unique_ptr< Type > MakeStructType(const Context &context, Position pos, std::string_view name, skia_private::TArray< Field > fields, bool interfaceBlock=false)
static void ErrorCheck(const Context &context, Position pos, Position modifiersPosition, const Layout &layout, ModifierFlags modifierFlags, const Type *type, const Type *baseType, Variable::Storage storage)
static std::unique_ptr< Variable > Convert(const Context &context, Position pos, Position modifiersPos, const Layout &layout, ModifierFlags flags, const Type *type, Position namePos, std::string_view name, Storage storage)
virtual void detachDeadInterfaceBlock()
Definition: SkSLVariable.h:129
ModifierFlags modifierFlags() const
Definition: SkSLVariable.h:89
virtual const Layout & layout() const
constexpr size_t size() const
Definition: SkSpan_impl.h:95
EMSCRIPTEN_KEEPALIVE void empty()
GAsyncResult * result
std::string void appendf(std::string *str, const char *fmt,...) SK_PRINTF_LIKE(2
Definition: SkSLString.cpp:92
static std::optional< int > find_rt_adjust_index(SkSpan< const Field > fields)
Position fPosition
Definition: SkSLType.h:84
const Type * fType
Definition: SkSLType.h:88
std::string description() const
SkSL::Layout fLayout
Definition: SkSLModifiers.h:19
Position fPosition
Definition: SkSLModifiers.h:18
SkSL::ModifierFlags fFlags
Definition: SkSLModifiers.h:20
static bool IsVertex(ProgramKind kind)
static bool IsFragment(ProgramKind kind)
static bool IsCompute(ProgramKind kind)