DxilMetadataHelper.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892
  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. // For case a system semantic don't have index, add 0 for it.
  363. if (SemanticIndexVector.empty() && !SE.IsArbitrary()) {
  364. SE.SetSemanticIndexVec({0});
  365. }
  366. // Name-value list of extended properties.
  367. m_ExtraPropertyHelper->LoadSignatureElementProperties(pTupleMD->getOperand(kDxilSignatureElementNameValueList), SE);
  368. }
  369. //
  370. // Resources.
  371. //
  372. MDTuple *DxilMDHelper::EmitDxilResourceTuple(MDTuple *pSRVs, MDTuple *pUAVs,
  373. MDTuple *pCBuffers, MDTuple *pSamplers) {
  374. DXASSERT(pSRVs != nullptr || pUAVs != nullptr || pCBuffers != nullptr || pSamplers != nullptr, "resource tuple should not be emitted if there are no resources");
  375. Metadata *MDVals[kDxilNumResourceFields];
  376. MDVals[kDxilResourceSRVs ] = pSRVs;
  377. MDVals[kDxilResourceUAVs ] = pUAVs;
  378. MDVals[kDxilResourceCBuffers] = pCBuffers;
  379. MDVals[kDxilResourceSamplers] = pSamplers;
  380. MDTuple *pTupleMD = MDNode::get(m_Ctx, MDVals);
  381. return pTupleMD;
  382. }
  383. void DxilMDHelper::EmitDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  384. NamedMDNode *pResourcesNamedMD = m_pModule->getNamedMetadata(kDxilResourcesMDName);
  385. IFTBOOL(pResourcesNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  386. pResourcesNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  387. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  388. }
  389. void DxilMDHelper::UpdateDxilResources(llvm::MDTuple *pDxilResourceTuple) {
  390. NamedMDNode *pResourcesNamedMD =
  391. m_pModule->getNamedMetadata(kDxilResourcesMDName);
  392. if (!pResourcesNamedMD) {
  393. pResourcesNamedMD =
  394. m_pModule->getOrInsertNamedMetadata(kDxilResourcesMDName);
  395. }
  396. if (pDxilResourceTuple) {
  397. if (pResourcesNamedMD->getNumOperands() != 0) {
  398. pResourcesNamedMD->setOperand(0, pDxilResourceTuple);
  399. }
  400. else {
  401. pResourcesNamedMD->addOperand(pDxilResourceTuple);
  402. }
  403. } else {
  404. m_pModule->eraseNamedMetadata(pResourcesNamedMD);
  405. }
  406. }
  407. void DxilMDHelper::GetDxilResources(const MDOperand &MDO, const MDTuple *&pSRVs,
  408. const MDTuple *&pUAVs, const MDTuple *&pCBuffers,
  409. const MDTuple *&pSamplers) {
  410. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  411. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  412. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  413. IFTBOOL(pTupleMD->getNumOperands() == kDxilNumResourceFields, DXC_E_INCORRECT_DXIL_METADATA);
  414. pSRVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSRVs ));
  415. pUAVs = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceUAVs ));
  416. pCBuffers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceCBuffers));
  417. pSamplers = CastToTupleOrNull(pTupleMD->getOperand(kDxilResourceSamplers));
  418. }
  419. void DxilMDHelper::EmitDxilResourceBase(const DxilResourceBase &R, Metadata *ppMDVals[]) {
  420. ppMDVals[kDxilResourceBaseID ] = Uint32ToConstMD(R.GetID());
  421. ppMDVals[kDxilResourceBaseVariable ] = ValueAsMetadata::get(R.GetGlobalSymbol());
  422. ppMDVals[kDxilResourceBaseName ] = MDString::get(m_Ctx, R.GetGlobalName());
  423. ppMDVals[kDxilResourceBaseSpaceID ] = Uint32ToConstMD(R.GetSpaceID());
  424. ppMDVals[kDxilResourceBaseLowerBound] = Uint32ToConstMD(R.GetLowerBound());
  425. ppMDVals[kDxilResourceBaseRangeSize ] = Uint32ToConstMD(R.GetRangeSize());
  426. }
  427. void DxilMDHelper::LoadDxilResourceBase(const MDOperand &MDO, DxilResourceBase &R) {
  428. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  429. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  430. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  431. IFTBOOL(pTupleMD->getNumOperands() >= kDxilResourceBaseNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  432. R.SetID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseID)));
  433. R.SetGlobalSymbol(dyn_cast<Constant>(ValueMDToValue(pTupleMD->getOperand(kDxilResourceBaseVariable))));
  434. R.SetGlobalName(StringMDToString(pTupleMD->getOperand(kDxilResourceBaseName)));
  435. R.SetSpaceID(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseSpaceID)));
  436. R.SetLowerBound(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseLowerBound)));
  437. R.SetRangeSize(ConstMDToUint32(pTupleMD->getOperand(kDxilResourceBaseRangeSize)));
  438. }
  439. MDTuple *DxilMDHelper::EmitDxilSRV(const DxilResource &SRV) {
  440. Metadata *MDVals[kDxilSRVNumFields];
  441. EmitDxilResourceBase(SRV, &MDVals[0]);
  442. // SRV-specific fields.
  443. MDVals[kDxilSRVShape ] = Uint32ToConstMD((unsigned)SRV.GetKind());
  444. MDVals[kDxilSRVSampleCount ] = Uint32ToConstMD(SRV.GetSampleCount());
  445. // Name-value list of extended properties.
  446. MDVals[kDxilSRVNameValueList] = nullptr;
  447. vector<Metadata *> MDExtraVals;
  448. m_ExtraPropertyHelper->EmitSRVProperties(SRV, MDExtraVals);
  449. if (!MDExtraVals.empty()) {
  450. MDVals[kDxilSRVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  451. }
  452. return MDNode::get(m_Ctx, MDVals);
  453. }
  454. void DxilMDHelper::LoadDxilSRV(const MDOperand &MDO, DxilResource &SRV) {
  455. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  456. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  457. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  458. IFTBOOL(pTupleMD->getNumOperands() == kDxilSRVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  459. SRV.SetRW(false);
  460. LoadDxilResourceBase(MDO, SRV);
  461. // SRV-specific fields.
  462. SRV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilSRVShape)));
  463. SRV.SetSampleCount(ConstMDToUint32(pTupleMD->getOperand(kDxilSRVSampleCount)));
  464. // Name-value list of extended properties.
  465. m_ExtraPropertyHelper->LoadSRVProperties(pTupleMD->getOperand(kDxilSRVNameValueList), SRV);
  466. }
  467. MDTuple *DxilMDHelper::EmitDxilUAV(const DxilResource &UAV) {
  468. Metadata *MDVals[kDxilUAVNumFields];
  469. EmitDxilResourceBase(UAV, &MDVals[0]);
  470. // UAV-specific fields.
  471. MDVals[kDxilUAVShape ] = Uint32ToConstMD((unsigned)UAV.GetKind());
  472. MDVals[kDxilUAVGloballyCoherent ] = BoolToConstMD(UAV.IsGloballyCoherent());
  473. MDVals[kDxilUAVCounter ] = BoolToConstMD(UAV.HasCounter());
  474. MDVals[kDxilUAVRasterizerOrderedView] = BoolToConstMD(UAV.IsROV());
  475. // Name-value list of extended properties.
  476. MDVals[kDxilUAVNameValueList ] = nullptr;
  477. vector<Metadata *> MDExtraVals;
  478. m_ExtraPropertyHelper->EmitUAVProperties(UAV, MDExtraVals);
  479. if (!MDExtraVals.empty()) {
  480. MDVals[kDxilUAVNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  481. }
  482. return MDNode::get(m_Ctx, MDVals);
  483. }
  484. void DxilMDHelper::LoadDxilUAV(const MDOperand &MDO, DxilResource &UAV) {
  485. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  486. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  487. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  488. IFTBOOL(pTupleMD->getNumOperands() == kDxilUAVNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  489. UAV.SetRW(true);
  490. LoadDxilResourceBase(MDO, UAV);
  491. // UAV-specific fields.
  492. UAV.SetKind((DxilResource::Kind)ConstMDToUint32(pTupleMD->getOperand(kDxilUAVShape)));
  493. UAV.SetGloballyCoherent(ConstMDToBool(pTupleMD->getOperand(kDxilUAVGloballyCoherent)));
  494. UAV.SetHasCounter(ConstMDToBool(pTupleMD->getOperand(kDxilUAVCounter)));
  495. UAV.SetROV(ConstMDToBool(pTupleMD->getOperand(kDxilUAVRasterizerOrderedView)));
  496. // Name-value list of extended properties.
  497. m_ExtraPropertyHelper->LoadUAVProperties(pTupleMD->getOperand(kDxilUAVNameValueList), UAV);
  498. }
  499. MDTuple *DxilMDHelper::EmitDxilCBuffer(const DxilCBuffer &CB) {
  500. Metadata *MDVals[kDxilCBufferNumFields];
  501. EmitDxilResourceBase(CB, &MDVals[0]);
  502. // CBuffer-specific fields.
  503. // CBuffer size in bytes.
  504. MDVals[kDxilCBufferSizeInBytes ] = Uint32ToConstMD(CB.GetSize());
  505. // Name-value list of extended properties.
  506. MDVals[kDxilCBufferNameValueList] = nullptr;
  507. vector<Metadata *> MDExtraVals;
  508. m_ExtraPropertyHelper->EmitCBufferProperties(CB, MDExtraVals);
  509. if (!MDExtraVals.empty()) {
  510. MDVals[kDxilCBufferNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  511. }
  512. return MDNode::get(m_Ctx, MDVals);
  513. }
  514. void DxilMDHelper::LoadDxilCBuffer(const MDOperand &MDO, DxilCBuffer &CB) {
  515. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  516. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  517. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  518. IFTBOOL(pTupleMD->getNumOperands() == kDxilCBufferNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  519. LoadDxilResourceBase(MDO, CB);
  520. // CBuffer-specific fields.
  521. CB.SetSize(ConstMDToUint32(pTupleMD->getOperand(kDxilCBufferSizeInBytes)));
  522. // Name-value list of extended properties.
  523. m_ExtraPropertyHelper->LoadCBufferProperties(pTupleMD->getOperand(kDxilCBufferNameValueList), CB);
  524. }
  525. void DxilMDHelper::EmitDxilTypeSystem(DxilTypeSystem &TypeSystem, vector<GlobalVariable*> &LLVMUsed) {
  526. auto &TypeMap = TypeSystem.GetStructAnnotationMap();
  527. vector<Metadata *> MDVals;
  528. MDVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemStructTag)); // Tag
  529. unsigned GVIdx = 0;
  530. for (auto it = TypeMap.begin(); it != TypeMap.end(); ++it, GVIdx++) {
  531. StructType *pStructType = const_cast<StructType *>(it->first);
  532. DxilStructAnnotation *pA = it->second.get();
  533. // Don't emit type annotation for empty struct.
  534. if (pA->IsEmptyStruct())
  535. continue;
  536. // Emit struct type field annotations.
  537. Metadata *pMD = EmitDxilStructAnnotation(*pA);
  538. MDVals.push_back(ValueAsMetadata::get(UndefValue::get(pStructType)));
  539. MDVals.push_back(pMD);
  540. }
  541. auto &FuncMap = TypeSystem.GetFunctionAnnotationMap();
  542. vector<Metadata *> MDFuncVals;
  543. MDFuncVals.emplace_back(Uint32ToConstMD(kDxilTypeSystemFunctionTag)); // Tag
  544. for (auto it = FuncMap.begin(); it != FuncMap.end(); ++it) {
  545. DxilFunctionAnnotation *pA = it->second.get();
  546. MDFuncVals.push_back(ValueAsMetadata::get(const_cast<Function*>(pA->GetFunction())));
  547. // Emit function annotations.
  548. Metadata *pMD;
  549. pMD = EmitDxilFunctionAnnotation(*pA);
  550. MDFuncVals.push_back(pMD);
  551. }
  552. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  553. if (pDxilTypeAnnotationsMD != nullptr) {
  554. m_pModule->eraseNamedMetadata(pDxilTypeAnnotationsMD);
  555. }
  556. if (MDVals.size() > 1) {
  557. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  558. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDVals));
  559. }
  560. if (MDFuncVals.size() > 1) {
  561. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  562. if (pDxilTypeAnnotationsMD == nullptr)
  563. pDxilTypeAnnotationsMD = m_pModule->getOrInsertNamedMetadata(kDxilTypeSystemMDName);
  564. pDxilTypeAnnotationsMD->addOperand(MDNode::get(m_Ctx, MDFuncVals));
  565. }
  566. }
  567. void DxilMDHelper::LoadDxilTypeSystemNode(const llvm::MDTuple &MDT,
  568. DxilTypeSystem &TypeSystem) {
  569. unsigned Tag = ConstMDToUint32(MDT.getOperand(0));
  570. if (Tag == kDxilTypeSystemStructTag) {
  571. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  572. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  573. Constant *pGV =
  574. dyn_cast<Constant>(ValueMDToValue(MDT.getOperand(i)));
  575. IFTBOOL(pGV != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  576. StructType *pGVType =
  577. dyn_cast<StructType>(pGV->getType());
  578. IFTBOOL(pGVType != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  579. DxilStructAnnotation *pSA = TypeSystem.AddStructAnnotation(pGVType);
  580. LoadDxilStructAnnotation(MDT.getOperand(i + 1), *pSA);
  581. }
  582. } else {
  583. IFTBOOL((MDT.getNumOperands() & 0x1) == 1, DXC_E_INCORRECT_DXIL_METADATA);
  584. for (unsigned i = 1; i < MDT.getNumOperands(); i += 2) {
  585. Function *F = dyn_cast<Function>(ValueMDToValue(MDT.getOperand(i)));
  586. DxilFunctionAnnotation *pFA = TypeSystem.AddFunctionAnnotation(F);
  587. LoadDxilFunctionAnnotation(MDT.getOperand(i + 1), *pFA);
  588. }
  589. }
  590. }
  591. void DxilMDHelper::LoadDxilTypeSystem(DxilTypeSystem &TypeSystem) {
  592. NamedMDNode *pDxilTypeAnnotationsMD = m_pModule->getNamedMetadata(kDxilTypeSystemMDName);
  593. if (pDxilTypeAnnotationsMD == nullptr)
  594. return;
  595. IFTBOOL(pDxilTypeAnnotationsMD->getNumOperands() <= 2, DXC_E_INCORRECT_DXIL_METADATA);
  596. for (unsigned i = 0; i < pDxilTypeAnnotationsMD->getNumOperands(); i++) {
  597. const MDTuple *pTupleMD = dyn_cast<MDTuple>(pDxilTypeAnnotationsMD->getOperand(i));
  598. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  599. LoadDxilTypeSystemNode(*pTupleMD, TypeSystem);
  600. }
  601. }
  602. Metadata *DxilMDHelper::EmitDxilStructAnnotation(const DxilStructAnnotation &SA) {
  603. vector<Metadata *> MDVals(SA.GetNumFields() + 1);
  604. MDVals[0] = Uint32ToConstMD(SA.GetCBufferSize());
  605. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  606. MDVals[i+1] = EmitDxilFieldAnnotation(SA.GetFieldAnnotation(i));
  607. }
  608. return MDNode::get(m_Ctx, MDVals);
  609. }
  610. void DxilMDHelper::LoadDxilStructAnnotation(const MDOperand &MDO, DxilStructAnnotation &SA) {
  611. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  612. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  613. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  614. if (pTupleMD->getNumOperands() == 1) {
  615. SA.MarkEmptyStruct();
  616. }
  617. IFTBOOL(pTupleMD->getNumOperands() == SA.GetNumFields()+1, DXC_E_INCORRECT_DXIL_METADATA);
  618. SA.SetCBufferSize(ConstMDToUint32(pTupleMD->getOperand(0)));
  619. for (unsigned i = 0; i < SA.GetNumFields(); i++) {
  620. const MDOperand &MDO = pTupleMD->getOperand(i+1);
  621. DxilFieldAnnotation &FA = SA.GetFieldAnnotation(i);
  622. LoadDxilFieldAnnotation(MDO, FA);
  623. }
  624. }
  625. Metadata *
  626. DxilMDHelper::EmitDxilFunctionAnnotation(const DxilFunctionAnnotation &FA) {
  627. return EmitDxilParamAnnotations(FA);
  628. }
  629. void DxilMDHelper::LoadDxilFunctionAnnotation(const MDOperand &MDO,
  630. DxilFunctionAnnotation &FA) {
  631. LoadDxilParamAnnotations(MDO, FA);
  632. }
  633. llvm::Metadata *
  634. DxilMDHelper::EmitDxilParamAnnotations(const DxilFunctionAnnotation &FA) {
  635. vector<Metadata *> MDParamAnnotations(FA.GetNumParameters() + 1);
  636. MDParamAnnotations[0] = EmitDxilParamAnnotation(FA.GetRetTypeAnnotation());
  637. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  638. MDParamAnnotations[i + 1] =
  639. EmitDxilParamAnnotation(FA.GetParameterAnnotation(i));
  640. }
  641. return MDNode::get(m_Ctx, MDParamAnnotations);
  642. }
  643. void DxilMDHelper::LoadDxilParamAnnotations(const llvm::MDOperand &MDO,
  644. DxilFunctionAnnotation &FA) {
  645. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  646. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  647. IFTBOOL(pTupleMD->getNumOperands() == FA.GetNumParameters() + 1,
  648. DXC_E_INCORRECT_DXIL_METADATA);
  649. DxilParameterAnnotation &retTyAnnotation = FA.GetRetTypeAnnotation();
  650. LoadDxilParamAnnotation(pTupleMD->getOperand(0), retTyAnnotation);
  651. for (unsigned i = 0; i < FA.GetNumParameters(); i++) {
  652. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  653. DxilParameterAnnotation &PA = FA.GetParameterAnnotation(i);
  654. LoadDxilParamAnnotation(MDO, PA);
  655. }
  656. }
  657. Metadata *
  658. DxilMDHelper::EmitDxilParamAnnotation(const DxilParameterAnnotation &PA) {
  659. vector<Metadata *> MDVals(3);
  660. MDVals[0] = Uint32ToConstMD(static_cast<unsigned>(PA.GetParamInputQual()));
  661. MDVals[1] = EmitDxilFieldAnnotation(PA);
  662. MDVals[2] = Uint32VectorToConstMDTuple(PA.GetSemanticIndexVec());
  663. return MDNode::get(m_Ctx, MDVals);
  664. }
  665. void DxilMDHelper::LoadDxilParamAnnotation(const MDOperand &MDO,
  666. DxilParameterAnnotation &PA) {
  667. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  668. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  669. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  670. IFTBOOL(pTupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  671. PA.SetParamInputQual(static_cast<DxilParamInputQual>(
  672. ConstMDToUint32(pTupleMD->getOperand(0))));
  673. LoadDxilFieldAnnotation(pTupleMD->getOperand(1), PA);
  674. MDTuple *pSemanticIndexVectorMD = dyn_cast<MDTuple>(pTupleMD->getOperand(2));
  675. vector<unsigned> SemanticIndexVector;
  676. ConstMDTupleToUint32Vector(pSemanticIndexVectorMD, SemanticIndexVector);
  677. PA.SetSemanticIndexVec(SemanticIndexVector);
  678. }
  679. Metadata *DxilMDHelper::EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA) {
  680. vector<Metadata *> MDVals; // Tag-Value list.
  681. if (FA.HasFieldName()) {
  682. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationFieldNameTag));
  683. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetFieldName()));
  684. }
  685. if (FA.IsPrecise()) {
  686. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationPreciseTag)); // Tag
  687. MDVals.emplace_back(BoolToConstMD(true)); // Value
  688. }
  689. if (FA.HasMatrixAnnotation()) {
  690. const DxilMatrixAnnotation &MA = FA.GetMatrixAnnotation();
  691. Metadata *MatrixMD[3];
  692. MatrixMD[0] = Uint32ToConstMD(MA.Rows);
  693. MatrixMD[1] = Uint32ToConstMD(MA.Cols);
  694. MatrixMD[2] = Uint32ToConstMD((unsigned)MA.Orientation);
  695. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationMatrixTag));
  696. MDVals.emplace_back(MDNode::get(m_Ctx, MatrixMD));
  697. }
  698. if (FA.HasCBufferOffset()) {
  699. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCBufferOffsetTag));
  700. MDVals.emplace_back(Uint32ToConstMD(FA.GetCBufferOffset()));
  701. }
  702. if (FA.HasSemanticString()) {
  703. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationSemanticStringTag));
  704. MDVals.emplace_back(MDString::get(m_Ctx, FA.GetSemanticString()));
  705. }
  706. if (FA.HasInterpolationMode()) {
  707. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationInterpolationModeTag));
  708. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetInterpolationMode().GetKind()));
  709. }
  710. if (FA.HasCompType()) {
  711. MDVals.emplace_back(Uint32ToConstMD(kDxilFieldAnnotationCompTypeTag));
  712. MDVals.emplace_back(Uint32ToConstMD((unsigned)FA.GetCompType().GetKind()));
  713. }
  714. return MDNode::get(m_Ctx, MDVals);
  715. }
  716. void DxilMDHelper::LoadDxilFieldAnnotation(const MDOperand &MDO, DxilFieldAnnotation &FA) {
  717. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  718. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  719. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  720. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  721. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  722. unsigned Tag = ConstMDToUint32(pTupleMD->getOperand(i));
  723. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  724. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  725. switch (Tag) {
  726. case kDxilFieldAnnotationPreciseTag:
  727. FA.SetPrecise(ConstMDToBool(MDO));
  728. break;
  729. case kDxilFieldAnnotationMatrixTag: {
  730. DxilMatrixAnnotation MA;
  731. const MDTuple *pMATupleMD = dyn_cast<MDTuple>(MDO.get());
  732. IFTBOOL(pMATupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  733. IFTBOOL(pMATupleMD->getNumOperands() == 3, DXC_E_INCORRECT_DXIL_METADATA);
  734. MA.Rows = ConstMDToUint32(pMATupleMD->getOperand(0));
  735. MA.Cols = ConstMDToUint32(pMATupleMD->getOperand(1));
  736. MA.Orientation = (MatrixOrientation)ConstMDToUint32(pMATupleMD->getOperand(2));
  737. FA.SetMatrixAnnotation(MA);
  738. } break;
  739. case kDxilFieldAnnotationCBufferOffsetTag:
  740. FA.SetCBufferOffset(ConstMDToUint32(MDO));
  741. break;
  742. case kDxilFieldAnnotationSemanticStringTag:
  743. FA.SetSemanticString(StringMDToString(MDO));
  744. break;
  745. case kDxilFieldAnnotationInterpolationModeTag:
  746. FA.SetInterpolationMode(InterpolationMode((InterpolationMode::Kind)ConstMDToUint32(MDO)));
  747. break;
  748. case kDxilFieldAnnotationFieldNameTag:
  749. FA.SetFieldName(StringMDToString(MDO));
  750. break;
  751. case kDxilFieldAnnotationCompTypeTag:
  752. FA.SetCompType((CompType::Kind)ConstMDToUint32(MDO));
  753. break;
  754. default:
  755. // TODO: I don't think we should be failing unrecognized extended tags.
  756. // Perhaps we can flag this case in the module and fail validation
  757. // if flagged.
  758. // That way, an existing loader will not fail on an additional tag
  759. // and the blob would not be signed if the extra tag was not legal.
  760. IFTBOOL(false, DXC_E_INCORRECT_DXIL_METADATA);
  761. }
  762. }
  763. }
  764. const Function *DxilMDHelper::LoadDxilFunctionProps(const MDTuple *pProps,
  765. hlsl::DxilFunctionProps *props) {
  766. unsigned idx = 0;
  767. const Function *F = dyn_cast<Function>(
  768. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  769. DXIL::ShaderKind shaderKind =
  770. static_cast<DXIL::ShaderKind>(ConstMDToUint32(pProps->getOperand(idx++)));
  771. bool bRayAttributes = false;
  772. props->shaderKind = shaderKind;
  773. switch (shaderKind) {
  774. case DXIL::ShaderKind::Compute:
  775. props->ShaderProps.CS.numThreads[0] =
  776. ConstMDToUint32(pProps->getOperand(idx++));
  777. props->ShaderProps.CS.numThreads[1] =
  778. ConstMDToUint32(pProps->getOperand(idx++));
  779. props->ShaderProps.CS.numThreads[2] =
  780. ConstMDToUint32(pProps->getOperand(idx++));
  781. break;
  782. case DXIL::ShaderKind::Geometry:
  783. props->ShaderProps.GS.inputPrimitive =
  784. (DXIL::InputPrimitive)ConstMDToUint32(pProps->getOperand(idx++));
  785. props->ShaderProps.GS.maxVertexCount =
  786. ConstMDToUint32(pProps->getOperand(idx++));
  787. props->ShaderProps.GS.instanceCount =
  788. ConstMDToUint32(pProps->getOperand(idx++));
  789. for (size_t i = 0;
  790. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  791. props->ShaderProps.GS.streamPrimitiveTopologies[i] =
  792. (DXIL::PrimitiveTopology)ConstMDToUint32(pProps->getOperand(idx++));
  793. break;
  794. case DXIL::ShaderKind::Hull:
  795. props->ShaderProps.HS.patchConstantFunc = dyn_cast<Function>(
  796. dyn_cast<ValueAsMetadata>(pProps->getOperand(idx++))->getValue());
  797. props->ShaderProps.HS.domain =
  798. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  799. props->ShaderProps.HS.partition =
  800. (DXIL::TessellatorPartitioning)ConstMDToUint32(
  801. pProps->getOperand(idx++));
  802. props->ShaderProps.HS.outputPrimitive =
  803. (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(
  804. pProps->getOperand(idx++));
  805. props->ShaderProps.HS.inputControlPoints =
  806. ConstMDToUint32(pProps->getOperand(idx++));
  807. props->ShaderProps.HS.outputControlPoints =
  808. ConstMDToUint32(pProps->getOperand(idx++));
  809. props->ShaderProps.HS.maxTessFactor =
  810. ConstMDToFloat(pProps->getOperand(idx++));
  811. break;
  812. case DXIL::ShaderKind::Domain:
  813. props->ShaderProps.DS.domain =
  814. (DXIL::TessellatorDomain)ConstMDToUint32(pProps->getOperand(idx++));
  815. props->ShaderProps.DS.inputControlPoints =
  816. ConstMDToUint32(pProps->getOperand(idx++));
  817. break;
  818. case DXIL::ShaderKind::Pixel:
  819. props->ShaderProps.PS.EarlyDepthStencil =
  820. ConstMDToUint32(pProps->getOperand(idx++));
  821. break;
  822. case DXIL::ShaderKind::AnyHit:
  823. case DXIL::ShaderKind::ClosestHit:
  824. bRayAttributes = true;
  825. case DXIL::ShaderKind::Miss:
  826. case DXIL::ShaderKind::Callable:
  827. // payload/params unioned and first:
  828. props->ShaderProps.Ray.payloadSizeInBytes =
  829. ConstMDToUint32(pProps->getOperand(idx++));
  830. if (bRayAttributes)
  831. props->ShaderProps.Ray.attributeSizeInBytes =
  832. ConstMDToUint32(pProps->getOperand(idx++));
  833. break;
  834. default:
  835. break;
  836. }
  837. return F;
  838. }
  839. MDTuple *DxilMDHelper::EmitDxilEntryProperties(uint64_t rawShaderFlag,
  840. const DxilFunctionProps &props,
  841. unsigned autoBindingSpace) {
  842. vector<Metadata *> MDVals;
  843. // DXIL shader flags.
  844. if (props.IsPS()) {
  845. if (props.ShaderProps.PS.EarlyDepthStencil) {
  846. ShaderFlags flags;
  847. flags.SetShaderFlagsRaw(rawShaderFlag);
  848. flags.SetForceEarlyDepthStencil(true);
  849. rawShaderFlag = flags.GetShaderFlagsRaw();
  850. }
  851. }
  852. if (rawShaderFlag != 0) {
  853. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderFlagsTag));
  854. MDVals.emplace_back(Uint64ToConstMD(rawShaderFlag));
  855. }
  856. // Add shader kind for lib entrys.
  857. if (m_pSM->IsLib() && props.shaderKind != DXIL::ShaderKind::Library) {
  858. MDVals.emplace_back(Uint32ToConstMD(kDxilShaderKindTag));
  859. MDVals.emplace_back(
  860. Uint32ToConstMD(static_cast<unsigned>(props.shaderKind)));
  861. }
  862. switch (props.shaderKind) {
  863. // Compute shader.
  864. case DXIL::ShaderKind::Compute: {
  865. auto &CS = props.ShaderProps.CS;
  866. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  867. vector<Metadata *> NumThreadVals;
  868. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[0]));
  869. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[1]));
  870. NumThreadVals.emplace_back(Uint32ToConstMD(CS.numThreads[2]));
  871. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  872. } break;
  873. // Geometry shader.
  874. case DXIL::ShaderKind::Geometry: {
  875. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  876. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  877. unsigned activeStreamMask = 0;
  878. for (size_t i = 0;
  879. i < _countof(props.ShaderProps.GS.streamPrimitiveTopologies); ++i) {
  880. if (props.ShaderProps.GS.streamPrimitiveTopologies[i] !=
  881. DXIL::PrimitiveTopology::Undefined) {
  882. activeStreamMask |= 1 << i;
  883. DXASSERT_NOMSG(topo == DXIL::PrimitiveTopology::Undefined ||
  884. topo ==
  885. props.ShaderProps.GS.streamPrimitiveTopologies[i]);
  886. topo = props.ShaderProps.GS.streamPrimitiveTopologies[i];
  887. }
  888. }
  889. MDTuple *pMDTuple =
  890. EmitDxilGSState(props.ShaderProps.GS.inputPrimitive,
  891. props.ShaderProps.GS.maxVertexCount, activeStreamMask,
  892. topo, props.ShaderProps.GS.instanceCount);
  893. MDVals.emplace_back(pMDTuple);
  894. } break;
  895. // Domain shader.
  896. case DXIL::ShaderKind::Domain: {
  897. auto &DS = props.ShaderProps.DS;
  898. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  899. MDTuple *pMDTuple = EmitDxilDSState(DS.domain, DS.inputControlPoints);
  900. MDVals.emplace_back(pMDTuple);
  901. } break;
  902. // Hull shader.
  903. case DXIL::ShaderKind::Hull: {
  904. auto &HS = props.ShaderProps.HS;
  905. MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  906. MDTuple *pMDTuple = EmitDxilHSState(
  907. HS.patchConstantFunc, HS.inputControlPoints, HS.outputControlPoints,
  908. HS.domain, HS.partition, HS.outputPrimitive, HS.maxTessFactor);
  909. MDVals.emplace_back(pMDTuple);
  910. } break;
  911. // Raytracing.
  912. case DXIL::ShaderKind::AnyHit:
  913. case DXIL::ShaderKind::ClosestHit: {
  914. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  915. MDVals.emplace_back(
  916. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  917. MDVals.emplace_back(Uint32ToConstMD(kDxilRayAttribSizeTag));
  918. MDVals.emplace_back(
  919. Uint32ToConstMD(props.ShaderProps.Ray.attributeSizeInBytes));
  920. } break;
  921. case DXIL::ShaderKind::Miss:
  922. case DXIL::ShaderKind::Callable: {
  923. MDVals.emplace_back(Uint32ToConstMD(kDxilRayPayloadSizeTag));
  924. MDVals.emplace_back(
  925. Uint32ToConstMD(props.ShaderProps.Ray.payloadSizeInBytes));
  926. } break;
  927. default:
  928. break;
  929. }
  930. if (autoBindingSpace != UINT_MAX && m_pSM->IsSMAtLeast(6, 3)) {
  931. MDVals.emplace_back(Uint32ToConstMD(kDxilAutoBindingSpaceTag));
  932. MDVals.emplace_back(
  933. MDNode::get(m_Ctx, {Uint32ToConstMD(autoBindingSpace)}));
  934. }
  935. if (!MDVals.empty())
  936. return MDNode::get(m_Ctx, MDVals);
  937. else
  938. return nullptr;
  939. }
  940. void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO,
  941. uint64_t &rawShaderFlag,
  942. DxilFunctionProps &props,
  943. uint32_t &autoBindingSpace) {
  944. if (MDO.get() == nullptr)
  945. return;
  946. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  947. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  948. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0,
  949. DXC_E_INCORRECT_DXIL_METADATA);
  950. bool bEarlyDepth = false;
  951. if (!m_pSM->IsLib()) {
  952. props.shaderKind = m_pSM->GetKind();
  953. } else {
  954. props.shaderKind = DXIL::ShaderKind::Library;
  955. }
  956. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  957. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  958. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  959. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  960. switch (Tag) {
  961. case DxilMDHelper::kDxilShaderFlagsTag: {
  962. rawShaderFlag = ConstMDToUint64(MDO);
  963. ShaderFlags flags;
  964. flags.SetShaderFlagsRaw(rawShaderFlag);
  965. bEarlyDepth = flags.GetForceEarlyDepthStencil();
  966. } break;
  967. case DxilMDHelper::kDxilNumThreadsTag: {
  968. DXASSERT(props.IsCS(), "else invalid shader kind");
  969. auto &CS = props.ShaderProps.CS;
  970. MDNode *pNode = cast<MDNode>(MDO.get());
  971. CS.numThreads[0] = ConstMDToUint32(pNode->getOperand(0));
  972. CS.numThreads[1] = ConstMDToUint32(pNode->getOperand(1));
  973. CS.numThreads[2] = ConstMDToUint32(pNode->getOperand(2));
  974. } break;
  975. case DxilMDHelper::kDxilGSStateTag: {
  976. DXASSERT(props.IsGS(), "else invalid shader kind");
  977. auto &GS = props.ShaderProps.GS;
  978. DXIL::PrimitiveTopology topo = DXIL::PrimitiveTopology::Undefined;
  979. unsigned activeStreamMask;
  980. LoadDxilGSState(MDO, GS.inputPrimitive, GS.maxVertexCount,
  981. activeStreamMask, topo, GS.instanceCount);
  982. if (topo != DXIL::PrimitiveTopology::Undefined) {
  983. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  984. unsigned mask = 1 << i;
  985. if (activeStreamMask & mask) {
  986. GS.streamPrimitiveTopologies[i] = topo;
  987. } else {
  988. GS.streamPrimitiveTopologies[i] =
  989. DXIL::PrimitiveTopology::Undefined;
  990. }
  991. }
  992. }
  993. } break;
  994. case DxilMDHelper::kDxilDSStateTag: {
  995. DXASSERT(props.IsDS(), "else invalid shader kind");
  996. auto &DS = props.ShaderProps.DS;
  997. LoadDxilDSState(MDO, DS.domain, DS.inputControlPoints);
  998. } break;
  999. case DxilMDHelper::kDxilHSStateTag: {
  1000. DXASSERT(props.IsHS(), "else invalid shader kind");
  1001. auto &HS = props.ShaderProps.HS;
  1002. LoadDxilHSState(MDO, HS.patchConstantFunc, HS.inputControlPoints,
  1003. HS.outputControlPoints, HS.domain, HS.partition,
  1004. HS.outputPrimitive, HS.maxTessFactor);
  1005. } break;
  1006. case DxilMDHelper::kDxilAutoBindingSpaceTag: {
  1007. MDNode *pNode = cast<MDNode>(MDO.get());
  1008. autoBindingSpace = ConstMDToUint32(pNode->getOperand(0));
  1009. break;
  1010. }
  1011. case DxilMDHelper::kDxilRayPayloadSizeTag: {
  1012. DXASSERT(props.IsAnyHit() || props.IsClosestHit() || props.IsMiss() ||
  1013. props.IsCallable(),
  1014. "else invalid shader kind");
  1015. props.ShaderProps.Ray.payloadSizeInBytes =
  1016. ConstMDToUint32(MDO);
  1017. } break;
  1018. case DxilMDHelper::kDxilRayAttribSizeTag: {
  1019. DXASSERT(props.IsAnyHit() || props.IsClosestHit(),
  1020. "else invalid shader kind");
  1021. props.ShaderProps.Ray.attributeSizeInBytes =
  1022. ConstMDToUint32(MDO);
  1023. } break;
  1024. case DxilMDHelper::kDxilShaderKindTag: {
  1025. DXIL::ShaderKind kind =
  1026. static_cast<DXIL::ShaderKind>(ConstMDToUint32(MDO));
  1027. DXASSERT(props.shaderKind == DXIL::ShaderKind::Library,
  1028. "else invalid shader kind");
  1029. props.shaderKind = kind;
  1030. } break;
  1031. default:
  1032. DXASSERT(false, "Unknown extended shader properties tag");
  1033. break;
  1034. }
  1035. }
  1036. if (bEarlyDepth) {
  1037. DXASSERT(props.IsPS(), "else invalid shader kind");
  1038. props.ShaderProps.PS.EarlyDepthStencil = true;
  1039. }
  1040. }
  1041. MDTuple *
  1042. DxilMDHelper::EmitDxilFunctionProps(const hlsl::DxilFunctionProps *props,
  1043. const Function *F) {
  1044. bool bRayAttributes = false;
  1045. Metadata *MDVals[30];
  1046. std::fill(MDVals, MDVals + _countof(MDVals), nullptr);
  1047. unsigned valIdx = 0;
  1048. MDVals[valIdx++] = ValueAsMetadata::get(const_cast<Function*>(F));
  1049. MDVals[valIdx++] = Uint32ToConstMD(static_cast<unsigned>(props->shaderKind));
  1050. switch (props->shaderKind) {
  1051. case DXIL::ShaderKind::Compute:
  1052. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[0]);
  1053. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[1]);
  1054. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.CS.numThreads[2]);
  1055. break;
  1056. case DXIL::ShaderKind::Geometry:
  1057. MDVals[valIdx++] =
  1058. Uint8ToConstMD((uint8_t)props->ShaderProps.GS.inputPrimitive);
  1059. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.maxVertexCount);
  1060. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.GS.instanceCount);
  1061. for (size_t i = 0;
  1062. i < _countof(props->ShaderProps.GS.streamPrimitiveTopologies); ++i)
  1063. MDVals[valIdx++] = Uint8ToConstMD(
  1064. (uint8_t)props->ShaderProps.GS.streamPrimitiveTopologies[i]);
  1065. break;
  1066. case DXIL::ShaderKind::Hull:
  1067. MDVals[valIdx++] =
  1068. ValueAsMetadata::get(props->ShaderProps.HS.patchConstantFunc);
  1069. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.domain);
  1070. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.HS.partition);
  1071. MDVals[valIdx++] =
  1072. Uint8ToConstMD((uint8_t)props->ShaderProps.HS.outputPrimitive);
  1073. MDVals[valIdx++] =
  1074. Uint32ToConstMD(props->ShaderProps.HS.inputControlPoints);
  1075. MDVals[valIdx++] =
  1076. Uint32ToConstMD(props->ShaderProps.HS.outputControlPoints);
  1077. MDVals[valIdx++] = FloatToConstMD(props->ShaderProps.HS.maxTessFactor);
  1078. break;
  1079. case DXIL::ShaderKind::Domain:
  1080. MDVals[valIdx++] = Uint8ToConstMD((uint8_t)props->ShaderProps.DS.domain);
  1081. MDVals[valIdx++] =
  1082. Uint32ToConstMD(props->ShaderProps.DS.inputControlPoints);
  1083. break;
  1084. case DXIL::ShaderKind::Pixel:
  1085. MDVals[valIdx++] = BoolToConstMD(props->ShaderProps.PS.EarlyDepthStencil);
  1086. break;
  1087. case DXIL::ShaderKind::AnyHit:
  1088. case DXIL::ShaderKind::ClosestHit:
  1089. bRayAttributes = true;
  1090. case DXIL::ShaderKind::Miss:
  1091. case DXIL::ShaderKind::Callable:
  1092. // payload/params unioned and first:
  1093. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.payloadSizeInBytes);
  1094. if (bRayAttributes)
  1095. MDVals[valIdx++] = Uint32ToConstMD(props->ShaderProps.Ray.attributeSizeInBytes);
  1096. break;
  1097. default:
  1098. break;
  1099. }
  1100. return MDTuple::get(m_Ctx, ArrayRef<llvm::Metadata *>(MDVals, valIdx));
  1101. }
  1102. void DxilMDHelper::EmitDxilViewIdState(DxilViewIdState &ViewIdState) {
  1103. const vector<unsigned> &Data = ViewIdState.GetSerialized();
  1104. // If all UINTs are zero, do not emit ViewIdState.
  1105. if (!std::any_of(Data.begin(), Data.end(), [](unsigned e){return e!=0;}))
  1106. return;
  1107. Constant *V = ConstantDataArray::get(m_Ctx, ArrayRef<uint32_t>(Data));
  1108. NamedMDNode *pViewIdNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1109. IFTBOOL(pViewIdNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1110. pViewIdNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilViewIdStateMDName);
  1111. pViewIdNamedMD->addOperand(MDNode::get(m_Ctx, {ConstantAsMetadata::get(V)}));
  1112. }
  1113. void DxilMDHelper::LoadDxilViewIdState(DxilViewIdState &ViewIdState) {
  1114. NamedMDNode *pViewIdStateNamedMD = m_pModule->getNamedMetadata(kDxilViewIdStateMDName);
  1115. if(!pViewIdStateNamedMD)
  1116. return;
  1117. IFTBOOL(pViewIdStateNamedMD->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1118. MDNode *pNode = pViewIdStateNamedMD->getOperand(0);
  1119. IFTBOOL(pNode->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1120. const MDOperand &MDO = pNode->getOperand(0);
  1121. const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MDO.get());
  1122. IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1123. if (isa<ConstantAggregateZero>(pMetaData->getValue()))
  1124. return;
  1125. const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pMetaData->getValue());
  1126. IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1127. IFTBOOL(pData->getElementType() == Type::getInt32Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
  1128. IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
  1129. (pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1130. ViewIdState.Deserialize((const unsigned *)pData->getRawDataValues().begin(),
  1131. (unsigned)pData->getRawDataValues().size() / 4);
  1132. }
  1133. MDNode *DxilMDHelper::EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<DXIL::ControlFlowHint> &hints) {
  1134. SmallVector<Metadata *, 4> Args;
  1135. // Reserve operand 0 for self reference.
  1136. auto TempNode = MDNode::getTemporary(Ctx, None);
  1137. Args.emplace_back(TempNode.get());
  1138. Args.emplace_back(MDString::get(Ctx, kDxilControlFlowHintMDName));
  1139. for (DXIL::ControlFlowHint &hint : hints)
  1140. Args.emplace_back(Uint32ToConstMD(static_cast<unsigned>(hint), Ctx));
  1141. MDNode *hintsNode = MDNode::get(Ctx, Args);
  1142. // Set the first operand to itself.
  1143. hintsNode->replaceOperandWith(0, hintsNode);
  1144. return hintsNode;
  1145. }
  1146. MDTuple *DxilMDHelper::EmitDxilSampler(const DxilSampler &S) {
  1147. Metadata *MDVals[kDxilSamplerNumFields];
  1148. EmitDxilResourceBase(S, &MDVals[0]);
  1149. // Sampler-specific fields.
  1150. MDVals[kDxilSamplerType ] = Uint32ToConstMD((unsigned)S.GetSamplerKind());
  1151. // Name-value list of extended properties.
  1152. MDVals[kDxilSamplerNameValueList] = nullptr;
  1153. vector<Metadata *> MDExtraVals;
  1154. m_ExtraPropertyHelper->EmitSamplerProperties(S, MDExtraVals);
  1155. if (!MDExtraVals.empty()) {
  1156. MDVals[kDxilSamplerNameValueList] = MDNode::get(m_Ctx, MDExtraVals);
  1157. }
  1158. return MDNode::get(m_Ctx, MDVals);
  1159. }
  1160. void DxilMDHelper::LoadDxilSampler(const MDOperand &MDO, DxilSampler &S) {
  1161. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1162. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1163. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1164. IFTBOOL(pTupleMD->getNumOperands() == kDxilSamplerNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1165. LoadDxilResourceBase(MDO, S);
  1166. // Sampler-specific fields.
  1167. S.SetSamplerKind((DxilSampler::SamplerKind)ConstMDToUint32(pTupleMD->getOperand(kDxilSamplerType)));
  1168. // Name-value list of extended properties.
  1169. m_ExtraPropertyHelper->LoadSamplerProperties(pTupleMD->getOperand(kDxilSamplerNameValueList), S);
  1170. }
  1171. const MDOperand &DxilMDHelper::GetResourceClass(llvm::MDNode *MD,
  1172. DXIL::ResourceClass &RC) {
  1173. IFTBOOL(MD->getNumOperands() >=
  1174. DxilMDHelper::kHLDxilResourceAttributeNumFields,
  1175. DXC_E_INCORRECT_DXIL_METADATA);
  1176. RC = static_cast<DxilResource::Class>(ConstMDToUint32(
  1177. MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeClass)));
  1178. return MD->getOperand(DxilMDHelper::kHLDxilResourceAttributeMeta);
  1179. }
  1180. void DxilMDHelper::LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD,
  1181. DxilResourceBase &R) {
  1182. DxilResource::Class RC = DxilResource::Class::Invalid;
  1183. const MDOperand &Meta = GetResourceClass(MD, RC);
  1184. switch (RC) {
  1185. case DxilResource::Class::CBuffer: {
  1186. DxilCBuffer CB;
  1187. LoadDxilCBuffer(Meta, CB);
  1188. R = CB;
  1189. } break;
  1190. case DxilResource::Class::Sampler: {
  1191. DxilSampler S;
  1192. LoadDxilSampler(Meta, S);
  1193. R = S;
  1194. } break;
  1195. case DxilResource::Class::SRV: {
  1196. DxilResource Res;
  1197. LoadDxilSRV(Meta, Res);
  1198. R = Res;
  1199. } break;
  1200. case DxilResource::Class::UAV: {
  1201. DxilResource Res;
  1202. LoadDxilUAV(Meta, Res);
  1203. R = Res;
  1204. } break;
  1205. default:
  1206. DXASSERT(0, "Invalid metadata");
  1207. }
  1208. }
  1209. void DxilMDHelper::LoadDxilResourceFromMDNode(llvm::MDNode *MD,
  1210. DxilResource &R) {
  1211. DxilResource::Class RC = DxilResource::Class::Invalid;
  1212. const MDOperand &Meta = GetResourceClass(MD, RC);
  1213. switch (RC) {
  1214. case DxilResource::Class::SRV: {
  1215. LoadDxilSRV(Meta, R);
  1216. } break;
  1217. case DxilResource::Class::UAV: {
  1218. LoadDxilUAV(Meta, R);
  1219. } break;
  1220. default:
  1221. DXASSERT(0, "Invalid metadata");
  1222. }
  1223. }
  1224. void DxilMDHelper::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  1225. DxilResource::Class RC = DxilResource::Class::Invalid;
  1226. const MDOperand &Meta = GetResourceClass(MD, RC);
  1227. switch (RC) {
  1228. case DxilResource::Class::Sampler: {
  1229. LoadDxilSampler(Meta, S);
  1230. } break;
  1231. default:
  1232. DXASSERT(0, "Invalid metadata");
  1233. }
  1234. }
  1235. //
  1236. // DxilExtraPropertyHelper shader-specific methods.
  1237. //
  1238. MDTuple *DxilMDHelper::EmitDxilGSState(DXIL::InputPrimitive Primitive,
  1239. unsigned MaxVertexCount,
  1240. unsigned ActiveStreamMask,
  1241. DXIL::PrimitiveTopology StreamPrimitiveTopology,
  1242. unsigned GSInstanceCount) {
  1243. Metadata *MDVals[kDxilGSStateNumFields];
  1244. MDVals[kDxilGSStateInputPrimitive ] = Uint32ToConstMD((unsigned)Primitive);
  1245. MDVals[kDxilGSStateMaxVertexCount ] = Uint32ToConstMD(MaxVertexCount);
  1246. MDVals[kDxilGSStateActiveStreamMask ] = Uint32ToConstMD(ActiveStreamMask);
  1247. MDVals[kDxilGSStateOutputStreamTopology] = Uint32ToConstMD((unsigned)StreamPrimitiveTopology);
  1248. MDVals[kDxilGSStateGSInstanceCount ] = Uint32ToConstMD(GSInstanceCount);
  1249. return MDNode::get(m_Ctx, MDVals);
  1250. }
  1251. void DxilMDHelper::LoadDxilGSState(const MDOperand &MDO,
  1252. DXIL::InputPrimitive &Primitive,
  1253. unsigned &MaxVertexCount,
  1254. unsigned &ActiveStreamMask,
  1255. DXIL::PrimitiveTopology &StreamPrimitiveTopology,
  1256. unsigned &GSInstanceCount) {
  1257. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1258. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1259. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1260. IFTBOOL(pTupleMD->getNumOperands() == kDxilGSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1261. Primitive = (DXIL::InputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateInputPrimitive));
  1262. MaxVertexCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateMaxVertexCount));
  1263. ActiveStreamMask = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateActiveStreamMask));
  1264. StreamPrimitiveTopology = (DXIL::PrimitiveTopology)ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateOutputStreamTopology));
  1265. GSInstanceCount = ConstMDToUint32(pTupleMD->getOperand(kDxilGSStateGSInstanceCount));
  1266. }
  1267. MDTuple *DxilMDHelper::EmitDxilDSState(DXIL::TessellatorDomain Domain, unsigned InputControlPointCount) {
  1268. Metadata *MDVals[kDxilDSStateNumFields];
  1269. MDVals[kDxilDSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)Domain);
  1270. MDVals[kDxilDSStateInputControlPointCount] = Uint32ToConstMD(InputControlPointCount);
  1271. return MDNode::get(m_Ctx, MDVals);
  1272. }
  1273. void DxilMDHelper::LoadDxilDSState(const MDOperand &MDO,
  1274. DXIL::TessellatorDomain &Domain,
  1275. unsigned &InputControlPointCount) {
  1276. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1277. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1278. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1279. IFTBOOL(pTupleMD->getNumOperands() == kDxilDSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1280. Domain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateTessellatorDomain));
  1281. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilDSStateInputControlPointCount));
  1282. }
  1283. MDTuple *DxilMDHelper::EmitDxilHSState(Function *pPatchConstantFunction,
  1284. unsigned InputControlPointCount,
  1285. unsigned OutputControlPointCount,
  1286. DXIL::TessellatorDomain TessDomain,
  1287. DXIL::TessellatorPartitioning TessPartitioning,
  1288. DXIL::TessellatorOutputPrimitive TessOutputPrimitive,
  1289. float MaxTessFactor) {
  1290. Metadata *MDVals[kDxilHSStateNumFields];
  1291. MDVals[kDxilHSStatePatchConstantFunction ] = ValueAsMetadata::get(pPatchConstantFunction);
  1292. MDVals[kDxilHSStateInputControlPointCount ] = Uint32ToConstMD(InputControlPointCount);
  1293. MDVals[kDxilHSStateOutputControlPointCount ] = Uint32ToConstMD(OutputControlPointCount);
  1294. MDVals[kDxilHSStateTessellatorDomain ] = Uint32ToConstMD((unsigned)TessDomain);
  1295. MDVals[kDxilHSStateTessellatorPartitioning ] = Uint32ToConstMD((unsigned)TessPartitioning);
  1296. MDVals[kDxilHSStateTessellatorOutputPrimitive] = Uint32ToConstMD((unsigned)TessOutputPrimitive);
  1297. MDVals[kDxilHSStateMaxTessellationFactor ] = FloatToConstMD(MaxTessFactor);
  1298. return MDNode::get(m_Ctx, MDVals);
  1299. }
  1300. void DxilMDHelper::LoadDxilHSState(const MDOperand &MDO,
  1301. Function *&pPatchConstantFunction,
  1302. unsigned &InputControlPointCount,
  1303. unsigned &OutputControlPointCount,
  1304. DXIL::TessellatorDomain &TessDomain,
  1305. DXIL::TessellatorPartitioning &TessPartitioning,
  1306. DXIL::TessellatorOutputPrimitive &TessOutputPrimitive,
  1307. float &MaxTessFactor) {
  1308. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1309. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1310. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1311. IFTBOOL(pTupleMD->getNumOperands() == kDxilHSStateNumFields, DXC_E_INCORRECT_DXIL_METADATA);
  1312. pPatchConstantFunction = dyn_cast<Function>(ValueMDToValue(pTupleMD->getOperand(kDxilHSStatePatchConstantFunction)));
  1313. InputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateInputControlPointCount));
  1314. OutputControlPointCount = ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateOutputControlPointCount));
  1315. TessDomain = (DXIL::TessellatorDomain)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorDomain));
  1316. TessPartitioning = (DXIL::TessellatorPartitioning)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorPartitioning));
  1317. TessOutputPrimitive = (DXIL::TessellatorOutputPrimitive)ConstMDToUint32(pTupleMD->getOperand(kDxilHSStateTessellatorOutputPrimitive));
  1318. MaxTessFactor = ConstMDToFloat(pTupleMD->getOperand(kDxilHSStateMaxTessellationFactor));
  1319. }
  1320. //
  1321. // DxilExtraPropertyHelper methods.
  1322. //
  1323. DxilMDHelper::ExtraPropertyHelper::ExtraPropertyHelper(Module *pModule)
  1324. : m_Ctx(pModule->getContext())
  1325. , m_pModule(pModule) {
  1326. }
  1327. DxilExtraPropertyHelper::DxilExtraPropertyHelper(Module *pModule)
  1328. : ExtraPropertyHelper(pModule) {
  1329. }
  1330. void DxilExtraPropertyHelper::EmitSRVProperties(const DxilResource &SRV, std::vector<Metadata *> &MDVals) {
  1331. // Element type for typed resource.
  1332. if (!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer()) {
  1333. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  1334. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)SRV.GetCompType().GetKind(), m_Ctx));
  1335. }
  1336. // Element stride for structured buffer.
  1337. if (SRV.IsStructuredBuffer()) {
  1338. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  1339. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SRV.GetElementStride(), m_Ctx));
  1340. }
  1341. }
  1342. void DxilExtraPropertyHelper::LoadSRVProperties(const MDOperand &MDO, DxilResource &SRV) {
  1343. SRV.SetElementStride(SRV.IsRawBuffer() ? 1 : 4);
  1344. SRV.SetCompType(CompType());
  1345. if (MDO.get() == nullptr) {
  1346. return;
  1347. }
  1348. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1349. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1350. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1351. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1352. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1353. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1354. switch (Tag) {
  1355. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  1356. DXASSERT_NOMSG(!SRV.IsStructuredBuffer() && !SRV.IsRawBuffer());
  1357. SRV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  1358. break;
  1359. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  1360. DXASSERT_NOMSG(SRV.IsStructuredBuffer());
  1361. SRV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  1362. break;
  1363. default:
  1364. DXASSERT(false, "Unknown resource record tag");
  1365. }
  1366. }
  1367. }
  1368. void DxilExtraPropertyHelper::EmitUAVProperties(const DxilResource &UAV, std::vector<Metadata *> &MDVals) {
  1369. // Element type for typed RW resource.
  1370. if (!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer()) {
  1371. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilTypedBufferElementTypeTag, m_Ctx));
  1372. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD((unsigned)UAV.GetCompType().GetKind(), m_Ctx));
  1373. }
  1374. // Element stride for structured RW buffer.
  1375. if (UAV.IsStructuredBuffer()) {
  1376. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilStructuredBufferElementStrideTag, m_Ctx));
  1377. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(UAV.GetElementStride(), m_Ctx));
  1378. }
  1379. }
  1380. void DxilExtraPropertyHelper::LoadUAVProperties(const MDOperand &MDO, DxilResource &UAV) {
  1381. UAV.SetElementStride(UAV.IsRawBuffer() ? 1 : 4);
  1382. UAV.SetCompType(CompType());
  1383. if (MDO.get() == nullptr) {
  1384. return;
  1385. }
  1386. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1387. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1388. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1389. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1390. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1391. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1392. switch (Tag) {
  1393. case DxilMDHelper::kDxilTypedBufferElementTypeTag:
  1394. DXASSERT_NOMSG(!UAV.IsStructuredBuffer() && !UAV.IsRawBuffer());
  1395. UAV.SetCompType(CompType(DxilMDHelper::ConstMDToUint32(MDO)));
  1396. break;
  1397. case DxilMDHelper::kDxilStructuredBufferElementStrideTag:
  1398. DXASSERT_NOMSG(UAV.IsStructuredBuffer());
  1399. UAV.SetElementStride(DxilMDHelper::ConstMDToUint32(MDO));
  1400. break;
  1401. default:
  1402. DXASSERT(false, "Unknown resource record tag");
  1403. }
  1404. }
  1405. }
  1406. void DxilExtraPropertyHelper::EmitCBufferProperties(const DxilCBuffer &CB, vector<Metadata *> &MDVals) {
  1407. // Emit property to preserve tbuffer kind
  1408. if (CB.GetKind() == DXIL::ResourceKind::TBuffer) {
  1409. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kHLCBufferIsTBufferTag, m_Ctx));
  1410. MDVals.emplace_back(DxilMDHelper::BoolToConstMD(true, m_Ctx));
  1411. }
  1412. }
  1413. void DxilExtraPropertyHelper::LoadCBufferProperties(const MDOperand &MDO, DxilCBuffer &CB) {
  1414. if (MDO.get() == nullptr)
  1415. return;
  1416. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1417. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1418. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1419. // Override kind for tbuffer that has not yet been converted to SRV.
  1420. CB.SetKind(DXIL::ResourceKind::CBuffer);
  1421. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1422. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1423. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1424. switch (Tag) {
  1425. case DxilMDHelper::kHLCBufferIsTBufferTag:
  1426. if (DxilMDHelper::ConstMDToBool(MDO)) {
  1427. CB.SetKind(DXIL::ResourceKind::TBuffer);
  1428. }
  1429. break;
  1430. default:
  1431. DXASSERT(false, "Unknown cbuffer tag");
  1432. }
  1433. }
  1434. }
  1435. void DxilExtraPropertyHelper::EmitSamplerProperties(const DxilSampler &S, std::vector<Metadata *> &MDVals) {
  1436. // Nothing yet.
  1437. }
  1438. void DxilExtraPropertyHelper::LoadSamplerProperties(const MDOperand &MDO, DxilSampler &S) {
  1439. // Nothing yet.
  1440. }
  1441. void DxilExtraPropertyHelper::EmitSignatureElementProperties(const DxilSignatureElement &SE,
  1442. vector<Metadata *> &MDVals) {
  1443. // Output stream, if non-zero.
  1444. if (SE.GetOutputStream() != 0) {
  1445. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementOutputStreamTag, m_Ctx));
  1446. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetOutputStream(), m_Ctx));
  1447. }
  1448. // Mask of Dynamically indexed components.
  1449. if (SE.GetDynIdxCompMask() != 0) {
  1450. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag, m_Ctx));
  1451. MDVals.emplace_back(DxilMDHelper::Uint32ToConstMD(SE.GetDynIdxCompMask(), m_Ctx));
  1452. }
  1453. }
  1454. void DxilExtraPropertyHelper::LoadSignatureElementProperties(const MDOperand &MDO, DxilSignatureElement &SE) {
  1455. if (MDO.get() == nullptr)
  1456. return;
  1457. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1458. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1459. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1460. // Stream.
  1461. for (unsigned i = 0; i < pTupleMD->getNumOperands(); i += 2) {
  1462. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(i));
  1463. const MDOperand &MDO = pTupleMD->getOperand(i + 1);
  1464. switch (Tag) {
  1465. case DxilMDHelper::kDxilSignatureElementOutputStreamTag:
  1466. SE.SetOutputStream(DxilMDHelper::ConstMDToUint32(MDO));
  1467. break;
  1468. case DxilMDHelper::kHLSignatureElementGlobalSymbolTag:
  1469. break;
  1470. case DxilMDHelper::kDxilSignatureElementDynIdxCompMaskTag:
  1471. SE.SetDynIdxCompMask(DxilMDHelper::ConstMDToUint32(MDO));
  1472. break;
  1473. default:
  1474. DXASSERT(false, "Unknown signature element tag");
  1475. }
  1476. }
  1477. }
  1478. //
  1479. // Utilities.
  1480. //
  1481. bool DxilMDHelper::IsKnownNamedMetaData(const llvm::NamedMDNode &Node) {
  1482. StringRef name = Node.getName();
  1483. for (unsigned i = 0; i < DxilMDNames.size(); i++) {
  1484. if (name == DxilMDNames[i]) {
  1485. return true;
  1486. }
  1487. }
  1488. return false;
  1489. }
  1490. void DxilMDHelper::combineDxilMetadata(llvm::Instruction *K,
  1491. const llvm::Instruction *J) {
  1492. if (IsMarkedNonUniform(J))
  1493. MarkNonUniform(K);
  1494. if (IsMarkedPrecise(J))
  1495. MarkPrecise(K);
  1496. }
  1497. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v, LLVMContext &Ctx) {
  1498. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1499. }
  1500. ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v) {
  1501. return DxilMDHelper::Int32ToConstMD(v, m_Ctx);
  1502. }
  1503. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v, LLVMContext &Ctx) {
  1504. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
  1505. }
  1506. ConstantAsMetadata *DxilMDHelper::Uint32ToConstMD(unsigned v) {
  1507. return DxilMDHelper::Uint32ToConstMD(v, m_Ctx);
  1508. }
  1509. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v, LLVMContext &Ctx) {
  1510. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 64), APInt(64, v)));
  1511. }
  1512. ConstantAsMetadata *DxilMDHelper::Uint64ToConstMD(uint64_t v) {
  1513. return DxilMDHelper::Uint64ToConstMD(v, m_Ctx);
  1514. }
  1515. ConstantAsMetadata *DxilMDHelper::Int8ToConstMD(int8_t v) {
  1516. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1517. }
  1518. ConstantAsMetadata *DxilMDHelper::Uint8ToConstMD(uint8_t v) {
  1519. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)));
  1520. }
  1521. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v, LLVMContext &Ctx) {
  1522. return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 1), APInt(1, v ? 1 : 0)));
  1523. }
  1524. ConstantAsMetadata *DxilMDHelper::BoolToConstMD(bool v) {
  1525. return DxilMDHelper::BoolToConstMD(v, m_Ctx);
  1526. }
  1527. ConstantAsMetadata *DxilMDHelper::FloatToConstMD(float v) {
  1528. return ConstantAsMetadata::get(ConstantFP::get(m_Ctx, APFloat(v)));
  1529. }
  1530. int32_t DxilMDHelper::ConstMDToInt32(const MDOperand &MDO) {
  1531. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1532. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1533. return (int32_t)pConst->getZExtValue();
  1534. }
  1535. unsigned DxilMDHelper::ConstMDToUint32(const MDOperand &MDO) {
  1536. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1537. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1538. return (unsigned)pConst->getZExtValue();
  1539. }
  1540. uint64_t DxilMDHelper::ConstMDToUint64(const MDOperand &MDO) {
  1541. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1542. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1543. return pConst->getZExtValue();
  1544. }
  1545. int8_t DxilMDHelper::ConstMDToInt8(const MDOperand &MDO) {
  1546. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1547. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1548. return (int8_t)pConst->getZExtValue();
  1549. }
  1550. uint8_t DxilMDHelper::ConstMDToUint8(const MDOperand &MDO) {
  1551. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1552. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1553. return (uint8_t)pConst->getZExtValue();
  1554. }
  1555. bool DxilMDHelper::ConstMDToBool(const MDOperand &MDO) {
  1556. ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
  1557. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1558. return pConst->getZExtValue() != 0;
  1559. }
  1560. float DxilMDHelper::ConstMDToFloat(const MDOperand &MDO) {
  1561. ConstantFP *pConst = mdconst::extract<ConstantFP>(MDO);
  1562. IFTBOOL(pConst != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1563. return pConst->getValueAPF().convertToFloat();
  1564. }
  1565. string DxilMDHelper::StringMDToString(const MDOperand &MDO) {
  1566. MDString *pMDString = dyn_cast<MDString>(MDO.get());
  1567. IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1568. return pMDString->getString();
  1569. }
  1570. Value *DxilMDHelper::ValueMDToValue(const MDOperand &MDO) {
  1571. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1572. ValueAsMetadata *pValAsMD = dyn_cast<ValueAsMetadata>(MDO.get());
  1573. IFTBOOL(pValAsMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1574. Value *pValue = pValAsMD->getValue();
  1575. IFTBOOL(pValue != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1576. return pValue;
  1577. }
  1578. MDTuple *DxilMDHelper::Uint32VectorToConstMDTuple(const std::vector<unsigned> &Vec) {
  1579. vector<Metadata *> MDVals;
  1580. MDVals.resize(Vec.size());
  1581. for (size_t i = 0; i < Vec.size(); i++) {
  1582. MDVals[i] = Uint32ToConstMD(Vec[i]);
  1583. }
  1584. return MDNode::get(m_Ctx, MDVals);
  1585. }
  1586. void DxilMDHelper::ConstMDTupleToUint32Vector(MDTuple *pTupleMD, std::vector<unsigned> &Vec) {
  1587. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1588. Vec.resize(pTupleMD->getNumOperands());
  1589. for (size_t i = 0; i < pTupleMD->getNumOperands(); i++) {
  1590. Vec[i] = ConstMDToUint32(pTupleMD->getOperand(i));
  1591. }
  1592. }
  1593. bool DxilMDHelper::IsMarkedPrecise(const Instruction *inst) {
  1594. int32_t val = 0;
  1595. if (MDNode *precise = inst->getMetadata(kDxilPreciseAttributeMDName)) {
  1596. assert(precise->getNumOperands() == 1);
  1597. val = ConstMDToInt32(precise->getOperand(0));
  1598. }
  1599. return val;
  1600. }
  1601. void DxilMDHelper::MarkPrecise(Instruction *I) {
  1602. LLVMContext &Ctx = I->getContext();
  1603. MDNode *preciseNode = MDNode::get(
  1604. Ctx,
  1605. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  1606. I->setMetadata(DxilMDHelper::kDxilPreciseAttributeMDName, preciseNode);
  1607. }
  1608. bool DxilMDHelper::IsMarkedNonUniform(const Instruction *inst) {
  1609. int32_t val = 0;
  1610. if (MDNode *precise = inst->getMetadata(kDxilNonUniformAttributeMDName)) {
  1611. assert(precise->getNumOperands() == 1);
  1612. val = ConstMDToInt32(precise->getOperand(0));
  1613. }
  1614. return val;
  1615. }
  1616. void DxilMDHelper::MarkNonUniform(Instruction *I) {
  1617. LLVMContext &Ctx = I->getContext();
  1618. MDNode *preciseNode = MDNode::get(
  1619. Ctx,
  1620. { ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
  1621. I->setMetadata(DxilMDHelper::kDxilNonUniformAttributeMDName, preciseNode);
  1622. }
  1623. } // namespace hlsl