DxilMetadataHelper.cpp 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106
  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/DXIL/DxilMetadataHelper.h"
  11. #include "dxc/DXIL/DxilShaderModel.h"
  12. #include "dxc/DXIL/DxilCBuffer.h"
  13. #include "dxc/DXIL/DxilResource.h"
  14. #include "dxc/DXIL/DxilSampler.h"
  15. #include "dxc/DXIL/DxilSignatureElement.h"
  16. #include "dxc/DXIL/DxilSignature.h"
  17. #include "dxc/DXIL/DxilTypeSystem.h"
  18. #include "dxc/DXIL/DxilFunctionProps.h"
  19. #include "dxc/DXIL/DxilShaderFlags.h"
  20. #include "dxc/DXIL/DxilSubobject.h"
  21. #include "llvm/IR/Constants.h"
  22. #include "llvm/IR/Function.h"
  23. #include "llvm/IR/LLVMContext.h"
  24. #include "llvm/IR/Metadata.h"
  25. #include "llvm/IR/Module.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. #include <array>
  28. #include <algorithm>
  29. #include "dxc/Support/WinIncludes.h"
  30. #include "dxc/Support/WinFunctions.h"
  31. using namespace llvm;
  32. using std::string;
  33. using std::vector;
  34. using std::unique_ptr;
  35. namespace hlsl {
  36. const char DxilMDHelper::kDxilVersionMDName[] = "dx.version";
  37. const char DxilMDHelper::kDxilShaderModelMDName[] = "dx.shaderModel";
  38. const char DxilMDHelper::kDxilEntryPointsMDName[] = "dx.entryPoints";
  39. const char DxilMDHelper::kDxilResourcesMDName[] = "dx.resources";
  40. const char DxilMDHelper::kDxilTypeSystemMDName[] = "dx.typeAnnotations";
  41. const char DxilMDHelper::kDxilTypeSystemHelperVariablePrefix[] = "dx.typevar.";
  42. const char DxilMDHelper::kDxilControlFlowHintMDName[] = "dx.controlflow.hints";
  43. const char DxilMDHelper::kDxilPreciseAttributeMDName[] = "dx.precise";
  44. const char DxilMDHelper::kDxilNonUniformAttributeMDName[] = "dx.nonuniform";
  45. const char DxilMDHelper::kHLDxilResourceAttributeMDName[] = "dx.hl.resource.attribute";
  46. const char DxilMDHelper::kDxilValidatorVersionMDName[] = "dx.valver";
  47. // This named metadata is not valid in final module (should be moved to DxilContainer)
  48. const char DxilMDHelper::kDxilRootSignatureMDName[] = "dx.rootSignature";
  49. const char DxilMDHelper::kDxilIntermediateOptionsMDName[] = "dx.intermediateOptions";
  50. const char DxilMDHelper::kDxilViewIdStateMDName[] = "dx.viewIdState";
  51. const char DxilMDHelper::kDxilSubobjectsMDName[] = "dx.subobjects";
  52. const char DxilMDHelper::kDxilSourceContentsMDName[] = "dx.source.contents";
  53. const char DxilMDHelper::kDxilSourceDefinesMDName[] = "dx.source.defines";
  54. const char DxilMDHelper::kDxilSourceMainFileNameMDName[] = "dx.source.mainFileName";
  55. const char DxilMDHelper::kDxilSourceArgsMDName[] = "dx.source.args";
  56. static std::array<const char *, 7> DxilMDNames = { {
  57. DxilMDHelper::kDxilVersionMDName,
  58. DxilMDHelper::kDxilShaderModelMDName,
  59. DxilMDHelper::kDxilEntryPointsMDName,
  60. DxilMDHelper::kDxilResourcesMDName,
  61. DxilMDHelper::kDxilTypeSystemMDName,
  62. DxilMDHelper::kDxilValidatorVersionMDName,
  63. DxilMDHelper::kDxilViewIdStateMDName,
  64. }};
  65. DxilMDHelper::DxilMDHelper(Module *pModule, std::unique_ptr<ExtraPropertyHelper> EPH)
  66. : m_Ctx(pModule->getContext())
  67. , m_pModule(pModule)
  68. , m_pSM(nullptr)
  69. , m_ExtraPropertyHelper(std::move(EPH)) {
  70. }
  71. DxilMDHelper::~DxilMDHelper() {
  72. }
  73. void DxilMDHelper::SetShaderModel(const ShaderModel *pSM) {
  74. m_pSM = pSM;
  75. }
  76. const ShaderModel *DxilMDHelper::GetShaderModel() const {
  77. return m_pSM;
  78. }
  79. //
  80. // DXIL version.
  81. //
  82. void DxilMDHelper::EmitDxilVersion(unsigned Major, unsigned Minor) {
  83. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  84. IFTBOOL(pDxilVersionMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  85. pDxilVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilVersionMDName);
  86. Metadata *MDVals[kDxilVersionNumFields];
  87. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  88. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  89. pDxilVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  90. }
  91. void DxilMDHelper::LoadDxilVersion(unsigned &Major, unsigned &Minor) {
  92. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  93. IFTBOOL(pDxilVersionMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  94. IFTBOOL(pDxilVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  95. MDNode *pVersionMD = pDxilVersionMD->getOperand(0);
  96. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  97. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  98. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  99. }
  100. //
  101. // Validator version.
  102. //
  103. void DxilMDHelper::EmitValidatorVersion(unsigned Major, unsigned Minor) {
  104. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  105. // Allow re-writing the validator version, since this can be changed at later points.
  106. if (pDxilValidatorVersionMD)
  107. m_pModule->eraseNamedMetadata(pDxilValidatorVersionMD);
  108. pDxilValidatorVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilValidatorVersionMDName);
  109. Metadata *MDVals[kDxilVersionNumFields];
  110. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  111. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  112. pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  113. }
  114. void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
  115. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  116. if (pDxilValidatorVersionMD == nullptr) {
  117. // If no validator version metadata, assume 1.0
  118. Major = 1;
  119. Minor = 0;
  120. return;
  121. }
  122. IFTBOOL(pDxilValidatorVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  123. MDNode *pVersionMD = pDxilValidatorVersionMD->getOperand(0);
  124. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  125. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  126. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  127. }
  128. //
  129. // DXIL shader model.
  130. //
  131. void DxilMDHelper::EmitDxilShaderModel(const ShaderModel *pSM) {
  132. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  133. IFTBOOL(pShaderModelNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  134. pShaderModelNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilShaderModelMDName);
  135. Metadata *MDVals[kDxilShaderModelNumFields];
  136. MDVals[kDxilShaderModelTypeIdx ] = MDString::get(m_Ctx, pSM->GetKindName());
  137. MDVals[kDxilShaderModelMajorIdx] = Uint32ToConstMD(pSM->GetMajor());
  138. MDVals[kDxilShaderModelMinorIdx] = Uint32ToConstMD(pSM->GetMinor());
  139. pShaderModelNamedMD->addOperand(MDNode::get(m_Ctx, MDVals));
  140. }
  141. void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
  142. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  143. IFTBOOL(pShaderModelNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  144. IFTBOOL(pShaderModelNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  145. MDNode *pShaderModelMD = pShaderModelNamedMD->getOperand(0);
  146. IFTBOOL(pShaderModelMD->getNumOperands() == kDxilShaderModelNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  147. MDString *pShaderTypeMD = dyn_cast<MDString>(pShaderModelMD->getOperand(kDxilShaderModelTypeIdx));
  148. IFTBOOL(pShaderTypeMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  149. unsigned Major = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMajorIdx));
  150. unsigned Minor = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMinorIdx));
  151. string ShaderModelName = pShaderTypeMD->getString();
  152. ShaderModelName += "_" + std::to_string(Major) + "_" +
  153. (Minor == ShaderModel::kOfflineMinor ? "x" : std::to_string(Minor));
  154. pSM = ShaderModel::GetByName(ShaderModelName.c_str());
  155. if (!pSM->IsValidForDxil()) {
  156. char ErrorMsgTxt[40];
  157. StringCchPrintfA(ErrorMsgTxt, _countof(ErrorMsgTxt),
  158. "Unknown shader model '%s'", ShaderModelName.c_str());
  159. string ErrorMsg(ErrorMsgTxt);
  160. throw hlsl::Exception(DXC_E_INCORRECT_DXIL_METADATA, ErrorMsg);
  161. }
  162. }
  163. //
  164. // intermediate options.
  165. //
  166. void DxilMDHelper::EmitDxilIntermediateOptions(uint32_t flags) {
  167. if (flags == 0) return;
  168. NamedMDNode *pIntermediateOptionsNamedMD = m_pModule->getNamedMetadata(kDxilIntermediateOptionsMDName);
  169. IFTBOOL(pIntermediateOptionsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  170. pIntermediateOptionsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilIntermediateOptionsMDName);
  171. pIntermediateOptionsNamedMD->addOperand(
  172. MDNode::get(m_Ctx, { Uint32ToConstMD(kDxilIntermediateOptionsFlags), Uint32ToConstMD(flags) }));
  173. }
  174. void DxilMDHelper::LoadDxilIntermediateOptions(uint32_t &flags) {
  175. flags = 0;
  176. NamedMDNode *pIntermediateOptionsNamedMD = m_pModule->getNamedMetadata(kDxilIntermediateOptionsMDName);
  177. if (pIntermediateOptionsNamedMD == nullptr) return;
  178. for (unsigned i = 0; i < pIntermediateOptionsNamedMD->getNumOperands(); i++) {
  179. MDTuple *pEntry = dyn_cast<MDTuple>(pIntermediateOptionsNamedMD->getOperand(i));
  180. IFTBOOL(pEntry != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  181. IFTBOOL(pEntry->getNumOperands() >= 1, DXC_E_INCORRECT_DXIL_METADATA);
  182. uint32_t id = ConstMDToUint32(pEntry->getOperand(0));
  183. switch (id) {
  184. case kDxilIntermediateOptionsFlags:
  185. IFTBOOL(pEntry->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
  186. flags = ConstMDToUint32(pEntry->getOperand(1));
  187. break;
  188. default: throw hlsl::Exception(DXC_E_INCORRECT_DXIL_METADATA, "Unrecognized intermediate options metadata");
  189. }
  190. }
  191. }
  192. //
  193. // Entry points.
  194. //
  195. void DxilMDHelper::EmitDxilEntryPoints(vector<MDNode *> &MDEntries) {
  196. DXASSERT(MDEntries.size() == 1 || GetShaderModel()->IsLib(),
  197. "only one entry point is supported for now");
  198. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  199. IFTBOOL(pEntryPointsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  200. pEntryPointsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilEntryPointsMDName);
  201. for (size_t i = 0; i < MDEntries.size(); i++) {
  202. pEntryPointsNamedMD->addOperand(MDEntries[i]);
  203. }
  204. }
  205. void DxilMDHelper::UpdateDxilEntryPoints(vector<MDNode *> &MDEntries) {
  206. DXASSERT(MDEntries.size() == 1, "only one entry point is supported for now");
  207. NamedMDNode *pEntryPointsNamedMD =
  208. m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  209. IFTBOOL(pEntryPointsNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  210. for (size_t i = 0; i < MDEntries.size(); i++) {
  211. pEntryPointsNamedMD->setOperand(i, MDEntries[i]);
  212. }
  213. }
  214. const NamedMDNode *DxilMDHelper::GetDxilEntryPoints() {
  215. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  216. IFTBOOL(pEntryPointsNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  217. return pEntryPointsNamedMD;
  218. }
  219. MDTuple *DxilMDHelper::EmitDxilEntryPointTuple(Function *pFunc, const string &Name,
  220. MDTuple *pSignatures, MDTuple *pResources,
  221. MDTuple *pProperties) {
  222. Metadata *MDVals[kDxilEntryPointNumFields];
  223. MDVals[kDxilEntryPointFunction ] = pFunc ? ValueAsMetadata::get(pFunc) : nullptr;
  224. MDVals[kDxilEntryPointName ] = MDString::get(m_Ctx, Name.c_str());
  225. MDVals[kDxilEntryPointSignatures] = pSignatures;
  226. MDVals[kDxilEntryPointResources ] = pResources;
  227. MDVals[kDxilEntryPointProperties] = pProperties;
  228. return MDNode::get(m_Ctx, MDVals);
  229. }
  230. void DxilMDHelper::GetDxilEntryPoint(const MDNode *MDO, Function *&pFunc, string &Name,
  231. const MDOperand *&pSignatures, const MDOperand *&pResources,
  232. const MDOperand *&pProperties) {
  233. IFTBOOL(MDO != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  234. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO);
  235. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  236. IFTBOOL(pTupleMD->getNumOperands() == kDxilEntryPointNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  237. // Retrieve entry function symbol.
  238. const MDOperand &MDOFunc = pTupleMD->getOperand(kDxilEntryPointFunction);
  239. if (MDOFunc.get() != nullptr) {
  240. ValueAsMetadata *pValueFunc = dyn_cast<ValueAsMetadata>(MDOFunc.get());
  241. IFTBOOL(pValueFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  242. pFunc = dyn_cast<Function>(pValueFunc->getValue());
  243. IFTBOOL(pFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  244. } else {
  245. pFunc = nullptr; // pass-through CP.
  246. }
  247. // Retrieve entry function name.
  248. const MDOperand &MDOName = pTupleMD->getOperand(kDxilEntryPointName);
  249. IFTBOOL(MDOName.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  250. MDString *pMDName = dyn_cast<MDString>(MDOName);
  251. IFTBOOL(pMDName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  252. Name = pMDName->getString();
  253. pSignatures = &pTupleMD->getOperand(kDxilEntryPointSignatures);
  254. pResources = &pTupleMD->getOperand(kDxilEntryPointResources );
  255. pProperties = &pTupleMD->getOperand(kDxilEntryPointProperties);
  256. }
  257. //
  258. // Signatures.
  259. //
  260. MDTuple *DxilMDHelper::EmitDxilSignatures(const DxilEntrySignature &EntrySig) {
  261. MDTuple *pSignatureTupleMD = nullptr;
  262. const DxilSignature &InputSig = EntrySig.InputSignature;
  263. const DxilSignature &OutputSig = EntrySig.OutputSignature;
  264. const DxilSignature &PCSig = EntrySig.PatchConstantSignature;
  265. if (!InputSig.GetElements().empty() || !OutputSig.GetElements().empty() || !PCSig.GetElements().empty()) {
  266. Metadata *MDVals[kDxilNumSignatureFields];
  267. MDVals[kDxilInputSignature] = EmitSignatureMetadata(InputSig);
  268. MDVals[kDxilOutputSignature] = EmitSignatureMetadata(OutputSig);
  269. MDVals[kDxilPatchConstantSignature] = EmitSignatureMetadata(PCSig);
  270. pSignatureTupleMD = MDNode::get(m_Ctx, MDVals);
  271. }
  272. return pSignatureTupleMD;
  273. }
  274. void DxilMDHelper::EmitRootSignature(
  275. std::vector<uint8_t> &SerializedRootSignature) {
  276. if (SerializedRootSignature.empty()) {
  277. return;
  278. }
  279. Constant *V = llvm::ConstantDataArray::get(
  280. m_Ctx, llvm::ArrayRef<uint8_t>(SerializedRootSignature.data(),
  281. SerializedRootSignature.size()));
  282. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  283. IFTBOOL(pRootSignatureNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  284. pRootSignatureNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilRootSignatureMDName);
  285. pRootSignatureNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  286. return ;
  287. }
  288. void DxilMDHelper::LoadDxilSignatures(const MDOperand &MDO, DxilEntrySignature &EntrySig) {
  289. if (MDO.get() == nullptr)
  290. return;
  291. DxilSignature &InputSig = EntrySig.InputSignature;
  292. DxilSignature &OutputSig = EntrySig.OutputSignature;
  293. DxilSignature &PCSig = EntrySig.PatchConstantSignature;
  294. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  295. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  296. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumSignatureFields, DXC_E_INCORRECT_DXIL_METADATA);
  297. LoadSignatureMetadata(pTupleMD->getOperand(kDxilInputSignature), InputSig);
  298. LoadSignatureMetadata(pTupleMD->getOperand(kDxilOutputSignature), OutputSig);
  299. LoadSignatureMetadata(pTupleMD->getOperand(kDxilPatchConstantSignature), PCSig);
  300. }
  301. MDTuple *DxilMDHelper::EmitSignatureMetadata(const DxilSignature &Sig) {
  302. auto &Elements = Sig.GetElements();
  303. if (Elements.empty())
  304. return nullptr;
  305. vector<Metadata *> MDVals;
  306. for (size_t i = 0; i < Elements.size(); i++) {
  307. MDVals.emplace_back(EmitSignatureElement(*Elements[i]));
  308. }
  309. return MDNode::get(m_Ctx, MDVals);
  310. }
  311. void DxilMDHelper::LoadSignatureMetadata(const MDOperand &MDO, DxilSignature &Sig) {
  312. if (MDO.get() == nullptr)
  313. return;
  314. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  315. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  316. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i++) {
  317. unique_ptr<DxilSignatureElement> pSE(Sig.CreateElement());
  318. LoadSignatureElement(pTupleMD->getOperand(i), *pSE.get());
  319. Sig.AppendElement(std::move(pSE));
  320. }
  321. }
  322. void DxilMDHelper::LoadRootSignature(std::vector<uint8_t> &SerializedRootSignature) {
  323. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  324. if(!pRootSignatureNamedMD)
  325. return;
  326. IFTBOOL(pRootSignatureNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  327. MDNode *pNode = pRootSignatureNamedMD->getOperand(0);
  328. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  329. const MDOperand &MDO = pNode->getOperand(0);
  330. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  331. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  332. const ConstantDataArray *pData =
  333. dyn_cast<ConstantDataArray>(pMetaData->getValue());
  334. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  335. IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx),
  336. DXC_E_INCORRECT_DXIL_METADATA);
  337. SerializedRootSignature.clear();
  338. unsigned size = pData->getRawDataValues().size();
  339. SerializedRootSignature.resize(size);
  340. memcpy(SerializedRootSignature.data(),
  341. (const uint8_t *)pData->getRawDataValues().begin(), size);
  342. }
  343. static const MDTuple *CastToTupleOrNull(const MDOperand &MDO) {
  344. if (MDO.get() == nullptr)
  345. return nullptr;
  346. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  347. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  348. return pTupleMD;
  349. }
  350. MDTuple *DxilMDHelper::EmitSignatureElement(const DxilSignatureElement &SE) {
  351. Metadata *MDVals[kDxilSignatureElementNumFields];
  352. MDVals[kDxilSignatureElementID ] = Uint32ToConstMD(SE.GetID());
  353. MDVals[kDxilSignatureElementName ] = MDString::get(m_Ctx, SE.GetName());
  354. MDVals[kDxilSignatureElementType ] = Uint8ToConstMD((uint8_t)SE.GetCompType().GetKind());
  355. MDVals[kDxilSignatureElementSystemValue ] = Uint8ToConstMD((uint8_t)SE.GetKind());
  356. MDVals[kDxilSignatureElementIndexVector ] = Uint32VectorToConstMDTuple(SE.GetSemanticIndexVec());
  357. MDVals[kDxilSignatureElementInterpMode ] = Uint8ToConstMD((uint8_t)SE.GetInterpolationMode()->GetKind());
  358. MDVals[kDxilSignatureElementRows ] = Uint32ToConstMD(SE.GetRows());
  359. MDVals[kDxilSignatureElementCols ] = Uint8ToConstMD((uint8_t)SE.GetCols());
  360. MDVals[kDxilSignatureElementStartRow ] = Int32ToConstMD(SE.GetStartRow());
  361. MDVals[kDxilSignatureElementStartCol ] = Int8ToConstMD((int8_t)SE.GetStartCol());
  362. // Name-value list of extended properties.
  363. MDVals[kDxilSignatureElementNameValueList] = nullptr;
  364. vector<Metadata *> MDExtraVals;
  365. m_ExtraPropertyHelper->EmitSignatureElementProperties(SE, MDExtraVals);
  366. if (!MDExtraVals.empty()) {
  367. MDVals[kDxilSignatureElementNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  368. }
  369. // NOTE: when extra properties for signature elements are needed, extend ExtraPropertyHelper.
  370. return MDNode::get(m_Ctx, MDVals);
  371. }
  372. void DxilMDHelper::LoadSignatureElement(const MDOperand &MDO, DxilSignatureElement &SE) {
  373. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  374. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  375. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  376. IFTBOOL(pTupleMD->getNumOperands() == kDxilSignatureElementNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  377. unsigned ID = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementID));
  378. MDString *pName = dyn_cast<MDString>( pTupleMD->getOperand(kDxilSignatureElementName));
  379. CompType CT = CompType(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementType)));
  380. DXIL::SemanticKind SemKind =
  381. (DXIL::SemanticKind)ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementSystemValue));
  382. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(kDxilSignatureElementIndexVector));
  383. InterpolationMode IM(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementInterpMode)));
  384. unsigned NumRows = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementRows));
  385. uint8_t NumCols = ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementCols));
  386. int32_t StartRow = ConstMDToInt32( pTupleMD->getOperand(kDxilSignatureElementStartRow));
  387. int8_t StartCol = ConstMDToInt8( pTupleMD->getOperand(kDxilSignatureElementStartCol));
  388. IFTBOOL(pName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  389. IFTBOOL(pSemanticIndexVectorMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  390. vector<unsigned> SemanticIndexVector;
  391. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  392. SE.Initialize(pName->getString(), CT, IM, NumRows, NumCols, StartRow, StartCol, ID, SemanticIndexVector);
  393. SE.SetKind(SemKind);
  394. // For case a system semantic don't have index, add 0 for it.
  395. if (SemanticIndexVector.empty() && !SE.IsArbitrary()) {
  396. SE.SetSemanticIndexVec({0});
  397. }
  398. // Name-value list of extended properties.
  399. m_ExtraPropertyHelper->LoadSignatureElementProperties(pTupleMD->getOperand(kDxilSignatureElementNameValueList), SE);
  400. }
  401. //
  402. // Resources.
  403. //
  404. MDTuple *DxilMDHelper::EmitDxilResourceTuple(MDTuple *pSRVs, MDTuple *pUAVs,
  405. MDTuple *pCBuffers, MDTuple *pSamplers) {
  406. DXASSERT(pSRVs != nullptr || pUAVs != nullptr || pCBuffers != nullptr || pSamplers != nullptr, "resource tuple should not be emitted if there are no resources");
  407. Metadata *MDVals[kDxilNumResourceFields];
  408. MDVals[kDxilResourceSRVs ] = pSRVs;
  409. MDVals[kDxilResourceUAVs ] = pUAVs;
  410. MDVals[kDxilResourceCBuffers] = pCBuffers;
  411. MDVals[kDxilResourceSamplers] = pSamplers;
  412. MDTuple *pTupleMD = MDNode::get(m_Ctx, MDVals);
  413. return pTupleMD;
  414. }
  415. void DxilMDHelper::EmitDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  416. NamedMDNode *pResourcesNamedMD = m_pModule->getNamedMetadata(kDxilResourcesMDName);
  417. IFTBOOL(pResourcesNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  418. pResourcesNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  419. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  420. }
  421. void DxilMDHelper::UpdateDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  422. NamedMDNode *pResourcesNamedMD =
  423. m_pModule->getNamedMetadata(kDxilResourcesMDName);
  424. if (!pResourcesNamedMD) {
  425. pResourcesNamedMD =
  426. m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  427. }
  428. if (pDxilResourceTuple) {
  429. if (pResourcesNamedMD->getNumOperands() != 0) {
  430. pResourcesNamedMD->setOperand(0, pDxilResourceTuple);
  431. }
  432. else {
  433. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  434. }
  435. } else {
  436. m_pModule->eraseNamedMetadata(pResourcesNamedMD);
  437. }
  438. }
  439. void DxilMDHelper::GetDxilResources(const MDOperand &MDO, const MDTuple *&pSRVs,
  440. const MDTuple *&pUAVs, const MDTuple *&pCBuffers,
  441. const MDTuple *&pSamplers) {
  442. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  443. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  444. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  445. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumResourceFields, DXC_E_INCORRECT_DXIL_METADATA);
  446. pSRVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSRVs ));
  447. pUAVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceUAVs ));
  448. pCBuffers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceCBuffers));
  449. pSamplers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSamplers));
  450. }
  451. void DxilMDHelper::EmitDxilResourceBase(const DxilResourceBase &R, Metadata *ppMDVals[]) {
  452. ppMDVals[kDxilResourceBaseID ] = Uint32ToConstMD(R.GetID());
  453. ppMDVals[kDxilResourceBaseVariable ] = ValueAsMetadata::get(R.GetGlobalSymbol());
  454. ppMDVals[kDxilResourceBaseName ] = MDString::get(m_Ctx, R.GetGlobalName());
  455. ppMDVals[kDxilResourceBaseSpaceID ] = Uint32ToConstMD(R.GetSpaceID());
  456. ppMDVals[kDxilResourceBaseLowerBound] = Uint32ToConstMD(R.GetLowerBound());
  457. ppMDVals[kDxilResourceBaseRangeSize ] = Uint32ToConstMD(R.GetRangeSize());
  458. }
  459. void DxilMDHelper::LoadDxilResourceBase(const MDOperand &MDO, DxilResourceBase &R) {
  460. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  461. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  462. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  463. IFTBOOL(pTupleMD->getNumOperands() >= kDxilResourceBaseNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  464. R.SetID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseID)));
  465. R.SetGlobalSymbol(dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilResourceBaseVariable))));
  466. R.SetGlobalName(StringMDToString(pTupleMD->getOperand(kDxilResourceBaseName)));
  467. R.SetSpaceID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseSpaceID)));
  468. R.SetLowerBound(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseLowerBound)));
  469. R.SetRangeSize(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseRangeSize)));
  470. }
  471. MDTuple *DxilMDHelper::EmitDxilSRV(const DxilResource &SRV) {
  472. Metadata *MDVals[kDxilSRVNumFields];
  473. EmitDxilResourceBase(SRV, &MDVals[0]);
  474. // SRV-specific fields.
  475. MDVals[kDxilSRVShape ] = Uint32ToConstMD((unsigned)SRV.GetKind());
  476. MDVals[kDxilSRVSampleCount ] = Uint32ToConstMD(SRV.GetSampleCount());
  477. // Name-value list of extended properties.
  478. MDVals[kDxilSRVNameValueList] = nullptr;
  479. vector<Metadata *> MDExtraVals;
  480. m_ExtraPropertyHelper->EmitSRVProperties(SRV, MDExtraVals);
  481. if (!MDExtraVals.empty()) {
  482. MDVals[kDxilSRVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  483. }
  484. return MDNode::get(m_Ctx, MDVals);
  485. }
  486. void DxilMDHelper::LoadDxilSRV(const MDOperand &MDO, DxilResource &SRV) {
  487. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  488. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  489. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  490. IFTBOOL(pTupleMD->getNumOperands() == kDxilSRVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  491. SRV.SetRW(false);
  492. LoadDxilResourceBase(MDO, SRV);
  493. // SRV-specific fields.
  494. SRV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilSRVShape)));
  495. SRV.SetSampleCount(ConstMDToUint32(pTupleMD->getOperand(kDxilSRVSampleCount)));
  496. // Name-value list of extended properties.
  497. m_ExtraPropertyHelper->LoadSRVProperties(pTupleMD->getOperand(kDxilSRVNameValueList), SRV);
  498. }
  499. MDTuple *DxilMDHelper::EmitDxilUAV(const DxilResource &UAV) {
  500. Metadata *MDVals[kDxilUAVNumFields];
  501. EmitDxilResourceBase(UAV, &MDVals[0]);
  502. // UAV-specific fields.
  503. MDVals[kDxilUAVShape ] = Uint32ToConstMD((unsigned)UAV.GetKind());
  504. MDVals[kDxilUAVGloballyCoherent ] = BoolToConstMD(UAV.IsGloballyCoherent());
  505. MDVals[kDxilUAVCounter ] = BoolToConstMD(UAV.HasCounter());
  506. MDVals[kDxilUAVRasterizerOrderedView] = BoolToConstMD(UAV.IsROV());
  507. // Name-value list of extended properties.
  508. MDVals[kDxilUAVNameValueList ] = nullptr;
  509. vector<Metadata *> MDExtraVals;
  510. m_ExtraPropertyHelper->EmitUAVProperties(UAV, MDExtraVals);
  511. if (!MDExtraVals.empty()) {
  512. MDVals[kDxilUAVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  513. }
  514. return MDNode::get(m_Ctx, MDVals);
  515. }
  516. void DxilMDHelper::LoadDxilUAV(const MDOperand &MDO, DxilResource &UAV) {
  517. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  518. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  519. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  520. IFTBOOL(pTupleMD->getNumOperands() == kDxilUAVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  521. UAV.SetRW(true);
  522. LoadDxilResourceBase(MDO, UAV);
  523. // UAV-specific fields.
  524. UAV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilUAVShape)));
  525. UAV.SetGloballyCoherent(ConstMDToBool(pTupleMD->getOperand(kDxilUAVGloballyCoherent)));
  526. UAV.SetHasCounter(ConstMDToBool(pTupleMD->getOperand(kDxilUAVCounter)));
  527. UAV.SetROV(ConstMDToBool(pTupleMD->getOperand(kDxilUAVRasterizerOrderedView)));
  528. // Name-value list of extended properties.
  529. m_ExtraPropertyHelper->LoadUAVProperties(pTupleMD->getOperand(kDxilUAVNameValueList), UAV);
  530. }
  531. MDTuple *DxilMDHelper::EmitDxilCBuffer(const DxilCBuffer &CB) {
  532. Metadata *MDVals[kDxilCBufferNumFields];
  533. EmitDxilResourceBase(CB, &MDVals[0]);
  534. // CBuffer-specific fields.
  535. // CBuffer size in bytes.
  536. MDVals[kDxilCBufferSizeInBytes ] = Uint32ToConstMD(CB.GetSize());
  537. // Name-value list of extended properties.
  538. MDVals[kDxilCBufferNameValueList] = nullptr;
  539. vector<Metadata *> MDExtraVals;
  540. m_ExtraPropertyHelper->EmitCBufferProperties(CB, MDExtraVals);
  541. if (!MDExtraVals.empty()) {
  542. MDVals[kDxilCBufferNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  543. }
  544. return MDNode::get(m_Ctx, MDVals);
  545. }
  546. void DxilMDHelper::LoadDxilCBuffer(const MDOperand &MDO, DxilCBuffer &CB) {
  547. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  548. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  549. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  550. IFTBOOL(pTupleMD->getNumOperands() == kDxilCBufferNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  551. LoadDxilResourceBase(MDO, CB);
  552. // CBuffer-specific fields.
  553. CB.SetSize(ConstMDToUint32(pTupleMD->getOperand(kDxilCBufferSizeInBytes)));
  554. // Name-value list of extended properties.
  555. m_ExtraPropertyHelper->LoadCBufferProperties(pTupleMD->getOperand(kDxilCBufferNameValueList), CB);
  556. }
  557. void DxilMDHelper::EmitDxilTypeSystem(DxilTypeSystem &TypeSystem, vector<GlobalVariable*> &LLVMUsed) {
  558. auto &TypeMap = TypeSystem.GetStructAnnotationMap();
  559. vector<Metadata *> MDVals;
  560. MDVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemStructTag)); // Tag
  561. unsigned GVIdx = 0;
  562. for (auto it = TypeMap.begin(); it != TypeMap.end(); ++it, GVIdx++) {
  563. StructType *pStructType = const_cast<StructType *>(it->first);
  564. DxilStructAnnotation *pA = it->second.get();
  565. // Don't emit type annotation for empty struct.
  566. if (pA->IsEmptyStruct())
  567. continue;
  568. // Emit struct type field annotations.
  569. Metadata *pMD = EmitDxilStructAnnotation(*pA);
  570. MDVals.push_back(ValueAsMetadata::get(UndefValue::get(pStructType)));
  571. MDVals.push_back(pMD);
  572. }
  573. auto &FuncMap = TypeSystem.GetFunctionAnnotationMap();
  574. vector<Metadata *> MDFuncVals;
  575. MDFuncVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemFunctionTag)); // Tag
  576. for (auto it = FuncMap.begin(); it != FuncMap.end(); ++it) {
  577. DxilFunctionAnnotation *pA = it->second.get();
  578. MDFuncVals.push_back(ValueAsMetadata::get(const_cast<Function*>(pA->GetFunction())));
  579. // Emit function annotations.
  580. Metadata *pMD;
  581. pMD = EmitDxilFunctionAnnotation(*pA);
  582. MDFuncVals.push_back(pMD);
  583. }
  584. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  585. if (pDxilTypeAnnotationsMD != nullptr) {
  586. m_pModule->eraseNamedMetadata(pDxilTypeAnnotationsMD);
  587. }
  588. if (MDVals.size() > 1) {
  589. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  590. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDVals));
  591. }
  592. if (MDFuncVals.size() > 1) {
  593. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  594. if (pDxilTypeAnnotationsMD == nullptr)
  595. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  596. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDFuncVals));
  597. }
  598. }
  599. void DxilMDHelper::LoadDxilTypeSystemNode(const llvm::MDTuple &MDT,
  600. DxilTypeSystem &TypeSystem) {
  601. unsigned Tag = ConstMDToUint32(MDT.getOperand(0));
  602. if (Tag == kDxilTypeSystemStructTag) {
  603. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  604. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  605. Constant *pGV =
  606. dyn_cast<Constant>(ValueMDToValue(MDT.getOperand(i)));
  607. IFTBOOL(pGV != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  608. StructType *pGVType =
  609. dyn_cast<StructType>(pGV->getType());
  610. IFTBOOL(pGVType != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  611. DxilStructAnnotation *pSA = TypeSystem.AddStructAnnotation(pGVType);
  612. LoadDxilStructAnnotation(MDT.getOperand(i + 1), *pSA);
  613. }
  614. } else {
  615. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  616. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  617. Function *F = dyn_cast<Function>(ValueMDToValue(MDT.getOperand(i)));
  618. DxilFunctionAnnotation *pFA = TypeSystem.AddFunctionAnnotation(F);
  619. LoadDxilFunctionAnnotation(MDT.getOperand(i + 1), *pFA);
  620. }
  621. }
  622. }
  623. void DxilMDHelper::LoadDxilTypeSystem(DxilTypeSystem &TypeSystem) {
  624. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  625. if (pDxilTypeAnnotationsMD == nullptr)
  626. return;
  627. IFTBOOL(pDxilTypeAnnotationsMD->getNumOperands() <= 2, DXC_E_INCORRECT_DXIL_METADATA);
  628. for (unsigned i = 0; i < pDxilTypeAnnotationsMD->getNumOperands(); i++) {
  629. const MDTuple *pTupleMD = dyn_cast<MDTuple>(pDxilTypeAnnotationsMD->getOperand(i));
  630. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  631. LoadDxilTypeSystemNode(*pTupleMD, TypeSystem);
  632. }
  633. }
  634. Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
  635. vector<Metadata *> MDVals(SA.GetNumFields() + 1);
  636. MDVals[0] = Uint32ToConstMD(SA.GetCBufferSize());
  637. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  638. MDVals[i+1] = EmitDxilFieldAnnotation(SA.GetFieldAnnotation(i));
  639. }
  640. return MDNode::get(m_Ctx, MDVals);
  641. }
  642. void DxilMDHelper::LoadDxilStructAnnotation(const MDOperand &MDO, DxilStructAnnotation &SA) {
  643. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  644. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  645. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  646. if (pTupleMD->getNumOperands() == 1) {
  647. SA.MarkEmptyStruct();
  648. }
  649. IFTBOOL(pTupleMD->getNumOperands() == SA.GetNumFields()+1, DXC_E_INCORRECT_DXIL_METADATA);
  650. SA.SetCBufferSize(ConstMDToUint32(pTupleMD->getOperand(0)));
  651. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  652. const MDOperand &MDO = pTupleMD->getOperand(i+1);
  653. DxilFieldAnnotation &FA = SA.GetFieldAnnotation(i);
  654. LoadDxilFieldAnnotation(MDO, FA);
  655. }
  656. }
  657. Metadata *
  658. DxilMDHelper::EmitDxilFunctionAnnotation(const DxilFunctionAnnotation &FA) {
  659. return EmitDxilParamAnnotations(FA);
  660. }
  661. void DxilMDHelper::LoadDxilFunctionAnnotation(const MDOperand &MDO,
  662. DxilFunctionAnnotation &FA) {
  663. LoadDxilParamAnnotations(MDO, FA);
  664. }
  665. llvm::Metadata *
  666. DxilMDHelper::EmitDxilParamAnnotations(const DxilFunctionAnnotation &FA) {
  667. vector<Metadata *> MDParamAnnotations(FA.GetNumParameters() + 1);
  668. MDParamAnnotations[0] = EmitDxilParamAnnotation(FA.GetRetTypeAnnotation());
  669. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  670. MDParamAnnotations[i + 1] =
  671. EmitDxilParamAnnotation(FA.GetParameterAnnotation(i));
  672. }
  673. return MDNode::get(m_Ctx, MDParamAnnotations);
  674. }
  675. void DxilMDHelper::LoadDxilParamAnnotations(const llvm::MDOperand &MDO,
  676. DxilFunctionAnnotation &FA) {
  677. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  678. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  679. IFTBOOL(pTupleMD->getNumOperands() == FA.GetNumParameters() + 1,
  680. DXC_E_INCORRECT_DXIL_METADATA);
  681. DxilParameterAnnotation &retTyAnnotation = FA.GetRetTypeAnnotation();
  682. LoadDxilParamAnnotation(pTupleMD->getOperand(0), retTyAnnotation);
  683. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  684. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  685. DxilParameterAnnotation &PA = FA.GetParameterAnnotation(i);
  686. LoadDxilParamAnnotation(MDO, PA);
  687. }
  688. }
  689. Metadata *
  690. DxilMDHelper::EmitDxilParamAnnotation(const DxilParameterAnnotation &PA) {
  691. vector<Metadata *> MDVals(3);
  692. MDVals[0] = Uint32ToConstMD(static_cast<unsigned>(PA.GetParamInputQual()));
  693. MDVals[1] = EmitDxilFieldAnnotation(PA);
  694. MDVals[2] = Uint32VectorToConstMDTuple(PA.GetSemanticIndexVec());
  695. return MDNode::get(m_Ctx, MDVals);
  696. }
  697. void DxilMDHelper::LoadDxilParamAnnotation(const MDOperand &MDO,
  698. DxilParameterAnnotation &PA) {
  699. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  700. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  701. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  702. IFTBOOL(pTupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  703. PA.SetParamInputQual(static_cast<DxilParamInputQual>(
  704. ConstMDToUint32(pTupleMD->getOperand(0))));
  705. LoadDxilFieldAnnotation(pTupleMD->getOperand(1), PA);
  706. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(2));
  707. vector<unsigned> SemanticIndexVector;
  708. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  709. PA.SetSemanticIndexVec(SemanticIndexVector);
  710. }
  711. Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
  712. vector<Metadata *> MDVals; // Tag-Value list.
  713. if (FA.HasFieldName()) {
  714. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationFieldNameTag));
  715. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetFieldName()));
  716. }
  717. if (FA.IsPrecise()) {
  718. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationPreciseTag)); // Tag
  719. MDVals.emplace_back(BoolToConstMD(true)); // Value
  720. }
  721. if (FA.HasMatrixAnnotation()) {
  722. const DxilMatrixAnnotation &MA = FA.GetMatrixAnnotation();
  723. Metadata *MatrixMD[3];
  724. MatrixMD[0] = Uint32ToConstMD(MA.Rows);
  725. MatrixMD[1] = Uint32ToConstMD(MA.Cols);
  726. MatrixMD[2] = Uint32ToConstMD((unsigned)MA.Orientation);
  727. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationMatrixTag));
  728. MDVals.emplace_back(MDNode::get(m_Ctx, MatrixMD));
  729. }
  730. if (FA.HasCBufferOffset()) {
  731. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBufferOffsetTag));
  732. MDVals.emplace_back(Uint32ToConstMD(FA.GetCBufferOffset()));
  733. }
  734. if (FA.HasSemanticString()) {
  735. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationSemanticStringTag));
  736. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetSemanticString()));
  737. }
  738. if (FA.HasInterpolationMode()) {
  739. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationInterpolationModeTag));
  740. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetInterpolationMode().GetKind()));
  741. }
  742. if (FA.HasCompType()) {
  743. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
  744. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
  745. }
  746. return MDNode::get(m_Ctx, MDVals);
  747. }
  748. void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnotation &FA) {
  749. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  750. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  751. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  752. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  753. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  754. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(i));
  755. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  756. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  757. switch (Tag) {
  758. case kDxilFieldAnnotationPreciseTag:
  759. FA.SetPrecise(ConstMDToBool(MDO));
  760. break;
  761. case kDxilFieldAnnotationMatrixTag: {
  762. DxilMatrixAnnotation MA;
  763. const MDTuple *pMATupleMD = dyn_cast<MDTuple>(MDO.get());
  764. IFTBOOL(pMATupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  765. IFTBOOL(pMATupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  766. MA.Rows = ConstMDToUint32(pMATupleMD->getOperand(0));
  767. MA.Cols = ConstMDToUint32(pMATupleMD->getOperand(1));
  768. MA.Orientation = (MatrixOrientation)ConstMDToUint32(pMATupleMD->getOperand(2));
  769. FA.SetMatrixAnnotation(MA);
  770. } break;
  771. case kDxilFieldAnnotationCBufferOffsetTag:
  772. FA.SetCBufferOffset(ConstMDToUint32(MDO));
  773. break;
  774. case kDxilFieldAnnotationSemanticStringTag:
  775. FA.SetSemanticString(StringMDToString(MDO));
  776. break;
  777. case kDxilFieldAnnotationInterpolationModeTag:
  778. FA.SetInterpolationMode(InterpolationMode((InterpolationMode::Kind)ConstMDToUint32(MDO)));
  779. break;
  780. case kDxilFieldAnnotationFieldNameTag:
  781. FA.SetFieldName(StringMDToString(MDO));
  782. break;
  783. case kDxilFieldAnnotationCompTypeTag:
  784. FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
  785. break;
  786. default:
  787. // TODO: I don't think we should be failing unrecognized extended tags.
  788. // Perhaps we can flag this case in the module and fail validation
  789. // if flagged.
  790. // That way, an existing loader will not fail on an additional tag
  791. // and the blob would not be signed if the extra tag was not legal.
  792. IFTBOOL(false, DXC_E_INCORRECT_DXIL_METADATA);
  793. }
  794. }
  795. }
  796. const Function *DxilMDHelper::LoadDxilFunctionProps(const MDTuple *pProps,
  797. hlsl::DxilFunctionProps *props) {
  798. unsigned idx = 0;
  799. const Function *F = dyn_cast<Function>(
  800. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  801. DXIL::ShaderKind shaderKind =
  802. static_cast<DXIL::ShaderKind>(ConstMDToUint32(pProps->getOperand(idx++)));
  803. bool bRayAttributes = false;
  804. props->shaderKind = shaderKind;
  805. switch (shaderKind) {
  806. case DXIL::ShaderKind::Compute:
  807. props->ShaderProps.CS.numThreads[0] =
  808. ConstMDToUint32(pProps->getOperand(idx++));
  809. props->ShaderProps.CS.numThreads[1] =
  810. ConstMDToUint32(pProps->getOperand(idx++));
  811. props->ShaderProps.CS.numThreads[2] =
  812. ConstMDToUint32(pProps->getOperand(idx++));
  813. break;
  814. case DXIL::ShaderKind::Geometry:
  815. props->ShaderProps.GS.inputPrimitive =
  816. (DXIL::InputPrimitive)ConstMDToUint32(pProps->getOperand(idx++));
  817. props->ShaderProps.GS.maxVertexCount =
  818. ConstMDToUint32(pProps->getOperand(idx++));
  819. props->ShaderProps.GS.instanceCount =
  820. ConstMDToUint32(pProps->getOperand(idx++));
  821. for (size_t i = 0;
  822. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  823. props->ShaderProps.GS.streamPrimitiveTopologies[i] =
  824. (DXIL::PrimitiveTopology)ConstMDToUint32(pProps->getOperand(idx++));
  825. break;
  826. case DXIL::ShaderKind::Hull:
  827. props->ShaderProps.HS.patchConstantFunc = dyn_cast<Function>(
  828. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  829. props->ShaderProps.HS.domain =
  830. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  831. props->ShaderProps.HS.partition =
  832. (DXIL::TessellatorPartitioning)ConstMDToUint32(
  833. pProps->getOperand(idx++));
  834. props->ShaderProps.HS.outputPrimitive =
  835. (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(
  836. pProps->getOperand(idx++));
  837. props->ShaderProps.HS.inputControlPoints =
  838. ConstMDToUint32(pProps->getOperand(idx++));
  839. props->ShaderProps.HS.outputControlPoints =
  840. ConstMDToUint32(pProps->getOperand(idx++));
  841. props->ShaderProps.HS.maxTessFactor =
  842. ConstMDToFloat(pProps->getOperand(idx++));
  843. break;
  844. case DXIL::ShaderKind::Domain:
  845. props->ShaderProps.DS.domain =
  846. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  847. props->ShaderProps.DS.inputControlPoints =
  848. ConstMDToUint32(pProps->getOperand(idx++));
  849. break;
  850. case DXIL::ShaderKind::Pixel:
  851. props->ShaderProps.PS.EarlyDepthStencil =
  852. ConstMDToUint32(pProps->getOperand(idx++));
  853. break;
  854. case DXIL::ShaderKind::AnyHit:
  855. case DXIL::ShaderKind::ClosestHit:
  856. bRayAttributes = true;
  857. case DXIL::ShaderKind::Miss:
  858. case DXIL::ShaderKind::Callable:
  859. // payload/params unioned and first:
  860. props->ShaderProps.Ray.payloadSizeInBytes =
  861. ConstMDToUint32(pProps->getOperand(idx++));
  862. if (bRayAttributes)
  863. props->ShaderProps.Ray.attributeSizeInBytes =
  864. ConstMDToUint32(pProps->getOperand(idx++));
  865. break;
  866. default:
  867. break;
  868. }
  869. return F;
  870. }
  871. MDTuple *DxilMDHelper::EmitDxilEntryProperties(uint64_t rawShaderFlag,
  872. const DxilFunctionProps &props,
  873. unsigned autoBindingSpace) {
  874. vector<Metadata *> MDVals;
  875. // DXIL shader flags.
  876. if (props.IsPS()) {
  877. if (props.ShaderProps.PS.EarlyDepthStencil) {
  878. ShaderFlags flags;
  879. flags.SetShaderFlagsRaw(rawShaderFlag);
  880. flags.SetForceEarlyDepthStencil(true);
  881. rawShaderFlag = flags.GetShaderFlagsRaw();
  882. }
  883. }
  884. if (rawShaderFlag != 0) {
  885. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderFlagsTag));
  886. MDVals.emplace_back(Uint64ToConstMD(rawShaderFlag));
  887. }
  888. // Add shader kind for lib entrys.
  889. if (m_pSM->IsLib() && props.shaderKind != DXIL::ShaderKind::Library) {
  890. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderKindTag));
  891. MDVals.emplace_back(
  892. Uint32ToConstMD(static_cast<unsigned>(props.shaderKind)));
  893. }
  894. switch (props.shaderKind) {
  895. // Compute shader.
  896. case DXIL::ShaderKind::Compute: {
  897. auto &CS = props.ShaderProps.CS;
  898. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  899. vector<Metadata *> NumThreadVals;
  900. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[0]));
  901. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[1]));
  902. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[2]));
  903. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  904. } break;
  905. // Geometry shader.
  906. case DXIL::ShaderKind::Geometry: {
  907. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  908. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  909. unsigned activeStreamMask = 0;
  910. for (size_t i = 0;
  911. i < _countof(props.ShaderProps.GS.streamPrimitiveTopologies); ++i) {
  912. if (props.ShaderProps.GS.streamPrimitiveTopologies[i] !=
  913. DXIL::PrimitiveTopology::Undefined) {
  914. activeStreamMask |= 1 << i;
  915. DXASSERT_NOMSG(topo == DXIL::PrimitiveTopology::Undefined ||
  916. topo ==
  917. props.ShaderProps.GS.streamPrimitiveTopologies[i]);
  918. topo = props.ShaderProps.GS.streamPrimitiveTopologies[i];
  919. }
  920. }
  921. MDTuple *pMDTuple =
  922. EmitDxilGSState(props.ShaderProps.GS.inputPrimitive,
  923. props.ShaderProps.GS.maxVertexCount, activeStreamMask,
  924. topo, props.ShaderProps.GS.instanceCount);
  925. MDVals.emplace_back(pMDTuple);
  926. } break;
  927. // Domain shader.
  928. case DXIL::ShaderKind::Domain: {
  929. auto &DS = props.ShaderProps.DS;
  930. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  931. MDTuple *pMDTuple = EmitDxilDSState(DS.domain, DS.inputControlPoints);
  932. MDVals.emplace_back(pMDTuple);
  933. } break;
  934. // Hull shader.
  935. case DXIL::ShaderKind::Hull: {
  936. auto &HS = props.ShaderProps.HS;
  937. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  938. MDTuple *pMDTuple = EmitDxilHSState(
  939. HS.patchConstantFunc, HS.inputControlPoints, HS.outputControlPoints,
  940. HS.domain, HS.partition, HS.outputPrimitive, HS.maxTessFactor);
  941. MDVals.emplace_back(pMDTuple);
  942. } break;
  943. // Raytracing.
  944. case DXIL::ShaderKind::AnyHit:
  945. case DXIL::ShaderKind::ClosestHit: {
  946. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  947. MDVals.emplace_back(
  948. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  949. MDVals.emplace_back(Uint32ToConstMD(kDxilRayAttribSizeTag));
  950. MDVals.emplace_back(
  951. Uint32ToConstMD(props.ShaderProps.Ray.attributeSizeInBytes));
  952. } break;
  953. case DXIL::ShaderKind::Miss:
  954. case DXIL::ShaderKind::Callable: {
  955. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  956. MDVals.emplace_back(
  957. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  958. } break;
  959. default:
  960. break;
  961. }
  962. if (autoBindingSpace != UINT_MAX && m_pSM->IsSMAtLeast(6, 3)) {
  963. MDVals.emplace_back(Uint32ToConstMD(kDxilAutoBindingSpaceTag));
  964. MDVals.emplace_back(
  965. MDNode::get(m_Ctx, {Uint32ToConstMD(autoBindingSpace)}));
  966. }
  967. if (!MDVals.empty())
  968. return MDNode::get(m_Ctx, MDVals);
  969. else
  970. return nullptr;
  971. }
  972. void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO,
  973. uint64_t &rawShaderFlag,
  974. DxilFunctionProps &props,
  975. uint32_t &autoBindingSpace) {
  976. if (MDO.get() == nullptr)
  977. return;
  978. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  979. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  980. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0,
  981. DXC_E_INCORRECT_DXIL_METADATA);
  982. bool bEarlyDepth = false;
  983. if (!m_pSM->IsLib()) {
  984. props.shaderKind = m_pSM->GetKind();
  985. } else {
  986. props.shaderKind = DXIL::ShaderKind::Library;
  987. }
  988. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  989. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  990. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  991. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  992. switch (Tag) {
  993. case DxilMDHelper::kDxilShaderFlagsTag: {
  994. rawShaderFlag = ConstMDToUint64(MDO);
  995. ShaderFlags flags;
  996. flags.SetShaderFlagsRaw(rawShaderFlag);
  997. bEarlyDepth = flags.GetForceEarlyDepthStencil();
  998. } break;
  999. case DxilMDHelper::kDxilNumThreadsTag: {
  1000. DXASSERT(props.IsCS(), "else invalid shader kind");
  1001. auto &CS = props.ShaderProps.CS;
  1002. MDNode *pNode = cast<MDNode>(MDO.get());
  1003. CS.numThreads[0] = ConstMDToUint32(pNode->getOperand(0));
  1004. CS.numThreads[1] = ConstMDToUint32(pNode->getOperand(1));
  1005. CS.numThreads[2] = ConstMDToUint32(pNode->getOperand(2));
  1006. } break;
  1007. case DxilMDHelper::kDxilGSStateTag: {
  1008. DXASSERT(props.IsGS(), "else invalid shader kind");
  1009. auto &GS = props.ShaderProps.GS;
  1010. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  1011. unsigned activeStreamMask;
  1012. LoadDxilGSState(MDO, GS.inputPrimitive, GS.maxVertexCount,
  1013. activeStreamMask, topo, GS.instanceCount);
  1014. if (topo != DXIL::PrimitiveTopology::Undefined) {
  1015. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  1016. unsigned mask = 1 << i;
  1017. if (activeStreamMask & mask) {
  1018. GS.streamPrimitiveTopologies[i] = topo;
  1019. } else {
  1020. GS.streamPrimitiveTopologies[i] =
  1021. DXIL::PrimitiveTopology::Undefined;
  1022. }
  1023. }
  1024. }
  1025. } break;
  1026. case DxilMDHelper::kDxilDSStateTag: {
  1027. DXASSERT(props.IsDS(), "else invalid shader kind");
  1028. auto &DS = props.ShaderProps.DS;
  1029. LoadDxilDSState(MDO, DS.domain, DS.inputControlPoints);
  1030. } break;
  1031. case DxilMDHelper::kDxilHSStateTag: {
  1032. DXASSERT(props.IsHS(), "else invalid shader kind");
  1033. auto &HS = props.ShaderProps.HS;
  1034. LoadDxilHSState(MDO, HS.patchConstantFunc, HS.inputControlPoints,
  1035. HS.outputControlPoints, HS.domain, HS.partition,
  1036. HS.outputPrimitive, HS.maxTessFactor);
  1037. } break;
  1038. case DxilMDHelper::kDxilAutoBindingSpaceTag: {
  1039. MDNode *pNode = cast<MDNode>(MDO.get());
  1040. autoBindingSpace = ConstMDToUint32(pNode->getOperand(0));
  1041. break;
  1042. }
  1043. case DxilMDHelper::kDxilRayPayloadSizeTag: {
  1044. DXASSERT(props.IsAnyHit() || props.IsClosestHit() || props.IsMiss() ||
  1045. props.IsCallable(),
  1046. "else invalid shader kind");
  1047. props.ShaderProps.Ray.payloadSizeInBytes =
  1048. ConstMDToUint32(MDO);
  1049. } break;
  1050. case DxilMDHelper::kDxilRayAttribSizeTag: {
  1051. DXASSERT(props.IsAnyHit() || props.IsClosestHit(),
  1052. "else invalid shader kind");
  1053. props.ShaderProps.Ray.attributeSizeInBytes =
  1054. ConstMDToUint32(MDO);
  1055. } break;
  1056. case DxilMDHelper::kDxilShaderKindTag: {
  1057. DXIL::ShaderKind kind =
  1058. static_cast<DXIL::ShaderKind>(ConstMDToUint32(MDO));
  1059. DXASSERT(props.shaderKind == DXIL::ShaderKind::Library,
  1060. "else invalid shader kind");
  1061. props.shaderKind = kind;
  1062. } break;
  1063. default:
  1064. DXASSERT(false, "Unknown extended shader properties tag");
  1065. break;
  1066. }
  1067. }
  1068. if (bEarlyDepth) {
  1069. DXASSERT(props.IsPS(), "else invalid shader kind");
  1070. props.ShaderProps.PS.EarlyDepthStencil = true;
  1071. }
  1072. }
  1073. MDTuple *
  1074. DxilMDHelper::EmitDxilFunctionProps(const hlsl::DxilFunctionProps *props,
  1075. const Function *F) {
  1076. bool bRayAttributes = false;
  1077. Metadata *MDVals[30];
  1078. std::fill(MDVals, MDVals + _countof(MDVals), nullptr);
  1079. unsigned valIdx = 0;
  1080. MDVals[valIdx++] = ValueAsMetadata::get(const_cast<Function*>(F));
  1081. MDVals[valIdx++] = Uint32ToConstMD(static_cast<unsigned>(props->shaderKind));
  1082. switch (props->shaderKind) {
  1083. case DXIL::ShaderKind::Compute:
  1084. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[0]);
  1085. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[1]);
  1086. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[2]);
  1087. break;
  1088. case DXIL::ShaderKind::Geometry:
  1089. MDVals[valIdx++] =
  1090. Uint8ToConstMD((uint8_t)props->ShaderProps.GS.inputPrimitive);
  1091. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.maxVertexCount);
  1092. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.instanceCount);
  1093. for (size_t i = 0;
  1094. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  1095. MDVals[valIdx++] = Uint8ToConstMD(
  1096. (uint8_t)props->ShaderProps.GS.streamPrimitiveTopologies[i]);
  1097. break;
  1098. case DXIL::ShaderKind::Hull:
  1099. MDVals[valIdx++] =
  1100. ValueAsMetadata::get(props->ShaderProps.HS.patchConstantFunc);
  1101. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.domain);
  1102. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.partition);
  1103. MDVals[valIdx++] =
  1104. Uint8ToConstMD((uint8_t)props->ShaderProps.HS.outputPrimitive);
  1105. MDVals[valIdx++] =
  1106. Uint32ToConstMD(props->ShaderProps.HS.inputControlPoints);
  1107. MDVals[valIdx++] =
  1108. Uint32ToConstMD(props->ShaderProps.HS.outputControlPoints);
  1109. MDVals[valIdx++] = FloatToConstMD(props->ShaderProps.HS.maxTessFactor);
  1110. break;
  1111. case DXIL::ShaderKind::Domain:
  1112. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.DS.domain);
  1113. MDVals[valIdx++] =
  1114. Uint32ToConstMD(props->ShaderProps.DS.inputControlPoints);
  1115. break;
  1116. case DXIL::ShaderKind::Pixel:
  1117. MDVals[valIdx++] = BoolToConstMD(props->ShaderProps.PS.EarlyDepthStencil);
  1118. break;
  1119. case DXIL::ShaderKind::AnyHit:
  1120. case DXIL::ShaderKind::ClosestHit:
  1121. bRayAttributes = true;
  1122. case DXIL::ShaderKind::Miss:
  1123. case DXIL::ShaderKind::Callable:
  1124. // payload/params unioned and first:
  1125. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.payloadSizeInBytes);
  1126. if (bRayAttributes)
  1127. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.attributeSizeInBytes);
  1128. break;
  1129. default:
  1130. break;
  1131. }
  1132. return MDTuple::get(m_Ctx, ArrayRef<llvm::Metadata *>(MDVals, valIdx));
  1133. }
  1134. void DxilMDHelper::EmitDxilViewIdState(std::vector<unsigned> &SerializedState) {
  1135. const vector<unsigned> &Data = SerializedState;
  1136. // If all UINTs are zero, do not emit ViewIdState.
  1137. if (!std::any_of(Data.begin(), Data.end(), [](unsigned e){return e!=0;}))
  1138. return;
  1139. Constant *V = ConstantDataArray::get(m_Ctx, ArrayRef<uint32_t>(Data));
  1140. NamedMDNode *pViewIdNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1141. IFTBOOL(pViewIdNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1142. pViewIdNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilViewIdStateMDName);
  1143. pViewIdNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  1144. }
  1145. void DxilMDHelper::LoadDxilViewIdState(std::vector<unsigned> &SerializedState) {
  1146. NamedMDNode *pViewIdStateNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1147. if(!pViewIdStateNamedMD)
  1148. return;
  1149. IFTBOOL(pViewIdStateNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1150. MDNode *pNode = pViewIdStateNamedMD->getOperand(0);
  1151. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1152. const MDOperand &MDO = pNode->getOperand(0);
  1153. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  1154. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1155. if (isa<ConstantAggregateZero>(pMetaData->getValue()))
  1156. return;
  1157. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pMetaData->getValue());
  1158. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1159. IFTBOOL(pData->getElementType() == Type::getInt32Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  1160. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  1161. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1162. SerializedState.clear();
  1163. unsigned size = (unsigned)pData->getRawDataValues().size() / 4;
  1164. SerializedState.resize(size);
  1165. const unsigned *Ptr = (const unsigned *)pData->getRawDataValues().begin();
  1166. memcpy(SerializedState.data(), Ptr, size * sizeof(unsigned));
  1167. }
  1168. MDNode *DxilMDHelper::EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<DXIL::ControlFlowHint> &hints) {
  1169. SmallVector<Metadata *, 4> Args;
  1170. // Reserve operand 0 for self reference.
  1171. auto TempNode = MDNode::getTemporary(Ctx, None);
  1172. Args.emplace_back(TempNode.get());
  1173. Args.emplace_back(MDString::get(Ctx, kDxilControlFlowHintMDName));
  1174. for (DXIL::ControlFlowHint &hint : hints)
  1175. Args.emplace_back(Uint32ToConstMD(static_cast<unsigned>(hint), Ctx));
  1176. MDNode *hintsNode = MDNode::get(Ctx, Args);
  1177. // Set the first operand to itself.
  1178. hintsNode->replaceOperandWith(0, hintsNode);
  1179. return hintsNode;
  1180. }
  1181. void DxilMDHelper::EmitSubobjects(const DxilSubobjects &Subobjects) {
  1182. NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
  1183. IFTBOOL(pSubobjectsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1184. pSubobjectsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilSubobjectsMDName);
  1185. const auto &objMap = Subobjects.GetSubobjects();
  1186. for (auto &it : objMap)
  1187. pSubobjectsNamedMD->addOperand(cast<MDNode>(EmitSubobject(*it.second)));
  1188. }
  1189. void DxilMDHelper::LoadSubobjects(DxilSubobjects &Subobjects) {
  1190. NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
  1191. if (!pSubobjectsNamedMD)
  1192. return;
  1193. for (unsigned i = 0; i < pSubobjectsNamedMD->getNumOperands(); ++i)
  1194. LoadSubobject(*pSubobjectsNamedMD->getOperand(i), Subobjects);
  1195. }
  1196. Metadata *DxilMDHelper::EmitSubobject(const DxilSubobject &obj) {
  1197. SmallVector<Metadata *, 6> Args;
  1198. Args.emplace_back(MDString::get(m_Ctx, obj.GetName()));
  1199. Args.emplace_back(Uint32ToConstMD((unsigned)obj.GetKind()));
  1200. bool bLocalRS = false;
  1201. IFTBOOL(DXIL::IsValidSubobjectKind(obj.GetKind()), DXC_E_INCORRECT_DXIL_METADATA);
  1202. switch (obj.GetKind()) {
  1203. case DXIL::SubobjectKind::StateObjectConfig: {
  1204. uint32_t Flags;
  1205. IFTBOOL(obj.GetStateObjectConfig(Flags),
  1206. DXC_E_INCORRECT_DXIL_METADATA);
  1207. Args.emplace_back(Uint32ToConstMD((unsigned)Flags));
  1208. break;
  1209. }
  1210. case DXIL::SubobjectKind::LocalRootSignature:
  1211. bLocalRS = true;
  1212. __fallthrough;
  1213. case DXIL::SubobjectKind::GlobalRootSignature: {
  1214. const char * Text;
  1215. const void * Data;
  1216. uint32_t Size;
  1217. IFTBOOL(obj.GetRootSignature(bLocalRS, Data, Size, &Text),
  1218. DXC_E_INCORRECT_DXIL_METADATA);
  1219. Constant *V = ConstantDataArray::get(m_Ctx,
  1220. ArrayRef<uint8_t>((const uint8_t *)Data, Size));
  1221. Args.emplace_back(MDNode::get(m_Ctx, { ConstantAsMetadata::get(V) }));
  1222. Args.emplace_back(MDString::get(m_Ctx, Text));
  1223. break;
  1224. }
  1225. case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
  1226. StringRef Subobj;
  1227. const char * const * Exports;
  1228. uint32_t NumExports;
  1229. IFTBOOL(obj.GetSubobjectToExportsAssociation(Subobj, Exports, NumExports),
  1230. DXC_E_INCORRECT_DXIL_METADATA);
  1231. SmallVector<Metadata *, 4> strArgs;
  1232. for (unsigned i = 0; i < NumExports; ++i) {
  1233. strArgs.emplace_back(MDString::get(m_Ctx, Exports[i]));
  1234. }
  1235. Args.emplace_back(MDString::get(m_Ctx, Subobj));
  1236. Args.emplace_back(MDNode::get(m_Ctx, strArgs));
  1237. break;
  1238. }
  1239. case DXIL::SubobjectKind::RaytracingShaderConfig: {
  1240. uint32_t MaxPayloadSizeInBytes;
  1241. uint32_t MaxAttributeSizeInBytes;
  1242. IFTBOOL(obj.GetRaytracingShaderConfig(MaxPayloadSizeInBytes,
  1243. MaxAttributeSizeInBytes),
  1244. DXC_E_INCORRECT_DXIL_METADATA);
  1245. Args.emplace_back(Uint32ToConstMD(MaxPayloadSizeInBytes));
  1246. Args.emplace_back(Uint32ToConstMD(MaxAttributeSizeInBytes));
  1247. break;
  1248. }
  1249. case DXIL::SubobjectKind::RaytracingPipelineConfig: {
  1250. uint32_t MaxTraceRecursionDepth;
  1251. IFTBOOL(obj.GetRaytracingPipelineConfig(MaxTraceRecursionDepth),
  1252. DXC_E_INCORRECT_DXIL_METADATA);
  1253. Args.emplace_back(Uint32ToConstMD(MaxTraceRecursionDepth));
  1254. break;
  1255. }
  1256. case DXIL::SubobjectKind::HitGroup: {
  1257. llvm::StringRef Intersection, AnyHit, ClosestHit;
  1258. DXIL::HitGroupType hgType;
  1259. IFTBOOL(obj.GetHitGroup(hgType, Intersection, AnyHit, ClosestHit),
  1260. DXC_E_INCORRECT_DXIL_METADATA);
  1261. Args.emplace_back(Uint32ToConstMD((uint32_t)hgType));
  1262. Args.emplace_back(MDString::get(m_Ctx, Intersection));
  1263. Args.emplace_back(MDString::get(m_Ctx, AnyHit));
  1264. Args.emplace_back(MDString::get(m_Ctx, ClosestHit));
  1265. break;
  1266. }
  1267. default:
  1268. DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
  1269. break;
  1270. }
  1271. return MDNode::get(m_Ctx, Args);
  1272. }
  1273. void DxilMDHelper::LoadSubobject(const llvm::MDNode &MD, DxilSubobjects &Subobjects) {
  1274. IFTBOOL(MD.getNumOperands() >= 2, DXC_E_INCORRECT_DXIL_METADATA);
  1275. unsigned i = 0;
  1276. StringRef name(StringMDToStringRef(MD.getOperand(i++)));
  1277. DXIL::SubobjectKind kind = (DXIL::SubobjectKind)ConstMDToUint32(MD.getOperand(i++));
  1278. IFTBOOL(DXIL::IsValidSubobjectKind(kind), DXC_E_INCORRECT_DXIL_METADATA);
  1279. bool bLocalRS = false;
  1280. switch (kind) {
  1281. case DXIL::SubobjectKind::StateObjectConfig: {
  1282. uint32_t Flags = ConstMDToUint32(MD.getOperand(i++));
  1283. IFTBOOL(0 == ((~(uint32_t)DXIL::StateObjectFlags::ValidMask) & Flags),
  1284. DXC_E_INCORRECT_DXIL_METADATA);
  1285. Subobjects.CreateStateObjectConfig(name, Flags);
  1286. break;
  1287. }
  1288. case DXIL::SubobjectKind::LocalRootSignature:
  1289. bLocalRS = true;
  1290. __fallthrough;
  1291. case DXIL::SubobjectKind::GlobalRootSignature: {
  1292. const MDNode *pDataMDWrapper = dyn_cast<MDNode>(MD.getOperand(i++));
  1293. IFTBOOL(pDataMDWrapper != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1294. IFTBOOL(pDataMDWrapper->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1295. const ConstantAsMetadata *pDataMD = dyn_cast<ConstantAsMetadata>(pDataMDWrapper->getOperand(0));
  1296. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pDataMD->getValue());
  1297. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1298. IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  1299. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  1300. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1301. const void *Data = pData->getRawDataValues().begin();
  1302. uint32_t Size = pData->getRawDataValues().size();
  1303. StringRef Text(StringMDToStringRef(MD.getOperand(i++)));
  1304. Subobjects.CreateRootSignature(name, bLocalRS, Data, Size, Text.size() ? &Text : nullptr);
  1305. break;
  1306. }
  1307. case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
  1308. StringRef Subobj(StringMDToStringRef(MD.getOperand(i++)));
  1309. const MDNode *exportMD = dyn_cast<MDNode>(MD.getOperand(i++));
  1310. SmallVector<StringRef, 4> Exports;
  1311. for (unsigned iExport = 0; iExport < exportMD->getNumOperands(); iExport++) {
  1312. Exports.push_back(StringMDToStringRef(exportMD->getOperand(iExport)));
  1313. }
  1314. Subobjects.CreateSubobjectToExportsAssociation(name, Subobj, Exports.data(), Exports.size());
  1315. break;
  1316. }
  1317. case DXIL::SubobjectKind::RaytracingShaderConfig: {
  1318. uint32_t MaxPayloadSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
  1319. uint32_t MaxAttributeSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
  1320. Subobjects.CreateRaytracingShaderConfig(name, MaxPayloadSizeInBytes, MaxAttributeSizeInBytes);
  1321. break;
  1322. }
  1323. case DXIL::SubobjectKind::RaytracingPipelineConfig: {
  1324. uint32_t MaxTraceRecursionDepth = ConstMDToUint32(MD.getOperand(i++));;
  1325. Subobjects.CreateRaytracingPipelineConfig(name, MaxTraceRecursionDepth);
  1326. break;
  1327. }
  1328. case DXIL::SubobjectKind::HitGroup: {
  1329. uint32_t hgType = ConstMDToUint32(MD.getOperand(i++));
  1330. StringRef Intersection(StringMDToStringRef(MD.getOperand(i++)));
  1331. StringRef AnyHit(StringMDToStringRef(MD.getOperand(i++)));
  1332. StringRef ClosestHit(StringMDToStringRef(MD.getOperand(i++)));
  1333. Subobjects.CreateHitGroup(name, (DXIL::HitGroupType)hgType, AnyHit, ClosestHit, Intersection);
  1334. break;
  1335. }
  1336. default:
  1337. DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
  1338. break;
  1339. }
  1340. }
  1341. MDTuple *DxilMDHelper::EmitDxilSampler(const DxilSampler &S) {
  1342. Metadata *MDVals[kDxilSamplerNumFields];
  1343. EmitDxilResourceBase(S, &MDVals[0]);
  1344. // Sampler-specific fields.
  1345. MDVals[kDxilSamplerType ] = Uint32ToConstMD((unsigned)S.GetSamplerKind());
  1346. // Name-value list of extended properties.
  1347. MDVals[kDxilSamplerNameValueList] = nullptr;
  1348. vector<Metadata *> MDExtraVals;
  1349. m_ExtraPropertyHelper->EmitSamplerProperties(S, MDExtraVals);
  1350. if (!MDExtraVals.empty()) {
  1351. MDVals[kDxilSamplerNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  1352. }
  1353. return MDNode::get(m_Ctx, MDVals);
  1354. }
  1355. void DxilMDHelper::LoadDxilSampler(const MDOperand &MDO, DxilSampler &S) {
  1356. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1357. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1358. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1359. IFTBOOL(pTupleMD->getNumOperands() == kDxilSamplerNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1360. LoadDxilResourceBase(MDO, S);
  1361. // Sampler-specific fields.
  1362. S.SetSamplerKind((DxilSampler::SamplerKind)ConstMDToUint32(pTupleMD->getOperand(kDxilSamplerType)));
  1363. // Name-value list of extended properties.
  1364. m_ExtraPropertyHelper->LoadSamplerProperties(pTupleMD->getOperand(kDxilSamplerNameValueList), S);
  1365. }
  1366. const MDOperand &DxilMDHelper::GetResourceClass(llvm::MDNode *MD,
  1367. DXIL::ResourceClass &RC) {
  1368. IFTBOOL(MD->getNumOperands() >=
  1369. DxilMDHelper::kHLDxilResourceAttributeNumFields,
  1370. DXC_E_INCORRECT_DXIL_METADATA);
  1371. RC = static_cast<DxilResource::Class>(ConstMDToUint32(
  1372. MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeClass)));
  1373. return MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeMeta);
  1374. }
  1375. void DxilMDHelper::LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD,
  1376. DxilResourceBase &R) {
  1377. DxilResource::Class RC = DxilResource::Class::Invalid;
  1378. const MDOperand &Meta = GetResourceClass(MD, RC);
  1379. switch (RC) {
  1380. case DxilResource::Class::CBuffer: {
  1381. DxilCBuffer CB;
  1382. LoadDxilCBuffer(Meta, CB);
  1383. R = CB;
  1384. } break;
  1385. case DxilResource::Class::Sampler: {
  1386. DxilSampler S;
  1387. LoadDxilSampler(Meta, S);
  1388. R = S;
  1389. } break;
  1390. case DxilResource::Class::SRV: {
  1391. DxilResource Res;
  1392. LoadDxilSRV(Meta, Res);
  1393. R = Res;
  1394. } break;
  1395. case DxilResource::Class::UAV: {
  1396. DxilResource Res;
  1397. LoadDxilUAV(Meta, Res);
  1398. R = Res;
  1399. } break;
  1400. default:
  1401. DXASSERT(0, "Invalid metadata");
  1402. }
  1403. }
  1404. void DxilMDHelper::LoadDxilResourceFromMDNode(llvm::MDNode *MD,
  1405. DxilResource &R) {
  1406. DxilResource::Class RC = DxilResource::Class::Invalid;
  1407. const MDOperand &Meta = GetResourceClass(MD, RC);
  1408. switch (RC) {
  1409. case DxilResource::Class::SRV: {
  1410. LoadDxilSRV(Meta, R);
  1411. } break;
  1412. case DxilResource::Class::UAV: {
  1413. LoadDxilUAV(Meta, R);
  1414. } break;
  1415. default:
  1416. DXASSERT(0, "Invalid metadata");
  1417. }
  1418. }
  1419. void DxilMDHelper::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  1420. DxilResource::Class RC = DxilResource::Class::Invalid;
  1421. const MDOperand &Meta = GetResourceClass(MD, RC);
  1422. switch (RC) {
  1423. case DxilResource::Class::Sampler: {
  1424. LoadDxilSampler(Meta, S);
  1425. } break;
  1426. default:
  1427. DXASSERT(0, "Invalid metadata");
  1428. }
  1429. }
  1430. //
  1431. // DxilExtraPropertyHelper shader-specific methods.
  1432. //
  1433. MDTuple *DxilMDHelper::EmitDxilGSState(DXIL::InputPrimitive Primitive,
  1434. unsigned MaxVertexCount,
  1435. unsigned ActiveStreamMask,
  1436. DXIL::PrimitiveTopology StreamPrimitiveTopology,
  1437. unsigned GSInstanceCount) {
  1438. Metadata *MDVals[kDxilGSStateNumFields];
  1439. MDVals[kDxilGSStateInputPrimitive ] = Uint32ToConstMD((unsigned)Primitive);
  1440. MDVals[kDxilGSStateMaxVertexCount ] = Uint32ToConstMD(MaxVertexCount);
  1441. MDVals[kDxilGSStateActiveStreamMask ] = Uint32ToConstMD(ActiveStreamMask);
  1442. MDVals[kDxilGSStateOutputStreamTopology] = Uint32ToConstMD((unsigned)StreamPrimitiveTopology);
  1443. MDVals[kDxilGSStateGSInstanceCount ] = Uint32ToConstMD(GSInstanceCount);
  1444. return MDNode::get(m_Ctx, MDVals);
  1445. }
  1446. void DxilMDHelper::LoadDxilGSState(const MDOperand &MDO,
  1447. DXIL::InputPrimitive &Primitive,
  1448. unsigned &MaxVertexCount,
  1449. unsigned &ActiveStreamMask,
  1450. DXIL::PrimitiveTopology &StreamPrimitiveTopology,
  1451. unsigned &GSInstanceCount) {
  1452. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1453. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1454. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1455. IFTBOOL(pTupleMD->getNumOperands() == kDxilGSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1456. Primitive = (DXIL::InputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateInputPrimitive));
  1457. MaxVertexCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateMaxVertexCount));
  1458. ActiveStreamMask = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateActiveStreamMask));
  1459. StreamPrimitiveTopology = (DXIL::PrimitiveTopology)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateOutputStreamTopology));
  1460. GSInstanceCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateGSInstanceCount));
  1461. }
  1462. MDTuple *DxilMDHelper::EmitDxilDSState(DXIL::TessellatorDomain Domain, unsigned InputControlPointCount) {
  1463. Metadata *MDVals[kDxilDSStateNumFields];
  1464. MDVals[kDxilDSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)Domain);
  1465. MDVals[kDxilDSStateInputControlPointCount] = Uint32ToConstMD(InputControlPointCount);
  1466. return MDNode::get(m_Ctx, MDVals);
  1467. }
  1468. void DxilMDHelper::LoadDxilDSState(const MDOperand &MDO,
  1469. DXIL::TessellatorDomain &Domain,
  1470. unsigned &InputControlPointCount) {
  1471. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1472. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1473. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1474. IFTBOOL(pTupleMD->getNumOperands() == kDxilDSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1475. Domain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateTessellatorDomain));
  1476. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateInputControlPointCount));
  1477. }
  1478. MDTuple *DxilMDHelper::EmitDxilHSState(Function *pPatchConstantFunction,
  1479. unsigned InputControlPointCount,
  1480. unsigned OutputControlPointCount,
  1481. DXIL::TessellatorDomain TessDomain,
  1482. DXIL::TessellatorPartitioning TessPartitioning,
  1483. DXIL::TessellatorOutputPrimitive TessOutputPrimitive,
  1484. float MaxTessFactor) {
  1485. Metadata *MDVals[kDxilHSStateNumFields];
  1486. MDVals[kDxilHSStatePatchConstantFunction ] = ValueAsMetadata::get(pPatchConstantFunction);
  1487. MDVals[kDxilHSStateInputControlPointCount ] = Uint32ToConstMD(InputControlPointCount);
  1488. MDVals[kDxilHSStateOutputControlPointCount ] = Uint32ToConstMD(OutputControlPointCount);
  1489. MDVals[kDxilHSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)TessDomain);
  1490. MDVals[kDxilHSStateTessellatorPartitioning ] = Uint32ToConstMD((unsigned)TessPartitioning);
  1491. MDVals[kDxilHSStateTessellatorOutputPrimitive] = Uint32ToConstMD((unsigned)TessOutputPrimitive);
  1492. MDVals[kDxilHSStateMaxTessellationFactor ] = FloatToConstMD(MaxTessFactor);
  1493. return MDNode::get(m_Ctx, MDVals);
  1494. }
  1495. void DxilMDHelper::LoadDxilHSState(const MDOperand &MDO,
  1496. Function *&pPatchConstantFunction,
  1497. unsigned &InputControlPointCount,
  1498. unsigned &OutputControlPointCount,
  1499. DXIL::TessellatorDomain &TessDomain,
  1500. DXIL::TessellatorPartitioning &TessPartitioning,
  1501. DXIL::TessellatorOutputPrimitive &TessOutputPrimitive,
  1502. float &MaxTessFactor) {
  1503. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1504. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1505. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1506. IFTBOOL(pTupleMD->getNumOperands() == kDxilHSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1507. pPatchConstantFunction = dyn_cast<Function>(ValueMDToValue(pTupleMD->getOperand(kDxilHSStatePatchConstantFunction)));
  1508. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateInputControlPointCount));
  1509. OutputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateOutputControlPointCount));
  1510. TessDomain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorDomain));
  1511. TessPartitioning = (DXIL::TessellatorPartitioning)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorPartitioning));
  1512. TessOutputPrimitive = (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorOutputPrimitive));
  1513. MaxTessFactor = ConstMDToFloat(pTupleMD->getOperand(kDxilHSStateMaxTessellationFactor));
  1514. }
  1515. //
  1516. // DxilExtraPropertyHelper methods.
  1517. //
  1518. DxilMDHelper::ExtraPropertyHelper::ExtraPropertyHelper(Module *pModule)
  1519. : m_Ctx(pModule->getContext())
  1520. , m_pModule(pModule) {
  1521. }
  1522. DxilExtraPropertyHelper::DxilExtraPropertyHelper(Module *pModule)
  1523. : ExtraPropertyHelper(pModule) {
  1524. }
  1525. void DxilExtraPropertyHelper::EmitSRVProperties(const DxilResource &SRV, std::vector<Metadata *> &MDVals) {
  1526. // Element type for typed resource.
  1527. if (!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer()) {
  1528. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  1529. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)SRV.GetCompType().GetKind(), m_Ctx));
  1530. }
  1531. // Element stride for structured buffer.
  1532. if (SRV.IsStructuredBuffer()) {
  1533. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  1534. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SRV.GetElementStride(), m_Ctx));
  1535. }
  1536. }
  1537. void DxilExtraPropertyHelper::LoadSRVProperties(const MDOperand &MDO, DxilResource &SRV) {
  1538. SRV.SetElementStride(SRV.IsRawBuffer() ? 1 : 4);
  1539. SRV.SetCompType(CompType());
  1540. if (MDO.get() == nullptr) {
  1541. return;
  1542. }
  1543. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1544. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1545. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1546. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1547. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1548. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1549. switch (Tag) {
  1550. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  1551. DXASSERT_NOMSG(!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer());
  1552. SRV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  1553. break;
  1554. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  1555. DXASSERT_NOMSG(SRV.IsStructuredBuffer());
  1556. SRV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  1557. break;
  1558. default:
  1559. DXASSERT(false, "Unknown resource record tag");
  1560. }
  1561. }
  1562. }
  1563. void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::vector<Metadata *> &MDVals) {
  1564. // Element type for typed RW resource.
  1565. if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer()) {
  1566. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  1567. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetCompType().GetKind(), m_Ctx));
  1568. }
  1569. // Element stride for structured RW buffer.
  1570. if (UAV.IsStructuredBuffer()) {
  1571. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  1572. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(UAV.GetElementStride(), m_Ctx));
  1573. }
  1574. }
  1575. void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResource &UAV) {
  1576. UAV.SetElementStride(UAV.IsRawBuffer() ? 1 : 4);
  1577. UAV.SetCompType(CompType());
  1578. if (MDO.get() == nullptr) {
  1579. return;
  1580. }
  1581. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1582. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1583. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1584. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1585. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1586. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1587. switch (Tag) {
  1588. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  1589. DXASSERT_NOMSG(!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer());
  1590. UAV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  1591. break;
  1592. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  1593. DXASSERT_NOMSG(UAV.IsStructuredBuffer());
  1594. UAV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  1595. break;
  1596. default:
  1597. DXASSERT(false, "Unknown resource record tag");
  1598. }
  1599. }
  1600. }
  1601. void DxilExtraPropertyHelper::EmitCBufferProperties(const DxilCBuffer &CB, vector<Metadata *> &MDVals) {
  1602. // Emit property to preserve tbuffer kind
  1603. if (CB.GetKind() == DXIL::ResourceKind::TBuffer) {
  1604. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kHLCBufferIsTBufferTag, m_Ctx));
  1605. MDVals.emplace_back(DxilMDHelper::BoolToConstMD(true, m_Ctx));
  1606. }
  1607. }
  1608. void DxilExtraPropertyHelper::LoadCBufferProperties(const MDOperand &MDO, DxilCBuffer &CB) {
  1609. if (MDO.get() == nullptr)
  1610. return;
  1611. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1612. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1613. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1614. // Override kind for tbuffer that has not yet been converted to SRV.
  1615. CB.SetKind(DXIL::ResourceKind::CBuffer);
  1616. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1617. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1618. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1619. switch (Tag) {
  1620. case DxilMDHelper::kHLCBufferIsTBufferTag:
  1621. if (DxilMDHelper::ConstMDToBool(MDO)) {
  1622. CB.SetKind(DXIL::ResourceKind::TBuffer);
  1623. }
  1624. break;
  1625. default:
  1626. DXASSERT(false, "Unknown cbuffer tag");
  1627. }
  1628. }
  1629. }
  1630. void DxilExtraPropertyHelper::EmitSamplerProperties(const DxilSampler &S, std::vector<Metadata *> &MDVals) {
  1631. // Nothing yet.
  1632. }
  1633. void DxilExtraPropertyHelper::LoadSamplerProperties(const MDOperand &MDO, DxilSampler &S) {
  1634. // Nothing yet.
  1635. }
  1636. void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignatureElement &SE,
  1637. vector<Metadata *> &MDVals) {
  1638. // Output stream, if non-zero.
  1639. if (SE.GetOutputStream() != 0) {
  1640. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementOutputStreamTag, m_Ctx));
  1641. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetOutputStream(), m_Ctx));
  1642. }
  1643. // Mask of Dynamically indexed components.
  1644. if (SE.GetDynIdxCompMask() != 0) {
  1645. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
  1646. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
  1647. }
  1648. }
  1649. void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
  1650. if (MDO.get() == nullptr)
  1651. return;
  1652. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1653. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1654. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1655. // Stream.
  1656. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1657. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1658. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1659. switch (Tag) {
  1660. case DxilMDHelper::kDxilSignatureElementOutputStreamTag:
  1661. SE.SetOutputStream(DxilMDHelper::ConstMDToUint32(MDO));
  1662. break;
  1663. case DxilMDHelper::kHLSignatureElementGlobalSymbolTag:
  1664. break;
  1665. case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
  1666. SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
  1667. break;
  1668. default:
  1669. DXASSERT(false, "Unknown signature element tag");
  1670. }
  1671. }
  1672. }
  1673. //
  1674. // Utilities.
  1675. //
  1676. bool DxilMDHelper::IsKnownNamedMetaData(const llvm::NamedMDNode &Node) {
  1677. StringRef name = Node.getName();
  1678. for (unsigned i = 0; i < DxilMDNames.size(); i++) {
  1679. if (name == DxilMDNames[i]) {
  1680. return true;
  1681. }
  1682. }
  1683. return false;
  1684. }
  1685. void DxilMDHelper::combineDxilMetadata(llvm::Instruction *K,
  1686. const llvm::Instruction *J) {
  1687. if (IsMarkedNonUniform(J))
  1688. MarkNonUniform(K);
  1689. if (IsMarkedPrecise(J))
  1690. MarkPrecise(K);
  1691. }
  1692. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v, LLVMContext &Ctx) {
  1693. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1694. }
  1695. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v) {
  1696. return DxilMDHelper::Int32ToConstMD(v, m_Ctx);
  1697. }
  1698. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v, LLVMContext &Ctx) {
  1699. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1700. }
  1701. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v) {
  1702. return DxilMDHelper::Uint32ToConstMD(v, m_Ctx);
  1703. }
  1704. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v, LLVMContext &Ctx) {
  1705. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 64), APInt(64, v)));
  1706. }
  1707. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v) {
  1708. return DxilMDHelper::Uint64ToConstMD(v, m_Ctx);
  1709. }
  1710. ConstantAsMetadata *DxilMDHelper::Int8ToConstMD(int8_t v) {
  1711. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1712. }
  1713. ConstantAsMetadata *DxilMDHelper::Uint8ToConstMD(uint8_t v) {
  1714. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1715. }
  1716. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v, LLVMContext &Ctx) {
  1717. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 1), APInt(1, v ? 1 : 0)));
  1718. }
  1719. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v) {
  1720. return DxilMDHelper::BoolToConstMD(v, m_Ctx);
  1721. }
  1722. ConstantAsMetadata *DxilMDHelper::FloatToConstMD(float v) {
  1723. return ConstantAsMetadata::get(ConstantFP::get(m_Ctx, APFloat(v)));
  1724. }
  1725. int32_t DxilMDHelper::ConstMDToInt32(const MDOperand &MDO) {
  1726. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1727. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1728. return (int32_t)pConst->getZExtValue();
  1729. }
  1730. unsigned DxilMDHelper::ConstMDToUint32(const MDOperand &MDO) {
  1731. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1732. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1733. return (unsigned)pConst->getZExtValue();
  1734. }
  1735. uint64_t DxilMDHelper::ConstMDToUint64(const MDOperand &MDO) {
  1736. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1737. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1738. return pConst->getZExtValue();
  1739. }
  1740. int8_t DxilMDHelper::ConstMDToInt8(const MDOperand &MDO) {
  1741. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1742. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1743. return (int8_t)pConst->getZExtValue();
  1744. }
  1745. uint8_t DxilMDHelper::ConstMDToUint8(const MDOperand &MDO) {
  1746. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1747. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1748. return (uint8_t)pConst->getZExtValue();
  1749. }
  1750. bool DxilMDHelper::ConstMDToBool(const MDOperand &MDO) {
  1751. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1752. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1753. return pConst->getZExtValue() != 0;
  1754. }
  1755. float DxilMDHelper::ConstMDToFloat(const MDOperand &MDO) {
  1756. ConstantFP *pConst = mdconst::extract<ConstantFP>(MDO);
  1757. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1758. return pConst->getValueAPF().convertToFloat();
  1759. }
  1760. string DxilMDHelper::StringMDToString(const MDOperand &MDO) {
  1761. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  1762. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1763. return pMDString->getString();
  1764. }
  1765. StringRef DxilMDHelper::StringMDToStringRef(const MDOperand &MDO) {
  1766. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  1767. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1768. return pMDString->getString();
  1769. }
  1770. Value *DxilMDHelper::ValueMDToValue(const MDOperand &MDO) {
  1771. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1772. ValueAsMetadata *pValAsMD = dyn_cast<ValueAsMetadata>(MDO.get());
  1773. IFTBOOL(pValAsMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1774. Value *pValue = pValAsMD->getValue();
  1775. IFTBOOL(pValue != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1776. return pValue;
  1777. }
  1778. MDTuple *DxilMDHelper::Uint32VectorToConstMDTuple(const std::vector<unsigned> &Vec) {
  1779. vector<Metadata *> MDVals;
  1780. MDVals.resize(Vec.size());
  1781. for (size_t i = 0; i < Vec.size(); i++) {
  1782. MDVals[i] = Uint32ToConstMD(Vec[i]);
  1783. }
  1784. return MDNode::get(m_Ctx, MDVals);
  1785. }
  1786. void DxilMDHelper::ConstMDTupleToUint32Vector(MDTuple *pTupleMD, std::vector<unsigned> &Vec) {
  1787. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1788. Vec.resize(pTupleMD->getNumOperands());
  1789. for (size_t i = 0; i < pTupleMD->getNumOperands(); i++) {
  1790. Vec[i] = ConstMDToUint32(pTupleMD->getOperand(i));
  1791. }
  1792. }
  1793. bool DxilMDHelper::IsMarkedPrecise(const Instruction *inst) {
  1794. int32_t val = 0;
  1795. if (MDNode *precise = inst->getMetadata(kDxilPreciseAttributeMDName)) {
  1796. assert(precise->getNumOperands() == 1);
  1797. val = ConstMDToInt32(precise->getOperand(0));
  1798. }
  1799. return val;
  1800. }
  1801. void DxilMDHelper::MarkPrecise(Instruction *I) {
  1802. LLVMContext &Ctx = I->getContext();
  1803. MDNode *preciseNode = MDNode::get(
  1804. Ctx,
  1805. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  1806. I->setMetadata(DxilMDHelper::kDxilPreciseAttributeMDName, preciseNode);
  1807. }
  1808. bool DxilMDHelper::IsMarkedNonUniform(const Instruction *inst) {
  1809. int32_t val = 0;
  1810. if (MDNode *precise = inst->getMetadata(kDxilNonUniformAttributeMDName)) {
  1811. assert(precise->getNumOperands() == 1);
  1812. val = ConstMDToInt32(precise->getOperand(0));
  1813. }
  1814. return val;
  1815. }
  1816. void DxilMDHelper::MarkNonUniform(Instruction *I) {
  1817. LLVMContext &Ctx = I->getContext();
  1818. MDNode *preciseNode = MDNode::get(
  1819. Ctx,
  1820. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  1821. I->setMetadata(DxilMDHelper::kDxilNonUniformAttributeMDName, preciseNode);
  1822. }
  1823. } // namespace hlsl