DeclResultIdMapper.h 33 KB

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