DxilMetadataHelper.cpp 117 KB

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