DxilContainerReflection.cpp 87 KB

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