val_composites_test.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297
  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 = R"(
  1293. OpCapability Shader
  1294. OpCapability Float16
  1295. OpCapability CooperativeMatrixNV
  1296. OpExtension "SPV_NV_cooperative_matrix"
  1297. OpMemoryModel Logical GLSL450
  1298. OpEntryPoint GLCompute %main "main"
  1299. %void = OpTypeVoid
  1300. %func = OpTypeFunction %void
  1301. %bool = OpTypeBool
  1302. %f16 = OpTypeFloat 16
  1303. %f32 = OpTypeFloat 32
  1304. %u32 = OpTypeInt 32 0
  1305. %u32_8 = OpConstant %u32 8
  1306. %subgroup = OpConstant %u32 3
  1307. %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
  1308. %f32_1 = OpConstant %f32 1
  1309. %f16mat_1 = OpConstantComposite %f16mat %f32_1
  1310. %main = OpFunction %void None %func
  1311. %main_entry = OpLabel
  1312. OpReturn
  1313. OpFunctionEnd)";
  1314. CompileSuccessfully(body.c_str());
  1315. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1316. EXPECT_THAT(
  1317. getDiagnosticString(),
  1318. HasSubstr("OpConstantComposite Constituent <id> '11[%float_1]' type does "
  1319. "not match the Result Type <id> '10[%10]'s component type."));
  1320. }
  1321. TEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) {
  1322. const std::string body = R"(
  1323. OpCapability Shader
  1324. OpCapability Float16
  1325. OpCapability CooperativeMatrixNV
  1326. OpExtension "SPV_NV_cooperative_matrix"
  1327. OpMemoryModel Logical GLSL450
  1328. OpEntryPoint GLCompute %main "main"
  1329. %void = OpTypeVoid
  1330. %func = OpTypeFunction %void
  1331. %bool = OpTypeBool
  1332. %f16 = OpTypeFloat 16
  1333. %f32 = OpTypeFloat 32
  1334. %u32 = OpTypeInt 32 0
  1335. %u32_8 = OpConstant %u32 8
  1336. %subgroup = OpConstant %u32 3
  1337. %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
  1338. %f32_1 = OpConstant %f32 1
  1339. %main = OpFunction %void None %func
  1340. %main_entry = OpLabel
  1341. %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
  1342. OpReturn
  1343. OpFunctionEnd)";
  1344. CompileSuccessfully(body.c_str());
  1345. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1346. EXPECT_THAT(
  1347. getDiagnosticString(),
  1348. HasSubstr("Expected Constituent type to be equal to the component type"));
  1349. }
  1350. TEST_F(ValidateComposites, CoopMatKHRConstantCompositeMismatchFail) {
  1351. const std::string body = R"(
  1352. OpCapability Shader
  1353. OpCapability Float16
  1354. OpCapability CooperativeMatrixKHR
  1355. OpExtension "SPV_KHR_cooperative_matrix"
  1356. OpExtension "SPV_KHR_vulkan_memory_model"
  1357. OpMemoryModel Logical GLSL450
  1358. OpEntryPoint GLCompute %main "main"
  1359. %void = OpTypeVoid
  1360. %func = OpTypeFunction %void
  1361. %bool = OpTypeBool
  1362. %f16 = OpTypeFloat 16
  1363. %f32 = OpTypeFloat 32
  1364. %u32 = OpTypeInt 32 0
  1365. %u32_16 = OpConstant %u32 16
  1366. %useA = OpConstant %u32 0
  1367. %subgroup = OpConstant %u32 3
  1368. %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
  1369. %f32_1 = OpConstant %f32 1
  1370. %f16mat_1 = OpConstantComposite %f16mat %f32_1
  1371. %main = OpFunction %void None %func
  1372. %main_entry = OpLabel
  1373. OpReturn
  1374. OpFunctionEnd)";
  1375. CompileSuccessfully(body.c_str());
  1376. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1377. EXPECT_THAT(
  1378. getDiagnosticString(),
  1379. HasSubstr(
  1380. "OpConstantComposite Constituent <id> '12[%float_1]' type "
  1381. "does not match the Result Type <id> '11[%11]'s component type."));
  1382. }
  1383. TEST_F(ValidateComposites, CoopMatKHRCompositeConstructMismatchFail) {
  1384. const std::string body = R"(
  1385. OpCapability Shader
  1386. OpCapability Float16
  1387. OpCapability CooperativeMatrixKHR
  1388. OpExtension "SPV_KHR_cooperative_matrix"
  1389. OpExtension "SPV_KHR_vulkan_memory_model"
  1390. OpMemoryModel Logical GLSL450
  1391. OpEntryPoint GLCompute %main "main"
  1392. %void = OpTypeVoid
  1393. %func = OpTypeFunction %void
  1394. %bool = OpTypeBool
  1395. %f16 = OpTypeFloat 16
  1396. %f32 = OpTypeFloat 32
  1397. %u32 = OpTypeInt 32 0
  1398. %u32_16 = OpConstant %u32 16
  1399. %useA = OpConstant %u32 0
  1400. %subgroup = OpConstant %u32 3
  1401. %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
  1402. %f32_1 = OpConstant %f32 1
  1403. %main = OpFunction %void None %func
  1404. %main_entry = OpLabel
  1405. %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
  1406. OpReturn
  1407. OpFunctionEnd)";
  1408. CompileSuccessfully(body.c_str());
  1409. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1410. EXPECT_THAT(
  1411. getDiagnosticString(),
  1412. HasSubstr("Expected Constituent type to be equal to the component type"));
  1413. }
  1414. TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
  1415. const std::string spirv = R"(
  1416. OpCapability Shader
  1417. OpCapability Linkage
  1418. OpMemoryModel Logical GLSL450
  1419. %void = OpTypeVoid
  1420. %float = OpTypeFloat 32
  1421. %v4float = OpTypeVector %float 4
  1422. %void_fn = OpTypeFunction %void
  1423. %float_0 = OpConstant %float 0
  1424. %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
  1425. %func = OpFunction %void None %void_fn
  1426. %1 = OpLabel
  1427. %ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0
  1428. OpReturn
  1429. OpFunctionEnd
  1430. )";
  1431. CompileSuccessfully(spirv);
  1432. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1433. EXPECT_THAT(getDiagnosticString(),
  1434. HasSubstr("Expected Index to be int scalar"));
  1435. }
  1436. TEST_F(ValidateComposites, CopyLogicalSameType) {
  1437. const std::string spirv = R"(
  1438. OpCapability Shader
  1439. OpCapability Linkage
  1440. OpMemoryModel Logical GLSL450
  1441. %void = OpTypeVoid
  1442. %struct = OpTypeStruct
  1443. %const_struct = OpConstantComposite %struct
  1444. %void_fn = OpTypeFunction %void
  1445. %func = OpFunction %void None %void_fn
  1446. %1 = OpLabel
  1447. %copy = OpCopyLogical %struct %const_struct
  1448. OpReturn
  1449. OpFunctionEnd
  1450. )";
  1451. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1452. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1453. EXPECT_THAT(getDiagnosticString(),
  1454. HasSubstr("Result Type must not equal the Operand type"));
  1455. }
  1456. TEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) {
  1457. const std::string spirv = R"(
  1458. OpCapability Shader
  1459. OpCapability Linkage
  1460. OpMemoryModel Logical GLSL450
  1461. %void = OpTypeVoid
  1462. %struct1 = OpTypeStruct
  1463. %struct2 = OpTypeStruct
  1464. %const_struct = OpConstantComposite %struct1
  1465. %void_fn = OpTypeFunction %void
  1466. %func = OpFunction %void None %void_fn
  1467. %1 = OpLabel
  1468. %copy = OpCopyLogical %struct2 %const_struct
  1469. OpReturn
  1470. OpFunctionEnd
  1471. )";
  1472. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1473. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1474. }
  1475. TEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) {
  1476. const std::string spirv = R"(
  1477. OpCapability Shader
  1478. OpCapability Linkage
  1479. OpMemoryModel Logical GLSL450
  1480. %void = OpTypeVoid
  1481. %int = OpTypeInt 32 0
  1482. %int_4 = OpConstant %int 4
  1483. %int_5 = OpConstant %int 5
  1484. %array1 = OpTypeArray %int %int_4
  1485. %array2 = OpTypeArray %int %int_5
  1486. %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
  1487. %void_fn = OpTypeFunction %void
  1488. %func = OpFunction %void None %void_fn
  1489. %1 = OpLabel
  1490. %copy = OpCopyLogical %array2 %const_array
  1491. OpReturn
  1492. OpFunctionEnd
  1493. )";
  1494. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1495. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1496. EXPECT_THAT(
  1497. getDiagnosticString(),
  1498. HasSubstr("Result Type does not logically match the Operand type"));
  1499. }
  1500. TEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) {
  1501. const std::string spirv = R"(
  1502. OpCapability Shader
  1503. OpCapability Linkage
  1504. OpMemoryModel Logical GLSL450
  1505. %void = OpTypeVoid
  1506. %float = OpTypeFloat 32
  1507. %int = OpTypeInt 32 0
  1508. %int_4 = OpConstant %int 4
  1509. %array1 = OpTypeArray %int %int_4
  1510. %array2 = OpTypeArray %float %int_4
  1511. %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
  1512. %void_fn = OpTypeFunction %void
  1513. %func = OpFunction %void None %void_fn
  1514. %1 = OpLabel
  1515. %copy = OpCopyLogical %array2 %const_array
  1516. OpReturn
  1517. OpFunctionEnd
  1518. )";
  1519. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1520. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1521. EXPECT_THAT(
  1522. getDiagnosticString(),
  1523. HasSubstr("Result Type does not logically match the Operand type"));
  1524. }
  1525. TEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) {
  1526. const std::string spirv = R"(
  1527. OpCapability Shader
  1528. OpCapability Linkage
  1529. OpMemoryModel Logical GLSL450
  1530. %void = OpTypeVoid
  1531. %float = OpTypeFloat 32
  1532. %int = OpTypeInt 32 0
  1533. %int_1 = OpConstant %int 1
  1534. %inner1 = OpTypeArray %int %int_1
  1535. %inner2 = OpTypeArray %int %int_1
  1536. %array1 = OpTypeArray %inner1 %int_1
  1537. %array2 = OpTypeArray %inner2 %int_1
  1538. %const_inner = OpConstantComposite %inner1 %int_1
  1539. %const_array = OpConstantComposite %array1 %const_inner
  1540. %void_fn = OpTypeFunction %void
  1541. %func = OpFunction %void None %void_fn
  1542. %1 = OpLabel
  1543. %copy = OpCopyLogical %array2 %const_array
  1544. OpReturn
  1545. OpFunctionEnd
  1546. )";
  1547. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1548. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1549. }
  1550. TEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) {
  1551. const std::string spirv = R"(
  1552. OpCapability Shader
  1553. OpCapability Linkage
  1554. OpMemoryModel Logical GLSL450
  1555. %void = OpTypeVoid
  1556. %int = OpTypeInt 32 0
  1557. %struct1 = OpTypeStruct
  1558. %struct2 = OpTypeStruct %int
  1559. %const_struct = OpConstantComposite %struct1
  1560. %void_fn = OpTypeFunction %void
  1561. %func = OpFunction %void None %void_fn
  1562. %1 = OpLabel
  1563. %copy = OpCopyLogical %struct2 %const_struct
  1564. OpReturn
  1565. OpFunctionEnd
  1566. )";
  1567. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1568. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1569. EXPECT_THAT(
  1570. getDiagnosticString(),
  1571. HasSubstr("Result Type does not logically match the Operand type"));
  1572. }
  1573. TEST_F(ValidateComposites, CopyLogicalStructDifferentElement) {
  1574. const std::string spirv = R"(
  1575. OpCapability Shader
  1576. OpCapability Linkage
  1577. OpMemoryModel Logical GLSL450
  1578. %void = OpTypeVoid
  1579. %uint = OpTypeInt 32 0
  1580. %int = OpTypeInt 32 1
  1581. %int_0 = OpConstant %int 0
  1582. %uint_0 = OpConstant %uint 0
  1583. %struct1 = OpTypeStruct %int %uint
  1584. %struct2 = OpTypeStruct %int %int
  1585. %const_struct = OpConstantComposite %struct1 %int_0 %uint_0
  1586. %void_fn = OpTypeFunction %void
  1587. %func = OpFunction %void None %void_fn
  1588. %1 = OpLabel
  1589. %copy = OpCopyLogical %struct2 %const_struct
  1590. OpReturn
  1591. OpFunctionEnd
  1592. )";
  1593. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1594. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1595. EXPECT_THAT(
  1596. getDiagnosticString(),
  1597. HasSubstr("Result Type does not logically match the Operand type"));
  1598. }
  1599. TEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) {
  1600. const std::string spirv = R"(
  1601. OpCapability Shader
  1602. OpCapability Linkage
  1603. OpMemoryModel Logical GLSL450
  1604. %void = OpTypeVoid
  1605. %int = OpTypeInt 32 0
  1606. %int_1 = OpConstant %int 1
  1607. %array1 = OpTypeArray %int %int_1
  1608. %array2 = OpTypeArray %int %int_1
  1609. %struct1 = OpTypeStruct %int %array1
  1610. %struct2 = OpTypeStruct %int %array2
  1611. %const_array = OpConstantComposite %array1 %int_1
  1612. %const_struct = OpConstantComposite %struct1 %int_1 %const_array
  1613. %void_fn = OpTypeFunction %void
  1614. %func = OpFunction %void None %void_fn
  1615. %1 = OpLabel
  1616. %copy = OpCopyLogical %struct2 %const_struct
  1617. OpReturn
  1618. OpFunctionEnd
  1619. )";
  1620. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  1621. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  1622. }
  1623. using ValidateSmallComposites = spvtest::ValidateBase<std::string>;
  1624. CodeGenerator GetSmallCompositesCodeGenerator() {
  1625. CodeGenerator generator;
  1626. generator.capabilities_ = R"(
  1627. OpCapability Shader
  1628. OpCapability Linkage
  1629. OpCapability UniformAndStorageBuffer16BitAccess
  1630. OpCapability UniformAndStorageBuffer8BitAccess
  1631. )";
  1632. generator.extensions_ = R"(
  1633. OpExtension "SPV_KHR_16bit_storage"
  1634. OpExtension "SPV_KHR_8bit_storage"
  1635. )";
  1636. generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
  1637. generator.before_types_ = R"(
  1638. OpDecorate %char_block Block
  1639. OpMemberDecorate %char_block 0 Offset 0
  1640. OpDecorate %short_block Block
  1641. OpMemberDecorate %short_block 0 Offset 0
  1642. OpDecorate %half_block Block
  1643. OpMemberDecorate %half_block 0 Offset 0
  1644. )";
  1645. generator.types_ = R"(
  1646. %void = OpTypeVoid
  1647. %int = OpTypeInt 32 0
  1648. %int_0 = OpConstant %int 0
  1649. %int_1 = OpConstant %int 1
  1650. %char = OpTypeInt 8 0
  1651. %char2 = OpTypeVector %char 2
  1652. %short = OpTypeInt 16 0
  1653. %short2 = OpTypeVector %short 2
  1654. %half = OpTypeFloat 16
  1655. %half2 = OpTypeVector %half 2
  1656. %char_block = OpTypeStruct %char2
  1657. %short_block = OpTypeStruct %short2
  1658. %half_block = OpTypeStruct %half2
  1659. %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
  1660. %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
  1661. %ptr_ssbo_char = OpTypePointer StorageBuffer %char
  1662. %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
  1663. %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
  1664. %ptr_ssbo_short = OpTypePointer StorageBuffer %short
  1665. %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
  1666. %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
  1667. %ptr_ssbo_half = OpTypePointer StorageBuffer %half
  1668. %void_fn = OpTypeFunction %void
  1669. %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
  1670. %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
  1671. %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
  1672. )";
  1673. generator.after_types_ = R"(
  1674. %func = OpFunction %void None %void_fn
  1675. %entry = OpLabel
  1676. %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
  1677. %ld_char2 = OpLoad %char2 %char2_gep
  1678. %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
  1679. %ld_char = OpLoad %char %char_gep
  1680. %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
  1681. %ld_short2 = OpLoad %short2 %short2_gep
  1682. %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
  1683. %ld_short = OpLoad %short %short_gep
  1684. %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
  1685. %ld_half2 = OpLoad %half2 %half2_gep
  1686. %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
  1687. %ld_half = OpLoad %half %half_gep
  1688. )";
  1689. generator.add_at_the_end_ = R"(
  1690. OpReturn
  1691. OpFunctionEnd
  1692. )";
  1693. return generator;
  1694. }
  1695. TEST_P(ValidateSmallComposites, VectorExtractDynamic) {
  1696. std::string type = GetParam();
  1697. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1698. std::string inst =
  1699. "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_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(getDiagnosticString(),
  1705. HasSubstr("Cannot extract from a vector of 8- or 16-bit types"));
  1706. }
  1707. TEST_P(ValidateSmallComposites, VectorInsertDynamic) {
  1708. std::string type = GetParam();
  1709. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1710. std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" +
  1711. type + "2 %ld_" + type + " %int_0\n";
  1712. generator.after_types_ += inst;
  1713. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1714. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1715. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1716. EXPECT_THAT(getDiagnosticString(),
  1717. HasSubstr("Cannot insert into a vector of 8- or 16-bit types"));
  1718. }
  1719. TEST_P(ValidateSmallComposites, VectorShuffle) {
  1720. std::string type = GetParam();
  1721. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1722. std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type +
  1723. "2 %ld_" + type + "2 0 0\n";
  1724. generator.after_types_ += inst;
  1725. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1726. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1727. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1728. EXPECT_THAT(getDiagnosticString(),
  1729. HasSubstr("Cannot shuffle a vector of 8- or 16-bit types"));
  1730. }
  1731. TEST_P(ValidateSmallComposites, CompositeConstruct) {
  1732. std::string type = GetParam();
  1733. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1734. std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type +
  1735. " %ld_" + type + "\n";
  1736. generator.after_types_ += inst;
  1737. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1738. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1739. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1740. EXPECT_THAT(
  1741. getDiagnosticString(),
  1742. HasSubstr("Cannot create a composite containing 8- or 16-bit types"));
  1743. }
  1744. TEST_P(ValidateSmallComposites, CompositeExtract) {
  1745. std::string type = GetParam();
  1746. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1747. std::string inst =
  1748. "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n";
  1749. generator.after_types_ += inst;
  1750. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1751. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1752. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1753. EXPECT_THAT(
  1754. getDiagnosticString(),
  1755. HasSubstr("Cannot extract from a composite of 8- or 16-bit types"));
  1756. }
  1757. TEST_P(ValidateSmallComposites, CompositeInsert) {
  1758. std::string type = GetParam();
  1759. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1760. std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type +
  1761. " %ld_" + type + "2 0\n";
  1762. generator.after_types_ += inst;
  1763. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1764. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1765. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1766. EXPECT_THAT(
  1767. getDiagnosticString(),
  1768. HasSubstr("Cannot insert into a composite of 8- or 16-bit types"));
  1769. }
  1770. TEST_P(ValidateSmallComposites, CopyObject) {
  1771. std::string type = GetParam();
  1772. CodeGenerator generator = GetSmallCompositesCodeGenerator();
  1773. std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n";
  1774. generator.after_types_ += inst;
  1775. CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
  1776. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1777. }
  1778. INSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites,
  1779. Values("char", "short", "half"));
  1780. TEST_F(ValidateComposites, HalfMatrixCannotTranspose) {
  1781. const std::string spirv = R"(
  1782. OpCapability Shader
  1783. OpCapability Linkage
  1784. OpCapability UniformAndStorageBuffer16BitAccess
  1785. OpExtension "SPV_KHR_16bit_storage"
  1786. OpMemoryModel Logical GLSL450
  1787. OpDecorate %block Block
  1788. OpMemberDecorate %block 0 Offset 0
  1789. OpMemberDecorate %block 0 RowMajor
  1790. OpMemberDecorate %block 0 MatrixStride 8
  1791. %void = OpTypeVoid
  1792. %int = OpTypeInt 32 0
  1793. %int_0 = OpConstant %int 0
  1794. %float = OpTypeFloat 16
  1795. %float2 = OpTypeVector %float 2
  1796. %mat2x2 = OpTypeMatrix %float2 2
  1797. %block = OpTypeStruct %mat2x2
  1798. %ptr_ssbo_block = OpTypePointer StorageBuffer %block
  1799. %ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2
  1800. %var = OpVariable %ptr_ssbo_block StorageBuffer
  1801. %void_fn = OpTypeFunction %void
  1802. %func = OpFunction %void None %void_fn
  1803. %entry = OpLabel
  1804. %gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0
  1805. %ld = OpLoad %mat2x2 %gep
  1806. %inst = OpTranspose %mat2x2 %ld
  1807. OpReturn
  1808. OpFunctionEnd
  1809. )";
  1810. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1811. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1812. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1813. EXPECT_THAT(getDiagnosticString(),
  1814. HasSubstr("Cannot transpose matrices of 16-bit floats"));
  1815. }
  1816. TEST_F(ValidateComposites, CopyObjectVoid) {
  1817. const std::string spirv = R"(
  1818. OpCapability Shader
  1819. %1 = OpExtInstImport "GLSL.std.450"
  1820. OpMemoryModel Logical GLSL450
  1821. OpEntryPoint Fragment %4 "main"
  1822. OpExecutionMode %4 OriginUpperLeft
  1823. OpSource ESSL 320
  1824. OpName %4 "main"
  1825. OpName %6 "foo("
  1826. %2 = OpTypeVoid
  1827. %3 = OpTypeFunction %2
  1828. %4 = OpFunction %2 None %3
  1829. %5 = OpLabel
  1830. %8 = OpFunctionCall %2 %6
  1831. %20 = OpCopyObject %2 %8
  1832. OpReturn
  1833. OpFunctionEnd
  1834. %6 = OpFunction %2 None %3
  1835. %7 = OpLabel
  1836. OpReturn
  1837. OpFunctionEnd
  1838. )";
  1839. CompileSuccessfully(spirv);
  1840. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1841. EXPECT_THAT(getDiagnosticString(),
  1842. HasSubstr("OpCopyObject cannot have void result type"));
  1843. }
  1844. TEST_F(ValidateComposites, CoopVecConstantCompositePass) {
  1845. const std::string body = R"(
  1846. OpCapability Shader
  1847. OpCapability Float16
  1848. OpCapability CooperativeVectorNV
  1849. OpExtension "SPV_NV_cooperative_vector"
  1850. OpExtension "SPV_KHR_vulkan_memory_model"
  1851. OpMemoryModel Logical GLSL450
  1852. OpEntryPoint GLCompute %main "main"
  1853. %void = OpTypeVoid
  1854. %func = OpTypeFunction %void
  1855. %bool = OpTypeBool
  1856. %f16 = OpTypeFloat 16
  1857. %f32 = OpTypeFloat 32
  1858. %u32 = OpTypeInt 32 0
  1859. %u32_16 = OpConstant %u32 16
  1860. %useA = OpConstant %u32 0
  1861. %subgroup = OpConstant %u32 3
  1862. %f16vec = OpTypeCooperativeVectorNV %f16 %u32_16
  1863. %f16_1 = OpConstant %f16 1
  1864. %f16vec_1 = OpConstantComposite %f16vec %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1
  1865. %main = OpFunction %void None %func
  1866. %main_entry = OpLabel
  1867. OpReturn
  1868. OpFunctionEnd)";
  1869. CompileSuccessfully(body.c_str());
  1870. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1871. }
  1872. TEST_F(ValidateComposites, CoopVecConstantCompositeMismatchFail) {
  1873. const std::string body = R"(
  1874. OpCapability Shader
  1875. OpCapability Float16
  1876. OpCapability CooperativeVectorNV
  1877. OpExtension "SPV_NV_cooperative_vector"
  1878. OpExtension "SPV_KHR_vulkan_memory_model"
  1879. OpMemoryModel Logical GLSL450
  1880. OpEntryPoint GLCompute %main "main"
  1881. %void = OpTypeVoid
  1882. %func = OpTypeFunction %void
  1883. %bool = OpTypeBool
  1884. %f16 = OpTypeFloat 16
  1885. %f32 = OpTypeFloat 32
  1886. %u32 = OpTypeInt 32 0
  1887. %u32_16 = OpConstant %u32 16
  1888. %useA = OpConstant %u32 0
  1889. %subgroup = OpConstant %u32 3
  1890. %f16vec = OpTypeCooperativeVectorNV %f16 %u32_16
  1891. %f32_1 = OpConstant %f32 1
  1892. %f16vec_1 = OpConstantComposite %f16vec %f32_1
  1893. %main = OpFunction %void None %func
  1894. %main_entry = OpLabel
  1895. OpReturn
  1896. OpFunctionEnd)";
  1897. CompileSuccessfully(body.c_str());
  1898. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1899. EXPECT_THAT(
  1900. getDiagnosticString(),
  1901. HasSubstr("OpConstantComposite Constituent <id> count does not match "
  1902. "Result Type <id> '11[%11]'s vector component count"));
  1903. }
  1904. TEST_F(ValidateComposites, CoopVecCompositeConstructPass) {
  1905. const std::string body = R"(
  1906. OpCapability Shader
  1907. OpCapability Float16
  1908. OpCapability CooperativeVectorNV
  1909. OpExtension "SPV_NV_cooperative_vector"
  1910. OpExtension "SPV_KHR_vulkan_memory_model"
  1911. OpMemoryModel Logical GLSL450
  1912. OpEntryPoint GLCompute %main "main"
  1913. %void = OpTypeVoid
  1914. %func = OpTypeFunction %void
  1915. %bool = OpTypeBool
  1916. %f16 = OpTypeFloat 16
  1917. %f32 = OpTypeFloat 32
  1918. %u32 = OpTypeInt 32 0
  1919. %u32_16 = OpConstant %u32 16
  1920. %useA = OpConstant %u32 0
  1921. %subgroup = OpConstant %u32 3
  1922. %f16vec = OpTypeCooperativeVectorNV %f16 %u32_16
  1923. %f16_1 = OpConstant %f16 1
  1924. %main = OpFunction %void None %func
  1925. %main_entry = OpLabel
  1926. %f16vec_1 = OpCompositeConstruct %f16vec %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1
  1927. OpReturn
  1928. OpFunctionEnd)";
  1929. CompileSuccessfully(body.c_str());
  1930. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1931. }
  1932. TEST_F(ValidateComposites, CoopVecCompositeConstructMismatchFail) {
  1933. const std::string body = R"(
  1934. OpCapability Shader
  1935. OpCapability Float16
  1936. OpCapability CooperativeVectorNV
  1937. OpExtension "SPV_NV_cooperative_vector"
  1938. OpExtension "SPV_KHR_vulkan_memory_model"
  1939. OpMemoryModel Logical GLSL450
  1940. OpEntryPoint GLCompute %main "main"
  1941. %void = OpTypeVoid
  1942. %func = OpTypeFunction %void
  1943. %bool = OpTypeBool
  1944. %f16 = OpTypeFloat 16
  1945. %f32 = OpTypeFloat 32
  1946. %u32 = OpTypeInt 32 0
  1947. %u32_16 = OpConstant %u32 16
  1948. %useA = OpConstant %u32 0
  1949. %subgroup = OpConstant %u32 3
  1950. %f16vec = OpTypeCooperativeVectorNV %f16 %u32_16
  1951. %f32_1 = OpConstant %f32 1
  1952. %main = OpFunction %void None %func
  1953. %main_entry = OpLabel
  1954. %f16vec_1 = OpCompositeConstruct %f16vec %f32_1
  1955. OpReturn
  1956. OpFunctionEnd)";
  1957. CompileSuccessfully(body.c_str());
  1958. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1959. EXPECT_THAT(getDiagnosticString(),
  1960. HasSubstr("Expected Constituents to be scalars or vectors of the "
  1961. "same type as Result Type components"));
  1962. }
  1963. TEST_F(ValidateComposites, CoopVecInsertExtractDynamicPass) {
  1964. const std::string body = R"(
  1965. OpCapability Shader
  1966. OpCapability Float16
  1967. OpCapability CooperativeVectorNV
  1968. OpExtension "SPV_NV_cooperative_vector"
  1969. OpExtension "SPV_KHR_vulkan_memory_model"
  1970. OpMemoryModel Logical GLSL450
  1971. OpEntryPoint GLCompute %main "main"
  1972. %void = OpTypeVoid
  1973. %func = OpTypeFunction %void
  1974. %bool = OpTypeBool
  1975. %f16 = OpTypeFloat 16
  1976. %f32 = OpTypeFloat 32
  1977. %u32 = OpTypeInt 32 0
  1978. %u32_1 = OpConstant %u32 1
  1979. %u32_16 = OpConstant %u32 16
  1980. %useA = OpConstant %u32 0
  1981. %subgroup = OpConstant %u32 3
  1982. %f16vec = OpTypeCooperativeVectorNV %f16 %u32_16
  1983. %f16_1 = OpConstant %f16 1
  1984. %f16vec_1 = OpConstantComposite %f16vec %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1 %f16_1
  1985. %main = OpFunction %void None %func
  1986. %main_entry = OpLabel
  1987. %insert = OpVectorInsertDynamic %f16vec %f16vec_1 %f16_1 %u32_1
  1988. %extract = OpVectorExtractDynamic %f16 %insert %u32_1
  1989. OpReturn
  1990. OpFunctionEnd)";
  1991. CompileSuccessfully(body.c_str());
  1992. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1993. }
  1994. } // namespace
  1995. } // namespace val
  1996. } // namespace spvtools