DeclResultIdMapper.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. //===--- DeclResultIdMapper.h - AST Decl to SPIR-V <result-id> mapper ------==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef LLVM_CLANG_LIB_SPIRV_DECLRESULTIDMAPPER_H
  10. #define LLVM_CLANG_LIB_SPIRV_DECLRESULTIDMAPPER_H
  11. #include <tuple>
  12. #include <vector>
  13. #include "dxc/DXIL/DxilSemantic.h"
  14. #include "dxc/DXIL/DxilSigPoint.h"
  15. #include "dxc/Support/SPIRVOptions.h"
  16. #include "spirv/unified1/spirv.hpp11"
  17. #include "clang/AST/Attr.h"
  18. #include "clang/SPIRV/FeatureManager.h"
  19. #include "clang/SPIRV/SpirvBuilder.h"
  20. #include "llvm/ADT/DenseMap.h"
  21. #include "llvm/ADT/Optional.h"
  22. #include "llvm/ADT/SmallVector.h"
  23. #include "GlPerVertex.h"
  24. namespace clang {
  25. namespace spirv {
  26. class SpirvEmitter;
  27. /// A struct containing information about a particular HLSL semantic.
  28. struct SemanticInfo {
  29. llvm::StringRef str; ///< The original semantic string
  30. const hlsl::Semantic *semantic; ///< The unique semantic object
  31. llvm::StringRef name; ///< The semantic string without index
  32. uint32_t index; ///< The semantic index
  33. SourceLocation loc; ///< Source code location
  34. bool isValid() const { return semantic != nullptr; }
  35. inline hlsl::Semantic::Kind getKind() const;
  36. /// \brief Returns true if this semantic is a SV_Target.
  37. inline bool isTarget() const;
  38. };
  39. /// \brief The class containing HLSL and SPIR-V information about a Vulkan stage
  40. /// (builtin/input/output) variable.
  41. class StageVar {
  42. public:
  43. inline StageVar(const hlsl::SigPoint *sig, SemanticInfo semaInfo,
  44. const VKBuiltInAttr *builtin, QualType astType,
  45. uint32_t locCount)
  46. : sigPoint(sig), semanticInfo(std::move(semaInfo)), builtinAttr(builtin),
  47. type(astType), value(nullptr), isBuiltin(false),
  48. storageClass(spv::StorageClass::Max), location(nullptr),
  49. locationCount(locCount) {
  50. isBuiltin = builtinAttr != nullptr;
  51. }
  52. const hlsl::SigPoint *getSigPoint() const { return sigPoint; }
  53. const SemanticInfo &getSemanticInfo() const { return semanticInfo; }
  54. std::string getSemanticStr() const;
  55. QualType getAstType() const { return type; }
  56. SpirvVariable *getSpirvInstr() const { return value; }
  57. void setSpirvInstr(SpirvVariable *spvInstr) { value = spvInstr; }
  58. const VKBuiltInAttr *getBuiltInAttr() const { return builtinAttr; }
  59. bool isSpirvBuitin() const { return isBuiltin; }
  60. void setIsSpirvBuiltin() { isBuiltin = true; }
  61. spv::StorageClass getStorageClass() const { return storageClass; }
  62. void setStorageClass(spv::StorageClass sc) { storageClass = sc; }
  63. const VKLocationAttr *getLocationAttr() const { return location; }
  64. void setLocationAttr(const VKLocationAttr *loc) { location = loc; }
  65. const VKIndexAttr *getIndexAttr() const { return indexAttr; }
  66. void setIndexAttr(const VKIndexAttr *idx) { indexAttr = idx; }
  67. uint32_t getLocationCount() const { return locationCount; }
  68. private:
  69. /// HLSL SigPoint. It uniquely identifies each set of parameters that may be
  70. /// input or output for each entry point.
  71. const hlsl::SigPoint *sigPoint;
  72. /// Information about HLSL semantic string.
  73. SemanticInfo semanticInfo;
  74. /// SPIR-V BuiltIn attribute.
  75. const VKBuiltInAttr *builtinAttr;
  76. /// The AST QualType.
  77. QualType type;
  78. /// SPIR-V instruction.
  79. SpirvVariable *value;
  80. /// Indicates whether this stage variable should be a SPIR-V builtin.
  81. bool isBuiltin;
  82. /// SPIR-V storage class this stage variable belongs to.
  83. spv::StorageClass storageClass;
  84. /// Location assignment if input/output variable.
  85. const VKLocationAttr *location;
  86. /// Index assignment if PS output variable
  87. const VKIndexAttr *indexAttr;
  88. /// How many locations this stage variable takes.
  89. uint32_t locationCount;
  90. };
  91. class ResourceVar {
  92. public:
  93. ResourceVar(SpirvVariable *var, const Decl *decl, SourceLocation loc,
  94. const hlsl::RegisterAssignment *r, const VKBindingAttr *b,
  95. const VKCounterBindingAttr *cb, bool counter = false,
  96. bool globalsBuffer = false)
  97. : variable(var), srcLoc(loc), reg(r), binding(b), counterBinding(cb),
  98. isCounterVar(counter), isGlobalsCBuffer(globalsBuffer), arraySize(1) {
  99. if (decl) {
  100. if (const ValueDecl *valueDecl = dyn_cast<ValueDecl>(decl)) {
  101. const QualType type = valueDecl->getType();
  102. if (!type.isNull() && type->isConstantArrayType()) {
  103. if (auto constArrayType = dyn_cast<ConstantArrayType>(type)) {
  104. arraySize =
  105. static_cast<uint32_t>(constArrayType->getSize().getZExtValue());
  106. }
  107. }
  108. }
  109. }
  110. }
  111. SpirvVariable *getSpirvInstr() const { return variable; }
  112. SourceLocation getSourceLocation() const { return srcLoc; }
  113. const hlsl::RegisterAssignment *getRegister() const { return reg; }
  114. const VKBindingAttr *getBinding() const { return binding; }
  115. bool isCounter() const { return isCounterVar; }
  116. bool isGlobalsBuffer() const { return isGlobalsCBuffer; }
  117. const VKCounterBindingAttr *getCounterBinding() const {
  118. return counterBinding;
  119. }
  120. uint32_t getArraySize() const { return arraySize; }
  121. private:
  122. SpirvVariable *variable; ///< The variable
  123. SourceLocation srcLoc; ///< Source location
  124. const hlsl::RegisterAssignment *reg; ///< HLSL register assignment
  125. const VKBindingAttr *binding; ///< Vulkan binding assignment
  126. const VKCounterBindingAttr *counterBinding; ///< Vulkan counter binding
  127. bool isCounterVar; ///< Couter variable or not
  128. bool isGlobalsCBuffer; ///< $Globals cbuffer or not
  129. uint32_t arraySize; ///< Size if resource is an array
  130. };
  131. /// A (instruction-pointer, is-alias-or-not) pair for counter variables
  132. class CounterIdAliasPair {
  133. public:
  134. /// Default constructor to satisfy llvm::DenseMap
  135. CounterIdAliasPair() : counterVar(nullptr), isAlias(false) {}
  136. CounterIdAliasPair(SpirvVariable *var, bool alias)
  137. : counterVar(var), isAlias(alias) {}
  138. /// Returns the pointer to the counter variable. Dereferences first if this is
  139. /// an alias to a counter variable.
  140. SpirvInstruction *get(SpirvBuilder &builder, SpirvContext &spvContext) const;
  141. /// Stores the counter variable's pointer in srcPair to the curent counter
  142. /// variable. The current counter variable must be an alias.
  143. inline void assign(const CounterIdAliasPair &srcPair, SpirvBuilder &,
  144. SpirvContext &) const;
  145. private:
  146. SpirvVariable *counterVar;
  147. /// Note: legalization specific code
  148. bool isAlias;
  149. };
  150. /// A class for holding all the counter variables associated with a struct's
  151. /// fields
  152. ///
  153. /// A alias local RW/Append/Consume structured buffer will need an associated
  154. /// counter variable generated. There are four forms such an alias buffer can
  155. /// be:
  156. ///
  157. /// 1 (AssocCounter#1). A stand-alone variable,
  158. /// 2 (AssocCounter#2). A struct field,
  159. /// 3 (AssocCounter#3). A struct containing alias fields,
  160. /// 4 (AssocCounter#4). A nested struct containing alias fields.
  161. ///
  162. /// We consider the first two cases as *final* alias entities; The last two
  163. /// cases are called as *intermediate* alias entities, since we can still
  164. /// decompose them and get final alias entities.
  165. ///
  166. /// We need to create an associated counter variable no matter which form the
  167. /// alias buffer is in, which means we need to recursively visit all fields of a
  168. /// struct to discover if it's not AssocCounter#1. That means a hierarchy.
  169. ///
  170. /// The purpose of this class is to provide such hierarchy in a *flattened* way.
  171. /// Each field's associated counter is represented with an index vector and the
  172. /// counter's <result-id>. For example, for the following structs,
  173. ///
  174. /// struct S {
  175. /// RWStructuredBuffer s1;
  176. /// AppendStructuredBuffer s2;
  177. /// };
  178. ///
  179. /// struct T {
  180. /// S t1;
  181. /// S t2;
  182. /// };
  183. ///
  184. /// An instance of T will have four associated counters for
  185. /// field: indices, <result-id>
  186. /// t1.s1: [0, 0], <id-1>
  187. /// t1.s2: [0, 1], <id-2>
  188. /// t2.s1: [1, 0], <id-3>
  189. /// t2.s2: [1, 1], <id-4>
  190. class CounterVarFields {
  191. public:
  192. CounterVarFields() = default;
  193. /// Registers a field's associated counter.
  194. void append(const llvm::SmallVector<uint32_t, 4> &indices,
  195. SpirvVariable *counter) {
  196. fields.emplace_back(indices, counter);
  197. }
  198. /// Returns the counter associated with the field at the given indices if it
  199. /// has. Returns nullptr otherwise.
  200. const CounterIdAliasPair *
  201. get(const llvm::SmallVectorImpl<uint32_t> &indices) const;
  202. /// Assigns to all the fields' associated counter from the srcFields.
  203. /// Returns true if there are no errors during the assignment.
  204. ///
  205. /// This first overload is for assigning a struct as whole: we need to update
  206. /// all the associated counters in the target struct. This second overload is
  207. /// for assigning a potentially nested struct.
  208. bool assign(const CounterVarFields &srcFields, SpirvBuilder &,
  209. SpirvContext &) const;
  210. bool assign(const CounterVarFields &srcFields,
  211. const llvm::SmallVector<uint32_t, 4> &dstPrefix,
  212. const llvm::SmallVector<uint32_t, 4> &srcPrefix, SpirvBuilder &,
  213. SpirvContext &) const;
  214. private:
  215. struct IndexCounterPair {
  216. IndexCounterPair(const llvm::SmallVector<uint32_t, 4> &idx,
  217. SpirvVariable *counter)
  218. : indices(idx), counterVar(counter, true) {}
  219. llvm::SmallVector<uint32_t, 4> indices; ///< Index vector
  220. CounterIdAliasPair counterVar; ///< Counter variable information
  221. };
  222. llvm::SmallVector<IndexCounterPair, 4> fields;
  223. };
  224. /// \brief The class containing mappings from Clang frontend Decls to their
  225. /// corresponding SPIR-V <result-id>s.
  226. ///
  227. /// All symbols defined in the AST should be "defined" or registered in this
  228. /// class and have their <result-id>s queried from this class. In the process
  229. /// of defining a Decl, the SPIR-V module builder passed into the constructor
  230. /// will be used to generate all SPIR-V instructions required.
  231. ///
  232. /// This class acts as a middle layer to handle the mapping between HLSL
  233. /// semantics and Vulkan stage (builtin/input/output) variables. Such mapping
  234. /// is required because of the semantic differences between DirectX and
  235. /// Vulkan and the essence of HLSL as the front-end language for DirectX.
  236. /// A normal variable attached with some semantic will be translated into a
  237. /// single stage variable if it is of non-struct type. If it is of struct
  238. /// type, the fields with attached semantics will need to be translated into
  239. /// stage variables per Vulkan's requirements.
  240. class DeclResultIdMapper {
  241. public:
  242. inline DeclResultIdMapper(ASTContext &context, SpirvContext &spirvContext,
  243. SpirvBuilder &spirvBuilder, SpirvEmitter &emitter,
  244. FeatureManager &features,
  245. const SpirvCodeGenOptions &spirvOptions);
  246. /// \brief Returns the SPIR-V builtin variable.
  247. SpirvVariable *getBuiltinVar(spv::BuiltIn builtIn, QualType type,
  248. SourceLocation);
  249. /// \brief Creates the stage output variables by parsing the semantics
  250. /// attached to the given function's parameter or return value and returns
  251. /// true on success. SPIR-V instructions will also be generated to update the
  252. /// contents of the output variables by extracting sub-values from the given
  253. /// storedValue. forPCF should be set to true for handling decls in patch
  254. /// constant function.
  255. ///
  256. /// Note that the control point stage output variable of HS should be created
  257. /// by the other overload.
  258. bool createStageOutputVar(const DeclaratorDecl *decl,
  259. SpirvInstruction *storedValue, bool forPCF);
  260. /// \brief Overload for handling HS control point stage ouput variable.
  261. bool createStageOutputVar(const DeclaratorDecl *decl, uint32_t arraySize,
  262. SpirvInstruction *invocationId,
  263. SpirvInstruction *storedValue);
  264. /// \brief Creates the stage input variables by parsing the semantics attached
  265. /// to the given function's parameter and returns true on success. SPIR-V
  266. /// instructions will also be generated to load the contents from the input
  267. /// variables and composite them into one and write to *loadedValue. forPCF
  268. /// should be set to true for handling decls in patch constant function.
  269. bool createStageInputVar(const ParmVarDecl *paramDecl,
  270. SpirvInstruction **loadedValue, bool forPCF);
  271. /// \brief Creates stage variables for raytracing.
  272. SpirvVariable *createRayTracingNVStageVar(spv::StorageClass sc,
  273. const VarDecl *decl);
  274. /// \brief Creates the taskNV stage variables for payload struct variable
  275. /// and returns true on success. SPIR-V instructions will also be generated
  276. /// to load/store the contents from/to *value. payloadMemOffset is incremented
  277. /// based on payload struct member size, alignment and offset, and SPIR-V
  278. /// decorations PerTaskNV and Offset are assigned to each member.
  279. bool createPayloadStageVars(const hlsl::SigPoint *sigPoint,
  280. spv::StorageClass sc, const NamedDecl *decl,
  281. bool asInput, QualType type,
  282. const llvm::StringRef namePrefix,
  283. SpirvInstruction **value,
  284. uint32_t payloadMemOffset = 0);
  285. /// \brief Creates a function-scope paramter in the current function and
  286. /// returns its instruction.
  287. SpirvFunctionParameter *createFnParam(const ParmVarDecl *param);
  288. /// \brief Creates the counter variable associated with the given param.
  289. /// This is meant to be used for forward-declared functions and this objects
  290. /// of methods.
  291. ///
  292. /// Note: legalization specific code
  293. inline void createFnParamCounterVar(const VarDecl *param);
  294. /// \brief Creates a function-scope variable in the current function and
  295. /// returns its instruction.
  296. SpirvVariable *createFnVar(const VarDecl *var,
  297. llvm::Optional<SpirvInstruction *> init);
  298. /// \brief Creates a file-scope variable and returns its instruction.
  299. SpirvVariable *createFileVar(const VarDecl *var,
  300. llvm::Optional<SpirvInstruction *> init);
  301. /// \brief Creates an external-visible variable and returns its instruction.
  302. SpirvVariable *createExternVar(const VarDecl *var);
  303. /// \brief Returns an OpString instruction that represents the given VarDecl.
  304. /// VarDecl must be a variable of string type.
  305. ///
  306. /// This function inspects the VarDecl for an initialization expression. If
  307. /// initialization expression is not found, it will emit an error because the
  308. /// variable cannot be deduced to an OpString literal, and string variables do
  309. /// not exist in SPIR-V.
  310. ///
  311. /// Note: HLSL has the 'string' type which can be used for rare purposes such
  312. /// as printf (SPIR-V's DebugPrintf). SPIR-V does not have a 'char' or
  313. /// 'string' type, and therefore any variable of such type is never created.
  314. /// The string literal is evaluated when needed and an OpString is generated
  315. /// for it.
  316. SpirvInstruction *createOrUpdateStringVar(const VarDecl *);
  317. /// \brief Creates an Enum constant.
  318. void createEnumConstant(const EnumConstantDecl *decl);
  319. /// \brief Creates a cbuffer/tbuffer from the given decl.
  320. ///
  321. /// In the AST, cbuffer/tbuffer is represented as a HLSLBufferDecl, which is
  322. /// a DeclContext, and all fields in the buffer are represented as VarDecls.
  323. /// We cannot do the normal translation path, which will translate a field
  324. /// into a standalone variable. We need to create a single SPIR-V variable
  325. /// for the whole buffer. When we refer to the field VarDecl later, we need
  326. /// to do an extra OpAccessChain to get its pointer from the SPIR-V variable
  327. /// standing for the whole buffer.
  328. SpirvVariable *createCTBuffer(const HLSLBufferDecl *decl);
  329. /// \brief Creates a cbuffer/tbuffer from the given decl.
  330. ///
  331. /// In the AST, a variable whose type is ConstantBuffer/TextureBuffer is
  332. /// represented as a VarDecl whose DeclContext is a HLSLBufferDecl. These
  333. /// VarDecl's type is labelled as the struct upon which ConstantBuffer/
  334. /// TextureBuffer is parameterized. For a such VarDecl, we need to create
  335. /// a corresponding SPIR-V variable for it. Later referencing of such a
  336. /// VarDecl does not need an extra OpAccessChain.
  337. SpirvVariable *createCTBuffer(const VarDecl *decl);
  338. /// \brief Creates a PushConstant block from the given decl.
  339. SpirvVariable *createPushConstant(const VarDecl *decl);
  340. /// \brief Creates the $Globals cbuffer.
  341. void createGlobalsCBuffer(const VarDecl *var);
  342. /// \brief Returns the suitable type for the given decl, considering the
  343. /// given decl could possibly be created as an alias variable. If true, a
  344. /// pointer-to-the-value type will be returned, otherwise, just return the
  345. /// normal value type. For an alias variable having a associated counter, the
  346. /// counter variable will also be emitted.
  347. ///
  348. /// If the type is for an alias variable, writes true to *shouldBeAlias and
  349. /// writes storage class, layout rule, and valTypeId to *info.
  350. ///
  351. /// Note: legalization specific code
  352. QualType
  353. getTypeAndCreateCounterForPotentialAliasVar(const DeclaratorDecl *var,
  354. bool *shouldBeAlias = nullptr);
  355. /// \brief Sets the entry function.
  356. void setEntryFunction(SpirvFunction *fn) { entryFunction = fn; }
  357. /// Raytracing specific functions
  358. /// \brief Handle specific implicit declarations present only in raytracing
  359. /// stages.
  360. void createRayTracingNVImplicitVar(const VarDecl *varDecl);
  361. /// \brief Creates a ShaderRecordBufferNV block from the given decl.
  362. SpirvVariable *createShaderRecordBufferNV(const VarDecl *decl);
  363. SpirvVariable *createShaderRecordBufferNV(const HLSLBufferDecl *decl);
  364. private:
  365. /// The struct containing SPIR-V information of a AST Decl.
  366. struct DeclSpirvInfo {
  367. /// Default constructor to satisfy DenseMap
  368. DeclSpirvInfo() : instr(nullptr), indexInCTBuffer(-1) {}
  369. DeclSpirvInfo(SpirvInstruction *instr_, int index = -1)
  370. : instr(instr_), indexInCTBuffer(index) {}
  371. /// Implicit conversion to SpirvInstruction*.
  372. operator SpirvInstruction *() const { return instr; }
  373. SpirvInstruction *instr;
  374. /// Value >= 0 means that this decl is a VarDecl inside a cbuffer/tbuffer
  375. /// and this is the index; value < 0 means this is just a standalone decl.
  376. int indexInCTBuffer;
  377. };
  378. /// \brief Returns the SPIR-V information for the given decl.
  379. /// Returns nullptr if no such decl was previously registered.
  380. const DeclSpirvInfo *getDeclSpirvInfo(const ValueDecl *decl) const;
  381. public:
  382. /// \brief Returns the information for the given decl.
  383. ///
  384. /// This method will panic if the given decl is not registered.
  385. SpirvInstruction *getDeclEvalInfo(const ValueDecl *decl, SourceLocation loc);
  386. /// \brief Returns the instruction pointer for the given function if already
  387. /// registered; otherwise, treats the given function as a normal decl and
  388. /// returns a newly created instruction for it.
  389. SpirvFunction *getOrRegisterFn(const FunctionDecl *fn);
  390. /// Registers that the given decl should be translated into the given spec
  391. /// constant.
  392. void registerSpecConstant(const VarDecl *decl,
  393. SpirvInstruction *specConstant);
  394. /// \brief Returns the associated counter's (instr-ptr, is-alias-or-not)
  395. /// pair for the given {RW|Append|Consume}StructuredBuffer variable.
  396. /// If indices is not nullptr, walks trhough the fields of the decl, expected
  397. /// to be of struct type, using the indices to find the field. Returns nullptr
  398. /// if the given decl has no associated counter variable created.
  399. const CounterIdAliasPair *getCounterIdAliasPair(
  400. const DeclaratorDecl *decl,
  401. const llvm::SmallVector<uint32_t, 4> *indices = nullptr);
  402. /// \brief Returns all the associated counters for the given decl. The decl is
  403. /// expected to be a struct containing alias RW/Append/Consume structured
  404. /// buffers. Returns nullptr if it does not.
  405. const CounterVarFields *getCounterVarFields(const DeclaratorDecl *decl);
  406. /// \brief Returns the <type-id> for the given cbuffer, tbuffer,
  407. /// ConstantBuffer, TextureBuffer, or push constant block.
  408. ///
  409. /// Note: we need this method because constant/texture buffers and push
  410. /// constant blocks are all represented as normal struct types upon which
  411. /// they are parameterized. That is different from structured buffers,
  412. /// for which we can tell they are not normal structs by investigating
  413. /// the name. But for constant/texture buffers and push constant blocks,
  414. /// we need to have the additional Block/BufferBlock decoration to keep
  415. /// type consistent. Normal translation path for structs via TypeTranslator
  416. /// won't attach Block/BufferBlock decoration.
  417. const SpirvType *getCTBufferPushConstantType(const DeclContext *decl);
  418. /// \brief Returns all defined stage (builtin/input/ouput) variables in this
  419. /// mapper.
  420. std::vector<SpirvVariable *> collectStageVars() const;
  421. /// \brief Writes out the contents in the function parameter for the GS
  422. /// stream output to the corresponding stage output variables in a recursive
  423. /// manner. Returns true on success, false if errors occur.
  424. ///
  425. /// decl is the Decl with semantic string attached and will be used to find
  426. /// the stage output variable to write to, value is the SPIR-V variable to
  427. /// read data from.
  428. ///
  429. /// This method is specially for writing back per-vertex data at the time of
  430. /// OpEmitVertex in GS.
  431. bool writeBackOutputStream(const NamedDecl *decl, QualType type,
  432. SpirvInstruction *value);
  433. /// \brief Negates to get the additive inverse of SV_Position.y if requested.
  434. SpirvInstruction *invertYIfRequested(SpirvInstruction *position,
  435. SourceLocation loc);
  436. /// \brief Reciprocates to get the multiplicative inverse of SV_Position.w
  437. /// if requested.
  438. SpirvInstruction *invertWIfRequested(SpirvInstruction *position,
  439. SourceLocation loc);
  440. /// \brief Decorates all stage input and output variables with proper
  441. /// location and returns true on success.
  442. ///
  443. /// This method will write the location assignment into the module under
  444. /// construction.
  445. inline bool decorateStageIOLocations();
  446. /// \brief Decorates all resource variables with proper set and binding
  447. /// numbers and returns true on success.
  448. ///
  449. /// This method will write the set and binding number assignment into the
  450. /// module under construction.
  451. bool decorateResourceBindings();
  452. bool requiresLegalization() const { return needsLegalization; }
  453. /// \brief Returns the given decl's HLSL semantic information.
  454. static SemanticInfo getStageVarSemantic(const NamedDecl *decl);
  455. /// \brief Returns SPIR-V instruction for given stage var decl.
  456. SpirvInstruction *getStageVarInstruction(const DeclaratorDecl *decl) {
  457. auto *value = stageVarInstructions.lookup(decl);
  458. assert(value);
  459. return value;
  460. }
  461. private:
  462. /// \brief Wrapper method to create a fatal error message and report it
  463. /// in the diagnostic engine associated with this consumer.
  464. template <unsigned N>
  465. DiagnosticBuilder emitFatalError(const char (&message)[N],
  466. SourceLocation loc) {
  467. const auto diagId =
  468. diags.getCustomDiagID(clang::DiagnosticsEngine::Fatal, message);
  469. return diags.Report(loc, diagId);
  470. }
  471. /// \brief Wrapper method to create an error message and report it
  472. /// in the diagnostic engine associated with this consumer.
  473. template <unsigned N>
  474. DiagnosticBuilder emitError(const char (&message)[N], SourceLocation loc) {
  475. const auto diagId =
  476. diags.getCustomDiagID(clang::DiagnosticsEngine::Error, message);
  477. return diags.Report(loc, diagId);
  478. }
  479. /// \brief Wrapper method to create a warning message and report it
  480. /// in the diagnostic engine associated with this consumer.
  481. template <unsigned N>
  482. DiagnosticBuilder emitWarning(const char (&message)[N], SourceLocation loc) {
  483. const auto diagId =
  484. diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, message);
  485. return diags.Report(loc, diagId);
  486. }
  487. /// \brief Wrapper method to create a note message and report it
  488. /// in the diagnostic engine associated with this consumer.
  489. template <unsigned N>
  490. DiagnosticBuilder emitNote(const char (&message)[N], SourceLocation loc) {
  491. const auto diagId =
  492. diags.getCustomDiagID(clang::DiagnosticsEngine::Note, message);
  493. return diags.Report(loc, diagId);
  494. }
  495. /// \brief Checks whether some semantic is used more than once and returns
  496. /// true if no such cases. Returns false otherwise.
  497. bool checkSemanticDuplication(bool forInput);
  498. /// \brief Decorates all stage input (if forInput is true) or output (if
  499. /// forInput is false) variables with proper location and returns true on
  500. /// success.
  501. ///
  502. /// This method will write the location assignment into the module under
  503. /// construction.
  504. bool finalizeStageIOLocations(bool forInput);
  505. /// \brief An enum class for representing what the DeclContext is used for
  506. enum class ContextUsageKind {
  507. CBuffer,
  508. TBuffer,
  509. PushConstant,
  510. Globals,
  511. ShaderRecordBufferNV,
  512. };
  513. /// Creates a variable of struct type with explicit layout decorations.
  514. /// The sub-Decls in the given DeclContext will be treated as the struct
  515. /// fields. The struct type will be named as typeName, and the variable
  516. /// will be named as varName.
  517. ///
  518. /// This method should only be used for cbuffers/ContantBuffers, tbuffers/
  519. /// TextureBuffers, and PushConstants. usageKind must be set properly
  520. /// depending on the usage kind.
  521. ///
  522. /// If arraySize is 0, the variable will be created as a struct ; if arraySize
  523. /// is > 0, the variable will be created as an array; if arraySize is -1, the
  524. /// variable will be created as a runtime array.
  525. ///
  526. /// Panics if the DeclContext is neither HLSLBufferDecl or RecordDecl.
  527. SpirvVariable *createStructOrStructArrayVarOfExplicitLayout(
  528. const DeclContext *decl, int arraySize, ContextUsageKind usageKind,
  529. llvm::StringRef typeName, llvm::StringRef varName);
  530. /// Creates all the stage variables mapped from semantics on the given decl.
  531. /// Returns true on sucess.
  532. ///
  533. /// If decl is of struct type, this means flattening it and create stand-
  534. /// alone variables for each field. If arraySize is not zero, the created
  535. /// stage variables will have an additional arrayness over its original type.
  536. /// This is for supporting HS/DS/GS, which takes in primitives containing
  537. /// multiple vertices. asType should be the type we are treating decl as;
  538. /// For HS/DS/GS, the outermost arrayness should be discarded and use
  539. /// arraySize instead.
  540. ///
  541. /// Also performs reading the stage variables and compose a temporary value
  542. /// of the given type and writing into *value, if asInput is true. Otherwise,
  543. /// Decomposes the *value according to type and writes back into the stage
  544. /// output variables, unless noWriteBack is set to true. noWriteBack is used
  545. /// by GS since in GS we manually control write back using .Append() method.
  546. ///
  547. /// invocationId is only used for HS to indicate the index of the output
  548. /// array element to write to.
  549. ///
  550. /// Assumes the decl has semantic attached to itself or to its fields.
  551. /// If inheritSemantic is valid, it will override all semantics attached to
  552. /// the children of this decl, and the children of this decl will be using
  553. /// the semantic in inheritSemantic, with index increasing sequentially.
  554. bool createStageVars(const hlsl::SigPoint *sigPoint, const NamedDecl *decl,
  555. bool asInput, QualType asType, uint32_t arraySize,
  556. const llvm::StringRef namePrefix,
  557. llvm::Optional<SpirvInstruction *> invocationId,
  558. SpirvInstruction **value, bool noWriteBack,
  559. SemanticInfo *inheritSemantic);
  560. /// Creates the SPIR-V variable instruction for the given StageVar and returns
  561. /// the instruction. Also sets whether the StageVar is a SPIR-V builtin and
  562. /// its storage class accordingly. name will be used as the debug name when
  563. /// creating a stage input/output variable.
  564. SpirvVariable *createSpirvStageVar(StageVar *, const NamedDecl *decl,
  565. const llvm::StringRef name,
  566. SourceLocation);
  567. /// Returns true if all vk:: attributes usages are valid.
  568. bool validateVKAttributes(const NamedDecl *decl);
  569. /// Returns true if all vk::builtin usages are valid.
  570. bool validateVKBuiltins(const NamedDecl *decl,
  571. const hlsl::SigPoint *sigPoint);
  572. /// Methods for creating counter variables associated with the given decl.
  573. /// Creates assoicated counter variables for all AssocCounter cases (see the
  574. /// comment of CounterVarFields).
  575. void createCounterVarForDecl(const DeclaratorDecl *decl);
  576. /// Creates the associated counter variable for final RW/Append/Consume
  577. /// structured buffer. Handles AssocCounter#1 and AssocCounter#2 (see the
  578. /// comment of CounterVarFields).
  579. ///
  580. /// declId is the SPIR-V instruction for the given decl. It should be non-zero
  581. /// for non-alias buffers.
  582. ///
  583. /// The counter variable will be created as an alias variable (of
  584. /// pointer-to-pointer type in Private storage class) if isAlias is true.
  585. ///
  586. /// Note: isAlias - legalization specific code
  587. void
  588. createCounterVar(const DeclaratorDecl *decl, SpirvInstruction *declInstr,
  589. bool isAlias,
  590. const llvm::SmallVector<uint32_t, 4> *indices = nullptr);
  591. /// Creates all assoicated counter variables by recursively visiting decl's
  592. /// fields. Handles AssocCounter#3 and AssocCounter#4 (see the comment of
  593. /// CounterVarFields).
  594. inline void createFieldCounterVars(const DeclaratorDecl *decl);
  595. void createFieldCounterVars(const DeclaratorDecl *rootDecl,
  596. const DeclaratorDecl *decl,
  597. llvm::SmallVector<uint32_t, 4> *indices);
  598. /// Decorates varInstr of the given asType with proper interpolation modes
  599. /// considering the attributes on the given decl.
  600. void decorateInterpolationMode(const NamedDecl *decl, QualType asType,
  601. SpirvVariable *varInstr);
  602. /// Returns the proper SPIR-V storage class (Input or Output) for the given
  603. /// SigPoint.
  604. spv::StorageClass getStorageClassForSigPoint(const hlsl::SigPoint *);
  605. /// Returns true if the given SPIR-V stage variable has Input storage class.
  606. inline bool isInputStorageClass(const StageVar &v);
  607. private:
  608. SpirvBuilder &spvBuilder;
  609. SpirvEmitter &theEmitter;
  610. const SpirvCodeGenOptions &spirvOptions;
  611. ASTContext &astContext;
  612. SpirvContext &spvContext;
  613. DiagnosticsEngine &diags;
  614. SpirvFunction *entryFunction;
  615. /// Mapping of all Clang AST decls to their instruction pointers.
  616. llvm::DenseMap<const ValueDecl *, DeclSpirvInfo> astDecls;
  617. llvm::DenseMap<const ValueDecl *, SpirvFunction *> astFunctionDecls;
  618. /// Vector of all defined stage variables.
  619. llvm::SmallVector<StageVar, 8> stageVars;
  620. /// Mapping from Clang AST decls to the corresponding stage variables.
  621. /// This field is only used by GS for manually emitting vertices, when
  622. /// we need to query the output stage variables involved in writing back. For
  623. /// other cases, stage variable reading and writing is done at the time of
  624. /// creating that stage variable, so that we don't need to query them again
  625. /// for reading and writing.
  626. llvm::DenseMap<const ValueDecl *, SpirvVariable *> stageVarInstructions;
  627. /// Vector of all defined resource variables.
  628. llvm::SmallVector<ResourceVar, 8> resourceVars;
  629. /// Mapping from {RW|Append|Consume}StructuredBuffers to their
  630. /// counter variables' (instr-ptr, is-alias-or-not) pairs
  631. ///
  632. /// conterVars holds entities of AssocCounter#1, fieldCounterVars holds
  633. /// entities of the rest.
  634. llvm::DenseMap<const DeclaratorDecl *, CounterIdAliasPair> counterVars;
  635. llvm::DenseMap<const DeclaratorDecl *, CounterVarFields> fieldCounterVars;
  636. /// Mapping from cbuffer/tbuffer/ConstantBuffer/TextureBufer/push-constant
  637. /// to the SPIR-V type.
  638. llvm::DenseMap<const DeclContext *, const SpirvType *> ctBufferPCTypes;
  639. /// The SPIR-V builtin variables accessed by WaveGetLaneCount(),
  640. /// WaveGetLaneIndex() and ray tracing builtins.
  641. ///
  642. /// These are the only few cases where SPIR-V builtin variables are accessed
  643. /// using HLSL intrinsic function calls. All other builtin variables are
  644. /// accessed using stage IO variables.
  645. llvm::DenseMap<uint32_t, SpirvVariable *> builtinToVarMap;
  646. /// Whether the translated SPIR-V binary needs legalization.
  647. ///
  648. /// The following cases will require legalization:
  649. ///
  650. /// 1. Opaque types (textures, samplers) within structs
  651. /// 2. Structured buffer aliasing
  652. /// 3. Using SPIR-V instructions not allowed in the currect shader stage
  653. ///
  654. /// This covers the second case:
  655. ///
  656. /// When we have a kind of structured or byte buffer, meaning one of the
  657. /// following
  658. ///
  659. /// * StructuredBuffer
  660. /// * RWStructuredBuffer
  661. /// * AppendStructuredBuffer
  662. /// * ConsumeStructuredBuffer
  663. /// * ByteAddressStructuredBuffer
  664. /// * RWByteAddressStructuredBuffer
  665. ///
  666. /// and assigning to them (using operator=, passing in as function parameter,
  667. /// returning as function return), we need legalization.
  668. ///
  669. /// All variable definitions (including static/non-static local/global
  670. /// variables, function parameters/returns) will gain another level of
  671. /// pointerness, unless they will generate externally visible SPIR-V
  672. /// variables. So variables and parameters will be of pointer-to-pointer type,
  673. /// while function returns will be of pointer type. We adopt this mechanism to
  674. /// convey to the legalization passes that they are *alias* variables, and
  675. /// all accesses should happen to the aliased-to-variables. Loading such an
  676. /// alias variable will give the pointer to the aliased-to-variable, while
  677. /// storing into such an alias variable should write the pointer to the
  678. /// aliased-to-variable.
  679. ///
  680. /// Based on the above, CodeGen should take care of the following AST nodes:
  681. ///
  682. /// * Definition of alias variables: should add another level of pointers
  683. /// * Assigning non-alias variables to alias variables: should avoid the load
  684. /// over the non-alias variables
  685. /// * Accessing alias variables: should load the pointer first and then
  686. /// further compose access chains.
  687. ///
  688. /// Note that the associated counters bring about their own complication.
  689. /// We also need to apply the alias mechanism for them.
  690. ///
  691. /// If this is true, SPIRV-Tools legalization passes will be executed after
  692. /// the translation to legalize the generated SPIR-V binary.
  693. ///
  694. /// Note: legalization specific code
  695. bool needsLegalization;
  696. public:
  697. /// The gl_PerVertex structs for both input and output
  698. GlPerVertex glPerVertex;
  699. };
  700. hlsl::Semantic::Kind SemanticInfo::getKind() const {
  701. assert(semantic);
  702. return semantic->GetKind();
  703. }
  704. bool SemanticInfo::isTarget() const {
  705. return semantic && semantic->GetKind() == hlsl::Semantic::Kind::Target;
  706. }
  707. void CounterIdAliasPair::assign(const CounterIdAliasPair &srcPair,
  708. SpirvBuilder &builder,
  709. SpirvContext &context) const {
  710. assert(isAlias);
  711. builder.createStore(counterVar, srcPair.get(builder, context),
  712. /* SourceLocation */ {});
  713. }
  714. DeclResultIdMapper::DeclResultIdMapper(ASTContext &context,
  715. SpirvContext &spirvContext,
  716. SpirvBuilder &spirvBuilder,
  717. SpirvEmitter &emitter,
  718. FeatureManager &features,
  719. const SpirvCodeGenOptions &options)
  720. : spvBuilder(spirvBuilder), theEmitter(emitter), spirvOptions(options),
  721. astContext(context), spvContext(spirvContext),
  722. diags(context.getDiagnostics()), entryFunction(nullptr),
  723. needsLegalization(false),
  724. glPerVertex(context, spirvContext, spirvBuilder) {}
  725. bool DeclResultIdMapper::decorateStageIOLocations() {
  726. if (spvContext.isRay() || spvContext.isAS()) {
  727. // No location assignment for any raytracing stage variables or
  728. // amplification shader variables
  729. return true;
  730. }
  731. // Try both input and output even if input location assignment failed
  732. return finalizeStageIOLocations(true) & finalizeStageIOLocations(false);
  733. }
  734. bool DeclResultIdMapper::isInputStorageClass(const StageVar &v) {
  735. return getStorageClassForSigPoint(v.getSigPoint()) ==
  736. spv::StorageClass::Input;
  737. }
  738. void DeclResultIdMapper::createFnParamCounterVar(const VarDecl *param) {
  739. createCounterVarForDecl(param);
  740. }
  741. void DeclResultIdMapper::createFieldCounterVars(const DeclaratorDecl *decl) {
  742. llvm::SmallVector<uint32_t, 4> indices;
  743. createFieldCounterVars(decl, decl, &indices);
  744. }
  745. } // end namespace spirv
  746. } // end namespace clang
  747. #endif