HLSignatureLower.cpp 58 KB

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