HLSignatureLower.cpp 58 KB

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