DxilContainerTest.cpp 36 KB

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