DxilContainerReflection.cpp 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilContainerReflection.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. // Provides support for reading DXIL container structures. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "llvm/Bitcode/ReaderWriter.h"
  12. #include "llvm/IR/LLVMContext.h"
  13. #include "llvm/IR/InstIterator.h"
  14. #include "dxc/HLSL/DxilContainer.h"
  15. #include "dxc/HLSL/DxilModule.h"
  16. #include "dxc/HLSL/DxilShaderModel.h"
  17. #include "dxc/HLSL/DxilOperations.h"
  18. #include "dxc/HLSL/DxilInstructions.h"
  19. #include "dxc/Support/Global.h"
  20. #include "dxc/Support/Unicode.h"
  21. #include "dxc/Support/WinIncludes.h"
  22. #include "dxc/Support/microcom.h"
  23. #include "dxc/Support/FileIOHelper.h"
  24. #include "dxc/Support/dxcapi.impl.h"
  25. #include <unordered_set>
  26. #include "dxc/dxcapi.h"
  27. #include "d3d12shader.h" // for compatibility
  28. #include "d3d11shader.h" // for compatibility
  29. const GUID IID_ID3D11ShaderReflection_43 = {
  30. 0x0a233719,
  31. 0x3960,
  32. 0x4578,
  33. {0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1}};
  34. const GUID IID_ID3D11ShaderReflection_47 = {
  35. 0x8d536ca1,
  36. 0x0cca,
  37. 0x4956,
  38. {0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84}};
  39. using namespace llvm;
  40. using namespace hlsl;
  41. class DxilContainerReflection : public IDxcContainerReflection {
  42. private:
  43. DXC_MICROCOM_REF_FIELD(m_dwRef)
  44. CComPtr<IDxcBlob> m_container;
  45. const DxilContainerHeader *m_pHeader;
  46. uint32_t m_headerLen;
  47. bool IsLoaded() const { return m_pHeader != nullptr; }
  48. public:
  49. DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef)
  50. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
  51. return DoBasicQueryInterface<IDxcContainerReflection>(this, iid, ppvObject);
  52. }
  53. DxilContainerReflection() : m_dwRef(0), m_pHeader(nullptr), m_headerLen(0) { }
  54. __override HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer);
  55. __override HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult);
  56. __override HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult);
  57. __override HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult);
  58. __override HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult);
  59. __override HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, _COM_Outptr_ void **ppvObject);
  60. };
  61. class CShaderReflectionConstantBuffer;
  62. class CShaderReflectionType;
  63. class DxilShaderReflection : public ID3D12ShaderReflection {
  64. private:
  65. DXC_MICROCOM_REF_FIELD(m_dwRef)
  66. CComPtr<IDxcBlob> m_pContainer;
  67. LLVMContext Context;
  68. std::unique_ptr<Module> m_pModule; // Must come after LLVMContext, otherwise unique_ptr will over-delete.
  69. DxilModule *m_pDxilModule;
  70. std::vector<CShaderReflectionConstantBuffer> m_CBs;
  71. std::vector<D3D12_SHADER_INPUT_BIND_DESC> m_Resources;
  72. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_InputSignature;
  73. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_OutputSignature;
  74. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_PatchConstantSignature;
  75. std::vector<std::unique_ptr<char[]>> m_UpperCaseNames;
  76. std::vector<std::unique_ptr<CShaderReflectionType>> m_Types;
  77. void CreateReflectionObjects();
  78. void SetCBufferUsage();
  79. void CreateReflectionObjectForResource(DxilResourceBase *R);
  80. void CreateReflectionObjectsForSignature(
  81. const DxilSignature &Sig,
  82. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> &Descs);
  83. LPCSTR CreateUpperCase(LPCSTR pValue);
  84. void MarkUsedSignatureElements();
  85. public:
  86. enum class PublicAPI { D3D12 = 0, D3D11_47 = 1, D3D11_43 = 2 };
  87. PublicAPI m_PublicAPI;
  88. void SetPublicAPI(PublicAPI value) { m_PublicAPI = value; }
  89. static PublicAPI IIDToAPI(REFIID iid) {
  90. DxilShaderReflection::PublicAPI api =
  91. DxilShaderReflection::PublicAPI::D3D12;
  92. if (IsEqualIID(IID_ID3D11ShaderReflection_43, iid))
  93. api = DxilShaderReflection::PublicAPI::D3D11_43;
  94. else if (IsEqualIID(IID_ID3D11ShaderReflection_47, iid))
  95. api = DxilShaderReflection::PublicAPI::D3D11_47;
  96. return api;
  97. }
  98. DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef)
  99. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
  100. HRESULT hr = DoBasicQueryInterface<ID3D12ShaderReflection>(this, iid, ppvObject);
  101. if (hr == E_NOINTERFACE) {
  102. // ID3D11ShaderReflection is identical to ID3D12ShaderReflection, except
  103. // for some shorter data structures in some out parameters.
  104. PublicAPI api = IIDToAPI(iid);
  105. if (api == m_PublicAPI) {
  106. *ppvObject = (ID3D12ShaderReflection *)this;
  107. this->AddRef();
  108. hr = S_OK;
  109. }
  110. }
  111. return hr;
  112. }
  113. DxilShaderReflection() : m_dwRef(0), m_pDxilModule(nullptr) { }
  114. HRESULT Load(IDxcBlob *pBlob, const DxilPartHeader *pPart);
  115. // ID3D12ShaderReflection
  116. STDMETHODIMP GetDesc(THIS_ _Out_ D3D12_SHADER_DESC *pDesc);
  117. STDMETHODIMP_(ID3D12ShaderReflectionConstantBuffer*) GetConstantBufferByIndex(THIS_ _In_ UINT Index);
  118. STDMETHODIMP_(ID3D12ShaderReflectionConstantBuffer*) GetConstantBufferByName(THIS_ _In_ LPCSTR Name);
  119. STDMETHODIMP GetResourceBindingDesc(THIS_ _In_ UINT ResourceIndex,
  120. _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc);
  121. STDMETHODIMP GetInputParameterDesc(THIS_ _In_ UINT ParameterIndex,
  122. _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc);
  123. STDMETHODIMP GetOutputParameterDesc(THIS_ _In_ UINT ParameterIndex,
  124. _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc);
  125. STDMETHODIMP GetPatchConstantParameterDesc(THIS_ _In_ UINT ParameterIndex,
  126. _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc);
  127. STDMETHODIMP_(ID3D12ShaderReflectionVariable*) GetVariableByName(THIS_ _In_ LPCSTR Name);
  128. STDMETHODIMP GetResourceBindingDescByName(THIS_ _In_ LPCSTR Name,
  129. _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc);
  130. STDMETHODIMP_(UINT) GetMovInstructionCount(THIS);
  131. STDMETHODIMP_(UINT) GetMovcInstructionCount(THIS);
  132. STDMETHODIMP_(UINT) GetConversionInstructionCount(THIS);
  133. STDMETHODIMP_(UINT) GetBitwiseInstructionCount(THIS);
  134. STDMETHODIMP_(D3D_PRIMITIVE) GetGSInputPrimitive(THIS);
  135. STDMETHODIMP_(BOOL) IsSampleFrequencyShader(THIS);
  136. STDMETHODIMP_(UINT) GetNumInterfaceSlots(THIS);
  137. STDMETHODIMP GetMinFeatureLevel(THIS_ _Out_ enum D3D_FEATURE_LEVEL* pLevel);
  138. STDMETHODIMP_(UINT) GetThreadGroupSize(THIS_
  139. _Out_opt_ UINT* pSizeX,
  140. _Out_opt_ UINT* pSizeY,
  141. _Out_opt_ UINT* pSizeZ);
  142. STDMETHODIMP_(UINT64) GetRequiresFlags(THIS);
  143. };
  144. _Use_decl_annotations_
  145. HRESULT DxilContainerReflection::Load(IDxcBlob *pContainer) {
  146. if (pContainer == nullptr) {
  147. m_container.Release();
  148. m_pHeader = nullptr;
  149. m_headerLen = 0;
  150. return S_OK;
  151. }
  152. uint32_t bufLen = pContainer->GetBufferSize();
  153. const DxilContainerHeader *pHeader =
  154. IsDxilContainerLike(pContainer->GetBufferPointer(), bufLen);
  155. if (pHeader == nullptr) {
  156. return E_INVALIDARG;
  157. }
  158. if (!IsValidDxilContainer(pHeader, bufLen)) {
  159. return E_INVALIDARG;
  160. }
  161. m_container = pContainer;
  162. m_headerLen = bufLen;
  163. m_pHeader = pHeader;
  164. return S_OK;
  165. }
  166. _Use_decl_annotations_
  167. HRESULT DxilContainerReflection::GetPartCount(UINT32 *pResult) {
  168. if (pResult == nullptr) return E_POINTER;
  169. if (!IsLoaded()) return E_NOT_VALID_STATE;
  170. *pResult = m_pHeader->PartCount;
  171. return S_OK;
  172. }
  173. _Use_decl_annotations_
  174. HRESULT DxilContainerReflection::GetPartKind(UINT32 idx, _Out_ UINT32 *pResult) {
  175. if (pResult == nullptr) return E_POINTER;
  176. if (!IsLoaded()) return E_NOT_VALID_STATE;
  177. if (idx >= m_pHeader->PartCount) return E_BOUNDS;
  178. const DxilPartHeader *pPart = GetDxilContainerPart(m_pHeader, idx);
  179. *pResult = pPart->PartFourCC;
  180. return S_OK;
  181. }
  182. _Use_decl_annotations_
  183. HRESULT DxilContainerReflection::GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) {
  184. if (ppResult == nullptr) return E_POINTER;
  185. *ppResult = nullptr;
  186. if (!IsLoaded()) return E_NOT_VALID_STATE;
  187. if (idx >= m_pHeader->PartCount) return E_BOUNDS;
  188. const DxilPartHeader *pPart = GetDxilContainerPart(m_pHeader, idx);
  189. const char *pData = GetDxilPartData(pPart);
  190. uint32_t offset = (uint32_t)(pData - (char*)m_container->GetBufferPointer()); // Offset from the beginning.
  191. uint32_t length = pPart->PartSize;
  192. return DxcCreateBlobFromBlob(m_container, offset, length, ppResult);
  193. }
  194. _Use_decl_annotations_
  195. HRESULT DxilContainerReflection::FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) {
  196. if (pResult == nullptr) return E_POINTER;
  197. *pResult = 0;
  198. if (!IsLoaded()) return E_NOT_VALID_STATE;
  199. DxilPartIterator it = std::find_if(begin(m_pHeader), end(m_pHeader), DxilPartIsType(kind));
  200. if (it == end(m_pHeader)) return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  201. *pResult = it.index;
  202. return S_OK;
  203. }
  204. _Use_decl_annotations_
  205. HRESULT DxilContainerReflection::GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) {
  206. if (ppvObject == nullptr) return E_POINTER;
  207. *ppvObject = nullptr;
  208. if (!IsLoaded()) return E_NOT_VALID_STATE;
  209. if (idx >= m_pHeader->PartCount) return E_BOUNDS;
  210. const DxilPartHeader *pPart = GetDxilContainerPart(m_pHeader, idx);
  211. if (pPart->PartFourCC != DFCC_DXIL && pPart->PartFourCC != DFCC_ShaderDebugInfoDXIL) {
  212. return E_NOTIMPL;
  213. }
  214. HRESULT hr = S_OK;
  215. CComPtr<DxilShaderReflection> pReflection = new (std::nothrow)DxilShaderReflection();
  216. IFCOOM(pReflection.p);
  217. DxilShaderReflection::PublicAPI api = DxilShaderReflection::IIDToAPI(iid);
  218. pReflection->SetPublicAPI(api);
  219. IFC(pReflection->Load(m_container, pPart));
  220. IFC(pReflection.p->QueryInterface(iid, ppvObject));
  221. Cleanup:
  222. return hr;
  223. }
  224. void hlsl::CreateDxcContainerReflection(IDxcContainerReflection **ppResult) {
  225. CComPtr<DxilContainerReflection> pReflection = new DxilContainerReflection();
  226. *ppResult = pReflection.Detach();
  227. }
  228. ///////////////////////////////////////////////////////////////////////////////
  229. // DxilShaderReflection implementation - helper objects. //
  230. class CShaderReflectionType;
  231. class CShaderReflectionVariable;
  232. class CShaderReflectionConstantBuffer;
  233. class CShaderReflection;
  234. struct D3D11_INTERNALSHADER_RESOURCE_DEF;
  235. class CShaderReflectionType : public ID3D12ShaderReflectionType
  236. {
  237. protected:
  238. D3D12_SHADER_TYPE_DESC m_Desc;
  239. std::string m_Name;
  240. std::vector<StringRef> m_MemberNames;
  241. std::vector<CShaderReflectionType*> m_MemberTypes;
  242. CShaderReflectionType* m_pSubType;
  243. CShaderReflectionType* m_pBaseClass;
  244. std::vector<CShaderReflectionType*> m_Interfaces;
  245. ULONG_PTR m_Identity;
  246. public:
  247. // Internal
  248. HRESULT Initialize(
  249. DxilModule &M,
  250. llvm::Type *type,
  251. DxilFieldAnnotation &typeAnnotation,
  252. unsigned int baseOffset,
  253. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
  254. // ID3D12ShaderReflectionType
  255. STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC *pDesc);
  256. STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByIndex)(UINT Index);
  257. STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByName)(LPCSTR Name);
  258. STDMETHOD_(LPCSTR, GetMemberTypeName)(UINT Index);
  259. STDMETHOD(IsEqual)(THIS_ ID3D12ShaderReflectionType* pType);
  260. STDMETHOD_(ID3D12ShaderReflectionType*, GetSubType)(THIS);
  261. STDMETHOD_(ID3D12ShaderReflectionType*, GetBaseClass)(THIS);
  262. STDMETHOD_(UINT, GetNumInterfaces)(THIS);
  263. STDMETHOD_(ID3D12ShaderReflectionType*, GetInterfaceByIndex)(THIS_ UINT uIndex);
  264. STDMETHOD(IsOfType)(THIS_ ID3D12ShaderReflectionType* pType);
  265. STDMETHOD(ImplementsInterface)(THIS_ ID3D12ShaderReflectionType* pBase);
  266. bool CheckEqual(__in CShaderReflectionType *pOther) {
  267. return m_Identity == pOther->m_Identity;
  268. }
  269. };
  270. class CShaderReflectionVariable : public ID3D12ShaderReflectionVariable
  271. {
  272. protected:
  273. D3D12_SHADER_VARIABLE_DESC m_Desc;
  274. CShaderReflectionType *m_pType;
  275. CShaderReflectionConstantBuffer *m_pBuffer;
  276. BYTE *m_pDefaultValue;
  277. public:
  278. void Initialize(CShaderReflectionConstantBuffer *pBuffer,
  279. D3D12_SHADER_VARIABLE_DESC *pDesc,
  280. CShaderReflectionType *pType, BYTE *pDefaultValue);
  281. LPCSTR GetName() { return m_Desc.Name; }
  282. // ID3D12ShaderReflectionVariable
  283. STDMETHOD(GetDesc)(D3D12_SHADER_VARIABLE_DESC *pDesc);
  284. STDMETHOD_(ID3D12ShaderReflectionType*, GetType)();
  285. STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetBuffer)();
  286. STDMETHOD_(UINT, GetInterfaceSlot)(THIS_ UINT uArrayIndex);
  287. };
  288. class CShaderReflectionConstantBuffer : public ID3D12ShaderReflectionConstantBuffer
  289. {
  290. protected:
  291. D3D12_SHADER_BUFFER_DESC m_Desc;
  292. std::vector<CShaderReflectionVariable> m_Variables;
  293. public:
  294. CShaderReflectionConstantBuffer() = default;
  295. CShaderReflectionConstantBuffer(CShaderReflectionConstantBuffer &&other) {
  296. m_Desc = other.m_Desc;
  297. std::swap(m_Variables, other.m_Variables);
  298. }
  299. void Initialize(DxilModule &M,
  300. DxilCBuffer &CB,
  301. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
  302. void InitializeStructuredBuffer(DxilModule &M,
  303. DxilResource &R,
  304. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes);
  305. LPCSTR GetName() { return m_Desc.Name; }
  306. // ID3D12ShaderReflectionConstantBuffer
  307. STDMETHOD(GetDesc)(D3D12_SHADER_BUFFER_DESC *pDesc);
  308. STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByIndex)(UINT Index);
  309. STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(LPCSTR Name);
  310. };
  311. // Invalid type sentinel definitions
  312. class CInvalidSRType;
  313. class CInvalidSRVariable;
  314. class CInvalidSRConstantBuffer;
  315. class CInvalidSRLibraryFunction;
  316. class CInvalidSRFunctionParameter;
  317. class CInvalidSRType : public ID3D12ShaderReflectionType {
  318. STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC *pDesc) { return E_FAIL; }
  319. STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByIndex)(UINT Index);
  320. STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByName)(LPCSTR Name);
  321. STDMETHOD_(LPCSTR, GetMemberTypeName)(UINT Index) { return "$Invalid"; }
  322. STDMETHOD(IsEqual)(THIS_ ID3D12ShaderReflectionType* pType) { return E_FAIL; }
  323. STDMETHOD_(ID3D12ShaderReflectionType*, GetSubType)(THIS);
  324. STDMETHOD_(ID3D12ShaderReflectionType*, GetBaseClass)(THIS);
  325. STDMETHOD_(UINT, GetNumInterfaces)(THIS) { return 0; }
  326. STDMETHOD_(ID3D12ShaderReflectionType*, GetInterfaceByIndex)(THIS_ UINT uIndex);
  327. STDMETHOD(IsOfType)(THIS_ ID3D12ShaderReflectionType* pType) { return E_FAIL; }
  328. STDMETHOD(ImplementsInterface)(THIS_ ID3D12ShaderReflectionType* pBase) { return E_FAIL; }
  329. };
  330. static CInvalidSRType g_InvalidSRType;
  331. ID3D12ShaderReflectionType* CInvalidSRType::GetMemberTypeByIndex(UINT) { return &g_InvalidSRType; }
  332. ID3D12ShaderReflectionType* CInvalidSRType::GetMemberTypeByName(LPCSTR) { return &g_InvalidSRType; }
  333. ID3D12ShaderReflectionType* CInvalidSRType::GetSubType() { return &g_InvalidSRType; }
  334. ID3D12ShaderReflectionType* CInvalidSRType::GetBaseClass() { return &g_InvalidSRType; }
  335. ID3D12ShaderReflectionType* CInvalidSRType::GetInterfaceByIndex(UINT) { return &g_InvalidSRType; }
  336. class CInvalidSRVariable : public ID3D12ShaderReflectionVariable {
  337. STDMETHOD(GetDesc)(D3D12_SHADER_VARIABLE_DESC *pDesc) { return E_FAIL; }
  338. STDMETHOD_(ID3D12ShaderReflectionType*, GetType)() { return &g_InvalidSRType; }
  339. STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetBuffer)();
  340. STDMETHOD_(UINT, GetInterfaceSlot)(THIS_ UINT uIndex) { return UINT_MAX; }
  341. };
  342. static CInvalidSRVariable g_InvalidSRVariable;
  343. class CInvalidSRConstantBuffer : public ID3D12ShaderReflectionConstantBuffer {
  344. STDMETHOD(GetDesc)(D3D12_SHADER_BUFFER_DESC *pDesc) { return E_FAIL; }
  345. STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByIndex)(UINT Index) { return &g_InvalidSRVariable; }
  346. STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(LPCSTR Name) { return &g_InvalidSRVariable; }
  347. };
  348. static CInvalidSRConstantBuffer g_InvalidSRConstantBuffer;
  349. void CShaderReflectionVariable::Initialize(
  350. CShaderReflectionConstantBuffer *pBuffer, D3D12_SHADER_VARIABLE_DESC *pDesc,
  351. CShaderReflectionType *pType, BYTE *pDefaultValue) {
  352. m_pBuffer = pBuffer;
  353. memcpy(&m_Desc, pDesc, sizeof(m_Desc));
  354. m_pType = pType;
  355. m_pDefaultValue = pDefaultValue;
  356. }
  357. HRESULT CShaderReflectionVariable::GetDesc(D3D12_SHADER_VARIABLE_DESC *pDesc) {
  358. if (!pDesc) return E_POINTER;
  359. memcpy(pDesc, &m_Desc, sizeof(m_Desc));
  360. return S_OK;
  361. }
  362. ID3D12ShaderReflectionType *CShaderReflectionVariable::GetType() {
  363. return m_pType;
  364. }
  365. ID3D12ShaderReflectionConstantBuffer *CShaderReflectionVariable::GetBuffer() {
  366. return m_pBuffer;
  367. }
  368. UINT CShaderReflectionVariable::GetInterfaceSlot(UINT uArrayIndex) {
  369. return UINT_MAX;
  370. }
  371. ID3D12ShaderReflectionConstantBuffer *CInvalidSRVariable::GetBuffer() {
  372. return &g_InvalidSRConstantBuffer;
  373. }
  374. STDMETHODIMP CShaderReflectionType::GetDesc(D3D12_SHADER_TYPE_DESC *pDesc)
  375. {
  376. if (!pDesc) return E_POINTER;
  377. memcpy(pDesc, &m_Desc, sizeof(m_Desc));
  378. return S_OK;
  379. }
  380. STDMETHODIMP_(ID3D12ShaderReflectionType*) CShaderReflectionType::GetMemberTypeByIndex(UINT Index)
  381. {
  382. if (Index >= m_MemberTypes.size()) {
  383. return &g_InvalidSRType;
  384. }
  385. return m_MemberTypes[Index];
  386. }
  387. STDMETHODIMP_(LPCSTR) CShaderReflectionType::GetMemberTypeName(UINT Index)
  388. {
  389. if (Index >= m_MemberTypes.size()) {
  390. return nullptr;
  391. }
  392. return (LPCSTR) m_MemberNames[Index].bytes_begin();
  393. }
  394. STDMETHODIMP_(ID3D12ShaderReflectionType*) CShaderReflectionType::GetMemberTypeByName(LPCSTR Name)
  395. {
  396. UINT memberCount = m_Desc.Members;
  397. for( UINT mm = 0; mm < memberCount; ++mm ) {
  398. if( m_MemberNames[mm] == Name ) {
  399. return m_MemberTypes[mm];
  400. }
  401. }
  402. return nullptr;
  403. }
  404. STDMETHODIMP CShaderReflectionType::IsEqual(THIS_ ID3D12ShaderReflectionType* pType)
  405. {
  406. // TODO: implement this check, if users actually depend on it
  407. return S_FALSE;
  408. }
  409. STDMETHODIMP_(ID3D12ShaderReflectionType*) CShaderReflectionType::GetSubType(THIS)
  410. {
  411. // TODO: implement `class`-related features, if requested
  412. return nullptr;
  413. }
  414. STDMETHODIMP_(ID3D12ShaderReflectionType*) CShaderReflectionType::GetBaseClass(THIS)
  415. {
  416. // TODO: implement `class`-related features, if requested
  417. return nullptr;
  418. }
  419. STDMETHODIMP_(UINT) CShaderReflectionType::GetNumInterfaces(THIS)
  420. {
  421. // HLSL interfaces have been deprecated
  422. return 0;
  423. }
  424. STDMETHODIMP_(ID3D12ShaderReflectionType*) CShaderReflectionType::GetInterfaceByIndex(THIS_ UINT uIndex)
  425. {
  426. // HLSL interfaces have been deprecated
  427. return nullptr;
  428. }
  429. STDMETHODIMP CShaderReflectionType::IsOfType(THIS_ ID3D12ShaderReflectionType* pType)
  430. {
  431. // TODO: implement `class`-related features, if requested
  432. return S_FALSE;
  433. }
  434. STDMETHODIMP CShaderReflectionType::ImplementsInterface(THIS_ ID3D12ShaderReflectionType* pBase)
  435. {
  436. // HLSL interfaces have been deprecated
  437. return S_FALSE;
  438. }
  439. // Helper routine for types that don't have an obvious mapping
  440. // to the existing shader reflection interface.
  441. static bool ProcessUnhandledObjectType(
  442. llvm::StructType *structType,
  443. D3D_SHADER_VARIABLE_TYPE *outObjectType)
  444. {
  445. // Don't actually make this a hard error, but instead report the problem using a suitable debug message.
  446. #ifdef DBG
  447. OutputDebugFormatA("DxilContainerReflection.cpp: error: unhandled object type '%s'.\n", structType->getName().str().c_str());
  448. #endif
  449. *outObjectType = D3D_SVT_VOID;
  450. return true;
  451. }
  452. // Helper routine to try to detect if a type represents an HLSL "object" type
  453. // (a texture, sampler, buffer, etc.), and to extract the coresponding shader
  454. // reflection type.
  455. static bool TryToDetectObjectType(
  456. llvm::StructType *structType,
  457. D3D_SHADER_VARIABLE_TYPE *outObjectType)
  458. {
  459. // Note: This logic is largely duplicated from `HLModule::IsHLSLObjectType`
  460. // with the addition of returning the appropriate reflection type tag.
  461. //
  462. // That logic looks error-prone, since it relies on string tests against
  463. // type names, including cases that just test against a prefix.
  464. // This code doesn't try to be any more robust.
  465. StringRef name = structType->getName();
  466. if(name.startswith("dx.types.wave_t") )
  467. {
  468. return ProcessUnhandledObjectType(structType, outObjectType);
  469. }
  470. // Strip off some prefixes we are likely to see.
  471. name = name.ltrim("class.");
  472. name = name.ltrim("struct.");
  473. // Slice types occur as intermediates (they aren not objects)
  474. if(name.endswith("_slice_type")) { return false; }
  475. // We might check for an exact name match, or a prefix match
  476. #define EXACT_MATCH(NAME, TAG) \
  477. else if(name == #NAME) do { *outObjectType = TAG; return true; } while(0)
  478. #define PREFIX_MATCH(NAME, TAG) \
  479. else if(name.startswith(#NAME)) do { *outObjectType = TAG; return true; } while(0)
  480. if(0) {}
  481. EXACT_MATCH(SamplerState, D3D_SVT_SAMPLER);
  482. EXACT_MATCH(SamplerComparisonState, D3D_SVT_SAMPLER);
  483. // Note: GS output stream types are supported in the reflection interface.
  484. else if(name.startswith("TriangleStream")) { return ProcessUnhandledObjectType(structType, outObjectType); }
  485. else if(name.startswith("PointStream")) { return ProcessUnhandledObjectType(structType, outObjectType); }
  486. else if(name.startswith("LineStream")) { return ProcessUnhandledObjectType(structType, outObjectType); }
  487. PREFIX_MATCH(AppendStructuredBuffer, D3D_SVT_APPEND_STRUCTURED_BUFFER);
  488. PREFIX_MATCH(ConsumeStructuredBuffer, D3D_SVT_CONSUME_STRUCTURED_BUFFER);
  489. PREFIX_MATCH(ConstantBuffer, D3D_SVT_CBUFFER);
  490. // Note: the `HLModule` code does this trick to avoid checking more names
  491. // than it has to, but it doesn't seem 100% correct to do this.
  492. // TODO: consider just listing the `RasterizerOrdered` cases explicitly,
  493. // just as we do for the `RW` cases already.
  494. name = name.ltrim("RasterizerOrdered");
  495. if(0) {}
  496. EXACT_MATCH(ByteAddressBuffer, D3D_SVT_BYTEADDRESS_BUFFER);
  497. EXACT_MATCH(RWByteAddressBuffer, D3D_SVT_RWBYTEADDRESS_BUFFER);
  498. PREFIX_MATCH(Buffer, D3D_SVT_BUFFER);
  499. PREFIX_MATCH(RWBuffer, D3D_SVT_RWBUFFER);
  500. PREFIX_MATCH(StructuredBuffer, D3D_SVT_STRUCTURED_BUFFER);
  501. PREFIX_MATCH(RWStructuredBuffer, D3D_SVT_RWSTRUCTURED_BUFFER);
  502. PREFIX_MATCH(Texture1D, D3D_SVT_TEXTURE1D);
  503. PREFIX_MATCH(RWTexture1D, D3D_SVT_RWTEXTURE1D);
  504. PREFIX_MATCH(Texture1DArray, D3D_SVT_TEXTURE1DARRAY);
  505. PREFIX_MATCH(RWTexture1DArray, D3D_SVT_RWTEXTURE1DARRAY);
  506. PREFIX_MATCH(Texture2D, D3D_SVT_TEXTURE2D);
  507. PREFIX_MATCH(RWTexture2D, D3D_SVT_RWTEXTURE2D);
  508. PREFIX_MATCH(Texture2DArray, D3D_SVT_TEXTURE2DARRAY);
  509. PREFIX_MATCH(RWTexture2DArray, D3D_SVT_RWTEXTURE2DARRAY);
  510. PREFIX_MATCH(Texture3D, D3D_SVT_TEXTURE3D);
  511. PREFIX_MATCH(RWTexture3D, D3D_SVT_RWTEXTURE3D);
  512. PREFIX_MATCH(TextureCube, D3D_SVT_TEXTURECUBE);
  513. PREFIX_MATCH(TextureCubeArray, D3D_SVT_TEXTURECUBEARRAY);
  514. PREFIX_MATCH(Texture2DMS, D3D_SVT_TEXTURE2DMS);
  515. PREFIX_MATCH(Texture2DMSArray, D3D_SVT_TEXTURE2DMSARRAY);
  516. #undef EXACT_MATCH
  517. #undef PREFIX_MATCH
  518. // Default: not an object type
  519. return false;
  520. }
  521. // Helper to determine if an LLVM type represents an HLSL
  522. // object type (uses the `TryToDetectObjectType()` function
  523. // defined previously).
  524. static bool IsObjectType(
  525. llvm::Type* inType)
  526. {
  527. llvm::Type* type = inType;
  528. while(type->isArrayTy())
  529. {
  530. type = type->getArrayElementType();
  531. }
  532. llvm::StructType* structType = dyn_cast<StructType>(type);
  533. if(!structType)
  534. return false;
  535. D3D_SHADER_VARIABLE_TYPE ignored;
  536. return TryToDetectObjectType(structType, &ignored);
  537. }
  538. // Main logic for translating an LLVM type and associated
  539. // annotations into a D3D shader reflection type.
  540. HRESULT CShaderReflectionType::Initialize(
  541. DxilModule &M,
  542. llvm::Type *inType,
  543. DxilFieldAnnotation &typeAnnotation,
  544. unsigned int baseOffset,
  545. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes)
  546. {
  547. DXASSERT_NOMSG(inType);
  548. // Set a bunch of fields to default values, to avoid duplication.
  549. m_Desc.Rows = 0;
  550. m_Desc.Columns = 0;
  551. m_Desc.Elements = 0;
  552. m_Desc.Members = 0;
  553. // Extract offset relative to parent.
  554. // Note: the `baseOffset` is used in the case where the type in
  555. // question is a field in a constant buffer, since then both the
  556. // field and the variable store the same offset information, and
  557. // we need to zero out the value in the type to avoid the user
  558. // of the reflection interface seeing 2x the correct value.
  559. m_Desc.Offset = typeAnnotation.GetCBufferOffset() - baseOffset;
  560. // Arrays don't seem to be represented directly in the reflection
  561. // data, but only as the `Elements` field being non-zero.
  562. // We "unwrap" any array type here, and then proceed to look
  563. // at the element type.
  564. llvm::Type* type = inType;
  565. while(type->isArrayTy())
  566. {
  567. llvm::Type* elementType = type->getArrayElementType();
  568. // Note: At this point an HLSL matrix type may appear as an ordinary
  569. // array (not wrapped in a `struct`), so `HLMatrixLower::IsMatrixType()`
  570. // is not sufficient. Instead we need to check the field annotation.
  571. //
  572. // We might have an array of matrices, though, so we only exit if
  573. // the field annotation says we have a matrix, and we've bottomed
  574. // out and the element type isn't itself an array.
  575. if(typeAnnotation.HasMatrixAnnotation() && !elementType->isArrayTy())
  576. {
  577. break;
  578. }
  579. // Non-array types should have `Elements` be zero, so as soon as we
  580. // find that we have our first real array (not a matrix), we initialize `Elements`
  581. if(!m_Desc.Elements) m_Desc.Elements = 1;
  582. // It isn't clear what is the desired behavior for multi-dimensional arrays,
  583. // but for now we do the expedient thing of multiplying out all their
  584. // dimensions.
  585. m_Desc.Elements *= type->getArrayNumElements();
  586. type = elementType;
  587. }
  588. // Default to a scalar type, just to avoid some duplication later.
  589. m_Desc.Class = D3D_SVC_SCALAR;
  590. // Look at the annotation to try to determine the basic type of value.
  591. //
  592. // Note that DXIL supports some types that don't currently have equivalents
  593. // in the reflection interface, so we try to muddle through here.
  594. D3D_SHADER_VARIABLE_TYPE componentType = D3D_SVT_VOID;
  595. switch(typeAnnotation.GetCompType().GetKind())
  596. {
  597. case hlsl::DXIL::ComponentType::Invalid:
  598. break;
  599. case hlsl::DXIL::ComponentType::I1:
  600. componentType = D3D_SVT_BOOL;
  601. m_Name = "bool";
  602. break;
  603. case hlsl::DXIL::ComponentType::I16:
  604. componentType = D3D_SVT_MIN16INT;
  605. m_Name = "min16int";
  606. break;
  607. case hlsl::DXIL::ComponentType::U16:
  608. componentType = D3D_SVT_MIN16UINT;
  609. m_Name = "min16uint";
  610. break;
  611. case hlsl::DXIL::ComponentType::I64:
  612. #ifdef DBG
  613. OutputDebugStringA("DxilContainerReflection.cpp: warning: component of type 'I64' being reflected as if 'I32'\n");
  614. #endif
  615. case hlsl::DXIL::ComponentType::I32:
  616. componentType = D3D_SVT_INT;
  617. m_Name = "int";
  618. break;
  619. case hlsl::DXIL::ComponentType::U64:
  620. #ifdef DBG
  621. OutputDebugStringA("DxilContainerReflection.cpp: warning: component of type 'U64' being reflected as if 'U32'\n");
  622. #endif
  623. case hlsl::DXIL::ComponentType::U32:
  624. componentType = D3D_SVT_UINT;
  625. m_Name = "uint";
  626. break;
  627. case hlsl::DXIL::ComponentType::F16:
  628. case hlsl::DXIL::ComponentType::SNormF16:
  629. case hlsl::DXIL::ComponentType::UNormF16:
  630. componentType = D3D_SVT_MIN16FLOAT;
  631. m_Name = "min16float";
  632. break;
  633. case hlsl::DXIL::ComponentType::F32:
  634. case hlsl::DXIL::ComponentType::SNormF32:
  635. case hlsl::DXIL::ComponentType::UNormF32:
  636. componentType = D3D_SVT_FLOAT;
  637. m_Name = "float";
  638. break;
  639. case hlsl::DXIL::ComponentType::F64:
  640. case hlsl::DXIL::ComponentType::SNormF64:
  641. case hlsl::DXIL::ComponentType::UNormF64:
  642. componentType = D3D_SVT_DOUBLE;
  643. m_Name = "double";
  644. break;
  645. default:
  646. #ifdef DBG
  647. OutputDebugStringA("DxilContainerReflection.cpp: error: unknown component type\n");
  648. #endif
  649. break;
  650. }
  651. m_Desc.Type = componentType;
  652. // A matrix type is encoded as a vector type, plus annotations, so we
  653. // need to check for this case before other vector cases.
  654. if(typeAnnotation.HasMatrixAnnotation())
  655. {
  656. // We can extract the details from the annotation.
  657. DxilMatrixAnnotation const& matrixAnnotation = typeAnnotation.GetMatrixAnnotation();
  658. switch(matrixAnnotation.Orientation)
  659. {
  660. default:
  661. #ifdef DBG
  662. OutputDebugStringA("DxilContainerReflection.cpp: error: unknown matrix orientation\n");
  663. #endif
  664. // Note: column-major layout is the default
  665. case hlsl::MatrixOrientation::Undefined:
  666. case hlsl::MatrixOrientation::ColumnMajor:
  667. m_Desc.Class = D3D_SVC_MATRIX_COLUMNS;
  668. break;
  669. case hlsl::MatrixOrientation::RowMajor:
  670. m_Desc.Class = D3D_SVC_MATRIX_ROWS;
  671. break;
  672. }
  673. m_Desc.Rows = matrixAnnotation.Rows;
  674. m_Desc.Columns = matrixAnnotation.Cols;
  675. m_Name += std::to_string(matrixAnnotation.Rows) + "x" + std::to_string(matrixAnnotation.Cols);
  676. }
  677. else if( type->isVectorTy() )
  678. {
  679. // We assume that LLVM vectors either represent matrices (handled above)
  680. // or HLSL vectors.
  681. //
  682. // Note: the reflection interface encodes an N-vector as if it had 1 row
  683. // and N columns.
  684. m_Desc.Class = D3D_SVC_VECTOR;
  685. m_Desc.Rows = 1;
  686. m_Desc.Columns = type->getVectorNumElements();
  687. m_Name += std::to_string(type->getVectorNumElements());
  688. }
  689. else if( type->isStructTy() )
  690. {
  691. // A struct type might be an ordinary user-defined `struct`,
  692. // or one of the builtin in HLSL "object" types.
  693. StructType *structType = cast<StructType>(type);
  694. // We use our function to try to detect an object type
  695. // based on its name.
  696. if(TryToDetectObjectType(structType, &m_Desc.Type))
  697. {
  698. m_Desc.Class = D3D_SVC_OBJECT;
  699. }
  700. else
  701. {
  702. // Otherwise we have a struct and need to recurse on its fields.
  703. m_Desc.Class = D3D_SVC_STRUCT;
  704. m_Desc.Rows = 1;
  705. // Try to "clean" the type name for use in reflection data
  706. llvm::StringRef name = structType->getName();
  707. name = name.ltrim("dx.alignment.legacy.");
  708. name = name.ltrim("struct.");
  709. m_Name = name;
  710. unsigned int fieldCount = type->getStructNumElements();
  711. // Fields may have annotations, and we need to look at these
  712. // in order to decode their types properly.
  713. DxilTypeSystem &typeSys = M.GetTypeSystem();
  714. DxilStructAnnotation *structAnnotation = typeSys.GetStructAnnotation(structType);
  715. DXASSERT(structAnnotation, "else type system is missing annotations for user-defined struct");
  716. // The DXBC reflection info computes `Columns` for a
  717. // `struct` type from the fields (see below)
  718. UINT columnCounter = 0;
  719. for(unsigned int ff = 0; ff < fieldCount; ++ff)
  720. {
  721. DxilFieldAnnotation& fieldAnnotation = structAnnotation->GetFieldAnnotation(ff);
  722. llvm::Type* fieldType = structType->getStructElementType(ff);
  723. // Skip fields with object types, since applications may not expect to see them here.
  724. //
  725. // TODO: should skipping be context-dependent, since we might not be inside
  726. // a constant buffer?
  727. if( IsObjectType(fieldType) )
  728. {
  729. continue;
  730. }
  731. CShaderReflectionType *fieldReflectionType = new CShaderReflectionType();
  732. allTypes.push_back(std::unique_ptr<CShaderReflectionType>(fieldReflectionType));
  733. fieldReflectionType->Initialize(M, fieldType, fieldAnnotation, 0, allTypes);
  734. m_MemberTypes.push_back(fieldReflectionType);
  735. m_MemberNames.push_back(fieldAnnotation.GetFieldName().c_str());
  736. // Effectively, we want to add one to `Columns` for every scalar nested recursively
  737. // inside this `struct` type (ignoring objects, which we filtered above). We should
  738. // be able to compute this as the product of the `Columns`, `Rows` and `Elements`
  739. // of each field, with the caveat that some of these may be zero, but shoud be
  740. // treated as one.
  741. columnCounter +=
  742. (fieldReflectionType->m_Desc.Columns ? fieldReflectionType->m_Desc.Columns : 1)
  743. * (fieldReflectionType->m_Desc.Rows ? fieldReflectionType->m_Desc.Rows : 1)
  744. * (fieldReflectionType->m_Desc.Elements ? fieldReflectionType->m_Desc.Elements : 1);
  745. }
  746. m_Desc.Columns = columnCounter;
  747. // Because we might have skipped fields during enumeration,
  748. // the `Members` count in the description might not be the same
  749. // as the field count of the original LLVM type.
  750. m_Desc.Members = m_MemberTypes.size();
  751. }
  752. }
  753. else if( type->isPointerTy() )
  754. {
  755. #ifdef DBG
  756. OutputDebugStringA("DxilContainerReflection.cpp: error: cannot reflect pointer type\n");
  757. #endif
  758. }
  759. else if( type->isVoidTy() )
  760. {
  761. // Name for `void` wasn't handle in the component-type `switch` above
  762. m_Name = "void";
  763. m_Desc.Class = D3D_SVC_SCALAR;
  764. m_Desc.Rows = 1;
  765. m_Desc.Columns = 1;
  766. }
  767. else
  768. {
  769. // Assume we have a scalar at this point.
  770. m_Desc.Class = D3D_SVC_SCALAR;
  771. m_Desc.Rows = 1;
  772. m_Desc.Columns = 1;
  773. // Special-case naming
  774. switch(m_Desc.Type)
  775. {
  776. default:
  777. break;
  778. case D3D_SVT_UINT:
  779. // Scalar `uint` gets reflected as `dword`, while vectors/matrices use `uint`...
  780. m_Name = "dword";
  781. break;
  782. }
  783. }
  784. // TODO: are there other cases to be handled?
  785. m_Desc.Name = m_Name.c_str();
  786. return S_OK;
  787. }
  788. void CShaderReflectionConstantBuffer::Initialize(
  789. DxilModule &M,
  790. DxilCBuffer &CB,
  791. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes) {
  792. ZeroMemory(&m_Desc, sizeof(m_Desc));
  793. m_Desc.Name = CB.GetGlobalName().c_str();
  794. m_Desc.Size = CB.GetSize() / CB.GetRangeSize();
  795. m_Desc.Size = (m_Desc.Size + 0x0f) & ~(0x0f); // Round up to 16 bytes for reflection.
  796. m_Desc.Type = D3D_CT_CBUFFER;
  797. m_Desc.uFlags = 0;
  798. Type *Ty = CB.GetGlobalSymbol()->getType()->getPointerElementType();
  799. // For ConstantBuffer<> buf[2], the array size is in Resource binding count
  800. // part.
  801. if (Ty->isArrayTy())
  802. Ty = Ty->getArrayElementType();
  803. DxilTypeSystem &typeSys = M.GetTypeSystem();
  804. StructType *ST = cast<StructType>(Ty);
  805. DxilStructAnnotation *annotation =
  806. typeSys.GetStructAnnotation(cast<StructType>(ST));
  807. // Dxil from dxbc doesn't have annotation.
  808. if (!annotation)
  809. return;
  810. m_Desc.Variables = ST->getNumContainedTypes();
  811. unsigned lastIndex = ST->getNumContainedTypes() - 1;
  812. for (unsigned i = 0; i < ST->getNumContainedTypes(); ++i) {
  813. DxilFieldAnnotation &fieldAnnotation = annotation->GetFieldAnnotation(i);
  814. D3D12_SHADER_VARIABLE_DESC VarDesc;
  815. ZeroMemory(&VarDesc, sizeof(VarDesc));
  816. VarDesc.uFlags |= D3D_SVF_USED; // Will update in SetCBufferUsage.
  817. CShaderReflectionVariable Var;
  818. //Create reflection type.
  819. CShaderReflectionType *pVarType = new CShaderReflectionType();
  820. allTypes.push_back(std::unique_ptr<CShaderReflectionType>(pVarType));
  821. pVarType->Initialize(M, ST->getContainedType(i), fieldAnnotation, fieldAnnotation.GetCBufferOffset(), allTypes);
  822. BYTE *pDefaultValue = nullptr;
  823. VarDesc.Name = fieldAnnotation.GetFieldName().c_str();
  824. VarDesc.StartOffset = fieldAnnotation.GetCBufferOffset();
  825. if (i < lastIndex) {
  826. DxilFieldAnnotation &nextFieldAnnotation =
  827. annotation->GetFieldAnnotation(i + 1);
  828. VarDesc.Size = nextFieldAnnotation.GetCBufferOffset() - fieldAnnotation.GetCBufferOffset();
  829. }
  830. else {
  831. VarDesc.Size = CB.GetSize() - fieldAnnotation.GetCBufferOffset();
  832. }
  833. Var.Initialize(this, &VarDesc, pVarType, pDefaultValue);
  834. m_Variables.push_back(Var);
  835. }
  836. }
  837. static unsigned CalcTypeSize(Type *Ty) {
  838. // Assume aligned values.
  839. if (Ty->isIntegerTy() || Ty->isFloatTy()) {
  840. return Ty->getPrimitiveSizeInBits() / 8;
  841. }
  842. else if (Ty->isArrayTy()) {
  843. ArrayType *AT = dyn_cast<ArrayType>(Ty);
  844. return AT->getNumElements() * CalcTypeSize(AT->getArrayElementType());
  845. }
  846. else if (Ty->isStructTy()) {
  847. StructType *ST = dyn_cast<StructType>(Ty);
  848. unsigned i = 0, c = ST->getStructNumElements();
  849. unsigned result = 0;
  850. for (; i < c; ++i) {
  851. result += CalcTypeSize(ST->getStructElementType(i));
  852. // TODO: align!
  853. }
  854. return result;
  855. }
  856. else if (Ty->isVectorTy()) {
  857. VectorType *VT = dyn_cast<VectorType>(Ty);
  858. return VT->getVectorNumElements() * CalcTypeSize(VT->getVectorElementType());
  859. }
  860. else {
  861. DXASSERT_NOMSG(false);
  862. return 0;
  863. }
  864. }
  865. static unsigned CalcResTypeSize(DxilModule &M, DxilResource &R) {
  866. UNREFERENCED_PARAMETER(M);
  867. Type *Ty = R.GetGlobalSymbol()->getType()->getPointerElementType();
  868. return CalcTypeSize(Ty);
  869. }
  870. void CShaderReflectionConstantBuffer::InitializeStructuredBuffer(
  871. DxilModule &M,
  872. DxilResource &R,
  873. std::vector<std::unique_ptr<CShaderReflectionType>>& allTypes) {
  874. ZeroMemory(&m_Desc, sizeof(m_Desc));
  875. m_Desc.Name = R.GetGlobalName().c_str();
  876. //m_Desc.Size = R.GetSize();
  877. m_Desc.Type = D3D11_CT_RESOURCE_BIND_INFO;
  878. m_Desc.uFlags = 0;
  879. m_Desc.Variables = 1;
  880. D3D12_SHADER_VARIABLE_DESC VarDesc;
  881. ZeroMemory(&VarDesc, sizeof(VarDesc));
  882. VarDesc.Name = "$Element";
  883. VarDesc.Size = CalcResTypeSize(M, R); // aligned bytes
  884. VarDesc.StartTexture = UINT_MAX;
  885. VarDesc.StartSampler = UINT_MAX;
  886. VarDesc.uFlags |= D3D_SVF_USED; // TODO: not necessarily true
  887. CShaderReflectionVariable Var;
  888. CShaderReflectionType *pVarType = nullptr;
  889. // Create reflection type, if we have the necessary annotation info
  890. // Extract the `struct` that wraps element type of the buffer resource
  891. Constant *GV = R.GetGlobalSymbol();
  892. Type *Ty = GV->getType()->getPointerElementType();
  893. if(Ty->isArrayTy())
  894. Ty = Ty->getArrayElementType();
  895. StructType *ST = cast<StructType>(Ty);
  896. // Look up struct type annotation on the element type
  897. DxilTypeSystem &typeSys = M.GetTypeSystem();
  898. DxilStructAnnotation *annotation =
  899. typeSys.GetStructAnnotation(cast<StructType>(ST));
  900. // Dxil from dxbc doesn't have annotation.
  901. if(annotation)
  902. {
  903. // Actually create the reflection type.
  904. pVarType = new CShaderReflectionType();
  905. allTypes.push_back(std::unique_ptr<CShaderReflectionType>(pVarType));
  906. // The user-visible element type is the first field of the wrapepr `struct`
  907. Type *fieldType = ST->getElementType(0);
  908. DxilFieldAnnotation &fieldAnnotation = annotation->GetFieldAnnotation(0);
  909. pVarType->Initialize(M, fieldType, fieldAnnotation, fieldAnnotation.GetCBufferOffset(), allTypes);
  910. }
  911. BYTE *pDefaultValue = nullptr;
  912. Var.Initialize(this, &VarDesc, pVarType, pDefaultValue);
  913. m_Variables.push_back(Var);
  914. m_Desc.Size = VarDesc.Size;
  915. }
  916. HRESULT CShaderReflectionConstantBuffer::GetDesc(D3D12_SHADER_BUFFER_DESC *pDesc) {
  917. if (!pDesc)
  918. return E_POINTER;
  919. memcpy(pDesc, &m_Desc, sizeof(m_Desc));
  920. return S_OK;
  921. }
  922. ID3D12ShaderReflectionVariable *
  923. CShaderReflectionConstantBuffer::GetVariableByIndex(UINT Index) {
  924. if (Index >= m_Variables.size()) {
  925. return &g_InvalidSRVariable;
  926. }
  927. return &m_Variables[Index];
  928. }
  929. ID3D12ShaderReflectionVariable *
  930. CShaderReflectionConstantBuffer::GetVariableByName(LPCSTR Name) {
  931. UINT index;
  932. if (NULL == Name) {
  933. return &g_InvalidSRVariable;
  934. }
  935. for (index = 0; index < m_Variables.size(); ++index) {
  936. if (0 == strcmp(m_Variables[index].GetName(), Name)) {
  937. return &m_Variables[index];
  938. }
  939. }
  940. return &g_InvalidSRVariable;
  941. }
  942. ///////////////////////////////////////////////////////////////////////////////
  943. // DxilShaderReflection implementation. //
  944. static DxilResource *DxilResourceFromBase(DxilResourceBase *RB) {
  945. DxilResourceBase::Class C = RB->GetClass();
  946. if (C == DXIL::ResourceClass::UAV || C == DXIL::ResourceClass::SRV)
  947. return (DxilResource *)RB;
  948. return nullptr;
  949. }
  950. static D3D_SHADER_INPUT_TYPE ResourceToShaderInputType(DxilResourceBase *RB) {
  951. DxilResource *R = DxilResourceFromBase(RB);
  952. bool isUAV = RB->GetClass() == DxilResourceBase::Class::UAV;
  953. switch (RB->GetKind()) {
  954. case DxilResource::Kind::CBuffer:
  955. return D3D_SIT_CBUFFER;
  956. case DxilResource::Kind::Sampler:
  957. return D3D_SIT_SAMPLER;
  958. case DxilResource::Kind::RawBuffer:
  959. return isUAV ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS;
  960. case DxilResource::Kind::StructuredBuffer: {
  961. if (!isUAV) return D3D_SIT_STRUCTURED;
  962. // TODO: D3D_SIT_UAV_CONSUME_STRUCTURED, D3D_SIT_UAV_APPEND_STRUCTURED?
  963. if (R->HasCounter()) return D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER;
  964. return D3D_SIT_UAV_RWSTRUCTURED;
  965. }
  966. case DxilResource::Kind::TypedBuffer:
  967. return isUAV ? D3D_SIT_UAV_RWTYPED : D3D_SIT_STRUCTURED;
  968. case DxilResource::Kind::Texture1D:
  969. case DxilResource::Kind::Texture1DArray:
  970. case DxilResource::Kind::Texture2D:
  971. case DxilResource::Kind::Texture2DArray:
  972. case DxilResource::Kind::Texture2DMS:
  973. case DxilResource::Kind::Texture2DMSArray:
  974. case DxilResource::Kind::Texture3D:
  975. case DxilResource::Kind::TextureCube:
  976. case DxilResource::Kind::TextureCubeArray:
  977. return R->IsRW() ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE;
  978. default:
  979. return (D3D_SHADER_INPUT_TYPE)0;
  980. }
  981. }
  982. static D3D_RESOURCE_RETURN_TYPE ResourceToReturnType(DxilResourceBase *RB) {
  983. DxilResource *R = DxilResourceFromBase(RB);
  984. if (R != nullptr) {
  985. CompType CT = R->GetCompType();
  986. if (CT.GetKind() == CompType::Kind::F64) return D3D_RETURN_TYPE_DOUBLE;
  987. if (CT.IsUNorm()) return D3D_RETURN_TYPE_UNORM;
  988. if (CT.IsSNorm()) return D3D_RETURN_TYPE_SNORM;
  989. if (CT.IsSIntTy()) return D3D_RETURN_TYPE_SINT;
  990. if (CT.IsUIntTy()) return D3D_RETURN_TYPE_UINT;
  991. if (CT.IsFloatTy()) return D3D_RETURN_TYPE_FLOAT;
  992. // D3D_RETURN_TYPE_CONTINUED: Return type is a multiple-dword type, such as a
  993. // double or uint64, and the component is continued from the previous
  994. // component that was declared. The first component represents the lower bits.
  995. return D3D_RETURN_TYPE_MIXED;
  996. }
  997. return (D3D_RESOURCE_RETURN_TYPE)0;
  998. }
  999. static D3D_SRV_DIMENSION ResourceToDimension(DxilResourceBase *RB) {
  1000. switch (RB->GetKind()) {
  1001. case DxilResource::Kind::StructuredBuffer:
  1002. case DxilResource::Kind::TypedBuffer:
  1003. return D3D_SRV_DIMENSION_BUFFER;
  1004. case DxilResource::Kind::Texture1D:
  1005. return D3D_SRV_DIMENSION_TEXTURE1D;
  1006. case DxilResource::Kind::Texture1DArray:
  1007. return D3D_SRV_DIMENSION_TEXTURE1DARRAY;
  1008. case DxilResource::Kind::Texture2D:
  1009. return D3D_SRV_DIMENSION_TEXTURE2D;
  1010. case DxilResource::Kind::Texture2DArray:
  1011. return D3D_SRV_DIMENSION_TEXTURE2DARRAY;
  1012. case DxilResource::Kind::Texture2DMS:
  1013. return D3D_SRV_DIMENSION_TEXTURE2DMS;
  1014. case DxilResource::Kind::Texture2DMSArray:
  1015. return D3D_SRV_DIMENSION_TEXTURE2DMSARRAY;
  1016. case DxilResource::Kind::Texture3D:
  1017. return D3D_SRV_DIMENSION_TEXTURE3D;
  1018. case DxilResource::Kind::TextureCube:
  1019. return D3D_SRV_DIMENSION_TEXTURECUBE;
  1020. case DxilResource::Kind::TextureCubeArray:
  1021. return D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
  1022. case DxilResource::Kind::RawBuffer:
  1023. return D3D11_SRV_DIMENSION_BUFFER; // D3D11_SRV_DIMENSION_BUFFEREX?
  1024. default:
  1025. return D3D_SRV_DIMENSION_UNKNOWN;
  1026. }
  1027. }
  1028. static UINT ResourceToFlags(DxilResourceBase *RB) {
  1029. UINT result = 0;
  1030. DxilResource *R = DxilResourceFromBase(RB);
  1031. if (R != nullptr &&
  1032. (R->IsAnyTexture() || R->GetKind() == DXIL::ResourceKind::TypedBuffer)) {
  1033. llvm::Type *RetTy = R->GetRetType();
  1034. if (VectorType *VT = dyn_cast<VectorType>(RetTy)) {
  1035. unsigned vecSize = VT->getNumElements();
  1036. switch (vecSize) {
  1037. case 4:
  1038. result |= D3D_SIF_TEXTURE_COMPONENTS;
  1039. break;
  1040. case 3:
  1041. result |= D3D_SIF_TEXTURE_COMPONENT_1;
  1042. break;
  1043. case 2:
  1044. result |= D3D_SIF_TEXTURE_COMPONENT_0;
  1045. break;
  1046. }
  1047. }
  1048. }
  1049. // D3D_SIF_USERPACKED
  1050. if (RB->GetClass() == DXIL::ResourceClass::Sampler) {
  1051. DxilSampler *S = static_cast<DxilSampler *>(RB);
  1052. if (S->GetSamplerKind() == DXIL::SamplerKind::Comparison)
  1053. result |= D3D_SIF_COMPARISON_SAMPLER;
  1054. }
  1055. return result;
  1056. }
  1057. void DxilShaderReflection::CreateReflectionObjectForResource(DxilResourceBase *RB) {
  1058. DxilResourceBase::Class C = RB->GetClass();
  1059. DxilResource *R =
  1060. (C == DXIL::ResourceClass::UAV || C == DXIL::ResourceClass::SRV)
  1061. ? (DxilResource *)RB
  1062. : nullptr;
  1063. D3D12_SHADER_INPUT_BIND_DESC inputBind;
  1064. ZeroMemory(&inputBind, sizeof(inputBind));
  1065. inputBind.BindCount = RB->GetRangeSize();
  1066. if (RB->GetRangeSize() == UINT_MAX)
  1067. inputBind.BindCount = 0;
  1068. inputBind.BindPoint = RB->GetLowerBound();
  1069. inputBind.Dimension = ResourceToDimension(RB);
  1070. inputBind.Name = RB->GetGlobalName().c_str();
  1071. inputBind.Type = ResourceToShaderInputType(RB);
  1072. if (R == nullptr) {
  1073. inputBind.NumSamples = 0;
  1074. }
  1075. else {
  1076. inputBind.NumSamples = R->GetSampleCount();
  1077. if (inputBind.NumSamples == 0) {
  1078. if (R->IsStructuredBuffer()) {
  1079. inputBind.NumSamples = CalcResTypeSize(*m_pDxilModule, *R);
  1080. }
  1081. else if (!R->IsRawBuffer()) {
  1082. inputBind.NumSamples = 0xFFFFFFFF;
  1083. }
  1084. }
  1085. }
  1086. inputBind.ReturnType = ResourceToReturnType(RB);
  1087. inputBind.Space = RB->GetSpaceID();
  1088. inputBind.uFlags = ResourceToFlags(RB);
  1089. inputBind.uID = RB->GetID();
  1090. m_Resources.push_back(inputBind);
  1091. }
  1092. // Find the imm offset part from a value.
  1093. // It must exist unless offset is 0.
  1094. static unsigned GetCBOffset(Value *V) {
  1095. if (ConstantInt *Imm = dyn_cast<ConstantInt>(V))
  1096. return Imm->getLimitedValue();
  1097. else if (UnaryInstruction *UI = dyn_cast<UnaryInstruction>(V)) {
  1098. return 0;
  1099. } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V)) {
  1100. switch (BO->getOpcode()) {
  1101. case Instruction::Add: {
  1102. unsigned left = GetCBOffset(BO->getOperand(0));
  1103. unsigned right = GetCBOffset(BO->getOperand(1));
  1104. return left + right;
  1105. } break;
  1106. case Instruction::Or: {
  1107. unsigned left = GetCBOffset(BO->getOperand(0));
  1108. unsigned right = GetCBOffset(BO->getOperand(1));
  1109. return left | right;
  1110. } break;
  1111. default:
  1112. return 0;
  1113. }
  1114. } else {
  1115. return 0;
  1116. }
  1117. }
  1118. void CollectInPhiChain(PHINode *cbUser, std::vector<unsigned> &cbufUsage,
  1119. unsigned offset, std::unordered_set<Value *> &userSet) {
  1120. if (userSet.count(cbUser) > 0)
  1121. return;
  1122. userSet.insert(cbUser);
  1123. for (User *cbU : cbUser->users()) {
  1124. if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
  1125. for (unsigned idx : EV->getIndices()) {
  1126. cbufUsage.emplace_back(offset + idx * 4);
  1127. }
  1128. } else {
  1129. PHINode *phi = cast<PHINode>(cbU);
  1130. CollectInPhiChain(phi, cbufUsage, offset, userSet);
  1131. }
  1132. }
  1133. }
  1134. static void CollectCBufUsage(Value *cbHandle,
  1135. std::vector<unsigned> &cbufUsage) {
  1136. for (User *U : cbHandle->users()) {
  1137. CallInst *CI = cast<CallInst>(U);
  1138. ConstantInt *opcodeV =
  1139. cast<ConstantInt>(CI->getArgOperand(DXIL::OperandIndex::kOpcodeIdx));
  1140. DXIL::OpCode opcode = static_cast<DXIL::OpCode>(opcodeV->getLimitedValue());
  1141. if (opcode == DXIL::OpCode::CBufferLoadLegacy) {
  1142. DxilInst_CBufferLoadLegacy cbload(CI);
  1143. Value *resIndex = cbload.get_regIndex();
  1144. unsigned offset = GetCBOffset(resIndex);
  1145. // 16 bytes align.
  1146. offset <<= 4;
  1147. for (User *cbU : U->users()) {
  1148. if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(cbU)) {
  1149. for (unsigned idx : EV->getIndices()) {
  1150. cbufUsage.emplace_back(offset + idx * 4);
  1151. }
  1152. } else {
  1153. PHINode *phi = cast<PHINode>(cbU);
  1154. std::unordered_set<Value *> userSet;
  1155. CollectInPhiChain(phi, cbufUsage, offset, userSet);
  1156. }
  1157. }
  1158. } else if (opcode == DXIL::OpCode::CBufferLoad) {
  1159. DxilInst_CBufferLoad cbload(CI);
  1160. Value *byteOffset = cbload.get_byteOffset();
  1161. unsigned offset = GetCBOffset(byteOffset);
  1162. cbufUsage.emplace_back(offset);
  1163. } else {
  1164. //
  1165. DXASSERT(0, "invalid opcode");
  1166. }
  1167. }
  1168. }
  1169. static void SetCBufVarUsage(CShaderReflectionConstantBuffer &cb,
  1170. std::vector<unsigned> usage) {
  1171. D3D12_SHADER_BUFFER_DESC Desc;
  1172. if (FAILED(cb.GetDesc(&Desc)))
  1173. return;
  1174. unsigned size = Desc.Variables;
  1175. std::sort(usage.begin(), usage.end());
  1176. for (unsigned i = 0; i < size; i++) {
  1177. ID3D12ShaderReflectionVariable *pVar = cb.GetVariableByIndex(i);
  1178. D3D12_SHADER_VARIABLE_DESC VarDesc;
  1179. if (FAILED(pVar->GetDesc(&VarDesc)))
  1180. continue;
  1181. if (!pVar)
  1182. continue;
  1183. unsigned begin = VarDesc.StartOffset;
  1184. unsigned end = begin + VarDesc.Size;
  1185. auto beginIt = std::find_if(usage.begin(), usage.end(),
  1186. [&](unsigned v) { return v >= begin; });
  1187. auto endIt = std::find_if(usage.begin(), usage.end(),
  1188. [&](unsigned v) { return v >= end; });
  1189. bool used = beginIt != endIt;
  1190. // Clear used.
  1191. if (!used) {
  1192. CShaderReflectionType *pVarType = (CShaderReflectionType *)pVar->GetType();
  1193. BYTE *pDefaultValue = nullptr;
  1194. VarDesc.uFlags &= ~D3D_SVF_USED;
  1195. CShaderReflectionVariable *pCVarDesc = (CShaderReflectionVariable*)pVar;
  1196. pCVarDesc->Initialize(&cb, &VarDesc, pVarType, pDefaultValue);
  1197. }
  1198. }
  1199. }
  1200. void DxilShaderReflection::SetCBufferUsage() {
  1201. hlsl::OP *hlslOP = m_pDxilModule->GetOP();
  1202. LLVMContext &Ctx = m_pDxilModule->GetCtx();
  1203. unsigned cbSize = m_CBs.size();
  1204. std::vector< std::vector<unsigned> > cbufUsage(cbSize);
  1205. Function *createHandle = hlslOP->GetOpFunc(DXIL::OpCode::CreateHandle, Type::getVoidTy(Ctx));
  1206. if (createHandle->user_empty()) {
  1207. createHandle->eraseFromParent();
  1208. return;
  1209. }
  1210. // Find all cb handles.
  1211. for (User *U : createHandle->users()) {
  1212. DxilInst_CreateHandle handle(cast<CallInst>(U));
  1213. Value *resClass = handle.get_resourceClass();
  1214. ConstantInt *immResClass = cast<ConstantInt>(resClass);
  1215. if (immResClass->getLimitedValue() == (unsigned)DXIL::ResourceClass::CBuffer) {
  1216. ConstantInt *cbID = cast<ConstantInt>(handle.get_rangeId());
  1217. CollectCBufUsage(U, cbufUsage[cbID->getLimitedValue()]);
  1218. }
  1219. }
  1220. for (unsigned i=0;i<cbSize;i++) {
  1221. SetCBufVarUsage(m_CBs[i], cbufUsage[i]);
  1222. }
  1223. }
  1224. void DxilShaderReflection::CreateReflectionObjects() {
  1225. DXASSERT_NOMSG(m_pDxilModule != nullptr);
  1226. // Create constant buffers, resources and signatures.
  1227. for (auto && cb : m_pDxilModule->GetCBuffers()) {
  1228. CShaderReflectionConstantBuffer rcb;
  1229. rcb.Initialize(*m_pDxilModule, *(cb.get()), m_Types);
  1230. m_CBs.push_back(std::move(rcb));
  1231. }
  1232. // Set cbuf usage.
  1233. SetCBufferUsage();
  1234. // TODO: add tbuffers into m_CBs
  1235. for (auto && uav : m_pDxilModule->GetUAVs()) {
  1236. if (uav->GetKind() != DxilResource::Kind::StructuredBuffer) {
  1237. continue;
  1238. }
  1239. CShaderReflectionConstantBuffer rcb;
  1240. rcb.InitializeStructuredBuffer(*m_pDxilModule, *(uav.get()), m_Types);
  1241. m_CBs.push_back(std::move(rcb));
  1242. }
  1243. for (auto && srv : m_pDxilModule->GetSRVs()) {
  1244. if (srv->GetKind() != DxilResource::Kind::StructuredBuffer) {
  1245. continue;
  1246. }
  1247. CShaderReflectionConstantBuffer rcb;
  1248. rcb.InitializeStructuredBuffer(*m_pDxilModule, *(srv.get()), m_Types);
  1249. m_CBs.push_back(std::move(rcb));
  1250. }
  1251. // Populate all resources.
  1252. for (auto && cbRes : m_pDxilModule->GetCBuffers()) {
  1253. CreateReflectionObjectForResource(cbRes.get());
  1254. }
  1255. for (auto && samplerRes : m_pDxilModule->GetSamplers()) {
  1256. CreateReflectionObjectForResource(samplerRes.get());
  1257. }
  1258. for (auto && srvRes : m_pDxilModule->GetSRVs()) {
  1259. CreateReflectionObjectForResource(srvRes.get());
  1260. }
  1261. for (auto && uavRes : m_pDxilModule->GetUAVs()) {
  1262. CreateReflectionObjectForResource(uavRes.get());
  1263. }
  1264. // Populate input/output/patch constant signatures.
  1265. CreateReflectionObjectsForSignature(m_pDxilModule->GetInputSignature(), m_InputSignature);
  1266. CreateReflectionObjectsForSignature(m_pDxilModule->GetOutputSignature(), m_OutputSignature);
  1267. CreateReflectionObjectsForSignature(m_pDxilModule->GetPatchConstantSignature(), m_PatchConstantSignature);
  1268. MarkUsedSignatureElements();
  1269. }
  1270. static D3D_REGISTER_COMPONENT_TYPE CompTypeToRegisterComponentType(CompType CT) {
  1271. switch (CT.GetKind()) {
  1272. case DXIL::ComponentType::F16:
  1273. case DXIL::ComponentType::F32:
  1274. return D3D_REGISTER_COMPONENT_FLOAT32;
  1275. case DXIL::ComponentType::I1:
  1276. case DXIL::ComponentType::U16:
  1277. case DXIL::ComponentType::U32:
  1278. return D3D_REGISTER_COMPONENT_UINT32;
  1279. case DXIL::ComponentType::I16:
  1280. case DXIL::ComponentType::I32:
  1281. return D3D_REGISTER_COMPONENT_SINT32;
  1282. default:
  1283. return D3D_REGISTER_COMPONENT_UNKNOWN;
  1284. }
  1285. }
  1286. static D3D_MIN_PRECISION CompTypeToMinPrecision(CompType CT) {
  1287. switch (CT.GetKind()) {
  1288. case DXIL::ComponentType::F16:
  1289. return D3D_MIN_PRECISION_FLOAT_16;
  1290. case DXIL::ComponentType::I16:
  1291. return D3D_MIN_PRECISION_SINT_16;
  1292. case DXIL::ComponentType::U16:
  1293. return D3D_MIN_PRECISION_UINT_16;
  1294. default:
  1295. return D3D_MIN_PRECISION_DEFAULT;
  1296. }
  1297. }
  1298. D3D_NAME SemanticToSystemValueType(const Semantic *S, DXIL::TessellatorDomain domain) {
  1299. switch (S->GetKind()) {
  1300. case Semantic::Kind::ClipDistance:
  1301. return D3D_NAME_CLIP_DISTANCE;
  1302. case Semantic::Kind::Arbitrary:
  1303. return D3D_NAME_UNDEFINED;
  1304. case Semantic::Kind::VertexID:
  1305. return D3D_NAME_VERTEX_ID;
  1306. case Semantic::Kind::InstanceID:
  1307. return D3D_NAME_INSTANCE_ID;
  1308. case Semantic::Kind::Position:
  1309. return D3D_NAME_POSITION;
  1310. case Semantic::Kind::Coverage:
  1311. return D3D_NAME_COVERAGE;
  1312. case Semantic::Kind::InnerCoverage:
  1313. return D3D_NAME_INNER_COVERAGE;
  1314. case Semantic::Kind::PrimitiveID:
  1315. return D3D_NAME_PRIMITIVE_ID;
  1316. case Semantic::Kind::SampleIndex:
  1317. return D3D_NAME_SAMPLE_INDEX;
  1318. case Semantic::Kind::IsFrontFace:
  1319. return D3D_NAME_IS_FRONT_FACE;
  1320. case Semantic::Kind::RenderTargetArrayIndex:
  1321. return D3D_NAME_RENDER_TARGET_ARRAY_INDEX;
  1322. case Semantic::Kind::ViewPortArrayIndex:
  1323. return D3D_NAME_VIEWPORT_ARRAY_INDEX;
  1324. case Semantic::Kind::CullDistance:
  1325. return D3D_NAME_CULL_DISTANCE;
  1326. case Semantic::Kind::Target:
  1327. return D3D_NAME_TARGET;
  1328. case Semantic::Kind::Depth:
  1329. return D3D_NAME_DEPTH;
  1330. case Semantic::Kind::DepthLessEqual:
  1331. return D3D_NAME_DEPTH_LESS_EQUAL;
  1332. case Semantic::Kind::DepthGreaterEqual:
  1333. return D3D_NAME_DEPTH_GREATER_EQUAL;
  1334. case Semantic::Kind::StencilRef:
  1335. return D3D_NAME_STENCIL_REF;
  1336. case Semantic::Kind::TessFactor: {
  1337. switch (domain) {
  1338. case DXIL::TessellatorDomain::IsoLine:
  1339. return D3D_NAME_FINAL_LINE_DETAIL_TESSFACTOR;
  1340. case DXIL::TessellatorDomain::Tri:
  1341. return D3D_NAME_FINAL_TRI_EDGE_TESSFACTOR;
  1342. case DXIL::TessellatorDomain::Quad:
  1343. return D3D_NAME_FINAL_QUAD_EDGE_TESSFACTOR;
  1344. default:
  1345. return D3D_NAME_UNDEFINED;
  1346. }
  1347. }
  1348. case Semantic::Kind::InsideTessFactor:
  1349. switch (domain) {
  1350. case DXIL::TessellatorDomain::Tri:
  1351. return D3D_NAME_FINAL_TRI_INSIDE_TESSFACTOR;
  1352. case DXIL::TessellatorDomain::Quad:
  1353. return D3D_NAME_FINAL_QUAD_INSIDE_TESSFACTOR;
  1354. default:
  1355. return D3D_NAME_UNDEFINED;
  1356. }
  1357. case Semantic::Kind::DispatchThreadID:
  1358. case Semantic::Kind::GroupID:
  1359. case Semantic::Kind::GroupIndex:
  1360. case Semantic::Kind::GroupThreadID:
  1361. case Semantic::Kind::DomainLocation:
  1362. case Semantic::Kind::OutputControlPointID:
  1363. case Semantic::Kind::GSInstanceID:
  1364. case Semantic::Kind::Invalid:
  1365. default:
  1366. return D3D_NAME_UNDEFINED;
  1367. }
  1368. }
  1369. static uint8_t NegMask(uint8_t V) {
  1370. V ^= 0xF;
  1371. return V & 0xF;
  1372. }
  1373. void DxilShaderReflection::CreateReflectionObjectsForSignature(
  1374. const DxilSignature &Sig,
  1375. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> &Descs) {
  1376. bool clipDistanceSeen = false;
  1377. for (auto && SigElem : Sig.GetElements()) {
  1378. D3D12_SIGNATURE_PARAMETER_DESC Desc;
  1379. // TODO: why do we have multiple SV_ClipDistance elements?
  1380. if (SigElem->GetSemantic()->GetKind() == DXIL::SemanticKind::ClipDistance) {
  1381. if (clipDistanceSeen) continue;
  1382. clipDistanceSeen = true;
  1383. }
  1384. Desc.ComponentType = CompTypeToRegisterComponentType(SigElem->GetCompType());
  1385. Desc.Mask = SigElem->GetColsAsMask();
  1386. // D3D11_43 does not have MinPrecison.
  1387. if (m_PublicAPI != PublicAPI::D3D11_43)
  1388. Desc.MinPrecision = CompTypeToMinPrecision(SigElem->GetCompType());
  1389. Desc.ReadWriteMask = Sig.IsInput() ? 0 : Desc.Mask; // Start with output-never-written/input-never-read.
  1390. Desc.Register = SigElem->GetStartRow();
  1391. Desc.Stream = SigElem->GetOutputStream();
  1392. Desc.SystemValueType = SemanticToSystemValueType(SigElem->GetSemantic(), m_pDxilModule->GetTessellatorDomain());
  1393. Desc.SemanticName = SigElem->GetName();
  1394. if (!SigElem->GetSemantic()->IsArbitrary())
  1395. Desc.SemanticName = CreateUpperCase(Desc.SemanticName);
  1396. const std::vector<unsigned> &indexVec = SigElem->GetSemanticIndexVec();
  1397. for (unsigned semIdx = 0; semIdx < indexVec.size(); ++semIdx) {
  1398. Desc.SemanticIndex = indexVec[semIdx];
  1399. if (Desc.SystemValueType == D3D_NAME_FINAL_LINE_DETAIL_TESSFACTOR &&
  1400. Desc.SemanticIndex == 1)
  1401. Desc.SystemValueType = D3D_NAME_FINAL_LINE_DETAIL_TESSFACTOR;
  1402. Descs.push_back(Desc);
  1403. }
  1404. }
  1405. }
  1406. LPCSTR DxilShaderReflection::CreateUpperCase(LPCSTR pValue) {
  1407. // Restricted only to [a-z] ASCII.
  1408. LPCSTR pCursor = pValue;
  1409. while (*pCursor != '\0') {
  1410. if ('a' <= *pCursor && *pCursor <= 'z') {
  1411. break;
  1412. }
  1413. ++pCursor;
  1414. }
  1415. if (*pCursor == '\0')
  1416. return pValue;
  1417. std::unique_ptr<char[]> pUpperStr = std::make_unique<char[]>(strlen(pValue) + 1);
  1418. char *pWrite = pUpperStr.get();
  1419. pCursor = pValue;
  1420. for (;;) {
  1421. *pWrite = *pCursor;
  1422. if ('a' <= *pWrite && *pWrite <= 'z') {
  1423. *pWrite += ('A' - 'a');
  1424. }
  1425. if (*pWrite == '\0') break;
  1426. ++pWrite;
  1427. ++pCursor;
  1428. }
  1429. m_UpperCaseNames.push_back(std::move(pUpperStr));
  1430. return m_UpperCaseNames.back().get();
  1431. }
  1432. HRESULT DxilShaderReflection::Load(IDxcBlob *pBlob,
  1433. const DxilPartHeader *pPart) {
  1434. DXASSERT_NOMSG(pBlob != nullptr);
  1435. DXASSERT_NOMSG(pPart != nullptr);
  1436. m_pContainer = pBlob;
  1437. const char *pData = GetDxilPartData(pPart);
  1438. try {
  1439. const char *pBitcode;
  1440. uint32_t bitcodeLength;
  1441. GetDxilProgramBitcode((DxilProgramHeader *)pData, &pBitcode, &bitcodeLength);
  1442. std::unique_ptr<MemoryBuffer> pMemBuffer =
  1443. MemoryBuffer::getMemBufferCopy(StringRef(pBitcode, bitcodeLength));
  1444. #if 0 // We materialize eagerly, because we'll need to walk instructions to look for usage information.
  1445. ErrorOr<std::unique_ptr<Module>> module =
  1446. getLazyBitcodeModule(std::move(pMemBuffer), Context);
  1447. #else
  1448. ErrorOr<std::unique_ptr<Module>> module =
  1449. parseBitcodeFile(pMemBuffer->getMemBufferRef(), Context, nullptr);
  1450. #endif
  1451. if (!module) {
  1452. return E_INVALIDARG;
  1453. }
  1454. std::swap(m_pModule, module.get());
  1455. m_pDxilModule = &m_pModule->GetOrCreateDxilModule();
  1456. CreateReflectionObjects();
  1457. return S_OK;
  1458. }
  1459. CATCH_CPP_RETURN_HRESULT();
  1460. };
  1461. _Use_decl_annotations_
  1462. HRESULT DxilShaderReflection::GetDesc(D3D12_SHADER_DESC *pDesc) {
  1463. IFR(ZeroMemoryToOut(pDesc));
  1464. const DxilModule &M = *m_pDxilModule;
  1465. const ShaderModel *pSM = M.GetShaderModel();
  1466. pDesc->Version = EncodeVersion(pSM->GetKind(), pSM->GetMajor(), pSM->GetMinor());
  1467. // Unset: LPCSTR Creator; // Creator string
  1468. // Unset: UINT Flags; // Shader compilation/parse flags
  1469. pDesc->ConstantBuffers = m_CBs.size();
  1470. pDesc->BoundResources = m_Resources.size();
  1471. pDesc->InputParameters = m_InputSignature.size();
  1472. pDesc->OutputParameters = m_OutputSignature.size();
  1473. pDesc->PatchConstantParameters = m_PatchConstantSignature.size();
  1474. // Unset: UINT InstructionCount; // Number of emitted instructions
  1475. // Unset: UINT TempRegisterCount; // Number of temporary registers used
  1476. // Unset: UINT TempArrayCount; // Number of temporary arrays used
  1477. // Unset: UINT DefCount; // Number of constant defines
  1478. // Unset: UINT DclCount; // Number of declarations (input + output)
  1479. // Unset: UINT TextureNormalInstructions; // Number of non-categorized texture instructions
  1480. // Unset: UINT TextureLoadInstructions; // Number of texture load instructions
  1481. // Unset: UINT TextureCompInstructions; // Number of texture comparison instructions
  1482. // Unset: UINT TextureBiasInstructions; // Number of texture bias instructions
  1483. // Unset: UINT TextureGradientInstructions; // Number of texture gradient instructions
  1484. // Unset: UINT FloatInstructionCount; // Number of floating point arithmetic instructions used
  1485. // Unset: UINT IntInstructionCount; // Number of signed integer arithmetic instructions used
  1486. // Unset: UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used
  1487. // Unset: UINT StaticFlowControlCount; // Number of static flow control instructions used
  1488. // Unset: UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used
  1489. // Unset: UINT MacroInstructionCount; // Number of macro instructions used
  1490. // Unset: UINT ArrayInstructionCount; // Number of array instructions used
  1491. // Unset: UINT CutInstructionCount; // Number of cut instructions used
  1492. // Unset: UINT EmitInstructionCount; // Number of emit instructions used
  1493. // Unset: D3D_PRIMITIVE_TOPOLOGY GSOutputTopology; // Geometry shader output topology
  1494. // Unset: UINT GSMaxOutputVertexCount; // Geometry shader maximum output vertex count
  1495. // Unset: D3D_PRIMITIVE InputPrimitive; // GS/HS input primitive
  1496. // Unset: UINT cGSInstanceCount; // Number of Geometry shader instances
  1497. // Unset: UINT cControlPoints; // Number of control points in the HS->DS stage
  1498. // Unset: D3D_TESSELLATOR_OUTPUT_PRIMITIVE HSOutputPrimitive; // Primitive output by the tessellator
  1499. // Unset: D3D_TESSELLATOR_PARTITIONING HSPartitioning; // Partitioning mode of the tessellator
  1500. // Unset: D3D_TESSELLATOR_DOMAIN TessellatorDomain; // Domain of the tessellator (quad, tri, isoline)
  1501. // instruction counts
  1502. // Unset: UINT cBarrierInstructions; // Number of barrier instructions in a compute shader
  1503. // Unset: UINT cInterlockedInstructions; // Number of interlocked instructions
  1504. // Unset: UINT cTextureStoreInstructions; // Number of texture writes
  1505. return S_OK;
  1506. }
  1507. static bool GetUnsignedVal(Value *V, uint32_t *pValue) {
  1508. ConstantInt *CI = dyn_cast<ConstantInt>(V);
  1509. if (!CI) return false;
  1510. uint64_t u = CI->getZExtValue();
  1511. if (u > UINT32_MAX) return false;
  1512. *pValue = (uint32_t)u;
  1513. return true;
  1514. }
  1515. void DxilShaderReflection::MarkUsedSignatureElements() {
  1516. Function *F = m_pDxilModule->GetEntryFunction();
  1517. DXASSERT(F != nullptr, "else module load should have failed");
  1518. // For every loadInput/storeOutput, update the corresponding ReadWriteMask.
  1519. // F is a pointer to a Function instance
  1520. unsigned elementCount = m_InputSignature.size() + m_OutputSignature.size() +
  1521. m_PatchConstantSignature.size();
  1522. unsigned markedElementCount = 0;
  1523. for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
  1524. DxilInst_LoadInput LI(&*I);
  1525. DxilInst_StoreOutput SO(&*I);
  1526. DxilInst_LoadPatchConstant LPC(&*I);
  1527. DxilInst_StorePatchConstant SPC(&*I);
  1528. std::vector<D3D12_SIGNATURE_PARAMETER_DESC> *pDescs;
  1529. const DxilSignature *pSig;
  1530. uint32_t col, row, sigId;
  1531. if (LI) {
  1532. if (!GetUnsignedVal(LI.get_inputSigId(), &sigId)) continue;
  1533. if (!GetUnsignedVal(LI.get_colIndex(), &col)) continue;
  1534. if (!GetUnsignedVal(LI.get_rowIndex(), &row)) continue;
  1535. pDescs = &m_InputSignature;
  1536. pSig = &m_pDxilModule->GetInputSignature();
  1537. }
  1538. else if (SO) {
  1539. if (!GetUnsignedVal(SO.get_outputtSigId(), &sigId)) continue;
  1540. if (!GetUnsignedVal(SO.get_colIndex(), &col)) continue;
  1541. if (!GetUnsignedVal(SO.get_rowIndex(), &row)) continue;
  1542. pDescs = &m_OutputSignature;
  1543. pSig = &m_pDxilModule->GetOutputSignature();
  1544. }
  1545. else if (SPC) {
  1546. if (!GetUnsignedVal(SPC.get_outputSigID(), &sigId)) continue;
  1547. if (!GetUnsignedVal(SPC.get_col(), &col)) continue;
  1548. if (!GetUnsignedVal(SPC.get_row(), &row)) continue;
  1549. pDescs = &m_PatchConstantSignature;
  1550. pSig = &m_pDxilModule->GetPatchConstantSignature();
  1551. }
  1552. else if (LPC) {
  1553. if (!GetUnsignedVal(LPC.get_inputSigId(), &sigId)) continue;
  1554. if (!GetUnsignedVal(LPC.get_col(), &col)) continue;
  1555. if (!GetUnsignedVal(LPC.get_row(), &row)) continue;
  1556. pDescs = &m_PatchConstantSignature;
  1557. pSig = &m_pDxilModule->GetPatchConstantSignature();
  1558. }
  1559. else {
  1560. continue;
  1561. }
  1562. if (sigId >= pDescs->size()) continue;
  1563. D3D12_SIGNATURE_PARAMETER_DESC *pDesc = &(*pDescs)[sigId];
  1564. // Consider being more fine-grained about masks.
  1565. // We report sometimes-read on input as always-read.
  1566. unsigned UsedMask = pSig->IsInput() ? pDesc->Mask : NegMask(pDesc->Mask);
  1567. if (pDesc->ReadWriteMask == UsedMask)
  1568. continue;
  1569. pDesc->ReadWriteMask = UsedMask;
  1570. ++markedElementCount;
  1571. if (markedElementCount == elementCount)
  1572. return;
  1573. }
  1574. }
  1575. _Use_decl_annotations_
  1576. ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByIndex(UINT Index) {
  1577. if (Index >= m_CBs.size()) {
  1578. return &g_InvalidSRConstantBuffer;
  1579. }
  1580. return &m_CBs[Index];
  1581. }
  1582. _Use_decl_annotations_
  1583. ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByName(LPCSTR Name) {
  1584. if (!Name) {
  1585. return &g_InvalidSRConstantBuffer;
  1586. }
  1587. for (UINT index = 0; index < m_CBs.size(); ++index) {
  1588. if (0 == strcmp(m_CBs[index].GetName(), Name)) {
  1589. return &m_CBs[index];
  1590. }
  1591. }
  1592. return &g_InvalidSRConstantBuffer;
  1593. }
  1594. _Use_decl_annotations_
  1595. HRESULT DxilShaderReflection::GetResourceBindingDesc(UINT ResourceIndex,
  1596. _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) {
  1597. IFRBOOL(pDesc != nullptr, E_INVALIDARG);
  1598. IFRBOOL(ResourceIndex < m_Resources.size(), E_INVALIDARG);
  1599. if (m_PublicAPI != PublicAPI::D3D12) {
  1600. memcpy(pDesc, &m_Resources[ResourceIndex], sizeof(D3D11_SHADER_INPUT_BIND_DESC));
  1601. }
  1602. else {
  1603. *pDesc = m_Resources[ResourceIndex];
  1604. }
  1605. return S_OK;
  1606. }
  1607. _Use_decl_annotations_
  1608. HRESULT DxilShaderReflection::GetInputParameterDesc(UINT ParameterIndex,
  1609. _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) {
  1610. IFRBOOL(pDesc != nullptr, E_INVALIDARG);
  1611. IFRBOOL(ParameterIndex < m_InputSignature.size(), E_INVALIDARG);
  1612. if (m_PublicAPI != PublicAPI::D3D11_43)
  1613. *pDesc = m_InputSignature[ParameterIndex];
  1614. else
  1615. memcpy(pDesc, &m_InputSignature[ParameterIndex],
  1616. // D3D11_43 does not have MinPrecison.
  1617. sizeof(D3D12_SIGNATURE_PARAMETER_DESC) - sizeof(D3D_MIN_PRECISION));
  1618. return S_OK;
  1619. }
  1620. _Use_decl_annotations_
  1621. HRESULT DxilShaderReflection::GetOutputParameterDesc(UINT ParameterIndex,
  1622. D3D12_SIGNATURE_PARAMETER_DESC *pDesc) {
  1623. IFRBOOL(pDesc != nullptr, E_INVALIDARG);
  1624. IFRBOOL(ParameterIndex < m_OutputSignature.size(), E_INVALIDARG);
  1625. if (m_PublicAPI != PublicAPI::D3D11_43)
  1626. *pDesc = m_OutputSignature[ParameterIndex];
  1627. else
  1628. memcpy(pDesc, &m_OutputSignature[ParameterIndex],
  1629. // D3D11_43 does not have MinPrecison.
  1630. sizeof(D3D12_SIGNATURE_PARAMETER_DESC) - sizeof(D3D_MIN_PRECISION));
  1631. return S_OK;
  1632. }
  1633. _Use_decl_annotations_
  1634. HRESULT DxilShaderReflection::GetPatchConstantParameterDesc(UINT ParameterIndex,
  1635. D3D12_SIGNATURE_PARAMETER_DESC *pDesc) {
  1636. IFRBOOL(pDesc != nullptr, E_INVALIDARG);
  1637. IFRBOOL(ParameterIndex < m_PatchConstantSignature.size(), E_INVALIDARG);
  1638. if (m_PublicAPI != PublicAPI::D3D11_43)
  1639. *pDesc = m_PatchConstantSignature[ParameterIndex];
  1640. else
  1641. memcpy(pDesc, &m_PatchConstantSignature[ParameterIndex],
  1642. // D3D11_43 does not have MinPrecison.
  1643. sizeof(D3D12_SIGNATURE_PARAMETER_DESC) - sizeof(D3D_MIN_PRECISION));
  1644. return S_OK;
  1645. }
  1646. _Use_decl_annotations_
  1647. ID3D12ShaderReflectionVariable* DxilShaderReflection::GetVariableByName(LPCSTR Name) {
  1648. if (Name != nullptr) {
  1649. // Iterate through all cbuffers to find the variable.
  1650. for (UINT i = 0; i < m_CBs.size(); i++) {
  1651. ID3D12ShaderReflectionVariable *pVar = m_CBs[i].GetVariableByName(Name);
  1652. if (pVar != &g_InvalidSRVariable) {
  1653. return pVar;
  1654. }
  1655. }
  1656. }
  1657. return &g_InvalidSRVariable;
  1658. }
  1659. _Use_decl_annotations_
  1660. HRESULT DxilShaderReflection::GetResourceBindingDescByName(LPCSTR Name,
  1661. D3D12_SHADER_INPUT_BIND_DESC *pDesc) {
  1662. IFRBOOL(Name != nullptr, E_INVALIDARG);
  1663. IFR(ZeroMemoryToOut(pDesc));
  1664. for (UINT i = 0; i < m_Resources.size(); i++) {
  1665. if (strcmp(m_Resources[i].Name, Name) == 0) {
  1666. if (m_PublicAPI != PublicAPI::D3D12) {
  1667. memcpy(pDesc, &m_Resources[i], sizeof(D3D11_SHADER_INPUT_BIND_DESC));
  1668. }
  1669. else {
  1670. *pDesc = m_Resources[i];
  1671. }
  1672. return S_OK;
  1673. }
  1674. }
  1675. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  1676. }
  1677. UINT DxilShaderReflection::GetMovInstructionCount() { return 0; }
  1678. UINT DxilShaderReflection::GetMovcInstructionCount() { return 0; }
  1679. UINT DxilShaderReflection::GetConversionInstructionCount() { return 0; }
  1680. UINT DxilShaderReflection::GetBitwiseInstructionCount() { return 0; }
  1681. D3D_PRIMITIVE DxilShaderReflection::GetGSInputPrimitive() {
  1682. return (D3D_PRIMITIVE)m_pDxilModule->GetInputPrimitive();
  1683. }
  1684. BOOL DxilShaderReflection::IsSampleFrequencyShader() {
  1685. // TODO: determine correct value
  1686. return FALSE;
  1687. }
  1688. UINT DxilShaderReflection::GetNumInterfaceSlots() { return 0; }
  1689. _Use_decl_annotations_
  1690. HRESULT DxilShaderReflection::GetMinFeatureLevel(enum D3D_FEATURE_LEVEL* pLevel) {
  1691. IFR(AssignToOut(D3D_FEATURE_LEVEL_12_0, pLevel));
  1692. return S_OK;
  1693. }
  1694. _Use_decl_annotations_
  1695. UINT DxilShaderReflection::GetThreadGroupSize(UINT *pSizeX, UINT *pSizeY, UINT *pSizeZ) {
  1696. UINT *pNumThreads = m_pDxilModule->m_NumThreads;
  1697. AssignToOutOpt(pNumThreads[0], pSizeX);
  1698. AssignToOutOpt(pNumThreads[1], pSizeY);
  1699. AssignToOutOpt(pNumThreads[2], pSizeZ);
  1700. return pNumThreads[0] * pNumThreads[1] * pNumThreads[2];
  1701. }
  1702. UINT64 DxilShaderReflection::GetRequiresFlags() {
  1703. UINT64 result = 0;
  1704. uint64_t features = m_pDxilModule->m_ShaderFlags.GetFeatureInfo();
  1705. if (features & ShaderFeatureInfo_Doubles) result |= D3D_SHADER_REQUIRES_DOUBLES;
  1706. if (features & ShaderFeatureInfo_UAVsAtEveryStage) result |= D3D_SHADER_REQUIRES_UAVS_AT_EVERY_STAGE;
  1707. if (features & ShaderFeatureInfo_64UAVs) result |= D3D_SHADER_REQUIRES_64_UAVS;
  1708. if (features & ShaderFeatureInfo_MininumPrecision) result |= D3D_SHADER_REQUIRES_MINIMUM_PRECISION;
  1709. if (features & ShaderFeatureInfo_11_1_DoubleExtensions) result |= D3D_SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS;
  1710. if (features & ShaderFeatureInfo_11_1_ShaderExtensions) result |= D3D_SHADER_REQUIRES_11_1_SHADER_EXTENSIONS;
  1711. if (features & ShaderFeatureInfo_LEVEL9ComparisonFiltering) result |= D3D_SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING;
  1712. if (features & ShaderFeatureInfo_TiledResources) result |= D3D_SHADER_REQUIRES_TILED_RESOURCES;
  1713. if (features & ShaderFeatureInfo_StencilRef) result |= D3D_SHADER_REQUIRES_STENCIL_REF;
  1714. if (features & ShaderFeatureInfo_InnerCoverage) result |= D3D_SHADER_REQUIRES_INNER_COVERAGE;
  1715. if (features & ShaderFeatureInfo_TypedUAVLoadAdditionalFormats) result |= D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS;
  1716. if (features & ShaderFeatureInfo_ROVs) result |= D3D_SHADER_REQUIRES_ROVS;
  1717. if (features & ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer) result |= D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER;
  1718. return result;
  1719. }