HLSignatureLower.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // HLSignatureLower.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. // Lower signatures of entry function to DXIL LoadInput/StoreOutput. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "HLSignatureLower.h"
  12. #include "dxc/HLSL/DxilOperations.h"
  13. #include "dxc/HLSL/DxilSignatureElement.h"
  14. #include "dxc/HLSL/DxilSigPoint.h"
  15. #include "dxc/Support/Global.h"
  16. #include "dxc/HLSL/DxilTypeSystem.h"
  17. #include "dxc/HLSL/DxilSemantic.h"
  18. #include "dxc/HLSL/HLModule.h"
  19. #include "dxc/HLSL/HLMatrixLowerHelper.h"
  20. #include "dxc/HlslIntrinsicOp.h"
  21. #include "llvm/IR/IRBuilder.h"
  22. #include "llvm/IR/DebugInfo.h"
  23. #include "llvm/Transforms/Utils/Local.h"
  24. #include "llvm/IR/IntrinsicInst.h"
  25. using namespace llvm;
  26. using namespace hlsl;
  27. namespace {
  28. // Decompose semantic name (eg FOO1=>FOO,1), change interp mode for SV_Position.
  29. // Return semantic index.
  30. unsigned UpateSemanticAndInterpMode(StringRef &semName,
  31. DXIL::InterpolationMode &mode,
  32. DXIL::SigPointKind kind,
  33. LLVMContext &Context) {
  34. llvm::StringRef baseSemName; // The 'FOO' in 'FOO1'.
  35. uint32_t semIndex; // The '1' in 'FOO1'
  36. // Split semName and index.
  37. Semantic::DecomposeNameAndIndex(semName, &baseSemName, &semIndex);
  38. semName = baseSemName;
  39. const Semantic *semantic = Semantic::GetByName(semName, kind);
  40. if (semantic && semantic->GetKind() == Semantic::Kind::Position) {
  41. // Update interp mode to no_perspective version for SV_Position.
  42. switch (mode) {
  43. case InterpolationMode::Kind::LinearCentroid:
  44. mode = InterpolationMode::Kind::LinearNoperspectiveCentroid;
  45. break;
  46. case InterpolationMode::Kind::LinearSample:
  47. mode = InterpolationMode::Kind::LinearNoperspectiveSample;
  48. break;
  49. case InterpolationMode::Kind::Linear:
  50. mode = InterpolationMode::Kind::LinearNoperspective;
  51. break;
  52. case InterpolationMode::Kind::Constant: {
  53. Context.emitError("invalid interpolation mode for SV_Position");
  54. } break;
  55. }
  56. }
  57. return semIndex;
  58. }
  59. DxilSignatureElement *FindArgInSignature(Argument &arg,
  60. llvm::StringRef semantic,
  61. DXIL::InterpolationMode interpMode,
  62. DXIL::SigPointKind kind,
  63. DxilSignature &sig) {
  64. // Match output ID.
  65. unsigned semIndex =
  66. UpateSemanticAndInterpMode(semantic, interpMode, kind, arg.getContext());
  67. for (uint32_t i = 0; i < sig.GetElements().size(); i++) {
  68. DxilSignatureElement &SE = sig.GetElement(i);
  69. bool semNameMatch = semantic.equals_lower(SE.GetName());
  70. bool semIndexMatch = semIndex == SE.GetSemanticIndexVec()[0];
  71. if (semNameMatch && semIndexMatch) {
  72. // Find a match.
  73. return &SE;
  74. }
  75. }
  76. return nullptr;
  77. }
  78. } // namespace
  79. namespace {
  80. void replaceInputOutputWithIntrinsic(DXIL::SemanticKind semKind, Value *GV,
  81. OP *hlslOP, IRBuilder<> &Builder) {
  82. Type *Ty = GV->getType();
  83. if (Ty->isPointerTy())
  84. Ty = Ty->getPointerElementType();
  85. OP::OpCode opcode;
  86. switch (semKind) {
  87. case Semantic::Kind::DomainLocation:
  88. opcode = OP::OpCode::DomainLocation;
  89. break;
  90. case Semantic::Kind::OutputControlPointID:
  91. opcode = OP::OpCode::OutputControlPointID;
  92. break;
  93. case Semantic::Kind::GSInstanceID:
  94. opcode = OP::OpCode::GSInstanceID;
  95. break;
  96. case Semantic::Kind::PrimitiveID:
  97. opcode = OP::OpCode::PrimitiveID;
  98. break;
  99. case Semantic::Kind::SampleIndex:
  100. opcode = OP::OpCode::SampleIndex;
  101. break;
  102. case Semantic::Kind::Coverage:
  103. opcode = OP::OpCode::Coverage;
  104. break;
  105. case Semantic::Kind::InnerCoverage:
  106. opcode = OP::OpCode::InnerCoverage;
  107. break;
  108. case Semantic::Kind::ViewID:
  109. opcode = OP::OpCode::ViewID;
  110. break;
  111. default:
  112. DXASSERT(0, "invalid semantic");
  113. return;
  114. }
  115. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty->getScalarType());
  116. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  117. Value *newArg = nullptr;
  118. if (semKind == Semantic::Kind::DomainLocation) {
  119. unsigned vecSize = 1;
  120. if (Ty->isVectorTy())
  121. vecSize = Ty->getVectorNumElements();
  122. newArg = Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU8Const(0)});
  123. if (vecSize > 1) {
  124. Value *result = UndefValue::get(Ty);
  125. result = Builder.CreateInsertElement(result, newArg, (uint64_t)0);
  126. for (unsigned i = 1; i < vecSize; i++) {
  127. Value *newElt =
  128. Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU8Const(i)});
  129. result = Builder.CreateInsertElement(result, newElt, i);
  130. }
  131. newArg = result;
  132. }
  133. } else {
  134. newArg = Builder.CreateCall(dxilFunc, {OpArg});
  135. }
  136. if (newArg->getType() != GV->getType()) {
  137. DXASSERT_NOMSG(GV->getType()->isPointerTy());
  138. for (User *U : GV->users()) {
  139. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  140. LI->replaceAllUsesWith(newArg);
  141. }
  142. }
  143. } else {
  144. GV->replaceAllUsesWith(newArg);
  145. }
  146. }
  147. } // namespace
  148. void HLSignatureLower::ProcessArgument(Function *func,
  149. DxilFunctionAnnotation *funcAnnotation,
  150. Argument &arg, DxilFunctionProps &props,
  151. const ShaderModel *pSM,
  152. bool isPatchConstantFunction,
  153. bool forceOut, bool &hasClipPlane) {
  154. Type *Ty = arg.getType();
  155. DxilParameterAnnotation &paramAnnotation =
  156. funcAnnotation->GetParameterAnnotation(arg.getArgNo());
  157. hlsl::DxilParamInputQual qual =
  158. forceOut ? DxilParamInputQual::Out : paramAnnotation.GetParamInputQual();
  159. bool isInout = qual == DxilParamInputQual::Inout;
  160. // If this was an inout param, do the output side first
  161. if (isInout) {
  162. DXASSERT(!isPatchConstantFunction,
  163. "Patch Constant function should not have inout param");
  164. m_inoutArgSet.insert(&arg);
  165. const bool bForceOutTrue = true;
  166. ProcessArgument(func, funcAnnotation, arg, props, pSM,
  167. isPatchConstantFunction, bForceOutTrue, hasClipPlane);
  168. qual = DxilParamInputQual::In;
  169. }
  170. // Get stream index
  171. unsigned streamIdx = 0;
  172. switch (qual) {
  173. case DxilParamInputQual::OutStream1:
  174. streamIdx = 1;
  175. break;
  176. case DxilParamInputQual::OutStream2:
  177. streamIdx = 2;
  178. break;
  179. case DxilParamInputQual::OutStream3:
  180. streamIdx = 3;
  181. break;
  182. default:
  183. // Use streamIdx = 0 by default.
  184. break;
  185. }
  186. const SigPoint *sigPoint = SigPoint::GetSigPoint(
  187. SigPointFromInputQual(qual, props.shaderKind, isPatchConstantFunction));
  188. unsigned rows, cols;
  189. HLModule::GetParameterRowsAndCols(Ty, rows, cols, paramAnnotation);
  190. CompType EltTy = paramAnnotation.GetCompType();
  191. DXIL::InterpolationMode interpMode =
  192. paramAnnotation.GetInterpolationMode().GetKind();
  193. // Set undefined interpMode.
  194. if (!sigPoint->NeedsInterpMode())
  195. interpMode = InterpolationMode::Kind::Undefined;
  196. else if (interpMode == InterpolationMode::Kind::Undefined) {
  197. // Type-based default: linear for floats, constant for others.
  198. if (EltTy.IsFloatTy())
  199. interpMode = InterpolationMode::Kind::Linear;
  200. else
  201. interpMode = InterpolationMode::Kind::Constant;
  202. }
  203. llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
  204. if (semanticStr.empty()) {
  205. func->getContext().emitError(
  206. "Semantic must be defined for all parameters of an entry function or "
  207. "patch constant function");
  208. return;
  209. }
  210. UpateSemanticAndInterpMode(semanticStr, interpMode, sigPoint->GetKind(),
  211. arg.getContext());
  212. // Get Semantic interpretation, skipping if not in signature
  213. const Semantic *pSemantic = Semantic::GetByName(semanticStr);
  214. DXIL::SemanticInterpretationKind interpretation =
  215. SigPoint::GetInterpretation(pSemantic->GetKind(), sigPoint->GetKind(),
  216. pSM->GetMajor(), pSM->GetMinor());
  217. // Verify system value semantics do not overlap.
  218. // Note: Arbitrary are always in the signature and will be verified with a
  219. // different mechanism. For patch constant function, only validate patch
  220. // constant elements (others already validated on hull function)
  221. if (pSemantic->GetKind() != DXIL::SemanticKind::Arbitrary &&
  222. (!isPatchConstantFunction ||
  223. (!sigPoint->IsInput() && !sigPoint->IsOutput()))) {
  224. auto &SemanticUseMap =
  225. sigPoint->IsInput()
  226. ? m_InputSemanticsUsed
  227. : (sigPoint->IsOutput()
  228. ? m_OutputSemanticsUsed[streamIdx]
  229. : (sigPoint->IsPatchConstant() ? m_PatchConstantSemanticsUsed
  230. : m_OtherSemanticsUsed));
  231. if (SemanticUseMap.count((unsigned)pSemantic->GetKind()) > 0) {
  232. auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
  233. for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
  234. if (SemanticIndexSet.count(idx) > 0) {
  235. func->getContext().emitError(
  236. Twine("Parameter with semantic ") + semanticStr +
  237. Twine(" has overlapping semantic index at ") + Twine(idx));
  238. return;
  239. }
  240. }
  241. }
  242. auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
  243. for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
  244. SemanticIndexSet.emplace(idx);
  245. }
  246. // Enforce Coverage and InnerCoverage input mutual exclusivity
  247. if (sigPoint->IsInput()) {
  248. if ((pSemantic->GetKind() == DXIL::SemanticKind::Coverage &&
  249. SemanticUseMap.count((unsigned)DXIL::SemanticKind::InnerCoverage) >
  250. 0) ||
  251. (pSemantic->GetKind() == DXIL::SemanticKind::InnerCoverage &&
  252. SemanticUseMap.count((unsigned)DXIL::SemanticKind::Coverage) > 0)) {
  253. func->getContext().emitError(
  254. "Pixel shader inputs SV_Coverage and SV_InnerCoverage are mutually "
  255. "exclusive");
  256. return;
  257. }
  258. }
  259. }
  260. // Validate interpretation and replace argument usage with load/store
  261. // intrinsics
  262. {
  263. switch (interpretation) {
  264. case DXIL::SemanticInterpretationKind::NA:
  265. func->getContext().emitError(Twine("Semantic ") + semanticStr +
  266. Twine(" is invalid for shader model: ") +
  267. ShaderModel::GetKindName(props.shaderKind));
  268. return;
  269. case DXIL::SemanticInterpretationKind::NotInSig:
  270. case DXIL::SemanticInterpretationKind::Shadow: {
  271. IRBuilder<> funcBuilder(func->getEntryBlock().getFirstInsertionPt());
  272. if (DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(&arg)) {
  273. funcBuilder.SetCurrentDebugLocation(DDI->getDebugLoc());
  274. }
  275. replaceInputOutputWithIntrinsic(pSemantic->GetKind(), &arg, HLM.GetOP(),
  276. funcBuilder);
  277. if (interpretation == DXIL::SemanticInterpretationKind::NotInSig)
  278. return; // This argument should not be included in the signature
  279. break;
  280. }
  281. case DXIL::SemanticInterpretationKind::SV:
  282. case DXIL::SemanticInterpretationKind::SGV:
  283. case DXIL::SemanticInterpretationKind::Arb:
  284. case DXIL::SemanticInterpretationKind::Target:
  285. case DXIL::SemanticInterpretationKind::TessFactor:
  286. case DXIL::SemanticInterpretationKind::NotPacked:
  287. // Will be replaced with load/store intrinsics in
  288. // GenerateDxilInputsOutputs
  289. break;
  290. default:
  291. DXASSERT(false, "Unexpected SemanticInterpretationKind");
  292. return;
  293. }
  294. }
  295. // Determine signature this argument belongs in, if any
  296. DxilSignature *pSig = nullptr;
  297. DXIL::SignatureKind sigKind = sigPoint->GetSignatureKindWithFallback();
  298. switch (sigKind) {
  299. case DXIL::SignatureKind::Input:
  300. pSig = &EntrySig.InputSignature;
  301. break;
  302. case DXIL::SignatureKind::Output:
  303. pSig = &EntrySig.OutputSignature;
  304. break;
  305. case DXIL::SignatureKind::PatchConstant:
  306. pSig = &EntrySig.PatchConstantSignature;
  307. break;
  308. default:
  309. DXASSERT(false, "Expected real signature kind at this point");
  310. return; // No corresponding signature
  311. }
  312. // Create and add element to signature
  313. DxilSignatureElement *pSE = nullptr;
  314. {
  315. // Add signature element to appropriate maps
  316. if (isPatchConstantFunction &&
  317. sigKind != DXIL::SignatureKind::PatchConstant) {
  318. pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
  319. interpMode, sigPoint->GetKind(), *pSig);
  320. if (!pSE) {
  321. func->getContext().emitError(
  322. Twine("Signature element ") + semanticStr +
  323. Twine(", referred to by patch constant function, is not found in "
  324. "corresponding hull shader ") +
  325. (sigKind == DXIL::SignatureKind::Input ? "input." : "output."));
  326. return;
  327. }
  328. m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
  329. } else {
  330. std::unique_ptr<DxilSignatureElement> SE = pSig->CreateElement();
  331. pSE = SE.get();
  332. pSig->AppendElement(std::move(SE));
  333. pSE->SetSigPointKind(sigPoint->GetKind());
  334. pSE->Initialize(semanticStr, EltTy, interpMode, rows, cols,
  335. Semantic::kUndefinedRow, Semantic::kUndefinedCol,
  336. pSE->GetID(), paramAnnotation.GetSemanticIndexVec());
  337. m_sigValueMap[pSE] = &arg;
  338. }
  339. }
  340. if (paramAnnotation.IsPrecise())
  341. m_preciseSigSet.insert(pSE);
  342. if (sigKind == DXIL::SignatureKind::Output &&
  343. pSemantic->GetKind() == Semantic::Kind::Position && hasClipPlane) {
  344. GenerateClipPlanesForVS(&arg);
  345. hasClipPlane = false;
  346. }
  347. // Set Output Stream.
  348. if (streamIdx > 0)
  349. pSE->SetOutputStream(streamIdx);
  350. }
  351. void HLSignatureLower::CreateDxilSignatures() {
  352. DxilFunctionProps &props = HLM.GetDxilFunctionProps(Entry);
  353. const ShaderModel *pSM = HLM.GetShaderModel();
  354. DXASSERT(Entry->getReturnType()->isVoidTy(),
  355. "Should changed in SROA_Parameter_HLSL");
  356. DxilFunctionAnnotation *EntryAnnotation = HLM.GetFunctionAnnotation(Entry);
  357. DXASSERT(EntryAnnotation, "must have function annotation for entry function");
  358. bool bHasClipPlane =
  359. props.shaderKind == DXIL::ShaderKind::Vertex ? HasClipPlanes() : false;
  360. const bool isPatchConstantFunctionFalse = false;
  361. const bool bForOutFasle = false;
  362. for (Argument &arg : Entry->getArgumentList()) {
  363. Type *Ty = arg.getType();
  364. // Skip streamout obj.
  365. if (HLModule::IsStreamOutputPtrType(Ty))
  366. continue;
  367. ProcessArgument(Entry, EntryAnnotation, arg, props, pSM,
  368. isPatchConstantFunctionFalse, bForOutFasle, bHasClipPlane);
  369. }
  370. if (bHasClipPlane) {
  371. Entry->getContext().emitError("Cannot use clipplanes attribute without "
  372. "specifying a 4-component SV_Position "
  373. "output");
  374. }
  375. m_OtherSemanticsUsed.clear();
  376. if (props.shaderKind == DXIL::ShaderKind::Hull) {
  377. Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
  378. if (patchConstantFunc == nullptr) {
  379. Entry->getContext().emitError(
  380. "Patch constant function is not specified.");
  381. }
  382. DxilFunctionAnnotation *patchFuncAnnotation =
  383. HLM.GetFunctionAnnotation(patchConstantFunc);
  384. DXASSERT(patchFuncAnnotation,
  385. "must have function annotation for patch constant function");
  386. const bool isPatchConstantFunctionTrue = true;
  387. for (Argument &arg : patchConstantFunc->getArgumentList()) {
  388. ProcessArgument(patchConstantFunc, patchFuncAnnotation, arg, props, pSM,
  389. isPatchConstantFunctionTrue, bForOutFasle, bHasClipPlane);
  390. }
  391. }
  392. }
  393. // Allocate input/output slots
  394. void HLSignatureLower::AllocateDxilInputOutputs() {
  395. DxilFunctionProps &props = HLM.GetDxilFunctionProps(Entry);
  396. const ShaderModel *pSM = HLM.GetShaderModel();
  397. const HLOptions &opts = HLM.GetHLOptions();
  398. DXASSERT_NOMSG(opts.PackingStrategy <
  399. (unsigned)DXIL::PackingStrategy::Invalid);
  400. DXIL::PackingStrategy packing = (DXIL::PackingStrategy)opts.PackingStrategy;
  401. if (packing == DXIL::PackingStrategy::Default)
  402. packing = pSM->GetDefaultPackingStrategy();
  403. EntrySig.InputSignature.PackElements(packing);
  404. if (!EntrySig.InputSignature.IsFullyAllocated()) {
  405. HLM.GetCtx().emitError(
  406. "Failed to allocate all input signature elements in available space.");
  407. }
  408. EntrySig.OutputSignature.PackElements(packing);
  409. if (!EntrySig.OutputSignature.IsFullyAllocated()) {
  410. HLM.GetCtx().emitError(
  411. "Failed to allocate all output signature elements in available space.");
  412. }
  413. if (props.shaderKind == DXIL::ShaderKind::Hull ||
  414. props.shaderKind == DXIL::ShaderKind::Domain) {
  415. EntrySig.PatchConstantSignature.PackElements(packing);
  416. if (!EntrySig.PatchConstantSignature.IsFullyAllocated()) {
  417. HLM.GetCtx().emitError("Failed to allocate all patch constant signature "
  418. "elements in available space.");
  419. }
  420. }
  421. }
  422. namespace {
  423. // Helper functions and class for lower signature.
  424. void GenerateStOutput(Function *stOutput, MutableArrayRef<Value *> args,
  425. IRBuilder<> &Builder, bool cast) {
  426. if (cast) {
  427. Value *value = args[DXIL::OperandIndex::kStoreOutputValOpIdx];
  428. args[DXIL::OperandIndex::kStoreOutputValOpIdx] =
  429. Builder.CreateZExt(value, Builder.getInt32Ty());
  430. }
  431. Builder.CreateCall(stOutput, args);
  432. }
  433. void replaceStWithStOutput(Function *stOutput, StoreInst *stInst,
  434. Constant *OpArg, Constant *outputID, Value *idx,
  435. unsigned cols, bool bI1Cast) {
  436. IRBuilder<> Builder(stInst);
  437. Value *val = stInst->getValueOperand();
  438. if (VectorType *VT = dyn_cast<VectorType>(val->getType())) {
  439. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  440. for (unsigned col = 0; col < cols; col++) {
  441. Value *subVal = Builder.CreateExtractElement(val, col);
  442. Value *colIdx = Builder.getInt8(col);
  443. Value *args[] = {OpArg, outputID, idx, colIdx, subVal};
  444. GenerateStOutput(stOutput, args, Builder, bI1Cast);
  445. }
  446. // remove stInst
  447. stInst->eraseFromParent();
  448. } else if (!val->getType()->isArrayTy()) {
  449. // TODO: support case cols not 1
  450. DXASSERT(cols == 1, "only support scalar here");
  451. Value *colIdx = Builder.getInt8(0);
  452. Value *args[] = {OpArg, outputID, idx, colIdx, val};
  453. GenerateStOutput(stOutput, args, Builder, bI1Cast);
  454. // remove stInst
  455. stInst->eraseFromParent();
  456. } else {
  457. DXASSERT(0, "not support array yet");
  458. // TODO: support array.
  459. Value *colIdx = Builder.getInt8(0);
  460. ArrayType *AT = cast<ArrayType>(val->getType());
  461. Value *args[] = {OpArg, outputID, idx, colIdx, /*val*/ nullptr};
  462. args;
  463. AT;
  464. }
  465. }
  466. Value *GenerateLdInput(Function *loadInput, ArrayRef<Value *> args,
  467. IRBuilder<> &Builder, Value *zero, bool bCast,
  468. Type *Ty) {
  469. Value *input = Builder.CreateCall(loadInput, args);
  470. if (!bCast)
  471. return input;
  472. else {
  473. Value *bVal = Builder.CreateICmpNE(input, zero);
  474. IntegerType *IT = cast<IntegerType>(Ty);
  475. if (IT->getBitWidth() == 1)
  476. return bVal;
  477. else
  478. return Builder.CreateZExt(bVal, Ty);
  479. }
  480. }
  481. Value *replaceLdWithLdInput(Function *loadInput, LoadInst *ldInst,
  482. unsigned cols, MutableArrayRef<Value *> args,
  483. bool bCast) {
  484. IRBuilder<> Builder(ldInst);
  485. Type *Ty = ldInst->getType();
  486. Type *EltTy = Ty->getScalarType();
  487. // Change i1 to i32 for load input.
  488. Value *zero = Builder.getInt32(0);
  489. if (VectorType *VT = dyn_cast<VectorType>(Ty)) {
  490. Value *newVec = llvm::UndefValue::get(VT);
  491. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  492. for (unsigned col = 0; col < cols; col++) {
  493. Value *colIdx = Builder.getInt8(col);
  494. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  495. Value *input =
  496. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  497. newVec = Builder.CreateInsertElement(newVec, input, col);
  498. }
  499. ldInst->replaceAllUsesWith(newVec);
  500. ldInst->eraseFromParent();
  501. return newVec;
  502. } else {
  503. Value *colIdx = args[DXIL::OperandIndex::kLoadInputColOpIdx];
  504. if (colIdx == nullptr) {
  505. DXASSERT(cols == 1, "only support scalar here");
  506. colIdx = Builder.getInt8(0);
  507. } else {
  508. if (colIdx->getType() == Builder.getInt32Ty()) {
  509. colIdx = Builder.CreateTrunc(colIdx, Builder.getInt8Ty());
  510. }
  511. }
  512. if (isa<ConstantInt>(colIdx)) {
  513. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  514. Value *input =
  515. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  516. ldInst->replaceAllUsesWith(input);
  517. ldInst->eraseFromParent();
  518. return input;
  519. } else {
  520. // Vector indexing.
  521. // Load to array.
  522. ArrayType *AT = ArrayType::get(ldInst->getType(), cols);
  523. Value *arrayVec = Builder.CreateAlloca(AT);
  524. Value *zeroIdx = Builder.getInt32(0);
  525. for (unsigned col = 0; col < cols; col++) {
  526. Value *colIdx = Builder.getInt8(col);
  527. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  528. Value *input =
  529. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  530. Value *GEP = Builder.CreateInBoundsGEP(arrayVec, {zeroIdx, colIdx});
  531. Builder.CreateStore(input, GEP);
  532. }
  533. Value *vecIndexingPtr =
  534. Builder.CreateInBoundsGEP(arrayVec, {zeroIdx, colIdx});
  535. Value *input = Builder.CreateLoad(vecIndexingPtr);
  536. ldInst->replaceAllUsesWith(input);
  537. ldInst->eraseFromParent();
  538. return input;
  539. }
  540. }
  541. }
  542. void replaceDirectInputParameter(Value *param, Function *loadInput,
  543. unsigned cols, MutableArrayRef<Value *> args,
  544. bool bCast, OP *hlslOP, IRBuilder<> &Builder) {
  545. Value *zero = hlslOP->GetU32Const(0);
  546. Type *Ty = param->getType();
  547. Type *EltTy = Ty->getScalarType();
  548. if (VectorType *VT = dyn_cast<VectorType>(Ty)) {
  549. Value *newVec = llvm::UndefValue::get(VT);
  550. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  551. for (unsigned col = 0; col < cols; col++) {
  552. Value *colIdx = hlslOP->GetU8Const(col);
  553. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  554. Value *input =
  555. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  556. newVec = Builder.CreateInsertElement(newVec, input, col);
  557. }
  558. param->replaceAllUsesWith(newVec);
  559. } else if (!Ty->isArrayTy() && !HLMatrixLower::IsMatrixType(Ty)) {
  560. DXASSERT(cols == 1, "only support scalar here");
  561. Value *colIdx = hlslOP->GetU8Const(0);
  562. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  563. Value *input =
  564. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  565. param->replaceAllUsesWith(input);
  566. } else if (HLMatrixLower::IsMatrixType(Ty)) {
  567. Value *colIdx = hlslOP->GetU8Const(0);
  568. colIdx;
  569. DXASSERT(param->hasOneUse(),
  570. "matrix arg should only has one use as matrix to vec");
  571. CallInst *CI = cast<CallInst>(param->user_back());
  572. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  573. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLCast,
  574. "must be hlcast here");
  575. unsigned opcode = GetHLOpcode(CI);
  576. HLCastOpcode matOp = static_cast<HLCastOpcode>(opcode);
  577. switch (matOp) {
  578. case HLCastOpcode::ColMatrixToVecCast: {
  579. IRBuilder<> LocalBuilder(CI);
  580. Type *matTy =
  581. CI->getArgOperand(HLOperandIndex::kUnaryOpSrc0Idx)->getType();
  582. unsigned col, row;
  583. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  584. std::vector<Value *> matElts(col * row);
  585. for (unsigned c = 0; c < col; c++) {
  586. Value *rowIdx = hlslOP->GetI32Const(c);
  587. args[DXIL::OperandIndex::kLoadInputRowOpIdx] = rowIdx;
  588. for (unsigned r = 0; r < row; r++) {
  589. Value *colIdx = hlslOP->GetU8Const(r);
  590. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  591. Value *input =
  592. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  593. unsigned matIdx = c * row + r;
  594. matElts[matIdx] = input;
  595. }
  596. }
  597. Value *newVec =
  598. HLMatrixLower::BuildVector(EltTy, col * row, matElts, LocalBuilder);
  599. CI->replaceAllUsesWith(newVec);
  600. CI->eraseFromParent();
  601. } break;
  602. case HLCastOpcode::RowMatrixToVecCast: {
  603. IRBuilder<> LocalBuilder(CI);
  604. Type *matTy =
  605. CI->getArgOperand(HLOperandIndex::kUnaryOpSrc0Idx)->getType();
  606. unsigned col, row;
  607. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  608. std::vector<Value *> matElts(col * row);
  609. for (unsigned r = 0; r < row; r++) {
  610. Value *rowIdx = hlslOP->GetI32Const(r);
  611. args[DXIL::OperandIndex::kLoadInputRowOpIdx] = rowIdx;
  612. for (unsigned c = 0; c < col; c++) {
  613. Value *colIdx = hlslOP->GetU8Const(c);
  614. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  615. Value *input =
  616. GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  617. unsigned matIdx = r * col + c;
  618. matElts[matIdx] = input;
  619. }
  620. }
  621. Value *newVec =
  622. HLMatrixLower::BuildVector(EltTy, col * row, matElts, LocalBuilder);
  623. CI->replaceAllUsesWith(newVec);
  624. CI->eraseFromParent();
  625. } break;
  626. }
  627. } else {
  628. DXASSERT(0, "invalid type for direct input");
  629. }
  630. }
  631. struct InputOutputAccessInfo {
  632. // For input output which has only 1 row, idx is 0.
  633. Value *idx;
  634. // VertexID for HS/DS/GS input.
  635. Value *vertexID;
  636. // Vector index.
  637. Value *vectorIdx;
  638. // Load/Store/LoadMat/StoreMat on input/output.
  639. Instruction *user;
  640. InputOutputAccessInfo(Value *index, Instruction *I)
  641. : idx(index), user(I), vertexID(nullptr), vectorIdx(nullptr) {}
  642. InputOutputAccessInfo(Value *index, Instruction *I, Value *ID, Value *vecIdx)
  643. : idx(index), user(I), vertexID(ID), vectorIdx(vecIdx) {}
  644. };
  645. void collectInputOutputAccessInfo(
  646. Value *GV, Constant *constZero,
  647. std::vector<InputOutputAccessInfo> &accessInfoList, bool hasVertexID,
  648. bool bInput) {
  649. auto User = GV->user_begin();
  650. auto UserE = GV->user_end();
  651. for (; User != UserE;) {
  652. Value *I = *(User++);
  653. if (LoadInst *ldInst = dyn_cast<LoadInst>(I)) {
  654. if (bInput) {
  655. InputOutputAccessInfo info = {constZero, ldInst};
  656. accessInfoList.push_back(info);
  657. }
  658. } else if (StoreInst *stInst = dyn_cast<StoreInst>(I)) {
  659. if (!bInput) {
  660. InputOutputAccessInfo info = {constZero, stInst};
  661. accessInfoList.push_back(info);
  662. }
  663. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
  664. // Vector indexing may has more indices.
  665. // Vector indexing changed to array indexing in SROA_HLSL.
  666. auto idx = GEP->idx_begin();
  667. DXASSERT_LOCALVAR(idx, idx->get() == constZero,
  668. "only support 0 offset for input pointer");
  669. Value *vertexID = nullptr;
  670. Value *vectorIdx = nullptr;
  671. gep_type_iterator GEPIt = gep_type_begin(GEP), E = gep_type_end(GEP);
  672. // Skip first pointer idx which must be 0.
  673. GEPIt++;
  674. if (hasVertexID) {
  675. // Save vertexID.
  676. vertexID = GEPIt.getOperand();
  677. GEPIt++;
  678. }
  679. // Start from first index.
  680. Value *rowIdx = GEPIt.getOperand();
  681. if (GEPIt != E) {
  682. if ((*GEPIt)->isVectorTy()) {
  683. // Vector indexing.
  684. rowIdx = constZero;
  685. vectorIdx = GEPIt.getOperand();
  686. DXASSERT_NOMSG((++GEPIt) == E);
  687. } else {
  688. // Array which may have vector indexing.
  689. GEPIt++;
  690. IRBuilder<> Builder(GEP);
  691. Type *idxTy = rowIdx->getType();
  692. for (; GEPIt != E; ++GEPIt) {
  693. DXASSERT(!GEPIt->isStructTy(),
  694. "Struct should be flattened SROA_Parameter_HLSL");
  695. DXASSERT(!GEPIt->isPointerTy(),
  696. "not support pointer type in middle of GEP");
  697. if (GEPIt->isArrayTy()) {
  698. Constant *arraySize =
  699. ConstantInt::get(idxTy, GEPIt->getArrayNumElements());
  700. rowIdx = Builder.CreateMul(rowIdx, arraySize);
  701. rowIdx = Builder.CreateAdd(rowIdx, GEPIt.getOperand());
  702. } else {
  703. Type *Ty = *GEPIt;
  704. DXASSERT_LOCALVAR(Ty, Ty->isVectorTy(),
  705. "must be vector type here to index");
  706. // Save vector idx.
  707. vectorIdx = GEPIt.getOperand();
  708. }
  709. }
  710. }
  711. } else
  712. rowIdx = constZero;
  713. auto GepUser = GEP->user_begin();
  714. auto GepUserE = GEP->user_end();
  715. Value *idxVal = rowIdx;
  716. for (; GepUser != GepUserE;) {
  717. auto GepUserIt = GepUser++;
  718. if (LoadInst *ldInst = dyn_cast<LoadInst>(*GepUserIt)) {
  719. if (bInput) {
  720. InputOutputAccessInfo info = {idxVal, ldInst, vertexID, vectorIdx};
  721. accessInfoList.push_back(info);
  722. }
  723. } else if (StoreInst *stInst = dyn_cast<StoreInst>(*GepUserIt)) {
  724. if (!bInput) {
  725. InputOutputAccessInfo info = {idxVal, stInst, vertexID, vectorIdx};
  726. accessInfoList.push_back(info);
  727. }
  728. } else if (CallInst *CI = dyn_cast<CallInst>(*GepUserIt)) {
  729. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  730. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLMatLoadStore,
  731. "input/output should only used by ld/st");
  732. HLMatLoadStoreOpcode opcode = (HLMatLoadStoreOpcode)GetHLOpcode(CI);
  733. if ((opcode == HLMatLoadStoreOpcode::ColMatLoad ||
  734. opcode == HLMatLoadStoreOpcode::RowMatLoad)
  735. ? bInput
  736. : !bInput) {
  737. InputOutputAccessInfo info = {idxVal, CI, vertexID, vectorIdx};
  738. accessInfoList.push_back(info);
  739. }
  740. } else
  741. DXASSERT(0, "input output should only used by ld/st");
  742. }
  743. } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
  744. InputOutputAccessInfo info = {constZero, CI};
  745. accessInfoList.push_back(info);
  746. } else
  747. DXASSERT(0, "input output should only used by ld/st");
  748. }
  749. }
  750. void GenerateInputOutputUserCall(InputOutputAccessInfo &info, Value *undefVertexIdx,
  751. Function *ldStFunc, Constant *OpArg, Constant *ID, unsigned cols, bool bI1Cast,
  752. Constant *columnConsts[],
  753. bool bNeedVertexID, bool isArrayTy, bool bInput, bool bIsInout) {
  754. Value *idxVal = info.idx;
  755. Value *vertexID = undefVertexIdx;
  756. if (bNeedVertexID && isArrayTy) {
  757. vertexID = info.vertexID;
  758. }
  759. if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
  760. SmallVector<Value *, 4> args = {OpArg, ID, idxVal, info.vectorIdx};
  761. if (vertexID)
  762. args.emplace_back(vertexID);
  763. replaceLdWithLdInput(ldStFunc, ldInst, cols, args, bI1Cast);
  764. } else if (StoreInst *stInst = dyn_cast<StoreInst>(info.user)) {
  765. if (bInput) {
  766. DXASSERT_LOCALVAR(bIsInout, bIsInout, "input should not have store use.");
  767. } else {
  768. if (!info.vectorIdx) {
  769. replaceStWithStOutput(ldStFunc, stInst, OpArg, ID, idxVal, cols,
  770. bI1Cast);
  771. } else {
  772. Value *V = stInst->getValueOperand();
  773. Type *Ty = V->getType();
  774. DXASSERT_LOCALVAR(Ty == Ty->getScalarType() && !Ty->isAggregateType(),
  775. Ty, "only support scalar here");
  776. if (ConstantInt *ColIdx = dyn_cast<ConstantInt>(info.vectorIdx)) {
  777. IRBuilder<> Builder(stInst);
  778. if (ColIdx->getType()->getBitWidth() != 8) {
  779. ColIdx = Builder.getInt8(ColIdx->getValue().getLimitedValue());
  780. }
  781. Value *args[] = {OpArg, ID, idxVal, ColIdx, V};
  782. GenerateStOutput(ldStFunc, args, Builder, bI1Cast);
  783. } else {
  784. BasicBlock *BB = stInst->getParent();
  785. BasicBlock *EndBB = BB->splitBasicBlock(stInst);
  786. TerminatorInst *TI = BB->getTerminator();
  787. IRBuilder<> SwitchBuilder(TI);
  788. LLVMContext &Ctx = stInst->getContext();
  789. SwitchInst *Switch =
  790. SwitchBuilder.CreateSwitch(info.vectorIdx, EndBB, cols);
  791. TI->eraseFromParent();
  792. Function *F = EndBB->getParent();
  793. for (unsigned i = 0; i < cols; i++) {
  794. BasicBlock *CaseBB = BasicBlock::Create(Ctx, "case", F, EndBB);
  795. Switch->addCase(SwitchBuilder.getInt32(i), CaseBB);
  796. IRBuilder<> CaseBuilder(CaseBB);
  797. ConstantInt *CaseIdx = SwitchBuilder.getInt8(i);
  798. Value *args[] = {OpArg, ID, idxVal, CaseIdx, V};
  799. GenerateStOutput(ldStFunc, args, CaseBuilder, bI1Cast);
  800. CaseBuilder.CreateBr(EndBB);
  801. }
  802. }
  803. // remove stInst
  804. stInst->eraseFromParent();
  805. }
  806. }
  807. } else if (CallInst *CI = dyn_cast<CallInst>(info.user)) {
  808. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  809. // Intrinsic will be translated later.
  810. if (group == HLOpcodeGroup::HLIntrinsic)
  811. return;
  812. unsigned opcode = GetHLOpcode(CI);
  813. DXASSERT(group == HLOpcodeGroup::HLMatLoadStore, "");
  814. HLMatLoadStoreOpcode matOp = static_cast<HLMatLoadStoreOpcode>(opcode);
  815. switch (matOp) {
  816. case HLMatLoadStoreOpcode::ColMatLoad: {
  817. IRBuilder<> LocalBuilder(CI);
  818. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx)
  819. ->getType()
  820. ->getPointerElementType();
  821. unsigned col, row;
  822. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  823. std::vector<Value *> matElts(col * row);
  824. for (unsigned c = 0; c < col; c++) {
  825. Constant *constRowIdx = LocalBuilder.getInt32(c);
  826. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  827. for (unsigned r = 0; r < row; r++) {
  828. SmallVector<Value *, 4> args = {OpArg, ID, rowIdx, columnConsts[r]};
  829. if (vertexID)
  830. args.emplace_back(vertexID);
  831. Value *input = LocalBuilder.CreateCall(ldStFunc, args);
  832. unsigned matIdx = c * row + r;
  833. matElts[matIdx] = input;
  834. }
  835. }
  836. Value *newVec =
  837. HLMatrixLower::BuildVector(EltTy, col * row, matElts, LocalBuilder);
  838. CI->replaceAllUsesWith(newVec);
  839. CI->eraseFromParent();
  840. } break;
  841. case HLMatLoadStoreOpcode::RowMatLoad: {
  842. IRBuilder<> LocalBuilder(CI);
  843. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx)
  844. ->getType()
  845. ->getPointerElementType();
  846. unsigned col, row;
  847. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  848. std::vector<Value *> matElts(col * row);
  849. for (unsigned r = 0; r < row; r++) {
  850. Constant *constRowIdx = LocalBuilder.getInt32(r);
  851. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  852. for (unsigned c = 0; c < col; c++) {
  853. SmallVector<Value *, 4> args = {OpArg, ID, rowIdx, columnConsts[c]};
  854. if (vertexID)
  855. args.emplace_back(vertexID);
  856. Value *input = LocalBuilder.CreateCall(ldStFunc, args);
  857. unsigned matIdx = r * col + c;
  858. matElts[matIdx] = input;
  859. }
  860. }
  861. Value *newVec =
  862. HLMatrixLower::BuildVector(EltTy, col * row, matElts, LocalBuilder);
  863. CI->replaceAllUsesWith(newVec);
  864. CI->eraseFromParent();
  865. } break;
  866. case HLMatLoadStoreOpcode::ColMatStore: {
  867. IRBuilder<> LocalBuilder(CI);
  868. Value *Val = CI->getArgOperand(HLOperandIndex::kMatStoreValOpIdx);
  869. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatStoreDstPtrOpIdx)
  870. ->getType()
  871. ->getPointerElementType();
  872. unsigned col, row;
  873. HLMatrixLower::GetMatrixInfo(matTy, col, row);
  874. for (unsigned c = 0; c < col; c++) {
  875. Constant *constColIdx = LocalBuilder.getInt32(c);
  876. Value *colIdx = LocalBuilder.CreateAdd(idxVal, constColIdx);
  877. for (unsigned r = 0; r < row; r++) {
  878. unsigned matIdx = HLMatrixLower::GetColMajorIdx(r, c, row);
  879. Value *Elt = LocalBuilder.CreateExtractElement(Val, matIdx);
  880. LocalBuilder.CreateCall(ldStFunc,
  881. {OpArg, ID, colIdx, columnConsts[r], Elt});
  882. }
  883. }
  884. CI->eraseFromParent();
  885. } break;
  886. case HLMatLoadStoreOpcode::RowMatStore: {
  887. IRBuilder<> LocalBuilder(CI);
  888. Value *Val = CI->getArgOperand(HLOperandIndex::kMatStoreValOpIdx);
  889. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatStoreDstPtrOpIdx)
  890. ->getType()
  891. ->getPointerElementType();
  892. unsigned col, row;
  893. HLMatrixLower::GetMatrixInfo(matTy, col, row);
  894. for (unsigned r = 0; r < row; r++) {
  895. Constant *constRowIdx = LocalBuilder.getInt32(r);
  896. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  897. for (unsigned c = 0; c < col; c++) {
  898. unsigned matIdx = HLMatrixLower::GetRowMajorIdx(r, c, col);
  899. Value *Elt = LocalBuilder.CreateExtractElement(Val, matIdx);
  900. LocalBuilder.CreateCall(ldStFunc,
  901. {OpArg, ID, rowIdx, columnConsts[c], Elt});
  902. }
  903. }
  904. CI->eraseFromParent();
  905. } break;
  906. }
  907. } else
  908. DXASSERT(0, "invalid operation on input output");
  909. }
  910. } // namespace
  911. void HLSignatureLower::GenerateDxilInputs() {
  912. GenerateDxilInputsOutputs(/*bInput*/ true);
  913. }
  914. void HLSignatureLower::GenerateDxilOutputs() {
  915. GenerateDxilInputsOutputs(/*bInput*/ false);
  916. }
  917. void HLSignatureLower::GenerateDxilInputsOutputs(bool bInput) {
  918. OP *hlslOP = HLM.GetOP();
  919. DxilFunctionProps &props = HLM.GetDxilFunctionProps(Entry);
  920. Module &M = *(HLM.GetModule());
  921. OP::OpCode opcode = bInput ? OP::OpCode::LoadInput : OP::OpCode::StoreOutput;
  922. bool bNeedVertexID = bInput && (props.IsGS() || props.IsDS() || props.IsHS());
  923. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  924. Constant *columnConsts[] = {
  925. hlslOP->GetU8Const(0), hlslOP->GetU8Const(1), hlslOP->GetU8Const(2),
  926. hlslOP->GetU8Const(3), hlslOP->GetU8Const(4), hlslOP->GetU8Const(5),
  927. hlslOP->GetU8Const(6), hlslOP->GetU8Const(7), hlslOP->GetU8Const(8),
  928. hlslOP->GetU8Const(9), hlslOP->GetU8Const(10), hlslOP->GetU8Const(11),
  929. hlslOP->GetU8Const(12), hlslOP->GetU8Const(13), hlslOP->GetU8Const(14),
  930. hlslOP->GetU8Const(15)};
  931. Constant *constZero = hlslOP->GetU32Const(0);
  932. Value *undefVertexIdx = UndefValue::get(Type::getInt32Ty(HLM.GetCtx()));
  933. DxilSignature &Sig =
  934. bInput ? EntrySig.InputSignature : EntrySig.OutputSignature;
  935. Type *i1Ty = Type::getInt1Ty(constZero->getContext());
  936. Type *i32Ty = constZero->getType();
  937. llvm::SmallVector<unsigned, 8> removeIndices;
  938. for (unsigned i = 0; i < Sig.GetElements().size(); i++) {
  939. DxilSignatureElement *SE = &Sig.GetElement(i);
  940. llvm::Type *Ty = SE->GetCompType().GetLLVMType(HLM.GetCtx());
  941. // Cast i1 to i32 for load input.
  942. bool bI1Cast = false;
  943. if (Ty == i1Ty) {
  944. bI1Cast = true;
  945. Ty = i32Ty;
  946. }
  947. if (!hlslOP->IsOverloadLegal(opcode, Ty)) {
  948. std::string O;
  949. raw_string_ostream OSS(O);
  950. Ty->print(OSS);
  951. OSS << "(type for " << SE->GetName() << ")";
  952. OSS << " cannot be used as shader inputs or outputs.";
  953. OSS.flush();
  954. HLM.GetCtx().emitError(O);
  955. continue;
  956. }
  957. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty);
  958. Constant *ID = hlslOP->GetU32Const(i);
  959. unsigned cols = SE->GetCols();
  960. Value *GV = m_sigValueMap[SE];
  961. bool bIsInout = m_inoutArgSet.count(GV) > 0;
  962. IRBuilder<> EntryBuilder(Entry->getEntryBlock().getFirstInsertionPt());
  963. if (DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(GV)) {
  964. EntryBuilder.SetCurrentDebugLocation(DDI->getDebugLoc());
  965. }
  966. DXIL::SemanticInterpretationKind SI = SE->GetInterpretation();
  967. DXASSERT_NOMSG(SI < DXIL::SemanticInterpretationKind::Invalid);
  968. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NA);
  969. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NotInSig);
  970. if (SI == DXIL::SemanticInterpretationKind::Shadow)
  971. continue; // Handled in ProcessArgument
  972. if (!GV->getType()->isPointerTy()) {
  973. DXASSERT(bInput, "direct parameter must be input");
  974. Value *vertexID = undefVertexIdx;
  975. Value *args[] = {OpArg, ID, /*rowIdx*/ constZero, /*colIdx*/ nullptr,
  976. vertexID};
  977. replaceDirectInputParameter(GV, dxilFunc, cols, args, bI1Cast, hlslOP,
  978. EntryBuilder);
  979. continue;
  980. }
  981. bool bIsArrayTy = GV->getType()->getPointerElementType()->isArrayTy();
  982. bool bIsPrecise = m_preciseSigSet.count(SE);
  983. if (bIsPrecise)
  984. HLModule::MarkPreciseAttributeOnPtrWithFunctionCall(GV, M);
  985. std::vector<InputOutputAccessInfo> accessInfoList;
  986. collectInputOutputAccessInfo(GV, constZero, accessInfoList,
  987. bNeedVertexID && bIsArrayTy, bInput);
  988. for (InputOutputAccessInfo &info : accessInfoList) {
  989. GenerateInputOutputUserCall(info, undefVertexIdx, dxilFunc, OpArg, ID,
  990. cols, bI1Cast, columnConsts, bNeedVertexID,
  991. bIsArrayTy, bInput, bIsInout);
  992. }
  993. }
  994. }
  995. void HLSignatureLower::GenerateDxilCSInputs() {
  996. OP *hlslOP = HLM.GetOP();
  997. DxilFunctionAnnotation *funcAnnotation = HLM.GetFunctionAnnotation(Entry);
  998. DXASSERT(funcAnnotation, "must find annotation for entry function");
  999. IRBuilder<> Builder(Entry->getEntryBlock().getFirstInsertionPt());
  1000. for (Argument &arg : Entry->args()) {
  1001. DxilParameterAnnotation &paramAnnotation =
  1002. funcAnnotation->GetParameterAnnotation(arg.getArgNo());
  1003. llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
  1004. if (semanticStr.empty()) {
  1005. Entry->getContext().emitError("Semantic must be defined for all "
  1006. "parameters of an entry function or patch "
  1007. "constant function");
  1008. return;
  1009. }
  1010. const Semantic *semantic =
  1011. Semantic::GetByName(semanticStr, DXIL::SigPointKind::CSIn);
  1012. OP::OpCode opcode;
  1013. switch (semantic->GetKind()) {
  1014. case Semantic::Kind::GroupThreadID:
  1015. opcode = OP::OpCode::ThreadIdInGroup;
  1016. break;
  1017. case Semantic::Kind::GroupID:
  1018. opcode = OP::OpCode::GroupId;
  1019. break;
  1020. case Semantic::Kind::DispatchThreadID:
  1021. opcode = OP::OpCode::ThreadId;
  1022. break;
  1023. case Semantic::Kind::GroupIndex:
  1024. opcode = OP::OpCode::FlattenedThreadIdInGroup;
  1025. break;
  1026. default:
  1027. DXASSERT(semantic->IsInvalid(),
  1028. "else compute shader semantics out-of-date");
  1029. Entry->getContext().emitError("invalid semantic found in CS");
  1030. return;
  1031. }
  1032. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1033. Type *Ty = arg.getType();
  1034. if (Ty->isPointerTy())
  1035. Ty = Ty->getPointerElementType();
  1036. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty->getScalarType());
  1037. Value *newArg = nullptr;
  1038. if (opcode == OP::OpCode::FlattenedThreadIdInGroup) {
  1039. newArg = Builder.CreateCall(dxilFunc, {OpArg});
  1040. } else {
  1041. unsigned vecSize = 1;
  1042. if (Ty->isVectorTy())
  1043. vecSize = Ty->getVectorNumElements();
  1044. newArg = Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU32Const(0)});
  1045. if (vecSize > 1) {
  1046. Value *result = UndefValue::get(Ty);
  1047. result = Builder.CreateInsertElement(result, newArg, (uint64_t)0);
  1048. for (unsigned i = 1; i < vecSize; i++) {
  1049. Value *newElt =
  1050. Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU32Const(i)});
  1051. result = Builder.CreateInsertElement(result, newElt, i);
  1052. }
  1053. newArg = result;
  1054. }
  1055. }
  1056. if (newArg->getType() != arg.getType()) {
  1057. DXASSERT_NOMSG(arg.getType()->isPointerTy());
  1058. for (User *U : arg.users()) {
  1059. LoadInst *LI = cast<LoadInst>(U);
  1060. LI->replaceAllUsesWith(newArg);
  1061. }
  1062. } else {
  1063. arg.replaceAllUsesWith(newArg);
  1064. }
  1065. }
  1066. }
  1067. void HLSignatureLower::GenerateDxilPatchConstantLdSt() {
  1068. OP *hlslOP = HLM.GetOP();
  1069. DxilFunctionProps &props = HLM.GetDxilFunctionProps(Entry);
  1070. Module &M = *(HLM.GetModule());
  1071. Constant *constZero = hlslOP->GetU32Const(0);
  1072. DxilSignature &Sig = EntrySig.PatchConstantSignature;
  1073. auto InsertPt = Entry->getEntryBlock().getFirstInsertionPt();
  1074. const bool bIsHs = props.IsHS();
  1075. const bool bIsInput = !bIsHs;
  1076. const bool bIsInout = false;
  1077. const bool bNeedVertexID = false;
  1078. if (bIsHs) {
  1079. DxilFunctionProps &EntryQual = HLM.GetDxilFunctionProps(Entry);
  1080. Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
  1081. InsertPt = patchConstantFunc->getEntryBlock().getFirstInsertionPt();
  1082. }
  1083. IRBuilder<> Builder(InsertPt);
  1084. Type *i1Ty = Builder.getInt1Ty();
  1085. Type *i32Ty = Builder.getInt32Ty();
  1086. // LoadPatchConst don't have vertexIdx operand.
  1087. Value *undefVertexIdx = nullptr;
  1088. Constant *columnConsts[] = {
  1089. hlslOP->GetU8Const(0), hlslOP->GetU8Const(1), hlslOP->GetU8Const(2),
  1090. hlslOP->GetU8Const(3), hlslOP->GetU8Const(4), hlslOP->GetU8Const(5),
  1091. hlslOP->GetU8Const(6), hlslOP->GetU8Const(7), hlslOP->GetU8Const(8),
  1092. hlslOP->GetU8Const(9), hlslOP->GetU8Const(10), hlslOP->GetU8Const(11),
  1093. hlslOP->GetU8Const(12), hlslOP->GetU8Const(13), hlslOP->GetU8Const(14),
  1094. hlslOP->GetU8Const(15)};
  1095. OP::OpCode opcode =
  1096. bIsInput ? OP::OpCode::LoadPatchConstant : OP::OpCode::StorePatchConstant;
  1097. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1098. for (unsigned i = 0; i < Sig.GetElements().size(); i++) {
  1099. DxilSignatureElement *SE = &Sig.GetElement(i);
  1100. Value *GV = m_sigValueMap[SE];
  1101. DXIL::SemanticInterpretationKind SI = SE->GetInterpretation();
  1102. DXASSERT_NOMSG(SI < DXIL::SemanticInterpretationKind::Invalid);
  1103. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NA);
  1104. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NotInSig);
  1105. if (SI == DXIL::SemanticInterpretationKind::Shadow)
  1106. continue; // Handled in ProcessArgument
  1107. Constant *ID = hlslOP->GetU32Const(i);
  1108. // Generate LoadPatchConstant.
  1109. Type *Ty = SE->GetCompType().GetLLVMType(HLM.GetCtx());
  1110. // Cast i1 to i32 for load input.
  1111. bool bI1Cast = false;
  1112. if (Ty == i1Ty) {
  1113. bI1Cast = true;
  1114. Ty = i32Ty;
  1115. }
  1116. unsigned cols = SE->GetCols();
  1117. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty);
  1118. if (!GV->getType()->isPointerTy()) {
  1119. DXASSERT(bIsInput, "Must be DS input.");
  1120. Constant *OpArg = hlslOP->GetU32Const(
  1121. static_cast<unsigned>(OP::OpCode::LoadPatchConstant));
  1122. Value *args[] = {OpArg, ID, /*rowIdx*/ constZero, /*colIdx*/ nullptr};
  1123. replaceDirectInputParameter(GV, dxilFunc, cols, args, bI1Cast, hlslOP,
  1124. Builder);
  1125. continue;
  1126. }
  1127. std::vector<InputOutputAccessInfo> accessInfoList;
  1128. collectInputOutputAccessInfo(GV, constZero, accessInfoList, bNeedVertexID,
  1129. bIsInput);
  1130. bool bIsArrayTy = GV->getType()->getPointerElementType()->isArrayTy();
  1131. bool isPrecise = m_preciseSigSet.count(SE);
  1132. if (isPrecise)
  1133. HLModule::MarkPreciseAttributeOnPtrWithFunctionCall(GV, M);
  1134. for (InputOutputAccessInfo &info : accessInfoList) {
  1135. GenerateInputOutputUserCall(info, undefVertexIdx, dxilFunc, OpArg, ID,
  1136. cols, bI1Cast, columnConsts, bNeedVertexID,
  1137. bIsArrayTy, bIsInput, bIsInout);
  1138. }
  1139. }
  1140. }
  1141. void HLSignatureLower::GenerateDxilPatchConstantFunctionInputs() {
  1142. // Map input patch, to input sig
  1143. // LoadOutputControlPoint for output patch .
  1144. OP *hlslOP = HLM.GetOP();
  1145. Constant *constZero = hlslOP->GetU32Const(0);
  1146. DxilFunctionProps &EntryQual = HLM.GetDxilFunctionProps(Entry);
  1147. Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
  1148. DxilFunctionAnnotation *patchFuncAnnotation =
  1149. HLM.GetFunctionAnnotation(patchConstantFunc);
  1150. DXASSERT(patchFuncAnnotation,
  1151. "must find annotation for patch constant function");
  1152. Type *i1Ty = Type::getInt1Ty(constZero->getContext());
  1153. Type *i32Ty = constZero->getType();
  1154. for (Argument &arg : patchConstantFunc->args()) {
  1155. DxilParameterAnnotation &paramAnnotation =
  1156. patchFuncAnnotation->GetParameterAnnotation(arg.getArgNo());
  1157. DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
  1158. if (inputQual == DxilParamInputQual::InputPatch ||
  1159. inputQual == DxilParamInputQual::OutputPatch) {
  1160. DxilSignatureElement *SE = m_patchConstantInputsSigMap[arg.getArgNo()];
  1161. if (!SE) // Error should have been reported at an earlier stage.
  1162. continue;
  1163. Constant *inputID = hlslOP->GetU32Const(SE->GetID());
  1164. unsigned cols = SE->GetCols();
  1165. Type *Ty = SE->GetCompType().GetLLVMType(HLM.GetCtx());
  1166. // Cast i1 to i32 for load input.
  1167. bool bI1Cast = false;
  1168. if (Ty == i1Ty) {
  1169. bI1Cast = true;
  1170. Ty = i32Ty;
  1171. }
  1172. OP::OpCode opcode = inputQual == DxilParamInputQual::InputPatch
  1173. ? OP::OpCode::LoadInput
  1174. : OP::OpCode::LoadOutputControlPoint;
  1175. Function *dxilLdFunc = hlslOP->GetOpFunc(opcode, Ty);
  1176. std::vector<InputOutputAccessInfo> accessInfoList;
  1177. collectInputOutputAccessInfo(&arg, constZero, accessInfoList,
  1178. /*hasVertexID*/ true, true);
  1179. for (InputOutputAccessInfo &info : accessInfoList) {
  1180. if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
  1181. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1182. Value *args[] = {OpArg, inputID, info.idx, info.vectorIdx,
  1183. info.vertexID};
  1184. replaceLdWithLdInput(dxilLdFunc, ldInst, cols, args, bI1Cast);
  1185. } else
  1186. DXASSERT(0, "input should only be ld");
  1187. }
  1188. }
  1189. }
  1190. }
  1191. bool HLSignatureLower::HasClipPlanes() {
  1192. if (!HLM.HasDxilFunctionProps(Entry))
  1193. return false;
  1194. DxilFunctionProps &EntryQual = HLM.GetDxilFunctionProps(Entry);
  1195. auto &VS = EntryQual.ShaderProps.VS;
  1196. unsigned numClipPlanes = 0;
  1197. for (unsigned i = 0; i < DXIL::kNumClipPlanes; i++) {
  1198. if (!VS.clipPlanes[i])
  1199. break;
  1200. numClipPlanes++;
  1201. }
  1202. return numClipPlanes != 0;
  1203. }
  1204. void HLSignatureLower::GenerateClipPlanesForVS(Value *outPosition) {
  1205. DxilFunctionProps &EntryQual = HLM.GetDxilFunctionProps(Entry);
  1206. auto &VS = EntryQual.ShaderProps.VS;
  1207. unsigned numClipPlanes = 0;
  1208. for (unsigned i = 0; i < DXIL::kNumClipPlanes; i++) {
  1209. if (!VS.clipPlanes[i])
  1210. break;
  1211. numClipPlanes++;
  1212. }
  1213. if (!numClipPlanes)
  1214. return;
  1215. LLVMContext &Ctx = HLM.GetCtx();
  1216. Function *dp4 =
  1217. HLM.GetOP()->GetOpFunc(DXIL::OpCode::Dot4, Type::getFloatTy(Ctx));
  1218. Value *dp4Args[] = {
  1219. ConstantInt::get(Type::getInt32Ty(Ctx),
  1220. static_cast<unsigned>(DXIL::OpCode::Dot4)),
  1221. nullptr,
  1222. nullptr,
  1223. nullptr,
  1224. nullptr,
  1225. nullptr,
  1226. nullptr,
  1227. nullptr,
  1228. nullptr,
  1229. };
  1230. // out SV_Position should only have StoreInst use.
  1231. // Done by LegalizeDxilInputOutputs in ScalarReplAggregatesHLSL.cpp
  1232. for (User *U : outPosition->users()) {
  1233. StoreInst *ST = cast<StoreInst>(U);
  1234. Value *posVal = ST->getValueOperand();
  1235. DXASSERT(posVal->getType()->isVectorTy(), "SV_Position must be a vector");
  1236. IRBuilder<> Builder(ST);
  1237. // Put position to args.
  1238. for (unsigned i = 0; i < 4; i++)
  1239. dp4Args[i + 1] = Builder.CreateExtractElement(posVal, i);
  1240. // For each clip plane.
  1241. // clipDistance = dp4 position, clipPlane.
  1242. auto argIt = Entry->getArgumentList().rbegin();
  1243. for (int clipIdx = numClipPlanes - 1; clipIdx >= 0; clipIdx--) {
  1244. Constant *GV = VS.clipPlanes[clipIdx];
  1245. DXASSERT_NOMSG(GV->hasOneUse());
  1246. StoreInst *ST = cast<StoreInst>(GV->user_back());
  1247. Value *clipPlane = ST->getValueOperand();
  1248. ST->eraseFromParent();
  1249. Argument &arg = *(argIt++);
  1250. // Put clipPlane to args.
  1251. for (unsigned i = 0; i < 4; i++)
  1252. dp4Args[i + 5] = Builder.CreateExtractElement(clipPlane, i);
  1253. Value *clipDistance = Builder.CreateCall(dp4, dp4Args);
  1254. Builder.CreateStore(clipDistance, &arg);
  1255. }
  1256. }
  1257. }
  1258. namespace {
  1259. // Helper functions for Gs Streams.
  1260. void GenerateStOutput(Function *stOutput, Value *eltVal, Value *outputID,
  1261. Value *rowIdx, Value *colIdx, OP *hlslOP,
  1262. IRBuilder<> Builder) {
  1263. Constant *OpArg = hlslOP->GetU32Const((unsigned)OP::OpCode::StoreOutput);
  1264. Builder.CreateCall(stOutput, {OpArg, outputID, rowIdx, colIdx, eltVal});
  1265. }
  1266. Value *TranslateStreamAppend(CallInst *CI, unsigned ID, hlsl::OP *OP) {
  1267. Function *DxilFunc = OP->GetOpFunc(OP::OpCode::EmitStream, CI->getType());
  1268. // TODO: generate a emit which has the data being emited as its argment.
  1269. // Value *data = CI->getArgOperand(HLOperandIndex::kStreamAppendDataOpIndex);
  1270. Constant *opArg = OP->GetU32Const((unsigned)OP::OpCode::EmitStream);
  1271. IRBuilder<> Builder(CI);
  1272. Constant *streamID = OP->GetU8Const(ID);
  1273. Value *args[] = {opArg, streamID};
  1274. return Builder.CreateCall(DxilFunc, args);
  1275. }
  1276. Value *TranslateStreamCut(CallInst *CI, unsigned ID, hlsl::OP *OP) {
  1277. Function *DxilFunc = OP->GetOpFunc(OP::OpCode::CutStream, CI->getType());
  1278. // TODO: generate a emit which has the data being emited as its argment.
  1279. // Value *data = CI->getArgOperand(HLOperandIndex::kStreamAppendDataOpIndex);
  1280. Constant *opArg = OP->GetU32Const((unsigned)OP::OpCode::CutStream);
  1281. IRBuilder<> Builder(CI);
  1282. Constant *streamID = OP->GetU8Const(ID);
  1283. Value *args[] = {opArg, streamID};
  1284. return Builder.CreateCall(DxilFunc, args);
  1285. }
  1286. } // namespace
  1287. // Generate DXIL stream output operation.
  1288. void HLSignatureLower::GenerateStreamOutputOperation(Value *streamVal, unsigned ID) {
  1289. OP * hlslOP = HLM.GetOP();
  1290. for (auto U = streamVal->user_begin(); U != streamVal->user_end();) {
  1291. Value *user = *(U++);
  1292. // Should only used by append, restartStrip .
  1293. CallInst *CI = cast<CallInst>(user);
  1294. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  1295. unsigned opcode = GetHLOpcode(CI);
  1296. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLIntrinsic, "");
  1297. IntrinsicOp IOP = static_cast<IntrinsicOp>(opcode);
  1298. switch (IOP) {
  1299. case IntrinsicOp::MOP_Append:
  1300. TranslateStreamAppend(CI, ID, hlslOP);
  1301. break;
  1302. case IntrinsicOp::MOP_RestartStrip:
  1303. TranslateStreamCut(CI, ID, hlslOP);
  1304. break;
  1305. default:
  1306. DXASSERT(0, "invalid operation on stream");
  1307. }
  1308. CI->eraseFromParent();
  1309. }
  1310. }
  1311. // Generate DXIL stream output operations.
  1312. void HLSignatureLower::GenerateStreamOutputOperations() {
  1313. DxilFunctionAnnotation *EntryAnnotation = HLM.GetFunctionAnnotation(Entry);
  1314. DXASSERT(EntryAnnotation, "must find annotation for entry function");
  1315. for (Argument &arg : Entry->getArgumentList()) {
  1316. if (HLModule::IsStreamOutputPtrType(arg.getType())) {
  1317. unsigned streamID = 0;
  1318. DxilParameterAnnotation &paramAnnotation =
  1319. EntryAnnotation->GetParameterAnnotation(arg.getArgNo());
  1320. DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
  1321. switch (inputQual) {
  1322. case DxilParamInputQual::OutStream0:
  1323. streamID = 0;
  1324. break;
  1325. case DxilParamInputQual::OutStream1:
  1326. streamID = 1;
  1327. break;
  1328. case DxilParamInputQual::OutStream2:
  1329. streamID = 2;
  1330. break;
  1331. case DxilParamInputQual::OutStream3:
  1332. default:
  1333. DXASSERT(inputQual == DxilParamInputQual::OutStream3,
  1334. "invalid input qual.");
  1335. streamID = 3;
  1336. break;
  1337. }
  1338. GenerateStreamOutputOperation(&arg, streamID);
  1339. }
  1340. }
  1341. }
  1342. // Lower signatures.
  1343. void HLSignatureLower::Run() {
  1344. DxilFunctionProps &props = HLM.GetDxilFunctionProps(Entry);
  1345. if (props.IsGraphics()) {
  1346. CreateDxilSignatures();
  1347. // Allocate input output.
  1348. AllocateDxilInputOutputs();
  1349. GenerateDxilInputs();
  1350. GenerateDxilOutputs();
  1351. } else if (props.IsCS()) {
  1352. GenerateDxilCSInputs();
  1353. }
  1354. if (props.IsDS() || props.IsHS())
  1355. GenerateDxilPatchConstantLdSt();
  1356. if (props.IsHS())
  1357. GenerateDxilPatchConstantFunctionInputs();
  1358. if (props.IsGS())
  1359. GenerateStreamOutputOperations();
  1360. }