DxilContainerReflection.cpp 71 KB

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