DxilContainerReflection.cpp 87 KB

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