1 /* 2 * Copyright 2016 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 8 #ifndef SKSL_INTERFACEBLOCK 9 #define SKSL_INTERFACEBLOCK 10 11 #include "include/core/SkTypes.h" 12 #include "include/private/SkSLIRNode.h" 13 #include "include/private/SkSLProgramElement.h" 14 #include "include/sksl/SkSLPosition.h" 15 #include "src/sksl/ir/SkSLType.h" 16 #include "src/sksl/ir/SkSLVariable.h" 17 18 #include <memory> 19 #include <optional> 20 #include <string> 21 #include <string_view> 22 #include <utility> 23 24 namespace SkSL { 25 26 class Context; 27 class SymbolTable; 28 29 /** 30 * An interface block, as in: 31 * 32 * out sk_PerVertex { 33 * layout(builtin=0) float4 sk_Position; 34 * layout(builtin=1) float sk_PointSize; 35 * }; 36 * 37 * At the IR level, this is represented by a single variable of struct type. 38 */ 39 class InterfaceBlock final : public ProgramElement { 40 public: 41 inline static constexpr Kind kIRNodeKind = Kind::kInterfaceBlock; 42 InterfaceBlock(Position pos,Variable * var,std::shared_ptr<SymbolTable> typeOwner)43 InterfaceBlock(Position pos, 44 Variable* var, 45 std::shared_ptr<SymbolTable> typeOwner) 46 : INHERITED(pos, kIRNodeKind) 47 , fVariable(var) 48 , fTypeOwner(std::move(typeOwner)) { 49 SkASSERT(fVariable->type().componentType().isInterfaceBlock()); 50 fVariable->setInterfaceBlock(this); 51 } 52 53 ~InterfaceBlock() override; 54 55 // Returns an InterfaceBlock; errors are reported to the ErrorReporter. 56 // The caller is responsible for adding the InterfaceBlock to the program elements. 57 // The program's RTAdjustData will be updated if the InterfaceBlock contains sk_RTAdjust. 58 // The passed-in symbol table will be updated with a reference to the interface block variable 59 // (if it is named) or each of the interface block fields (if it is anonymous). 60 static std::unique_ptr<InterfaceBlock> Convert(const Context& context, 61 Position pos, 62 Variable* variable, 63 std::shared_ptr<SymbolTable> symbols); 64 65 // Returns an InterfaceBlock; errors are reported via SkASSERT. 66 // The caller is responsible for adding the InterfaceBlock to the program elements. 67 // If the InterfaceBlock contains sk_RTAdjust, the caller is responsible for passing its field 68 // index in `rtAdjustIndex`. 69 // The passed-in symbol table will be updated with a reference to the interface block variable 70 // (if it is named) or each of the interface block fields (if it is anonymous). 71 static std::unique_ptr<InterfaceBlock> Make(const Context& context, 72 Position pos, 73 Variable* variable, 74 std::optional<int> rtAdjustIndex, 75 std::shared_ptr<SymbolTable> symbols); 76 var()77 Variable* var() const { 78 return fVariable; 79 } 80 detachDeadVariable()81 void detachDeadVariable() { 82 fVariable = nullptr; 83 } 84 typeName()85 std::string_view typeName() const { 86 return fVariable->type().componentType().name(); 87 } 88 instanceName()89 std::string_view instanceName() const { 90 return fVariable->name(); 91 } 92 typeOwner()93 const std::shared_ptr<SymbolTable>& typeOwner() const { 94 return fTypeOwner; 95 } 96 arraySize()97 int arraySize() const { 98 return fVariable->type().isArray() ? fVariable->type().columns() : 0; 99 } 100 101 std::unique_ptr<ProgramElement> clone() const override; 102 103 std::string description() const override; 104 105 private: 106 Variable* fVariable; 107 std::shared_ptr<SymbolTable> fTypeOwner; 108 109 using INHERITED = ProgramElement; 110 }; 111 112 } // namespace SkSL 113 114 #endif 115