HLSignatureLower.cpp 58 KB

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