DxilTypeSystem.cpp 16 KB

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