val_composites_test.cpp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029
  1. // Copyright (c) 2017 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <sstream>
  15. #include <string>
  16. #include "gmock/gmock.h"
  17. #include "test/unit_spirv.h"
  18. #include "test/val/val_code_generator.h"
  19. #include "test/val/val_fixtures.h"
  20. namespace spvtools {
  21. namespace val {
  22. namespace {
  23. using ::testing::HasSubstr;
  24. using ::testing::Not;
  25. using ::testing::Values;
  26. using ValidateComposites = spvtest::ValidateBase<bool>;
  27. std::string GenerateShaderCode(
  28. const std::string& body,
  29. const std::string& capabilities_and_extensions = "",
  30. const std::string& execution_model = "Fragment") {
  31. std::ostringstream ss;
  32. ss << R"(
  33. OpCapability Shader
  34. OpCapability Float64
  35. )";
  36. ss << capabilities_and_extensions;
  37. ss << "OpMemoryModel Logical GLSL450\n";
  38. ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
  39. if (execution_model == "Fragment") {
  40. ss << "OpExecutionMode %main OriginUpperLeft\n";
  41. }
  42. ss << R"(
  43. %void = OpTypeVoid
  44. %func = OpTypeFunction %void
  45. %bool = OpTypeBool
  46. %f32 = OpTypeFloat 32
  47. %f64 = OpTypeFloat 64
  48. %u32 = OpTypeInt 32 0
  49. %s32 = OpTypeInt 32 1
  50. %f32vec2 = OpTypeVector %f32 2
  51. %f32vec3 = OpTypeVector %f32 3
  52. %f32vec4 = OpTypeVector %f32 4
  53. %f64vec2 = OpTypeVector %f64 2
  54. %u32vec2 = OpTypeVector %u32 2
  55. %u32vec4 = OpTypeVector %u32 4
  56. %f64mat22 = OpTypeMatrix %f64vec2 2
  57. %f32mat22 = OpTypeMatrix %f32vec2 2
  58. %f32mat23 = OpTypeMatrix %f32vec2 3
  59. %f32mat32 = OpTypeMatrix %f32vec3 2
  60. %f32_0 = OpConstant %f32 0
  61. %f32_1 = OpConstant %f32 1
  62. %f32_2 = OpConstant %f32 2
  63. %f32_3 = OpConstant %f32 3
  64. %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
  65. %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
  66. %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
  67. %u32_0 = OpConstant %u32 0
  68. %u32_1 = OpConstant %u32 1
  69. %u32_2 = OpConstant %u32 2
  70. %u32_3 = OpConstant %u32 3
  71. %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
  72. %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
  73. %f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
  74. %f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
  75. %f32vec2arr3 = OpTypeArray %f32vec2 %u32_3
  76. %f32vec2arr2 = OpTypeArray %f32vec2 %u32_2
  77. %f32u32struct = OpTypeStruct %f32 %u32
  78. %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2arr2 %f32u32struct
  79. %ptr_big_struct = OpTypePointer Uniform %big_struct
  80. %var_big_struct = OpVariable %ptr_big_struct Uniform
  81. %main = OpFunction %void None %func
  82. %main_entry = OpLabel
  83. )";
  84. ss << body;
  85. ss << R"(
  86. OpReturn
  87. OpFunctionEnd)";
  88. return ss.str();
  89. }
  90. // Returns header for legacy tests taken from val_id_test.cpp.
  91. std::string GetHeaderForTestsFromValId() {
  92. return R"(
  93. OpCapability Shader
  94. OpCapability Linkage
  95. OpCapability Addresses
  96. OpCapability Pipes
  97. OpCapability LiteralSampler
  98. OpCapability DeviceEnqueue
  99. OpCapability Vector16
  100. OpCapability Int8
  101. OpCapability Int16
  102. OpCapability Int64
  103. OpCapability Float64
  104. OpMemoryModel Logical GLSL450
  105. %void = OpTypeVoid
  106. %void_f = OpTypeFunction %void
  107. %int = OpTypeInt 32 0
  108. %float = OpTypeFloat 32
  109. %v3float = OpTypeVector %float 3
  110. %mat4x3 = OpTypeMatrix %v3float 4
  111. %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
  112. %_ptr_Private_float = OpTypePointer Private %float
  113. %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
  114. %my_float_var = OpVariable %_ptr_Private_float Private
  115. %_ptr_Function_float = OpTypePointer Function %float
  116. %int_0 = OpConstant %int 0
  117. %int_1 = OpConstant %int 1
  118. %int_2 = OpConstant %int 2
  119. %int_3 = OpConstant %int 3
  120. %int_5 = OpConstant %int 5
  121. ; Making the following nested structures.
  122. ;
  123. ; struct S {
  124. ; bool b;
  125. ; vec4 v[5];
  126. ; int i;
  127. ; mat4x3 m[5];
  128. ; }
  129. ; uniform blockName {
  130. ; S s;
  131. ; bool cond;
  132. ; }
  133. %f32arr = OpTypeRuntimeArray %float
  134. %v4float = OpTypeVector %float 4
  135. %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
  136. %array5_vec4 = OpTypeArray %v4float %int_5
  137. %_ptr_Uniform_float = OpTypePointer Uniform %float
  138. %_ptr_Function_vec4 = OpTypePointer Function %v4float
  139. %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
  140. %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
  141. %struct_blockName = OpTypeStruct %struct_s %int
  142. %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
  143. %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
  144. %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
  145. %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
  146. %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
  147. %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
  148. %spec_int = OpSpecConstant %int 2
  149. %func = OpFunction %void None %void_f
  150. %my_label = OpLabel
  151. )";
  152. }
  153. TEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
  154. const std::string body = R"(
  155. %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
  156. )";
  157. CompileSuccessfully(GenerateShaderCode(body).c_str());
  158. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  159. }
  160. TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
  161. const std::string body = R"(
  162. %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
  163. )";
  164. CompileSuccessfully(GenerateShaderCode(body).c_str());
  165. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  166. EXPECT_THAT(getDiagnosticString(),
  167. HasSubstr("Expected Result Type to be a scalar type"));
  168. }
  169. TEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
  170. const std::string body = R"(
  171. %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
  172. )";
  173. CompileSuccessfully(GenerateShaderCode(body).c_str());
  174. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  175. EXPECT_THAT(getDiagnosticString(),
  176. HasSubstr("Expected Vector type to be OpTypeVector"));
  177. }
  178. TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
  179. const std::string body = R"(
  180. %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
  181. )";
  182. CompileSuccessfully(GenerateShaderCode(body).c_str());
  183. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  184. EXPECT_THAT(
  185. getDiagnosticString(),
  186. HasSubstr("Expected Vector component type to be equal to Result Type"));
  187. }
  188. TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
  189. const std::string body = R"(
  190. %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
  191. )";
  192. CompileSuccessfully(GenerateShaderCode(body).c_str());
  193. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  194. EXPECT_THAT(getDiagnosticString(),
  195. HasSubstr("Expected Index to be int scalar"));
  196. }
  197. TEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
  198. const std::string body = R"(
  199. %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
  200. )";
  201. CompileSuccessfully(GenerateShaderCode(body).c_str());
  202. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  203. }
  204. TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
  205. const std::string body = R"(
  206. %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
  207. )";
  208. CompileSuccessfully(GenerateShaderCode(body).c_str());
  209. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  210. EXPECT_THAT(getDiagnosticString(),
  211. HasSubstr("Expected Result Type to be OpTypeVector"));
  212. }
  213. TEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
  214. const std::string body = R"(
  215. %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
  216. )";
  217. CompileSuccessfully(GenerateShaderCode(body).c_str());
  218. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  219. EXPECT_THAT(getDiagnosticString(),
  220. HasSubstr("Expected Vector type to be equal to Result Type"));
  221. }
  222. TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
  223. const std::string body = R"(
  224. %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
  225. )";
  226. CompileSuccessfully(GenerateShaderCode(body).c_str());
  227. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  228. EXPECT_THAT(getDiagnosticString(),
  229. HasSubstr("Expected Component type to be equal to Result Type "
  230. "component type"));
  231. }
  232. TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
  233. const std::string body = R"(
  234. %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
  235. )";
  236. CompileSuccessfully(GenerateShaderCode(body).c_str());
  237. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  238. EXPECT_THAT(getDiagnosticString(),
  239. HasSubstr("Expected Index to be int scalar"));
  240. }
  241. TEST_F(ValidateComposites, CompositeConstructNotComposite) {
  242. const std::string body = R"(
  243. %val1 = OpCompositeConstruct %f32 %f32_1
  244. )";
  245. CompileSuccessfully(GenerateShaderCode(body).c_str());
  246. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  247. EXPECT_THAT(getDiagnosticString(),
  248. HasSubstr("Expected Result Type to be a composite type"));
  249. }
  250. TEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
  251. const std::string body = R"(
  252. %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
  253. %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
  254. %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
  255. %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
  256. )";
  257. CompileSuccessfully(GenerateShaderCode(body).c_str());
  258. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  259. }
  260. TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
  261. const std::string body = R"(
  262. %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
  263. )";
  264. CompileSuccessfully(GenerateShaderCode(body).c_str());
  265. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  266. EXPECT_THAT(getDiagnosticString(),
  267. HasSubstr("Expected number of constituents to be at least 2"));
  268. }
  269. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
  270. const std::string body = R"(
  271. %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
  272. )";
  273. CompileSuccessfully(GenerateShaderCode(body).c_str());
  274. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  275. EXPECT_THAT(getDiagnosticString(),
  276. HasSubstr("Operand '5[%float]' cannot be a "
  277. "type"));
  278. }
  279. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
  280. const std::string body = R"(
  281. %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01
  282. )";
  283. CompileSuccessfully(GenerateShaderCode(body).c_str());
  284. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  285. EXPECT_THAT(
  286. getDiagnosticString(),
  287. HasSubstr("Expected Constituents to be scalars or vectors of the same "
  288. "type as Result Type components"));
  289. }
  290. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) {
  291. const std::string body = R"(
  292. %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0
  293. )";
  294. CompileSuccessfully(GenerateShaderCode(body).c_str());
  295. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  296. EXPECT_THAT(
  297. getDiagnosticString(),
  298. HasSubstr("Expected Constituents to be scalars or vectors of the same "
  299. "type as Result Type components"));
  300. }
  301. TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) {
  302. const std::string body = R"(
  303. %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0
  304. )";
  305. CompileSuccessfully(GenerateShaderCode(body).c_str());
  306. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  307. EXPECT_THAT(
  308. getDiagnosticString(),
  309. HasSubstr("Expected total number of given components to be equal to the "
  310. "size of Result Type vector"));
  311. }
  312. TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) {
  313. const std::string body = R"(
  314. %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0
  315. )";
  316. CompileSuccessfully(GenerateShaderCode(body).c_str());
  317. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  318. EXPECT_THAT(
  319. getDiagnosticString(),
  320. HasSubstr("Expected total number of given components to be equal to the "
  321. "size of Result Type vector"));
  322. }
  323. TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) {
  324. const std::string body = R"(
  325. %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12
  326. %val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
  327. )";
  328. CompileSuccessfully(GenerateShaderCode(body).c_str());
  329. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  330. }
  331. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) {
  332. const std::string body = R"(
  333. %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12
  334. )";
  335. CompileSuccessfully(GenerateShaderCode(body).c_str());
  336. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  337. EXPECT_THAT(
  338. getDiagnosticString(),
  339. HasSubstr("Expected total number of Constituents to be equal to the "
  340. "number of columns of Result Type matrix"));
  341. }
  342. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) {
  343. const std::string body = R"(
  344. %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12
  345. )";
  346. CompileSuccessfully(GenerateShaderCode(body).c_str());
  347. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  348. EXPECT_THAT(
  349. getDiagnosticString(),
  350. HasSubstr("Expected total number of Constituents to be equal to the "
  351. "number of columns of Result Type matrix"));
  352. }
  353. TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) {
  354. const std::string body = R"(
  355. %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01
  356. )";
  357. CompileSuccessfully(GenerateShaderCode(body).c_str());
  358. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  359. EXPECT_THAT(
  360. getDiagnosticString(),
  361. HasSubstr("Expected Constituent type to be equal to the column type "
  362. "Result Type matrix"));
  363. }
  364. TEST_F(ValidateComposites, CompositeConstructArraySuccess) {
  365. const std::string body = R"(
  366. %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
  367. )";
  368. CompileSuccessfully(GenerateShaderCode(body).c_str());
  369. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  370. }
  371. TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) {
  372. const std::string body = R"(
  373. %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12
  374. )";
  375. CompileSuccessfully(GenerateShaderCode(body).c_str());
  376. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  377. EXPECT_THAT(
  378. getDiagnosticString(),
  379. HasSubstr("Expected total number of Constituents to be equal to the "
  380. "number of elements of Result Type array"));
  381. }
  382. TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) {
  383. const std::string body = R"(
  384. %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12
  385. )";
  386. CompileSuccessfully(GenerateShaderCode(body).c_str());
  387. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  388. EXPECT_THAT(
  389. getDiagnosticString(),
  390. HasSubstr("Expected total number of Constituents to be equal to the "
  391. "number of elements of Result Type array"));
  392. }
  393. TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) {
  394. const std::string body = R"(
  395. %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12
  396. )";
  397. CompileSuccessfully(GenerateShaderCode(body).c_str());
  398. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  399. EXPECT_THAT(
  400. getDiagnosticString(),
  401. HasSubstr("Expected Constituent type to be equal to the column type "
  402. "Result Type array"));
  403. }
  404. TEST_F(ValidateComposites, CompositeConstructStructSuccess) {
  405. const std::string body = R"(
  406. %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1
  407. )";
  408. CompileSuccessfully(GenerateShaderCode(body).c_str());
  409. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  410. }
  411. TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) {
  412. const std::string body = R"(
  413. %val1 = OpCompositeConstruct %f32u32struct %f32_0
  414. )";
  415. CompileSuccessfully(GenerateShaderCode(body).c_str());
  416. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  417. EXPECT_THAT(
  418. getDiagnosticString(),
  419. HasSubstr("Expected total number of Constituents to be equal to the "
  420. "number of members of Result Type struct"));
  421. }
  422. TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) {
  423. const std::string body = R"(
  424. %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1
  425. )";
  426. CompileSuccessfully(GenerateShaderCode(body).c_str());
  427. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  428. EXPECT_THAT(
  429. getDiagnosticString(),
  430. HasSubstr("Expected total number of Constituents to be equal to the "
  431. "number of members of Result Type struct"));
  432. }
  433. TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) {
  434. const std::string body = R"(
  435. %val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1
  436. )";
  437. CompileSuccessfully(GenerateShaderCode(body).c_str());
  438. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  439. EXPECT_THAT(getDiagnosticString(),
  440. HasSubstr("Expected Constituent type to be equal to the "
  441. "corresponding member type of Result Type struct"));
  442. }
  443. TEST_F(ValidateComposites, CopyObjectSuccess) {
  444. const std::string body = R"(
  445. %val1 = OpCopyObject %f32 %f32_0
  446. %val2 = OpCopyObject %f32vec4 %f32vec4_0123
  447. )";
  448. CompileSuccessfully(GenerateShaderCode(body).c_str());
  449. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  450. }
  451. TEST_F(ValidateComposites, CopyObjectResultTypeNotType) {
  452. const std::string body = R"(
  453. %val1 = OpCopyObject %f32_0 %f32_0
  454. )";
  455. CompileSuccessfully(GenerateShaderCode(body).c_str());
  456. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  457. EXPECT_THAT(getDiagnosticString(),
  458. HasSubstr("ID '19[%float_0]' is not a type id"));
  459. }
  460. TEST_F(ValidateComposites, CopyObjectWrongOperandType) {
  461. const std::string body = R"(
  462. %val1 = OpCopyObject %f32 %u32_0
  463. )";
  464. CompileSuccessfully(GenerateShaderCode(body).c_str());
  465. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  466. EXPECT_THAT(
  467. getDiagnosticString(),
  468. HasSubstr("Expected Result Type and Operand type to be the same"));
  469. }
  470. TEST_F(ValidateComposites, TransposeSuccess) {
  471. const std::string body = R"(
  472. %val1 = OpTranspose %f32mat32 %f32mat23_121212
  473. %val2 = OpTranspose %f32mat22 %f32mat22_1212
  474. )";
  475. CompileSuccessfully(GenerateShaderCode(body).c_str());
  476. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  477. }
  478. TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) {
  479. const std::string body = R"(
  480. %val1 = OpTranspose %f32vec4 %f32mat22_1212
  481. )";
  482. CompileSuccessfully(GenerateShaderCode(body).c_str());
  483. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  484. EXPECT_THAT(getDiagnosticString(),
  485. HasSubstr("Expected Result Type to be a matrix type"));
  486. }
  487. TEST_F(ValidateComposites, TransposeDifferentComponentTypes) {
  488. const std::string body = R"(
  489. %val1 = OpTranspose %f64mat22 %f32mat22_1212
  490. )";
  491. CompileSuccessfully(GenerateShaderCode(body).c_str());
  492. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  493. EXPECT_THAT(
  494. getDiagnosticString(),
  495. HasSubstr("Expected component types of Matrix and Result Type to be "
  496. "identical"));
  497. }
  498. TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) {
  499. const std::string body = R"(
  500. %val1 = OpTranspose %f32mat23 %f32mat22_1212
  501. )";
  502. CompileSuccessfully(GenerateShaderCode(body).c_str());
  503. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  504. EXPECT_THAT(getDiagnosticString(),
  505. HasSubstr("Expected number of columns and the column size "
  506. "of Matrix to be the reverse of those of Result Type"));
  507. }
  508. TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) {
  509. const std::string body = R"(
  510. %val1 = OpTranspose %f32mat32 %f32mat22_1212
  511. )";
  512. CompileSuccessfully(GenerateShaderCode(body).c_str());
  513. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  514. EXPECT_THAT(getDiagnosticString(),
  515. HasSubstr("Expected number of columns and the column size "
  516. "of Matrix to be the reverse of those of Result Type"));
  517. }
  518. TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) {
  519. const std::string body = R"(
  520. %val1 = OpTranspose %f32mat23 %f32mat23_121212
  521. )";
  522. CompileSuccessfully(GenerateShaderCode(body).c_str());
  523. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  524. EXPECT_THAT(getDiagnosticString(),
  525. HasSubstr("Expected number of columns and the column size "
  526. "of Matrix to be the reverse of those of Result Type"));
  527. }
  528. TEST_F(ValidateComposites, CompositeExtractSuccess) {
  529. const std::string body = R"(
  530. %val1 = OpCompositeExtract %f32 %f32vec4_0123 1
  531. %val2 = OpCompositeExtract %u32 %u32vec4_0123 0
  532. %val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1
  533. %val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0
  534. %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
  535. %val5 = OpCompositeExtract %f32vec2 %array 2
  536. %val6 = OpCompositeExtract %f32 %array 2 1
  537. %struct = OpLoad %big_struct %var_big_struct
  538. %val7 = OpCompositeExtract %f32 %struct 0
  539. %val8 = OpCompositeExtract %f32vec4 %struct 1
  540. %val9 = OpCompositeExtract %f32 %struct 1 2
  541. %val10 = OpCompositeExtract %f32mat23 %struct 2
  542. %val11 = OpCompositeExtract %f32vec2 %struct 2 2
  543. %val12 = OpCompositeExtract %f32 %struct 2 2 1
  544. %val13 = OpCompositeExtract %f32vec2 %struct 3 2
  545. %val14 = OpCompositeExtract %f32 %struct 3 2 1
  546. %val15 = OpCompositeExtract %f32vec2 %struct 4 1
  547. %val16 = OpCompositeExtract %f32 %struct 4 0 1
  548. %val17 = OpCompositeExtract %f32 %struct 5 0
  549. %val18 = OpCompositeExtract %u32 %struct 5 1
  550. )";
  551. CompileSuccessfully(GenerateShaderCode(body));
  552. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  553. }
  554. TEST_F(ValidateComposites, CompositeExtractNotObject) {
  555. const std::string body = R"(
  556. %val1 = OpCompositeExtract %f32 %f32vec4 1
  557. )";
  558. CompileSuccessfully(GenerateShaderCode(body));
  559. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  560. EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '11[%v4float]' cannot "
  561. "be a type"));
  562. }
  563. TEST_F(ValidateComposites, CompositeExtractNotComposite) {
  564. const std::string body = R"(
  565. %val1 = OpCompositeExtract %f32 %f32_1 0
  566. )";
  567. CompileSuccessfully(GenerateShaderCode(body));
  568. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  569. EXPECT_THAT(getDiagnosticString(),
  570. HasSubstr("Reached non-composite type while indexes still remain "
  571. "to be traversed."));
  572. }
  573. TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) {
  574. const std::string body = R"(
  575. %val1 = OpCompositeExtract %f32 %f32vec4_0123 4
  576. )";
  577. CompileSuccessfully(GenerateShaderCode(body));
  578. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  579. EXPECT_THAT(getDiagnosticString(),
  580. HasSubstr("Vector access is out of bounds, "
  581. "vector size is 4, but access index is 4"));
  582. }
  583. TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) {
  584. const std::string body = R"(
  585. %val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1
  586. )";
  587. CompileSuccessfully(GenerateShaderCode(body));
  588. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  589. EXPECT_THAT(getDiagnosticString(),
  590. HasSubstr("Matrix access is out of bounds, "
  591. "matrix has 3 columns, but access index is 3"));
  592. }
  593. TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) {
  594. const std::string body = R"(
  595. %val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5
  596. )";
  597. CompileSuccessfully(GenerateShaderCode(body));
  598. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  599. EXPECT_THAT(getDiagnosticString(),
  600. HasSubstr("Vector access is out of bounds, "
  601. "vector size is 2, but access index is 5"));
  602. }
  603. TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) {
  604. const std::string body = R"(
  605. %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
  606. %val1 = OpCompositeExtract %f32vec2 %array 3
  607. )";
  608. CompileSuccessfully(GenerateShaderCode(body));
  609. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  610. EXPECT_THAT(getDiagnosticString(),
  611. HasSubstr("Array access is out of bounds, "
  612. "array size is 3, but access index is 3"));
  613. }
  614. TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) {
  615. const std::string body = R"(
  616. %struct = OpLoad %big_struct %var_big_struct
  617. %val1 = OpCompositeExtract %f32 %struct 6
  618. )";
  619. CompileSuccessfully(GenerateShaderCode(body));
  620. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  621. EXPECT_THAT(getDiagnosticString(),
  622. HasSubstr("Index is out of bounds, can not find index 6 in the "
  623. "structure <id> '37'. This structure has 6 members. "
  624. "Largest valid index is 5."));
  625. }
  626. TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) {
  627. const std::string body = R"(
  628. %struct = OpLoad %big_struct %var_big_struct
  629. %val1 = OpCompositeExtract %f32 %struct 3 1 5
  630. )";
  631. CompileSuccessfully(GenerateShaderCode(body));
  632. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  633. EXPECT_THAT(getDiagnosticString(),
  634. HasSubstr("Vector access is out of bounds, "
  635. "vector size is 2, but access index is 5"));
  636. }
  637. TEST_F(ValidateComposites, CompositeExtractTooManyIndices) {
  638. const std::string body = R"(
  639. %struct = OpLoad %big_struct %var_big_struct
  640. %val1 = OpCompositeExtract %f32 %struct 3 1 1 2
  641. )";
  642. CompileSuccessfully(GenerateShaderCode(body));
  643. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  644. EXPECT_THAT(getDiagnosticString(),
  645. HasSubstr("Reached non-composite type while "
  646. "indexes still remain to be traversed."));
  647. }
  648. TEST_F(ValidateComposites, CompositeExtractNoIndices) {
  649. const std::string body = R"(
  650. %struct = OpLoad %big_struct %var_big_struct
  651. %val1 = OpCompositeExtract %big_struct %struct
  652. )";
  653. CompileSuccessfully(GenerateShaderCode(body));
  654. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  655. EXPECT_THAT(getDiagnosticString(),
  656. HasSubstr("Expected at least one index to OpCompositeExtract"));
  657. }
  658. TEST_F(ValidateComposites, CompositeExtractWrongType1) {
  659. const std::string body = R"(
  660. %struct = OpLoad %big_struct %var_big_struct
  661. %val1 = OpCompositeExtract %f32vec2 %struct 3 1 1
  662. )";
  663. CompileSuccessfully(GenerateShaderCode(body));
  664. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  665. EXPECT_THAT(
  666. getDiagnosticString(),
  667. HasSubstr(
  668. "Result type (OpTypeVector) does not match the type that results "
  669. "from indexing into the composite (OpTypeFloat)."));
  670. }
  671. TEST_F(ValidateComposites, CompositeExtractWrongType2) {
  672. const std::string body = R"(
  673. %struct = OpLoad %big_struct %var_big_struct
  674. %val1 = OpCompositeExtract %f32 %struct 3 1
  675. )";
  676. CompileSuccessfully(GenerateShaderCode(body));
  677. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  678. EXPECT_THAT(getDiagnosticString(),
  679. HasSubstr("Result type (OpTypeFloat) does not match the type "
  680. "that results from indexing into the composite "
  681. "(OpTypeVector)."));
  682. }
  683. TEST_F(ValidateComposites, CompositeExtractWrongType3) {
  684. const std::string body = R"(
  685. %struct = OpLoad %big_struct %var_big_struct
  686. %val1 = OpCompositeExtract %f32 %struct 2 1
  687. )";
  688. CompileSuccessfully(GenerateShaderCode(body));
  689. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  690. EXPECT_THAT(getDiagnosticString(),
  691. HasSubstr("Result type (OpTypeFloat) does not match the type "
  692. "that results from indexing into the composite "
  693. "(OpTypeVector)."));
  694. }
  695. TEST_F(ValidateComposites, CompositeExtractWrongType4) {
  696. const std::string body = R"(
  697. %struct = OpLoad %big_struct %var_big_struct
  698. %val1 = OpCompositeExtract %f32 %struct 4 1
  699. )";
  700. CompileSuccessfully(GenerateShaderCode(body));
  701. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  702. EXPECT_THAT(getDiagnosticString(),
  703. HasSubstr("Result type (OpTypeFloat) does not match the type "
  704. "that results from indexing into the composite "
  705. "(OpTypeVector)."));
  706. }
  707. TEST_F(ValidateComposites, CompositeExtractWrongType5) {
  708. const std::string body = R"(
  709. %struct = OpLoad %big_struct %var_big_struct
  710. %val1 = OpCompositeExtract %f32 %struct 5 1
  711. )";
  712. CompileSuccessfully(GenerateShaderCode(body));
  713. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  714. EXPECT_THAT(
  715. getDiagnosticString(),
  716. HasSubstr(
  717. "Result type (OpTypeFloat) does not match the "
  718. "type that results from indexing into the composite (OpTypeInt)."));
  719. }
  720. TEST_F(ValidateComposites, CompositeInsertSuccess) {
  721. const std::string body = R"(
  722. %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0
  723. %val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0
  724. %val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1
  725. %val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0
  726. %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
  727. %val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2
  728. %val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1
  729. %struct = OpLoad %big_struct %var_big_struct
  730. %val7 = OpCompositeInsert %big_struct %f32_3 %struct 0
  731. %val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1
  732. %val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2
  733. %val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2
  734. %val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2
  735. %val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1
  736. %val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2
  737. %val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1
  738. %val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 1
  739. %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 0 1
  740. %val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0
  741. %val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1
  742. )";
  743. CompileSuccessfully(GenerateShaderCode(body));
  744. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  745. }
  746. TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) {
  747. const std::string body = R"(
  748. %val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0
  749. )";
  750. CompileSuccessfully(GenerateShaderCode(body));
  751. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  752. EXPECT_THAT(getDiagnosticString(),
  753. HasSubstr("The Result Type must be the same as Composite type in "
  754. "OpCompositeInsert yielding Result Id 5."));
  755. }
  756. TEST_F(ValidateComposites, CompositeInsertNotComposite) {
  757. const std::string body = R"(
  758. %val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0
  759. )";
  760. CompileSuccessfully(GenerateShaderCode(body));
  761. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  762. EXPECT_THAT(getDiagnosticString(),
  763. HasSubstr("Reached non-composite type while indexes still remain "
  764. "to be traversed."));
  765. }
  766. TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) {
  767. const std::string body = R"(
  768. %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4
  769. )";
  770. CompileSuccessfully(GenerateShaderCode(body));
  771. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  772. EXPECT_THAT(getDiagnosticString(),
  773. HasSubstr("Vector access is out of bounds, "
  774. "vector size is 4, but access index is 4"));
  775. }
  776. TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) {
  777. const std::string body = R"(
  778. %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1
  779. )";
  780. CompileSuccessfully(GenerateShaderCode(body));
  781. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  782. EXPECT_THAT(getDiagnosticString(),
  783. HasSubstr("Matrix access is out of bounds, "
  784. "matrix has 3 columns, but access index is 3"));
  785. }
  786. TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) {
  787. const std::string body = R"(
  788. %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5
  789. )";
  790. CompileSuccessfully(GenerateShaderCode(body));
  791. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  792. EXPECT_THAT(getDiagnosticString(),
  793. HasSubstr("Vector access is out of bounds, "
  794. "vector size is 2, but access index is 5"));
  795. }
  796. TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) {
  797. const std::string body = R"(
  798. %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
  799. %val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3
  800. )";
  801. CompileSuccessfully(GenerateShaderCode(body));
  802. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  803. EXPECT_THAT(getDiagnosticString(),
  804. HasSubstr("Array access is out of bounds, array "
  805. "size is 3, but access index is 3"));
  806. }
  807. TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) {
  808. const std::string body = R"(
  809. %struct = OpLoad %big_struct %var_big_struct
  810. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 6
  811. )";
  812. CompileSuccessfully(GenerateShaderCode(body));
  813. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  814. EXPECT_THAT(getDiagnosticString(),
  815. HasSubstr("Index is out of bounds, can not find index 6 in the "
  816. "structure <id> '37'. This structure has 6 members. "
  817. "Largest valid index is 5."));
  818. }
  819. TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) {
  820. const std::string body = R"(
  821. %struct = OpLoad %big_struct %var_big_struct
  822. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5
  823. )";
  824. CompileSuccessfully(GenerateShaderCode(body));
  825. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  826. EXPECT_THAT(getDiagnosticString(),
  827. HasSubstr("Vector access is out of bounds, "
  828. "vector size is 2, but access index is 5"));
  829. }
  830. TEST_F(ValidateComposites, CompositeInsertTooManyIndices) {
  831. const std::string body = R"(
  832. %struct = OpLoad %big_struct %var_big_struct
  833. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2
  834. )";
  835. CompileSuccessfully(GenerateShaderCode(body));
  836. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  837. EXPECT_THAT(getDiagnosticString(),
  838. HasSubstr("Reached non-composite type while indexes still remain "
  839. "to be traversed."));
  840. }
  841. TEST_F(ValidateComposites, CompositeInsertWrongType1) {
  842. const std::string body = R"(
  843. %struct = OpLoad %big_struct %var_big_struct
  844. %val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1
  845. )";
  846. CompileSuccessfully(GenerateShaderCode(body));
  847. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  848. EXPECT_THAT(getDiagnosticString(),
  849. HasSubstr("The Object type (OpTypeVector) does not match the "
  850. "type that results from indexing into the Composite "
  851. "(OpTypeFloat)."));
  852. }
  853. TEST_F(ValidateComposites, CompositeInsertWrongType2) {
  854. const std::string body = R"(
  855. %struct = OpLoad %big_struct %var_big_struct
  856. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1
  857. )";
  858. CompileSuccessfully(GenerateShaderCode(body));
  859. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  860. EXPECT_THAT(getDiagnosticString(),
  861. HasSubstr("The Object type (OpTypeFloat) does not match the type "
  862. "that results from indexing into the Composite "
  863. "(OpTypeVector)."));
  864. }
  865. TEST_F(ValidateComposites, CompositeInsertWrongType3) {
  866. const std::string body = R"(
  867. %struct = OpLoad %big_struct %var_big_struct
  868. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1
  869. )";
  870. CompileSuccessfully(GenerateShaderCode(body));
  871. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  872. EXPECT_THAT(getDiagnosticString(),
  873. HasSubstr("The Object type (OpTypeFloat) does not match the type "
  874. "that results from indexing into the Composite "
  875. "(OpTypeVector)."));
  876. }
  877. TEST_F(ValidateComposites, CompositeInsertWrongType4) {
  878. const std::string body = R"(
  879. %struct = OpLoad %big_struct %var_big_struct
  880. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1
  881. )";
  882. CompileSuccessfully(GenerateShaderCode(body));
  883. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  884. EXPECT_THAT(getDiagnosticString(),
  885. HasSubstr("The Object type (OpTypeFloat) does not match the type "
  886. "that results from indexing into the Composite "
  887. "(OpTypeVector)."));
  888. }
  889. TEST_F(ValidateComposites, CompositeInsertWrongType5) {
  890. const std::string body = R"(
  891. %struct = OpLoad %big_struct %var_big_struct
  892. %val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1
  893. )";
  894. CompileSuccessfully(GenerateShaderCode(body));
  895. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  896. EXPECT_THAT(getDiagnosticString(),
  897. HasSubstr("The Object type (OpTypeFloat) does not match the type "
  898. "that results from indexing into the Composite "
  899. "(OpTypeInt)."));
  900. }
  901. // Tests ported from val_id_test.cpp.
  902. // Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes.
  903. TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) {
  904. int depth = 255;
  905. std::string header = GetHeaderForTestsFromValId();
  906. header.erase(header.find("%func"));
  907. std::ostringstream spirv;
  908. spirv << header << std::endl;
  909. // Build nested structures. Struct 'i' contains struct 'i-1'
  910. spirv << "%s_depth_1 = OpTypeStruct %float\n";
  911. for (int i = 2; i <= depth; ++i) {
  912. spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
  913. }
  914. // Define Pointer and Variable to use for CompositeExtract/Insert.
  915. spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
  916. << depth << "\n";
  917. spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
  918. // Function Start
  919. spirv << R"(
  920. %func = OpFunction %void None %void_f
  921. %my_label = OpLabel
  922. )";
  923. // OpCompositeExtract/Insert with 'n' indexes (n = depth)
  924. spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl;
  925. spirv << "%entry = OpCompositeExtract %float %deep";
  926. for (int i = 0; i < depth; ++i) {
  927. spirv << " 0";
  928. }
  929. spirv << std::endl;
  930. spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth
  931. << " %entry %deep";
  932. for (int i = 0; i < depth; ++i) {
  933. spirv << " 0";
  934. }
  935. spirv << std::endl;
  936. // Function end
  937. spirv << R"(
  938. OpReturn
  939. OpFunctionEnd
  940. )";
  941. CompileSuccessfully(spirv.str());
  942. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  943. }
  944. // Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255.
  945. TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) {
  946. std::ostringstream spirv;
  947. spirv << GetHeaderForTestsFromValId() << std::endl;
  948. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  949. spirv << "%entry = OpCompositeExtract %float %matrix";
  950. for (int i = 0; i < 256; ++i) {
  951. spirv << " 0";
  952. }
  953. spirv << R"(
  954. OpReturn
  955. OpFunctionEnd
  956. )";
  957. CompileSuccessfully(spirv.str());
  958. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  959. EXPECT_THAT(getDiagnosticString(),
  960. HasSubstr("The number of indexes in OpCompositeExtract may not "
  961. "exceed 255. Found 256 indexes."));
  962. }
  963. // Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255.
  964. TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) {
  965. std::ostringstream spirv;
  966. spirv << GetHeaderForTestsFromValId() << std::endl;
  967. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  968. spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
  969. for (int i = 0; i < 256; ++i) {
  970. spirv << " 0";
  971. }
  972. spirv << R"(
  973. OpReturn
  974. OpFunctionEnd
  975. )";
  976. CompileSuccessfully(spirv.str());
  977. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  978. EXPECT_THAT(getDiagnosticString(),
  979. HasSubstr("The number of indexes in OpCompositeInsert may not "
  980. "exceed 255. Found 256 indexes."));
  981. }
  982. // Invalid: In OpCompositeInsert, result type must be the same as composite type
  983. TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) {
  984. std::ostringstream spirv;
  985. spirv << GetHeaderForTestsFromValId() << std::endl;
  986. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  987. spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl;
  988. spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1"
  989. << std::endl;
  990. spirv << R"(OpReturn
  991. OpFunctionEnd)";
  992. CompileSuccessfully(spirv.str());
  993. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  994. EXPECT_THAT(getDiagnosticString(),
  995. HasSubstr("The Result Type must be the same as Composite type"));
  996. }
  997. // Invalid: No Indexes were passed to OpCompositeExtract.
  998. TEST_F(ValidateComposites, CompositeExtractNoIndices2) {
  999. std::ostringstream spirv;
  1000. spirv << GetHeaderForTestsFromValId() << std::endl;
  1001. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  1002. spirv << "%float_entry = OpCompositeExtract %mat4x3 %matrix" << std::endl;
  1003. spirv << R"(OpReturn
  1004. OpFunctionEnd)";
  1005. CompileSuccessfully(spirv.str());
  1006. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1007. EXPECT_THAT(
  1008. getDiagnosticString(),
  1009. HasSubstr(
  1010. "Expected at least one index to OpCompositeExtract, zero found"));
  1011. }
  1012. // Invalid: No Indexes were passed to OpCompositeExtract.
  1013. TEST_F(ValidateComposites, CompositeExtractNoIndicesWrongResultType) {
  1014. std::ostringstream spirv;
  1015. spirv << GetHeaderForTestsFromValId() << std::endl;
  1016. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  1017. spirv << "%float_entry = OpCompositeExtract %float %matrix" << std::endl;
  1018. spirv << R"(OpReturn
  1019. OpFunctionEnd)";
  1020. CompileSuccessfully(spirv.str());
  1021. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1022. EXPECT_THAT(
  1023. getDiagnosticString(),
  1024. HasSubstr(
  1025. "Expected at least one index to OpCompositeExtract, zero found"));
  1026. }
  1027. // Invalid: No Indices were passed to OpCompositeInsert, and the type of the
  1028. // Object<id> argument matches the Composite type.
  1029. TEST_F(ValidateComposites, CompositeInsertMissingIndices) {
  1030. std::ostringstream spirv;
  1031. spirv << GetHeaderForTestsFromValId() << std::endl;
  1032. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  1033. spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl;
  1034. spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix";
  1035. spirv << R"(
  1036. OpReturn
  1037. OpFunctionEnd)";
  1038. CompileSuccessfully(spirv.str());
  1039. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1040. EXPECT_THAT(
  1041. getDiagnosticString(),
  1042. HasSubstr(
  1043. "Expected at least one index to OpCompositeInsert, zero found"));
  1044. }
  1045. // Invalid: No Indices were passed to OpCompositeInsert, but the type of the
  1046. // Object<id> argument does not match the Composite type.
  1047. TEST_F(ValidateComposites, CompositeInsertMissingIndices2) {
  1048. std::ostringstream spirv;
  1049. spirv << GetHeaderForTestsFromValId() << std::endl;
  1050. spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
  1051. spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
  1052. spirv << R"(
  1053. OpReturn
  1054. OpFunctionEnd)";
  1055. CompileSuccessfully(spirv.str());
  1056. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1057. EXPECT_THAT(
  1058. getDiagnosticString(),
  1059. HasSubstr(
  1060. "Expected at least one index to OpCompositeInsert, zero found"));
  1061. }
  1062. // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
  1063. TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) {
  1064. // indexes that we are passing are: 0, 3, 1, 2, 0
  1065. // 0 will select the struct_s within the base struct (blockName)
  1066. // 3 will select the Array that contains 5 matrices
  1067. // 1 will select the Matrix that is at index 1 of the array
  1068. // 2 will select the column (which is a vector) within the matrix at index 2
  1069. // 0 will select the element at the index 0 of the vector. (which is a float).
  1070. std::ostringstream spirv;
  1071. spirv << GetHeaderForTestsFromValId() << R"(
  1072. %myblock = OpLoad %struct_blockName %blockName_var
  1073. %ss = OpCompositeExtract %struct_s %myblock 0
  1074. %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3
  1075. %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1
  1076. %sc = OpCompositeExtract %v3float %myblock 0 3 1 2
  1077. %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
  1078. ;
  1079. ; Now let's insert back at different levels...
  1080. ;
  1081. %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0
  1082. %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3
  1083. %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1
  1084. %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2
  1085. %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0
  1086. OpReturn
  1087. OpFunctionEnd
  1088. )";
  1089. CompileSuccessfully(spirv.str());
  1090. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1091. }
  1092. // Invalid. More indexes are provided than needed for OpCompositeExtract.
  1093. TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) {
  1094. // indexes that we are passing are: 0, 3, 1, 2, 0
  1095. // 0 will select the struct_s within the base struct (blockName)
  1096. // 3 will select the Array that contains 5 matrices
  1097. // 1 will select the Matrix that is at index 1 of the array
  1098. // 2 will select the column (which is a vector) within the matrix at index 2
  1099. // 0 will select the element at the index 0 of the vector. (which is a float).
  1100. std::ostringstream spirv;
  1101. spirv << GetHeaderForTestsFromValId() << R"(
  1102. %myblock = OpLoad %struct_blockName %blockName_var
  1103. %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1
  1104. OpReturn
  1105. OpFunctionEnd
  1106. )";
  1107. CompileSuccessfully(spirv.str());
  1108. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1109. EXPECT_THAT(getDiagnosticString(),
  1110. HasSubstr("Reached non-composite type while indexes still remain "
  1111. "to be traversed."));
  1112. }
  1113. // Invalid. More indexes are provided than needed for OpCompositeInsert.
  1114. TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) {
  1115. // indexes that we are passing are: 0, 3, 1, 2, 0
  1116. // 0 will select the struct_s within the base struct (blockName)
  1117. // 3 will select the Array that contains 5 matrices
  1118. // 1 will select the Matrix that is at index 1 of the array
  1119. // 2 will select the column (which is a vector) within the matrix at index 2
  1120. // 0 will select the element at the index 0 of the vector. (which is a float).
  1121. std::ostringstream spirv;
  1122. spirv << GetHeaderForTestsFromValId() << R"(
  1123. %myblock = OpLoad %struct_blockName %blockName_var
  1124. %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
  1125. %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1
  1126. OpReturn
  1127. OpFunctionEnd
  1128. )";
  1129. CompileSuccessfully(spirv.str());
  1130. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1131. EXPECT_THAT(getDiagnosticString(),
  1132. HasSubstr("Reached non-composite type while indexes still remain "
  1133. "to be traversed."));
  1134. }
  1135. // Invalid. Result type doesn't match the type we get from indexing into
  1136. // the composite.
  1137. TEST_F(ValidateComposites,
  1138. CompositeExtractResultTypeDoesntMatchIndexedTypeBad) {
  1139. // indexes that we are passing are: 0, 3, 1, 2, 0
  1140. // 0 will select the struct_s within the base struct (blockName)
  1141. // 3 will select the Array that contains 5 matrices
  1142. // 1 will select the Matrix that is at index 1 of the array
  1143. // 2 will select the column (which is a vector) within the matrix at index 2
  1144. // 0 will select the element at the index 0 of the vector. (which is a float).
  1145. std::ostringstream spirv;
  1146. spirv << GetHeaderForTestsFromValId() << R"(
  1147. %myblock = OpLoad %struct_blockName %blockName_var
  1148. %fl = OpCompositeExtract %int %myblock 0 3 1 2 0
  1149. OpReturn
  1150. OpFunctionEnd
  1151. )";
  1152. CompileSuccessfully(spirv.str());
  1153. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1154. EXPECT_THAT(getDiagnosticString(),
  1155. HasSubstr("Result type (OpTypeInt) does not match the type that "
  1156. "results from indexing into the composite "
  1157. "(OpTypeFloat)."));
  1158. }
  1159. // Invalid. Given object type doesn't match the type we get from indexing into
  1160. // the composite.
  1161. TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) {
  1162. // indexes that we are passing are: 0, 3, 1, 2, 0
  1163. // 0 will select the struct_s within the base struct (blockName)
  1164. // 3 will select the Array that contains 5 matrices
  1165. // 1 will select the Matrix that is at index 1 of the array
  1166. // 2 will select the column (which is a vector) within the matrix at index 2
  1167. // 0 will select the element at the index 0 of the vector. (which is a float).
  1168. // We are trying to insert an integer where we should be inserting a float.
  1169. std::ostringstream spirv;
  1170. spirv << GetHeaderForTestsFromValId() << R"(
  1171. %myblock = OpLoad %struct_blockName %blockName_var
  1172. %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0
  1173. OpReturn
  1174. OpFunctionEnd
  1175. )";
  1176. CompileSuccessfully(spirv.str());
  1177. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1178. EXPECT_THAT(getDiagnosticString(),
  1179. HasSubstr("The Object type (OpTypeInt) does not match the type "
  1180. "that results from indexing into the Composite "
  1181. "(OpTypeFloat)."));
  1182. }
  1183. // Invalid. Index into a struct is larger than the number of struct members.
  1184. TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) {
  1185. // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
  1186. std::ostringstream spirv;
  1187. spirv << GetHeaderForTestsFromValId() << R"(
  1188. %myblock = OpLoad %struct_blockName %blockName_var
  1189. %ss = OpCompositeExtract %struct_s %myblock 3
  1190. OpReturn
  1191. OpFunctionEnd
  1192. )";
  1193. CompileSuccessfully(spirv.str());
  1194. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1195. EXPECT_THAT(getDiagnosticString(),
  1196. HasSubstr("Index is out of bounds, can not find index 3 in the "
  1197. "structure <id> '25'. This structure has 2 members. "
  1198. "Largest valid index is 1."));
  1199. }
  1200. // Invalid. Index into a struct is larger than the number of struct members.
  1201. TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
  1202. // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
  1203. std::ostringstream spirv;
  1204. spirv << GetHeaderForTestsFromValId() << R"(
  1205. %myblock = OpLoad %struct_blockName %blockName_var
  1206. %ss = OpCompositeExtract %struct_s %myblock 0
  1207. %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3
  1208. OpReturn
  1209. OpFunctionEnd
  1210. )";
  1211. CompileSuccessfully(spirv.str());
  1212. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1213. EXPECT_THAT(
  1214. getDiagnosticString(),
  1215. HasSubstr("Index is out of bounds, can not find index 3 in the structure "
  1216. "<id> '25'. This structure has 2 members. Largest valid index "
  1217. "is 1."));
  1218. }
  1219. // #1403: Ensure that the default spec constant value is not used to check the
  1220. // extract index.
  1221. TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
  1222. std::string spirv = R"(
  1223. OpCapability Kernel
  1224. OpCapability Linkage
  1225. OpMemoryModel Logical OpenCL
  1226. OpDecorate %spec_const SpecId 1
  1227. %void = OpTypeVoid
  1228. %uint = OpTypeInt 32 0
  1229. %spec_const = OpSpecConstant %uint 3
  1230. %uint_array = OpTypeArray %uint %spec_const
  1231. %undef = OpUndef %uint_array
  1232. %voidf = OpTypeFunction %void
  1233. %func = OpFunction %void None %voidf
  1234. %1 = OpLabel
  1235. %2 = OpCompositeExtract %uint %undef 4
  1236. OpReturn
  1237. OpFunctionEnd
  1238. )";
  1239. CompileSuccessfully(spirv);
  1240. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1241. }
  1242. // #1403: Ensure that spec constant ops do not produce false positives.
  1243. TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
  1244. std::string spirv = R"(
  1245. OpCapability Kernel
  1246. OpCapability Linkage
  1247. OpMemoryModel Logical OpenCL
  1248. OpDecorate %spec_const SpecId 1
  1249. %void = OpTypeVoid
  1250. %uint = OpTypeInt 32 0
  1251. %const = OpConstant %uint 1
  1252. %spec_const = OpSpecConstant %uint 3
  1253. %spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
  1254. %uint_array = OpTypeArray %uint %spec_const_op
  1255. %undef = OpUndef %uint_array
  1256. %voidf = OpTypeFunction %void
  1257. %func = OpFunction %void None %voidf
  1258. %1 = OpLabel
  1259. %2 = OpCompositeExtract %uint %undef 4
  1260. OpReturn
  1261. OpFunctionEnd
  1262. )";
  1263. CompileSuccessfully(spirv);
  1264. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1265. }
  1266. // #1403: Ensure that the default spec constant value is not used to check the
  1267. // size of the array for a composite construct. This code has limited actual
  1268. // value as it is incorrect unless the specialization constant is assigned the
  1269. // value of 2, but it is still a valid module.
  1270. TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
  1271. std::string spirv = R"(
  1272. OpCapability Kernel
  1273. OpCapability Linkage
  1274. OpMemoryModel Logical OpenCL
  1275. OpDecorate %spec_const SpecId 1
  1276. %void = OpTypeVoid
  1277. %uint = OpTypeInt 32 0
  1278. %uint_0 = OpConstant %uint 0
  1279. %spec_const = OpSpecConstant %uint 3
  1280. %uint_array = OpTypeArray %uint %spec_const
  1281. %voidf = OpTypeFunction %void
  1282. %func = OpFunction %void None %voidf
  1283. %1 = OpLabel
  1284. %2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
  1285. OpReturn
  1286. OpFunctionEnd
  1287. )";
  1288. CompileSuccessfully(spirv);
  1289. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1290. }
  1291. TEST_F(ValidateComposites, CoopMatConstantCompositeMismatchFail) {
  1292. const std::string body =
  1293. R"(
  1294. OpCapability Shader
  1295. OpCapability Float16
  1296. OpCapability CooperativeMatrixNV
  1297. OpExtension "SPV_NV_cooperative_matrix"
  1298. OpMemoryModel Logical GLSL450
  1299. OpEntryPoint GLCompute %main "main"
  1300. %void = OpTypeVoid
  1301. %func = OpTypeFunction %void
  1302. %bool = OpTypeBool
  1303. %f16 = OpTypeFloat 16
  1304. %f32 = OpTypeFloat 32
  1305. %u32 = OpTypeInt 32 0
  1306. %u32_8 = OpConstant %u32 8
  1307. %subgroup = OpConstant %u32 3
  1308. %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
  1309. %f32_1 = OpConstant %f32 1
  1310. %f16mat_1 = OpConstantComposite %f16mat %f32_1
  1311. %main = OpFunction %void None %func
  1312. %main_entry = OpLabel
  1313. OpReturn
  1314. OpFunctionEnd)";
  1315. CompileSuccessfully(body.c_str());
  1316. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1317. EXPECT_THAT(
  1318. getDiagnosticString(),
  1319. HasSubstr("OpConstantComposite Constituent <id> '11[%float_1]' type does "
  1320. "not match the Result Type <id> '10[%10]'s component type."));
  1321. }
  1322. TEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) {
  1323. const std::string body =
  1324. R"(
  1325. OpCapability Shader
  1326. OpCapability Float16
  1327. OpCapability CooperativeMatrixNV
  1328. OpExtension "SPV_NV_cooperative_matrix"
  1329. OpMemoryModel Logical GLSL450
  1330. OpEntryPoint GLCompute %main "main"
  1331. %void = OpTypeVoid
  1332. %func = OpTypeFunction %void
  1333. %bool = OpTypeBool
  1334. %f16 = OpTypeFloat 16
  1335. %f32 = OpTypeFloat 32
  1336. %u32 = OpTypeInt 32 0
  1337. %u32_8 = OpConstant %u32 8
  1338. %subgroup = OpConstant %u32 3
  1339. %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
  1340. %f32_1 = OpConstant %f32 1
  1341. %main = OpFunction %void None %func
  1342. %main_entry = OpLabel
  1343. %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
  1344. OpReturn
  1345. OpFunctionEnd)";
  1346. CompileSuccessfully(body.c_str());
  1347. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1348. EXPECT_THAT(
  1349. getDiagnosticString(),
  1350. HasSubstr("Expected Constituent type to be equal to the component type"));
  1351. }
  1352. TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
  1353. const std::string spirv = R"(
  1354. OpCapability Shader
  1355. OpCapability Linkage
  1356. OpMemoryModel Logical GLSL450
  1357. %void = OpTypeVoid
  1358. %float = OpTypeFloat 32
  1359. %v4float = OpTypeVector %float 4
  1360. %void_fn = OpTypeFunction %void
  1361. %float_0 = OpConstant %float 0
  1362. %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1363. %func = OpFunction %void None %void_fn
  1364. %1 = OpLabel
  1365. %ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0
  1366. OpReturn
  1367. OpFunctionEnd
  1368. )";
  1369. CompileSuccessfully(spirv);
  1370. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1371. EXPECT_THAT(getDiagnosticString(),
  1372. HasSubstr("Expected Index to be int scalar"));
  1373. }
  1374. TEST_F(ValidateComposites, CopyLogicalSameType) {
  1375. const std::string spirv = R"(
  1376. OpCapability Shader
  1377. OpCapability Linkage
  1378. OpMemoryModel Logical GLSL450
  1379. %void = OpTypeVoid
  1380. %struct = OpTypeStruct
  1381. %const_struct = OpConstantComposite %struct
  1382. %void_fn = OpTypeFunction %void
  1383. %func = OpFunction %void None %void_fn
  1384. %1 = OpLabel
  1385. %copy = OpCopyLogical %struct %const_struct
  1386. OpReturn
  1387. OpFunctionEnd
  1388. )";
  1389. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1390. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1391. EXPECT_THAT(getDiagnosticString(),
  1392. HasSubstr("Result Type must not equal the Operand type"));
  1393. }
  1394. TEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) {
  1395. const std::string spirv = R"(
  1396. OpCapability Shader
  1397. OpCapability Linkage
  1398. OpMemoryModel Logical GLSL450
  1399. %void = OpTypeVoid
  1400. %struct1 = OpTypeStruct
  1401. %struct2 = OpTypeStruct
  1402. %const_struct = OpConstantComposite %struct1
  1403. %void_fn = OpTypeFunction %void
  1404. %func = OpFunction %void None %void_fn
  1405. %1 = OpLabel
  1406. %copy = OpCopyLogical %struct2 %const_struct
  1407. OpReturn
  1408. OpFunctionEnd
  1409. )";
  1410. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1411. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1412. }
  1413. TEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) {
  1414. const std::string spirv = R"(
  1415. OpCapability Shader
  1416. OpCapability Linkage
  1417. OpMemoryModel Logical GLSL450
  1418. %void = OpTypeVoid
  1419. %int = OpTypeInt 32 0
  1420. %int_4 = OpConstant %int 4
  1421. %int_5 = OpConstant %int 5
  1422. %array1 = OpTypeArray %int %int_4
  1423. %array2 = OpTypeArray %int %int_5
  1424. %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
  1425. %void_fn = OpTypeFunction %void
  1426. %func = OpFunction %void None %void_fn
  1427. %1 = OpLabel
  1428. %copy = OpCopyLogical %array2 %const_array
  1429. OpReturn
  1430. OpFunctionEnd
  1431. )";
  1432. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1433. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1434. EXPECT_THAT(
  1435. getDiagnosticString(),
  1436. HasSubstr("Result Type does not logically match the Operand type"));
  1437. }
  1438. TEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) {
  1439. const std::string spirv = R"(
  1440. OpCapability Shader
  1441. OpCapability Linkage
  1442. OpMemoryModel Logical GLSL450
  1443. %void = OpTypeVoid
  1444. %float = OpTypeFloat 32
  1445. %int = OpTypeInt 32 0
  1446. %int_4 = OpConstant %int 4
  1447. %array1 = OpTypeArray %int %int_4
  1448. %array2 = OpTypeArray %float %int_4
  1449. %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
  1450. %void_fn = OpTypeFunction %void
  1451. %func = OpFunction %void None %void_fn
  1452. %1 = OpLabel
  1453. %copy = OpCopyLogical %array2 %const_array
  1454. OpReturn
  1455. OpFunctionEnd
  1456. )";
  1457. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1458. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1459. EXPECT_THAT(
  1460. getDiagnosticString(),
  1461. HasSubstr("Result Type does not logically match the Operand type"));
  1462. }
  1463. TEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) {
  1464. const std::string spirv = R"(
  1465. OpCapability Shader
  1466. OpCapability Linkage
  1467. OpMemoryModel Logical GLSL450
  1468. %void = OpTypeVoid
  1469. %float = OpTypeFloat 32
  1470. %int = OpTypeInt 32 0
  1471. %int_1 = OpConstant %int 1
  1472. %inner1 = OpTypeArray %int %int_1
  1473. %inner2 = OpTypeArray %int %int_1
  1474. %array1 = OpTypeArray %inner1 %int_1
  1475. %array2 = OpTypeArray %inner2 %int_1
  1476. %const_inner = OpConstantComposite %inner1 %int_1
  1477. %const_array = OpConstantComposite %array1 %const_inner
  1478. %void_fn = OpTypeFunction %void
  1479. %func = OpFunction %void None %void_fn
  1480. %1 = OpLabel
  1481. %copy = OpCopyLogical %array2 %const_array
  1482. OpReturn
  1483. OpFunctionEnd
  1484. )";
  1485. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1486. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1487. }
  1488. TEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) {
  1489. const std::string spirv = R"(
  1490. OpCapability Shader
  1491. OpCapability Linkage
  1492. OpMemoryModel Logical GLSL450
  1493. %void = OpTypeVoid
  1494. %int = OpTypeInt 32 0
  1495. %struct1 = OpTypeStruct
  1496. %struct2 = OpTypeStruct %int
  1497. %const_struct = OpConstantComposite %struct1
  1498. %void_fn = OpTypeFunction %void
  1499. %func = OpFunction %void None %void_fn
  1500. %1 = OpLabel
  1501. %copy = OpCopyLogical %struct2 %const_struct
  1502. OpReturn
  1503. OpFunctionEnd
  1504. )";
  1505. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1506. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1507. EXPECT_THAT(
  1508. getDiagnosticString(),
  1509. HasSubstr("Result Type does not logically match the Operand type"));
  1510. }
  1511. TEST_F(ValidateComposites, CopyLogicalStructDifferentElement) {
  1512. const std::string spirv = R"(
  1513. OpCapability Shader
  1514. OpCapability Linkage
  1515. OpMemoryModel Logical GLSL450
  1516. %void = OpTypeVoid
  1517. %uint = OpTypeInt 32 0
  1518. %int = OpTypeInt 32 1
  1519. %int_0 = OpConstant %int 0
  1520. %uint_0 = OpConstant %uint 0
  1521. %struct1 = OpTypeStruct %int %uint
  1522. %struct2 = OpTypeStruct %int %int
  1523. %const_struct = OpConstantComposite %struct1 %int_0 %uint_0
  1524. %void_fn = OpTypeFunction %void
  1525. %func = OpFunction %void None %void_fn
  1526. %1 = OpLabel
  1527. %copy = OpCopyLogical %struct2 %const_struct
  1528. OpReturn
  1529. OpFunctionEnd
  1530. )";
  1531. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1532. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1533. EXPECT_THAT(
  1534. getDiagnosticString(),
  1535. HasSubstr("Result Type does not logically match the Operand type"));
  1536. }
  1537. TEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) {
  1538. const std::string spirv = R"(
  1539. OpCapability Shader
  1540. OpCapability Linkage
  1541. OpMemoryModel Logical GLSL450
  1542. %void = OpTypeVoid
  1543. %int = OpTypeInt 32 0
  1544. %int_1 = OpConstant %int 1
  1545. %array1 = OpTypeArray %int %int_1
  1546. %array2 = OpTypeArray %int %int_1
  1547. %struct1 = OpTypeStruct %int %array1
  1548. %struct2 = OpTypeStruct %int %array2
  1549. %const_array = OpConstantComposite %array1 %int_1
  1550. %const_struct = OpConstantComposite %struct1 %int_1 %const_array
  1551. %void_fn = OpTypeFunction %void
  1552. %func = OpFunction %void None %void_fn
  1553. %1 = OpLabel
  1554. %copy = OpCopyLogical %struct2 %const_struct
  1555. OpReturn
  1556. OpFunctionEnd
  1557. )";
  1558. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1559. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1560. }
  1561. using ValidateSmallComposites = spvtest::ValidateBase<std::string>;
  1562. CodeGenerator GetSmallCompositesCodeGenerator() {
  1563. CodeGenerator generator;
  1564. generator.capabilities_ = R"(
  1565. OpCapability Shader
  1566. OpCapability Linkage
  1567. OpCapability UniformAndStorageBuffer16BitAccess
  1568. OpCapability UniformAndStorageBuffer8BitAccess
  1569. )";
  1570. generator.extensions_ = R"(
  1571. OpExtension "SPV_KHR_16bit_storage"
  1572. OpExtension "SPV_KHR_8bit_storage"
  1573. )";
  1574. generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
  1575. generator.before_types_ = R"(
  1576. OpDecorate %char_block Block
  1577. OpMemberDecorate %char_block 0 Offset 0
  1578. OpDecorate %short_block Block
  1579. OpMemberDecorate %short_block 0 Offset 0
  1580. OpDecorate %half_block Block
  1581. OpMemberDecorate %half_block 0 Offset 0
  1582. )";
  1583. generator.types_ = R"(
  1584. %void = OpTypeVoid
  1585. %int = OpTypeInt 32 0
  1586. %int_0 = OpConstant %int 0
  1587. %int_1 = OpConstant %int 1
  1588. %char = OpTypeInt 8 0
  1589. %char2 = OpTypeVector %char 2
  1590. %short = OpTypeInt 16 0
  1591. %short2 = OpTypeVector %short 2
  1592. %half = OpTypeFloat 16
  1593. %half2 = OpTypeVector %half 2
  1594. %char_block = OpTypeStruct %char2
  1595. %short_block = OpTypeStruct %short2
  1596. %half_block = OpTypeStruct %half2
  1597. %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
  1598. %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
  1599. %ptr_ssbo_char = OpTypePointer StorageBuffer %char
  1600. %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
  1601. %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
  1602. %ptr_ssbo_short = OpTypePointer StorageBuffer %short
  1603. %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
  1604. %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
  1605. %ptr_ssbo_half = OpTypePointer StorageBuffer %half
  1606. %void_fn = OpTypeFunction %void
  1607. %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
  1608. %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
  1609. %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
  1610. )";
  1611. generator.after_types_ = R"(
  1612. %func = OpFunction %void None %void_fn
  1613. %entry = OpLabel
  1614. %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
  1615. %ld_char2 = OpLoad %char2 %char2_gep
  1616. %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
  1617. %ld_char = OpLoad %char %char_gep
  1618. %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
  1619. %ld_short2 = OpLoad %short2 %short2_gep
  1620. %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
  1621. %ld_short = OpLoad %short %short_gep
  1622. %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
  1623. %ld_half2 = OpLoad %half2 %half2_gep
  1624. %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
  1625. %ld_half = OpLoad %half %half_gep
  1626. )";
  1627. generator.add_at_the_end_ = R"(
  1628. OpReturn
  1629. OpFunctionEnd
  1630. )";
  1631. return generator;
  1632. }
  1633. TEST_P(ValidateSmallComposites, VectorExtractDynamic) {
  1634. std::string type = GetParam();
  1635. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1636. std::string inst =
  1637. "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_0\n";
  1638. generator.after_types_ += inst;
  1639. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1640. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1641. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1642. EXPECT_THAT(getDiagnosticString(),
  1643. HasSubstr("Cannot extract from a vector of 8- or 16-bit types"));
  1644. }
  1645. TEST_P(ValidateSmallComposites, VectorInsertDynamic) {
  1646. std::string type = GetParam();
  1647. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1648. std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" +
  1649. type + "2 %ld_" + type + " %int_0\n";
  1650. generator.after_types_ += inst;
  1651. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1652. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1653. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1654. EXPECT_THAT(getDiagnosticString(),
  1655. HasSubstr("Cannot insert into a vector of 8- or 16-bit types"));
  1656. }
  1657. TEST_P(ValidateSmallComposites, VectorShuffle) {
  1658. std::string type = GetParam();
  1659. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1660. std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type +
  1661. "2 %ld_" + type + "2 0 0\n";
  1662. generator.after_types_ += inst;
  1663. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1664. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1665. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1666. EXPECT_THAT(getDiagnosticString(),
  1667. HasSubstr("Cannot shuffle a vector of 8- or 16-bit types"));
  1668. }
  1669. TEST_P(ValidateSmallComposites, CompositeConstruct) {
  1670. std::string type = GetParam();
  1671. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1672. std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type +
  1673. " %ld_" + type + "\n";
  1674. generator.after_types_ += inst;
  1675. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1676. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1677. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1678. EXPECT_THAT(
  1679. getDiagnosticString(),
  1680. HasSubstr("Cannot create a composite containing 8- or 16-bit types"));
  1681. }
  1682. TEST_P(ValidateSmallComposites, CompositeExtract) {
  1683. std::string type = GetParam();
  1684. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1685. std::string inst =
  1686. "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n";
  1687. generator.after_types_ += inst;
  1688. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1689. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1690. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1691. EXPECT_THAT(
  1692. getDiagnosticString(),
  1693. HasSubstr("Cannot extract from a composite of 8- or 16-bit types"));
  1694. }
  1695. TEST_P(ValidateSmallComposites, CompositeInsert) {
  1696. std::string type = GetParam();
  1697. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1698. std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type +
  1699. " %ld_" + type + "2 0\n";
  1700. generator.after_types_ += inst;
  1701. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1702. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1703. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1704. EXPECT_THAT(
  1705. getDiagnosticString(),
  1706. HasSubstr("Cannot insert into a composite of 8- or 16-bit types"));
  1707. }
  1708. TEST_P(ValidateSmallComposites, CopyObject) {
  1709. std::string type = GetParam();
  1710. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1711. std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n";
  1712. generator.after_types_ += inst;
  1713. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1714. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1715. }
  1716. INSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites,
  1717. Values("char", "short", "half"));
  1718. TEST_F(ValidateComposites, HalfMatrixCannotTranspose) {
  1719. const std::string spirv = R"(
  1720. OpCapability Shader
  1721. OpCapability Linkage
  1722. OpCapability UniformAndStorageBuffer16BitAccess
  1723. OpExtension "SPV_KHR_16bit_storage"
  1724. OpMemoryModel Logical GLSL450
  1725. OpDecorate %block Block
  1726. OpMemberDecorate %block 0 Offset 0
  1727. OpMemberDecorate %block 0 RowMajor
  1728. OpMemberDecorate %block 0 MatrixStride 8
  1729. %void = OpTypeVoid
  1730. %int = OpTypeInt 32 0
  1731. %int_0 = OpConstant %int 0
  1732. %float = OpTypeFloat 16
  1733. %float2 = OpTypeVector %float 2
  1734. %mat2x2 = OpTypeMatrix %float2 2
  1735. %block = OpTypeStruct %mat2x2
  1736. %ptr_ssbo_block = OpTypePointer StorageBuffer %block
  1737. %ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2
  1738. %var = OpVariable %ptr_ssbo_block StorageBuffer
  1739. %void_fn = OpTypeFunction %void
  1740. %func = OpFunction %void None %void_fn
  1741. %entry = OpLabel
  1742. %gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0
  1743. %ld = OpLoad %mat2x2 %gep
  1744. %inst = OpTranspose %mat2x2 %ld
  1745. OpReturn
  1746. OpFunctionEnd
  1747. )";
  1748. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1749. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1750. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1751. EXPECT_THAT(getDiagnosticString(),
  1752. HasSubstr("Cannot transpose matrices of 16-bit floats"));
  1753. }
  1754. TEST_F(ValidateComposites, CopyObjectVoid) {
  1755. const std::string spirv = R"(
  1756. OpCapability Shader
  1757. %1 = OpExtInstImport "GLSL.std.450"
  1758. OpMemoryModel Logical GLSL450
  1759. OpEntryPoint Fragment %4 "main"
  1760. OpExecutionMode %4 OriginUpperLeft
  1761. OpSource ESSL 320
  1762. OpName %4 "main"
  1763. OpName %6 "foo("
  1764. %2 = OpTypeVoid
  1765. %3 = OpTypeFunction %2
  1766. %4 = OpFunction %2 None %3
  1767. %5 = OpLabel
  1768. %8 = OpFunctionCall %2 %6
  1769. %20 = OpCopyObject %2 %8
  1770. OpReturn
  1771. OpFunctionEnd
  1772. %6 = OpFunction %2 None %3
  1773. %7 = OpLabel
  1774. OpReturn
  1775. OpFunctionEnd
  1776. )";
  1777. CompileSuccessfully(spirv);
  1778. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1779. EXPECT_THAT(getDiagnosticString(),
  1780. HasSubstr("OpCopyObject cannot have void result type"));
  1781. }
  1782. } // namespace
  1783. } // namespace val
  1784. } // namespace spvtools