DxilMetadataHelper.cpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilMetadataHelper.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "dxc/Support/Global.h"
  10. #include "dxc/HLSL/DxilMetadataHelper.h"
  11. #include "dxc/HLSL/DxilShaderModel.h"
  12. #include "dxc/HLSL/DxilCBuffer.h"
  13. #include "dxc/HLSL/DxilResource.h"
  14. #include "dxc/HLSL/DxilSampler.h"
  15. #include "dxc/HLSL/DxilSignatureElement.h"
  16. #include "dxc/HLSL/DxilSignature.h"
  17. #include "dxc/HLSL/DxilTypeSystem.h"
  18. #include "dxc/HLSL/DxilRootSignature.h"
  19. #include "dxc/HLSL/ComputeViewIdState.h"
  20. #include "llvm/IR/Constants.h"
  21. #include "llvm/IR/Function.h"
  22. #include "llvm/IR/LLVMContext.h"
  23. #include "llvm/IR/Metadata.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. #include <array>
  27. #include <algorithm>
  28. #include "dxc/Support/WinIncludes.h"
  29. using namespace llvm;
  30. using std::string;
  31. using std::vector;
  32. using std::unique_ptr;
  33. namespace hlsl {
  34. const char DxilMDHelper::kDxilVersionMDName[] = "dx.version";
  35. const char DxilMDHelper::kDxilShaderModelMDName[] = "dx.shaderModel";
  36. const char DxilMDHelper::kDxilEntryPointsMDName[] = "dx.entryPoints";
  37. const char DxilMDHelper::kDxilResourcesMDName[] = "dx.resources";
  38. const char DxilMDHelper::kDxilTypeSystemMDName[] = "dx.typeAnnotations";
  39. const char DxilMDHelper::kDxilTypeSystemHelperVariablePrefix[] = "dx.typevar.";
  40. const char DxilMDHelper::kDxilControlFlowHintMDName[] = "dx.controlflow.hints";
  41. const char DxilMDHelper::kDxilPreciseAttributeMDName[] = "dx.precise";
  42. const char DxilMDHelper::kHLDxilResourceAttributeMDName[] = "dx.hl.resource.attribute";
  43. const char DxilMDHelper::kDxilValidatorVersionMDName[] = "dx.valver";
  44. // This named metadata is not valid in final module (should be moved to DxilContainer)
  45. const char DxilMDHelper::kDxilRootSignatureMDName[] = "dx.rootSignature";
  46. const char DxilMDHelper::kDxilViewIdStateMDName[] = "dx.viewIdState";
  47. static std::array<const char *, 7> DxilMDNames = {
  48. DxilMDHelper::kDxilVersionMDName,
  49. DxilMDHelper::kDxilShaderModelMDName,
  50. DxilMDHelper::kDxilEntryPointsMDName,
  51. DxilMDHelper::kDxilResourcesMDName,
  52. DxilMDHelper::kDxilTypeSystemMDName,
  53. DxilMDHelper::kDxilValidatorVersionMDName,
  54. DxilMDHelper::kDxilViewIdStateMDName
  55. };
  56. DxilMDHelper::DxilMDHelper(Module *pModule, std::unique_ptr<ExtraPropertyHelper> EPH)
  57. : m_pModule(pModule)
  58. , m_Ctx(pModule->getContext())
  59. , m_pSM(nullptr)
  60. , m_ExtraPropertyHelper(std::move(EPH)) {
  61. }
  62. DxilMDHelper::~DxilMDHelper() {
  63. }
  64. void DxilMDHelper::SetShaderModel(const ShaderModel *pSM) {
  65. m_pSM = pSM;
  66. }
  67. const ShaderModel *DxilMDHelper::GetShaderModel() const {
  68. return m_pSM;
  69. }
  70. //
  71. // DXIL version.
  72. //
  73. void DxilMDHelper::EmitDxilVersion(unsigned Major, unsigned Minor) {
  74. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  75. IFTBOOL(pDxilVersionMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  76. pDxilVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilVersionMDName);
  77. Metadata *MDVals[kDxilVersionNumFields];
  78. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  79. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  80. pDxilVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  81. }
  82. void DxilMDHelper::LoadDxilVersion(unsigned &Major, unsigned &Minor) {
  83. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  84. IFTBOOL(pDxilVersionMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  85. IFTBOOL(pDxilVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  86. MDNode *pVersionMD = pDxilVersionMD->getOperand(0);
  87. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  88. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  89. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  90. }
  91. //
  92. // Validator version.
  93. //
  94. void DxilMDHelper::EmitValidatorVersion(unsigned Major, unsigned Minor) {
  95. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  96. // Allow re-writing the validator version, since this can be changed at later points.
  97. if (pDxilValidatorVersionMD)
  98. m_pModule->eraseNamedMetadata(pDxilValidatorVersionMD);
  99. pDxilValidatorVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilValidatorVersionMDName);
  100. Metadata *MDVals[kDxilVersionNumFields];
  101. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  102. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  103. pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  104. }
  105. void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
  106. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  107. if (pDxilValidatorVersionMD == nullptr) {
  108. // If no validator version metadata, assume 1.0
  109. Major = 1;
  110. Minor = 0;
  111. return;
  112. }
  113. IFTBOOL(pDxilValidatorVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  114. MDNode *pVersionMD = pDxilValidatorVersionMD->getOperand(0);
  115. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  116. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  117. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  118. }
  119. //
  120. // DXIL shader model.
  121. //
  122. void DxilMDHelper::EmitDxilShaderModel(const ShaderModel *pSM) {
  123. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  124. IFTBOOL(pShaderModelNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  125. pShaderModelNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilShaderModelMDName);
  126. Metadata *MDVals[kDxilShaderModelNumFields];
  127. MDVals[kDxilShaderModelTypeIdx ] = MDString::get(m_Ctx, pSM->GetKindName().c_str());
  128. MDVals[kDxilShaderModelMajorIdx] = Uint32ToConstMD(pSM->GetMajor());
  129. MDVals[kDxilShaderModelMinorIdx] = Uint32ToConstMD(pSM->GetMinor());
  130. pShaderModelNamedMD->addOperand(MDNode::get(m_Ctx, MDVals));
  131. }
  132. void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
  133. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  134. IFTBOOL(pShaderModelNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  135. IFTBOOL(pShaderModelNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  136. MDNode *pShaderModelMD = pShaderModelNamedMD->getOperand(0);
  137. IFTBOOL(pShaderModelMD->getNumOperands() == kDxilShaderModelNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  138. MDString *pShaderTypeMD = dyn_cast<MDString>(pShaderModelMD->getOperand(kDxilShaderModelTypeIdx));
  139. IFTBOOL(pShaderTypeMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  140. unsigned Major = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMajorIdx));
  141. unsigned Minor = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMinorIdx));
  142. string ShaderModelName = pShaderTypeMD->getString();
  143. ShaderModelName += "_" + std::to_string(Major) + "_" + std::to_string(Minor);
  144. pSM = ShaderModel::GetByName(ShaderModelName.c_str());
  145. if (!pSM->IsValidForDxil()) {
  146. char ErrorMsgTxt[40];
  147. StringCchPrintfA(ErrorMsgTxt, _countof(ErrorMsgTxt),
  148. "Unknown shader model '%s'", ShaderModelName.c_str());
  149. string ErrorMsg(ErrorMsgTxt);
  150. throw hlsl::Exception(DXC_E_INCORRECT_DXIL_METADATA, ErrorMsg);
  151. }
  152. }
  153. //
  154. // Entry points.
  155. //
  156. void DxilMDHelper::EmitDxilEntryPoints(vector<MDNode *> &MDEntries) {
  157. DXASSERT(MDEntries.size() == 1, "only one entry point is supported for now");
  158. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  159. IFTBOOL(pEntryPointsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  160. pEntryPointsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilEntryPointsMDName);
  161. for (size_t i = 0; i < MDEntries.size(); i++) {
  162. pEntryPointsNamedMD->addOperand(MDEntries[i]);
  163. }
  164. }
  165. const NamedMDNode *DxilMDHelper::GetDxilEntryPoints() {
  166. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  167. IFTBOOL(pEntryPointsNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  168. return pEntryPointsNamedMD;
  169. }
  170. MDTuple *DxilMDHelper::EmitDxilEntryPointTuple(Function *pFunc, const string &Name,
  171. MDTuple *pSignatures, MDTuple *pResources,
  172. MDTuple *pProperties) {
  173. Metadata *MDVals[kDxilEntryPointNumFields];
  174. MDVals[kDxilEntryPointFunction ] = pFunc ? ValueAsMetadata::get(pFunc) : nullptr;
  175. MDVals[kDxilEntryPointName ] = MDString::get(m_Ctx, Name.c_str());
  176. MDVals[kDxilEntryPointSignatures] = pSignatures;
  177. MDVals[kDxilEntryPointResources ] = pResources;
  178. MDVals[kDxilEntryPointProperties] = pProperties;
  179. return MDNode::get(m_Ctx, MDVals);
  180. }
  181. void DxilMDHelper::GetDxilEntryPoint(const MDNode *MDO, Function *&pFunc, string &Name,
  182. const MDOperand *&pSignatures, const MDOperand *&pResources,
  183. const MDOperand *&pProperties) {
  184. IFTBOOL(MDO != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  185. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO);
  186. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  187. IFTBOOL(pTupleMD->getNumOperands() == kDxilEntryPointNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  188. // Retrieve entry function symbol.
  189. const MDOperand &MDOFunc = pTupleMD->getOperand(kDxilEntryPointFunction);
  190. if (MDOFunc.get() != nullptr) {
  191. ValueAsMetadata *pValueFunc = dyn_cast<ValueAsMetadata>(MDOFunc.get());
  192. IFTBOOL(pValueFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  193. pFunc = dyn_cast<Function>(pValueFunc->getValue());
  194. IFTBOOL(pFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  195. } else {
  196. pFunc = nullptr; // pass-through CP.
  197. }
  198. // Retrieve entry function name.
  199. const MDOperand &MDOName = pTupleMD->getOperand(kDxilEntryPointName);
  200. IFTBOOL(MDOName.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  201. MDString *pMDName = dyn_cast<MDString>(MDOName);
  202. IFTBOOL(pMDName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  203. Name = pMDName->getString();
  204. pSignatures = &pTupleMD->getOperand(kDxilEntryPointSignatures);
  205. pResources = &pTupleMD->getOperand(kDxilEntryPointResources );
  206. pProperties = &pTupleMD->getOperand(kDxilEntryPointProperties);
  207. }
  208. //
  209. // Signatures.
  210. //
  211. MDTuple *DxilMDHelper::EmitDxilSignatures(const DxilSignature &InputSig,
  212. const DxilSignature &OutputSig,
  213. const DxilSignature &PCSig) {
  214. MDTuple *pSignatureTupleMD = nullptr;
  215. if (!InputSig.GetElements().empty() || !OutputSig.GetElements().empty() || !PCSig.GetElements().empty()) {
  216. Metadata *MDVals[kDxilNumSignatureFields];
  217. MDVals[kDxilInputSignature] = EmitSignatureMetadata(InputSig);
  218. MDVals[kDxilOutputSignature] = EmitSignatureMetadata(OutputSig);
  219. MDVals[kDxilPatchConstantSignature] = EmitSignatureMetadata(PCSig);
  220. pSignatureTupleMD = MDNode::get(m_Ctx, MDVals);
  221. }
  222. return pSignatureTupleMD;
  223. }
  224. void DxilMDHelper::EmitRootSignature(RootSignatureHandle &RootSig) {
  225. if (RootSig.IsEmpty()) {
  226. return;
  227. }
  228. RootSig.EnsureSerializedAvailable();
  229. Constant *V = llvm::ConstantDataArray::get(
  230. m_Ctx, llvm::ArrayRef<uint8_t>(RootSig.GetSerializedBytes(),
  231. RootSig.GetSerializedSize()));
  232. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  233. IFTBOOL(pRootSignatureNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  234. pRootSignatureNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilRootSignatureMDName);
  235. pRootSignatureNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  236. return ;
  237. }
  238. void DxilMDHelper::LoadDxilSignatures(const MDOperand &MDO,
  239. DxilSignature &InputSig,
  240. DxilSignature &OutputSig,
  241. DxilSignature &PCSig) {
  242. if (MDO.get() == nullptr)
  243. return;
  244. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  245. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  246. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumSignatureFields, DXC_E_INCORRECT_DXIL_METADATA);
  247. LoadSignatureMetadata(pTupleMD->getOperand(kDxilInputSignature), InputSig);
  248. LoadSignatureMetadata(pTupleMD->getOperand(kDxilOutputSignature), OutputSig);
  249. LoadSignatureMetadata(pTupleMD->getOperand(kDxilPatchConstantSignature), PCSig);
  250. }
  251. MDTuple *DxilMDHelper::EmitSignatureMetadata(const DxilSignature &Sig) {
  252. auto &Elements = Sig.GetElements();
  253. if (Elements.empty())
  254. return nullptr;
  255. vector<Metadata *> MDVals;
  256. for (size_t i = 0; i < Elements.size(); i++) {
  257. MDVals.emplace_back(EmitSignatureElement(*Elements[i]));
  258. }
  259. return MDNode::get(m_Ctx, MDVals);
  260. }
  261. void DxilMDHelper::LoadSignatureMetadata(const MDOperand &MDO, DxilSignature &Sig) {
  262. if (MDO.get() == nullptr)
  263. return;
  264. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  265. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  266. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i++) {
  267. unique_ptr<DxilSignatureElement> pSE(Sig.CreateElement());
  268. LoadSignatureElement(pTupleMD->getOperand(i), *pSE.get());
  269. Sig.AppendElement(std::move(pSE));
  270. }
  271. }
  272. void DxilMDHelper::LoadRootSignature(RootSignatureHandle &Sig) {
  273. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  274. if(!pRootSignatureNamedMD)
  275. return;
  276. IFTBOOL(pRootSignatureNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  277. MDNode *pNode = pRootSignatureNamedMD->getOperand(0);
  278. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  279. const MDOperand &MDO = pNode->getOperand(0);
  280. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  281. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  282. const ConstantDataArray *pData =
  283. dyn_cast<ConstantDataArray>(pMetaData->getValue());
  284. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  285. IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx),
  286. DXC_E_INCORRECT_DXIL_METADATA);
  287. Sig.Clear();
  288. Sig.LoadSerialized((uint8_t *)pData->getRawDataValues().begin(),
  289. pData->getRawDataValues().size());
  290. }
  291. static const MDTuple *CastToTupleOrNull(const MDOperand &MDO) {
  292. if (MDO.get() == nullptr)
  293. return nullptr;
  294. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  295. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  296. return pTupleMD;
  297. }
  298. MDTuple *DxilMDHelper::EmitSignatureElement(const DxilSignatureElement &SE) {
  299. Metadata *MDVals[kDxilSignatureElementNumFields];
  300. MDVals[kDxilSignatureElementID ] = Uint32ToConstMD(SE.GetID());
  301. MDVals[kDxilSignatureElementName ] = MDString::get(m_Ctx, SE.GetName());
  302. MDVals[kDxilSignatureElementType ] = Uint8ToConstMD((uint8_t)SE.GetCompType().GetKind());
  303. MDVals[kDxilSignatureElementSystemValue ] = Uint8ToConstMD((uint8_t)SE.GetKind());
  304. MDVals[kDxilSignatureElementIndexVector ] = Uint32VectorToConstMDTuple(SE.GetSemanticIndexVec());
  305. MDVals[kDxilSignatureElementInterpMode ] = Uint8ToConstMD((uint8_t)SE.GetInterpolationMode()->GetKind());
  306. MDVals[kDxilSignatureElementRows ] = Uint32ToConstMD(SE.GetRows());
  307. MDVals[kDxilSignatureElementCols ] = Uint8ToConstMD((uint8_t)SE.GetCols());
  308. MDVals[kDxilSignatureElementStartRow ] = Int32ToConstMD(SE.GetStartRow());
  309. MDVals[kDxilSignatureElementStartCol ] = Int8ToConstMD((int8_t)SE.GetStartCol());
  310. // Name-value list of extended properties.
  311. MDVals[kDxilSignatureElementNameValueList] = nullptr;
  312. vector<Metadata *> MDExtraVals;
  313. m_ExtraPropertyHelper->EmitSignatureElementProperties(SE, MDExtraVals);
  314. if (!MDExtraVals.empty()) {
  315. MDVals[kDxilSignatureElementNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  316. }
  317. // NOTE: when extra properties for signature elements are needed, extend ExtraPropertyHelper.
  318. return MDNode::get(m_Ctx, MDVals);
  319. }
  320. void DxilMDHelper::LoadSignatureElement(const MDOperand &MDO, DxilSignatureElement &SE) {
  321. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  322. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  323. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  324. IFTBOOL(pTupleMD->getNumOperands() == kDxilSignatureElementNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  325. unsigned ID = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementID));
  326. MDString *pName = dyn_cast<MDString>( pTupleMD->getOperand(kDxilSignatureElementName));
  327. CompType CT = CompType(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementType)));
  328. DXIL::SemanticKind SemKind =
  329. (DXIL::SemanticKind)ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementSystemValue));
  330. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(kDxilSignatureElementIndexVector));
  331. InterpolationMode IM(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementInterpMode)));
  332. unsigned NumRows = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementRows));
  333. uint8_t NumCols = ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementCols));
  334. int32_t StartRow = ConstMDToInt32( pTupleMD->getOperand(kDxilSignatureElementStartRow));
  335. int8_t StartCol = ConstMDToInt8( pTupleMD->getOperand(kDxilSignatureElementStartCol));
  336. IFTBOOL(pName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  337. IFTBOOL(pSemanticIndexVectorMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  338. vector<unsigned> SemanticIndexVector;
  339. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  340. SE.Initialize(pName->getString(), CT, IM, NumRows, NumCols, StartRow, StartCol, ID, SemanticIndexVector);
  341. SE.SetKind(SemKind);
  342. // Name-value list of extended properties.
  343. m_ExtraPropertyHelper->LoadSignatureElementProperties(pTupleMD->getOperand(kDxilSignatureElementNameValueList), SE);
  344. }
  345. //
  346. // Resources.
  347. //
  348. MDTuple *DxilMDHelper::EmitDxilResourceTuple(MDTuple *pSRVs, MDTuple *pUAVs,
  349. MDTuple *pCBuffers, MDTuple *pSamplers) {
  350. DXASSERT(pSRVs != nullptr || pUAVs != nullptr || pCBuffers != nullptr || pSamplers != nullptr, "resource tuple should not be emitted if there are no resources");
  351. Metadata *MDVals[kDxilNumResourceFields];
  352. MDVals[kDxilResourceSRVs ] = pSRVs;
  353. MDVals[kDxilResourceUAVs ] = pUAVs;
  354. MDVals[kDxilResourceCBuffers] = pCBuffers;
  355. MDVals[kDxilResourceSamplers] = pSamplers;
  356. MDTuple *pTupleMD = MDNode::get(m_Ctx, MDVals);
  357. NamedMDNode *pResourcesNamedMD = m_pModule->getNamedMetadata(kDxilResourcesMDName);
  358. IFTBOOL(pResourcesNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  359. pResourcesNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  360. pResourcesNamedMD->addOperand(pTupleMD);
  361. return pTupleMD;
  362. }
  363. void DxilMDHelper::GetDxilResources(const MDOperand &MDO, const MDTuple *&pSRVs,
  364. const MDTuple *&pUAVs, const MDTuple *&pCBuffers,
  365. const MDTuple *&pSamplers) {
  366. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  367. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  368. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  369. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumResourceFields, DXC_E_INCORRECT_DXIL_METADATA);
  370. pSRVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSRVs ));
  371. pUAVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceUAVs ));
  372. pCBuffers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceCBuffers));
  373. pSamplers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSamplers));
  374. }
  375. void DxilMDHelper::EmitDxilResourceBase(const DxilResourceBase &R, Metadata *ppMDVals[]) {
  376. ppMDVals[kDxilResourceBaseID ] = Uint32ToConstMD(R.GetID());
  377. ppMDVals[kDxilResourceBaseVariable ] = ValueAsMetadata::get(R.GetGlobalSymbol());
  378. ppMDVals[kDxilResourceBaseName ] = MDString::get(m_Ctx, R.GetGlobalName());
  379. ppMDVals[kDxilResourceBaseSpaceID ] = Uint32ToConstMD(R.GetSpaceID());
  380. ppMDVals[kDxilResourceBaseLowerBound] = Uint32ToConstMD(R.GetLowerBound());
  381. ppMDVals[kDxilResourceBaseRangeSize ] = Uint32ToConstMD(R.GetRangeSize());
  382. }
  383. void DxilMDHelper::LoadDxilResourceBase(const MDOperand &MDO, DxilResourceBase &R) {
  384. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  385. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  386. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  387. IFTBOOL(pTupleMD->getNumOperands() >= kDxilResourceBaseNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  388. R.SetID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseID)));
  389. R.SetGlobalSymbol(dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilResourceBaseVariable))));
  390. R.SetGlobalName(StringMDToString(pTupleMD->getOperand(kDxilResourceBaseName)));
  391. R.SetSpaceID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseSpaceID)));
  392. R.SetLowerBound(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseLowerBound)));
  393. R.SetRangeSize(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseRangeSize)));
  394. }
  395. MDTuple *DxilMDHelper::EmitDxilSRV(const DxilResource &SRV) {
  396. Metadata *MDVals[kDxilSRVNumFields];
  397. EmitDxilResourceBase(SRV, &MDVals[0]);
  398. // SRV-specific fields.
  399. MDVals[kDxilSRVShape ] = Uint32ToConstMD((unsigned)SRV.GetKind());
  400. MDVals[kDxilSRVSampleCount ] = Uint32ToConstMD(SRV.GetSampleCount());
  401. // Name-value list of extended properties.
  402. MDVals[kDxilSRVNameValueList] = nullptr;
  403. vector<Metadata *> MDExtraVals;
  404. m_ExtraPropertyHelper->EmitSRVProperties(SRV, MDExtraVals);
  405. if (!MDExtraVals.empty()) {
  406. MDVals[kDxilSRVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  407. }
  408. return MDNode::get(m_Ctx, MDVals);
  409. }
  410. void DxilMDHelper::LoadDxilSRV(const MDOperand &MDO, DxilResource &SRV) {
  411. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  412. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  413. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  414. IFTBOOL(pTupleMD->getNumOperands() == kDxilSRVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  415. SRV.SetRW(false);
  416. LoadDxilResourceBase(MDO, SRV);
  417. // SRV-specific fields.
  418. SRV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilSRVShape)));
  419. SRV.SetSampleCount(ConstMDToUint32(pTupleMD->getOperand(kDxilSRVSampleCount)));
  420. // Name-value list of extended properties.
  421. m_ExtraPropertyHelper->LoadSRVProperties(pTupleMD->getOperand(kDxilSRVNameValueList), SRV);
  422. }
  423. MDTuple *DxilMDHelper::EmitDxilUAV(const DxilResource &UAV) {
  424. Metadata *MDVals[kDxilUAVNumFields];
  425. EmitDxilResourceBase(UAV, &MDVals[0]);
  426. // UAV-specific fields.
  427. MDVals[kDxilUAVShape ] = Uint32ToConstMD((unsigned)UAV.GetKind());
  428. MDVals[kDxilUAVGloballyCoherent ] = BoolToConstMD(UAV.IsGloballyCoherent());
  429. MDVals[kDxilUAVCounter ] = BoolToConstMD(UAV.HasCounter());
  430. MDVals[kDxilUAVRasterizerOrderedView] = BoolToConstMD(UAV.IsROV());
  431. // Name-value list of extended properties.
  432. MDVals[kDxilUAVNameValueList ] = nullptr;
  433. vector<Metadata *> MDExtraVals;
  434. m_ExtraPropertyHelper->EmitUAVProperties(UAV, MDExtraVals);
  435. if (!MDExtraVals.empty()) {
  436. MDVals[kDxilUAVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  437. }
  438. return MDNode::get(m_Ctx, MDVals);
  439. }
  440. void DxilMDHelper::LoadDxilUAV(const MDOperand &MDO, DxilResource &UAV) {
  441. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  442. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  443. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  444. IFTBOOL(pTupleMD->getNumOperands() == kDxilUAVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  445. UAV.SetRW(true);
  446. LoadDxilResourceBase(MDO, UAV);
  447. // UAV-specific fields.
  448. UAV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilUAVShape)));
  449. UAV.SetGloballyCoherent(ConstMDToBool(pTupleMD->getOperand(kDxilUAVGloballyCoherent)));
  450. UAV.SetHasCounter(ConstMDToBool(pTupleMD->getOperand(kDxilUAVCounter)));
  451. UAV.SetROV(ConstMDToBool(pTupleMD->getOperand(kDxilUAVRasterizerOrderedView)));
  452. // Name-value list of extended properties.
  453. m_ExtraPropertyHelper->LoadUAVProperties(pTupleMD->getOperand(kDxilUAVNameValueList), UAV);
  454. }
  455. MDTuple *DxilMDHelper::EmitDxilCBuffer(const DxilCBuffer &CB) {
  456. Metadata *MDVals[kDxilCBufferNumFields];
  457. EmitDxilResourceBase(CB, &MDVals[0]);
  458. // CBuffer-specific fields.
  459. // CBuffer size in bytes.
  460. MDVals[kDxilCBufferSizeInBytes ] = Uint32ToConstMD(CB.GetSize());
  461. // Name-value list of extended properties.
  462. MDVals[kDxilCBufferNameValueList] = nullptr;
  463. vector<Metadata *> MDExtraVals;
  464. m_ExtraPropertyHelper->EmitCBufferProperties(CB, MDExtraVals);
  465. if (!MDExtraVals.empty()) {
  466. MDVals[kDxilCBufferNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  467. }
  468. return MDNode::get(m_Ctx, MDVals);
  469. }
  470. void DxilMDHelper::LoadDxilCBuffer(const MDOperand &MDO, DxilCBuffer &CB) {
  471. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  472. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  473. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  474. IFTBOOL(pTupleMD->getNumOperands() == kDxilCBufferNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  475. LoadDxilResourceBase(MDO, CB);
  476. // CBuffer-specific fields.
  477. CB.SetSize(ConstMDToUint32(pTupleMD->getOperand(kDxilCBufferSizeInBytes)));
  478. // Name-value list of extended properties.
  479. m_ExtraPropertyHelper->LoadCBufferProperties(pTupleMD->getOperand(kDxilCBufferNameValueList), CB);
  480. }
  481. void DxilMDHelper::EmitDxilTypeSystem(DxilTypeSystem &TypeSystem, vector<GlobalVariable*> &LLVMUsed) {
  482. auto &TypeMap = TypeSystem.GetStructAnnotationMap();
  483. vector<Metadata *> MDVals;
  484. MDVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemStructTag)); // Tag
  485. unsigned GVIdx = 0;
  486. for (auto it = TypeMap.begin(); it != TypeMap.end(); ++it, GVIdx++) {
  487. StructType *pStructType = const_cast<StructType *>(it->first);
  488. DxilStructAnnotation *pA = it->second.get();
  489. // Emit struct type field annotations.
  490. Metadata *pMD = EmitDxilStructAnnotation(*pA);
  491. MDVals.push_back(ValueAsMetadata::get(UndefValue::get(pStructType)));
  492. MDVals.push_back(pMD);
  493. }
  494. auto &FuncMap = TypeSystem.GetFunctionAnnotationMap();
  495. vector<Metadata *> MDFuncVals;
  496. MDFuncVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemFunctionTag)); // Tag
  497. for (auto it = FuncMap.begin(); it != FuncMap.end(); ++it) {
  498. DxilFunctionAnnotation *pA = it->second.get();
  499. MDFuncVals.push_back(ValueAsMetadata::get(const_cast<Function*>(pA->GetFunction())));
  500. // Emit function annotations.
  501. Metadata *pMD = EmitDxilFunctionAnnotation(*pA);
  502. MDFuncVals.push_back(pMD);
  503. }
  504. if (MDVals.size() > 1) {
  505. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  506. IFTBOOL(pDxilTypeAnnotationsMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  507. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  508. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDVals));
  509. }
  510. if (MDFuncVals.size() > 1) {
  511. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  512. if (pDxilTypeAnnotationsMD == nullptr)
  513. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  514. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDFuncVals));
  515. }
  516. }
  517. void DxilMDHelper::LoadDxilTypeSystemNode(const llvm::MDTuple &MDT,
  518. DxilTypeSystem &TypeSystem) {
  519. unsigned Tag = ConstMDToUint32(MDT.getOperand(0));
  520. if (Tag == kDxilTypeSystemStructTag) {
  521. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  522. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  523. Constant *pGV =
  524. dyn_cast<Constant>(ValueMDToValue(MDT.getOperand(i)));
  525. IFTBOOL(pGV != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  526. StructType *pGVType =
  527. dyn_cast<StructType>(pGV->getType());
  528. IFTBOOL(pGVType != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  529. DxilStructAnnotation *pSA = TypeSystem.AddStructAnnotation(pGVType);
  530. LoadDxilStructAnnotation(MDT.getOperand(i + 1), *pSA);
  531. }
  532. } else {
  533. IFTBOOL(Tag == kDxilTypeSystemFunctionTag, DXC_E_INCORRECT_DXIL_METADATA);
  534. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  535. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  536. Function *F = dyn_cast<Function>(ValueMDToValue(MDT.getOperand(i)));
  537. DxilFunctionAnnotation *pFA = TypeSystem.AddFunctionAnnotation(F);
  538. LoadDxilFunctionAnnotation(MDT.getOperand(i + 1), *pFA);
  539. }
  540. }
  541. }
  542. void DxilMDHelper::LoadDxilTypeSystem(DxilTypeSystem &TypeSystem) {
  543. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  544. if (pDxilTypeAnnotationsMD == nullptr)
  545. return;
  546. IFTBOOL(pDxilTypeAnnotationsMD->getNumOperands() <= 2, DXC_E_INCORRECT_DXIL_METADATA);
  547. for (unsigned i = 0; i < pDxilTypeAnnotationsMD->getNumOperands(); i++) {
  548. const MDTuple *pTupleMD = dyn_cast<MDTuple>(pDxilTypeAnnotationsMD->getOperand(i));
  549. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  550. LoadDxilTypeSystemNode(*pTupleMD, TypeSystem);
  551. }
  552. }
  553. Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
  554. vector<Metadata *> MDVals(SA.GetNumFields() + 1);
  555. MDVals[0] = Uint32ToConstMD(SA.GetCBufferSize());
  556. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  557. MDVals[i+1] = EmitDxilFieldAnnotation(SA.GetFieldAnnotation(i));
  558. }
  559. return MDNode::get(m_Ctx, MDVals);
  560. }
  561. void DxilMDHelper::LoadDxilStructAnnotation(const MDOperand &MDO, DxilStructAnnotation &SA) {
  562. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  563. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  564. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  565. if (pTupleMD->getNumOperands() == 1) {
  566. const StructType *ST = SA.GetStructType();
  567. if (ST->getNumElements() == 1) {
  568. Type *EltTy = ST->getElementType(0);
  569. if (EltTy == Type::getInt8Ty(ST->getContext())) {
  570. SA.MarkEmptyStruct();
  571. }
  572. }
  573. }
  574. IFTBOOL(pTupleMD->getNumOperands() == SA.GetNumFields()+1, DXC_E_INCORRECT_DXIL_METADATA);
  575. SA.SetCBufferSize(ConstMDToUint32(pTupleMD->getOperand(0)));
  576. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  577. const MDOperand &MDO = pTupleMD->getOperand(i+1);
  578. DxilFieldAnnotation &FA = SA.GetFieldAnnotation(i);
  579. LoadDxilFieldAnnotation(MDO, FA);
  580. }
  581. }
  582. Metadata *
  583. DxilMDHelper::EmitDxilFunctionAnnotation(const DxilFunctionAnnotation &FA) {
  584. vector<Metadata *> MDVals(FA.GetNumParameters() + 1);
  585. MDVals[0] = EmitDxilParamAnnotation(FA.GetRetTypeAnnotation());
  586. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  587. MDVals[i + 1] = EmitDxilParamAnnotation(FA.GetParameterAnnotation(i));
  588. }
  589. return MDNode::get(m_Ctx, MDVals);
  590. }
  591. void DxilMDHelper::LoadDxilFunctionAnnotation(const MDOperand &MDO,
  592. DxilFunctionAnnotation &FA) {
  593. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  594. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  595. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  596. IFTBOOL(pTupleMD->getNumOperands() == FA.GetNumParameters() + 1,
  597. DXC_E_INCORRECT_DXIL_METADATA);
  598. DxilParameterAnnotation &retTyAnnotation = FA.GetRetTypeAnnotation();
  599. LoadDxilParamAnnotation(pTupleMD->getOperand(0), retTyAnnotation);
  600. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  601. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  602. DxilParameterAnnotation &PA = FA.GetParameterAnnotation(i);
  603. LoadDxilParamAnnotation(MDO, PA);
  604. }
  605. }
  606. Metadata *
  607. DxilMDHelper::EmitDxilParamAnnotation(const DxilParameterAnnotation &PA) {
  608. vector<Metadata *> MDVals(3);
  609. MDVals[0] = Uint32ToConstMD(static_cast<unsigned>(PA.GetParamInputQual()));
  610. MDVals[1] = EmitDxilFieldAnnotation(PA);
  611. MDVals[2] = Uint32VectorToConstMDTuple(PA.GetSemanticIndexVec());
  612. return MDNode::get(m_Ctx, MDVals);
  613. }
  614. void DxilMDHelper::LoadDxilParamAnnotation(const MDOperand &MDO,
  615. DxilParameterAnnotation &PA) {
  616. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  617. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  618. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  619. IFTBOOL(pTupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  620. PA.SetParamInputQual(static_cast<DxilParamInputQual>(
  621. ConstMDToUint32(pTupleMD->getOperand(0))));
  622. LoadDxilFieldAnnotation(pTupleMD->getOperand(1), PA);
  623. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(2));
  624. vector<unsigned> SemanticIndexVector;
  625. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  626. PA.SetSemanticIndexVec(SemanticIndexVector);
  627. }
  628. Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
  629. vector<Metadata *> MDVals; // Tag-Value list.
  630. if (FA.HasFieldName()) {
  631. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationFieldNameTag));
  632. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetFieldName()));
  633. }
  634. if (FA.IsPrecise()) {
  635. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationPreciseTag)); // Tag
  636. MDVals.emplace_back(BoolToConstMD(true)); // Value
  637. }
  638. if (FA.HasMatrixAnnotation()) {
  639. const DxilMatrixAnnotation &MA = FA.GetMatrixAnnotation();
  640. Metadata *MatrixMD[3];
  641. MatrixMD[0] = Uint32ToConstMD(MA.Rows);
  642. MatrixMD[1] = Uint32ToConstMD(MA.Cols);
  643. MatrixMD[2] = Uint32ToConstMD((unsigned)MA.Orientation);
  644. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationMatrixTag));
  645. MDVals.emplace_back(MDNode::get(m_Ctx, MatrixMD));
  646. }
  647. if (FA.HasCBufferOffset()) {
  648. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBufferOffsetTag));
  649. MDVals.emplace_back(Uint32ToConstMD(FA.GetCBufferOffset()));
  650. }
  651. if (FA.HasSemanticString()) {
  652. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationSemanticStringTag));
  653. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetSemanticString()));
  654. }
  655. if (FA.HasInterpolationMode()) {
  656. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationInterpolationModeTag));
  657. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetInterpolationMode().GetKind()));
  658. }
  659. if (FA.HasCompType()) {
  660. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
  661. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
  662. }
  663. return MDNode::get(m_Ctx, MDVals);
  664. }
  665. void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnotation &FA) {
  666. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  667. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  668. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  669. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  670. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  671. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(i));
  672. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  673. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  674. switch (Tag) {
  675. case kDxilFieldAnnotationPreciseTag:
  676. FA.SetPrecise(ConstMDToBool(MDO));
  677. break;
  678. case kDxilFieldAnnotationMatrixTag: {
  679. DxilMatrixAnnotation MA;
  680. const MDTuple *pMATupleMD = dyn_cast<MDTuple>(MDO.get());
  681. IFTBOOL(pMATupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  682. IFTBOOL(pMATupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  683. MA.Rows = ConstMDToUint32(pMATupleMD->getOperand(0));
  684. MA.Cols = ConstMDToUint32(pMATupleMD->getOperand(1));
  685. MA.Orientation = (MatrixOrientation)ConstMDToUint32(pMATupleMD->getOperand(2));
  686. FA.SetMatrixAnnotation(MA);
  687. } break;
  688. case kDxilFieldAnnotationCBufferOffsetTag:
  689. FA.SetCBufferOffset(ConstMDToUint32(MDO));
  690. break;
  691. case kDxilFieldAnnotationSemanticStringTag:
  692. FA.SetSemanticString(StringMDToString(MDO));
  693. break;
  694. case kDxilFieldAnnotationInterpolationModeTag:
  695. FA.SetInterpolationMode(InterpolationMode((InterpolationMode::Kind)ConstMDToUint32(MDO)));
  696. break;
  697. case kDxilFieldAnnotationFieldNameTag:
  698. FA.SetFieldName(StringMDToString(MDO));
  699. break;
  700. case kDxilFieldAnnotationCompTypeTag:
  701. FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
  702. break;
  703. default:
  704. // TODO: I don't think we should be failing unrecognized extended tags.
  705. // Perhaps we can flag this case in the module and fail validation
  706. // if flagged.
  707. // That way, an existing loader will not fail on an additional tag
  708. // and the blob would not be signed if the extra tag was not legal.
  709. IFTBOOL(false, DXC_E_INCORRECT_DXIL_METADATA);
  710. }
  711. }
  712. }
  713. void DxilMDHelper::EmitDxilViewIdState(DxilViewIdState &ViewIdState) {
  714. const vector<unsigned> &Data = ViewIdState.GetSerialized();
  715. // If all UINTs are zero, do not emit ViewIdState.
  716. if (!std::any_of(Data.begin(), Data.end(), [](unsigned e){return e!=0;}))
  717. return;
  718. Constant *V = ConstantDataArray::get(m_Ctx, ArrayRef<uint32_t>(Data));
  719. NamedMDNode *pViewIdNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  720. IFTBOOL(pViewIdNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  721. pViewIdNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilViewIdStateMDName);
  722. pViewIdNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  723. }
  724. void DxilMDHelper::LoadDxilViewIdState(DxilViewIdState &ViewIdState) {
  725. NamedMDNode *pViewIdStateNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  726. if(!pViewIdStateNamedMD)
  727. return;
  728. IFTBOOL(pViewIdStateNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  729. MDNode *pNode = pViewIdStateNamedMD->getOperand(0);
  730. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  731. const MDOperand &MDO = pNode->getOperand(0);
  732. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  733. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  734. if (isa<ConstantAggregateZero>(pMetaData->getValue()))
  735. return;
  736. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pMetaData->getValue());
  737. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  738. IFTBOOL(pData->getElementType() == Type::getInt32Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  739. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  740. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  741. ViewIdState.Deserialize((unsigned *)pData->getRawDataValues().begin(),
  742. (unsigned)pData->getRawDataValues().size() / 4);
  743. }
  744. MDNode *DxilMDHelper::EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<DXIL::ControlFlowHint> &hints) {
  745. SmallVector<Metadata *, 4> Args;
  746. // Reserve operand 0 for self reference.
  747. auto TempNode = MDNode::getTemporary(Ctx, None);
  748. Args.emplace_back(TempNode.get());
  749. Args.emplace_back(MDString::get(Ctx, kDxilControlFlowHintMDName));
  750. for (DXIL::ControlFlowHint &hint : hints)
  751. Args.emplace_back(Uint32ToConstMD(static_cast<unsigned>(hint), Ctx));
  752. MDNode *hintsNode = MDNode::get(Ctx, Args);
  753. // Set the first operand to itself.
  754. hintsNode->replaceOperandWith(0, hintsNode);
  755. return hintsNode;
  756. }
  757. MDTuple *DxilMDHelper::EmitDxilSampler(const DxilSampler &S) {
  758. Metadata *MDVals[kDxilSamplerNumFields];
  759. EmitDxilResourceBase(S, &MDVals[0]);
  760. // Sampler-specific fields.
  761. MDVals[kDxilSamplerType ] = Uint32ToConstMD((unsigned)S.GetSamplerKind());
  762. // Name-value list of extended properties.
  763. MDVals[kDxilSamplerNameValueList] = nullptr;
  764. vector<Metadata *> MDExtraVals;
  765. m_ExtraPropertyHelper->EmitSamplerProperties(S, MDExtraVals);
  766. if (!MDExtraVals.empty()) {
  767. MDVals[kDxilSamplerNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  768. }
  769. return MDNode::get(m_Ctx, MDVals);
  770. }
  771. void DxilMDHelper::LoadDxilSampler(const MDOperand &MDO, DxilSampler &S) {
  772. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  773. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  774. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  775. IFTBOOL(pTupleMD->getNumOperands() == kDxilSamplerNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  776. LoadDxilResourceBase(MDO, S);
  777. // Sampler-specific fields.
  778. S.SetSamplerKind((DxilSampler::SamplerKind)ConstMDToUint32(pTupleMD->getOperand(kDxilSamplerType)));
  779. // Name-value list of extended properties.
  780. m_ExtraPropertyHelper->LoadSamplerProperties(pTupleMD->getOperand(kDxilSamplerNameValueList), S);
  781. }
  782. const MDOperand &DxilMDHelper::GetResourceClass(llvm::MDNode *MD,
  783. DXIL::ResourceClass &RC) {
  784. IFTBOOL(MD->getNumOperands() >=
  785. DxilMDHelper::kHLDxilResourceAttributeNumFields,
  786. DXC_E_INCORRECT_DXIL_METADATA);
  787. RC = static_cast<DxilResource::Class>(ConstMDToUint32(
  788. MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeClass)));
  789. return MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeMeta);
  790. }
  791. void DxilMDHelper::LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD,
  792. DxilResourceBase &R) {
  793. DxilResource::Class RC = DxilResource::Class::Invalid;
  794. const MDOperand &Meta = GetResourceClass(MD, RC);
  795. switch (RC) {
  796. case DxilResource::Class::CBuffer: {
  797. DxilCBuffer CB;
  798. LoadDxilCBuffer(Meta, CB);
  799. R = CB;
  800. } break;
  801. case DxilResource::Class::Sampler: {
  802. DxilSampler S;
  803. LoadDxilSampler(Meta, S);
  804. R = S;
  805. } break;
  806. case DxilResource::Class::SRV: {
  807. DxilResource Res;
  808. LoadDxilSRV(Meta, Res);
  809. R = Res;
  810. } break;
  811. case DxilResource::Class::UAV: {
  812. DxilResource Res;
  813. LoadDxilUAV(Meta, Res);
  814. R = Res;
  815. } break;
  816. default:
  817. DXASSERT(0, "Invalid metadata");
  818. }
  819. }
  820. void DxilMDHelper::LoadDxilResourceFromMDNode(llvm::MDNode *MD,
  821. DxilResource &R) {
  822. DxilResource::Class RC = DxilResource::Class::Invalid;
  823. const MDOperand &Meta = GetResourceClass(MD, RC);
  824. switch (RC) {
  825. case DxilResource::Class::SRV: {
  826. LoadDxilSRV(Meta, R);
  827. } break;
  828. case DxilResource::Class::UAV: {
  829. LoadDxilUAV(Meta, R);
  830. } break;
  831. default:
  832. DXASSERT(0, "Invalid metadata");
  833. }
  834. }
  835. void DxilMDHelper::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  836. DxilResource::Class RC = DxilResource::Class::Invalid;
  837. const MDOperand &Meta = GetResourceClass(MD, RC);
  838. switch (RC) {
  839. case DxilResource::Class::Sampler: {
  840. LoadDxilSampler(Meta, S);
  841. } break;
  842. default:
  843. DXASSERT(0, "Invalid metadata");
  844. }
  845. }
  846. //
  847. // DxilExtraPropertyHelper shader-specific methods.
  848. //
  849. MDTuple *DxilMDHelper::EmitDxilGSState(DXIL::InputPrimitive Primitive,
  850. unsigned MaxVertexCount,
  851. unsigned ActiveStreamMask,
  852. DXIL::PrimitiveTopology StreamPrimitiveTopology,
  853. unsigned GSInstanceCount) {
  854. Metadata *MDVals[kDxilGSStateNumFields];
  855. MDVals[kDxilGSStateInputPrimitive ] = Uint32ToConstMD((unsigned)Primitive);
  856. MDVals[kDxilGSStateMaxVertexCount ] = Uint32ToConstMD(MaxVertexCount);
  857. MDVals[kDxilGSStateActiveStreamMask ] = Uint32ToConstMD(ActiveStreamMask);
  858. MDVals[kDxilGSStateOutputStreamTopology] = Uint32ToConstMD((unsigned)StreamPrimitiveTopology);
  859. MDVals[kDxilGSStateGSInstanceCount ] = Uint32ToConstMD(GSInstanceCount);
  860. return MDNode::get(m_Ctx, MDVals);
  861. }
  862. void DxilMDHelper::LoadDxilGSState(const MDOperand &MDO,
  863. DXIL::InputPrimitive &Primitive,
  864. unsigned &MaxVertexCount,
  865. unsigned &ActiveStreamMask,
  866. DXIL::PrimitiveTopology &StreamPrimitiveTopology,
  867. unsigned &GSInstanceCount) {
  868. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  869. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  870. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  871. IFTBOOL(pTupleMD->getNumOperands() == kDxilGSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  872. Primitive = (DXIL::InputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateInputPrimitive));
  873. MaxVertexCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateMaxVertexCount));
  874. ActiveStreamMask = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateActiveStreamMask));
  875. StreamPrimitiveTopology = (DXIL::PrimitiveTopology)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateOutputStreamTopology));
  876. GSInstanceCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateGSInstanceCount));
  877. }
  878. MDTuple *DxilMDHelper::EmitDxilDSState(DXIL::TessellatorDomain Domain, unsigned InputControlPointCount) {
  879. Metadata *MDVals[kDxilDSStateNumFields];
  880. MDVals[kDxilDSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)Domain);
  881. MDVals[kDxilDSStateInputControlPointCount] = Uint32ToConstMD(InputControlPointCount);
  882. return MDNode::get(m_Ctx, MDVals);
  883. }
  884. void DxilMDHelper::LoadDxilDSState(const MDOperand &MDO,
  885. DXIL::TessellatorDomain &Domain,
  886. unsigned &InputControlPointCount) {
  887. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  888. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  889. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  890. IFTBOOL(pTupleMD->getNumOperands() == kDxilDSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  891. Domain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateTessellatorDomain));
  892. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateInputControlPointCount));
  893. }
  894. MDTuple *DxilMDHelper::EmitDxilHSState(Function *pPatchConstantFunction,
  895. unsigned InputControlPointCount,
  896. unsigned OutputControlPointCount,
  897. DXIL::TessellatorDomain TessDomain,
  898. DXIL::TessellatorPartitioning TessPartitioning,
  899. DXIL::TessellatorOutputPrimitive TessOutputPrimitive,
  900. float MaxTessFactor) {
  901. Metadata *MDVals[kDxilHSStateNumFields];
  902. MDVals[kDxilHSStatePatchConstantFunction ] = ValueAsMetadata::get(pPatchConstantFunction);
  903. MDVals[kDxilHSStateInputControlPointCount ] = Uint32ToConstMD(InputControlPointCount);
  904. MDVals[kDxilHSStateOutputControlPointCount ] = Uint32ToConstMD(OutputControlPointCount);
  905. MDVals[kDxilHSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)TessDomain);
  906. MDVals[kDxilHSStateTessellatorPartitioning ] = Uint32ToConstMD((unsigned)TessPartitioning);
  907. MDVals[kDxilHSStateTessellatorOutputPrimitive] = Uint32ToConstMD((unsigned)TessOutputPrimitive);
  908. MDVals[kDxilHSStateMaxTessellationFactor ] = FloatToConstMD(MaxTessFactor);
  909. return MDNode::get(m_Ctx, MDVals);
  910. }
  911. void DxilMDHelper::LoadDxilHSState(const MDOperand &MDO,
  912. Function *&pPatchConstantFunction,
  913. unsigned &InputControlPointCount,
  914. unsigned &OutputControlPointCount,
  915. DXIL::TessellatorDomain &TessDomain,
  916. DXIL::TessellatorPartitioning &TessPartitioning,
  917. DXIL::TessellatorOutputPrimitive &TessOutputPrimitive,
  918. float &MaxTessFactor) {
  919. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  920. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  921. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  922. IFTBOOL(pTupleMD->getNumOperands() == kDxilHSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  923. pPatchConstantFunction = dyn_cast<Function>(ValueMDToValue(pTupleMD->getOperand(kDxilHSStatePatchConstantFunction)));
  924. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateInputControlPointCount));
  925. OutputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateOutputControlPointCount));
  926. TessDomain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorDomain));
  927. TessPartitioning = (DXIL::TessellatorPartitioning)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorPartitioning));
  928. TessOutputPrimitive = (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorOutputPrimitive));
  929. MaxTessFactor = ConstMDToFloat(pTupleMD->getOperand(kDxilHSStateMaxTessellationFactor));
  930. }
  931. //
  932. // DxilExtraPropertyHelper methods.
  933. //
  934. DxilMDHelper::ExtraPropertyHelper::ExtraPropertyHelper(Module *pModule)
  935. : m_pModule(pModule)
  936. , m_Ctx(pModule->getContext()) {
  937. }
  938. DxilExtraPropertyHelper::DxilExtraPropertyHelper(Module *pModule)
  939. : ExtraPropertyHelper(pModule) {
  940. }
  941. void DxilExtraPropertyHelper::EmitSRVProperties(const DxilResource &SRV, std::vector<Metadata *> &MDVals) {
  942. // Element type for typed resource.
  943. if (!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer()) {
  944. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  945. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)SRV.GetCompType().GetKind(), m_Ctx));
  946. }
  947. // Element stride for structured buffer.
  948. if (SRV.IsStructuredBuffer()) {
  949. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  950. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SRV.GetElementStride(), m_Ctx));
  951. }
  952. }
  953. void DxilExtraPropertyHelper::LoadSRVProperties(const MDOperand &MDO, DxilResource &SRV) {
  954. SRV.SetElementStride(SRV.IsRawBuffer() ? 1 : 4);
  955. SRV.SetCompType(CompType());
  956. if (MDO.get() == nullptr) {
  957. return;
  958. }
  959. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  960. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  961. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  962. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  963. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  964. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  965. switch (Tag) {
  966. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  967. DXASSERT_NOMSG(!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer());
  968. SRV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  969. break;
  970. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  971. DXASSERT_NOMSG(SRV.IsStructuredBuffer());
  972. SRV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  973. break;
  974. default:
  975. DXASSERT(false, "Unknown resource record tag");
  976. }
  977. }
  978. }
  979. void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::vector<Metadata *> &MDVals) {
  980. // Element type for typed RW resource.
  981. if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer()) {
  982. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  983. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetCompType().GetKind(), m_Ctx));
  984. }
  985. // Element stride for structured RW buffer.
  986. if (UAV.IsStructuredBuffer()) {
  987. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  988. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(UAV.GetElementStride(), m_Ctx));
  989. }
  990. }
  991. void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResource &UAV) {
  992. UAV.SetElementStride(UAV.IsRawBuffer() ? 1 : 4);
  993. UAV.SetCompType(CompType());
  994. if (MDO.get() == nullptr) {
  995. return;
  996. }
  997. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  998. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  999. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1000. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1001. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1002. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1003. switch (Tag) {
  1004. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  1005. DXASSERT_NOMSG(!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer());
  1006. UAV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  1007. break;
  1008. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  1009. DXASSERT_NOMSG(UAV.IsStructuredBuffer());
  1010. UAV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  1011. break;
  1012. default:
  1013. DXASSERT(false, "Unknown resource record tag");
  1014. }
  1015. }
  1016. }
  1017. void DxilExtraPropertyHelper::EmitCBufferProperties(const DxilCBuffer &CB, vector<Metadata *> &MDVals) {
  1018. // Emit property to preserve tbuffer kind
  1019. if (CB.GetKind() == DXIL::ResourceKind::TBuffer) {
  1020. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kHLCBufferIsTBufferTag, m_Ctx));
  1021. MDVals.emplace_back(DxilMDHelper::BoolToConstMD(true, m_Ctx));
  1022. }
  1023. }
  1024. void DxilExtraPropertyHelper::LoadCBufferProperties(const MDOperand &MDO, DxilCBuffer &CB) {
  1025. if (MDO.get() == nullptr)
  1026. return;
  1027. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1028. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1029. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1030. // Override kind for tbuffer that has not yet been converted to SRV.
  1031. CB.SetKind(DXIL::ResourceKind::CBuffer);
  1032. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1033. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1034. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1035. switch (Tag) {
  1036. case DxilMDHelper::kHLCBufferIsTBufferTag:
  1037. if (DxilMDHelper::ConstMDToBool(MDO)) {
  1038. CB.SetKind(DXIL::ResourceKind::TBuffer);
  1039. }
  1040. break;
  1041. default:
  1042. DXASSERT(false, "Unknown cbuffer tag");
  1043. }
  1044. }
  1045. }
  1046. void DxilExtraPropertyHelper::EmitSamplerProperties(const DxilSampler &S, std::vector<Metadata *> &MDVals) {
  1047. // Nothing yet.
  1048. }
  1049. void DxilExtraPropertyHelper::LoadSamplerProperties(const MDOperand &MDO, DxilSampler &S) {
  1050. // Nothing yet.
  1051. }
  1052. void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignatureElement &SE,
  1053. vector<Metadata *> &MDVals) {
  1054. // Output stream, if non-zero.
  1055. if (SE.GetOutputStream() != 0) {
  1056. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementOutputStreamTag, m_Ctx));
  1057. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetOutputStream(), m_Ctx));
  1058. }
  1059. // Mask of Dynamically indexed components.
  1060. if (SE.GetDynIdxCompMask() != 0) {
  1061. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
  1062. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
  1063. }
  1064. }
  1065. void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
  1066. if (MDO.get() == nullptr)
  1067. return;
  1068. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1069. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1070. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1071. // Stream.
  1072. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1073. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1074. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1075. switch (Tag) {
  1076. case DxilMDHelper::kDxilSignatureElementOutputStreamTag:
  1077. SE.SetOutputStream(DxilMDHelper::ConstMDToUint32(MDO));
  1078. break;
  1079. case DxilMDHelper::kHLSignatureElementGlobalSymbolTag:
  1080. break;
  1081. case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
  1082. SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
  1083. break;
  1084. default:
  1085. DXASSERT(false, "Unknown signature element tag");
  1086. }
  1087. }
  1088. }
  1089. //
  1090. // Utilities.
  1091. //
  1092. bool DxilMDHelper::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
  1093. StringRef name = Node.getName();
  1094. for (unsigned i = 0; i < DxilMDNames.size(); i++) {
  1095. if (name == DxilMDNames[i]) {
  1096. return true;
  1097. }
  1098. }
  1099. return false;
  1100. }
  1101. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v, LLVMContext &Ctx) {
  1102. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1103. }
  1104. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v) {
  1105. return DxilMDHelper::Int32ToConstMD(v, m_Ctx);
  1106. }
  1107. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v, LLVMContext &Ctx) {
  1108. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1109. }
  1110. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v) {
  1111. return DxilMDHelper::Uint32ToConstMD(v, m_Ctx);
  1112. }
  1113. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v, LLVMContext &Ctx) {
  1114. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 64), APInt(64, v)));
  1115. }
  1116. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v) {
  1117. return DxilMDHelper::Uint64ToConstMD(v, m_Ctx);
  1118. }
  1119. ConstantAsMetadata *DxilMDHelper::Int8ToConstMD(int8_t v) {
  1120. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1121. }
  1122. ConstantAsMetadata *DxilMDHelper::Uint8ToConstMD(uint8_t v) {
  1123. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1124. }
  1125. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v, LLVMContext &Ctx) {
  1126. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 1), APInt(1, v ? 1 : 0)));
  1127. }
  1128. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v) {
  1129. return DxilMDHelper::BoolToConstMD(v, m_Ctx);
  1130. }
  1131. ConstantAsMetadata *DxilMDHelper::FloatToConstMD(float v) {
  1132. return ConstantAsMetadata::get(ConstantFP::get(m_Ctx, APFloat(v)));
  1133. }
  1134. int32_t DxilMDHelper::ConstMDToInt32(const MDOperand &MDO) {
  1135. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1136. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1137. return (int32_t)pConst->getZExtValue();
  1138. }
  1139. unsigned DxilMDHelper::ConstMDToUint32(const MDOperand &MDO) {
  1140. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1141. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1142. return (unsigned)pConst->getZExtValue();
  1143. }
  1144. uint64_t DxilMDHelper::ConstMDToUint64(const MDOperand &MDO) {
  1145. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1146. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1147. return pConst->getZExtValue();
  1148. }
  1149. int8_t DxilMDHelper::ConstMDToInt8(const MDOperand &MDO) {
  1150. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1151. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1152. return (int8_t)pConst->getZExtValue();
  1153. }
  1154. uint8_t DxilMDHelper::ConstMDToUint8(const MDOperand &MDO) {
  1155. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1156. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1157. return (uint8_t)pConst->getZExtValue();
  1158. }
  1159. bool DxilMDHelper::ConstMDToBool(const MDOperand &MDO) {
  1160. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1161. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1162. return pConst->getZExtValue() != 0;
  1163. }
  1164. float DxilMDHelper::ConstMDToFloat(const MDOperand &MDO) {
  1165. ConstantFP *pConst = mdconst::extract<ConstantFP>(MDO);
  1166. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1167. return pConst->getValueAPF().convertToFloat();
  1168. }
  1169. string DxilMDHelper::StringMDToString(const MDOperand &MDO) {
  1170. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  1171. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1172. return pMDString->getString();
  1173. }
  1174. Value *DxilMDHelper::ValueMDToValue(const MDOperand &MDO) {
  1175. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1176. ValueAsMetadata *pValAsMD = dyn_cast<ValueAsMetadata>(MDO.get());
  1177. IFTBOOL(pValAsMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1178. Value *pValue = pValAsMD->getValue();
  1179. IFTBOOL(pValue != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1180. return pValue;
  1181. }
  1182. MDTuple *DxilMDHelper::Uint32VectorToConstMDTuple(const std::vector<unsigned> &Vec) {
  1183. vector<Metadata *> MDVals;
  1184. MDVals.resize(Vec.size());
  1185. for (size_t i = 0; i < Vec.size(); i++) {
  1186. MDVals[i] = Uint32ToConstMD(Vec[i]);
  1187. }
  1188. return MDNode::get(m_Ctx, MDVals);
  1189. }
  1190. void DxilMDHelper::ConstMDTupleToUint32Vector(MDTuple *pTupleMD, std::vector<unsigned> &Vec) {
  1191. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1192. Vec.resize(pTupleMD->getNumOperands());
  1193. for (size_t i = 0; i < pTupleMD->getNumOperands(); i++) {
  1194. Vec[i] = ConstMDToUint32(pTupleMD->getOperand(i));
  1195. }
  1196. }
  1197. } // namespace hlsl