HLSignatureLower.cpp 58 KB

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