DxilTypeSystem.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilTypeSystem.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. ///////////////////////////////////////////////////////////////////////////////
  9. #include "dxc/HLSL/DxilTypeSystem.h"
  10. #include "dxc/HLSL/DxilModule.h"
  11. #include "dxc/HLSL/HLModule.h"
  12. #include "dxc/Support/Global.h"
  13. #include "dxc/Support/WinFunctions.h"
  14. #include "llvm/IR/Module.h"
  15. #include "llvm/IR/LLVMContext.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. using namespace llvm;
  18. using std::unique_ptr;
  19. using std::string;
  20. using std::vector;
  21. using std::map;
  22. namespace hlsl {
  23. //------------------------------------------------------------------------------
  24. //
  25. // DxilMatrixAnnotation class methods.
  26. //
  27. DxilMatrixAnnotation::DxilMatrixAnnotation()
  28. : Rows(0)
  29. , Cols(0)
  30. , Orientation(MatrixOrientation::Undefined) {
  31. }
  32. //------------------------------------------------------------------------------
  33. //
  34. // DxilFieldAnnotation class methods.
  35. //
  36. DxilFieldAnnotation::DxilFieldAnnotation()
  37. : m_bPrecise(false)
  38. , m_ResourceAttribute(nullptr)
  39. , m_CBufferOffset(UINT_MAX) {
  40. }
  41. bool DxilFieldAnnotation::IsPrecise() const { return m_bPrecise; }
  42. void DxilFieldAnnotation::SetPrecise(bool b) { m_bPrecise = b; }
  43. bool DxilFieldAnnotation::HasMatrixAnnotation() const { return m_Matrix.Cols != 0; }
  44. const DxilMatrixAnnotation &DxilFieldAnnotation::GetMatrixAnnotation() const { return m_Matrix; }
  45. void DxilFieldAnnotation::SetMatrixAnnotation(const DxilMatrixAnnotation &MA) { m_Matrix = MA; }
  46. bool DxilFieldAnnotation::HasResourceAttribute() const {
  47. return m_ResourceAttribute;
  48. }
  49. llvm::MDNode *DxilFieldAnnotation::GetResourceAttribute() const {
  50. return m_ResourceAttribute;
  51. }
  52. void DxilFieldAnnotation::SetResourceAttribute(llvm::MDNode *MD) {
  53. m_ResourceAttribute = MD;
  54. }
  55. bool DxilFieldAnnotation::HasCBufferOffset() const { return m_CBufferOffset != UINT_MAX; }
  56. unsigned DxilFieldAnnotation::GetCBufferOffset() const { return m_CBufferOffset; }
  57. void DxilFieldAnnotation::SetCBufferOffset(unsigned Offset) { m_CBufferOffset = Offset; }
  58. bool DxilFieldAnnotation::HasCompType() const { return m_CompType.GetKind() != CompType::Kind::Invalid; }
  59. const CompType &DxilFieldAnnotation::GetCompType() const { return m_CompType; }
  60. void DxilFieldAnnotation::SetCompType(CompType::Kind kind) { m_CompType = CompType(kind); }
  61. bool DxilFieldAnnotation::HasSemanticString() const { return !m_Semantic.empty(); }
  62. const std::string &DxilFieldAnnotation::GetSemanticString() const { return m_Semantic; }
  63. llvm::StringRef DxilFieldAnnotation::GetSemanticStringRef() const { return llvm::StringRef(m_Semantic); }
  64. void DxilFieldAnnotation::SetSemanticString(const std::string &SemString) { m_Semantic = SemString; }
  65. bool DxilFieldAnnotation::HasInterpolationMode() const { return !m_InterpMode.IsUndefined(); }
  66. const InterpolationMode &DxilFieldAnnotation::GetInterpolationMode() const { return m_InterpMode; }
  67. void DxilFieldAnnotation::SetInterpolationMode(const InterpolationMode &IM) { m_InterpMode = IM; }
  68. bool DxilFieldAnnotation::HasFieldName() const { return !m_FieldName.empty(); }
  69. const std::string &DxilFieldAnnotation::GetFieldName() const { return m_FieldName; }
  70. void DxilFieldAnnotation::SetFieldName(const std::string &FieldName) { m_FieldName = FieldName; }
  71. //------------------------------------------------------------------------------
  72. //
  73. // DxilStructAnnotation class methods.
  74. //
  75. unsigned DxilStructAnnotation::GetNumFields() const {
  76. return (unsigned)m_FieldAnnotations.size();
  77. }
  78. DxilFieldAnnotation &DxilStructAnnotation::GetFieldAnnotation(unsigned FieldIdx) {
  79. return m_FieldAnnotations[FieldIdx];
  80. }
  81. const DxilFieldAnnotation &DxilStructAnnotation::GetFieldAnnotation(unsigned FieldIdx) const {
  82. return m_FieldAnnotations[FieldIdx];
  83. }
  84. const StructType *DxilStructAnnotation::GetStructType() const {
  85. return m_pStructType;
  86. }
  87. unsigned DxilStructAnnotation::GetCBufferSize() const { return m_CBufferSize; }
  88. void DxilStructAnnotation::SetCBufferSize(unsigned size) { m_CBufferSize = size; }
  89. void DxilStructAnnotation::MarkEmptyStruct() { m_FieldAnnotations.clear(); }
  90. bool DxilStructAnnotation::IsEmptyStruct() { return m_FieldAnnotations.empty(); }
  91. //------------------------------------------------------------------------------
  92. //
  93. // DxilParameterAnnotation class methods.
  94. //
  95. DxilParameterAnnotation::DxilParameterAnnotation()
  96. : DxilFieldAnnotation(), m_inputQual(DxilParamInputQual::In) {
  97. }
  98. DxilParamInputQual DxilParameterAnnotation::GetParamInputQual() const {
  99. return m_inputQual;
  100. }
  101. void DxilParameterAnnotation::SetParamInputQual(DxilParamInputQual qual) {
  102. m_inputQual = qual;
  103. }
  104. const std::vector<unsigned> &DxilParameterAnnotation::GetSemanticIndexVec() const {
  105. return m_semanticIndex;
  106. }
  107. void DxilParameterAnnotation::SetSemanticIndexVec(const std::vector<unsigned> &Vec) {
  108. m_semanticIndex = Vec;
  109. }
  110. void DxilParameterAnnotation::AppendSemanticIndex(unsigned SemIdx) {
  111. m_semanticIndex.emplace_back(SemIdx);
  112. }
  113. //------------------------------------------------------------------------------
  114. //
  115. // DxilFunctionAnnotation class methods.
  116. //
  117. unsigned DxilFunctionAnnotation::GetNumParameters() const {
  118. return (unsigned)m_parameterAnnotations.size();
  119. }
  120. DxilParameterAnnotation &DxilFunctionAnnotation::GetParameterAnnotation(unsigned ParamIdx) {
  121. return m_parameterAnnotations[ParamIdx];
  122. }
  123. const DxilParameterAnnotation &DxilFunctionAnnotation::GetParameterAnnotation(unsigned ParamIdx) const {
  124. return m_parameterAnnotations[ParamIdx];
  125. }
  126. DxilParameterAnnotation &DxilFunctionAnnotation::GetRetTypeAnnotation() {
  127. return m_retTypeAnnotation;
  128. }
  129. const DxilParameterAnnotation &DxilFunctionAnnotation::GetRetTypeAnnotation() const {
  130. return m_retTypeAnnotation;
  131. }
  132. const Function *DxilFunctionAnnotation::GetFunction() const {
  133. return m_pFunction;
  134. }
  135. //------------------------------------------------------------------------------
  136. //
  137. // DxilStructAnnotationSystem class methods.
  138. //
  139. DxilTypeSystem::DxilTypeSystem(Module *pModule)
  140. : m_pModule(pModule),
  141. m_LowPrecisionMode(DXIL::LowPrecisionMode::Undefined) {}
  142. DxilStructAnnotation *DxilTypeSystem::AddStructAnnotation(const StructType *pStructType) {
  143. DXASSERT_NOMSG(m_StructAnnotations.find(pStructType) == m_StructAnnotations.end());
  144. DxilStructAnnotation *pA = new DxilStructAnnotation();
  145. m_StructAnnotations[pStructType] = unique_ptr<DxilStructAnnotation>(pA);
  146. pA->m_pStructType = pStructType;
  147. pA->m_FieldAnnotations.resize(pStructType->getNumElements());
  148. return pA;
  149. }
  150. DxilStructAnnotation *DxilTypeSystem::GetStructAnnotation(const StructType *pStructType) {
  151. auto it = m_StructAnnotations.find(pStructType);
  152. if (it != m_StructAnnotations.end()) {
  153. return it->second.get();
  154. } else {
  155. return nullptr;
  156. }
  157. }
  158. const DxilStructAnnotation *
  159. DxilTypeSystem::GetStructAnnotation(const StructType *pStructType) const {
  160. auto it = m_StructAnnotations.find(pStructType);
  161. if (it != m_StructAnnotations.end()) {
  162. return it->second.get();
  163. } else {
  164. return nullptr;
  165. }
  166. }
  167. void DxilTypeSystem::EraseStructAnnotation(const StructType *pStructType) {
  168. DXASSERT_NOMSG(m_StructAnnotations.count(pStructType));
  169. m_StructAnnotations.remove_if([pStructType](
  170. const std::pair<const StructType *, std::unique_ptr<DxilStructAnnotation>>
  171. &I) { return pStructType == I.first; });
  172. }
  173. DxilTypeSystem::StructAnnotationMap &DxilTypeSystem::GetStructAnnotationMap() {
  174. return m_StructAnnotations;
  175. }
  176. DxilFunctionAnnotation *DxilTypeSystem::AddFunctionAnnotation(const Function *pFunction) {
  177. DXASSERT_NOMSG(m_FunctionAnnotations.find(pFunction) == m_FunctionAnnotations.end());
  178. DxilFunctionAnnotation *pA = new DxilFunctionAnnotation();
  179. m_FunctionAnnotations[pFunction] = unique_ptr<DxilFunctionAnnotation>(pA);
  180. pA->m_pFunction = pFunction;
  181. pA->m_parameterAnnotations.resize(pFunction->getFunctionType()->getNumParams());
  182. return pA;
  183. }
  184. DxilFunctionAnnotation *DxilTypeSystem::GetFunctionAnnotation(const Function *pFunction) {
  185. auto it = m_FunctionAnnotations.find(pFunction);
  186. if (it != m_FunctionAnnotations.end()) {
  187. return it->second.get();
  188. } else {
  189. return nullptr;
  190. }
  191. }
  192. const DxilFunctionAnnotation *
  193. DxilTypeSystem::GetFunctionAnnotation(const Function *pFunction) const {
  194. auto it = m_FunctionAnnotations.find(pFunction);
  195. if (it != m_FunctionAnnotations.end()) {
  196. return it->second.get();
  197. } else {
  198. return nullptr;
  199. }
  200. }
  201. void DxilTypeSystem::EraseFunctionAnnotation(const Function *pFunction) {
  202. DXASSERT_NOMSG(m_FunctionAnnotations.count(pFunction));
  203. m_FunctionAnnotations.remove_if([pFunction](
  204. const std::pair<const Function *, std::unique_ptr<DxilFunctionAnnotation>>
  205. &I) { return pFunction == I.first; });
  206. }
  207. DxilTypeSystem::FunctionAnnotationMap &DxilTypeSystem::GetFunctionAnnotationMap() {
  208. return m_FunctionAnnotations;
  209. }
  210. StructType *DxilTypeSystem::GetSNormF32Type(unsigned NumComps) {
  211. return GetNormFloatType(CompType::getSNormF32(), NumComps);
  212. }
  213. StructType *DxilTypeSystem::GetUNormF32Type(unsigned NumComps) {
  214. return GetNormFloatType(CompType::getUNormF32(), NumComps);
  215. }
  216. StructType *DxilTypeSystem::GetNormFloatType(CompType CT, unsigned NumComps) {
  217. Type *pCompType = CT.GetLLVMType(m_pModule->getContext());
  218. DXASSERT_NOMSG(pCompType->isFloatTy());
  219. Type *pFieldType = pCompType;
  220. string TypeName;
  221. raw_string_ostream NameStream(TypeName);
  222. if (NumComps > 1) {
  223. (NameStream << "dx.types." << NumComps << "x" << CT.GetName()).flush();
  224. pFieldType = VectorType::get(pFieldType, NumComps);
  225. } else {
  226. (NameStream << "dx.types." << CT.GetName()).flush();
  227. }
  228. StructType *pStructType = m_pModule->getTypeByName(TypeName);
  229. if (pStructType == nullptr) {
  230. pStructType = StructType::create(m_pModule->getContext(), pFieldType, TypeName);
  231. DxilStructAnnotation &TA = *AddStructAnnotation(pStructType);
  232. DxilFieldAnnotation &FA = TA.GetFieldAnnotation(0);
  233. FA.SetCompType(CT.GetKind());
  234. DXASSERT_NOMSG(CT.IsSNorm() || CT.IsUNorm());
  235. }
  236. return pStructType;
  237. }
  238. void DxilTypeSystem::CopyTypeAnnotation(const llvm::Type *Ty,
  239. const DxilTypeSystem &src) {
  240. if (isa<PointerType>(Ty))
  241. Ty = Ty->getPointerElementType();
  242. while (isa<ArrayType>(Ty))
  243. Ty = Ty->getArrayElementType();
  244. // Only struct type has annotation.
  245. if (!isa<StructType>(Ty))
  246. return;
  247. const StructType *ST = cast<StructType>(Ty);
  248. // Already exist.
  249. if (GetStructAnnotation(ST))
  250. return;
  251. if (const DxilStructAnnotation *annot = src.GetStructAnnotation(ST)) {
  252. DxilStructAnnotation *dstAnnot = AddStructAnnotation(ST);
  253. // Copy the annotation.
  254. *dstAnnot = *annot;
  255. // Copy field type annotations.
  256. for (Type *Ty : ST->elements()) {
  257. CopyTypeAnnotation(Ty, src);
  258. }
  259. }
  260. }
  261. void DxilTypeSystem::CopyFunctionAnnotation(const llvm::Function *pDstFunction,
  262. const llvm::Function *pSrcFunction,
  263. const DxilTypeSystem &src) {
  264. const DxilFunctionAnnotation *annot = src.GetFunctionAnnotation(pSrcFunction);
  265. // Don't have annotation.
  266. if (!annot)
  267. return;
  268. // Already exist.
  269. if (GetFunctionAnnotation(pDstFunction))
  270. return;
  271. DxilFunctionAnnotation *dstAnnot = AddFunctionAnnotation(pDstFunction);
  272. // Copy the annotation.
  273. *dstAnnot = *annot;
  274. dstAnnot->m_pFunction = pDstFunction;
  275. // Clone ret type annotation.
  276. CopyTypeAnnotation(pDstFunction->getReturnType(), src);
  277. // Clone param type annotations.
  278. for (const Argument &arg : pDstFunction->args()) {
  279. CopyTypeAnnotation(arg.getType(), src);
  280. }
  281. }
  282. DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q, DXIL::ShaderKind SK, bool isPC) {
  283. DXASSERT(Q != DxilParamInputQual::Inout, "Inout not expected for SigPointFromInputQual");
  284. switch (SK) {
  285. case DXIL::ShaderKind::Vertex:
  286. switch (Q) {
  287. case DxilParamInputQual::In:
  288. return DXIL::SigPointKind::VSIn;
  289. case DxilParamInputQual::Out:
  290. return DXIL::SigPointKind::VSOut;
  291. default:
  292. break;
  293. }
  294. break;
  295. case DXIL::ShaderKind::Hull:
  296. switch (Q) {
  297. case DxilParamInputQual::In:
  298. if (isPC)
  299. return DXIL::SigPointKind::PCIn;
  300. else
  301. return DXIL::SigPointKind::HSIn;
  302. case DxilParamInputQual::Out:
  303. if (isPC)
  304. return DXIL::SigPointKind::PCOut;
  305. else
  306. return DXIL::SigPointKind::HSCPOut;
  307. case DxilParamInputQual::InputPatch:
  308. return DXIL::SigPointKind::HSCPIn;
  309. case DxilParamInputQual::OutputPatch:
  310. return DXIL::SigPointKind::HSCPOut;
  311. default:
  312. break;
  313. }
  314. break;
  315. case DXIL::ShaderKind::Domain:
  316. switch (Q) {
  317. case DxilParamInputQual::In:
  318. return DXIL::SigPointKind::DSIn;
  319. case DxilParamInputQual::Out:
  320. return DXIL::SigPointKind::DSOut;
  321. case DxilParamInputQual::InputPatch:
  322. case DxilParamInputQual::OutputPatch:
  323. return DXIL::SigPointKind::DSCPIn;
  324. default:
  325. break;
  326. }
  327. break;
  328. case DXIL::ShaderKind::Geometry:
  329. switch (Q) {
  330. case DxilParamInputQual::In:
  331. return DXIL::SigPointKind::GSIn;
  332. case DxilParamInputQual::InputPrimitive:
  333. return DXIL::SigPointKind::GSVIn;
  334. case DxilParamInputQual::OutStream0:
  335. case DxilParamInputQual::OutStream1:
  336. case DxilParamInputQual::OutStream2:
  337. case DxilParamInputQual::OutStream3:
  338. return DXIL::SigPointKind::GSOut;
  339. default:
  340. break;
  341. }
  342. break;
  343. case DXIL::ShaderKind::Pixel:
  344. switch (Q) {
  345. case DxilParamInputQual::In:
  346. return DXIL::SigPointKind::PSIn;
  347. case DxilParamInputQual::Out:
  348. return DXIL::SigPointKind::PSOut;
  349. default:
  350. break;
  351. }
  352. break;
  353. case DXIL::ShaderKind::Compute:
  354. switch (Q) {
  355. case DxilParamInputQual::In:
  356. return DXIL::SigPointKind::CSIn;
  357. default:
  358. break;
  359. }
  360. break;
  361. default:
  362. break;
  363. }
  364. return DXIL::SigPointKind::Invalid;
  365. }
  366. void RemapSemantic(llvm::StringRef &oldSemName, llvm::StringRef &oldSemFullName, const char *newSemName,
  367. DxilParameterAnnotation &paramInfo, llvm::LLVMContext &Context) {
  368. // format deprecation warning
  369. Context.emitWarning(Twine("DX9-style semantic \"") + oldSemName + Twine("\" mapped to DX10 system semantic \"") + newSemName +
  370. Twine("\" due to -Gec flag. This functionality is deprecated in newer language versions."));
  371. // create new semantic name with the same index
  372. std::string newSemNameStr(newSemName);
  373. unsigned indexLen = oldSemFullName.size() - oldSemName.size();
  374. if (indexLen > 0) {
  375. newSemNameStr = newSemNameStr.append(oldSemFullName.data() + oldSemName.size(), indexLen);
  376. }
  377. paramInfo.SetSemanticString(newSemNameStr);
  378. }
  379. void RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo, DXIL::SigPointKind sigPoint, llvm::LLVMContext &Context) {
  380. DXASSERT(paramInfo.HasSemanticString(), "expected paramInfo with semantic");
  381. //*ppWarningMsg = nullptr;
  382. llvm::StringRef semFullName = paramInfo.GetSemanticStringRef();
  383. llvm::StringRef semName;
  384. unsigned semIndex;
  385. Semantic::DecomposeNameAndIndex(semFullName, &semName, &semIndex);
  386. if (sigPoint == DXIL::SigPointKind::PSOut) {
  387. if (semName.size() == 5) {
  388. if (_strnicmp(semName.data(), "COLOR", 5) == 0) {
  389. RemapSemantic(semName, semFullName, "SV_Target", paramInfo, Context);
  390. }
  391. else if (_strnicmp(semName.data(), "DEPTH", 5) == 0) {
  392. RemapSemantic(semName, semFullName, "SV_Depth", paramInfo, Context);
  393. }
  394. }
  395. }
  396. else if ((sigPoint == DXIL::SigPointKind::VSOut && semName.size() == 8 && _strnicmp(semName.data(), "POSITION", 8) == 0) ||
  397. (sigPoint == DXIL::SigPointKind::PSIn && semName.size() == 4 && _strnicmp(semName.data(), "VPOS", 4) == 0)) {
  398. RemapSemantic(semName, semFullName, "SV_Position", paramInfo, Context);
  399. }
  400. }
  401. bool DxilTypeSystem::UseMinPrecision() {
  402. if (m_LowPrecisionMode == DXIL::LowPrecisionMode::Undefined) {
  403. if (m_pModule->HasDxilModule()) {
  404. m_LowPrecisionMode = m_pModule->GetDxilModule().GetUseMinPrecision() ?
  405. DXIL::LowPrecisionMode::UseMinPrecision : DXIL::LowPrecisionMode::UseNativeLowPrecision;
  406. }
  407. else if (m_pModule->HasHLModule()) {
  408. m_LowPrecisionMode = m_pModule->GetHLModule().GetHLOptions().bUseMinPrecision ?
  409. DXIL::LowPrecisionMode::UseMinPrecision : DXIL::LowPrecisionMode::UseNativeLowPrecision;
  410. }
  411. else {
  412. DXASSERT(false, "otherwise module doesn't contain either HLModule or Dxil Module.");
  413. }
  414. }
  415. return m_LowPrecisionMode == DXIL::LowPrecisionMode::UseMinPrecision;
  416. }
  417. DxilStructTypeIterator::DxilStructTypeIterator(llvm::StructType *sTy, DxilStructAnnotation *sAnnotation,
  418. unsigned idx)
  419. : STy(sTy), SAnnotation(sAnnotation), index(idx) {
  420. DXASSERT(
  421. sTy->getNumElements() == sAnnotation->GetNumFields(),
  422. "Otherwise the pairing of annotation and struct type does not match.");
  423. }
  424. // prefix
  425. DxilStructTypeIterator &DxilStructTypeIterator::operator++() {
  426. index++;
  427. return *this;
  428. }
  429. // postfix
  430. DxilStructTypeIterator DxilStructTypeIterator::operator++(int) {
  431. DxilStructTypeIterator iter(STy, SAnnotation, index);
  432. index++;
  433. return iter;
  434. }
  435. bool DxilStructTypeIterator::operator==(DxilStructTypeIterator iter) {
  436. return iter.STy == STy && iter.SAnnotation == SAnnotation &&
  437. iter.index == index;
  438. }
  439. bool DxilStructTypeIterator::operator!=(DxilStructTypeIterator iter) { return !(operator==(iter)); }
  440. std::pair<llvm::Type *, DxilFieldAnnotation *> DxilStructTypeIterator::operator*() {
  441. return std::pair<llvm::Type *, DxilFieldAnnotation *>(
  442. STy->getElementType(index), &SAnnotation->GetFieldAnnotation(index));
  443. }
  444. DxilStructTypeIterator begin(llvm::StructType *STy, DxilStructAnnotation *SAnno) {
  445. return { STy, SAnno, 0 };
  446. }
  447. DxilStructTypeIterator end(llvm::StructType *STy, DxilStructAnnotation *SAnno) {
  448. return { STy, SAnno, STy->getNumElements() };
  449. }
  450. } // namespace hlsl