ValidationTest.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // ValidationTest.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // Licensed under the MIT license. See COPYRIGHT in the project root for //
  6. // full license information. //
  7. // //
  8. // //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include <memory>
  11. #include <vector>
  12. #include <string>
  13. #include <algorithm>
  14. #include <atlbase.h>
  15. #include "WexTestClass.h"
  16. #include "DxcTestUtils.h"
  17. #include "HlslTestUtils.h"
  18. using namespace std;
  19. class ValidationTest
  20. {
  21. public:
  22. BEGIN_TEST_CLASS(ValidationTest)
  23. TEST_METHOD_PROPERTY(L"Priority", L"0")
  24. END_TEST_CLASS()
  25. TEST_METHOD(WhenCorrectThenOK);
  26. TEST_METHOD(WhenMisalignedThenFail);
  27. TEST_METHOD(WhenEmptyFileThenFail);
  28. TEST_METHOD(WhenIncorrectMagicThenFail);
  29. TEST_METHOD(WhenIncorrectTargetTripleThenFail);
  30. TEST_METHOD(WhenIncorrectModelThenFail);
  31. TEST_METHOD(WhenIncorrectPSThenFail);
  32. TEST_METHOD(WhenWaveAffectsGradientThenFail);
  33. TEST_METHOD(WhenMultipleModulesThenFail);
  34. TEST_METHOD(WhenUnexpectedEOFThenFail);
  35. TEST_METHOD(WhenUnknownBlocksThenFail);
  36. TEST_METHOD(LoadOutputControlPointNotInPatchConstantFunction);
  37. TEST_METHOD(StorePatchControlNotInPatchConstantFunction);
  38. TEST_METHOD(OutputControlPointIDInPatchConstantFunction);
  39. TEST_METHOD(GsVertexIDOutOfBound)
  40. TEST_METHOD(StreamIDOutOfBound)
  41. TEST_METHOD(SignatureStreamIDForNonGS)
  42. TEST_METHOD(TypedUAVStoreFullMask0)
  43. TEST_METHOD(TypedUAVStoreFullMask1)
  44. TEST_METHOD(Recursive)
  45. TEST_METHOD(Recursive2)
  46. TEST_METHOD(ResourceRangeOverlap0)
  47. TEST_METHOD(ResourceRangeOverlap1)
  48. TEST_METHOD(ResourceRangeOverlap2)
  49. TEST_METHOD(ResourceRangeOverlap3)
  50. TEST_METHOD(CBufferOverlap0)
  51. TEST_METHOD(CBufferOverlap1)
  52. TEST_METHOD(ControlFlowHint)
  53. TEST_METHOD(ControlFlowHint1)
  54. TEST_METHOD(ControlFlowHint2)
  55. TEST_METHOD(SemanticLength1)
  56. TEST_METHOD(SemanticLength64)
  57. TEST_METHOD(PullModelPosition)
  58. TEST_METHOD(StructBufStrideAlign)
  59. TEST_METHOD(StructBufStrideOutOfBound)
  60. TEST_METHOD(StructBufGlobalCoherentAndCounter)
  61. TEST_METHOD(StructBufLoadCoordinates)
  62. TEST_METHOD(StructBufStoreCoordinates)
  63. TEST_METHOD(TypedBufRetType)
  64. TEST_METHOD(VsInputSemantic)
  65. TEST_METHOD(VsOutputSemantic)
  66. TEST_METHOD(HsInputSemantic)
  67. TEST_METHOD(HsOutputSemantic)
  68. TEST_METHOD(PatchConstSemantic)
  69. TEST_METHOD(DsInputSemantic)
  70. TEST_METHOD(DsOutputSemantic)
  71. TEST_METHOD(GsInputSemantic)
  72. TEST_METHOD(GsOutputSemantic)
  73. TEST_METHOD(PsInputSemantic)
  74. TEST_METHOD(PsOutputSemantic)
  75. TEST_METHOD(ArrayOfSVTarget)
  76. TEST_METHOD(InfiniteLog)
  77. TEST_METHOD(InfiniteAsin)
  78. TEST_METHOD(InfiniteAcos)
  79. TEST_METHOD(InfiniteDdxDdy)
  80. TEST_METHOD(IDivByZero)
  81. TEST_METHOD(UDivByZero)
  82. TEST_METHOD(UnusedMetadata)
  83. TEST_METHOD(WhenInstrDisallowedThenFail);
  84. TEST_METHOD(WhenDepthNotFloatThenFail);
  85. TEST_METHOD(BarrierFail);
  86. TEST_METHOD(CBufferLegacyOutOfBoundFail);
  87. TEST_METHOD(CBufferOutOfBoundFail);
  88. TEST_METHOD(CsThreadSizeFail);
  89. TEST_METHOD(DeadLoopFail);
  90. TEST_METHOD(EvalFail);
  91. TEST_METHOD(GetDimCalcLODFail);
  92. TEST_METHOD(HsAttributeFail);
  93. TEST_METHOD(InnerCoverageFail);
  94. TEST_METHOD(InterpChangeFail);
  95. TEST_METHOD(InterpOnIntFail);
  96. TEST_METHOD(InvalidSigCompTyFail);
  97. TEST_METHOD(MultiStream2Fail);
  98. TEST_METHOD(PhiTGSMFail);
  99. TEST_METHOD(ReducibleFail);
  100. TEST_METHOD(SampleBiasFail);
  101. TEST_METHOD(SamplerKindFail);
  102. TEST_METHOD(SemaOverlapFail);
  103. TEST_METHOD(SigOutOfRangeFail);
  104. TEST_METHOD(SigOverlapFail);
  105. TEST_METHOD(SimpleHs1Fail);
  106. TEST_METHOD(SimpleHs3Fail);
  107. TEST_METHOD(SimpleHs4Fail);
  108. TEST_METHOD(SimpleDs1Fail);
  109. TEST_METHOD(SimpleGs1Fail);
  110. TEST_METHOD(UavBarrierFail);
  111. TEST_METHOD(UndefValueFail);
  112. TEST_METHOD(UpdateCounterFail);
  113. TEST_METHOD(WhenSmUnknownThenFail);
  114. TEST_METHOD(WhenMetaFlagsUsageDeclThenOK);
  115. TEST_METHOD(WhenMetaFlagsUsageThenFail);
  116. dxc::DxcDllSupport m_dllSupport;
  117. void TestCheck(LPCWSTR name) {
  118. std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
  119. FileRunTestResult t = FileRunTestResult::RunFromFileCommands(fullPath.c_str());
  120. if (t.RunResult != 0) {
  121. CA2W commentWide(t.ErrorMessage.c_str(), CP_UTF8);
  122. WEX::Logging::Log::Comment(commentWide);
  123. WEX::Logging::Log::Error(L"Run result is not zero");
  124. }
  125. }
  126. bool CheckOperationResultMsg(IDxcOperationResult *pResult,
  127. const char *pErrorMsg, bool maySucceedAnyway) {
  128. HRESULT status;
  129. VERIFY_SUCCEEDED(pResult->GetStatus(&status));
  130. if (pErrorMsg == nullptr) {
  131. VERIFY_SUCCEEDED(status);
  132. }
  133. else {
  134. if (SUCCEEDED(status) && maySucceedAnyway) {
  135. return false;
  136. }
  137. //VERIFY_FAILED(status);
  138. CComPtr<IDxcBlobEncoding> text;
  139. VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&text));
  140. const char *pStart = (const char *)text->GetBufferPointer();
  141. const char *pEnd = pStart + text->GetBufferSize();
  142. const char *pMatch = std::search(pStart, pEnd, pErrorMsg, pErrorMsg + strlen(pErrorMsg));
  143. VERIFY_ARE_NOT_EQUAL(pEnd, pMatch);
  144. }
  145. return true;
  146. }
  147. void CheckValidationMsg(IDxcBlob *pBlob, const char *pErrorMsg) {
  148. CComPtr<IDxcValidator> pValidator;
  149. CComPtr<IDxcOperationResult> pResult;
  150. if (!m_dllSupport.IsEnabled()) {
  151. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  152. }
  153. VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
  154. VERIFY_SUCCEEDED(pValidator->Validate(pBlob, DxcValidatorFlags_Default, &pResult));
  155. CheckOperationResultMsg(pResult, pErrorMsg, false);
  156. }
  157. void CheckValidationMsg(const char *pBlob, size_t blobSize, const char *pErrorMsg) {
  158. if (!m_dllSupport.IsEnabled()) {
  159. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  160. }
  161. CComPtr<IDxcLibrary> pLibrary;
  162. CComPtr<IDxcBlobEncoding> pBlobEncoding; // Encoding doesn't actually matter, it's binary.
  163. VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  164. VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)pBlob, blobSize, CP_UTF8, &pBlobEncoding));
  165. CheckValidationMsg(pBlobEncoding, pErrorMsg);
  166. }
  167. void CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
  168. IDxcBlob **pResultBlob) {
  169. CComPtr<IDxcCompiler> pCompiler;
  170. CComPtr<IDxcOperationResult> pResult;
  171. CComPtr<IDxcBlob> pProgram;
  172. if (!m_dllSupport.IsEnabled()) {
  173. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  174. }
  175. CA2W shWide(pShaderModel, CP_UTF8);
  176. VERIFY_SUCCEEDED(
  177. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  178. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main",
  179. shWide, nullptr, 0, nullptr, 0, nullptr,
  180. &pResult));
  181. VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
  182. }
  183. void CompileSource(LPCSTR pSource, LPCSTR pShaderModel,
  184. IDxcBlob **pResultBlob) {
  185. if (!m_dllSupport.IsEnabled()) {
  186. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  187. }
  188. CComPtr<IDxcBlobEncoding> pSourceBlob;
  189. Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
  190. CompileSource(pSourceBlob, pShaderModel, pResultBlob);
  191. }
  192. void DisassembleProgram(IDxcBlob *pProgram, std::string *text) {
  193. CComPtr<IDxcCompiler> pCompiler;
  194. CComPtr<IDxcBlobEncoding> pDisassembly;
  195. if (!m_dllSupport.IsEnabled()) {
  196. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  197. }
  198. VERIFY_SUCCEEDED(
  199. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  200. VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
  201. *text = BlobToUtf8(pDisassembly);
  202. }
  203. void RewriteAssemblyCheckMsg(LPCSTR pSource, LPCSTR pShaderModel,
  204. LPCSTR pLookFor, LPCSTR pReplacement,
  205. LPCSTR pErrorMsg) {
  206. CComPtr<IDxcBlob> pText;
  207. CComPtr<IDxcBlobEncoding> pSourceBlob;
  208. if (!m_dllSupport.IsEnabled()) {
  209. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  210. }
  211. Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
  212. RewriteAssemblyToText(pSourceBlob, pShaderModel, pLookFor, pReplacement, &pText);
  213. CComPtr<IDxcAssembler> pAssembler;
  214. CComPtr<IDxcOperationResult> pAssembleResult;
  215. VERIFY_SUCCEEDED(
  216. m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
  217. VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
  218. if (!CheckOperationResultMsg(pAssembleResult, pErrorMsg, true)) {
  219. // Assembly succeeded, try validation.
  220. CComPtr<IDxcBlob> pBlob;
  221. VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
  222. CheckValidationMsg(pBlob, pErrorMsg);
  223. }
  224. }
  225. void RewriteAssemblyToText(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
  226. LPCSTR pLookFor, LPCSTR pReplacement,
  227. IDxcBlob **pBlob) {
  228. CComPtr<IDxcBlob> pProgram;
  229. std::string disassembly;
  230. CompileSource(pSource, pShaderModel, &pProgram);
  231. DisassembleProgram(pProgram, &disassembly);
  232. if (pLookFor && *pLookFor) {
  233. bool found = false;
  234. size_t pos = 0;
  235. size_t lookForLen = strlen(pLookFor);
  236. size_t replaceLen = strlen(pReplacement);
  237. for (;;) {
  238. pos = disassembly.find(pLookFor, pos);
  239. if (pos == std::string::npos)
  240. break;
  241. found = true; // at least once
  242. disassembly.replace(pos, lookForLen, pReplacement);
  243. pos += replaceLen;
  244. }
  245. VERIFY_IS_TRUE(found);
  246. }
  247. Utf8ToBlob(m_dllSupport, disassembly.c_str(), pBlob);
  248. }
  249. void RewriteAssemblyCheckMsg(LPCWSTR name, LPCSTR pShaderModel,
  250. LPCSTR pLookFor, LPCSTR pReplacement,
  251. LPCSTR pErrorMsg) {
  252. std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
  253. CComPtr<IDxcLibrary> pLibrary;
  254. CComPtr<IDxcBlobEncoding> pSource;
  255. if (!m_dllSupport.IsEnabled()) {
  256. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  257. }
  258. VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  259. VERIFY_SUCCEEDED(
  260. pLibrary->CreateBlobFromFile(fullPath.c_str(), nullptr, &pSource));
  261. CComPtr<IDxcBlob> pText;
  262. RewriteAssemblyToText(pSource, pShaderModel, pLookFor, pReplacement, &pText);
  263. CComPtr<IDxcAssembler> pAssembler;
  264. CComPtr<IDxcOperationResult> pAssembleResult;
  265. VERIFY_SUCCEEDED(
  266. m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
  267. VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pText, &pAssembleResult));
  268. if (!CheckOperationResultMsg(pAssembleResult, pErrorMsg, true)) {
  269. // Assembly succeeded, try validation.
  270. CComPtr<IDxcBlob> pBlob;
  271. VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pBlob));
  272. CheckValidationMsg(pBlob, pErrorMsg);
  273. }
  274. }
  275. };
  276. TEST_F(ValidationTest, WhenCorrectThenOK) {
  277. CComPtr<IDxcBlob> pProgram;
  278. CompileSource("float4 main() : SV_Target { return 1; }", "ps_5_0", &pProgram);
  279. CheckValidationMsg(pProgram, nullptr);
  280. }
  281. // Lots of these going on below for simplicity in setting up payloads.
  282. //
  283. // warning C4838: conversion from 'int' to 'const char' requires a narrowing conversion
  284. // warning C4309: 'initializing': truncation of constant value
  285. #pragma warning(disable: 4838)
  286. #pragma warning(disable: 4309)
  287. TEST_F(ValidationTest, WhenMisalignedThenFail) {
  288. // Bitcode size must 4-byte aligned
  289. const char blob[] = {
  290. 'B', 'C',
  291. };
  292. CheckValidationMsg(blob, _countof(blob), "Invalid bitcode size");
  293. }
  294. TEST_F(ValidationTest, WhenEmptyFileThenFail) {
  295. // No blocks after signature.
  296. const char blob[] = {
  297. 'B', 'C', 0xc0, 0xde
  298. };
  299. CheckValidationMsg(blob, _countof(blob), "Malformed IR file");
  300. }
  301. TEST_F(ValidationTest, WhenIncorrectMagicThenFail) {
  302. // Signature isn't 'B', 'C', 0xC0 0xDE
  303. const char blob[] = {
  304. 'B', 'C', 0xc0, 0xdd
  305. };
  306. CheckValidationMsg(blob, _countof(blob), "Invalid bitcode signature");
  307. }
  308. TEST_F(ValidationTest, WhenIncorrectTargetTripleThenFail) {
  309. const char blob[] = {
  310. 'B', 'C', 0xc0, 0xde
  311. };
  312. CheckValidationMsg(blob, _countof(blob), "Malformed IR file");
  313. }
  314. TEST_F(ValidationTest, WhenMultipleModulesThenFail) {
  315. const char blob[] = {
  316. 'B', 'C', 0xc0, 0xde,
  317. 0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
  318. 0x00, 0x00, 0x00, 0x00, // NumWords = 0
  319. 0x08, 0x00, 0x00, 0x00, // End-of-block, padding
  320. // At this point, this is valid bitcode (but missing required DXIL metadata)
  321. // Trigger the case we're looking for now
  322. 0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
  323. };
  324. CheckValidationMsg(blob, _countof(blob), "Unused bits in buffer");
  325. }
  326. TEST_F(ValidationTest, WhenUnexpectedEOFThenFail) {
  327. // Importantly, this is testing the usage of report_fatal_error during deserialization.
  328. const char blob[] = {
  329. 'B', 'C', 0xc0, 0xde,
  330. 0x21, 0x0c, 0x00, 0x00, // Enter sub-block, BlockID = 8, Code Size=3, padding x2
  331. 0x00, 0x00, 0x00, 0x00, // NumWords = 0
  332. };
  333. CheckValidationMsg(blob, _countof(blob), "Invalid record");
  334. }
  335. TEST_F(ValidationTest, WhenUnknownBlocksThenFail) {
  336. const char blob[] = {
  337. 'B', 'C', 0xc0, 0xde, // Signature
  338. 0x31, 0x00, 0x00, 0x00 // Enter sub-block, BlockID != 8
  339. };
  340. CheckValidationMsg(blob, _countof(blob), "Unrecognized block found");
  341. }
  342. TEST_F(ValidationTest, WhenInstrDisallowedThenFail) {
  343. TestCheck(L"val-inst-disallowed.ll");
  344. }
  345. TEST_F(ValidationTest, WhenDepthNotFloatThenFail) {
  346. TestCheck(L"dxil_validation\\IntegerDepth.ll");
  347. }
  348. TEST_F(ValidationTest, BarrierFail) {
  349. TestCheck(L"dxil_validation\\barrier.ll");
  350. }
  351. TEST_F(ValidationTest, CBufferLegacyOutOfBoundFail) {
  352. TestCheck(L"dxil_validation\\cbuffer1.50_legacy.ll");
  353. }
  354. TEST_F(ValidationTest, CBufferOutOfBoundFail) {
  355. TestCheck(L"dxil_validation\\cbuffer1.50.ll");
  356. }
  357. TEST_F(ValidationTest, CsThreadSizeFail) {
  358. TestCheck(L"dxil_validation\\csThreadSize.ll");
  359. }
  360. TEST_F(ValidationTest, DeadLoopFail) {
  361. TestCheck(L"dxil_validation\\deadloop.ll");
  362. }
  363. TEST_F(ValidationTest, EvalFail) {
  364. TestCheck(L"dxil_validation\\Eval.ll");
  365. }
  366. TEST_F(ValidationTest, GetDimCalcLODFail) {
  367. TestCheck(L"dxil_validation\\GetDimCalcLOD.ll");
  368. }
  369. TEST_F(ValidationTest, HsAttributeFail) {
  370. TestCheck(L"dxil_validation\\hsAttribute.ll");
  371. }
  372. TEST_F(ValidationTest, InnerCoverageFail) {
  373. TestCheck(L"dxil_validation\\InnerCoverage.ll");
  374. }
  375. TEST_F(ValidationTest, InterpChangeFail) {
  376. TestCheck(L"dxil_validation\\interpChange.ll");
  377. }
  378. TEST_F(ValidationTest, InterpOnIntFail) {
  379. TestCheck(L"dxil_validation\\interpOnInt.ll");
  380. }
  381. TEST_F(ValidationTest, InvalidSigCompTyFail) {
  382. TestCheck(L"dxil_validation\\invalidSigCompTy.ll");
  383. }
  384. TEST_F(ValidationTest, MultiStream2Fail) {
  385. TestCheck(L"dxil_validation\\multiStream2.ll");
  386. }
  387. TEST_F(ValidationTest, PhiTGSMFail) {
  388. TestCheck(L"dxil_validation\\phiTGSM.ll");
  389. }
  390. TEST_F(ValidationTest, ReducibleFail) {
  391. TestCheck(L"dxil_validation\\reducible.ll");
  392. }
  393. TEST_F(ValidationTest, SampleBiasFail) {
  394. TestCheck(L"dxil_validation\\sampleBias.ll");
  395. }
  396. TEST_F(ValidationTest, SamplerKindFail) {
  397. TestCheck(L"dxil_validation\\samplerKind.ll");
  398. }
  399. TEST_F(ValidationTest, SemaOverlapFail) {
  400. TestCheck(L"dxil_validation\\semaOverlap.ll");
  401. }
  402. TEST_F(ValidationTest, SigOutOfRangeFail) {
  403. TestCheck(L"dxil_validation\\sigOutOfRange.ll");
  404. }
  405. TEST_F(ValidationTest, SigOverlapFail) {
  406. TestCheck(L"dxil_validation\\sigOverlap.ll");
  407. }
  408. TEST_F(ValidationTest, SimpleHs1Fail) {
  409. TestCheck(L"dxil_validation\\SimpleHs1.ll");
  410. }
  411. TEST_F(ValidationTest, SimpleHs3Fail) {
  412. TestCheck(L"dxil_validation\\SimpleHs3.ll");
  413. }
  414. TEST_F(ValidationTest, SimpleHs4Fail) {
  415. TestCheck(L"dxil_validation\\SimpleHs4.ll");
  416. }
  417. TEST_F(ValidationTest, SimpleDs1Fail) {
  418. TestCheck(L"dxil_validation\\SimpleDs1.ll");
  419. }
  420. TEST_F(ValidationTest, SimpleGs1Fail) {
  421. TestCheck(L"dxil_validation\\SimpleGs1.ll");
  422. }
  423. TEST_F(ValidationTest, UavBarrierFail) {
  424. TestCheck(L"dxil_validation\\uavBarrier.ll");
  425. }
  426. TEST_F(ValidationTest, UndefValueFail) {
  427. TestCheck(L"dxil_validation\\UndefValue.ll");
  428. }
  429. TEST_F(ValidationTest, UpdateCounterFail) {
  430. TestCheck(L"dxil_validation\\UpdateCounter.ll");
  431. }
  432. TEST_F(ValidationTest, WhenIncorrectModelThenFail) {
  433. TestCheck(L"val-failures.hlsl");
  434. }
  435. TEST_F(ValidationTest, WhenIncorrectPSThenFail) {
  436. TestCheck(L"val-failures-ps.hlsl");
  437. }
  438. TEST_F(ValidationTest, WhenSmUnknownThenFail) {
  439. RewriteAssemblyCheckMsg("float4 main() : SV_Target { return 1; }", "ps_6_0",
  440. "{!\"ps\", i32 6, i32 0}", "{!\"ps\", i32 1, i32 2}",
  441. "Unknown shader model 'ps_1_2'");
  442. }
  443. TEST_F(ValidationTest, WhenMetaFlagsUsageDeclThenOK) {
  444. RewriteAssemblyCheckMsg(
  445. "uint u; float4 main() : SV_Target { uint64_t n = u; n *= u; return (uint)(n >> 32); }", "ps_6_0",
  446. "1048576", "1048577", // inhibit optimization, which should work fine
  447. nullptr);
  448. }
  449. TEST_F(ValidationTest, GsVertexIDOutOfBound) {
  450. RewriteAssemblyCheckMsg(
  451. L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_6_0",
  452. "dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 0)",
  453. "dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 1)",
  454. "expect VertexID between 0~1, got 1");
  455. }
  456. TEST_F(ValidationTest, StreamIDOutOfBound) {
  457. RewriteAssemblyCheckMsg(
  458. L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_6_0",
  459. "dx.op.emitStream(i32 97, i8 0)",
  460. "dx.op.emitStream(i32 97, i8 1)",
  461. "expect StreamID between 0 , got 1");
  462. }
  463. TEST_F(ValidationTest, SignatureStreamIDForNonGS) {
  464. RewriteAssemblyCheckMsg(
  465. L"..\\CodeGenHLSL\\abs1.hlsl", "ps_6_0",
  466. ", i8 0, i32 1, i8 4, i32 0, i8 0, null}",
  467. ", i8 0, i32 1, i8 4, i32 0, i8 0, !19}\n!19 = !{i32 0, i32 1}",
  468. "expect StreamID for none GS between 0, got 1");
  469. }
  470. TEST_F(ValidationTest, TypedUAVStoreFullMask0) {
  471. RewriteAssemblyCheckMsg(
  472. L"..\\CodeGenHLSL\\uav_typed_store.hlsl", "ps_6_0",
  473. "float 2.000000e+00, i8 15)",
  474. "float 2.000000e+00, i8 undef)",
  475. "Mask of TextureStore must be an immediate constant");
  476. }
  477. TEST_F(ValidationTest, TypedUAVStoreFullMask1) {
  478. RewriteAssemblyCheckMsg(
  479. L"..\\CodeGenHLSL\\uav_typed_store.hlsl", "ps_6_0",
  480. "float 3.000000e+00, i8 15)",
  481. "float 3.000000e+00, i8 undef)",
  482. "Mask of BufferStore must be an immediate constant");
  483. }
  484. TEST_F(ValidationTest, Recursive) {
  485. TestCheck(L"..\\CodeGenHLSL\\recursive.hlsl");
  486. }
  487. TEST_F(ValidationTest, Recursive2) {
  488. TestCheck(L"..\\CodeGenHLSL\\recursive2.hlsl");
  489. }
  490. TEST_F(ValidationTest, ResourceRangeOverlap0) {
  491. RewriteAssemblyCheckMsg(
  492. L"..\\CodeGenHLSL\\resource_overlap.hlsl", "ps_6_0",
  493. "!\"B\", i32 0, i32 1",
  494. "!\"B\", i32 0, i32 0",
  495. "Resource B with base 0 size 1 overlap");
  496. }
  497. TEST_F(ValidationTest, ResourceRangeOverlap1) {
  498. RewriteAssemblyCheckMsg(
  499. L"..\\CodeGenHLSL\\resource_overlap.hlsl", "ps_6_0",
  500. "!\"s1\", i32 0, i32 1",
  501. "!\"s1\", i32 0, i32 0",
  502. "Resource s1 with base 0 size 1 overlap");
  503. }
  504. TEST_F(ValidationTest, ResourceRangeOverlap2) {
  505. RewriteAssemblyCheckMsg(
  506. L"..\\CodeGenHLSL\\resource_overlap.hlsl", "ps_6_0",
  507. "!\"uav2\", i32 0, i32 0",
  508. "!\"uav2\", i32 0, i32 3",
  509. "Resource uav2 with base 3 size 1 overlap");
  510. }
  511. TEST_F(ValidationTest, ResourceRangeOverlap3) {
  512. RewriteAssemblyCheckMsg(
  513. L"..\\CodeGenHLSL\\resource_overlap.hlsl", "ps_6_0",
  514. "!\"srv2\", i32 0, i32 1",
  515. "!\"srv2\", i32 0, i32 0",
  516. "Resource srv2 with base 0 size 1 overlap");
  517. }
  518. TEST_F(ValidationTest, CBufferOverlap0) {
  519. RewriteAssemblyCheckMsg(
  520. L"..\\CodeGenHLSL\\cbufferOffset.hlsl", "ps_6_0",
  521. "i32 6, !\"g2\", i32 3, i32 0",
  522. "i32 6, !\"g2\", i32 3, i32 8",
  523. "CBuffer Foo1 has offset overlaps at 16");
  524. }
  525. TEST_F(ValidationTest, CBufferOverlap1) {
  526. RewriteAssemblyCheckMsg(
  527. L"..\\CodeGenHLSL\\cbufferOffset.hlsl", "ps_6_0",
  528. " = !{i32 32, !",
  529. " = !{i32 16, !",
  530. "CBuffer Foo1 size insufficient for element at offset 16");
  531. }
  532. TEST_F(ValidationTest, ControlFlowHint) {
  533. RewriteAssemblyCheckMsg(
  534. L"..\\CodeGenHLSL\\if1.hlsl", "ps_6_0",
  535. "!\"dx.controlflow.hints\", i32 1",
  536. "!\"dx.controlflow.hints\", i32 5",
  537. "Attribute forcecase only works for switch");
  538. }
  539. TEST_F(ValidationTest, ControlFlowHint1) {
  540. RewriteAssemblyCheckMsg(
  541. L"..\\CodeGenHLSL\\if1.hlsl", "ps_6_0",
  542. "!\"dx.controlflow.hints\", i32 1",
  543. "!\"dx.controlflow.hints\", i32 1, i32 2",
  544. "Can't use branch and flatten attributes together");
  545. }
  546. TEST_F(ValidationTest, ControlFlowHint2) {
  547. RewriteAssemblyCheckMsg(
  548. L"..\\CodeGenHLSL\\if1.hlsl", "ps_6_0",
  549. "!\"dx.controlflow.hints\", i32 1",
  550. "!\"dx.controlflow.hints\", i32 3",
  551. "Invalid control flow hint");
  552. }
  553. TEST_F(ValidationTest, SemanticLength1) {
  554. RewriteAssemblyCheckMsg(
  555. L"..\\CodeGenHLSL\\binary1.hlsl", "ps_6_0",
  556. "!\"C\"",
  557. "!\"\"",
  558. "Semantic length must be at least 1 and at most 64");
  559. }
  560. TEST_F(ValidationTest, SemanticLength64) {
  561. RewriteAssemblyCheckMsg(
  562. L"..\\CodeGenHLSL\\binary1.hlsl", "ps_6_0",
  563. "!\"C\"",
  564. "!\"CSESESESESESESESESESESESESESESESESESESESESESESESESESESESESESESESE\"",
  565. "Semantic length must be at least 1 and at most 64");
  566. }
  567. TEST_F(ValidationTest, PullModelPosition) {
  568. RewriteAssemblyCheckMsg(
  569. L"..\\CodeGenHLSL\\eval.hlsl", "ps_5_0",
  570. "!\"A\", i8 9, i8 0",
  571. "!\"SV_Position\", i8 9, i8 3",
  572. "does not support pull-model evaluation of position");
  573. }
  574. TEST_F(ValidationTest, StructBufGlobalCoherentAndCounter) {
  575. RewriteAssemblyCheckMsg(
  576. L"..\\CodeGenHLSL\\struct_buf1.hlsl", "ps_5_0",
  577. "!\"buf2\", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false",
  578. "!\"buf2\", i32 0, i32 0, i32 1, i32 12, i1 true, i1 true",
  579. "globallycoherent cannot be used with append/consume buffers'buf2'");
  580. }
  581. TEST_F(ValidationTest, StructBufStrideAlign) {
  582. RewriteAssemblyCheckMsg(
  583. L"..\\CodeGenHLSL\\struct_buf1.hlsl", "ps_5_0",
  584. "!7 = !{i32 1, i32 52}",
  585. "!7 = !{i32 1, i32 50}",
  586. "structured buffer element size must be a multiple of 4 bytes (actual size 50 bytes)");
  587. }
  588. TEST_F(ValidationTest, StructBufStrideOutOfBound) {
  589. RewriteAssemblyCheckMsg(
  590. L"..\\CodeGenHLSL\\struct_buf1.hlsl", "ps_5_0",
  591. "!7 = !{i32 1, i32 52}",
  592. "!7 = !{i32 1, i32 2052}",
  593. "structured buffer elements cannot be larger than 2048 bytes (actual size 2052 bytes)");
  594. }
  595. TEST_F(ValidationTest, StructBufLoadCoordinates) {
  596. RewriteAssemblyCheckMsg(
  597. L"..\\CodeGenHLSL\\struct_buf1.hlsl", "ps_5_0",
  598. "bufferLoad.f32(i32 69, %dx.types.Handle %buf1_texture_structbuf, i32 1, i32 8)",
  599. "bufferLoad.f32(i32 69, %dx.types.Handle %buf1_texture_structbuf, i32 1, i32 undef)",
  600. "structured buffer require 2 coordinates");
  601. }
  602. TEST_F(ValidationTest, StructBufStoreCoordinates) {
  603. RewriteAssemblyCheckMsg(
  604. L"..\\CodeGenHLSL\\struct_buf1.hlsl", "ps_5_0",
  605. "bufferStore.f32(i32 70, %dx.types.Handle %buf2_UAV_structbuf, i32 0, i32 0",
  606. "bufferStore.f32(i32 70, %dx.types.Handle %buf2_UAV_structbuf, i32 0, i32 undef",
  607. "structured buffer require 2 coordinates");
  608. }
  609. TEST_F(ValidationTest, TypedBufRetType) {
  610. RewriteAssemblyCheckMsg(
  611. L"..\\CodeGenHLSL\\sample5.hlsl", "ps_5_0",
  612. "%class.Texture2D = type { <4 x float>",
  613. "%class.Texture2D = type { <4 x double>",
  614. "elements of typed buffers and textures must fit in four 32-bit quantities");
  615. }
  616. TEST_F(ValidationTest, VsInputSemantic) {
  617. RewriteAssemblyCheckMsg(
  618. L"..\\CodeGenHLSL\\clip_planes.hlsl", "vs_5_0",
  619. "!\"POSITION\", i8 9, i8 0",
  620. "!\"SV_Target\", i8 9, i8 16",
  621. "Semantic 'SV_Target' is invalid as vs Input");
  622. }
  623. TEST_F(ValidationTest, VsOutputSemantic) {
  624. RewriteAssemblyCheckMsg(
  625. L"..\\CodeGenHLSL\\clip_planes.hlsl", "vs_5_0",
  626. "!\"NORMAL\", i8 9, i8 0",
  627. "!\"SV_Target\", i8 9, i8 16",
  628. "Semantic 'SV_Target' is invalid as vs Output");
  629. }
  630. TEST_F(ValidationTest, HsInputSemantic) {
  631. RewriteAssemblyCheckMsg(
  632. L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
  633. "!\"TEXCOORD\", i8 9, i8 0",
  634. "!\"VertexID\", i8 4, i8 1",
  635. "Semantic 'VertexID' is invalid as hs Input");
  636. }
  637. TEST_F(ValidationTest, HsOutputSemantic) {
  638. RewriteAssemblyCheckMsg(
  639. L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
  640. "!\"TEXCOORD\", i8 9, i8 0",
  641. "!\"VertexID\", i8 4, i8 1",
  642. "Semantic 'VertexID' is invalid as hs Output");
  643. }
  644. TEST_F(ValidationTest, PatchConstSemantic) {
  645. RewriteAssemblyCheckMsg(
  646. L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
  647. "!\"SV_TessFactor\", i8 9, i8 25",
  648. "!\"VertexID\", i8 4, i8 1",
  649. "Semantic 'VertexID' is invalid as hs PatchConstant");
  650. }
  651. TEST_F(ValidationTest, DsInputSemantic) {
  652. RewriteAssemblyCheckMsg(
  653. L"..\\CodeGenHLSL\\SimpleDs1.hlsl", "ds_5_0",
  654. "!\"TEXCOORD\", i8 9, i8 0",
  655. "!\"VertexID\", i8 4, i8 1",
  656. "Semantic 'VertexID' is invalid as ds Input");
  657. }
  658. TEST_F(ValidationTest, DsOutputSemantic) {
  659. RewriteAssemblyCheckMsg(
  660. L"..\\CodeGenHLSL\\SimpleDs1.hlsl", "ds_5_0",
  661. "!\"TEXCOORD\", i8 9, i8 0",
  662. "!\"VertexID\", i8 4, i8 1",
  663. "Semantic 'VertexID' is invalid as ds Output");
  664. }
  665. TEST_F(ValidationTest, GsInputSemantic) {
  666. RewriteAssemblyCheckMsg(
  667. L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_5_0",
  668. "!\"POSSIZE\", i8 9, i8 0",
  669. "!\"VertexID\", i8 4, i8 1",
  670. "Semantic 'VertexID' is invalid as gs Input");
  671. }
  672. TEST_F(ValidationTest, GsOutputSemantic) {
  673. RewriteAssemblyCheckMsg(
  674. L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_5_0",
  675. "!\"TEXCOORD\", i8 9, i8 0",
  676. "!\"VertexID\", i8 4, i8 1",
  677. "Semantic 'VertexID' is invalid as gs Output");
  678. }
  679. TEST_F(ValidationTest, PsInputSemantic) {
  680. RewriteAssemblyCheckMsg(
  681. L"..\\CodeGenHLSL\\abs2.hlsl", "ps_5_0",
  682. "!\"A\", i8 4, i8 0",
  683. "!\"VertexID\", i8 4, i8 1",
  684. "Semantic 'VertexID' is invalid as ps Input");
  685. }
  686. TEST_F(ValidationTest, PsOutputSemantic) {
  687. RewriteAssemblyCheckMsg(
  688. L"..\\CodeGenHLSL\\abs2.hlsl", "ps_5_0",
  689. "!\"SV_Target\", i8 9, i8 16",
  690. "!\"VertexID\", i8 4, i8 1",
  691. "Semantic 'VertexID' is invalid as ps Output");
  692. }
  693. TEST_F(ValidationTest, ArrayOfSVTarget) {
  694. RewriteAssemblyCheckMsg(
  695. L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_5_0",
  696. "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 1",
  697. "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 2",
  698. "Pixel shader output registers are not indexable.");
  699. }
  700. TEST_F(ValidationTest, InfiniteLog) {
  701. RewriteAssemblyCheckMsg(
  702. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  703. "op.unary.f32(i32 22, float %3)",
  704. "op.unary.f32(i32 22, float 0x7FF0000000000000)",
  705. "No indefinite logarithm");
  706. }
  707. TEST_F(ValidationTest, InfiniteAsin) {
  708. RewriteAssemblyCheckMsg(
  709. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  710. "op.unary.f32(i32 16, float %3)",
  711. "op.unary.f32(i32 16, float 0x7FF0000000000000)",
  712. "No indefinite arcsine");
  713. }
  714. TEST_F(ValidationTest, InfiniteAcos) {
  715. RewriteAssemblyCheckMsg(
  716. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  717. "op.unary.f32(i32 15, float %3)",
  718. "op.unary.f32(i32 15, float 0x7FF0000000000000)",
  719. "No indefinite arccosine");
  720. }
  721. TEST_F(ValidationTest, InfiniteDdxDdy) {
  722. RewriteAssemblyCheckMsg(
  723. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  724. "op.unary.f32(i32 86, float %3)",
  725. "op.unary.f32(i32 86, float 0x7FF0000000000000)",
  726. "No indefinite derivative calculation");
  727. }
  728. TEST_F(ValidationTest, IDivByZero) {
  729. RewriteAssemblyCheckMsg(
  730. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  731. "sdiv i32 %8, %9",
  732. "sdiv i32 %8, 0",
  733. "No signed integer division by zero");
  734. }
  735. TEST_F(ValidationTest, UDivByZero) {
  736. RewriteAssemblyCheckMsg(
  737. L"..\\CodeGenHLSL\\intrinsic_val_imm.hlsl", "ps_5_0",
  738. "udiv i32 %5, %6",
  739. "udiv i32 %5, 0",
  740. "No unsigned integer division by zero");
  741. }
  742. TEST_F(ValidationTest, UnusedMetadata) {
  743. RewriteAssemblyCheckMsg(L"..\\CodeGenHLSL\\loop2.hlsl", "ps_5_0",
  744. ", !llvm.loop ",
  745. ", !llvm.loop2 ",
  746. "All metadata must be used by dxil");
  747. }
  748. TEST_F(ValidationTest, WhenWaveAffectsGradientThenFail) {
  749. TestCheck(L"val-wave-failures-ps.hlsl");
  750. }
  751. TEST_F(ValidationTest, WhenMetaFlagsUsageThenFail) {
  752. RewriteAssemblyCheckMsg(
  753. "uint u; float4 main() : SV_Target { uint64_t n = u; n *= u; return (uint)(n >> 32); }", "ps_6_0",
  754. "1048576", "0", // remove the int64 flag
  755. "Flags must match usage");
  756. }
  757. TEST_F(ValidationTest, StorePatchControlNotInPatchConstantFunction) {
  758. RewriteAssemblyCheckMsg(
  759. "struct PSSceneIn \
  760. { \
  761. float4 pos : SV_Position; \
  762. float2 tex : TEXCOORD0; \
  763. float3 norm : NORMAL; \
  764. }; \
  765. \
  766. struct HSPerVertexData \
  767. { \
  768. PSSceneIn v; \
  769. }; \
  770. struct HSPerPatchData \
  771. { \
  772. float edges[ 3 ] : SV_TessFactor; \
  773. float inside : SV_InsideTessFactor; \
  774. }; \
  775. HSPerPatchData HSPerPatchFunc( const InputPatch< PSSceneIn, 3 > points, \
  776. OutputPatch<HSPerVertexData, 3> outpoints) \
  777. { \
  778. HSPerPatchData d; \
  779. \
  780. d.edges[ 0 ] = points[0].tex.x + outpoints[0].v.tex.x; \
  781. d.edges[ 1 ] = 1; \
  782. d.edges[ 2 ] = 1; \
  783. d.inside = 1; \
  784. \
  785. return d; \
  786. }\
  787. [domain(\"tri\")]\
  788. [partitioning(\"fractional_odd\")]\
  789. [outputtopology(\"triangle_cw\")]\
  790. [patchconstantfunc(\"HSPerPatchFunc\")]\
  791. [outputcontrolpoints(3)]\
  792. HSPerVertexData main( const uint id : SV_OutputControlPointID,\
  793. const InputPatch< PSSceneIn, 3 > points )\
  794. {\
  795. HSPerVertexData v;\
  796. \
  797. v.v = points[ id ];\
  798. \
  799. return v;\
  800. }\
  801. ",
  802. "hs_6_0",
  803. "dx.op.storeOutput.f32(i32 5",
  804. "dx.op.storePatchConstant.f32(i32 109",
  805. "opcode 'StorePatchConstant' should only used in 'PatchConstant function'");
  806. }
  807. TEST_F(ValidationTest, LoadOutputControlPointNotInPatchConstantFunction) {
  808. RewriteAssemblyCheckMsg(
  809. "struct PSSceneIn \
  810. { \
  811. float4 pos : SV_Position; \
  812. float2 tex : TEXCOORD0; \
  813. float3 norm : NORMAL; \
  814. }; \
  815. \
  816. struct HSPerVertexData \
  817. { \
  818. PSSceneIn v; \
  819. }; \
  820. struct HSPerPatchData \
  821. { \
  822. float edges[ 3 ] : SV_TessFactor; \
  823. float inside : SV_InsideTessFactor; \
  824. }; \
  825. HSPerPatchData HSPerPatchFunc( const InputPatch< PSSceneIn, 3 > points, \
  826. OutputPatch<HSPerVertexData, 3> outpoints) \
  827. { \
  828. HSPerPatchData d; \
  829. \
  830. d.edges[ 0 ] = points[0].tex.x + outpoints[0].v.tex.x; \
  831. d.edges[ 1 ] = 1; \
  832. d.edges[ 2 ] = 1; \
  833. d.inside = 1; \
  834. \
  835. return d; \
  836. }\
  837. [domain(\"tri\")]\
  838. [partitioning(\"fractional_odd\")]\
  839. [outputtopology(\"triangle_cw\")]\
  840. [patchconstantfunc(\"HSPerPatchFunc\")]\
  841. [outputcontrolpoints(3)]\
  842. HSPerVertexData main( const uint id : SV_OutputControlPointID,\
  843. const InputPatch< PSSceneIn, 3 > points )\
  844. {\
  845. HSPerVertexData v;\
  846. \
  847. v.v = points[ id ];\
  848. \
  849. return v;\
  850. }\
  851. ",
  852. "hs_6_0",
  853. "dx.op.loadInput.f32(i32 4",
  854. "dx.op.loadOutputControlPoint.f32(i32 106",
  855. "opcode 'LoadOutputControlPoint' should only used in 'PatchConstant function'");
  856. }
  857. TEST_F(ValidationTest, OutputControlPointIDInPatchConstantFunction) {
  858. RewriteAssemblyCheckMsg(
  859. "struct PSSceneIn \
  860. { \
  861. float4 pos : SV_Position; \
  862. float2 tex : TEXCOORD0; \
  863. float3 norm : NORMAL; \
  864. }; \
  865. \
  866. struct HSPerVertexData \
  867. { \
  868. PSSceneIn v; \
  869. }; \
  870. struct HSPerPatchData \
  871. { \
  872. float edges[ 3 ] : SV_TessFactor; \
  873. float inside : SV_InsideTessFactor; \
  874. }; \
  875. HSPerPatchData HSPerPatchFunc( const InputPatch< PSSceneIn, 3 > points, \
  876. OutputPatch<HSPerVertexData, 3> outpoints) \
  877. { \
  878. HSPerPatchData d; \
  879. \
  880. d.edges[ 0 ] = points[0].tex.x + outpoints[0].v.tex.x; \
  881. d.edges[ 1 ] = 1; \
  882. d.edges[ 2 ] = 1; \
  883. d.inside = 1; \
  884. \
  885. return d; \
  886. }\
  887. [domain(\"tri\")]\
  888. [partitioning(\"fractional_odd\")]\
  889. [outputtopology(\"triangle_cw\")]\
  890. [patchconstantfunc(\"HSPerPatchFunc\")]\
  891. [outputcontrolpoints(3)]\
  892. HSPerVertexData main( const uint id : SV_OutputControlPointID,\
  893. const InputPatch< PSSceneIn, 3 > points )\
  894. {\
  895. HSPerVertexData v;\
  896. \
  897. v.v = points[ id ];\
  898. \
  899. return v;\
  900. }\
  901. ",
  902. "hs_6_0",
  903. "ret void",
  904. "call i32 @dx.op.outputControlPointID.i32(i32 110)\n ret void",
  905. "opcode 'OutputControlPointID' should only used in 'hull function'");
  906. }
  907. // TODO: reject non-zero padding