1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef sw_SpirvShader_hpp 16 #define sw_SpirvShader_hpp 17 18 #include "System/Types.hpp" 19 #include "Vulkan/VkDebug.hpp" 20 21 #include <string> 22 #include <vector> 23 #include <unordered_map> 24 #include <cstdint> 25 #include <type_traits> 26 #include <spirv/unified1/spirv.hpp> 27 28 namespace sw 29 { 30 class SpirvShader 31 { 32 public: 33 using InsnStore = std::vector<uint32_t>; 34 InsnStore insns; 35 36 /* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */ 37 class InsnIterator 38 { 39 InsnStore::const_iterator iter; 40 41 public: opcode() const42 spv::Op opcode() const 43 { 44 return static_cast<spv::Op>(*iter & spv::OpCodeMask); 45 } 46 wordCount() const47 uint32_t wordCount() const 48 { 49 return *iter >> spv::WordCountShift; 50 } 51 word(uint32_t n) const52 uint32_t word(uint32_t n) const 53 { 54 ASSERT(n < wordCount()); 55 return iter[n]; 56 } 57 operator !=(InsnIterator const & other) const58 bool operator!=(InsnIterator const &other) const 59 { 60 return iter != other.iter; 61 } 62 operator *() const63 InsnIterator operator*() const 64 { 65 return *this; 66 } 67 operator ++()68 InsnIterator &operator++() 69 { 70 iter += wordCount(); 71 return *this; 72 } 73 operator ++(int)74 InsnIterator const operator++(int) 75 { 76 InsnIterator ret{*this}; 77 iter += wordCount(); 78 return ret; 79 } 80 81 InsnIterator(InsnIterator const &other) = default; 82 83 InsnIterator() = default; 84 InsnIterator(InsnStore::const_iterator iter)85 explicit InsnIterator(InsnStore::const_iterator iter) : iter{iter} 86 { 87 } 88 }; 89 90 /* range-based-for interface */ begin() const91 InsnIterator begin() const 92 { 93 return InsnIterator{insns.cbegin() + 5}; 94 } 95 end() const96 InsnIterator end() const 97 { 98 return InsnIterator{insns.cend()}; 99 } 100 101 class Object 102 { 103 public: 104 InsnIterator definition; 105 spv::StorageClass storageClass; 106 uint32_t sizeInComponents = 0; 107 bool isBuiltInBlock = false; 108 109 enum class Kind 110 { 111 Unknown, /* for paranoia -- if we get left with an object in this state, the module was broken */ 112 Type, 113 Variable, 114 InterfaceVariable, 115 Constant, 116 Value, 117 } kind = Kind::Unknown; 118 }; 119 getSerialID() const120 int getSerialID() const 121 { 122 return serialID; 123 } 124 125 explicit SpirvShader(InsnStore const &insns); 126 127 struct Modes 128 { 129 bool EarlyFragmentTests : 1; 130 bool DepthReplacing : 1; 131 bool DepthGreater : 1; 132 bool DepthLess : 1; 133 bool DepthUnchanged : 1; 134 bool ContainsKill : 1; 135 136 // Compute workgroup dimensions 137 int LocalSizeX, LocalSizeY, LocalSizeZ; 138 }; 139 getModes() const140 Modes const &getModes() const 141 { 142 return modes; 143 } 144 145 enum AttribType : unsigned char 146 { 147 ATTRIBTYPE_FLOAT, 148 ATTRIBTYPE_INT, 149 ATTRIBTYPE_UINT, 150 ATTRIBTYPE_UNUSED, 151 152 ATTRIBTYPE_LAST = ATTRIBTYPE_UINT 153 }; 154 hasBuiltinInput(spv::BuiltIn b) const155 bool hasBuiltinInput(spv::BuiltIn b) const 156 { 157 return inputBuiltins.find(b) != inputBuiltins.end(); 158 } 159 160 struct Decorations 161 { 162 int32_t Location; 163 int32_t Component; 164 spv::BuiltIn BuiltIn; 165 bool HasLocation : 1; 166 bool HasComponent : 1; 167 bool HasBuiltIn : 1; 168 bool Flat : 1; 169 bool Centroid : 1; 170 bool NoPerspective : 1; 171 bool Block : 1; 172 bool BufferBlock : 1; 173 Decorationssw::SpirvShader::Decorations174 Decorations() 175 : Location{-1}, Component{0}, BuiltIn{}, HasLocation{false}, HasComponent{false}, HasBuiltIn{false}, 176 Flat{false}, 177 Centroid{false}, NoPerspective{false}, Block{false}, 178 BufferBlock{false} 179 { 180 } 181 182 Decorations(Decorations const &) = default; 183 184 void Apply(Decorations const &src); 185 186 void Apply(spv::Decoration decoration, uint32_t arg); 187 }; 188 189 std::unordered_map<uint32_t, Decorations> decorations; 190 std::unordered_map<uint32_t, std::vector<Decorations>> memberDecorations; 191 192 struct InterfaceComponent 193 { 194 AttribType Type; 195 bool Flat : 1; 196 bool Centroid : 1; 197 bool NoPerspective : 1; 198 InterfaceComponentsw::SpirvShader::InterfaceComponent199 InterfaceComponent() 200 : Type{ATTRIBTYPE_UNUSED}, Flat{false}, Centroid{false}, NoPerspective{false} 201 { 202 } 203 }; 204 205 struct BuiltinMapping 206 { 207 uint32_t Id; 208 uint32_t FirstComponent; 209 uint32_t SizeInComponents; 210 }; 211 212 std::vector<InterfaceComponent> inputs; 213 std::vector<InterfaceComponent> outputs; 214 215 private: 216 const int serialID; 217 static volatile int serialCounter; 218 Modes modes; 219 std::unordered_map<uint32_t, Object> types; 220 std::unordered_map<uint32_t, Object> defs; 221 222 using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>; 223 std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> inputBuiltins; 224 std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> outputBuiltins; 225 getType(uint32_t id) const226 Object const &getType(uint32_t id) const 227 { 228 auto it = types.find(id); 229 assert(it != types.end()); 230 return it->second; 231 } 232 getObject(uint32_t id) const233 Object const &getObject(uint32_t id) const { 234 auto it = defs.find(id); 235 assert(it != defs.end()); 236 return it->second; 237 } 238 239 void ProcessExecutionMode(InsnIterator it); 240 241 uint32_t ComputeTypeSize(InsnIterator insn); 242 243 void PopulateInterfaceSlot(std::vector<InterfaceComponent> *iface, Decorations const &d, AttribType type); 244 245 int PopulateInterfaceInner(std::vector<InterfaceComponent> *iface, uint32_t id, Decorations d); 246 247 void PopulateInterface(std::vector<InterfaceComponent> *iface, uint32_t id); 248 249 uint32_t GetConstantInt(uint32_t id); 250 251 void ProcessInterfaceVariable(Object &object); 252 }; 253 } 254 255 #endif // sw_SpirvShader_hpp 256