DxilMetadataHelper.cpp 116 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790
  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/DxilCounters.h"
  14. #include "dxc/DXIL/DxilResource.h"
  15. #include "dxc/DXIL/DxilSampler.h"
  16. #include "dxc/DXIL/DxilSignatureElement.h"
  17. #include "dxc/DXIL/DxilSignature.h"
  18. #include "dxc/DXIL/DxilTypeSystem.h"
  19. #include "dxc/DXIL/DxilFunctionProps.h"
  20. #include "dxc/DXIL/DxilShaderFlags.h"
  21. #include "dxc/DXIL/DxilSubobject.h"
  22. #include "llvm/IR/Constants.h"
  23. #include "llvm/IR/Function.h"
  24. #include "llvm/IR/IntrinsicInst.h"
  25. #include "llvm/IR/LLVMContext.h"
  26. #include "llvm/IR/Metadata.h"
  27. #include "llvm/IR/Module.h"
  28. #include "llvm/IR/IRBuilder.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include "llvm/ADT/DenseSet.h"
  31. #include <array>
  32. #include <algorithm>
  33. #include "dxc/Support/WinIncludes.h"
  34. #include "dxc/Support/WinFunctions.h"
  35. using namespace llvm;
  36. using std::string;
  37. using std::vector;
  38. using std::unique_ptr;
  39. namespace hlsl {
  40. const char DxilMDHelper::kDxilVersionMDName[] = "dx.version";
  41. const char DxilMDHelper::kDxilShaderModelMDName[] = "dx.shaderModel";
  42. const char DxilMDHelper::kDxilEntryPointsMDName[] = "dx.entryPoints";
  43. const char DxilMDHelper::kDxilResourcesMDName[] = "dx.resources";
  44. const char DxilMDHelper::kDxilTypeSystemMDName[] = "dx.typeAnnotations";
  45. const char DxilMDHelper::kDxilTypeSystemHelperVariablePrefix[] = "dx.typevar.";
  46. const char DxilMDHelper::kDxilControlFlowHintMDName[] = "dx.controlflow.hints";
  47. const char DxilMDHelper::kDxilPreciseAttributeMDName[] = "dx.precise";
  48. const char DxilMDHelper::kDxilVariableDebugLayoutMDName[] = "dx.dbg.varlayout";
  49. const char DxilMDHelper::kDxilTempAllocaMDName[] = "dx.temp";
  50. const char DxilMDHelper::kDxilNonUniformAttributeMDName[] = "dx.nonuniform";
  51. const char DxilMDHelper::kHLDxilResourceAttributeMDName[] = "dx.hl.resource.attribute";
  52. const char DxilMDHelper::kDxilValidatorVersionMDName[] = "dx.valver";
  53. const char DxilMDHelper::kDxilDxrPayloadAnnotationsMDName[] = "dx.dxrPayloadAnnotations";
  54. // This named metadata is not valid in final module (should be moved to DxilContainer)
  55. const char DxilMDHelper::kDxilRootSignatureMDName[] = "dx.rootSignature";
  56. const char DxilMDHelper::kDxilIntermediateOptionsMDName[] = "dx.intermediateOptions";
  57. const char DxilMDHelper::kDxilViewIdStateMDName[] = "dx.viewIdState";
  58. const char DxilMDHelper::kDxilSubobjectsMDName[] = "dx.subobjects";
  59. const char DxilMDHelper::kDxilSourceContentsMDName[] = "dx.source.contents";
  60. const char DxilMDHelper::kDxilSourceDefinesMDName[] = "dx.source.defines";
  61. const char DxilMDHelper::kDxilSourceMainFileNameMDName[] = "dx.source.mainFileName";
  62. const char DxilMDHelper::kDxilSourceArgsMDName[] = "dx.source.args";
  63. const char DxilMDHelper::kDxilSourceContentsOldMDName[] = "llvm.dbg.contents";
  64. const char DxilMDHelper::kDxilSourceDefinesOldMDName[] = "llvm.dbg.defines";
  65. const char DxilMDHelper::kDxilSourceMainFileNameOldMDName[] = "llvm.dbg.mainFileName";
  66. const char DxilMDHelper::kDxilSourceArgsOldMDName[] = "llvm.dbg.args";
  67. // This is reflection-only metadata
  68. const char DxilMDHelper::kDxilCountersMDName[] = "dx.counters";
  69. static std::array<const char *, 8> DxilMDNames = { {
  70. DxilMDHelper::kDxilVersionMDName,
  71. DxilMDHelper::kDxilShaderModelMDName,
  72. DxilMDHelper::kDxilEntryPointsMDName,
  73. DxilMDHelper::kDxilResourcesMDName,
  74. DxilMDHelper::kDxilTypeSystemMDName,
  75. DxilMDHelper::kDxilValidatorVersionMDName,
  76. DxilMDHelper::kDxilViewIdStateMDName,
  77. DxilMDHelper::kDxilDxrPayloadAnnotationsMDName,
  78. }};
  79. DxilMDHelper::DxilMDHelper(Module *pModule, std::unique_ptr<ExtraPropertyHelper> EPH)
  80. : m_Ctx(pModule->getContext())
  81. , m_pModule(pModule)
  82. , m_pSM(nullptr)
  83. , m_ExtraPropertyHelper(std::move(EPH))
  84. , m_ValMajor(1)
  85. , m_ValMinor(0)
  86. , m_MinValMajor(1)
  87. , m_MinValMinor(0)
  88. , m_bExtraMetadata(false)
  89. {
  90. }
  91. DxilMDHelper::~DxilMDHelper() {
  92. }
  93. void DxilMDHelper::SetShaderModel(const ShaderModel *pSM) {
  94. m_pSM = pSM;
  95. m_pSM->GetMinValidatorVersion(m_MinValMajor, m_MinValMinor);
  96. if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, m_MinValMajor, m_MinValMinor) < 0) {
  97. m_ValMajor = m_MinValMajor;
  98. m_ValMinor = m_MinValMinor;
  99. }
  100. // Validator version 0.0 is not meant for validation or retail driver consumption,
  101. // and is used for separate reflection.
  102. // MinVal version drives metadata decisions for compatilbility, so snap this to
  103. // latest for reflection/no validation case.
  104. if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 0, 0) == 0) {
  105. m_MinValMajor = 0;
  106. m_MinValMinor = 0;
  107. }
  108. if (m_ExtraPropertyHelper) {
  109. m_ExtraPropertyHelper->m_ValMajor = m_ValMajor;
  110. m_ExtraPropertyHelper->m_ValMinor = m_ValMinor;
  111. m_ExtraPropertyHelper->m_MinValMajor = m_MinValMajor;
  112. m_ExtraPropertyHelper->m_MinValMinor = m_MinValMinor;
  113. }
  114. }
  115. const ShaderModel *DxilMDHelper::GetShaderModel() const {
  116. return m_pSM;
  117. }
  118. //
  119. // DXIL version.
  120. //
  121. void DxilMDHelper::EmitDxilVersion(unsigned Major, unsigned Minor) {
  122. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  123. IFTBOOL(pDxilVersionMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  124. pDxilVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilVersionMDName);
  125. Metadata *MDVals[kDxilVersionNumFields];
  126. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  127. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  128. pDxilVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  129. }
  130. void DxilMDHelper::LoadDxilVersion(unsigned &Major, unsigned &Minor) {
  131. NamedMDNode *pDxilVersionMD = m_pModule->getNamedMetadata(kDxilVersionMDName);
  132. IFTBOOL(pDxilVersionMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  133. IFTBOOL(pDxilVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  134. MDNode *pVersionMD = pDxilVersionMD->getOperand(0);
  135. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  136. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  137. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  138. }
  139. //
  140. // Validator version.
  141. //
  142. void DxilMDHelper::EmitValidatorVersion(unsigned Major, unsigned Minor) {
  143. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  144. // Allow re-writing the validator version, since this can be changed at later points.
  145. if (pDxilValidatorVersionMD)
  146. m_pModule->eraseNamedMetadata(pDxilValidatorVersionMD);
  147. pDxilValidatorVersionMD = m_pModule->getOrInsertNamedMetadata(kDxilValidatorVersionMDName);
  148. Metadata *MDVals[kDxilVersionNumFields];
  149. MDVals[kDxilVersionMajorIdx] = Uint32ToConstMD(Major);
  150. MDVals[kDxilVersionMinorIdx] = Uint32ToConstMD(Minor);
  151. pDxilValidatorVersionMD->addOperand(MDNode::get(m_Ctx, MDVals));
  152. m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
  153. }
  154. void DxilMDHelper::LoadValidatorVersion(unsigned &Major, unsigned &Minor) {
  155. NamedMDNode *pDxilValidatorVersionMD = m_pModule->getNamedMetadata(kDxilValidatorVersionMDName);
  156. if (pDxilValidatorVersionMD == nullptr) {
  157. // If no validator version metadata, assume 1.0
  158. Major = 1;
  159. Minor = 0;
  160. m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
  161. return;
  162. }
  163. IFTBOOL(pDxilValidatorVersionMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  164. MDNode *pVersionMD = pDxilValidatorVersionMD->getOperand(0);
  165. IFTBOOL(pVersionMD->getNumOperands() == kDxilVersionNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  166. Major = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMajorIdx));
  167. Minor = ConstMDToUint32(pVersionMD->getOperand(kDxilVersionMinorIdx));
  168. m_ValMajor = Major; m_ValMinor = Minor; // Keep these for later use
  169. }
  170. //
  171. // DXIL shader model.
  172. //
  173. void DxilMDHelper::EmitDxilShaderModel(const ShaderModel *pSM) {
  174. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  175. IFTBOOL(pShaderModelNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  176. pShaderModelNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilShaderModelMDName);
  177. Metadata *MDVals[kDxilShaderModelNumFields];
  178. MDVals[kDxilShaderModelTypeIdx ] = MDString::get(m_Ctx, pSM->GetKindName());
  179. MDVals[kDxilShaderModelMajorIdx] = Uint32ToConstMD(pSM->GetMajor());
  180. MDVals[kDxilShaderModelMinorIdx] = Uint32ToConstMD(pSM->GetMinor());
  181. pShaderModelNamedMD->addOperand(MDNode::get(m_Ctx, MDVals));
  182. SetShaderModel(pSM);
  183. }
  184. void DxilMDHelper::LoadDxilShaderModel(const ShaderModel *&pSM) {
  185. NamedMDNode *pShaderModelNamedMD = m_pModule->getNamedMetadata(kDxilShaderModelMDName);
  186. IFTBOOL(pShaderModelNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  187. IFTBOOL(pShaderModelNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  188. MDNode *pShaderModelMD = pShaderModelNamedMD->getOperand(0);
  189. IFTBOOL(pShaderModelMD->getNumOperands() == kDxilShaderModelNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  190. MDString *pShaderTypeMD = dyn_cast<MDString>(pShaderModelMD->getOperand(kDxilShaderModelTypeIdx));
  191. IFTBOOL(pShaderTypeMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  192. unsigned Major = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMajorIdx));
  193. unsigned Minor = ConstMDToUint32(pShaderModelMD->getOperand(kDxilShaderModelMinorIdx));
  194. string ShaderModelName = pShaderTypeMD->getString();
  195. ShaderModelName += "_" + std::to_string(Major) + "_" +
  196. (Minor == ShaderModel::kOfflineMinor ? "x" : std::to_string(Minor));
  197. pSM = ShaderModel::GetByName(ShaderModelName.c_str());
  198. if (!pSM->IsValidForDxil()) {
  199. char ErrorMsgTxt[40];
  200. StringCchPrintfA(ErrorMsgTxt, _countof(ErrorMsgTxt),
  201. "Unknown shader model '%s'", ShaderModelName.c_str());
  202. string ErrorMsg(ErrorMsgTxt);
  203. throw hlsl::Exception(DXC_E_INCORRECT_DXIL_METADATA, ErrorMsg);
  204. }
  205. SetShaderModel(pSM);
  206. }
  207. //
  208. // intermediate options.
  209. //
  210. void DxilMDHelper::EmitDxilIntermediateOptions(uint32_t flags) {
  211. if (flags == 0) return;
  212. NamedMDNode *pIntermediateOptionsNamedMD = m_pModule->getNamedMetadata(kDxilIntermediateOptionsMDName);
  213. IFTBOOL(pIntermediateOptionsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  214. pIntermediateOptionsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilIntermediateOptionsMDName);
  215. pIntermediateOptionsNamedMD->addOperand(
  216. MDNode::get(m_Ctx, { Uint32ToConstMD(kDxilIntermediateOptionsFlags), Uint32ToConstMD(flags) }));
  217. }
  218. void DxilMDHelper::LoadDxilIntermediateOptions(uint32_t &flags) {
  219. flags = 0;
  220. NamedMDNode *pIntermediateOptionsNamedMD = m_pModule->getNamedMetadata(kDxilIntermediateOptionsMDName);
  221. if (pIntermediateOptionsNamedMD == nullptr) return;
  222. for (unsigned i = 0; i < pIntermediateOptionsNamedMD->getNumOperands(); i++) {
  223. MDTuple *pEntry = dyn_cast<MDTuple>(pIntermediateOptionsNamedMD->getOperand(i));
  224. IFTBOOL(pEntry != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  225. IFTBOOL(pEntry->getNumOperands() >= 1, DXC_E_INCORRECT_DXIL_METADATA);
  226. uint32_t id = ConstMDToUint32(pEntry->getOperand(0));
  227. switch (id) {
  228. case kDxilIntermediateOptionsFlags:
  229. IFTBOOL(pEntry->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
  230. flags = ConstMDToUint32(pEntry->getOperand(1));
  231. break;
  232. default: throw hlsl::Exception(DXC_E_INCORRECT_DXIL_METADATA, "Unrecognized intermediate options metadata");
  233. }
  234. }
  235. }
  236. //
  237. // Entry points.
  238. //
  239. void DxilMDHelper::EmitDxilEntryPoints(vector<MDNode *> &MDEntries) {
  240. DXASSERT(MDEntries.size() == 1 || GetShaderModel()->IsLib(),
  241. "only one entry point is supported for now");
  242. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  243. IFTBOOL(pEntryPointsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  244. pEntryPointsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilEntryPointsMDName);
  245. for (size_t i = 0; i < MDEntries.size(); i++) {
  246. pEntryPointsNamedMD->addOperand(MDEntries[i]);
  247. }
  248. }
  249. void DxilMDHelper::UpdateDxilEntryPoints(vector<MDNode *> &MDEntries) {
  250. DXASSERT(MDEntries.size() == 1, "only one entry point is supported for now");
  251. NamedMDNode *pEntryPointsNamedMD =
  252. m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  253. IFTBOOL(pEntryPointsNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  254. for (size_t i = 0; i < MDEntries.size(); i++) {
  255. pEntryPointsNamedMD->setOperand(i, MDEntries[i]);
  256. }
  257. }
  258. const NamedMDNode *DxilMDHelper::GetDxilEntryPoints() {
  259. NamedMDNode *pEntryPointsNamedMD = m_pModule->getNamedMetadata(kDxilEntryPointsMDName);
  260. IFTBOOL(pEntryPointsNamedMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  261. return pEntryPointsNamedMD;
  262. }
  263. MDTuple *DxilMDHelper::EmitDxilEntryPointTuple(Function *pFunc, const string &Name,
  264. MDTuple *pSignatures, MDTuple *pResources,
  265. MDTuple *pProperties) {
  266. Metadata *MDVals[kDxilEntryPointNumFields];
  267. MDVals[kDxilEntryPointFunction ] = pFunc ? ValueAsMetadata::get(pFunc) : nullptr;
  268. MDVals[kDxilEntryPointName ] = MDString::get(m_Ctx, Name.c_str());
  269. MDVals[kDxilEntryPointSignatures] = pSignatures;
  270. MDVals[kDxilEntryPointResources ] = pResources;
  271. MDVals[kDxilEntryPointProperties] = pProperties;
  272. return MDNode::get(m_Ctx, MDVals);
  273. }
  274. void DxilMDHelper::GetDxilEntryPoint(const MDNode *MDO, Function *&pFunc, string &Name,
  275. const MDOperand *&pSignatures, const MDOperand *&pResources,
  276. const MDOperand *&pProperties) {
  277. IFTBOOL(MDO != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  278. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO);
  279. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  280. IFTBOOL(pTupleMD->getNumOperands() == kDxilEntryPointNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  281. // Retrieve entry function symbol.
  282. const MDOperand &MDOFunc = pTupleMD->getOperand(kDxilEntryPointFunction);
  283. if (MDOFunc.get() != nullptr) {
  284. ValueAsMetadata *pValueFunc = dyn_cast<ValueAsMetadata>(MDOFunc.get());
  285. IFTBOOL(pValueFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  286. pFunc = dyn_cast<Function>(pValueFunc->getValue());
  287. IFTBOOL(pFunc != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  288. } else {
  289. pFunc = nullptr; // pass-through CP.
  290. }
  291. // Retrieve entry function name.
  292. const MDOperand &MDOName = pTupleMD->getOperand(kDxilEntryPointName);
  293. IFTBOOL(MDOName.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  294. MDString *pMDName = dyn_cast<MDString>(MDOName);
  295. IFTBOOL(pMDName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  296. Name = pMDName->getString();
  297. pSignatures = &pTupleMD->getOperand(kDxilEntryPointSignatures);
  298. pResources = &pTupleMD->getOperand(kDxilEntryPointResources );
  299. pProperties = &pTupleMD->getOperand(kDxilEntryPointProperties);
  300. }
  301. //
  302. // Signatures.
  303. //
  304. MDTuple *DxilMDHelper::EmitDxilSignatures(const DxilEntrySignature &EntrySig) {
  305. MDTuple *pSignatureTupleMD = nullptr;
  306. const DxilSignature &InputSig = EntrySig.InputSignature;
  307. const DxilSignature &OutputSig = EntrySig.OutputSignature;
  308. const DxilSignature &PCPSig = EntrySig.PatchConstOrPrimSignature;
  309. if (!InputSig.GetElements().empty() || !OutputSig.GetElements().empty() || !PCPSig.GetElements().empty()) {
  310. Metadata *MDVals[kDxilNumSignatureFields];
  311. MDVals[kDxilInputSignature] = EmitSignatureMetadata(InputSig);
  312. MDVals[kDxilOutputSignature] = EmitSignatureMetadata(OutputSig);
  313. MDVals[kDxilPatchConstantSignature] = EmitSignatureMetadata(PCPSig);
  314. pSignatureTupleMD = MDNode::get(m_Ctx, MDVals);
  315. }
  316. return pSignatureTupleMD;
  317. }
  318. void DxilMDHelper::EmitRootSignature(
  319. std::vector<uint8_t> &SerializedRootSignature) {
  320. if (SerializedRootSignature.empty()) {
  321. return;
  322. }
  323. Constant *V = llvm::ConstantDataArray::get(
  324. m_Ctx, llvm::ArrayRef<uint8_t>(SerializedRootSignature.data(),
  325. SerializedRootSignature.size()));
  326. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  327. IFTBOOL(pRootSignatureNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  328. pRootSignatureNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilRootSignatureMDName);
  329. pRootSignatureNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  330. return ;
  331. }
  332. void DxilMDHelper::LoadDxilSignatures(const MDOperand &MDO, DxilEntrySignature &EntrySig) {
  333. if (MDO.get() == nullptr)
  334. return;
  335. DxilSignature &InputSig = EntrySig.InputSignature;
  336. DxilSignature &OutputSig = EntrySig.OutputSignature;
  337. DxilSignature &PCPSig = EntrySig.PatchConstOrPrimSignature;
  338. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  339. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  340. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumSignatureFields, DXC_E_INCORRECT_DXIL_METADATA);
  341. LoadSignatureMetadata(pTupleMD->getOperand(kDxilInputSignature), InputSig);
  342. LoadSignatureMetadata(pTupleMD->getOperand(kDxilOutputSignature), OutputSig);
  343. LoadSignatureMetadata(pTupleMD->getOperand(kDxilPatchConstantSignature), PCPSig);
  344. }
  345. MDTuple *DxilMDHelper::EmitSignatureMetadata(const DxilSignature &Sig) {
  346. auto &Elements = Sig.GetElements();
  347. if (Elements.empty())
  348. return nullptr;
  349. vector<Metadata *> MDVals;
  350. for (size_t i = 0; i < Elements.size(); i++) {
  351. MDVals.emplace_back(EmitSignatureElement(*Elements[i]));
  352. }
  353. return MDNode::get(m_Ctx, MDVals);
  354. }
  355. void DxilMDHelper::LoadSignatureMetadata(const MDOperand &MDO, DxilSignature &Sig) {
  356. if (MDO.get() == nullptr)
  357. return;
  358. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  359. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  360. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i++) {
  361. unique_ptr<DxilSignatureElement> pSE(Sig.CreateElement());
  362. LoadSignatureElement(pTupleMD->getOperand(i), *pSE.get());
  363. Sig.AppendElement(std::move(pSE));
  364. }
  365. }
  366. void DxilMDHelper::LoadRootSignature(std::vector<uint8_t> &SerializedRootSignature) {
  367. NamedMDNode *pRootSignatureNamedMD = m_pModule->getNamedMetadata(kDxilRootSignatureMDName);
  368. if(!pRootSignatureNamedMD)
  369. return;
  370. IFTBOOL(pRootSignatureNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  371. MDNode *pNode = pRootSignatureNamedMD->getOperand(0);
  372. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  373. const MDOperand &MDO = pNode->getOperand(0);
  374. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  375. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  376. const ConstantDataArray *pData =
  377. dyn_cast<ConstantDataArray>(pMetaData->getValue());
  378. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  379. IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx),
  380. DXC_E_INCORRECT_DXIL_METADATA);
  381. SerializedRootSignature.clear();
  382. unsigned size = pData->getRawDataValues().size();
  383. SerializedRootSignature.resize(size);
  384. memcpy(SerializedRootSignature.data(),
  385. (const uint8_t *)pData->getRawDataValues().begin(), size);
  386. }
  387. static const MDTuple *CastToTupleOrNull(const MDOperand &MDO) {
  388. if (MDO.get() == nullptr)
  389. return nullptr;
  390. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  391. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  392. return pTupleMD;
  393. }
  394. MDTuple *DxilMDHelper::EmitSignatureElement(const DxilSignatureElement &SE) {
  395. Metadata *MDVals[kDxilSignatureElementNumFields];
  396. MDVals[kDxilSignatureElementID ] = Uint32ToConstMD(SE.GetID());
  397. MDVals[kDxilSignatureElementName ] = MDString::get(m_Ctx, SE.GetName());
  398. MDVals[kDxilSignatureElementType ] = Uint8ToConstMD((uint8_t)SE.GetCompType().GetKind());
  399. MDVals[kDxilSignatureElementSystemValue ] = Uint8ToConstMD((uint8_t)SE.GetKind());
  400. MDVals[kDxilSignatureElementIndexVector ] = Uint32VectorToConstMDTuple(SE.GetSemanticIndexVec());
  401. MDVals[kDxilSignatureElementInterpMode ] = Uint8ToConstMD((uint8_t)SE.GetInterpolationMode()->GetKind());
  402. MDVals[kDxilSignatureElementRows ] = Uint32ToConstMD(SE.GetRows());
  403. MDVals[kDxilSignatureElementCols ] = Uint8ToConstMD((uint8_t)SE.GetCols());
  404. MDVals[kDxilSignatureElementStartRow ] = Int32ToConstMD(SE.GetStartRow());
  405. MDVals[kDxilSignatureElementStartCol ] = Int8ToConstMD((int8_t)SE.GetStartCol());
  406. // Name-value list of extended properties.
  407. MDVals[kDxilSignatureElementNameValueList] = nullptr;
  408. vector<Metadata *> MDExtraVals;
  409. m_ExtraPropertyHelper->EmitSignatureElementProperties(SE, MDExtraVals);
  410. if (!MDExtraVals.empty()) {
  411. MDVals[kDxilSignatureElementNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  412. }
  413. // NOTE: when extra properties for signature elements are needed, extend ExtraPropertyHelper.
  414. return MDNode::get(m_Ctx, MDVals);
  415. }
  416. void DxilMDHelper::LoadSignatureElement(const MDOperand &MDO, DxilSignatureElement &SE) {
  417. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  418. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  419. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  420. IFTBOOL(pTupleMD->getNumOperands() == kDxilSignatureElementNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  421. unsigned ID = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementID));
  422. MDString *pName = dyn_cast<MDString>( pTupleMD->getOperand(kDxilSignatureElementName));
  423. CompType CT = CompType(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementType)));
  424. DXIL::SemanticKind SemKind =
  425. (DXIL::SemanticKind)ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementSystemValue));
  426. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(kDxilSignatureElementIndexVector));
  427. InterpolationMode IM(ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementInterpMode)));
  428. unsigned NumRows = ConstMDToUint32( pTupleMD->getOperand(kDxilSignatureElementRows));
  429. uint8_t NumCols = ConstMDToUint8( pTupleMD->getOperand(kDxilSignatureElementCols));
  430. int32_t StartRow = ConstMDToInt32( pTupleMD->getOperand(kDxilSignatureElementStartRow));
  431. int8_t StartCol = ConstMDToInt8( pTupleMD->getOperand(kDxilSignatureElementStartCol));
  432. IFTBOOL(pName != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  433. IFTBOOL(pSemanticIndexVectorMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  434. vector<unsigned> SemanticIndexVector;
  435. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  436. SE.Initialize(pName->getString(), CT, IM, NumRows, NumCols, StartRow, StartCol, ID, SemanticIndexVector);
  437. SE.SetKind(SemKind);
  438. // For case a system semantic don't have index, add 0 for it.
  439. if (SemanticIndexVector.empty() && !SE.IsArbitrary()) {
  440. SE.SetSemanticIndexVec({0});
  441. }
  442. // Name-value list of extended properties.
  443. m_ExtraPropertyHelper->m_bExtraMetadata = false;
  444. m_ExtraPropertyHelper->LoadSignatureElementProperties(pTupleMD->getOperand(kDxilSignatureElementNameValueList), SE);
  445. m_bExtraMetadata |= m_ExtraPropertyHelper->m_bExtraMetadata;
  446. }
  447. //
  448. // Resources.
  449. //
  450. MDTuple *DxilMDHelper::EmitDxilResourceTuple(MDTuple *pSRVs, MDTuple *pUAVs,
  451. MDTuple *pCBuffers, MDTuple *pSamplers) {
  452. DXASSERT(pSRVs != nullptr || pUAVs != nullptr || pCBuffers != nullptr || pSamplers != nullptr, "resource tuple should not be emitted if there are no resources");
  453. Metadata *MDVals[kDxilNumResourceFields];
  454. MDVals[kDxilResourceSRVs ] = pSRVs;
  455. MDVals[kDxilResourceUAVs ] = pUAVs;
  456. MDVals[kDxilResourceCBuffers] = pCBuffers;
  457. MDVals[kDxilResourceSamplers] = pSamplers;
  458. MDTuple *pTupleMD = MDNode::get(m_Ctx, MDVals);
  459. return pTupleMD;
  460. }
  461. void DxilMDHelper::EmitDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  462. NamedMDNode *pResourcesNamedMD = m_pModule->getNamedMetadata(kDxilResourcesMDName);
  463. IFTBOOL(pResourcesNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  464. pResourcesNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  465. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  466. }
  467. void DxilMDHelper::UpdateDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  468. NamedMDNode *pResourcesNamedMD =
  469. m_pModule->getNamedMetadata(kDxilResourcesMDName);
  470. if (!pResourcesNamedMD) {
  471. pResourcesNamedMD =
  472. m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  473. }
  474. if (pDxilResourceTuple) {
  475. if (pResourcesNamedMD->getNumOperands() != 0) {
  476. pResourcesNamedMD->setOperand(0, pDxilResourceTuple);
  477. }
  478. else {
  479. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  480. }
  481. } else {
  482. m_pModule->eraseNamedMetadata(pResourcesNamedMD);
  483. }
  484. }
  485. void DxilMDHelper::GetDxilResources(const MDOperand &MDO, const MDTuple *&pSRVs,
  486. const MDTuple *&pUAVs, const MDTuple *&pCBuffers,
  487. const MDTuple *&pSamplers) {
  488. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  489. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  490. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  491. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumResourceFields, DXC_E_INCORRECT_DXIL_METADATA);
  492. pSRVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSRVs ));
  493. pUAVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceUAVs ));
  494. pCBuffers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceCBuffers));
  495. pSamplers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSamplers));
  496. }
  497. void DxilMDHelper::EmitDxilResourceBase(const DxilResourceBase &R, Metadata *ppMDVals[]) {
  498. ppMDVals[kDxilResourceBaseID ] = Uint32ToConstMD(R.GetID());
  499. Constant *GlobalSymbol = R.GetGlobalSymbol();
  500. // For sm66+, global symbol will be mutated into handle type.
  501. // Save hlsl type by generate bitcast on global symbol.
  502. if (m_pSM->IsSM66Plus()) {
  503. Type *HLSLTy = R.GetHLSLType();
  504. if (HLSLTy && HLSLTy != GlobalSymbol->getType())
  505. GlobalSymbol = cast<Constant>(
  506. ConstantExpr::getCast(Instruction::BitCast, GlobalSymbol, HLSLTy));
  507. }
  508. ppMDVals[kDxilResourceBaseVariable ] = ValueAsMetadata::get(GlobalSymbol);
  509. ppMDVals[kDxilResourceBaseName ] = MDString::get(m_Ctx, R.GetGlobalName());
  510. ppMDVals[kDxilResourceBaseSpaceID ] = Uint32ToConstMD(R.GetSpaceID());
  511. ppMDVals[kDxilResourceBaseLowerBound] = Uint32ToConstMD(R.GetLowerBound());
  512. ppMDVals[kDxilResourceBaseRangeSize ] = Uint32ToConstMD(R.GetRangeSize());
  513. }
  514. void DxilMDHelper::LoadDxilResourceBase(const MDOperand &MDO, DxilResourceBase &R) {
  515. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  516. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  517. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  518. IFTBOOL(pTupleMD->getNumOperands() >= kDxilResourceBaseNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  519. R.SetID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseID)));
  520. Constant *GlobalSymbol = dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilResourceBaseVariable)));
  521. // For sm66+, global symbol will be mutated into handle type.
  522. // Read hlsl type and global symbol from bitcast.
  523. if (m_pSM->IsSM66Plus()) {
  524. // Before mutate, there's no bitcast. After GlobalSymbol changed into undef,
  525. // there's no bitcast too. Bitcast will only exist when global symbol is
  526. // mutated into handle and not changed into undef for lib linking.
  527. if (BitCastOperator *BCO = dyn_cast<BitCastOperator>(GlobalSymbol)) {
  528. GlobalSymbol = cast<Constant>(BCO->getOperand(0));
  529. R.SetHLSLType(BCO->getType());
  530. }
  531. }
  532. R.SetGlobalSymbol(GlobalSymbol);
  533. R.SetGlobalName(StringMDToString(pTupleMD->getOperand(kDxilResourceBaseName)));
  534. R.SetSpaceID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseSpaceID)));
  535. R.SetLowerBound(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseLowerBound)));
  536. R.SetRangeSize(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseRangeSize)));
  537. }
  538. MDTuple *DxilMDHelper::EmitDxilSRV(const DxilResource &SRV) {
  539. Metadata *MDVals[kDxilSRVNumFields];
  540. EmitDxilResourceBase(SRV, &MDVals[0]);
  541. // SRV-specific fields.
  542. MDVals[kDxilSRVShape ] = Uint32ToConstMD((unsigned)SRV.GetKind());
  543. MDVals[kDxilSRVSampleCount ] = Uint32ToConstMD(SRV.GetSampleCount());
  544. // Name-value list of extended properties.
  545. MDVals[kDxilSRVNameValueList] = nullptr;
  546. vector<Metadata *> MDExtraVals;
  547. m_ExtraPropertyHelper->EmitSRVProperties(SRV, MDExtraVals);
  548. if (!MDExtraVals.empty()) {
  549. MDVals[kDxilSRVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  550. }
  551. return MDNode::get(m_Ctx, MDVals);
  552. }
  553. void DxilMDHelper::LoadDxilSRV(const MDOperand &MDO, DxilResource &SRV) {
  554. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  555. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  556. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  557. IFTBOOL(pTupleMD->getNumOperands() == kDxilSRVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  558. SRV.SetRW(false);
  559. LoadDxilResourceBase(MDO, SRV);
  560. // SRV-specific fields.
  561. SRV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilSRVShape)));
  562. SRV.SetSampleCount(ConstMDToUint32(pTupleMD->getOperand(kDxilSRVSampleCount)));
  563. // Name-value list of extended properties.
  564. m_ExtraPropertyHelper->m_bExtraMetadata = false;
  565. m_ExtraPropertyHelper->LoadSRVProperties(pTupleMD->getOperand(kDxilSRVNameValueList), SRV);
  566. m_bExtraMetadata |= m_ExtraPropertyHelper->m_bExtraMetadata;
  567. }
  568. MDTuple *DxilMDHelper::EmitDxilUAV(const DxilResource &UAV) {
  569. Metadata *MDVals[kDxilUAVNumFields];
  570. EmitDxilResourceBase(UAV, &MDVals[0]);
  571. // UAV-specific fields.
  572. MDVals[kDxilUAVShape ] = Uint32ToConstMD((unsigned)UAV.GetKind());
  573. MDVals[kDxilUAVGloballyCoherent ] = BoolToConstMD(UAV.IsGloballyCoherent());
  574. MDVals[kDxilUAVCounter ] = BoolToConstMD(UAV.HasCounter());
  575. MDVals[kDxilUAVRasterizerOrderedView] = BoolToConstMD(UAV.IsROV());
  576. // Name-value list of extended properties.
  577. MDVals[kDxilUAVNameValueList ] = nullptr;
  578. vector<Metadata *> MDExtraVals;
  579. m_ExtraPropertyHelper->EmitUAVProperties(UAV, MDExtraVals);
  580. if (!MDExtraVals.empty()) {
  581. MDVals[kDxilUAVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  582. }
  583. return MDNode::get(m_Ctx, MDVals);
  584. }
  585. void DxilMDHelper::LoadDxilUAV(const MDOperand &MDO, DxilResource &UAV) {
  586. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  587. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  588. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  589. IFTBOOL(pTupleMD->getNumOperands() == kDxilUAVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  590. UAV.SetRW(true);
  591. LoadDxilResourceBase(MDO, UAV);
  592. // UAV-specific fields.
  593. UAV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilUAVShape)));
  594. UAV.SetGloballyCoherent(ConstMDToBool(pTupleMD->getOperand(kDxilUAVGloballyCoherent)));
  595. UAV.SetHasCounter(ConstMDToBool(pTupleMD->getOperand(kDxilUAVCounter)));
  596. UAV.SetROV(ConstMDToBool(pTupleMD->getOperand(kDxilUAVRasterizerOrderedView)));
  597. // Name-value list of extended properties.
  598. m_ExtraPropertyHelper->m_bExtraMetadata = false;
  599. m_ExtraPropertyHelper->LoadUAVProperties(pTupleMD->getOperand(kDxilUAVNameValueList), UAV);
  600. m_bExtraMetadata |= m_ExtraPropertyHelper->m_bExtraMetadata;
  601. }
  602. MDTuple *DxilMDHelper::EmitDxilCBuffer(const DxilCBuffer &CB) {
  603. Metadata *MDVals[kDxilCBufferNumFields];
  604. EmitDxilResourceBase(CB, &MDVals[0]);
  605. // CBuffer-specific fields.
  606. // CBuffer size in bytes.
  607. MDVals[kDxilCBufferSizeInBytes ] = Uint32ToConstMD(CB.GetSize());
  608. // Name-value list of extended properties.
  609. MDVals[kDxilCBufferNameValueList] = nullptr;
  610. vector<Metadata *> MDExtraVals;
  611. m_ExtraPropertyHelper->EmitCBufferProperties(CB, MDExtraVals);
  612. if (!MDExtraVals.empty()) {
  613. MDVals[kDxilCBufferNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  614. }
  615. return MDNode::get(m_Ctx, MDVals);
  616. }
  617. void DxilMDHelper::LoadDxilCBuffer(const MDOperand &MDO, DxilCBuffer &CB) {
  618. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  619. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  620. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  621. IFTBOOL(pTupleMD->getNumOperands() == kDxilCBufferNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  622. LoadDxilResourceBase(MDO, CB);
  623. // CBuffer-specific fields.
  624. CB.SetSize(ConstMDToUint32(pTupleMD->getOperand(kDxilCBufferSizeInBytes)));
  625. // Name-value list of extended properties.
  626. m_ExtraPropertyHelper->m_bExtraMetadata = false;
  627. m_ExtraPropertyHelper->LoadCBufferProperties(pTupleMD->getOperand(kDxilCBufferNameValueList), CB);
  628. m_bExtraMetadata |= m_ExtraPropertyHelper->m_bExtraMetadata;
  629. }
  630. void DxilMDHelper::EmitDxilTypeSystem(DxilTypeSystem &TypeSystem, vector<GlobalVariable*> &LLVMUsed) {
  631. auto &TypeMap = TypeSystem.GetStructAnnotationMap();
  632. vector<Metadata *> MDVals;
  633. MDVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemStructTag)); // Tag
  634. unsigned GVIdx = 0;
  635. for (auto it = TypeMap.begin(); it != TypeMap.end(); ++it, GVIdx++) {
  636. StructType *pStructType = const_cast<StructType *>(it->first);
  637. DxilStructAnnotation *pA = it->second.get();
  638. // Don't emit type annotation for empty struct.
  639. if (pA->IsEmptyStruct())
  640. continue;
  641. // Emit struct type field annotations.
  642. Metadata *pMD = EmitDxilStructAnnotation(*pA);
  643. MDVals.push_back(ValueAsMetadata::get(UndefValue::get(pStructType)));
  644. MDVals.push_back(pMD);
  645. }
  646. auto &FuncMap = TypeSystem.GetFunctionAnnotationMap();
  647. vector<Metadata *> MDFuncVals;
  648. MDFuncVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemFunctionTag)); // Tag
  649. for (auto it = FuncMap.begin(); it != FuncMap.end(); ++it) {
  650. DxilFunctionAnnotation *pA = it->second.get();
  651. MDFuncVals.push_back(ValueAsMetadata::get(const_cast<Function*>(pA->GetFunction())));
  652. // Emit function annotations.
  653. Metadata *pMD;
  654. pMD = EmitDxilFunctionAnnotation(*pA);
  655. MDFuncVals.push_back(pMD);
  656. }
  657. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  658. if (pDxilTypeAnnotationsMD != nullptr) {
  659. m_pModule->eraseNamedMetadata(pDxilTypeAnnotationsMD);
  660. }
  661. if (MDVals.size() > 1) {
  662. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  663. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDVals));
  664. }
  665. if (MDFuncVals.size() > 1) {
  666. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  667. if (pDxilTypeAnnotationsMD == nullptr)
  668. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  669. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDFuncVals));
  670. }
  671. }
  672. void DxilMDHelper::LoadDxilTypeSystemNode(const llvm::MDTuple &MDT,
  673. DxilTypeSystem &TypeSystem) {
  674. unsigned Tag = ConstMDToUint32(MDT.getOperand(0));
  675. if (Tag == kDxilTypeSystemStructTag) {
  676. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  677. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  678. Constant *pGV =
  679. dyn_cast<Constant>(ValueMDToValue(MDT.getOperand(i)));
  680. IFTBOOL(pGV != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  681. StructType *pGVType =
  682. dyn_cast<StructType>(pGV->getType());
  683. IFTBOOL(pGVType != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  684. DxilStructAnnotation *pSA = TypeSystem.AddStructAnnotation(pGVType);
  685. LoadDxilStructAnnotation(MDT.getOperand(i + 1), *pSA);
  686. }
  687. } else {
  688. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  689. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  690. Function *F = dyn_cast<Function>(ValueMDToValue(MDT.getOperand(i)));
  691. DxilFunctionAnnotation *pFA = TypeSystem.AddFunctionAnnotation(F);
  692. LoadDxilFunctionAnnotation(MDT.getOperand(i + 1), *pFA);
  693. }
  694. }
  695. }
  696. void DxilMDHelper::LoadDxilTypeSystem(DxilTypeSystem &TypeSystem) {
  697. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  698. if (pDxilTypeAnnotationsMD == nullptr)
  699. return;
  700. IFTBOOL(pDxilTypeAnnotationsMD->getNumOperands() <= 2, DXC_E_INCORRECT_DXIL_METADATA);
  701. for (unsigned i = 0; i < pDxilTypeAnnotationsMD->getNumOperands(); i++) {
  702. const MDTuple *pTupleMD = dyn_cast<MDTuple>(pDxilTypeAnnotationsMD->getOperand(i));
  703. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  704. LoadDxilTypeSystemNode(*pTupleMD, TypeSystem);
  705. }
  706. }
  707. void DxilMDHelper::EmitDxrPayloadAnnotations(DxilTypeSystem &TypeSystem) {
  708. auto &TypeMap = TypeSystem.GetPayloadAnnotationMap();
  709. vector<Metadata *> MDVals;
  710. MDVals.emplace_back(Uint32ToConstMD(kDxilPayloadAnnotationStructTag)); // Tag
  711. unsigned GVIdx = 0;
  712. for (auto it = TypeMap.begin(); it != TypeMap.end(); ++it, GVIdx++) {
  713. StructType *pStructType = const_cast<StructType *>(it->first);
  714. DxilPayloadAnnotation *pA = it->second.get();
  715. // Emit struct type field annotations.
  716. Metadata *pMD = EmitDxrPayloadStructAnnotation(*pA);
  717. MDVals.push_back(ValueAsMetadata::get(UndefValue::get(pStructType)));
  718. MDVals.push_back(pMD);
  719. }
  720. NamedMDNode *pDxrPayloadAnnotationsMD = m_pModule->getNamedMetadata(kDxilDxrPayloadAnnotationsMDName);
  721. if (pDxrPayloadAnnotationsMD != nullptr) {
  722. m_pModule->eraseNamedMetadata(pDxrPayloadAnnotationsMD);
  723. }
  724. if (MDVals.size() > 1) {
  725. pDxrPayloadAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilDxrPayloadAnnotationsMDName);
  726. pDxrPayloadAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDVals));
  727. }
  728. }
  729. Metadata *
  730. DxilMDHelper::EmitDxrPayloadStructAnnotation(const DxilPayloadAnnotation &SA) {
  731. vector<Metadata *> MDVals;
  732. MDVals.reserve(SA.GetNumFields());
  733. MDVals.resize(SA.GetNumFields());
  734. const StructType* STy = SA.GetStructType();
  735. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  736. MDVals[i] = EmitDxrPayloadFieldAnnotation(SA.GetFieldAnnotation(i), STy->getElementType(i));
  737. }
  738. return MDNode::get(m_Ctx, MDVals);
  739. }
  740. void DxilMDHelper::LoadDxrPayloadAccessQualifiers(const MDOperand &MDO,
  741. DxilPayloadFieldAnnotation &FA) {
  742. unsigned fieldBitmask = ConstMDToInt32(MDO);
  743. if (fieldBitmask & ~DXIL::PayloadAccessQualifierValidMask) {
  744. DXASSERT(false, "Unknown payload access qualifier bits set");
  745. m_bExtraMetadata = true;
  746. }
  747. fieldBitmask &= DXIL::PayloadAccessQualifierValidMask;
  748. FA.SetPayloadFieldQualifierMask(fieldBitmask);
  749. }
  750. void DxilMDHelper::LoadDxrPayloadFieldAnnoation(
  751. const MDOperand &MDO, DxilPayloadFieldAnnotation &FA) {
  752. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  753. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get()); // Tag-Value list.
  754. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  755. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  756. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  757. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(i));
  758. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  759. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  760. switch (Tag) {
  761. case kDxilPayloadFieldAnnotationAccessTag:
  762. LoadDxrPayloadAccessQualifiers(MDO, FA);
  763. break;
  764. default:
  765. DXASSERT(false, "Unknown payload field annotation tag");
  766. m_bExtraMetadata = true;
  767. break;
  768. }
  769. }
  770. }
  771. void DxilMDHelper::LoadDxrPayloadFieldAnnoations(const MDOperand &MDO,
  772. DxilPayloadAnnotation &SA) {
  773. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  774. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  775. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  776. IFTBOOL(pTupleMD->getNumOperands() == SA.GetNumFields(),
  777. DXC_E_INCORRECT_DXIL_METADATA);
  778. for (unsigned i = 0; i < SA.GetNumFields(); ++i) {
  779. LoadDxrPayloadFieldAnnoation(pTupleMD->getOperand(i), SA.GetFieldAnnotation(i));
  780. }
  781. }
  782. void DxilMDHelper::LoadDxrPayloadAnnotationNode(const llvm::MDTuple &MDT,
  783. DxilTypeSystem &TypeSystem) {
  784. unsigned Tag = ConstMDToUint32(MDT.getOperand(0));
  785. IFTBOOL(Tag == kDxilPayloadAnnotationStructTag, DXC_E_INCORRECT_DXIL_METADATA)
  786. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  787. Constant *pGV = dyn_cast<Constant>(ValueMDToValue(MDT.getOperand(1)));
  788. IFTBOOL(pGV != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  789. StructType *pGVType = dyn_cast<StructType>(pGV->getType());
  790. IFTBOOL(pGVType != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  791. // Check if this struct is already part of the DXIL Type System
  792. DxilPayloadAnnotation *pPA = TypeSystem.AddPayloadAnnotation(pGVType);
  793. LoadDxrPayloadFieldAnnoations(MDT.getOperand(2), *pPA);
  794. }
  795. void DxilMDHelper::LoadDxrPayloadAnnotations(DxilTypeSystem &TypeSystem) {
  796. NamedMDNode *pDxilPayloadAnnotationsMD =
  797. m_pModule->getNamedMetadata(kDxilDxrPayloadAnnotationsMDName);
  798. if (pDxilPayloadAnnotationsMD == nullptr)
  799. return;
  800. if (DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 6) < 0) {
  801. DXASSERT(false, "payload access qualifier emitted for dxil version < 1.6");
  802. m_bExtraMetadata = true;
  803. }
  804. DXASSERT(pDxilPayloadAnnotationsMD->getNumOperands() != 0, "empty metadata node?");
  805. for (unsigned i = 0; i < pDxilPayloadAnnotationsMD->getNumOperands(); i++) {
  806. const MDTuple *pTupleMD =
  807. dyn_cast<MDTuple>(pDxilPayloadAnnotationsMD->getOperand(i));
  808. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  809. LoadDxrPayloadAnnotationNode(*pTupleMD, TypeSystem);
  810. }
  811. }
  812. Metadata *DxilMDHelper::EmitDxilTemplateArgAnnotation(const DxilTemplateArgAnnotation &annotation) {
  813. SmallVector<Metadata *, 2> MDVals;
  814. if (annotation.IsType()) {
  815. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilTemplateArgTypeTag));
  816. MDVals.emplace_back(ValueAsMetadata::get(UndefValue::get(const_cast<Type*>(annotation.GetType()))));
  817. } else if (annotation.IsIntegral()) {
  818. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilTemplateArgIntegralTag));
  819. MDVals.emplace_back(Uint64ToConstMD((uint64_t)annotation.GetIntegral()));
  820. }
  821. return MDNode::get(m_Ctx, MDVals);
  822. }
  823. void DxilMDHelper::LoadDxilTemplateArgAnnotation(const llvm::MDOperand &MDO, DxilTemplateArgAnnotation &annotation) {
  824. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  825. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  826. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  827. IFTBOOL(pTupleMD->getNumOperands() >= 1, DXC_E_INCORRECT_DXIL_METADATA);
  828. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(0));
  829. switch (Tag) {
  830. case kDxilTemplateArgTypeTag: {
  831. IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
  832. Constant *C = dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilTemplateArgValue)));
  833. IFTBOOL(C != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  834. annotation.SetType(C->getType());
  835. } break;
  836. case kDxilTemplateArgIntegralTag:
  837. IFTBOOL(pTupleMD->getNumOperands() == 2, DXC_E_INCORRECT_DXIL_METADATA);
  838. annotation.SetIntegral((int64_t)ConstMDToUint64(pTupleMD->getOperand(kDxilTemplateArgValue)));
  839. break;
  840. default:
  841. DXASSERT(false, "Unknown template argument type tag.");
  842. m_bExtraMetadata = true;
  843. break;
  844. }
  845. }
  846. Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
  847. bool bSupportExtended = DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 5) >= 0;
  848. vector<Metadata *> MDVals;
  849. MDVals.reserve(SA.GetNumFields() + 2); // In case of extended 1.5 property list
  850. MDVals.resize(SA.GetNumFields() + 1);
  851. MDVals[0] = Uint32ToConstMD(SA.GetCBufferSize());
  852. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  853. MDVals[i+1] = EmitDxilFieldAnnotation(SA.GetFieldAnnotation(i));
  854. }
  855. // Only add template args if shader target requires validator version that supports them.
  856. if (bSupportExtended && SA.GetNumTemplateArgs()) {
  857. vector<Metadata *> MDTemplateArgs(SA.GetNumTemplateArgs());
  858. for (unsigned i = 0; i < SA.GetNumTemplateArgs(); ++i) {
  859. MDTemplateArgs[i] = EmitDxilTemplateArgAnnotation(SA.GetTemplateArgAnnotation(i));
  860. }
  861. SmallVector<Metadata *, 2> MDExtraVals;
  862. MDExtraVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilTemplateArgumentsTag));
  863. MDExtraVals.emplace_back(MDNode::get(m_Ctx, MDTemplateArgs));
  864. MDVals.emplace_back(MDNode::get(m_Ctx, MDExtraVals));
  865. }
  866. return MDNode::get(m_Ctx, MDVals);
  867. }
  868. void DxilMDHelper::LoadDxilStructAnnotation(const MDOperand &MDO, DxilStructAnnotation &SA) {
  869. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  870. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  871. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  872. if (pTupleMD->getNumOperands() == 1) {
  873. SA.MarkEmptyStruct();
  874. }
  875. if (pTupleMD->getNumOperands() == SA.GetNumFields()+2) {
  876. DXASSERT(DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 5) >= 0,
  877. "otherwise, template annotation emitted for dxil version < 1.5");
  878. // Load template args from extended operand
  879. const MDOperand &MDOExtra = pTupleMD->getOperand(SA.GetNumFields()+1);
  880. const MDTuple *pTupleMDExtra = dyn_cast_or_null<MDTuple>(MDOExtra.get());
  881. if(pTupleMDExtra) {
  882. for (unsigned i = 0; i < pTupleMDExtra->getNumOperands(); i += 2) {
  883. unsigned Tag = ConstMDToUint32(pTupleMDExtra->getOperand(i));
  884. const MDOperand &MDO = pTupleMDExtra->getOperand(i + 1);
  885. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  886. switch (Tag) {
  887. case kDxilTemplateArgumentsTag: {
  888. const MDTuple *pTupleTemplateArgs = dyn_cast_or_null<MDTuple>(pTupleMDExtra->getOperand(1).get());
  889. IFTBOOL(pTupleTemplateArgs, DXC_E_INCORRECT_DXIL_METADATA);
  890. SA.SetNumTemplateArgs(pTupleTemplateArgs->getNumOperands());
  891. for (unsigned i = 0; i < pTupleTemplateArgs->getNumOperands(); ++i) {
  892. LoadDxilTemplateArgAnnotation(pTupleTemplateArgs->getOperand(i), SA.GetTemplateArgAnnotation(i));
  893. }
  894. } break;
  895. default:
  896. DXASSERT(false, "unknown extended tag for struct annotation.");
  897. m_bExtraMetadata = true;
  898. break;
  899. }
  900. }
  901. }
  902. } else {
  903. IFTBOOL(pTupleMD->getNumOperands() == SA.GetNumFields()+1, DXC_E_INCORRECT_DXIL_METADATA);
  904. }
  905. SA.SetCBufferSize(ConstMDToUint32(pTupleMD->getOperand(0)));
  906. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  907. const MDOperand &MDO = pTupleMD->getOperand(i+1);
  908. DxilFieldAnnotation &FA = SA.GetFieldAnnotation(i);
  909. LoadDxilFieldAnnotation(MDO, FA);
  910. }
  911. }
  912. Metadata *
  913. DxilMDHelper::EmitDxilFunctionAnnotation(const DxilFunctionAnnotation &FA) {
  914. return EmitDxilParamAnnotations(FA);
  915. }
  916. void DxilMDHelper::LoadDxilFunctionAnnotation(const MDOperand &MDO,
  917. DxilFunctionAnnotation &FA) {
  918. LoadDxilParamAnnotations(MDO, FA);
  919. }
  920. llvm::Metadata *
  921. DxilMDHelper::EmitDxilParamAnnotations(const DxilFunctionAnnotation &FA) {
  922. vector<Metadata *> MDParamAnnotations(FA.GetNumParameters() + 1);
  923. MDParamAnnotations[0] = EmitDxilParamAnnotation(FA.GetRetTypeAnnotation());
  924. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  925. MDParamAnnotations[i + 1] =
  926. EmitDxilParamAnnotation(FA.GetParameterAnnotation(i));
  927. }
  928. return MDNode::get(m_Ctx, MDParamAnnotations);
  929. }
  930. void DxilMDHelper::LoadDxilParamAnnotations(const llvm::MDOperand &MDO,
  931. DxilFunctionAnnotation &FA) {
  932. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  933. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  934. IFTBOOL(pTupleMD->getNumOperands() == FA.GetNumParameters() + 1,
  935. DXC_E_INCORRECT_DXIL_METADATA);
  936. DxilParameterAnnotation &retTyAnnotation = FA.GetRetTypeAnnotation();
  937. LoadDxilParamAnnotation(pTupleMD->getOperand(0), retTyAnnotation);
  938. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  939. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  940. DxilParameterAnnotation &PA = FA.GetParameterAnnotation(i);
  941. LoadDxilParamAnnotation(MDO, PA);
  942. }
  943. }
  944. Metadata *
  945. DxilMDHelper::EmitDxilParamAnnotation(const DxilParameterAnnotation &PA) {
  946. vector<Metadata *> MDVals(3);
  947. MDVals[0] = Uint32ToConstMD(static_cast<unsigned>(PA.GetParamInputQual()));
  948. MDVals[1] = EmitDxilFieldAnnotation(PA);
  949. MDVals[2] = Uint32VectorToConstMDTuple(PA.GetSemanticIndexVec());
  950. return MDNode::get(m_Ctx, MDVals);
  951. }
  952. void DxilMDHelper::LoadDxilParamAnnotation(const MDOperand &MDO,
  953. DxilParameterAnnotation &PA) {
  954. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  955. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  956. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  957. IFTBOOL(pTupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  958. PA.SetParamInputQual(static_cast<DxilParamInputQual>(
  959. ConstMDToUint32(pTupleMD->getOperand(0))));
  960. LoadDxilFieldAnnotation(pTupleMD->getOperand(1), PA);
  961. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(2));
  962. vector<unsigned> SemanticIndexVector;
  963. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  964. PA.SetSemanticIndexVec(SemanticIndexVector);
  965. }
  966. Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
  967. vector<Metadata *> MDVals; // Tag-Value list.
  968. if (FA.HasFieldName()) {
  969. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationFieldNameTag));
  970. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetFieldName()));
  971. }
  972. if (FA.IsPrecise()) {
  973. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationPreciseTag)); // Tag
  974. MDVals.emplace_back(BoolToConstMD(true)); // Value
  975. }
  976. if (FA.HasMatrixAnnotation()) {
  977. const DxilMatrixAnnotation &MA = FA.GetMatrixAnnotation();
  978. Metadata *MatrixMD[3];
  979. MatrixMD[0] = Uint32ToConstMD(MA.Rows);
  980. MatrixMD[1] = Uint32ToConstMD(MA.Cols);
  981. MatrixMD[2] = Uint32ToConstMD((unsigned)MA.Orientation);
  982. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationMatrixTag));
  983. MDVals.emplace_back(MDNode::get(m_Ctx, MatrixMD));
  984. }
  985. if (FA.HasCBufferOffset()) {
  986. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBufferOffsetTag));
  987. MDVals.emplace_back(Uint32ToConstMD(FA.GetCBufferOffset()));
  988. }
  989. if (FA.HasSemanticString()) {
  990. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationSemanticStringTag));
  991. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetSemanticString()));
  992. }
  993. if (FA.HasInterpolationMode()) {
  994. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationInterpolationModeTag));
  995. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetInterpolationMode().GetKind()));
  996. }
  997. if (FA.HasCompType()) {
  998. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
  999. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
  1000. }
  1001. if (FA.IsCBVarUsed() &&
  1002. DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 5) >= 0) {
  1003. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBUsedTag));
  1004. MDVals.emplace_back(BoolToConstMD(true));
  1005. }
  1006. return MDNode::get(m_Ctx, MDVals);
  1007. }
  1008. void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnotation &FA) {
  1009. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1010. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1011. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1012. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1013. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1014. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(i));
  1015. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1016. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1017. switch (Tag) {
  1018. case kDxilFieldAnnotationPreciseTag:
  1019. FA.SetPrecise(ConstMDToBool(MDO));
  1020. break;
  1021. case kDxilFieldAnnotationMatrixTag: {
  1022. DxilMatrixAnnotation MA;
  1023. const MDTuple *pMATupleMD = dyn_cast<MDTuple>(MDO.get());
  1024. IFTBOOL(pMATupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1025. IFTBOOL(pMATupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  1026. MA.Rows = ConstMDToUint32(pMATupleMD->getOperand(0));
  1027. MA.Cols = ConstMDToUint32(pMATupleMD->getOperand(1));
  1028. MA.Orientation = (MatrixOrientation)ConstMDToUint32(pMATupleMD->getOperand(2));
  1029. FA.SetMatrixAnnotation(MA);
  1030. } break;
  1031. case kDxilFieldAnnotationCBufferOffsetTag:
  1032. FA.SetCBufferOffset(ConstMDToUint32(MDO));
  1033. break;
  1034. case kDxilFieldAnnotationSemanticStringTag:
  1035. FA.SetSemanticString(StringMDToString(MDO));
  1036. break;
  1037. case kDxilFieldAnnotationInterpolationModeTag:
  1038. FA.SetInterpolationMode(InterpolationMode((InterpolationMode::Kind)ConstMDToUint32(MDO)));
  1039. break;
  1040. case kDxilFieldAnnotationFieldNameTag:
  1041. FA.SetFieldName(StringMDToString(MDO));
  1042. break;
  1043. case kDxilFieldAnnotationCompTypeTag:
  1044. FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
  1045. break;
  1046. case kDxilFieldAnnotationCBUsedTag:
  1047. FA.SetCBVarUsed(ConstMDToBool(MDO));
  1048. break;
  1049. default:
  1050. DXASSERT(false, "Unknown extended shader properties tag");
  1051. m_bExtraMetadata = true;
  1052. break;
  1053. }
  1054. }
  1055. }
  1056. Metadata *
  1057. DxilMDHelper::EmitDxrPayloadFieldAnnotation(const DxilPayloadFieldAnnotation &FA, Type* fieldType) {
  1058. vector<Metadata *> MDVals; // Tag-Value list.
  1059. MDVals.emplace_back(Uint32ToConstMD(kDxilPayloadFieldAnnotationAccessTag));
  1060. auto mask = FA.GetPayloadFieldQualifierMask();
  1061. MDVals.emplace_back(Uint32ToConstMD(mask));
  1062. return MDNode::get(m_Ctx, MDVals);
  1063. }
  1064. const Function *DxilMDHelper::LoadDxilFunctionProps(const MDTuple *pProps,
  1065. hlsl::DxilFunctionProps *props) {
  1066. unsigned idx = 0;
  1067. const Function *F = dyn_cast<Function>(
  1068. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  1069. DXIL::ShaderKind shaderKind =
  1070. static_cast<DXIL::ShaderKind>(ConstMDToUint32(pProps->getOperand(idx++)));
  1071. bool bRayAttributes = false;
  1072. props->shaderKind = shaderKind;
  1073. switch (shaderKind) {
  1074. case DXIL::ShaderKind::Compute:
  1075. props->ShaderProps.CS.numThreads[0] =
  1076. ConstMDToUint32(pProps->getOperand(idx++));
  1077. props->ShaderProps.CS.numThreads[1] =
  1078. ConstMDToUint32(pProps->getOperand(idx++));
  1079. props->ShaderProps.CS.numThreads[2] =
  1080. ConstMDToUint32(pProps->getOperand(idx++));
  1081. break;
  1082. case DXIL::ShaderKind::Geometry:
  1083. props->ShaderProps.GS.inputPrimitive =
  1084. (DXIL::InputPrimitive)ConstMDToUint32(pProps->getOperand(idx++));
  1085. props->ShaderProps.GS.maxVertexCount =
  1086. ConstMDToUint32(pProps->getOperand(idx++));
  1087. props->ShaderProps.GS.instanceCount =
  1088. ConstMDToUint32(pProps->getOperand(idx++));
  1089. for (size_t i = 0;
  1090. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  1091. props->ShaderProps.GS.streamPrimitiveTopologies[i] =
  1092. (DXIL::PrimitiveTopology)ConstMDToUint32(pProps->getOperand(idx++));
  1093. break;
  1094. case DXIL::ShaderKind::Hull:
  1095. props->ShaderProps.HS.patchConstantFunc = dyn_cast<Function>(
  1096. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  1097. props->ShaderProps.HS.domain =
  1098. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  1099. props->ShaderProps.HS.partition =
  1100. (DXIL::TessellatorPartitioning)ConstMDToUint32(
  1101. pProps->getOperand(idx++));
  1102. props->ShaderProps.HS.outputPrimitive =
  1103. (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(
  1104. pProps->getOperand(idx++));
  1105. props->ShaderProps.HS.inputControlPoints =
  1106. ConstMDToUint32(pProps->getOperand(idx++));
  1107. props->ShaderProps.HS.outputControlPoints =
  1108. ConstMDToUint32(pProps->getOperand(idx++));
  1109. props->ShaderProps.HS.maxTessFactor =
  1110. ConstMDToFloat(pProps->getOperand(idx++));
  1111. break;
  1112. case DXIL::ShaderKind::Domain:
  1113. props->ShaderProps.DS.domain =
  1114. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  1115. props->ShaderProps.DS.inputControlPoints =
  1116. ConstMDToUint32(pProps->getOperand(idx++));
  1117. break;
  1118. case DXIL::ShaderKind::Pixel:
  1119. props->ShaderProps.PS.EarlyDepthStencil =
  1120. ConstMDToUint32(pProps->getOperand(idx++));
  1121. break;
  1122. case DXIL::ShaderKind::AnyHit:
  1123. case DXIL::ShaderKind::ClosestHit:
  1124. bRayAttributes = true;
  1125. case DXIL::ShaderKind::Miss:
  1126. case DXIL::ShaderKind::Callable:
  1127. // payload/params unioned and first:
  1128. props->ShaderProps.Ray.payloadSizeInBytes =
  1129. ConstMDToUint32(pProps->getOperand(idx++));
  1130. if (bRayAttributes)
  1131. props->ShaderProps.Ray.attributeSizeInBytes =
  1132. ConstMDToUint32(pProps->getOperand(idx++));
  1133. break;
  1134. case DXIL::ShaderKind::Mesh:
  1135. props->ShaderProps.MS.numThreads[0] =
  1136. ConstMDToUint32(pProps->getOperand(idx++));
  1137. props->ShaderProps.MS.numThreads[1] =
  1138. ConstMDToUint32(pProps->getOperand(idx++));
  1139. props->ShaderProps.MS.numThreads[2] =
  1140. ConstMDToUint32(pProps->getOperand(idx++));
  1141. props->ShaderProps.MS.maxVertexCount =
  1142. ConstMDToUint32(pProps->getOperand(idx++));
  1143. props->ShaderProps.MS.maxPrimitiveCount =
  1144. ConstMDToUint32(pProps->getOperand(idx++));
  1145. props->ShaderProps.MS.outputTopology =
  1146. (DXIL::MeshOutputTopology)ConstMDToUint32(pProps->getOperand(idx++));
  1147. props->ShaderProps.MS.payloadSizeInBytes =
  1148. ConstMDToUint32(pProps->getOperand(idx++));
  1149. break;
  1150. case DXIL::ShaderKind::Amplification:
  1151. props->ShaderProps.AS.numThreads[0] =
  1152. ConstMDToUint32(pProps->getOperand(idx++));
  1153. props->ShaderProps.AS.numThreads[1] =
  1154. ConstMDToUint32(pProps->getOperand(idx++));
  1155. props->ShaderProps.AS.numThreads[2] =
  1156. ConstMDToUint32(pProps->getOperand(idx++));
  1157. props->ShaderProps.AS.payloadSizeInBytes =
  1158. ConstMDToUint32(pProps->getOperand(idx++));
  1159. break;
  1160. default:
  1161. break;
  1162. }
  1163. return F;
  1164. }
  1165. MDTuple *DxilMDHelper::EmitDxilEntryProperties(uint64_t rawShaderFlag,
  1166. const DxilFunctionProps &props,
  1167. unsigned autoBindingSpace) {
  1168. vector<Metadata *> MDVals;
  1169. // DXIL shader flags.
  1170. if (props.IsPS()) {
  1171. if (props.ShaderProps.PS.EarlyDepthStencil) {
  1172. ShaderFlags flags;
  1173. flags.SetShaderFlagsRaw(rawShaderFlag);
  1174. flags.SetForceEarlyDepthStencil(true);
  1175. rawShaderFlag = flags.GetShaderFlagsRaw();
  1176. }
  1177. }
  1178. if (rawShaderFlag != 0) {
  1179. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderFlagsTag));
  1180. MDVals.emplace_back(Uint64ToConstMD(rawShaderFlag));
  1181. }
  1182. // Add shader kind for lib entrys.
  1183. if (m_pSM->IsLib() && props.shaderKind != DXIL::ShaderKind::Library) {
  1184. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderKindTag));
  1185. MDVals.emplace_back(
  1186. Uint32ToConstMD(static_cast<unsigned>(props.shaderKind)));
  1187. }
  1188. switch (props.shaderKind) {
  1189. // Compute shader.
  1190. case DXIL::ShaderKind::Compute: {
  1191. auto &CS = props.ShaderProps.CS;
  1192. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  1193. vector<Metadata *> NumThreadVals;
  1194. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[0]));
  1195. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[1]));
  1196. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[2]));
  1197. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  1198. if (props.waveSize != 0) {
  1199. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilWaveSizeTag));
  1200. vector<Metadata *> WaveSizeVal;
  1201. WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveSize));
  1202. MDVals.emplace_back(MDNode::get(m_Ctx, WaveSizeVal));
  1203. }
  1204. } break;
  1205. // Geometry shader.
  1206. case DXIL::ShaderKind::Geometry: {
  1207. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  1208. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  1209. unsigned activeStreamMask = 0;
  1210. for (size_t i = 0;
  1211. i < _countof(props.ShaderProps.GS.streamPrimitiveTopologies); ++i) {
  1212. if (props.ShaderProps.GS.streamPrimitiveTopologies[i] !=
  1213. DXIL::PrimitiveTopology::Undefined) {
  1214. activeStreamMask |= 1 << i;
  1215. DXASSERT_NOMSG(topo == DXIL::PrimitiveTopology::Undefined ||
  1216. topo ==
  1217. props.ShaderProps.GS.streamPrimitiveTopologies[i]);
  1218. topo = props.ShaderProps.GS.streamPrimitiveTopologies[i];
  1219. }
  1220. }
  1221. MDTuple *pMDTuple =
  1222. EmitDxilGSState(props.ShaderProps.GS.inputPrimitive,
  1223. props.ShaderProps.GS.maxVertexCount, activeStreamMask,
  1224. topo, props.ShaderProps.GS.instanceCount);
  1225. MDVals.emplace_back(pMDTuple);
  1226. } break;
  1227. // Domain shader.
  1228. case DXIL::ShaderKind::Domain: {
  1229. auto &DS = props.ShaderProps.DS;
  1230. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  1231. MDTuple *pMDTuple = EmitDxilDSState(DS.domain, DS.inputControlPoints);
  1232. MDVals.emplace_back(pMDTuple);
  1233. } break;
  1234. // Hull shader.
  1235. case DXIL::ShaderKind::Hull: {
  1236. auto &HS = props.ShaderProps.HS;
  1237. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  1238. MDTuple *pMDTuple = EmitDxilHSState(
  1239. HS.patchConstantFunc, HS.inputControlPoints, HS.outputControlPoints,
  1240. HS.domain, HS.partition, HS.outputPrimitive, HS.maxTessFactor);
  1241. MDVals.emplace_back(pMDTuple);
  1242. } break;
  1243. // Raytracing.
  1244. case DXIL::ShaderKind::AnyHit:
  1245. case DXIL::ShaderKind::ClosestHit: {
  1246. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  1247. MDVals.emplace_back(
  1248. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  1249. MDVals.emplace_back(Uint32ToConstMD(kDxilRayAttribSizeTag));
  1250. MDVals.emplace_back(
  1251. Uint32ToConstMD(props.ShaderProps.Ray.attributeSizeInBytes));
  1252. } break;
  1253. case DXIL::ShaderKind::Miss:
  1254. case DXIL::ShaderKind::Callable: {
  1255. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  1256. MDVals.emplace_back(
  1257. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  1258. } break;
  1259. case DXIL::ShaderKind::Mesh: {
  1260. auto &MS = props.ShaderProps.MS;
  1261. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilMSStateTag));
  1262. MDTuple *pMDTuple = EmitDxilMSState(MS.numThreads,
  1263. MS.maxVertexCount,
  1264. MS.maxPrimitiveCount,
  1265. MS.outputTopology,
  1266. MS.payloadSizeInBytes);
  1267. MDVals.emplace_back(pMDTuple);
  1268. } break;
  1269. case DXIL::ShaderKind::Amplification: {
  1270. auto &AS = props.ShaderProps.AS;
  1271. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilASStateTag));
  1272. MDTuple *pMDTuple = EmitDxilASState(AS.numThreads, AS.payloadSizeInBytes);
  1273. MDVals.emplace_back(pMDTuple);
  1274. } break;
  1275. default:
  1276. break;
  1277. }
  1278. if (autoBindingSpace != UINT_MAX && m_pSM->IsSMAtLeast(6, 3)) {
  1279. MDVals.emplace_back(Uint32ToConstMD(kDxilAutoBindingSpaceTag));
  1280. MDVals.emplace_back(
  1281. MDNode::get(m_Ctx, {Uint32ToConstMD(autoBindingSpace)}));
  1282. }
  1283. if (!MDVals.empty())
  1284. return MDNode::get(m_Ctx, MDVals);
  1285. else
  1286. return nullptr;
  1287. }
  1288. void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO,
  1289. uint64_t &rawShaderFlag,
  1290. DxilFunctionProps &props,
  1291. uint32_t &autoBindingSpace) {
  1292. if (MDO.get() == nullptr)
  1293. return;
  1294. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1295. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1296. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0,
  1297. DXC_E_INCORRECT_DXIL_METADATA);
  1298. bool bEarlyDepth = false;
  1299. if (!m_pSM->IsLib()) {
  1300. props.shaderKind = m_pSM->GetKind();
  1301. } else {
  1302. props.shaderKind = DXIL::ShaderKind::Library;
  1303. }
  1304. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  1305. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  1306. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  1307. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1308. switch (Tag) {
  1309. case DxilMDHelper::kDxilShaderFlagsTag: {
  1310. rawShaderFlag = ConstMDToUint64(MDO);
  1311. ShaderFlags flags;
  1312. flags.SetShaderFlagsRaw(rawShaderFlag);
  1313. bEarlyDepth = flags.GetForceEarlyDepthStencil();
  1314. } break;
  1315. case DxilMDHelper::kDxilNumThreadsTag: {
  1316. DXASSERT(props.IsCS(), "else invalid shader kind");
  1317. auto &CS = props.ShaderProps.CS;
  1318. MDNode *pNode = cast<MDNode>(MDO.get());
  1319. CS.numThreads[0] = ConstMDToUint32(pNode->getOperand(0));
  1320. CS.numThreads[1] = ConstMDToUint32(pNode->getOperand(1));
  1321. CS.numThreads[2] = ConstMDToUint32(pNode->getOperand(2));
  1322. } break;
  1323. case DxilMDHelper::kDxilGSStateTag: {
  1324. DXASSERT(props.IsGS(), "else invalid shader kind");
  1325. auto &GS = props.ShaderProps.GS;
  1326. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  1327. unsigned activeStreamMask;
  1328. LoadDxilGSState(MDO, GS.inputPrimitive, GS.maxVertexCount,
  1329. activeStreamMask, topo, GS.instanceCount);
  1330. if (topo != DXIL::PrimitiveTopology::Undefined) {
  1331. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  1332. unsigned mask = 1 << i;
  1333. if (activeStreamMask & mask) {
  1334. GS.streamPrimitiveTopologies[i] = topo;
  1335. } else {
  1336. GS.streamPrimitiveTopologies[i] =
  1337. DXIL::PrimitiveTopology::Undefined;
  1338. }
  1339. }
  1340. }
  1341. } break;
  1342. case DxilMDHelper::kDxilDSStateTag: {
  1343. DXASSERT(props.IsDS(), "else invalid shader kind");
  1344. auto &DS = props.ShaderProps.DS;
  1345. LoadDxilDSState(MDO, DS.domain, DS.inputControlPoints);
  1346. } break;
  1347. case DxilMDHelper::kDxilHSStateTag: {
  1348. DXASSERT(props.IsHS(), "else invalid shader kind");
  1349. auto &HS = props.ShaderProps.HS;
  1350. LoadDxilHSState(MDO, HS.patchConstantFunc, HS.inputControlPoints,
  1351. HS.outputControlPoints, HS.domain, HS.partition,
  1352. HS.outputPrimitive, HS.maxTessFactor);
  1353. } break;
  1354. case DxilMDHelper::kDxilAutoBindingSpaceTag: {
  1355. MDNode *pNode = cast<MDNode>(MDO.get());
  1356. autoBindingSpace = ConstMDToUint32(pNode->getOperand(0));
  1357. break;
  1358. }
  1359. case DxilMDHelper::kDxilRayPayloadSizeTag: {
  1360. DXASSERT(props.IsAnyHit() || props.IsClosestHit() || props.IsMiss() ||
  1361. props.IsCallable(),
  1362. "else invalid shader kind");
  1363. props.ShaderProps.Ray.payloadSizeInBytes =
  1364. ConstMDToUint32(MDO);
  1365. } break;
  1366. case DxilMDHelper::kDxilRayAttribSizeTag: {
  1367. DXASSERT(props.IsAnyHit() || props.IsClosestHit(),
  1368. "else invalid shader kind");
  1369. props.ShaderProps.Ray.attributeSizeInBytes =
  1370. ConstMDToUint32(MDO);
  1371. } break;
  1372. case DxilMDHelper::kDxilShaderKindTag: {
  1373. DXIL::ShaderKind kind =
  1374. static_cast<DXIL::ShaderKind>(ConstMDToUint32(MDO));
  1375. DXASSERT(props.shaderKind == DXIL::ShaderKind::Library,
  1376. "else invalid shader kind");
  1377. props.shaderKind = kind;
  1378. } break;
  1379. case DxilMDHelper::kDxilMSStateTag: {
  1380. DXASSERT(props.IsMS(), "else invalid shader kind");
  1381. auto &MS = props.ShaderProps.MS;
  1382. LoadDxilMSState(MDO, MS.numThreads, MS.maxVertexCount,
  1383. MS.maxPrimitiveCount, MS.outputTopology,
  1384. MS.payloadSizeInBytes);
  1385. } break;
  1386. case DxilMDHelper::kDxilASStateTag: {
  1387. DXASSERT(props.IsAS(), "else invalid shader kind");
  1388. auto &AS = props.ShaderProps.AS;
  1389. LoadDxilASState(MDO, AS.numThreads, AS.payloadSizeInBytes);
  1390. } break;
  1391. case DxilMDHelper::kDxilWaveSizeTag: {
  1392. DXASSERT(props.IsCS(), "else invalid shader kind");
  1393. MDNode *pNode = cast<MDNode>(MDO.get());
  1394. props.waveSize = ConstMDToUint32(pNode->getOperand(0));
  1395. } break;
  1396. default:
  1397. DXASSERT(false, "Unknown extended shader properties tag");
  1398. m_bExtraMetadata = true;
  1399. break;
  1400. }
  1401. }
  1402. if (bEarlyDepth) {
  1403. DXASSERT(props.IsPS(), "else invalid shader kind");
  1404. props.ShaderProps.PS.EarlyDepthStencil = true;
  1405. }
  1406. }
  1407. MDTuple *
  1408. DxilMDHelper::EmitDxilFunctionProps(const hlsl::DxilFunctionProps *props,
  1409. const Function *F) {
  1410. bool bRayAttributes = false;
  1411. Metadata *MDVals[30];
  1412. std::fill(MDVals, MDVals + _countof(MDVals), nullptr);
  1413. unsigned valIdx = 0;
  1414. MDVals[valIdx++] = ValueAsMetadata::get(const_cast<Function*>(F));
  1415. MDVals[valIdx++] = Uint32ToConstMD(static_cast<unsigned>(props->shaderKind));
  1416. switch (props->shaderKind) {
  1417. case DXIL::ShaderKind::Compute:
  1418. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[0]);
  1419. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[1]);
  1420. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[2]);
  1421. break;
  1422. case DXIL::ShaderKind::Geometry:
  1423. MDVals[valIdx++] =
  1424. Uint8ToConstMD((uint8_t)props->ShaderProps.GS.inputPrimitive);
  1425. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.maxVertexCount);
  1426. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.instanceCount);
  1427. for (size_t i = 0;
  1428. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  1429. MDVals[valIdx++] = Uint8ToConstMD(
  1430. (uint8_t)props->ShaderProps.GS.streamPrimitiveTopologies[i]);
  1431. break;
  1432. case DXIL::ShaderKind::Hull:
  1433. MDVals[valIdx++] =
  1434. ValueAsMetadata::get(props->ShaderProps.HS.patchConstantFunc);
  1435. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.domain);
  1436. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.partition);
  1437. MDVals[valIdx++] =
  1438. Uint8ToConstMD((uint8_t)props->ShaderProps.HS.outputPrimitive);
  1439. MDVals[valIdx++] =
  1440. Uint32ToConstMD(props->ShaderProps.HS.inputControlPoints);
  1441. MDVals[valIdx++] =
  1442. Uint32ToConstMD(props->ShaderProps.HS.outputControlPoints);
  1443. MDVals[valIdx++] = FloatToConstMD(props->ShaderProps.HS.maxTessFactor);
  1444. break;
  1445. case DXIL::ShaderKind::Domain:
  1446. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.DS.domain);
  1447. MDVals[valIdx++] =
  1448. Uint32ToConstMD(props->ShaderProps.DS.inputControlPoints);
  1449. break;
  1450. case DXIL::ShaderKind::Pixel:
  1451. MDVals[valIdx++] = BoolToConstMD(props->ShaderProps.PS.EarlyDepthStencil);
  1452. break;
  1453. case DXIL::ShaderKind::AnyHit:
  1454. case DXIL::ShaderKind::ClosestHit:
  1455. bRayAttributes = true;
  1456. case DXIL::ShaderKind::Miss:
  1457. case DXIL::ShaderKind::Callable:
  1458. // payload/params unioned and first:
  1459. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.payloadSizeInBytes);
  1460. if (bRayAttributes)
  1461. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.attributeSizeInBytes);
  1462. break;
  1463. case DXIL::ShaderKind::Mesh:
  1464. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.numThreads[0]);
  1465. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.numThreads[1]);
  1466. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.numThreads[2]);
  1467. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.maxVertexCount);
  1468. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.maxPrimitiveCount);
  1469. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.MS.outputTopology);
  1470. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.MS.payloadSizeInBytes);
  1471. break;
  1472. case DXIL::ShaderKind::Amplification:
  1473. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.AS.numThreads[0]);
  1474. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.AS.numThreads[1]);
  1475. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.AS.numThreads[2]);
  1476. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.AS.payloadSizeInBytes);
  1477. break;
  1478. default:
  1479. break;
  1480. }
  1481. return MDTuple::get(m_Ctx, ArrayRef<llvm::Metadata *>(MDVals, valIdx));
  1482. }
  1483. void DxilMDHelper::EmitDxilViewIdState(std::vector<unsigned> &SerializedState) {
  1484. const vector<unsigned> &Data = SerializedState;
  1485. // If all UINTs are zero, do not emit ViewIdState.
  1486. if (!std::any_of(Data.begin(), Data.end(), [](unsigned e){return e!=0;}))
  1487. return;
  1488. Constant *V = ConstantDataArray::get(m_Ctx, ArrayRef<uint32_t>(Data));
  1489. NamedMDNode *pViewIdNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1490. IFTBOOL(pViewIdNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1491. pViewIdNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilViewIdStateMDName);
  1492. pViewIdNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  1493. }
  1494. void DxilMDHelper::LoadDxilViewIdState(std::vector<unsigned> &SerializedState) {
  1495. NamedMDNode *pViewIdStateNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1496. if(!pViewIdStateNamedMD)
  1497. return;
  1498. IFTBOOL(pViewIdStateNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1499. MDNode *pNode = pViewIdStateNamedMD->getOperand(0);
  1500. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1501. const MDOperand &MDO = pNode->getOperand(0);
  1502. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  1503. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1504. if (isa<ConstantAggregateZero>(pMetaData->getValue()))
  1505. return;
  1506. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pMetaData->getValue());
  1507. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1508. IFTBOOL(pData->getElementType() == Type::getInt32Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  1509. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  1510. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1511. SerializedState.clear();
  1512. unsigned size = (unsigned)pData->getRawDataValues().size() / 4;
  1513. SerializedState.resize(size);
  1514. const unsigned *Ptr = (const unsigned *)pData->getRawDataValues().begin();
  1515. memcpy(SerializedState.data(), Ptr, size * sizeof(unsigned));
  1516. }
  1517. MDNode *DxilMDHelper::EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<DXIL::ControlFlowHint> &hints) {
  1518. SmallVector<Metadata *, 4> Args;
  1519. // Reserve operand 0 for self reference.
  1520. auto TempNode = MDNode::getTemporary(Ctx, None);
  1521. Args.emplace_back(TempNode.get());
  1522. Args.emplace_back(MDString::get(Ctx, kDxilControlFlowHintMDName));
  1523. for (DXIL::ControlFlowHint &hint : hints)
  1524. Args.emplace_back(Uint32ToConstMD(static_cast<unsigned>(hint), Ctx));
  1525. MDNode *hintsNode = MDNode::get(Ctx, Args);
  1526. // Set the first operand to itself.
  1527. hintsNode->replaceOperandWith(0, hintsNode);
  1528. return hintsNode;
  1529. }
  1530. unsigned DxilMDHelper::GetControlFlowHintMask(const Instruction *I) {
  1531. // Check that there are control hint to use
  1532. // branch.
  1533. MDNode *MD = I->getMetadata(hlsl::DxilMDHelper::kDxilControlFlowHintMDName);
  1534. if (!MD)
  1535. return 0;
  1536. if (MD->getNumOperands() < 3)
  1537. return 0;
  1538. unsigned mask = 0;
  1539. for (unsigned i = 2; i < MD->getNumOperands(); i++) {
  1540. Metadata *Op = MD->getOperand(2).get();
  1541. auto ConstOp = cast<ConstantAsMetadata>(Op);
  1542. unsigned hint = ConstOp->getValue()->getUniqueInteger().getLimitedValue();
  1543. mask |= 1 << hint;
  1544. }
  1545. return mask;
  1546. }
  1547. bool DxilMDHelper::HasControlFlowHintToPreventFlatten(
  1548. const llvm::Instruction *I) {
  1549. unsigned mask = GetControlFlowHintMask(I);
  1550. const unsigned BranchMask =
  1551. 1 << (unsigned)(DXIL::ControlFlowHint::Branch) |
  1552. 1 << (unsigned)(DXIL::ControlFlowHint::Call) |
  1553. 1 << (unsigned)(DXIL::ControlFlowHint::ForceCase);
  1554. return mask & BranchMask;
  1555. }
  1556. void DxilMDHelper::EmitSubobjects(const DxilSubobjects &Subobjects) {
  1557. NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
  1558. IFTBOOL(pSubobjectsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1559. pSubobjectsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilSubobjectsMDName);
  1560. const auto &objMap = Subobjects.GetSubobjects();
  1561. for (auto &it : objMap)
  1562. pSubobjectsNamedMD->addOperand(cast<MDNode>(EmitSubobject(*it.second)));
  1563. }
  1564. void DxilMDHelper::LoadSubobjects(DxilSubobjects &Subobjects) {
  1565. NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
  1566. if (!pSubobjectsNamedMD)
  1567. return;
  1568. for (unsigned i = 0; i < pSubobjectsNamedMD->getNumOperands(); ++i)
  1569. LoadSubobject(*pSubobjectsNamedMD->getOperand(i), Subobjects);
  1570. }
  1571. Metadata *DxilMDHelper::EmitSubobject(const DxilSubobject &obj) {
  1572. SmallVector<Metadata *, 6> Args;
  1573. Args.emplace_back(MDString::get(m_Ctx, obj.GetName()));
  1574. Args.emplace_back(Uint32ToConstMD((unsigned)obj.GetKind()));
  1575. bool bLocalRS = false;
  1576. IFTBOOL(DXIL::IsValidSubobjectKind(obj.GetKind()), DXC_E_INCORRECT_DXIL_METADATA);
  1577. switch (obj.GetKind()) {
  1578. case DXIL::SubobjectKind::StateObjectConfig: {
  1579. uint32_t Flags;
  1580. IFTBOOL(obj.GetStateObjectConfig(Flags),
  1581. DXC_E_INCORRECT_DXIL_METADATA);
  1582. Args.emplace_back(Uint32ToConstMD((unsigned)Flags));
  1583. break;
  1584. }
  1585. case DXIL::SubobjectKind::LocalRootSignature:
  1586. bLocalRS = true;
  1587. __fallthrough;
  1588. case DXIL::SubobjectKind::GlobalRootSignature: {
  1589. const char * Text;
  1590. const void * Data;
  1591. uint32_t Size;
  1592. IFTBOOL(obj.GetRootSignature(bLocalRS, Data, Size, &Text),
  1593. DXC_E_INCORRECT_DXIL_METADATA);
  1594. Constant *V = ConstantDataArray::get(m_Ctx,
  1595. ArrayRef<uint8_t>((const uint8_t *)Data, Size));
  1596. Args.emplace_back(MDNode::get(m_Ctx, { ConstantAsMetadata::get(V) }));
  1597. Args.emplace_back(MDString::get(m_Ctx, Text));
  1598. break;
  1599. }
  1600. case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
  1601. StringRef Subobj;
  1602. const char * const * Exports;
  1603. uint32_t NumExports;
  1604. IFTBOOL(obj.GetSubobjectToExportsAssociation(Subobj, Exports, NumExports),
  1605. DXC_E_INCORRECT_DXIL_METADATA);
  1606. SmallVector<Metadata *, 4> strArgs;
  1607. for (unsigned i = 0; i < NumExports; ++i) {
  1608. strArgs.emplace_back(MDString::get(m_Ctx, Exports[i]));
  1609. }
  1610. Args.emplace_back(MDString::get(m_Ctx, Subobj));
  1611. Args.emplace_back(MDNode::get(m_Ctx, strArgs));
  1612. break;
  1613. }
  1614. case DXIL::SubobjectKind::RaytracingShaderConfig: {
  1615. uint32_t MaxPayloadSizeInBytes;
  1616. uint32_t MaxAttributeSizeInBytes;
  1617. IFTBOOL(obj.GetRaytracingShaderConfig(MaxPayloadSizeInBytes,
  1618. MaxAttributeSizeInBytes),
  1619. DXC_E_INCORRECT_DXIL_METADATA);
  1620. Args.emplace_back(Uint32ToConstMD(MaxPayloadSizeInBytes));
  1621. Args.emplace_back(Uint32ToConstMD(MaxAttributeSizeInBytes));
  1622. break;
  1623. }
  1624. case DXIL::SubobjectKind::RaytracingPipelineConfig: {
  1625. uint32_t MaxTraceRecursionDepth;
  1626. IFTBOOL(obj.GetRaytracingPipelineConfig(MaxTraceRecursionDepth),
  1627. DXC_E_INCORRECT_DXIL_METADATA);
  1628. Args.emplace_back(Uint32ToConstMD(MaxTraceRecursionDepth));
  1629. break;
  1630. }
  1631. case DXIL::SubobjectKind::HitGroup: {
  1632. llvm::StringRef Intersection, AnyHit, ClosestHit;
  1633. DXIL::HitGroupType hgType;
  1634. IFTBOOL(obj.GetHitGroup(hgType, Intersection, AnyHit, ClosestHit),
  1635. DXC_E_INCORRECT_DXIL_METADATA);
  1636. Args.emplace_back(Uint32ToConstMD((uint32_t)hgType));
  1637. Args.emplace_back(MDString::get(m_Ctx, Intersection));
  1638. Args.emplace_back(MDString::get(m_Ctx, AnyHit));
  1639. Args.emplace_back(MDString::get(m_Ctx, ClosestHit));
  1640. break;
  1641. }
  1642. case DXIL::SubobjectKind::RaytracingPipelineConfig1: {
  1643. uint32_t MaxTraceRecursionDepth;
  1644. uint32_t Flags;
  1645. IFTBOOL(obj.GetRaytracingPipelineConfig1(MaxTraceRecursionDepth, Flags),
  1646. DXC_E_INCORRECT_DXIL_METADATA);
  1647. Args.emplace_back(Uint32ToConstMD(MaxTraceRecursionDepth));
  1648. Args.emplace_back(Uint32ToConstMD(Flags));
  1649. break;
  1650. }
  1651. default:
  1652. DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
  1653. m_bExtraMetadata = true;
  1654. break;
  1655. }
  1656. return MDNode::get(m_Ctx, Args);
  1657. }
  1658. void DxilMDHelper::LoadSubobject(const llvm::MDNode &MD, DxilSubobjects &Subobjects) {
  1659. IFTBOOL(MD.getNumOperands() >= 2, DXC_E_INCORRECT_DXIL_METADATA);
  1660. unsigned i = 0;
  1661. StringRef name(StringMDToStringRef(MD.getOperand(i++)));
  1662. DXIL::SubobjectKind kind = (DXIL::SubobjectKind)ConstMDToUint32(MD.getOperand(i++));
  1663. IFTBOOL(DXIL::IsValidSubobjectKind(kind), DXC_E_INCORRECT_DXIL_METADATA);
  1664. bool bLocalRS = false;
  1665. switch (kind) {
  1666. case DXIL::SubobjectKind::StateObjectConfig: {
  1667. uint32_t Flags = ConstMDToUint32(MD.getOperand(i++));
  1668. IFTBOOL(0 == ((~(uint32_t)DXIL::StateObjectFlags::ValidMask) & Flags),
  1669. DXC_E_INCORRECT_DXIL_METADATA);
  1670. Subobjects.CreateStateObjectConfig(name, Flags);
  1671. break;
  1672. }
  1673. case DXIL::SubobjectKind::LocalRootSignature:
  1674. bLocalRS = true;
  1675. __fallthrough;
  1676. case DXIL::SubobjectKind::GlobalRootSignature: {
  1677. const MDNode *pDataMDWrapper = dyn_cast<MDNode>(MD.getOperand(i++));
  1678. IFTBOOL(pDataMDWrapper != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1679. IFTBOOL(pDataMDWrapper->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1680. const ConstantAsMetadata *pDataMD = dyn_cast<ConstantAsMetadata>(pDataMDWrapper->getOperand(0));
  1681. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pDataMD->getValue());
  1682. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1683. IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  1684. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  1685. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1686. const void *Data = pData->getRawDataValues().begin();
  1687. uint32_t Size = pData->getRawDataValues().size();
  1688. StringRef Text(StringMDToStringRef(MD.getOperand(i++)));
  1689. Subobjects.CreateRootSignature(name, bLocalRS, Data, Size, Text.size() ? &Text : nullptr);
  1690. break;
  1691. }
  1692. case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
  1693. StringRef Subobj(StringMDToStringRef(MD.getOperand(i++)));
  1694. const MDNode *exportMD = dyn_cast<MDNode>(MD.getOperand(i++));
  1695. SmallVector<StringRef, 4> Exports;
  1696. for (unsigned iExport = 0; iExport < exportMD->getNumOperands(); iExport++) {
  1697. Exports.push_back(StringMDToStringRef(exportMD->getOperand(iExport)));
  1698. }
  1699. Subobjects.CreateSubobjectToExportsAssociation(name, Subobj, Exports.data(), Exports.size());
  1700. break;
  1701. }
  1702. case DXIL::SubobjectKind::RaytracingShaderConfig: {
  1703. uint32_t MaxPayloadSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
  1704. uint32_t MaxAttributeSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
  1705. Subobjects.CreateRaytracingShaderConfig(name, MaxPayloadSizeInBytes, MaxAttributeSizeInBytes);
  1706. break;
  1707. }
  1708. case DXIL::SubobjectKind::RaytracingPipelineConfig: {
  1709. uint32_t MaxTraceRecursionDepth = ConstMDToUint32(MD.getOperand(i++));;
  1710. Subobjects.CreateRaytracingPipelineConfig(name, MaxTraceRecursionDepth);
  1711. break;
  1712. }
  1713. case DXIL::SubobjectKind::HitGroup: {
  1714. uint32_t hgType = ConstMDToUint32(MD.getOperand(i++));
  1715. StringRef Intersection(StringMDToStringRef(MD.getOperand(i++)));
  1716. StringRef AnyHit(StringMDToStringRef(MD.getOperand(i++)));
  1717. StringRef ClosestHit(StringMDToStringRef(MD.getOperand(i++)));
  1718. Subobjects.CreateHitGroup(name, (DXIL::HitGroupType)hgType, AnyHit, ClosestHit, Intersection);
  1719. break;
  1720. }
  1721. case DXIL::SubobjectKind::RaytracingPipelineConfig1: {
  1722. uint32_t MaxTraceRecursionDepth = ConstMDToUint32(MD.getOperand(i++));
  1723. uint32_t Flags = ConstMDToUint32(MD.getOperand(i++));
  1724. IFTBOOL(0 ==
  1725. ((~(uint32_t)DXIL::RaytracingPipelineFlags::ValidMask) & Flags),
  1726. DXC_E_INCORRECT_DXIL_METADATA);
  1727. Subobjects.CreateRaytracingPipelineConfig1(name, MaxTraceRecursionDepth,
  1728. Flags);
  1729. break;
  1730. }
  1731. default:
  1732. DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
  1733. m_bExtraMetadata = true;
  1734. break;
  1735. }
  1736. }
  1737. MDTuple *DxilMDHelper::EmitDxilSampler(const DxilSampler &S) {
  1738. Metadata *MDVals[kDxilSamplerNumFields];
  1739. EmitDxilResourceBase(S, &MDVals[0]);
  1740. // Sampler-specific fields.
  1741. MDVals[kDxilSamplerType ] = Uint32ToConstMD((unsigned)S.GetSamplerKind());
  1742. // Name-value list of extended properties.
  1743. MDVals[kDxilSamplerNameValueList] = nullptr;
  1744. vector<Metadata *> MDExtraVals;
  1745. m_ExtraPropertyHelper->EmitSamplerProperties(S, MDExtraVals);
  1746. if (!MDExtraVals.empty()) {
  1747. MDVals[kDxilSamplerNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  1748. }
  1749. return MDNode::get(m_Ctx, MDVals);
  1750. }
  1751. void DxilMDHelper::LoadDxilSampler(const MDOperand &MDO, DxilSampler &S) {
  1752. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1753. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1754. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1755. IFTBOOL(pTupleMD->getNumOperands() == kDxilSamplerNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1756. LoadDxilResourceBase(MDO, S);
  1757. // Sampler-specific fields.
  1758. S.SetSamplerKind((DxilSampler::SamplerKind)ConstMDToUint32(pTupleMD->getOperand(kDxilSamplerType)));
  1759. // Name-value list of extended properties.
  1760. m_ExtraPropertyHelper->m_bExtraMetadata = false;
  1761. m_ExtraPropertyHelper->LoadSamplerProperties(pTupleMD->getOperand(kDxilSamplerNameValueList), S);
  1762. m_bExtraMetadata |= m_ExtraPropertyHelper->m_bExtraMetadata;
  1763. }
  1764. const MDOperand &DxilMDHelper::GetResourceClass(llvm::MDNode *MD,
  1765. DXIL::ResourceClass &RC) {
  1766. IFTBOOL(MD->getNumOperands() >=
  1767. DxilMDHelper::kHLDxilResourceAttributeNumFields,
  1768. DXC_E_INCORRECT_DXIL_METADATA);
  1769. RC = static_cast<DxilResource::Class>(ConstMDToUint32(
  1770. MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeClass)));
  1771. return MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeMeta);
  1772. }
  1773. void DxilMDHelper::LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD,
  1774. DxilResourceBase &R) {
  1775. DxilResource::Class RC = DxilResource::Class::Invalid;
  1776. const MDOperand &Meta = GetResourceClass(MD, RC);
  1777. switch (RC) {
  1778. case DxilResource::Class::CBuffer: {
  1779. DxilCBuffer CB;
  1780. LoadDxilCBuffer(Meta, CB);
  1781. R = CB;
  1782. } break;
  1783. case DxilResource::Class::Sampler: {
  1784. DxilSampler S;
  1785. LoadDxilSampler(Meta, S);
  1786. R = S;
  1787. } break;
  1788. case DxilResource::Class::SRV: {
  1789. DxilResource Res;
  1790. LoadDxilSRV(Meta, Res);
  1791. R = Res;
  1792. } break;
  1793. case DxilResource::Class::UAV: {
  1794. DxilResource Res;
  1795. LoadDxilUAV(Meta, Res);
  1796. R = Res;
  1797. } break;
  1798. default:
  1799. DXASSERT(0, "Invalid metadata");
  1800. }
  1801. }
  1802. void DxilMDHelper::LoadDxilResourceFromMDNode(llvm::MDNode *MD,
  1803. DxilResource &R) {
  1804. DxilResource::Class RC = DxilResource::Class::Invalid;
  1805. const MDOperand &Meta = GetResourceClass(MD, RC);
  1806. switch (RC) {
  1807. case DxilResource::Class::SRV: {
  1808. LoadDxilSRV(Meta, R);
  1809. } break;
  1810. case DxilResource::Class::UAV: {
  1811. LoadDxilUAV(Meta, R);
  1812. } break;
  1813. default:
  1814. DXASSERT(0, "Invalid metadata");
  1815. }
  1816. }
  1817. void DxilMDHelper::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  1818. DxilResource::Class RC = DxilResource::Class::Invalid;
  1819. const MDOperand &Meta = GetResourceClass(MD, RC);
  1820. switch (RC) {
  1821. case DxilResource::Class::Sampler: {
  1822. LoadDxilSampler(Meta, S);
  1823. } break;
  1824. default:
  1825. DXASSERT(0, "Invalid metadata");
  1826. }
  1827. }
  1828. //
  1829. // DxilExtraPropertyHelper shader-specific methods.
  1830. //
  1831. MDTuple *DxilMDHelper::EmitDxilGSState(DXIL::InputPrimitive Primitive,
  1832. unsigned MaxVertexCount,
  1833. unsigned ActiveStreamMask,
  1834. DXIL::PrimitiveTopology StreamPrimitiveTopology,
  1835. unsigned GSInstanceCount) {
  1836. Metadata *MDVals[kDxilGSStateNumFields];
  1837. MDVals[kDxilGSStateInputPrimitive ] = Uint32ToConstMD((unsigned)Primitive);
  1838. MDVals[kDxilGSStateMaxVertexCount ] = Uint32ToConstMD(MaxVertexCount);
  1839. MDVals[kDxilGSStateActiveStreamMask ] = Uint32ToConstMD(ActiveStreamMask);
  1840. MDVals[kDxilGSStateOutputStreamTopology] = Uint32ToConstMD((unsigned)StreamPrimitiveTopology);
  1841. MDVals[kDxilGSStateGSInstanceCount ] = Uint32ToConstMD(GSInstanceCount);
  1842. return MDNode::get(m_Ctx, MDVals);
  1843. }
  1844. void DxilMDHelper::LoadDxilGSState(const MDOperand &MDO,
  1845. DXIL::InputPrimitive &Primitive,
  1846. unsigned &MaxVertexCount,
  1847. unsigned &ActiveStreamMask,
  1848. DXIL::PrimitiveTopology &StreamPrimitiveTopology,
  1849. unsigned &GSInstanceCount) {
  1850. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1851. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1852. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1853. IFTBOOL(pTupleMD->getNumOperands() == kDxilGSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1854. Primitive = (DXIL::InputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateInputPrimitive));
  1855. MaxVertexCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateMaxVertexCount));
  1856. ActiveStreamMask = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateActiveStreamMask));
  1857. StreamPrimitiveTopology = (DXIL::PrimitiveTopology)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateOutputStreamTopology));
  1858. GSInstanceCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateGSInstanceCount));
  1859. }
  1860. MDTuple *DxilMDHelper::EmitDxilDSState(DXIL::TessellatorDomain Domain, unsigned InputControlPointCount) {
  1861. Metadata *MDVals[kDxilDSStateNumFields];
  1862. MDVals[kDxilDSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)Domain);
  1863. MDVals[kDxilDSStateInputControlPointCount] = Uint32ToConstMD(InputControlPointCount);
  1864. return MDNode::get(m_Ctx, MDVals);
  1865. }
  1866. void DxilMDHelper::LoadDxilDSState(const MDOperand &MDO,
  1867. DXIL::TessellatorDomain &Domain,
  1868. unsigned &InputControlPointCount) {
  1869. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1870. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1871. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1872. IFTBOOL(pTupleMD->getNumOperands() == kDxilDSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1873. Domain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateTessellatorDomain));
  1874. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateInputControlPointCount));
  1875. }
  1876. MDTuple *DxilMDHelper::EmitDxilHSState(Function *pPatchConstantFunction,
  1877. unsigned InputControlPointCount,
  1878. unsigned OutputControlPointCount,
  1879. DXIL::TessellatorDomain TessDomain,
  1880. DXIL::TessellatorPartitioning TessPartitioning,
  1881. DXIL::TessellatorOutputPrimitive TessOutputPrimitive,
  1882. float MaxTessFactor) {
  1883. Metadata *MDVals[kDxilHSStateNumFields];
  1884. MDVals[kDxilHSStatePatchConstantFunction ] = ValueAsMetadata::get(pPatchConstantFunction);
  1885. MDVals[kDxilHSStateInputControlPointCount ] = Uint32ToConstMD(InputControlPointCount);
  1886. MDVals[kDxilHSStateOutputControlPointCount ] = Uint32ToConstMD(OutputControlPointCount);
  1887. MDVals[kDxilHSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)TessDomain);
  1888. MDVals[kDxilHSStateTessellatorPartitioning ] = Uint32ToConstMD((unsigned)TessPartitioning);
  1889. MDVals[kDxilHSStateTessellatorOutputPrimitive] = Uint32ToConstMD((unsigned)TessOutputPrimitive);
  1890. MDVals[kDxilHSStateMaxTessellationFactor ] = FloatToConstMD(MaxTessFactor);
  1891. return MDNode::get(m_Ctx, MDVals);
  1892. }
  1893. void DxilMDHelper::LoadDxilHSState(const MDOperand &MDO,
  1894. Function *&pPatchConstantFunction,
  1895. unsigned &InputControlPointCount,
  1896. unsigned &OutputControlPointCount,
  1897. DXIL::TessellatorDomain &TessDomain,
  1898. DXIL::TessellatorPartitioning &TessPartitioning,
  1899. DXIL::TessellatorOutputPrimitive &TessOutputPrimitive,
  1900. float &MaxTessFactor) {
  1901. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1902. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1903. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1904. IFTBOOL(pTupleMD->getNumOperands() == kDxilHSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1905. pPatchConstantFunction = dyn_cast<Function>(ValueMDToValue(pTupleMD->getOperand(kDxilHSStatePatchConstantFunction)));
  1906. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateInputControlPointCount));
  1907. OutputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateOutputControlPointCount));
  1908. TessDomain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorDomain));
  1909. TessPartitioning = (DXIL::TessellatorPartitioning)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorPartitioning));
  1910. TessOutputPrimitive = (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorOutputPrimitive));
  1911. MaxTessFactor = ConstMDToFloat(pTupleMD->getOperand(kDxilHSStateMaxTessellationFactor));
  1912. }
  1913. MDTuple *DxilMDHelper::EmitDxilMSState(const unsigned *NumThreads,
  1914. unsigned MaxVertexCount,
  1915. unsigned MaxPrimitiveCount,
  1916. DXIL::MeshOutputTopology OutputTopology,
  1917. unsigned payloadSizeInBytes) {
  1918. Metadata *MDVals[kDxilMSStateNumFields];
  1919. vector<Metadata *> NumThreadVals;
  1920. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[0]));
  1921. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[1]));
  1922. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[2]));
  1923. MDVals[kDxilMSStateNumThreads] = MDNode::get(m_Ctx, NumThreadVals);
  1924. MDVals[kDxilMSStateMaxVertexCount] = Uint32ToConstMD(MaxVertexCount);
  1925. MDVals[kDxilMSStateMaxPrimitiveCount] = Uint32ToConstMD(MaxPrimitiveCount);
  1926. MDVals[kDxilMSStateOutputTopology] = Uint32ToConstMD((unsigned)OutputTopology);
  1927. MDVals[kDxilMSStatePayloadSizeInBytes] = Uint32ToConstMD(payloadSizeInBytes);
  1928. return MDNode::get(m_Ctx, MDVals);
  1929. }
  1930. void DxilMDHelper::LoadDxilMSState(const MDOperand &MDO,
  1931. unsigned *NumThreads,
  1932. unsigned &MaxVertexCount,
  1933. unsigned &MaxPrimitiveCount,
  1934. DXIL::MeshOutputTopology &OutputTopology,
  1935. unsigned &payloadSizeInBytes) {
  1936. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1937. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1938. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1939. IFTBOOL(pTupleMD->getNumOperands() == kDxilMSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1940. MDNode *pNode = cast<MDNode>(pTupleMD->getOperand(kDxilMSStateNumThreads));
  1941. NumThreads[0] = ConstMDToUint32(pNode->getOperand(0));
  1942. NumThreads[1] = ConstMDToUint32(pNode->getOperand(1));
  1943. NumThreads[2] = ConstMDToUint32(pNode->getOperand(2));
  1944. MaxVertexCount = ConstMDToUint32(pTupleMD->getOperand(kDxilMSStateMaxVertexCount));
  1945. MaxPrimitiveCount = ConstMDToUint32(pTupleMD->getOperand(kDxilMSStateMaxPrimitiveCount));
  1946. OutputTopology = (DXIL::MeshOutputTopology)ConstMDToUint32(pTupleMD->getOperand(kDxilMSStateOutputTopology));
  1947. payloadSizeInBytes = ConstMDToUint32(pTupleMD->getOperand(kDxilMSStatePayloadSizeInBytes));
  1948. }
  1949. MDTuple *DxilMDHelper::EmitDxilASState(const unsigned *NumThreads, unsigned payloadSizeInBytes) {
  1950. Metadata *MDVals[kDxilASStateNumFields];
  1951. vector<Metadata *> NumThreadVals;
  1952. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[0]));
  1953. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[1]));
  1954. NumThreadVals.emplace_back(Uint32ToConstMD(NumThreads[2]));
  1955. MDVals[kDxilASStateNumThreads] = MDNode::get(m_Ctx, NumThreadVals);
  1956. MDVals[kDxilASStatePayloadSizeInBytes] = Uint32ToConstMD(payloadSizeInBytes);
  1957. return MDNode::get(m_Ctx, MDVals);
  1958. }
  1959. void DxilMDHelper::LoadDxilASState(const MDOperand &MDO, unsigned *NumThreads, unsigned &payloadSizeInBytes) {
  1960. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1961. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1962. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1963. IFTBOOL(pTupleMD->getNumOperands() == kDxilASStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1964. MDNode *pNode = cast<MDNode>(pTupleMD->getOperand(kDxilASStateNumThreads));
  1965. NumThreads[0] = ConstMDToUint32(pNode->getOperand(0));
  1966. NumThreads[1] = ConstMDToUint32(pNode->getOperand(1));
  1967. NumThreads[2] = ConstMDToUint32(pNode->getOperand(2));
  1968. payloadSizeInBytes = ConstMDToUint32(pTupleMD->getOperand(kDxilASStatePayloadSizeInBytes));
  1969. }
  1970. void DxilMDHelper::AddCounterIfNonZero(uint32_t value, StringRef name, vector<Metadata*> &MDVals) {
  1971. if (value) {
  1972. MDVals.emplace_back(MDString::get(m_Ctx, name));
  1973. MDVals.emplace_back(Uint32ToConstMD(value));
  1974. }
  1975. }
  1976. void DxilMDHelper::EmitDxilCounters(const DxilCounters &counters) {
  1977. NamedMDNode *pDxilCountersMD = m_pModule->getNamedMetadata(kDxilCountersMDName);
  1978. if (pDxilCountersMD)
  1979. m_pModule->eraseNamedMetadata(pDxilCountersMD);
  1980. vector<Metadata*> MDVals;
  1981. // <py::lines('OPCODE-COUNTERS')>['AddCounterIfNonZero(counters.%s, "%s", MDVals);' % (c,c) for c in hctdb_instrhelp.get_counters()]</py>
  1982. // OPCODE-COUNTERS:BEGIN
  1983. AddCounterIfNonZero(counters.array_local_bytes, "array_local_bytes", MDVals);
  1984. AddCounterIfNonZero(counters.array_local_ldst, "array_local_ldst", MDVals);
  1985. AddCounterIfNonZero(counters.array_static_bytes, "array_static_bytes", MDVals);
  1986. AddCounterIfNonZero(counters.array_static_ldst, "array_static_ldst", MDVals);
  1987. AddCounterIfNonZero(counters.array_tgsm_bytes, "array_tgsm_bytes", MDVals);
  1988. AddCounterIfNonZero(counters.array_tgsm_ldst, "array_tgsm_ldst", MDVals);
  1989. AddCounterIfNonZero(counters.atomic, "atomic", MDVals);
  1990. AddCounterIfNonZero(counters.barrier, "barrier", MDVals);
  1991. AddCounterIfNonZero(counters.branches, "branches", MDVals);
  1992. AddCounterIfNonZero(counters.fence, "fence", MDVals);
  1993. AddCounterIfNonZero(counters.floats, "floats", MDVals);
  1994. AddCounterIfNonZero(counters.gs_cut, "gs_cut", MDVals);
  1995. AddCounterIfNonZero(counters.gs_emit, "gs_emit", MDVals);
  1996. AddCounterIfNonZero(counters.insts, "insts", MDVals);
  1997. AddCounterIfNonZero(counters.ints, "ints", MDVals);
  1998. AddCounterIfNonZero(counters.sig_ld, "sig_ld", MDVals);
  1999. AddCounterIfNonZero(counters.sig_st, "sig_st", MDVals);
  2000. AddCounterIfNonZero(counters.tex_bias, "tex_bias", MDVals);
  2001. AddCounterIfNonZero(counters.tex_cmp, "tex_cmp", MDVals);
  2002. AddCounterIfNonZero(counters.tex_grad, "tex_grad", MDVals);
  2003. AddCounterIfNonZero(counters.tex_load, "tex_load", MDVals);
  2004. AddCounterIfNonZero(counters.tex_norm, "tex_norm", MDVals);
  2005. AddCounterIfNonZero(counters.tex_store, "tex_store", MDVals);
  2006. AddCounterIfNonZero(counters.uints, "uints", MDVals);
  2007. // OPCODE-COUNTERS:END
  2008. if (MDVals.size()) {
  2009. pDxilCountersMD = m_pModule->getOrInsertNamedMetadata(kDxilCountersMDName);
  2010. pDxilCountersMD->addOperand(MDNode::get(m_Ctx, MDVals));
  2011. }
  2012. }
  2013. void DxilMDHelper::LoadCounterMD(const MDOperand &MDName, const MDOperand &MDValue, DxilCounters &counters) const {
  2014. StringRef name = StringMDToStringRef(MDName);
  2015. uint32_t value = ConstMDToUint32(MDValue);
  2016. uint32_t *counter = LookupByName(name, counters);
  2017. if (counter)
  2018. *counter = value;
  2019. }
  2020. void DxilMDHelper::LoadDxilCounters(DxilCounters &counters) const {
  2021. ZeroMemory(&counters, sizeof(counters));
  2022. if (NamedMDNode *pDxilCountersMD = m_pModule->getNamedMetadata(kDxilCountersMDName)) {
  2023. MDNode *pMDCounters = pDxilCountersMD->getOperand(0);
  2024. for (unsigned i = 0; i < pMDCounters->getNumOperands(); i += 2) {
  2025. LoadCounterMD(pMDCounters->getOperand(i), pMDCounters->getOperand(i+1), counters);
  2026. }
  2027. }
  2028. }
  2029. //
  2030. // DxilExtraPropertyHelper methods.
  2031. //
  2032. DxilMDHelper::ExtraPropertyHelper::ExtraPropertyHelper(Module *pModule)
  2033. : m_Ctx(pModule->getContext())
  2034. , m_pModule(pModule)
  2035. , m_bExtraMetadata(false) {
  2036. }
  2037. DxilExtraPropertyHelper::DxilExtraPropertyHelper(Module *pModule)
  2038. : ExtraPropertyHelper(pModule) {
  2039. }
  2040. void DxilExtraPropertyHelper::EmitSRVProperties(const DxilResource &SRV, std::vector<Metadata *> &MDVals) {
  2041. // Element type for typed resource.
  2042. if (!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer()) {
  2043. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  2044. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)SRV.GetCompType().GetKind(), m_Ctx));
  2045. }
  2046. // Element stride for structured buffer.
  2047. if (SRV.IsStructuredBuffer()) {
  2048. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  2049. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SRV.GetElementStride(), m_Ctx));
  2050. }
  2051. }
  2052. void DxilExtraPropertyHelper::LoadSRVProperties(const MDOperand &MDO, DxilResource &SRV) {
  2053. SRV.SetElementStride(SRV.IsRawBuffer() ? 1 : 4);
  2054. SRV.SetCompType(CompType());
  2055. if (MDO.get() == nullptr) {
  2056. return;
  2057. }
  2058. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  2059. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2060. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  2061. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  2062. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  2063. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  2064. switch (Tag) {
  2065. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  2066. DXASSERT_NOMSG(!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer());
  2067. SRV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  2068. break;
  2069. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  2070. DXASSERT_NOMSG(SRV.IsStructuredBuffer());
  2071. SRV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  2072. break;
  2073. default:
  2074. DXASSERT(false, "Unknown resource record tag");
  2075. m_bExtraMetadata = true;
  2076. break;
  2077. }
  2078. }
  2079. }
  2080. void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::vector<Metadata *> &MDVals) {
  2081. // Element type for typed RW resource.
  2082. if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer() && !UAV.GetCompType().IsInvalid()) {
  2083. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  2084. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetCompType().GetKind(), m_Ctx));
  2085. }
  2086. // Element stride for structured RW buffer.
  2087. if (UAV.IsStructuredBuffer()) {
  2088. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  2089. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(UAV.GetElementStride(), m_Ctx));
  2090. }
  2091. // Sampler feedback kind
  2092. if (UAV.IsFeedbackTexture()) {
  2093. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSamplerFeedbackKindTag, m_Ctx));
  2094. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetSamplerFeedbackType(), m_Ctx));
  2095. }
  2096. // Whether resource is used for 64-bit atomic op
  2097. if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 6) >= 0 && UAV.HasAtomic64Use()) {
  2098. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilAtomic64UseTag, m_Ctx));
  2099. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)true, m_Ctx));
  2100. }
  2101. }
  2102. void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResource &UAV) {
  2103. UAV.SetElementStride(UAV.IsRawBuffer() ? 1 : 4);
  2104. UAV.SetCompType(CompType());
  2105. if (MDO.get() == nullptr) {
  2106. return;
  2107. }
  2108. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  2109. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2110. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  2111. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  2112. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  2113. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  2114. switch (Tag) {
  2115. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  2116. DXASSERT_NOMSG(!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer());
  2117. UAV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  2118. break;
  2119. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  2120. DXASSERT_NOMSG(UAV.IsStructuredBuffer());
  2121. UAV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  2122. break;
  2123. case DxilMDHelper::kDxilSamplerFeedbackKindTag:
  2124. DXASSERT_NOMSG(UAV.IsFeedbackTexture());
  2125. UAV.SetSamplerFeedbackType((DXIL::SamplerFeedbackType)DxilMDHelper::ConstMDToUint32(MDO));
  2126. break;
  2127. case DxilMDHelper::kDxilAtomic64UseTag:
  2128. UAV.SetHasAtomic64Use(DxilMDHelper::ConstMDToBool(MDO));
  2129. break;
  2130. default:
  2131. DXASSERT(false, "Unknown resource record tag");
  2132. m_bExtraMetadata = true;
  2133. break;
  2134. }
  2135. }
  2136. }
  2137. void DxilExtraPropertyHelper::EmitCBufferProperties(const DxilCBuffer &CB, vector<Metadata *> &MDVals) {
  2138. // Emit property to preserve tbuffer kind
  2139. if (CB.GetKind() == DXIL::ResourceKind::TBuffer) {
  2140. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kHLCBufferIsTBufferTag, m_Ctx));
  2141. MDVals.emplace_back(DxilMDHelper::BoolToConstMD(true, m_Ctx));
  2142. }
  2143. }
  2144. void DxilExtraPropertyHelper::LoadCBufferProperties(const MDOperand &MDO, DxilCBuffer &CB) {
  2145. if (MDO.get() == nullptr)
  2146. return;
  2147. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  2148. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2149. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  2150. // Override kind for tbuffer that has not yet been converted to SRV.
  2151. CB.SetKind(DXIL::ResourceKind::CBuffer);
  2152. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  2153. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  2154. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  2155. switch (Tag) {
  2156. case DxilMDHelper::kHLCBufferIsTBufferTag:
  2157. if (DxilMDHelper::ConstMDToBool(MDO)) {
  2158. CB.SetKind(DXIL::ResourceKind::TBuffer);
  2159. }
  2160. break;
  2161. default:
  2162. DXASSERT(false, "Unknown cbuffer tag");
  2163. m_bExtraMetadata = true;
  2164. break;
  2165. }
  2166. }
  2167. }
  2168. void DxilExtraPropertyHelper::EmitSamplerProperties(const DxilSampler &S, std::vector<Metadata *> &MDVals) {
  2169. // Nothing yet.
  2170. }
  2171. void DxilExtraPropertyHelper::LoadSamplerProperties(const MDOperand &MDO, DxilSampler &S) {
  2172. // Nothing yet.
  2173. }
  2174. void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignatureElement &SE,
  2175. vector<Metadata *> &MDVals) {
  2176. // Output stream, if non-zero.
  2177. if (SE.GetOutputStream() != 0) {
  2178. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementOutputStreamTag, m_Ctx));
  2179. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetOutputStream(), m_Ctx));
  2180. }
  2181. // Mask of Dynamically indexed components.
  2182. if (SE.GetDynIdxCompMask() != 0) {
  2183. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
  2184. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
  2185. }
  2186. if (SE.GetUsageMask() != 0 &&
  2187. DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
  2188. // Emitting this will not hurt old reatil loader (only asserts),
  2189. // and is required for signatures to match in validation.
  2190. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementUsageCompMaskTag, m_Ctx));
  2191. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetUsageMask(), m_Ctx));
  2192. }
  2193. }
  2194. void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
  2195. if (MDO.get() == nullptr)
  2196. return;
  2197. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  2198. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2199. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  2200. // Stream.
  2201. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  2202. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  2203. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  2204. switch (Tag) {
  2205. case DxilMDHelper::kDxilSignatureElementOutputStreamTag:
  2206. SE.SetOutputStream(DxilMDHelper::ConstMDToUint32(MDO));
  2207. break;
  2208. case DxilMDHelper::kHLSignatureElementGlobalSymbolTag:
  2209. break;
  2210. case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
  2211. SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
  2212. break;
  2213. case DxilMDHelper::kDxilSignatureElementUsageCompMaskTag:
  2214. SE.SetUsageMask(DxilMDHelper::ConstMDToUint32(MDO));
  2215. break;
  2216. default:
  2217. DXASSERT(false, "Unknown signature element tag");
  2218. m_bExtraMetadata = true;
  2219. break;
  2220. }
  2221. }
  2222. }
  2223. //
  2224. // Utilities.
  2225. //
  2226. bool DxilMDHelper::IsKnownNamedMetaData(const llvm::NamedMDNode &Node) {
  2227. StringRef name = Node.getName();
  2228. for (unsigned i = 0; i < DxilMDNames.size(); i++) {
  2229. if (name == DxilMDNames[i]) {
  2230. return true;
  2231. }
  2232. }
  2233. return false;
  2234. }
  2235. bool DxilMDHelper::IsKnownMetadataID(LLVMContext &Ctx, unsigned ID)
  2236. {
  2237. SmallVector<unsigned, 2> IDs;
  2238. GetKnownMetadataIDs(Ctx, &IDs);
  2239. return std::find(IDs.begin(), IDs.end(), ID) != IDs.end();
  2240. }
  2241. void DxilMDHelper::GetKnownMetadataIDs(LLVMContext &Ctx, SmallVectorImpl<unsigned> *pIDs)
  2242. {
  2243. auto AddIdIfExists = [&Ctx, &pIDs](StringRef Name) {
  2244. unsigned ID = 0;
  2245. if (Ctx.findMDKindID(hlsl::DxilMDHelper::kDxilPreciseAttributeMDName,
  2246. &ID)) {
  2247. pIDs->push_back(ID);
  2248. }
  2249. if (Ctx.findMDKindID(hlsl::DxilMDHelper::kDxilNonUniformAttributeMDName,
  2250. &ID)) {
  2251. pIDs->push_back(ID);
  2252. }
  2253. };
  2254. AddIdIfExists(hlsl::DxilMDHelper::kDxilPreciseAttributeMDName);
  2255. AddIdIfExists(hlsl::DxilMDHelper::kDxilNonUniformAttributeMDName);
  2256. }
  2257. void DxilMDHelper::combineDxilMetadata(llvm::Instruction *K,
  2258. const llvm::Instruction *J) {
  2259. if (IsMarkedNonUniform(J))
  2260. MarkNonUniform(K);
  2261. if (IsMarkedPrecise(J))
  2262. MarkPrecise(K);
  2263. }
  2264. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v, LLVMContext &Ctx) {
  2265. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  2266. }
  2267. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v) {
  2268. return DxilMDHelper::Int32ToConstMD(v, m_Ctx);
  2269. }
  2270. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v, LLVMContext &Ctx) {
  2271. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  2272. }
  2273. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v) {
  2274. return DxilMDHelper::Uint32ToConstMD(v, m_Ctx);
  2275. }
  2276. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v, LLVMContext &Ctx) {
  2277. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 64), APInt(64, v)));
  2278. }
  2279. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v) {
  2280. return DxilMDHelper::Uint64ToConstMD(v, m_Ctx);
  2281. }
  2282. ConstantAsMetadata *DxilMDHelper::Int8ToConstMD(int8_t v) {
  2283. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  2284. }
  2285. ConstantAsMetadata *DxilMDHelper::Uint8ToConstMD(uint8_t v) {
  2286. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  2287. }
  2288. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v, LLVMContext &Ctx) {
  2289. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 1), APInt(1, v ? 1 : 0)));
  2290. }
  2291. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v) {
  2292. return DxilMDHelper::BoolToConstMD(v, m_Ctx);
  2293. }
  2294. ConstantAsMetadata *DxilMDHelper::FloatToConstMD(float v) {
  2295. return ConstantAsMetadata::get(ConstantFP::get(m_Ctx, APFloat(v)));
  2296. }
  2297. int32_t DxilMDHelper::ConstMDToInt32(const MDOperand &MDO) {
  2298. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2299. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2300. return (int32_t)pConst->getZExtValue();
  2301. }
  2302. unsigned DxilMDHelper::ConstMDToUint32(const MDOperand &MDO) {
  2303. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2304. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2305. return (unsigned)pConst->getZExtValue();
  2306. }
  2307. uint64_t DxilMDHelper::ConstMDToUint64(const MDOperand &MDO) {
  2308. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2309. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2310. return pConst->getZExtValue();
  2311. }
  2312. int8_t DxilMDHelper::ConstMDToInt8(const MDOperand &MDO) {
  2313. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2314. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2315. return (int8_t)pConst->getZExtValue();
  2316. }
  2317. uint8_t DxilMDHelper::ConstMDToUint8(const MDOperand &MDO) {
  2318. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2319. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2320. return (uint8_t)pConst->getZExtValue();
  2321. }
  2322. bool DxilMDHelper::ConstMDToBool(const MDOperand &MDO) {
  2323. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  2324. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2325. return pConst->getZExtValue() != 0;
  2326. }
  2327. float DxilMDHelper::ConstMDToFloat(const MDOperand &MDO) {
  2328. ConstantFP *pConst = mdconst::extract<ConstantFP>(MDO);
  2329. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2330. return pConst->getValueAPF().convertToFloat();
  2331. }
  2332. string DxilMDHelper::StringMDToString(const MDOperand &MDO) {
  2333. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  2334. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2335. return pMDString->getString();
  2336. }
  2337. StringRef DxilMDHelper::StringMDToStringRef(const MDOperand &MDO) {
  2338. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  2339. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2340. return pMDString->getString();
  2341. }
  2342. Value *DxilMDHelper::ValueMDToValue(const MDOperand &MDO) {
  2343. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2344. ValueAsMetadata *pValAsMD = dyn_cast<ValueAsMetadata>(MDO.get());
  2345. IFTBOOL(pValAsMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2346. Value *pValue = pValAsMD->getValue();
  2347. IFTBOOL(pValue != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2348. return pValue;
  2349. }
  2350. MDTuple *DxilMDHelper::Uint32VectorToConstMDTuple(const std::vector<unsigned> &Vec) {
  2351. vector<Metadata *> MDVals;
  2352. MDVals.resize(Vec.size());
  2353. for (size_t i = 0; i < Vec.size(); i++) {
  2354. MDVals[i] = Uint32ToConstMD(Vec[i]);
  2355. }
  2356. return MDNode::get(m_Ctx, MDVals);
  2357. }
  2358. void DxilMDHelper::ConstMDTupleToUint32Vector(MDTuple *pTupleMD, std::vector<unsigned> &Vec) {
  2359. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  2360. Vec.resize(pTupleMD->getNumOperands());
  2361. for (size_t i = 0; i < pTupleMD->getNumOperands(); i++) {
  2362. Vec[i] = ConstMDToUint32(pTupleMD->getOperand(i));
  2363. }
  2364. }
  2365. bool DxilMDHelper::IsMarkedPrecise(const Instruction *inst) {
  2366. int32_t val = 0;
  2367. if (MDNode *precise = inst->getMetadata(kDxilPreciseAttributeMDName)) {
  2368. assert(precise->getNumOperands() == 1);
  2369. val = ConstMDToInt32(precise->getOperand(0));
  2370. }
  2371. return val;
  2372. }
  2373. void DxilMDHelper::MarkPrecise(Instruction *I) {
  2374. LLVMContext &Ctx = I->getContext();
  2375. MDNode *preciseNode = MDNode::get(
  2376. Ctx,
  2377. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  2378. I->setMetadata(DxilMDHelper::kDxilPreciseAttributeMDName, preciseNode);
  2379. }
  2380. bool DxilMDHelper::IsMarkedNonUniform(const Instruction *inst) {
  2381. int32_t val = 0;
  2382. if (MDNode *precise = inst->getMetadata(kDxilNonUniformAttributeMDName)) {
  2383. assert(precise->getNumOperands() == 1);
  2384. val = ConstMDToInt32(precise->getOperand(0));
  2385. }
  2386. return val;
  2387. }
  2388. void DxilMDHelper::MarkNonUniform(Instruction *I) {
  2389. LLVMContext &Ctx = I->getContext();
  2390. MDNode *preciseNode = MDNode::get(
  2391. Ctx,
  2392. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  2393. I->setMetadata(DxilMDHelper::kDxilNonUniformAttributeMDName, preciseNode);
  2394. }
  2395. bool DxilMDHelper::GetVariableDebugLayout(llvm::DbgDeclareInst *inst,
  2396. unsigned &StartOffsetInBits, std::vector<DxilDIArrayDim> &ArrayDims) {
  2397. llvm::MDTuple *Tuple = dyn_cast_or_null<MDTuple>(inst->getMetadata(DxilMDHelper::kDxilVariableDebugLayoutMDName));
  2398. if (Tuple == nullptr) return false;
  2399. IFTBOOL(Tuple->getNumOperands() % 2 == 1, DXC_E_INCORRECT_DXIL_METADATA);
  2400. StartOffsetInBits = ConstMDToUint32(Tuple->getOperand(0));
  2401. for (unsigned Idx = 1; Idx < Tuple->getNumOperands(); Idx += 2) {
  2402. DxilDIArrayDim ArrayDim = {};
  2403. ArrayDim.StrideInBits = ConstMDToUint32(Tuple->getOperand(Idx + 0));
  2404. ArrayDim.NumElements = ConstMDToUint32(Tuple->getOperand(Idx + 1));
  2405. ArrayDims.emplace_back(ArrayDim);
  2406. }
  2407. return true;
  2408. }
  2409. void DxilMDHelper::SetVariableDebugLayout(llvm::DbgDeclareInst *inst,
  2410. unsigned StartOffsetInBits, const std::vector<DxilDIArrayDim> &ArrayDims) {
  2411. LLVMContext &Ctx = inst->getContext();
  2412. std::vector<Metadata*> MDVals;
  2413. MDVals.reserve(ArrayDims.size() + 1);
  2414. MDVals.emplace_back(Uint32ToConstMD(StartOffsetInBits, Ctx));
  2415. for (const DxilDIArrayDim &ArrayDim : ArrayDims) {
  2416. MDVals.emplace_back(Uint32ToConstMD(ArrayDim.StrideInBits, Ctx));
  2417. MDVals.emplace_back(Uint32ToConstMD(ArrayDim.NumElements, Ctx));
  2418. }
  2419. inst->setMetadata(DxilMDHelper::kDxilVariableDebugLayoutMDName, MDNode::get(Ctx, MDVals));
  2420. }
  2421. void DxilMDHelper::CopyMetadata(Instruction &I, Instruction &SrcInst, ArrayRef<unsigned> WL) {
  2422. if (!SrcInst.hasMetadata())
  2423. return;
  2424. DenseSet<unsigned> WLS;
  2425. for (unsigned M : WL)
  2426. WLS.insert(M);
  2427. // Otherwise, enumerate and copy over metadata from the old instruction to the
  2428. // new one.
  2429. SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs;
  2430. SrcInst.getAllMetadataOtherThanDebugLoc(TheMDs);
  2431. for (const auto &MD : TheMDs) {
  2432. if (WL.empty() || WLS.count(MD.first))
  2433. I.setMetadata(MD.first, MD.second);
  2434. }
  2435. if (WL.empty() || WLS.count(LLVMContext::MD_dbg))
  2436. I.setDebugLoc(SrcInst.getDebugLoc());
  2437. }
  2438. } // namespace hlsl