DxilMetadataHelper.cpp 77 KB

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