DxilContainerTest.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilContainerTest.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 tests for container formatting and validation. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #ifndef UNICODE
  12. #define UNICODE
  13. #endif
  14. #include <memory>
  15. #include <vector>
  16. #include <string>
  17. #include <tuple>
  18. #include <cassert>
  19. #include <sstream>
  20. #include <algorithm>
  21. #include "dxc/Support/WinIncludes.h"
  22. #include "dxc/dxcapi.h"
  23. #include <atlfile.h>
  24. #include "HLSLTestData.h"
  25. #include "WexTestClass.h"
  26. #include "HlslTestUtils.h"
  27. #include "DxcTestUtils.h"
  28. #include "dxc/Support/Global.h"
  29. #include "dxc/Support/dxcapi.use.h"
  30. #include "dxc/Support/HLSLOptions.h"
  31. #include "dxc/HLSL/DxilContainer.h"
  32. #include <fstream>
  33. #include <filesystem>
  34. #include <d3dcompiler.h>
  35. #pragma comment(lib, "d3dcompiler.lib")
  36. #include <codecvt>
  37. using namespace std;
  38. using namespace hlsl_test;
  39. using namespace std::experimental::filesystem;
  40. static uint8_t MaskCount(uint8_t V) {
  41. DXASSERT_NOMSG(0 <= V && V <= 0xF);
  42. static const uint8_t Count[16] = {
  43. 0, 1, 1, 2,
  44. 1, 2, 2, 3,
  45. 1, 2, 2, 3,
  46. 2, 3, 3, 4
  47. };
  48. return Count[V];
  49. }
  50. class DxilContainerTest {
  51. public:
  52. BEGIN_TEST_CLASS(DxilContainerTest)
  53. TEST_METHOD_PROPERTY(L"Priority", L"0")
  54. END_TEST_CLASS()
  55. TEST_METHOD(CompileWhenOKThenIncludesFeatureInfo)
  56. TEST_METHOD(CompileWhenOKThenIncludesSignatures)
  57. TEST_METHOD(CompileWhenSigSquareThenIncludeSplit)
  58. TEST_METHOD(DisassemblyWhenMissingThenFails)
  59. TEST_METHOD(DisassemblyWhenBCInvalidThenFails)
  60. TEST_METHOD(DisassemblyWhenInvalidThenFails)
  61. TEST_METHOD(DisassemblyWhenValidThenOK)
  62. TEST_METHOD(ValidateFromLL_Abs2)
  63. TEST_METHOD(DxilContainerUnitTest)
  64. TEST_METHOD(ReflectionMatchesDXBC_CheckIn)
  65. BEGIN_TEST_METHOD(ReflectionMatchesDXBC_Full)
  66. TEST_METHOD_PROPERTY(L"Priority", L"1")
  67. END_TEST_METHOD()
  68. dxc::DxcDllSupport m_dllSupport;
  69. void CreateBlobPinned(_In_bytecount_(size) LPCVOID data, SIZE_T size,
  70. UINT32 codePage, _Outptr_ IDxcBlobEncoding **ppBlob) {
  71. CComPtr<IDxcLibrary> library;
  72. IFT(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &library));
  73. IFT(library->CreateBlobWithEncodingFromPinned((LPBYTE)data, size, codePage,
  74. ppBlob));
  75. }
  76. void CreateBlobFromText(_In_z_ const char *pText,
  77. _Outptr_ IDxcBlobEncoding **ppBlob) {
  78. CreateBlobPinned(pText, strlen(pText), CP_UTF8, ppBlob);
  79. }
  80. HRESULT CreateCompiler(IDxcCompiler **ppResult) {
  81. if (!m_dllSupport.IsEnabled()) {
  82. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  83. }
  84. return m_dllSupport.CreateInstance(CLSID_DxcCompiler, ppResult);
  85. }
  86. void CompareShaderInputBindDesc(D3D12_SHADER_INPUT_BIND_DESC *pTestDesc,
  87. D3D12_SHADER_INPUT_BIND_DESC *pBaseDesc) {
  88. VERIFY_ARE_EQUAL(pTestDesc->BindCount, pBaseDesc->BindCount);
  89. VERIFY_ARE_EQUAL(pTestDesc->BindPoint, pBaseDesc->BindPoint);
  90. VERIFY_ARE_EQUAL(pTestDesc->Dimension, pBaseDesc->Dimension);
  91. VERIFY_ARE_EQUAL_STR(pTestDesc->Name, pBaseDesc->Name);
  92. VERIFY_ARE_EQUAL(pTestDesc->NumSamples, pBaseDesc->NumSamples);
  93. VERIFY_ARE_EQUAL(pTestDesc->ReturnType, pBaseDesc->ReturnType);
  94. VERIFY_ARE_EQUAL(pTestDesc->Space, pBaseDesc->Space);
  95. if (pBaseDesc->Type == D3D_SIT_UAV_APPEND_STRUCTURED ||
  96. pBaseDesc->Type == D3D_SIT_UAV_CONSUME_STRUCTURED) {
  97. // dxil only have rw with counter.
  98. VERIFY_ARE_EQUAL(pTestDesc->Type, D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER);
  99. } else if (pTestDesc->Type == D3D_SIT_STRUCTURED &&
  100. pBaseDesc->Type != D3D_SIT_STRUCTURED) {
  101. VERIFY_ARE_EQUAL(pBaseDesc->Type, D3D_SIT_TEXTURE);
  102. } else
  103. VERIFY_ARE_EQUAL(pTestDesc->Type, pBaseDesc->Type);
  104. // D3D_SIF_USERPACKED is never set in dxil.
  105. UINT unusedFlag = D3D_SIF_USERPACKED;
  106. VERIFY_ARE_EQUAL(pTestDesc->uFlags, pBaseDesc->uFlags & ~unusedFlag);
  107. // VERIFY_ARE_EQUAL(pTestDesc->uID, pBaseDesc->uID); // Like register, this can vary.
  108. }
  109. void CompareParameterDesc(D3D12_SIGNATURE_PARAMETER_DESC *pTestDesc,
  110. D3D12_SIGNATURE_PARAMETER_DESC *pBaseDesc, bool isInput) {
  111. VERIFY_ARE_EQUAL(0, _stricmp(pTestDesc->SemanticName, pBaseDesc->SemanticName));
  112. if (pTestDesc->SystemValueType == D3D_NAME_CLIP_DISTANCE) return; // currently generating multiple clip distance params, one per component
  113. VERIFY_ARE_EQUAL(pTestDesc->ComponentType, pBaseDesc->ComponentType);
  114. VERIFY_ARE_EQUAL(MaskCount(pTestDesc->Mask), MaskCount(pBaseDesc->Mask));
  115. VERIFY_ARE_EQUAL(pTestDesc->MinPrecision, pBaseDesc->MinPrecision);
  116. if (!isInput)
  117. VERIFY_ARE_EQUAL(pTestDesc->ReadWriteMask != 0, pBaseDesc->ReadWriteMask != 0); // VERIFY_ARE_EQUAL(pTestDesc->ReadWriteMask, pBaseDesc->ReadWriteMask);
  118. // VERIFY_ARE_EQUAL(pTestDesc->Register, pBaseDesc->Register);
  119. //VERIFY_ARE_EQUAL(pTestDesc->SemanticIndex, pBaseDesc->SemanticIndex);
  120. VERIFY_ARE_EQUAL(pTestDesc->Stream, pBaseDesc->Stream);
  121. VERIFY_ARE_EQUAL(pTestDesc->SystemValueType, pBaseDesc->SystemValueType);
  122. }
  123. void CompareType(ID3D12ShaderReflectionType *pTest,
  124. ID3D12ShaderReflectionType *pBase,
  125. bool shouldSuppressOffsetChecks = false)
  126. {
  127. D3D12_SHADER_TYPE_DESC testDesc, baseDesc;
  128. VERIFY_SUCCEEDED(pTest->GetDesc(&testDesc));
  129. VERIFY_SUCCEEDED(pBase->GetDesc(&baseDesc));
  130. VERIFY_ARE_EQUAL(testDesc.Class, baseDesc.Class);
  131. VERIFY_ARE_EQUAL(testDesc.Type, baseDesc.Type);
  132. VERIFY_ARE_EQUAL(testDesc.Rows, baseDesc.Rows);
  133. VERIFY_ARE_EQUAL(testDesc.Columns, baseDesc.Columns);
  134. VERIFY_ARE_EQUAL(testDesc.Elements, baseDesc.Elements);
  135. VERIFY_ARE_EQUAL(testDesc.Members, baseDesc.Members);
  136. if(!shouldSuppressOffsetChecks)
  137. {
  138. VERIFY_ARE_EQUAL(testDesc.Offset, baseDesc.Offset);
  139. }
  140. VERIFY_ARE_EQUAL(0, strcmp(testDesc.Name, baseDesc.Name));
  141. for (UINT i = 0; i < baseDesc.Members; ++i) {
  142. ID3D12ShaderReflectionType* testMemberType = pTest->GetMemberTypeByIndex(i);
  143. ID3D12ShaderReflectionType* baseMemberType = pBase->GetMemberTypeByIndex(i);
  144. VERIFY_IS_NOT_NULL(testMemberType);
  145. VERIFY_IS_NOT_NULL(baseMemberType);
  146. CompareType(testMemberType, baseMemberType, shouldSuppressOffsetChecks);
  147. LPCSTR testMemberName = pTest->GetMemberTypeName(i);
  148. LPCSTR baseMemberName = pBase->GetMemberTypeName(i);
  149. VERIFY_ARE_EQUAL(0, strcmp(testMemberName, baseMemberName));
  150. }
  151. }
  152. typedef HRESULT (__stdcall ID3D12ShaderReflection::*GetParameterDescFn)(UINT, D3D12_SIGNATURE_PARAMETER_DESC*);
  153. void SortNameIdxVector(std::vector<std::tuple<LPCSTR, UINT, UINT>> &value) {
  154. struct FirstPredT {
  155. bool operator()(std::tuple<LPCSTR, UINT, UINT> &l,
  156. std::tuple<LPCSTR, UINT, UINT> &r) {
  157. int strResult = strcmp(std::get<0>(l), std::get<0>(r));
  158. return (strResult < 0 ) || (strResult == 0 && std::get<1>(l) < std::get<1>(r));
  159. }
  160. } FirstPred;
  161. std::sort(value.begin(), value.end(), FirstPred);
  162. }
  163. void CompareParameterDescs(UINT count, ID3D12ShaderReflection *pTest,
  164. ID3D12ShaderReflection *pBase,
  165. GetParameterDescFn Fn, bool isInput) {
  166. std::vector<std::tuple<LPCSTR, UINT, UINT>> testParams, baseParams;
  167. testParams.reserve(count);
  168. baseParams.reserve(count);
  169. for (UINT i = 0; i < count; ++i) {
  170. D3D12_SIGNATURE_PARAMETER_DESC D;
  171. VERIFY_SUCCEEDED((pTest->*Fn)(i, &D));
  172. testParams.push_back(std::make_tuple(D.SemanticName, D.SemanticIndex, i));
  173. VERIFY_SUCCEEDED((pBase->*Fn)(i, &D));
  174. baseParams.push_back(std::make_tuple(D.SemanticName, D.SemanticIndex, i));
  175. }
  176. SortNameIdxVector(testParams);
  177. SortNameIdxVector(baseParams);
  178. for (UINT i = 0; i < count; ++i) {
  179. D3D12_SIGNATURE_PARAMETER_DESC testParamDesc, baseParamDesc;
  180. VERIFY_SUCCEEDED(
  181. (pTest->*Fn)(std::get<2>(testParams[i]), &testParamDesc));
  182. VERIFY_SUCCEEDED(
  183. (pBase->*Fn)(std::get<2>(baseParams[i]), &baseParamDesc));
  184. CompareParameterDesc(&testParamDesc, &baseParamDesc, isInput);
  185. }
  186. }
  187. void CompareReflection(ID3D12ShaderReflection *pTest, ID3D12ShaderReflection *pBase) {
  188. D3D12_SHADER_DESC testDesc, baseDesc;
  189. VERIFY_SUCCEEDED(pTest->GetDesc(&testDesc));
  190. VERIFY_SUCCEEDED(pBase->GetDesc(&baseDesc));
  191. VERIFY_ARE_EQUAL(D3D12_SHVER_GET_TYPE(testDesc.Version), D3D12_SHVER_GET_TYPE(baseDesc.Version));
  192. VERIFY_ARE_EQUAL(testDesc.ConstantBuffers, baseDesc.ConstantBuffers);
  193. VERIFY_ARE_EQUAL(testDesc.BoundResources, baseDesc.BoundResources);
  194. VERIFY_ARE_EQUAL(testDesc.InputParameters, baseDesc.InputParameters);
  195. VERIFY_ARE_EQUAL(testDesc.OutputParameters, baseDesc.OutputParameters);
  196. VERIFY_ARE_EQUAL(testDesc.PatchConstantParameters, baseDesc.PatchConstantParameters);
  197. {
  198. for (UINT i = 0; i < testDesc.ConstantBuffers; ++i) {
  199. ID3D12ShaderReflectionConstantBuffer *pTestCB, *pBaseCB;
  200. D3D12_SHADER_BUFFER_DESC testCB, baseCB;
  201. pTestCB = pTest->GetConstantBufferByIndex(i);
  202. VERIFY_SUCCEEDED(pTestCB->GetDesc(&testCB));
  203. pBaseCB = pBase->GetConstantBufferByName(testCB.Name);
  204. VERIFY_SUCCEEDED(pBaseCB->GetDesc(&baseCB));
  205. VERIFY_ARE_EQUAL_STR(testCB.Name, baseCB.Name);
  206. VERIFY_ARE_EQUAL(testCB.Type, baseCB.Type);
  207. VERIFY_ARE_EQUAL(testCB.Variables, baseCB.Variables);
  208. VERIFY_ARE_EQUAL(testCB.Size, baseCB.Size);
  209. VERIFY_ARE_EQUAL(testCB.uFlags, baseCB.uFlags);
  210. llvm::StringMap<D3D12_SHADER_VARIABLE_DESC> variableMap;
  211. llvm::StringMap<ID3D12ShaderReflectionType*> variableTypeMap;
  212. for (UINT vi = 0; vi < testCB.Variables; ++vi) {
  213. ID3D12ShaderReflectionVariable *pBaseConst;
  214. D3D12_SHADER_VARIABLE_DESC baseConst;
  215. pBaseConst = pBaseCB->GetVariableByIndex(vi);
  216. VERIFY_SUCCEEDED(pBaseConst->GetDesc(&baseConst));
  217. variableMap[baseConst.Name] = baseConst;
  218. ID3D12ShaderReflectionType* pBaseType = pBaseConst->GetType();
  219. VERIFY_IS_NOT_NULL(pBaseType);
  220. variableTypeMap[baseConst.Name] = pBaseType;
  221. }
  222. for (UINT vi = 0; vi < testCB.Variables; ++vi) {
  223. ID3D12ShaderReflectionVariable *pTestConst;
  224. D3D12_SHADER_VARIABLE_DESC testConst;
  225. pTestConst = pTestCB->GetVariableByIndex(vi);
  226. VERIFY_SUCCEEDED(pTestConst->GetDesc(&testConst));
  227. VERIFY_ARE_EQUAL(variableMap.count(testConst.Name), 1);
  228. D3D12_SHADER_VARIABLE_DESC baseConst = variableMap[testConst.Name];
  229. VERIFY_ARE_EQUAL(testConst.uFlags, baseConst.uFlags);
  230. VERIFY_ARE_EQUAL(testConst.StartOffset, baseConst.StartOffset);
  231. // TODO: enalbe size cmp.
  232. //VERIFY_ARE_EQUAL(testConst.Size, baseConst.Size);
  233. ID3D12ShaderReflectionType* pTestType = pTestConst->GetType();
  234. VERIFY_IS_NOT_NULL(pTestType);
  235. VERIFY_ARE_EQUAL(variableTypeMap.count(testConst.Name), 1);
  236. ID3D12ShaderReflectionType* pBaseType = variableTypeMap[testConst.Name];
  237. // Note: we suppress comparing offsets for structured buffers, because dxc and fxc don't
  238. // seem to agree in that case.
  239. //
  240. // The information in the `D3D12_SHADER_BUFFER_DESC` doesn't give us enough to
  241. // be able to isolate structured buffers, so we do the test negatively: suppress
  242. // offset checks *unless* we are looking at a `cbuffer` or `tbuffer`.
  243. bool shouldSuppressOffsetChecks = true;
  244. switch( baseCB.Type )
  245. {
  246. default:
  247. break;
  248. case D3D_CT_CBUFFER:
  249. case D3D_CT_TBUFFER:
  250. shouldSuppressOffsetChecks = false;
  251. break;
  252. }
  253. CompareType(pTestType, pBaseType, shouldSuppressOffsetChecks);
  254. }
  255. }
  256. }
  257. for (UINT i = 0; i < testDesc.BoundResources; ++i) {
  258. D3D12_SHADER_INPUT_BIND_DESC testParamDesc, baseParamDesc;
  259. VERIFY_SUCCEEDED(pTest->GetResourceBindingDesc(i, &testParamDesc), WStrFmt(L"i=%u", i));
  260. VERIFY_SUCCEEDED(pBase->GetResourceBindingDescByName(testParamDesc.Name, &baseParamDesc));
  261. CompareShaderInputBindDesc(&testParamDesc, &baseParamDesc);
  262. }
  263. CompareParameterDescs(testDesc.InputParameters, pTest, pBase, &ID3D12ShaderReflection::GetInputParameterDesc, true);
  264. CompareParameterDescs(testDesc.OutputParameters, pTest, pBase,
  265. &ID3D12ShaderReflection::GetOutputParameterDesc,
  266. false);
  267. bool isHs = testDesc.HSPartitioning != D3D_TESSELLATOR_PARTITIONING::D3D11_TESSELLATOR_PARTITIONING_UNDEFINED;
  268. CompareParameterDescs(
  269. testDesc.PatchConstantParameters, pTest, pBase,
  270. &ID3D12ShaderReflection::GetPatchConstantParameterDesc, !isHs);
  271. {
  272. UINT32 testTotal, testX, testY, testZ;
  273. UINT32 baseTotal, baseX, baseY, baseZ;
  274. testTotal = pTest->GetThreadGroupSize(&testX, &testY, &testZ);
  275. baseTotal = pBase->GetThreadGroupSize(&baseX, &baseY, &baseZ);
  276. VERIFY_ARE_EQUAL(testTotal, baseTotal);
  277. VERIFY_ARE_EQUAL(testX, baseX);
  278. VERIFY_ARE_EQUAL(testY, baseY);
  279. VERIFY_ARE_EQUAL(testZ, baseZ);
  280. }
  281. }
  282. void split(const wstring &s, wchar_t delim, vector<wstring> &elems) {
  283. wstringstream ss(s);
  284. wstring item;
  285. while (getline(ss, item, delim)) {
  286. elems.push_back(item);
  287. }
  288. }
  289. vector<wstring> split(const wstring &s, char delim) {
  290. vector<wstring> elems;
  291. split(s, delim, elems);
  292. return elems;
  293. }
  294. wstring SplitFilename(const wstring &str) {
  295. size_t found;
  296. found = str.find_last_of(L"/\\");
  297. return str.substr(0, found);
  298. }
  299. void NameParseCommandPartsFromFile(LPCWSTR path, std::vector<FileRunCommandPart> &parts) {
  300. vector<wstring> Parts = split(wstring(path), '+');
  301. std::wstring Name = Parts[0];
  302. std::wstring EntryPoint = Parts[1];
  303. std::wstring ShaderModel = Parts[2];
  304. std::wstring Arguments = L"-T ";
  305. Arguments += ShaderModel;
  306. Arguments += L" -E ";
  307. Arguments += EntryPoint;
  308. Arguments += L" %s";
  309. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > w;
  310. string ArgumentsNarrow = w.to_bytes(Arguments);
  311. FileRunCommandPart P(string("%dxc"), ArgumentsNarrow, path);
  312. parts.push_back(P);
  313. }
  314. HRESULT CompileFromFile(LPCWSTR path, bool useDXBC, IDxcBlob **ppBlob) {
  315. std::vector<FileRunCommandPart> parts;
  316. //NameParseCommandPartsFromFile(path, parts);
  317. ParseCommandPartsFromFile(path, parts);
  318. VERIFY_IS_TRUE(parts.size() > 0);
  319. VERIFY_ARE_EQUAL_STR(parts[0].Command.c_str(), "%dxc");
  320. FileRunCommandPart &dxc = parts[0];
  321. m_dllSupport.Initialize();
  322. dxc.DllSupport = &m_dllSupport;
  323. hlsl::options::MainArgs args;
  324. hlsl::options::DxcOpts opts;
  325. dxc.ReadOptsForDxc(args, opts);
  326. if (opts.CodeGenHighLevel) return E_FAIL; // skip for now
  327. if (useDXBC) {
  328. // Consider supporting defines and flags if/when needed.
  329. std::string TargetProfile(opts.TargetProfile.str());
  330. TargetProfile[3] = '5'; TargetProfile[5] = '1';
  331. CComPtr<ID3DBlob> pDxbcBlob;
  332. CComPtr<ID3DBlob> pDxbcErrors;
  333. UINT unboundDescTab = (1 << 20);
  334. IFR(D3DCompileFromFile(path, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
  335. opts.EntryPoint.str().c_str(),
  336. TargetProfile.c_str(),
  337. unboundDescTab, 0, &pDxbcBlob, &pDxbcErrors));
  338. IFR(pDxbcBlob.QueryInterface(ppBlob));
  339. }
  340. else {
  341. dxc.Run(nullptr);
  342. IFRBOOL(dxc.RunResult == 0, E_FAIL);
  343. IFR(dxc.OpResult->GetResult(ppBlob));
  344. }
  345. return S_OK;
  346. }
  347. void CreateReflectionFromBlob(IDxcBlob *pBlob, ID3D12ShaderReflection **ppReflection) {
  348. CComPtr<IDxcContainerReflection> pReflection;
  349. UINT32 shaderIdx;
  350. m_dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pReflection);
  351. VERIFY_SUCCEEDED(pReflection->Load(pBlob));
  352. VERIFY_SUCCEEDED(pReflection->FindFirstPartKind(hlsl::DFCC_DXIL, &shaderIdx));
  353. VERIFY_SUCCEEDED(pReflection->GetPartReflection(shaderIdx, __uuidof(ID3D12ShaderReflection), (void**)ppReflection));
  354. }
  355. void CreateReflectionFromDXBC(IDxcBlob *pBlob, ID3D12ShaderReflection **ppReflection) {
  356. VERIFY_SUCCEEDED(
  357. D3DReflect(pBlob->GetBufferPointer(), pBlob->GetBufferSize(),
  358. __uuidof(ID3D12ShaderReflection), (void **)ppReflection));
  359. }
  360. std::string DisassembleProgram(LPCSTR program, LPCWSTR entryPoint,
  361. LPCWSTR target) {
  362. CComPtr<IDxcCompiler> pCompiler;
  363. CComPtr<IDxcBlobEncoding> pSource;
  364. CComPtr<IDxcBlob> pProgram;
  365. CComPtr<IDxcBlobEncoding> pDisassembly;
  366. CComPtr<IDxcOperationResult> pResult;
  367. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  368. CreateBlobFromText(program, &pSource);
  369. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", entryPoint,
  370. target, nullptr, 0, nullptr, 0, nullptr,
  371. &pResult));
  372. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  373. VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
  374. return BlobToUtf8(pDisassembly);
  375. }
  376. void SetupBasicHeader(hlsl::DxilContainerHeader *pHeader,
  377. uint32_t partCount = 0) {
  378. ZeroMemory(pHeader, sizeof(*pHeader));
  379. pHeader->HeaderFourCC = hlsl::DFCC_Container;
  380. pHeader->Version.Major = 1;
  381. pHeader->Version.Minor = 0;
  382. pHeader->PartCount = partCount;
  383. pHeader->ContainerSizeInBytes =
  384. sizeof(hlsl::DxilContainerHeader) +
  385. sizeof(uint32_t) * partCount +
  386. sizeof(hlsl::DxilPartHeader) * partCount;
  387. }
  388. void CodeGenTestCheck(LPCWSTR name) {
  389. std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
  390. FileRunTestResult t = FileRunTestResult::RunFromFileCommands(fullPath.c_str());
  391. if (t.RunResult != 0) {
  392. CA2W commentWide(t.ErrorMessage.c_str(), CP_UTF8);
  393. WEX::Logging::Log::Comment(commentWide);
  394. WEX::Logging::Log::Error(L"Run result is not zero");
  395. }
  396. }
  397. WEX::Common::String WStrFmt(const wchar_t* msg, ...) {
  398. va_list args;
  399. va_start(args, msg);
  400. WEX::Common::String result = WEX::Common::String().FormatV(msg, args);
  401. va_end(args);
  402. return result;
  403. }
  404. void ReflectionTest(LPCWSTR name, bool ignoreIfDXBCFails) {
  405. WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Reflection comparison for %s", name));
  406. CComPtr<IDxcBlob> pProgram;
  407. CComPtr<IDxcBlob> pProgramDXBC;
  408. HRESULT hrDXBC = CompileFromFile(name, true, &pProgramDXBC);
  409. if (FAILED(hrDXBC)) {
  410. WEX::Logging::Log::Comment(L"Failed to compile DXBC blob.");
  411. if (ignoreIfDXBCFails) return;
  412. VERIFY_FAIL();
  413. }
  414. if (FAILED(CompileFromFile(name, false, &pProgram))) {
  415. WEX::Logging::Log::Comment(L"Failed to compile DXIL blob.");
  416. if (ignoreIfDXBCFails) return;
  417. VERIFY_FAIL();
  418. }
  419. CComPtr<ID3D12ShaderReflection> pProgramReflection;
  420. CComPtr<ID3D12ShaderReflection> pProgramReflectionDXBC;
  421. CreateReflectionFromBlob(pProgram, &pProgramReflection);
  422. CreateReflectionFromDXBC(pProgramDXBC, &pProgramReflectionDXBC);
  423. CompareReflection(pProgramReflection, pProgramReflectionDXBC);
  424. }
  425. };
  426. TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) {
  427. char program[] =
  428. "struct PSInput {\r\n"
  429. " float4 position : SV_POSITION;\r\n"
  430. " float4 color : COLOR;\r\n"
  431. "};\r\n"
  432. "PSInput VSMain(float4 position : POSITION, float4 color : COLOR) {\r\n"
  433. " PSInput result;\r\n"
  434. " result.position = position;\r\n"
  435. " result.color = color;\r\n"
  436. " return result;\r\n"
  437. "}\r\n"
  438. "float4 PSMain(PSInput input) : SV_TARGET {\r\n"
  439. " return input.color;\r\n"
  440. "}";
  441. {
  442. std::string s = DisassembleProgram(program, L"VSMain", L"vs_6_0");
  443. // NOTE: this will change when proper packing is done, and when 'always-writes' is accurately implemented.
  444. const char expected[] =
  445. ";\n"
  446. "; Input signature:\n"
  447. ";\n"
  448. "; Name Index Mask Register SysValue Format Used\n"
  449. "; -------------------- ----- ------ -------- -------- ------- ------\n"
  450. "; POSITION 0 xyzw 0 NONE float \n" // should read 'xyzw' in Used
  451. "; COLOR 0 xyzw 1 NONE float \n" // should read '1' in register
  452. ";\n"
  453. ";\n"
  454. "; Output signature:\n"
  455. ";\n"
  456. "; Name Index Mask Register SysValue Format Used\n"
  457. "; -------------------- ----- ------ -------- -------- ------- ------\n"
  458. "; SV_Position 0 xyzw 0 POS float xyzw\n" // could read SV_POSITION
  459. "; COLOR 0 xyzw 1 NONE float xyzw\n"; // should read '1' in register
  460. std::string start(s.c_str(), strlen(expected));
  461. VERIFY_ARE_EQUAL_STR(expected, start.c_str());
  462. }
  463. {
  464. std::string s = DisassembleProgram(program, L"PSMain", L"ps_6_0");
  465. // NOTE: this will change when proper packing is done, and when 'always-writes' is accurately implemented.
  466. const char expected[] =
  467. ";\n"
  468. "; Input signature:\n"
  469. ";\n"
  470. "; Name Index Mask Register SysValue Format Used\n"
  471. "; -------------------- ----- ------ -------- -------- ------- ------\n"
  472. "; SV_Position 0 xyzw 0 POS float \n" // could read SV_POSITION
  473. "; COLOR 0 xyzw 1 NONE float \n" // should read '1' in register, xyzw in Used
  474. ";\n"
  475. ";\n"
  476. "; Output signature:\n"
  477. ";\n"
  478. "; Name Index Mask Register SysValue Format Used\n"
  479. "; -------------------- ----- ------ -------- -------- ------- ------\n"
  480. "; SV_Target 0 xyzw 0 TARGET float xyzw\n";// could read SV_TARGET
  481. std::string start(s.c_str(), strlen(expected));
  482. VERIFY_ARE_EQUAL_STR(expected, start.c_str());
  483. }
  484. }
  485. TEST_F(DxilContainerTest, CompileWhenSigSquareThenIncludeSplit) {
  486. #if 0 // TODO: reenable test when multiple rows are supported.
  487. const char program[] =
  488. "float main(float4x4 a : A, int4 b : B) : SV_Target {\n"
  489. " return a[b.x][b.y];\n"
  490. "}";
  491. std::string s = DisassembleProgram(program, L"main", L"ps_6_0");
  492. const char expected[] =
  493. "// Input signature:\n"
  494. "//\n"
  495. "// Name Index Mask Register SysValue Format Used\n"
  496. "// -------------------- ----- ------ -------- -------- ------- ------\n"
  497. "// A 0 xyzw 0 NONE float xyzw\n"
  498. "// A 1 xyzw 1 NONE float xyzw\n"
  499. "// A 2 xyzw 2 NONE float xyzw\n"
  500. "// A 3 xyzw 3 NONE float xyzw\n"
  501. "// B 0 xyzw 4 NONE int xy\n"
  502. "//\n"
  503. "//\n"
  504. "// Output signature:\n"
  505. "//\n"
  506. "// Name Index Mask Register SysValue Format Used\n"
  507. "// -------------------- ----- ------ -------- -------- ------- ------\n"
  508. "// SV_Target 0 x 0 TARGET float x\n";
  509. std::string start(s.c_str(), strlen(expected));
  510. VERIFY_ARE_EQUAL_STR(expected, start.c_str());
  511. #endif
  512. }
  513. TEST_F(DxilContainerTest, CompileWhenOKThenIncludesFeatureInfo) {
  514. CComPtr<IDxcCompiler> pCompiler;
  515. CComPtr<IDxcBlobEncoding> pSource;
  516. CComPtr<IDxcBlob> pProgram;
  517. CComPtr<IDxcBlobEncoding> pDisassembly;
  518. CComPtr<IDxcOperationResult> pResult;
  519. hlsl::DxilContainerHeader *pHeader;
  520. hlsl::DxilPartIterator pPartIter(nullptr, 0);
  521. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  522. CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
  523. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0",
  524. nullptr, 0, nullptr, 0, nullptr,
  525. &pResult));
  526. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  527. // Now mess with the program bitcode.
  528. pHeader = (hlsl::DxilContainerHeader *)pProgram->GetBufferPointer();
  529. pPartIter = std::find_if(hlsl::begin(pHeader), hlsl::end(pHeader),
  530. hlsl::DxilPartIsType(hlsl::DFCC_FeatureInfo));
  531. VERIFY_ARE_NOT_EQUAL(hlsl::end(pHeader), pPartIter);
  532. VERIFY_ARE_EQUAL(sizeof(uint64_t), (*pPartIter)->PartSize);
  533. VERIFY_ARE_EQUAL(0, *(uint64_t *)hlsl::GetDxilPartData(*pPartIter));
  534. }
  535. TEST_F(DxilContainerTest, DisassemblyWhenBCInvalidThenFails) {
  536. CComPtr<IDxcCompiler> pCompiler;
  537. CComPtr<IDxcBlobEncoding> pSource;
  538. CComPtr<IDxcBlob> pProgram;
  539. CComPtr<IDxcBlobEncoding> pDisassembly;
  540. CComPtr<IDxcOperationResult> pResult;
  541. hlsl::DxilContainerHeader *pHeader;
  542. hlsl::DxilPartHeader *pPart;
  543. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  544. CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
  545. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0",
  546. nullptr, 0, nullptr, 0, nullptr,
  547. &pResult));
  548. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  549. // Now mess with the program bitcode.
  550. pHeader = (hlsl::DxilContainerHeader *)pProgram->GetBufferPointer();
  551. pPart = const_cast<hlsl::DxilPartHeader *>(
  552. *std::find_if(hlsl::begin(pHeader), hlsl::end(pHeader),
  553. hlsl::DxilPartIsType(hlsl::DFCC_DXIL)));
  554. strcpy_s(hlsl::GetDxilPartData(pPart), pPart->PartSize, "corruption");
  555. VERIFY_FAILED(pCompiler->Disassemble(pProgram, &pDisassembly));
  556. }
  557. TEST_F(DxilContainerTest, DisassemblyWhenMissingThenFails) {
  558. CComPtr<IDxcCompiler> pCompiler;
  559. CComPtr<IDxcBlobEncoding> pSource;
  560. CComPtr<IDxcBlobEncoding> pDisassembly;
  561. hlsl::DxilContainerHeader header;
  562. SetupBasicHeader(&header);
  563. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  564. CreateBlobPinned(&header, header.ContainerSizeInBytes, CP_UTF8, &pSource);
  565. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  566. }
  567. TEST_F(DxilContainerTest, DisassemblyWhenInvalidThenFails) {
  568. CComPtr<IDxcCompiler> pCompiler;
  569. CComPtr<IDxcBlobEncoding> pDisassembly;
  570. uint8_t scratch[1024];
  571. hlsl::DxilContainerHeader *pHeader = (hlsl::DxilContainerHeader *)scratch;
  572. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  573. // Too small to contain header.
  574. {
  575. CComPtr<IDxcBlobEncoding> pSource;
  576. SetupBasicHeader(pHeader);
  577. CreateBlobPinned(pHeader, sizeof(hlsl::DxilContainerHeader) - 4, CP_UTF8,
  578. &pSource);
  579. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  580. }
  581. // Wrong major version.
  582. {
  583. CComPtr<IDxcBlobEncoding> pSource;
  584. SetupBasicHeader(pHeader);
  585. pHeader->Version.Major = 100;
  586. CreateBlobPinned(pHeader, pHeader->ContainerSizeInBytes, CP_UTF8, &pSource);
  587. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  588. }
  589. // Size out of bounds.
  590. {
  591. CComPtr<IDxcBlobEncoding> pSource;
  592. SetupBasicHeader(pHeader);
  593. pHeader->ContainerSizeInBytes = 1024;
  594. CreateBlobPinned(pHeader, sizeof(hlsl::DxilContainerHeader), CP_UTF8,
  595. &pSource);
  596. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  597. }
  598. // Size too large as per spec limit.
  599. {
  600. CComPtr<IDxcBlobEncoding> pSource;
  601. SetupBasicHeader(pHeader);
  602. pHeader->ContainerSizeInBytes = hlsl::DxilContainerMaxSize + 1;
  603. CreateBlobPinned(pHeader, pHeader->ContainerSizeInBytes, CP_UTF8, &pSource);
  604. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  605. }
  606. // Not large enough to hold offset table.
  607. {
  608. CComPtr<IDxcBlobEncoding> pSource;
  609. SetupBasicHeader(pHeader);
  610. pHeader->PartCount = 1;
  611. CreateBlobPinned(pHeader, pHeader->ContainerSizeInBytes, CP_UTF8, &pSource);
  612. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  613. }
  614. // Part offset out of bounds.
  615. {
  616. CComPtr<IDxcBlobEncoding> pSource;
  617. SetupBasicHeader(pHeader);
  618. pHeader->PartCount = 1;
  619. *((uint32_t *)(pHeader + 1)) = 1024;
  620. pHeader->ContainerSizeInBytes += sizeof(uint32_t);
  621. CreateBlobPinned(pHeader, pHeader->ContainerSizeInBytes, CP_UTF8, &pSource);
  622. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  623. }
  624. // Part size out of bounds.
  625. {
  626. CComPtr<IDxcBlobEncoding> pSource;
  627. SetupBasicHeader(pHeader);
  628. pHeader->PartCount = 1;
  629. *((uint32_t *)(pHeader + 1)) = sizeof(*pHeader) + sizeof(uint32_t);
  630. pHeader->ContainerSizeInBytes += sizeof(uint32_t);
  631. hlsl::GetDxilContainerPart(pHeader, 0)->PartSize = 1024;
  632. pHeader->ContainerSizeInBytes += sizeof(hlsl::DxilPartHeader);
  633. CreateBlobPinned(pHeader, pHeader->ContainerSizeInBytes, CP_UTF8, &pSource);
  634. VERIFY_FAILED(pCompiler->Disassemble(pSource, &pDisassembly));
  635. }
  636. }
  637. TEST_F(DxilContainerTest, DisassemblyWhenValidThenOK) {
  638. CComPtr<IDxcCompiler> pCompiler;
  639. CComPtr<IDxcBlobEncoding> pSource;
  640. CComPtr<IDxcBlob> pProgram;
  641. CComPtr<IDxcBlobEncoding> pDisassembly;
  642. CComPtr<IDxcOperationResult> pResult;
  643. hlsl::DxilContainerHeader header;
  644. SetupBasicHeader(&header);
  645. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  646. CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
  647. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0",
  648. nullptr, 0, nullptr, 0, nullptr,
  649. &pResult));
  650. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  651. VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
  652. std::string disassembleString(BlobToUtf8(pDisassembly));
  653. VERIFY_ARE_NOT_EQUAL(0, disassembleString.size());
  654. }
  655. class HlslFileVariables {
  656. private:
  657. std::wstring m_Entry;
  658. std::wstring m_Mode;
  659. std::wstring m_Target;
  660. std::vector<std::wstring> m_Arguments;
  661. std::vector<LPCWSTR> m_ArgumentPtrs;
  662. public:
  663. HlslFileVariables(HlslFileVariables &other) = delete;
  664. const LPCWSTR *GetArguments() const { return m_ArgumentPtrs.data(); }
  665. UINT32 GetArgumentCount() const { return m_ArgumentPtrs.size(); }
  666. LPCWSTR GetEntry() const { return m_Entry.c_str(); }
  667. LPCWSTR GetMode() const { return m_Mode.c_str(); }
  668. LPCWSTR GetTarget() const { return m_Target.c_str(); }
  669. void Reset();
  670. HRESULT SetFromText(_In_count_(len) const char *pText, size_t len);
  671. };
  672. void HlslFileVariables::Reset() {
  673. m_Entry.resize(0);
  674. m_Mode.resize(0);
  675. m_Target.resize(0);
  676. m_Arguments.resize(0);
  677. m_ArgumentPtrs.resize(0);
  678. }
  679. #include <codecvt>
  680. static bool wcsneq(const wchar_t *pValue, const wchar_t *pCheck) {
  681. return 0 == wcsncmp(pValue, pCheck, wcslen(pCheck));
  682. }
  683. HRESULT HlslFileVariables::SetFromText(_In_count_(len) const char *pText, size_t len) {
  684. // Look for the line of interest.
  685. const char *pEnd = pText + len;
  686. const char *pLineEnd = pText;
  687. while (pLineEnd < pEnd && *pLineEnd != '\n') pLineEnd++;
  688. // Create a UTF-16-backing store.
  689. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > w;
  690. std::wstring line = w.from_bytes(pText, pLineEnd);
  691. // Find starting and ending '-*-' delimiters.
  692. const wchar_t *pWText = line.c_str();
  693. const wchar_t *pVarStart = wcsstr(pWText, L"-*-");
  694. if (!pVarStart) return E_INVALIDARG;
  695. pVarStart += 3;
  696. const wchar_t *pVarEnd = wcsstr(pVarStart, L"-*-");
  697. if (!pVarEnd) return E_INVALIDARG;
  698. for (;;) {
  699. // Find 'name' ':' 'value' ';'
  700. const wchar_t *pVarNameStart = pVarStart;
  701. while (pVarNameStart < pVarEnd && L' ' == *pVarNameStart) ++pVarNameStart;
  702. if (pVarNameStart == pVarEnd) break;
  703. const wchar_t *pVarValDelim = pVarNameStart;
  704. while (pVarValDelim < pVarEnd && L':' != *pVarValDelim) ++pVarValDelim;
  705. if (pVarValDelim == pVarEnd) break;
  706. const wchar_t *pVarValStart = pVarValDelim + 1;
  707. while (pVarValStart < pVarEnd && L' ' == *pVarValStart) ++pVarValStart;
  708. if (pVarValStart == pVarEnd) break;
  709. const wchar_t *pVarValEnd = pVarValStart;
  710. while (pVarValEnd < pVarEnd && L';' != *pVarValEnd) ++pVarValEnd;
  711. if (wcsneq(pVarNameStart, L"mode")) {
  712. m_Mode.assign(pVarValStart, pVarValEnd - pVarValStart - 1);
  713. }
  714. else if (wcsneq(pVarNameStart, L"hlsl-entry")) {
  715. m_Entry.assign(pVarValStart, pVarValEnd - pVarValStart - 1);
  716. }
  717. else if (wcsneq(pVarNameStart, L"hlsl-target")) {
  718. m_Target.assign(pVarValStart, pVarValEnd - pVarValStart - 1);
  719. }
  720. else if (wcsneq(pVarNameStart, L"hlsl-args")) {
  721. // skip for now
  722. }
  723. }
  724. return S_OK;
  725. }
  726. TEST_F(DxilContainerTest, ReflectionMatchesDXBC_CheckIn) {
  727. WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
  728. ReflectionTest(hlsl_test::GetPathToHlslDataFile(L"..\\CodeGenHLSL\\Samples\\DX11\\SimpleBezier11DS.hlsl").c_str(), false);
  729. ReflectionTest(hlsl_test::GetPathToHlslDataFile(L"..\\CodeGenHLSL\\Samples\\DX11\\SubD11_SmoothPS.hlsl").c_str(), false);
  730. }
  731. TEST_F(DxilContainerTest, ReflectionMatchesDXBC_Full) {
  732. WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
  733. std::wstring codeGenPath = hlsl_test::GetPathToHlslDataFile(L"..\\CodeGenHLSL\\Samples");
  734. for (auto &p: recursive_directory_iterator(path(codeGenPath))) {
  735. if (is_regular_file(p)) {
  736. LPCWSTR fullPath = p.path().c_str();
  737. if (wcsstr(fullPath, L".hlsli") != nullptr) continue;
  738. if (wcsstr(fullPath, L"TessellatorCS40_defines.h") != nullptr) continue;
  739. // Skip failed tests.
  740. if (wcsstr(fullPath, L"SubD11_SubDToBezierHS") != nullptr) continue;
  741. ReflectionTest(fullPath, true);
  742. }
  743. }
  744. }
  745. TEST_F(DxilContainerTest, ValidateFromLL_Abs2) {
  746. CodeGenTestCheck(L"abs2_m.ll");
  747. }
  748. TEST_F(DxilContainerTest, DxilContainerUnitTest) {
  749. CComPtr<IDxcCompiler> pCompiler;
  750. CComPtr<IDxcBlobEncoding> pSource;
  751. CComPtr<IDxcBlob> pProgram;
  752. CComPtr<IDxcBlobEncoding> pDisassembly;
  753. CComPtr<IDxcOperationResult> pResult;
  754. std::vector<LPCWSTR> arguments;
  755. arguments.emplace_back(L"/Zi");
  756. VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
  757. CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
  758. // Test DxilContainer with ShaderDebugInfoDXIL
  759. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", arguments.data(), 1, nullptr, 0, nullptr, &pResult));
  760. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  761. const hlsl::DxilContainerHeader *pHeader = static_cast<const hlsl::DxilContainerHeader *> (pProgram->GetBufferPointer());
  762. VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(pHeader, pProgram->GetBufferSize()));
  763. VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(pHeader, pProgram->GetBufferSize()));
  764. VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
  765. VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
  766. VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
  767. VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
  768. pResult.Release();
  769. pProgram.Release();
  770. // Test DxilContainer without ShaderDebugInfoDXIL
  771. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
  772. VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
  773. pHeader = static_cast<const hlsl::DxilContainerHeader *> (pProgram->GetBufferPointer());
  774. VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(pHeader, pProgram->GetBufferSize()));
  775. VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(pHeader, pProgram->GetBufferSize()));
  776. VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
  777. VERIFY_IS_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
  778. VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
  779. VERIFY_IS_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
  780. // Test Empty DxilContainer
  781. hlsl::DxilContainerHeader header;
  782. SetupBasicHeader(&header);
  783. VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(&header, header.ContainerSizeInBytes));
  784. VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(&header, header.ContainerSizeInBytes));
  785. VERIFY_IS_NULL(hlsl::GetDxilProgramHeader(&header, hlsl::DxilFourCC::DFCC_DXIL));
  786. VERIFY_IS_NULL(hlsl::GetDxilPartByType(&header, hlsl::DxilFourCC::DFCC_DXIL));
  787. }