DeclResultIdMapper.h 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  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), declaration(decl), srcLoc(loc), reg(r), binding(b),
  98. counterBinding(cb), isCounterVar(counter),
  99. isGlobalsCBuffer(globalsBuffer) {}
  100. SpirvVariable *getSpirvInstr() const { return variable; }
  101. const Decl *getDeclaration() const { return declaration; }
  102. SourceLocation getSourceLocation() const { return srcLoc; }
  103. const hlsl::RegisterAssignment *getRegister() const { return reg; }
  104. const VKBindingAttr *getBinding() const { return binding; }
  105. bool isCounter() const { return isCounterVar; }
  106. bool isGlobalsBuffer() const { return isGlobalsCBuffer; }
  107. const VKCounterBindingAttr *getCounterBinding() const {
  108. return counterBinding;
  109. }
  110. private:
  111. SpirvVariable *variable; ///< The variable
  112. const Decl *declaration; ///< The declaration
  113. SourceLocation srcLoc; ///< Source location
  114. const hlsl::RegisterAssignment *reg; ///< HLSL register assignment
  115. const VKBindingAttr *binding; ///< Vulkan binding assignment
  116. const VKCounterBindingAttr *counterBinding; ///< Vulkan counter binding
  117. bool isCounterVar; ///< Couter variable or not
  118. bool isGlobalsCBuffer; ///< $Globals cbuffer or not
  119. };
  120. /// A (instruction-pointer, is-alias-or-not) pair for counter variables
  121. class CounterIdAliasPair {
  122. public:
  123. /// Default constructor to satisfy llvm::DenseMap
  124. CounterIdAliasPair() : counterVar(nullptr), isAlias(false) {}
  125. CounterIdAliasPair(SpirvVariable *var, bool alias)
  126. : counterVar(var), isAlias(alias) {}
  127. /// Returns the pointer to the counter variable. Dereferences first if this is
  128. /// an alias to a counter variable.
  129. SpirvInstruction *get(SpirvBuilder &builder, SpirvContext &spvContext) const;
  130. /// Stores the counter variable's pointer in srcPair to the curent counter
  131. /// variable. The current counter variable must be an alias.
  132. inline void assign(const CounterIdAliasPair &srcPair, SpirvBuilder &,
  133. SpirvContext &) const;
  134. private:
  135. SpirvVariable *counterVar;
  136. /// Note: legalization specific code
  137. bool isAlias;
  138. };
  139. /// A class for holding all the counter variables associated with a struct's
  140. /// fields
  141. ///
  142. /// A alias local RW/Append/Consume structured buffer will need an associated
  143. /// counter variable generated. There are four forms such an alias buffer can
  144. /// be:
  145. ///
  146. /// 1 (AssocCounter#1). A stand-alone variable,
  147. /// 2 (AssocCounter#2). A struct field,
  148. /// 3 (AssocCounter#3). A struct containing alias fields,
  149. /// 4 (AssocCounter#4). A nested struct containing alias fields.
  150. ///
  151. /// We consider the first two cases as *final* alias entities; The last two
  152. /// cases are called as *intermediate* alias entities, since we can still
  153. /// decompose them and get final alias entities.
  154. ///
  155. /// We need to create an associated counter variable no matter which form the
  156. /// alias buffer is in, which means we need to recursively visit all fields of a
  157. /// struct to discover if it's not AssocCounter#1. That means a hierarchy.
  158. ///
  159. /// The purpose of this class is to provide such hierarchy in a *flattened* way.
  160. /// Each field's associated counter is represented with an index vector and the
  161. /// counter's <result-id>. For example, for the following structs,
  162. ///
  163. /// struct S {
  164. /// RWStructuredBuffer s1;
  165. /// AppendStructuredBuffer s2;
  166. /// };
  167. ///
  168. /// struct T {
  169. /// S t1;
  170. /// S t2;
  171. /// };
  172. ///
  173. /// An instance of T will have four associated counters for
  174. /// field: indices, <result-id>
  175. /// t1.s1: [0, 0], <id-1>
  176. /// t1.s2: [0, 1], <id-2>
  177. /// t2.s1: [1, 0], <id-3>
  178. /// t2.s2: [1, 1], <id-4>
  179. class CounterVarFields {
  180. public:
  181. CounterVarFields() = default;
  182. /// Registers a field's associated counter.
  183. void append(const llvm::SmallVector<uint32_t, 4> &indices,
  184. SpirvVariable *counter) {
  185. fields.emplace_back(indices, counter);
  186. }
  187. /// Returns the counter associated with the field at the given indices if it
  188. /// has. Returns nullptr otherwise.
  189. const CounterIdAliasPair *
  190. get(const llvm::SmallVectorImpl<uint32_t> &indices) const;
  191. /// Assigns to all the fields' associated counter from the srcFields.
  192. /// Returns true if there are no errors during the assignment.
  193. ///
  194. /// This first overload is for assigning a struct as whole: we need to update
  195. /// all the associated counters in the target struct. This second overload is
  196. /// for assigning a potentially nested struct.
  197. bool assign(const CounterVarFields &srcFields, SpirvBuilder &,
  198. SpirvContext &) const;
  199. bool assign(const CounterVarFields &srcFields,
  200. const llvm::SmallVector<uint32_t, 4> &dstPrefix,
  201. const llvm::SmallVector<uint32_t, 4> &srcPrefix, SpirvBuilder &,
  202. SpirvContext &) const;
  203. private:
  204. struct IndexCounterPair {
  205. IndexCounterPair(const llvm::SmallVector<uint32_t, 4> &idx,
  206. SpirvVariable *counter)
  207. : indices(idx), counterVar(counter, true) {}
  208. llvm::SmallVector<uint32_t, 4> indices; ///< Index vector
  209. CounterIdAliasPair counterVar; ///< Counter variable information
  210. };
  211. llvm::SmallVector<IndexCounterPair, 4> fields;
  212. };
  213. /// \brief The class containing mappings from Clang frontend Decls to their
  214. /// corresponding SPIR-V <result-id>s.
  215. ///
  216. /// All symbols defined in the AST should be "defined" or registered in this
  217. /// class and have their <result-id>s queried from this class. In the process
  218. /// of defining a Decl, the SPIR-V module builder passed into the constructor
  219. /// will be used to generate all SPIR-V instructions required.
  220. ///
  221. /// This class acts as a middle layer to handle the mapping between HLSL
  222. /// semantics and Vulkan stage (builtin/input/output) variables. Such mapping
  223. /// is required because of the semantic differences between DirectX and
  224. /// Vulkan and the essence of HLSL as the front-end language for DirectX.
  225. /// A normal variable attached with some semantic will be translated into a
  226. /// single stage variable if it is of non-struct type. If it is of struct
  227. /// type, the fields with attached semantics will need to be translated into
  228. /// stage variables per Vulkan's requirements.
  229. class DeclResultIdMapper {
  230. public:
  231. inline DeclResultIdMapper(ASTContext &context, SpirvContext &spirvContext,
  232. SpirvBuilder &spirvBuilder, SpirvEmitter &emitter,
  233. FeatureManager &features,
  234. const SpirvCodeGenOptions &spirvOptions);
  235. /// \brief Returns the SPIR-V builtin variable.
  236. SpirvVariable *getBuiltinVar(spv::BuiltIn builtIn, QualType type,
  237. SourceLocation);
  238. /// \brief Creates the stage output variables by parsing the semantics
  239. /// attached to the given function's parameter or return value and returns
  240. /// true on success. SPIR-V instructions will also be generated to update the
  241. /// contents of the output variables by extracting sub-values from the given
  242. /// storedValue. forPCF should be set to true for handling decls in patch
  243. /// constant function.
  244. ///
  245. /// Note that the control point stage output variable of HS should be created
  246. /// by the other overload.
  247. bool createStageOutputVar(const DeclaratorDecl *decl,
  248. SpirvInstruction *storedValue, bool forPCF);
  249. /// \brief Overload for handling HS control point stage ouput variable.
  250. bool createStageOutputVar(const DeclaratorDecl *decl, uint32_t arraySize,
  251. SpirvInstruction *invocationId,
  252. SpirvInstruction *storedValue);
  253. /// \brief Creates the stage input variables by parsing the semantics attached
  254. /// to the given function's parameter and returns true on success. SPIR-V
  255. /// instructions will also be generated to load the contents from the input
  256. /// variables and composite them into one and write to *loadedValue. forPCF
  257. /// should be set to true for handling decls in patch constant function.
  258. bool createStageInputVar(const ParmVarDecl *paramDecl,
  259. SpirvInstruction **loadedValue, bool forPCF);
  260. /// \brief Creates stage variables for raytracing.
  261. SpirvVariable *createRayTracingNVStageVar(spv::StorageClass sc,
  262. const VarDecl *decl);
  263. /// \brief Creates the taskNV stage variables for payload struct variable
  264. /// and returns true on success. SPIR-V instructions will also be generated
  265. /// to load/store the contents from/to *value. payloadMemOffset is incremented
  266. /// based on payload struct member size, alignment and offset, and SPIR-V
  267. /// decorations PerTaskNV and Offset are assigned to each member.
  268. bool createPayloadStageVars(const hlsl::SigPoint *sigPoint,
  269. spv::StorageClass sc, const NamedDecl *decl,
  270. bool asInput, QualType type,
  271. const llvm::StringRef namePrefix,
  272. SpirvInstruction **value,
  273. uint32_t payloadMemOffset = 0);
  274. /// \brief Creates a function-scope paramter in the current function and
  275. /// returns its instruction. dbgArgNumber is used to specify the argument
  276. /// number of param among function parameters, which will be used for the
  277. /// debug information. Note that dbgArgNumber for the first function
  278. /// parameter must have "1", not "0", which is what Clang generates for
  279. /// LLVM debug metadata.
  280. SpirvFunctionParameter *createFnParam(const ParmVarDecl *param,
  281. uint32_t dbgArgNumber = 0);
  282. /// \brief Creates the counter variable associated with the given param.
  283. /// This is meant to be used for forward-declared functions and this objects
  284. /// of methods.
  285. ///
  286. /// Note: legalization specific code
  287. inline void createFnParamCounterVar(const VarDecl *param);
  288. /// \brief Creates a function-scope variable in the current function and
  289. /// returns its instruction.
  290. SpirvVariable *createFnVar(const VarDecl *var,
  291. llvm::Optional<SpirvInstruction *> init);
  292. /// \brief Creates a file-scope variable and returns its instruction.
  293. SpirvVariable *createFileVar(const VarDecl *var,
  294. llvm::Optional<SpirvInstruction *> init);
  295. /// \brief Creates an external-visible variable and returns its instruction.
  296. SpirvVariable *createExternVar(const VarDecl *var);
  297. /// \brief Returns an OpString instruction that represents the given VarDecl.
  298. /// VarDecl must be a variable of string type.
  299. ///
  300. /// This function inspects the VarDecl for an initialization expression. If
  301. /// initialization expression is not found, it will emit an error because the
  302. /// variable cannot be deduced to an OpString literal, and string variables do
  303. /// not exist in SPIR-V.
  304. ///
  305. /// Note: HLSL has the 'string' type which can be used for rare purposes such
  306. /// as printf (SPIR-V's DebugPrintf). SPIR-V does not have a 'char' or
  307. /// 'string' type, and therefore any variable of such type is never created.
  308. /// The string literal is evaluated when needed and an OpString is generated
  309. /// for it.
  310. SpirvInstruction *createOrUpdateStringVar(const VarDecl *);
  311. /// \brief Creates an Enum constant.
  312. void createEnumConstant(const EnumConstantDecl *decl);
  313. /// \brief Creates a cbuffer/tbuffer from the given decl.
  314. ///
  315. /// In the AST, cbuffer/tbuffer is represented as a HLSLBufferDecl, which is
  316. /// a DeclContext, and all fields in the buffer are represented as VarDecls.
  317. /// We cannot do the normal translation path, which will translate a field
  318. /// into a standalone variable. We need to create a single SPIR-V variable
  319. /// for the whole buffer. When we refer to the field VarDecl later, we need
  320. /// to do an extra OpAccessChain to get its pointer from the SPIR-V variable
  321. /// standing for the whole buffer.
  322. SpirvVariable *createCTBuffer(const HLSLBufferDecl *decl);
  323. /// \brief Creates a cbuffer/tbuffer from the given decl.
  324. ///
  325. /// In the AST, a variable whose type is ConstantBuffer/TextureBuffer is
  326. /// represented as a VarDecl whose DeclContext is a HLSLBufferDecl. These
  327. /// VarDecl's type is labelled as the struct upon which ConstantBuffer/
  328. /// TextureBuffer is parameterized. For a such VarDecl, we need to create
  329. /// a corresponding SPIR-V variable for it. Later referencing of such a
  330. /// VarDecl does not need an extra OpAccessChain.
  331. SpirvVariable *createCTBuffer(const VarDecl *decl);
  332. /// \brief Creates a PushConstant block from the given decl.
  333. SpirvVariable *createPushConstant(const VarDecl *decl);
  334. /// \brief Creates the $Globals cbuffer.
  335. void createGlobalsCBuffer(const VarDecl *var);
  336. /// \brief Returns the suitable type for the given decl, considering the
  337. /// given decl could possibly be created as an alias variable. If true, a
  338. /// pointer-to-the-value type will be returned, otherwise, just return the
  339. /// normal value type. For an alias variable having a associated counter, the
  340. /// counter variable will also be emitted.
  341. ///
  342. /// If the type is for an alias variable, writes true to *shouldBeAlias and
  343. /// writes storage class, layout rule, and valTypeId to *info.
  344. ///
  345. /// Note: legalization specific code
  346. QualType
  347. getTypeAndCreateCounterForPotentialAliasVar(const DeclaratorDecl *var,
  348. bool *shouldBeAlias = nullptr);
  349. /// \brief Sets the entry function.
  350. void setEntryFunction(SpirvFunction *fn) { entryFunction = fn; }
  351. /// \brief If the given decl is an implicit VarDecl that evaluates to a
  352. /// constant, it evaluates the constant and registers the resulting SPIR-V
  353. /// instruction in the astDecls map. Otherwise returns without doing anything.
  354. ///
  355. /// Note: There are many cases where the front-end might create such implicit
  356. /// VarDecls (such as some ray tracing enums).
  357. void tryToCreateImplicitConstVar(const ValueDecl *);
  358. /// \brief Creates a variable for hull shader output patch with Output
  359. /// storage class, and registers the SPIR-V variable for the given decl.
  360. SpirvInstruction *createHullMainOutputPatch(const ParmVarDecl *param,
  361. const QualType retType,
  362. uint32_t numOutputControlPoints);
  363. /// \brief An enum class for representing what the DeclContext is used for
  364. enum class ContextUsageKind {
  365. CBuffer,
  366. TBuffer,
  367. PushConstant,
  368. Globals,
  369. ShaderRecordBufferNV,
  370. ShaderRecordBufferEXT
  371. };
  372. /// Raytracing specific functions
  373. /// \brief Creates a ShaderRecordBufferEXT or ShaderRecordBufferNV block from the given decl.
  374. SpirvVariable *createShaderRecordBuffer(const VarDecl *decl, ContextUsageKind kind);
  375. SpirvVariable *createShaderRecordBuffer(const HLSLBufferDecl *decl, ContextUsageKind kind);
  376. private:
  377. /// The struct containing SPIR-V information of a AST Decl.
  378. struct DeclSpirvInfo {
  379. /// Default constructor to satisfy DenseMap
  380. DeclSpirvInfo() : instr(nullptr), indexInCTBuffer(-1) {}
  381. DeclSpirvInfo(SpirvInstruction *instr_, int index = -1)
  382. : instr(instr_), indexInCTBuffer(index) {}
  383. /// Implicit conversion to SpirvInstruction*.
  384. operator SpirvInstruction *() const { return instr; }
  385. SpirvInstruction *instr;
  386. /// Value >= 0 means that this decl is a VarDecl inside a cbuffer/tbuffer
  387. /// and this is the index; value < 0 means this is just a standalone decl.
  388. int indexInCTBuffer;
  389. };
  390. /// \brief Returns the SPIR-V information for the given decl.
  391. /// Returns nullptr if no such decl was previously registered.
  392. const DeclSpirvInfo *getDeclSpirvInfo(const ValueDecl *decl) const;
  393. /// \brief Creates DeclSpirvInfo using the given instr and index. It creates a
  394. /// clone variable if it is CTBuffer including matrix 1xN with FXC memory
  395. /// layout.
  396. DeclSpirvInfo createDeclSpirvInfo(SpirvInstruction *instr,
  397. int index = -1) const {
  398. if (auto *clone = spvBuilder.initializeCloneVarForFxcCTBuffer(instr))
  399. instr = clone;
  400. return DeclSpirvInfo(instr, index);
  401. }
  402. public:
  403. /// \brief Returns the information for the given decl.
  404. ///
  405. /// This method will panic if the given decl is not registered.
  406. SpirvInstruction *getDeclEvalInfo(const ValueDecl *decl, SourceLocation loc);
  407. /// \brief Returns the instruction pointer for the given function if already
  408. /// registered; otherwise, treats the given function as a normal decl and
  409. /// returns a newly created instruction for it.
  410. SpirvFunction *getOrRegisterFn(const FunctionDecl *fn);
  411. /// Registers that the given decl should be translated into the given spec
  412. /// constant.
  413. void registerSpecConstant(const VarDecl *decl,
  414. SpirvInstruction *specConstant);
  415. /// \brief Returns the associated counter's (instr-ptr, is-alias-or-not)
  416. /// pair for the given {RW|Append|Consume}StructuredBuffer variable.
  417. /// If indices is not nullptr, walks trhough the fields of the decl, expected
  418. /// to be of struct type, using the indices to find the field. Returns nullptr
  419. /// if the given decl has no associated counter variable created.
  420. const CounterIdAliasPair *getCounterIdAliasPair(
  421. const DeclaratorDecl *decl,
  422. const llvm::SmallVector<uint32_t, 4> *indices = nullptr);
  423. /// \brief Returns all the associated counters for the given decl. The decl is
  424. /// expected to be a struct containing alias RW/Append/Consume structured
  425. /// buffers. Returns nullptr if it does not.
  426. const CounterVarFields *getCounterVarFields(const DeclaratorDecl *decl);
  427. /// \brief Returns the <type-id> for the given cbuffer, tbuffer,
  428. /// ConstantBuffer, TextureBuffer, or push constant block.
  429. ///
  430. /// Note: we need this method because constant/texture buffers and push
  431. /// constant blocks are all represented as normal struct types upon which
  432. /// they are parameterized. That is different from structured buffers,
  433. /// for which we can tell they are not normal structs by investigating
  434. /// the name. But for constant/texture buffers and push constant blocks,
  435. /// we need to have the additional Block/BufferBlock decoration to keep
  436. /// type consistent. Normal translation path for structs via TypeTranslator
  437. /// won't attach Block/BufferBlock decoration.
  438. const SpirvType *getCTBufferPushConstantType(const DeclContext *decl);
  439. /// \brief Returns all defined stage (builtin/input/ouput) variables in this
  440. /// mapper.
  441. std::vector<SpirvVariable *> collectStageVars() const;
  442. /// \brief Writes out the contents in the function parameter for the GS
  443. /// stream output to the corresponding stage output variables in a recursive
  444. /// manner. Returns true on success, false if errors occur.
  445. ///
  446. /// decl is the Decl with semantic string attached and will be used to find
  447. /// the stage output variable to write to, value is the SPIR-V variable to
  448. /// read data from.
  449. ///
  450. /// This method is specially for writing back per-vertex data at the time of
  451. /// OpEmitVertex in GS.
  452. bool writeBackOutputStream(const NamedDecl *decl, QualType type,
  453. SpirvInstruction *value);
  454. /// \brief Negates to get the additive inverse of SV_Position.y if requested.
  455. SpirvInstruction *invertYIfRequested(SpirvInstruction *position,
  456. SourceLocation loc);
  457. /// \brief Reciprocates to get the multiplicative inverse of SV_Position.w
  458. /// if requested.
  459. SpirvInstruction *invertWIfRequested(SpirvInstruction *position,
  460. SourceLocation loc);
  461. /// \brief Decorates all stage input and output variables with proper
  462. /// location and returns true on success.
  463. ///
  464. /// This method will write the location assignment into the module under
  465. /// construction.
  466. inline bool decorateStageIOLocations();
  467. /// \brief Decorates all resource variables with proper set and binding
  468. /// numbers and returns true on success.
  469. ///
  470. /// This method will write the set and binding number assignment into the
  471. /// module under construction.
  472. bool decorateResourceBindings();
  473. /// \brief Decorates resource variables with Coherent decoration if they
  474. /// are declared as globallycoherent.
  475. bool decorateResourceCoherent();
  476. /// \brief Returns whether the SPIR-V module requires SPIR-V legalization
  477. /// passes run to make it legal.
  478. bool requiresLegalization() const { return needsLegalization; }
  479. /// \brief Returns whether the SPIR-V module requires an optimization pass to
  480. /// flatten array/structure of resources.
  481. bool requiresFlatteningCompositeResources() const {
  482. return needsFlatteningCompositeResources;
  483. }
  484. /// \brief Returns the given decl's HLSL semantic information.
  485. static SemanticInfo getStageVarSemantic(const NamedDecl *decl);
  486. /// \brief Returns SPIR-V instruction for given stage var decl.
  487. SpirvInstruction *getStageVarInstruction(const DeclaratorDecl *decl) {
  488. auto *value = stageVarInstructions.lookup(decl);
  489. assert(value);
  490. return value;
  491. }
  492. private:
  493. /// \brief Wrapper method to create a fatal error message and report it
  494. /// in the diagnostic engine associated with this consumer.
  495. template <unsigned N>
  496. DiagnosticBuilder emitFatalError(const char (&message)[N],
  497. SourceLocation loc) {
  498. const auto diagId =
  499. diags.getCustomDiagID(clang::DiagnosticsEngine::Fatal, message);
  500. return diags.Report(loc, diagId);
  501. }
  502. /// \brief Wrapper method to create an error message and report it
  503. /// in the diagnostic engine associated with this consumer.
  504. template <unsigned N>
  505. DiagnosticBuilder emitError(const char (&message)[N], SourceLocation loc) {
  506. const auto diagId =
  507. diags.getCustomDiagID(clang::DiagnosticsEngine::Error, message);
  508. return diags.Report(loc, diagId);
  509. }
  510. /// \brief Wrapper method to create a warning message and report it
  511. /// in the diagnostic engine associated with this consumer.
  512. template <unsigned N>
  513. DiagnosticBuilder emitWarning(const char (&message)[N], SourceLocation loc) {
  514. const auto diagId =
  515. diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, message);
  516. return diags.Report(loc, diagId);
  517. }
  518. /// \brief Wrapper method to create a note message and report it
  519. /// in the diagnostic engine associated with this consumer.
  520. template <unsigned N>
  521. DiagnosticBuilder emitNote(const char (&message)[N], SourceLocation loc) {
  522. const auto diagId =
  523. diags.getCustomDiagID(clang::DiagnosticsEngine::Note, message);
  524. return diags.Report(loc, diagId);
  525. }
  526. /// \brief Checks whether some semantic is used more than once and returns
  527. /// true if no such cases. Returns false otherwise.
  528. bool checkSemanticDuplication(bool forInput);
  529. /// \brief Decorates all stage input (if forInput is true) or output (if
  530. /// forInput is false) variables with proper location and returns true on
  531. /// success.
  532. ///
  533. /// This method will write the location assignment into the module under
  534. /// construction.
  535. bool finalizeStageIOLocations(bool forInput);
  536. /// Creates a variable of struct type with explicit layout decorations.
  537. /// The sub-Decls in the given DeclContext will be treated as the struct
  538. /// fields. The struct type will be named as typeName, and the variable
  539. /// will be named as varName.
  540. ///
  541. /// This method should only be used for cbuffers/ContantBuffers, tbuffers/
  542. /// TextureBuffers, and PushConstants. usageKind must be set properly
  543. /// depending on the usage kind.
  544. ///
  545. /// If arraySize is 0, the variable will be created as a struct ; if arraySize
  546. /// is > 0, the variable will be created as an array; if arraySize is -1, the
  547. /// variable will be created as a runtime array.
  548. ///
  549. /// Panics if the DeclContext is neither HLSLBufferDecl or RecordDecl.
  550. SpirvVariable *createStructOrStructArrayVarOfExplicitLayout(
  551. const DeclContext *decl, int arraySize, ContextUsageKind usageKind,
  552. llvm::StringRef typeName, llvm::StringRef varName);
  553. /// Creates all the stage variables mapped from semantics on the given decl.
  554. /// Returns true on sucess.
  555. ///
  556. /// If decl is of struct type, this means flattening it and create stand-
  557. /// alone variables for each field. If arraySize is not zero, the created
  558. /// stage variables will have an additional arrayness over its original type.
  559. /// This is for supporting HS/DS/GS, which takes in primitives containing
  560. /// multiple vertices. asType should be the type we are treating decl as;
  561. /// For HS/DS/GS, the outermost arrayness should be discarded and use
  562. /// arraySize instead.
  563. ///
  564. /// Also performs reading the stage variables and compose a temporary value
  565. /// of the given type and writing into *value, if asInput is true. Otherwise,
  566. /// Decomposes the *value according to type and writes back into the stage
  567. /// output variables, unless noWriteBack is set to true. noWriteBack is used
  568. /// by GS since in GS we manually control write back using .Append() method.
  569. ///
  570. /// invocationId is only used for HS to indicate the index of the output
  571. /// array element to write to.
  572. ///
  573. /// Assumes the decl has semantic attached to itself or to its fields.
  574. /// If inheritSemantic is valid, it will override all semantics attached to
  575. /// the children of this decl, and the children of this decl will be using
  576. /// the semantic in inheritSemantic, with index increasing sequentially.
  577. bool createStageVars(const hlsl::SigPoint *sigPoint, const NamedDecl *decl,
  578. bool asInput, QualType asType, uint32_t arraySize,
  579. const llvm::StringRef namePrefix,
  580. llvm::Optional<SpirvInstruction *> invocationId,
  581. SpirvInstruction **value, bool noWriteBack,
  582. SemanticInfo *inheritSemantic);
  583. /// Creates the SPIR-V variable instruction for the given StageVar and returns
  584. /// the instruction. Also sets whether the StageVar is a SPIR-V builtin and
  585. /// its storage class accordingly. name will be used as the debug name when
  586. /// creating a stage input/output variable.
  587. SpirvVariable *createSpirvStageVar(StageVar *, const NamedDecl *decl,
  588. const llvm::StringRef name,
  589. SourceLocation);
  590. // Create intermediate output variable to communicate patch constant
  591. // data in hull shader since workgroup memory is not allowed there.
  592. SpirvVariable *createSpirvIntermediateOutputStageVar(
  593. const NamedDecl *decl, const llvm::StringRef name, QualType asType);
  594. /// Returns true if all vk:: attributes usages are valid.
  595. bool validateVKAttributes(const NamedDecl *decl);
  596. /// Returns true if all vk::builtin usages are valid.
  597. bool validateVKBuiltins(const NamedDecl *decl,
  598. const hlsl::SigPoint *sigPoint);
  599. /// Methods for creating counter variables associated with the given decl.
  600. /// Creates assoicated counter variables for all AssocCounter cases (see the
  601. /// comment of CounterVarFields).
  602. void createCounterVarForDecl(const DeclaratorDecl *decl);
  603. /// Creates the associated counter variable for final RW/Append/Consume
  604. /// structured buffer. Handles AssocCounter#1 and AssocCounter#2 (see the
  605. /// comment of CounterVarFields).
  606. ///
  607. /// declId is the SPIR-V instruction for the given decl. It should be non-zero
  608. /// for non-alias buffers.
  609. ///
  610. /// The counter variable will be created as an alias variable (of
  611. /// pointer-to-pointer type in Private storage class) if isAlias is true.
  612. ///
  613. /// Note: isAlias - legalization specific code
  614. void
  615. createCounterVar(const DeclaratorDecl *decl, SpirvInstruction *declInstr,
  616. bool isAlias,
  617. const llvm::SmallVector<uint32_t, 4> *indices = nullptr);
  618. /// Creates all assoicated counter variables by recursively visiting decl's
  619. /// fields. Handles AssocCounter#3 and AssocCounter#4 (see the comment of
  620. /// CounterVarFields).
  621. inline void createFieldCounterVars(const DeclaratorDecl *decl);
  622. void createFieldCounterVars(const DeclaratorDecl *rootDecl,
  623. const DeclaratorDecl *decl,
  624. llvm::SmallVector<uint32_t, 4> *indices);
  625. /// Decorates varInstr of the given asType with proper interpolation modes
  626. /// considering the attributes on the given decl.
  627. void decorateInterpolationMode(const NamedDecl *decl, QualType asType,
  628. SpirvVariable *varInstr);
  629. /// Returns the proper SPIR-V storage class (Input or Output) for the given
  630. /// SigPoint.
  631. spv::StorageClass getStorageClassForSigPoint(const hlsl::SigPoint *);
  632. /// Returns true if the given SPIR-V stage variable has Input storage class.
  633. inline bool isInputStorageClass(const StageVar &v);
  634. /// Creates DebugGlobalVariable and returns it if rich debug information
  635. /// generation is enabled. Otherwise, returns nullptr.
  636. SpirvDebugGlobalVariable *createDebugGlobalVariable(SpirvVariable *var,
  637. const QualType &type,
  638. const SourceLocation &loc,
  639. const StringRef &name);
  640. /// Determines the register type for a resource that does not have an
  641. /// explicit register() declaration. Returns true if it is able to
  642. /// determine the register type and will set |*registerTypeOut| to
  643. /// 'u', 's', 'b', or 't'. Assumes |registerTypeOut| to be non-nullptr.
  644. ///
  645. /// Uses the following mapping of HLSL types to register spaces:
  646. /// t - for shader resource views (SRV)
  647. /// TEXTURE1D
  648. /// TEXTURE1DARRAY
  649. /// TEXTURE2D
  650. /// TEXTURE2DARRAY
  651. /// TEXTURE3D
  652. /// TEXTURECUBE
  653. /// TEXTURECUBEARRAY
  654. /// TEXTURE2DMS
  655. /// TEXTURE2DMSARRAY
  656. /// STRUCTUREDBUFFER
  657. /// BYTEADDRESSBUFFER
  658. /// BUFFER
  659. /// TBUFFER
  660. ///
  661. /// s - for samplers
  662. /// SAMPLER
  663. /// SAMPLER1D
  664. /// SAMPLER2D
  665. /// SAMPLER3D
  666. /// SAMPLERCUBE
  667. /// SAMPLERSTATE
  668. /// SAMPLERCOMPARISONSTATE
  669. ///
  670. /// u - for unordered access views (UAV)
  671. /// RWBYTEADDRESSBUFFER
  672. /// RWSTRUCTUREDBUFFER
  673. /// APPENDSTRUCTUREDBUFFER
  674. /// CONSUMESTRUCTUREDBUFFER
  675. /// RWBUFFER
  676. /// RWTEXTURE1D
  677. /// RWTEXTURE1DARRAY
  678. /// RWTEXTURE2D
  679. /// RWTEXTURE2DARRAY
  680. /// RWTEXTURE3D
  681. ///
  682. /// b - for constant buffer views (CBV)
  683. /// CBUFFER
  684. /// CONSTANTBUFFER
  685. bool getImplicitRegisterType(const ResourceVar &var,
  686. char *registerTypeOut) const;
  687. private:
  688. SpirvBuilder &spvBuilder;
  689. SpirvEmitter &theEmitter;
  690. const SpirvCodeGenOptions &spirvOptions;
  691. ASTContext &astContext;
  692. SpirvContext &spvContext;
  693. DiagnosticsEngine &diags;
  694. SpirvFunction *entryFunction;
  695. /// Mapping of all Clang AST decls to their instruction pointers.
  696. llvm::DenseMap<const ValueDecl *, DeclSpirvInfo> astDecls;
  697. llvm::DenseMap<const ValueDecl *, SpirvFunction *> astFunctionDecls;
  698. /// Vector of all defined stage variables.
  699. llvm::SmallVector<StageVar, 8> stageVars;
  700. /// Mapping from Clang AST decls to the corresponding stage variables.
  701. /// This field is only used by GS for manually emitting vertices, when
  702. /// we need to query the output stage variables involved in writing back. For
  703. /// other cases, stage variable reading and writing is done at the time of
  704. /// creating that stage variable, so that we don't need to query them again
  705. /// for reading and writing.
  706. llvm::DenseMap<const ValueDecl *, SpirvVariable *> stageVarInstructions;
  707. /// Vector of all defined resource variables.
  708. llvm::SmallVector<ResourceVar, 8> resourceVars;
  709. /// Mapping from {RW|Append|Consume}StructuredBuffers to their
  710. /// counter variables' (instr-ptr, is-alias-or-not) pairs
  711. ///
  712. /// conterVars holds entities of AssocCounter#1, fieldCounterVars holds
  713. /// entities of the rest.
  714. llvm::DenseMap<const DeclaratorDecl *, CounterIdAliasPair> counterVars;
  715. llvm::DenseMap<const DeclaratorDecl *, CounterVarFields> fieldCounterVars;
  716. /// Mapping from cbuffer/tbuffer/ConstantBuffer/TextureBufer/push-constant
  717. /// to the SPIR-V type.
  718. llvm::DenseMap<const DeclContext *, const SpirvType *> ctBufferPCTypes;
  719. /// The SPIR-V builtin variables accessed by WaveGetLaneCount(),
  720. /// WaveGetLaneIndex() and ray tracing builtins.
  721. ///
  722. /// These are the only few cases where SPIR-V builtin variables are accessed
  723. /// using HLSL intrinsic function calls. All other builtin variables are
  724. /// accessed using stage IO variables.
  725. llvm::DenseMap<uint32_t, SpirvVariable *> builtinToVarMap;
  726. /// Whether the translated SPIR-V binary needs legalization.
  727. ///
  728. /// The following cases will require legalization:
  729. ///
  730. /// 1. Opaque types (textures, samplers) within structs
  731. /// 2. Structured buffer aliasing
  732. /// 3. Using SPIR-V instructions not allowed in the currect shader stage
  733. ///
  734. /// This covers the second case:
  735. ///
  736. /// When we have a kind of structured or byte buffer, meaning one of the
  737. /// following
  738. ///
  739. /// * StructuredBuffer
  740. /// * RWStructuredBuffer
  741. /// * AppendStructuredBuffer
  742. /// * ConsumeStructuredBuffer
  743. /// * ByteAddressStructuredBuffer
  744. /// * RWByteAddressStructuredBuffer
  745. ///
  746. /// and assigning to them (using operator=, passing in as function parameter,
  747. /// returning as function return), we need legalization.
  748. ///
  749. /// All variable definitions (including static/non-static local/global
  750. /// variables, function parameters/returns) will gain another level of
  751. /// pointerness, unless they will generate externally visible SPIR-V
  752. /// variables. So variables and parameters will be of pointer-to-pointer type,
  753. /// while function returns will be of pointer type. We adopt this mechanism to
  754. /// convey to the legalization passes that they are *alias* variables, and
  755. /// all accesses should happen to the aliased-to-variables. Loading such an
  756. /// alias variable will give the pointer to the aliased-to-variable, while
  757. /// storing into such an alias variable should write the pointer to the
  758. /// aliased-to-variable.
  759. ///
  760. /// Based on the above, CodeGen should take care of the following AST nodes:
  761. ///
  762. /// * Definition of alias variables: should add another level of pointers
  763. /// * Assigning non-alias variables to alias variables: should avoid the load
  764. /// over the non-alias variables
  765. /// * Accessing alias variables: should load the pointer first and then
  766. /// further compose access chains.
  767. ///
  768. /// Note that the associated counters bring about their own complication.
  769. /// We also need to apply the alias mechanism for them.
  770. ///
  771. /// If this is true, SPIRV-Tools legalization passes will be executed after
  772. /// the translation to legalize the generated SPIR-V binary.
  773. ///
  774. /// Note: legalization specific code
  775. bool needsLegalization;
  776. /// Whether the translated SPIR-V binary needs flattening of composite
  777. /// resources.
  778. ///
  779. /// If the source HLSL contains global structure of resources, we need to run
  780. /// an additional SPIR-V optimization pass to flatten such structures.
  781. bool needsFlatteningCompositeResources;
  782. public:
  783. /// The gl_PerVertex structs for both input and output
  784. GlPerVertex glPerVertex;
  785. };
  786. hlsl::Semantic::Kind SemanticInfo::getKind() const {
  787. assert(semantic);
  788. return semantic->GetKind();
  789. }
  790. bool SemanticInfo::isTarget() const {
  791. return semantic && semantic->GetKind() == hlsl::Semantic::Kind::Target;
  792. }
  793. void CounterIdAliasPair::assign(const CounterIdAliasPair &srcPair,
  794. SpirvBuilder &builder,
  795. SpirvContext &context) const {
  796. assert(isAlias);
  797. builder.createStore(counterVar, srcPair.get(builder, context),
  798. /* SourceLocation */ {});
  799. }
  800. DeclResultIdMapper::DeclResultIdMapper(ASTContext &context,
  801. SpirvContext &spirvContext,
  802. SpirvBuilder &spirvBuilder,
  803. SpirvEmitter &emitter,
  804. FeatureManager &features,
  805. const SpirvCodeGenOptions &options)
  806. : spvBuilder(spirvBuilder), theEmitter(emitter), spirvOptions(options),
  807. astContext(context), spvContext(spirvContext),
  808. diags(context.getDiagnostics()), entryFunction(nullptr),
  809. needsLegalization(false), needsFlatteningCompositeResources(false),
  810. glPerVertex(context, spirvContext, spirvBuilder) {}
  811. bool DeclResultIdMapper::decorateStageIOLocations() {
  812. if (spvContext.isRay() || spvContext.isAS()) {
  813. // No location assignment for any raytracing stage variables or
  814. // amplification shader variables
  815. return true;
  816. }
  817. // Try both input and output even if input location assignment failed
  818. return finalizeStageIOLocations(true) & finalizeStageIOLocations(false);
  819. }
  820. bool DeclResultIdMapper::isInputStorageClass(const StageVar &v) {
  821. return getStorageClassForSigPoint(v.getSigPoint()) ==
  822. spv::StorageClass::Input;
  823. }
  824. void DeclResultIdMapper::createFnParamCounterVar(const VarDecl *param) {
  825. createCounterVarForDecl(param);
  826. }
  827. void DeclResultIdMapper::createFieldCounterVars(const DeclaratorDecl *decl) {
  828. llvm::SmallVector<uint32_t, 4> indices;
  829. createFieldCounterVars(decl, decl, &indices);
  830. }
  831. } // end namespace spirv
  832. } // end namespace clang
  833. #endif