HLSignatureLower.cpp 67 KB

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