DxilMetadataHelper.cpp 110 KB

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