instruction_test.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  1. // Copyright (c) 2016 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 <memory>
  15. #include <string>
  16. #include <vector>
  17. #include "gmock/gmock.h"
  18. #include "source/opt/instruction.h"
  19. #include "source/opt/ir_context.h"
  20. #include "spirv-tools/libspirv.h"
  21. #include "test/opt/pass_fixture.h"
  22. #include "test/opt/pass_utils.h"
  23. #include "test/unit_spirv.h"
  24. namespace spvtools {
  25. namespace opt {
  26. namespace {
  27. using spvtest::MakeInstruction;
  28. using ::testing::Eq;
  29. using DescriptorTypeTest = PassTest<::testing::Test>;
  30. using OpaqueTypeTest = PassTest<::testing::Test>;
  31. using GetBaseTest = PassTest<::testing::Test>;
  32. using ValidBasePointerTest = PassTest<::testing::Test>;
  33. TEST(InstructionTest, CreateTrivial) {
  34. Instruction empty;
  35. EXPECT_EQ(SpvOpNop, empty.opcode());
  36. EXPECT_EQ(0u, empty.type_id());
  37. EXPECT_EQ(0u, empty.result_id());
  38. EXPECT_EQ(0u, empty.NumOperands());
  39. EXPECT_EQ(0u, empty.NumOperandWords());
  40. EXPECT_EQ(0u, empty.NumInOperandWords());
  41. EXPECT_EQ(empty.cend(), empty.cbegin());
  42. EXPECT_EQ(empty.end(), empty.begin());
  43. }
  44. TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
  45. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  46. Instruction inst(&context, SpvOpReturn);
  47. EXPECT_EQ(SpvOpReturn, inst.opcode());
  48. EXPECT_EQ(0u, inst.type_id());
  49. EXPECT_EQ(0u, inst.result_id());
  50. EXPECT_EQ(0u, inst.NumOperands());
  51. EXPECT_EQ(0u, inst.NumOperandWords());
  52. EXPECT_EQ(0u, inst.NumInOperandWords());
  53. EXPECT_EQ(inst.cend(), inst.cbegin());
  54. EXPECT_EQ(inst.end(), inst.begin());
  55. }
  56. // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
  57. uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
  58. 32, 1};
  59. // The operands that would be parsed from kSampleInstructionWords
  60. spv_parsed_operand_t kSampleParsedOperands[] = {
  61. {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
  62. {2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
  63. {3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
  64. };
  65. // A valid parse of kSampleParsedOperands.
  66. spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
  67. uint16_t(4),
  68. uint16_t(SpvOpTypeInt),
  69. SPV_EXT_INST_TYPE_NONE,
  70. 0, // type id
  71. 44, // result id
  72. kSampleParsedOperands,
  73. 3};
  74. // The words for an OpAccessChain instruction.
  75. uint32_t kSampleAccessChainInstructionWords[] = {
  76. (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
  77. // The operands that would be parsed from kSampleAccessChainInstructionWords.
  78. spv_parsed_operand_t kSampleAccessChainOperands[] = {
  79. {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
  80. {2, 1, SPV_OPERAND_TYPE_TYPE_ID, SPV_NUMBER_NONE, 0},
  81. {3, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
  82. {4, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
  83. {5, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
  84. {6, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
  85. };
  86. // A valid parse of kSampleAccessChainInstructionWords
  87. spv_parsed_instruction_t kSampleAccessChainInstruction = {
  88. kSampleAccessChainInstructionWords,
  89. uint16_t(7),
  90. uint16_t(SpvOpAccessChain),
  91. SPV_EXT_INST_TYPE_NONE,
  92. 100, // type id
  93. 101, // result id
  94. kSampleAccessChainOperands,
  95. 6};
  96. // The words for an OpControlBarrier instruction.
  97. uint32_t kSampleControlBarrierInstructionWords[] = {
  98. (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
  99. // The operands that would be parsed from kSampleControlBarrierInstructionWords.
  100. spv_parsed_operand_t kSampleControlBarrierOperands[] = {
  101. {1, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Execution
  102. {2, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Memory
  103. {3, 1, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_NUMBER_NONE,
  104. 0}, // Semantics
  105. };
  106. // A valid parse of kSampleControlBarrierInstructionWords
  107. spv_parsed_instruction_t kSampleControlBarrierInstruction = {
  108. kSampleControlBarrierInstructionWords,
  109. uint16_t(4),
  110. uint16_t(SpvOpControlBarrier),
  111. SPV_EXT_INST_TYPE_NONE,
  112. 0, // type id
  113. 0, // result id
  114. kSampleControlBarrierOperands,
  115. 3};
  116. TEST(InstructionTest, CreateWithOpcodeAndOperands) {
  117. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  118. Instruction inst(&context, kSampleParsedInstruction);
  119. EXPECT_EQ(SpvOpTypeInt, inst.opcode());
  120. EXPECT_EQ(0u, inst.type_id());
  121. EXPECT_EQ(44u, inst.result_id());
  122. EXPECT_EQ(3u, inst.NumOperands());
  123. EXPECT_EQ(3u, inst.NumOperandWords());
  124. EXPECT_EQ(2u, inst.NumInOperandWords());
  125. }
  126. TEST(InstructionTest, GetOperand) {
  127. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  128. Instruction inst(&context, kSampleParsedInstruction);
  129. EXPECT_THAT(inst.GetOperand(0).words, Eq(std::vector<uint32_t>{44}));
  130. EXPECT_THAT(inst.GetOperand(1).words, Eq(std::vector<uint32_t>{32}));
  131. EXPECT_THAT(inst.GetOperand(2).words, Eq(std::vector<uint32_t>{1}));
  132. }
  133. TEST(InstructionTest, GetInOperand) {
  134. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  135. Instruction inst(&context, kSampleParsedInstruction);
  136. EXPECT_THAT(inst.GetInOperand(0).words, Eq(std::vector<uint32_t>{32}));
  137. EXPECT_THAT(inst.GetInOperand(1).words, Eq(std::vector<uint32_t>{1}));
  138. }
  139. TEST(InstructionTest, OperandConstIterators) {
  140. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  141. Instruction inst(&context, kSampleParsedInstruction);
  142. // Spot check iteration across operands.
  143. auto cbegin = inst.cbegin();
  144. auto cend = inst.cend();
  145. EXPECT_NE(cend, inst.cbegin());
  146. auto citer = inst.cbegin();
  147. for (int i = 0; i < 3; ++i, ++citer) {
  148. const auto& operand = *citer;
  149. EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
  150. EXPECT_THAT(operand.words,
  151. Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
  152. EXPECT_NE(cend, citer);
  153. }
  154. EXPECT_EQ(cend, citer);
  155. // Check that cbegin and cend have not changed.
  156. EXPECT_EQ(cbegin, inst.cbegin());
  157. EXPECT_EQ(cend, inst.cend());
  158. // Check arithmetic.
  159. const Operand& operand2 = *(inst.cbegin() + 2);
  160. EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
  161. }
  162. TEST(InstructionTest, OperandIterators) {
  163. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  164. Instruction inst(&context, kSampleParsedInstruction);
  165. // Spot check iteration across operands, with mutable iterators.
  166. auto begin = inst.begin();
  167. auto end = inst.end();
  168. EXPECT_NE(end, inst.begin());
  169. auto iter = inst.begin();
  170. for (int i = 0; i < 3; ++i, ++iter) {
  171. const auto& operand = *iter;
  172. EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
  173. EXPECT_THAT(operand.words,
  174. Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
  175. EXPECT_NE(end, iter);
  176. }
  177. EXPECT_EQ(end, iter);
  178. // Check that begin and end have not changed.
  179. EXPECT_EQ(begin, inst.begin());
  180. EXPECT_EQ(end, inst.end());
  181. // Check arithmetic.
  182. Operand& operand2 = *(inst.begin() + 2);
  183. EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
  184. // Check mutation through an iterator.
  185. operand2.type = SPV_OPERAND_TYPE_TYPE_ID;
  186. EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type);
  187. }
  188. TEST(InstructionTest, ForInIdStandardIdTypes) {
  189. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  190. Instruction inst(&context, kSampleAccessChainInstruction);
  191. std::vector<uint32_t> ids;
  192. inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
  193. EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
  194. ids.clear();
  195. inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
  196. EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
  197. }
  198. TEST(InstructionTest, ForInIdNonstandardIdTypes) {
  199. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  200. Instruction inst(&context, kSampleControlBarrierInstruction);
  201. std::vector<uint32_t> ids;
  202. inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
  203. EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
  204. ids.clear();
  205. inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
  206. EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
  207. }
  208. TEST(InstructionTest, UniqueIds) {
  209. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  210. Instruction inst1(&context);
  211. Instruction inst2(&context);
  212. EXPECT_NE(inst1.unique_id(), inst2.unique_id());
  213. }
  214. TEST(InstructionTest, CloneUniqueIdDifferent) {
  215. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  216. Instruction inst(&context);
  217. std::unique_ptr<Instruction> clone(inst.Clone(&context));
  218. EXPECT_EQ(inst.context(), clone->context());
  219. EXPECT_NE(inst.unique_id(), clone->unique_id());
  220. }
  221. TEST(InstructionTest, CloneDifferentContext) {
  222. IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
  223. IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
  224. Instruction inst(&c1);
  225. std::unique_ptr<Instruction> clone(inst.Clone(&c2));
  226. EXPECT_EQ(&c1, inst.context());
  227. EXPECT_EQ(&c2, clone->context());
  228. EXPECT_NE(&c1, &c2);
  229. }
  230. TEST(InstructionTest, CloneDifferentContextDifferentUniqueId) {
  231. IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
  232. IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
  233. Instruction inst(&c1);
  234. Instruction other(&c2);
  235. std::unique_ptr<Instruction> clone(inst.Clone(&c2));
  236. EXPECT_EQ(&c2, clone->context());
  237. EXPECT_NE(other.unique_id(), clone->unique_id());
  238. }
  239. TEST(InstructionTest, EqualsEqualsOperator) {
  240. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  241. Instruction i1(&context);
  242. Instruction i2(&context);
  243. std::unique_ptr<Instruction> clone(i1.Clone(&context));
  244. EXPECT_TRUE(i1 == i1);
  245. EXPECT_FALSE(i1 == i2);
  246. EXPECT_FALSE(i1 == *clone);
  247. EXPECT_FALSE(i2 == *clone);
  248. }
  249. TEST(InstructionTest, LessThanOperator) {
  250. IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
  251. Instruction i1(&context);
  252. Instruction i2(&context);
  253. std::unique_ptr<Instruction> clone(i1.Clone(&context));
  254. EXPECT_TRUE(i1 < i2);
  255. EXPECT_TRUE(i1 < *clone);
  256. EXPECT_TRUE(i2 < *clone);
  257. }
  258. TEST_F(DescriptorTypeTest, StorageImage) {
  259. const std::string text = R"(
  260. OpCapability Shader
  261. %1 = OpExtInstImport "GLSL.std.450"
  262. OpMemoryModel Logical GLSL450
  263. OpEntryPoint Fragment %2 "main"
  264. OpExecutionMode %2 OriginUpperLeft
  265. OpSource GLSL 430
  266. OpName %3 "myStorageImage"
  267. OpDecorate %3 DescriptorSet 0
  268. OpDecorate %3 Binding 0
  269. %4 = OpTypeVoid
  270. %5 = OpTypeFunction %4
  271. %6 = OpTypeFloat 32
  272. %7 = OpTypeImage %6 2D 0 0 0 2 R32f
  273. %8 = OpTypePointer UniformConstant %7
  274. %3 = OpVariable %8 UniformConstant
  275. %2 = OpFunction %4 None %5
  276. %9 = OpLabel
  277. OpReturn
  278. OpFunctionEnd
  279. )";
  280. std::unique_ptr<IRContext> context =
  281. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  282. Instruction* type = context->get_def_use_mgr()->GetDef(8);
  283. EXPECT_TRUE(type->IsVulkanStorageImage());
  284. EXPECT_FALSE(type->IsVulkanSampledImage());
  285. EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
  286. EXPECT_FALSE(type->IsVulkanStorageBuffer());
  287. EXPECT_FALSE(type->IsVulkanUniformBuffer());
  288. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  289. EXPECT_FALSE(variable->IsReadOnlyVariable());
  290. }
  291. TEST_F(DescriptorTypeTest, SampledImage) {
  292. const std::string text = R"(
  293. OpCapability Shader
  294. %1 = OpExtInstImport "GLSL.std.450"
  295. OpMemoryModel Logical GLSL450
  296. OpEntryPoint Fragment %2 "main"
  297. OpExecutionMode %2 OriginUpperLeft
  298. OpSource GLSL 430
  299. OpName %3 "myStorageImage"
  300. OpDecorate %3 DescriptorSet 0
  301. OpDecorate %3 Binding 0
  302. %4 = OpTypeVoid
  303. %5 = OpTypeFunction %4
  304. %6 = OpTypeFloat 32
  305. %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
  306. %8 = OpTypePointer UniformConstant %7
  307. %3 = OpVariable %8 UniformConstant
  308. %2 = OpFunction %4 None %5
  309. %9 = OpLabel
  310. OpReturn
  311. OpFunctionEnd
  312. )";
  313. std::unique_ptr<IRContext> context =
  314. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  315. Instruction* type = context->get_def_use_mgr()->GetDef(8);
  316. EXPECT_FALSE(type->IsVulkanStorageImage());
  317. EXPECT_TRUE(type->IsVulkanSampledImage());
  318. EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
  319. EXPECT_FALSE(type->IsVulkanStorageBuffer());
  320. EXPECT_FALSE(type->IsVulkanUniformBuffer());
  321. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  322. EXPECT_TRUE(variable->IsReadOnlyVariable());
  323. }
  324. TEST_F(DescriptorTypeTest, StorageTexelBuffer) {
  325. const std::string text = R"(
  326. OpCapability Shader
  327. %1 = OpExtInstImport "GLSL.std.450"
  328. OpMemoryModel Logical GLSL450
  329. OpEntryPoint Fragment %2 "main"
  330. OpExecutionMode %2 OriginUpperLeft
  331. OpSource GLSL 430
  332. OpName %3 "myStorageImage"
  333. OpDecorate %3 DescriptorSet 0
  334. OpDecorate %3 Binding 0
  335. %4 = OpTypeVoid
  336. %5 = OpTypeFunction %4
  337. %6 = OpTypeFloat 32
  338. %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
  339. %8 = OpTypePointer UniformConstant %7
  340. %3 = OpVariable %8 UniformConstant
  341. %2 = OpFunction %4 None %5
  342. %9 = OpLabel
  343. OpReturn
  344. OpFunctionEnd
  345. )";
  346. std::unique_ptr<IRContext> context =
  347. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  348. Instruction* type = context->get_def_use_mgr()->GetDef(8);
  349. EXPECT_FALSE(type->IsVulkanStorageImage());
  350. EXPECT_FALSE(type->IsVulkanSampledImage());
  351. EXPECT_TRUE(type->IsVulkanStorageTexelBuffer());
  352. EXPECT_FALSE(type->IsVulkanStorageBuffer());
  353. EXPECT_FALSE(type->IsVulkanUniformBuffer());
  354. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  355. EXPECT_FALSE(variable->IsReadOnlyVariable());
  356. }
  357. TEST_F(DescriptorTypeTest, StorageBuffer) {
  358. const std::string text = R"(
  359. OpCapability Shader
  360. %1 = OpExtInstImport "GLSL.std.450"
  361. OpMemoryModel Logical GLSL450
  362. OpEntryPoint Fragment %2 "main"
  363. OpExecutionMode %2 OriginUpperLeft
  364. OpSource GLSL 430
  365. OpName %3 "myStorageImage"
  366. OpDecorate %3 DescriptorSet 0
  367. OpDecorate %3 Binding 0
  368. OpDecorate %9 BufferBlock
  369. %4 = OpTypeVoid
  370. %5 = OpTypeFunction %4
  371. %6 = OpTypeFloat 32
  372. %7 = OpTypeVector %6 4
  373. %8 = OpTypeRuntimeArray %7
  374. %9 = OpTypeStruct %8
  375. %10 = OpTypePointer Uniform %9
  376. %3 = OpVariable %10 Uniform
  377. %2 = OpFunction %4 None %5
  378. %11 = OpLabel
  379. OpReturn
  380. OpFunctionEnd
  381. )";
  382. std::unique_ptr<IRContext> context =
  383. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  384. Instruction* type = context->get_def_use_mgr()->GetDef(10);
  385. EXPECT_FALSE(type->IsVulkanStorageImage());
  386. EXPECT_FALSE(type->IsVulkanSampledImage());
  387. EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
  388. EXPECT_TRUE(type->IsVulkanStorageBuffer());
  389. EXPECT_FALSE(type->IsVulkanUniformBuffer());
  390. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  391. EXPECT_FALSE(variable->IsReadOnlyVariable());
  392. }
  393. TEST_F(DescriptorTypeTest, UniformBuffer) {
  394. const std::string text = R"(
  395. OpCapability Shader
  396. %1 = OpExtInstImport "GLSL.std.450"
  397. OpMemoryModel Logical GLSL450
  398. OpEntryPoint Fragment %2 "main"
  399. OpExecutionMode %2 OriginUpperLeft
  400. OpSource GLSL 430
  401. OpName %3 "myStorageImage"
  402. OpDecorate %3 DescriptorSet 0
  403. OpDecorate %3 Binding 0
  404. OpDecorate %9 Block
  405. %4 = OpTypeVoid
  406. %5 = OpTypeFunction %4
  407. %6 = OpTypeFloat 32
  408. %7 = OpTypeVector %6 4
  409. %8 = OpTypeRuntimeArray %7
  410. %9 = OpTypeStruct %8
  411. %10 = OpTypePointer Uniform %9
  412. %3 = OpVariable %10 Uniform
  413. %2 = OpFunction %4 None %5
  414. %11 = OpLabel
  415. OpReturn
  416. OpFunctionEnd
  417. )";
  418. std::unique_ptr<IRContext> context =
  419. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  420. Instruction* type = context->get_def_use_mgr()->GetDef(10);
  421. EXPECT_FALSE(type->IsVulkanStorageImage());
  422. EXPECT_FALSE(type->IsVulkanSampledImage());
  423. EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
  424. EXPECT_FALSE(type->IsVulkanStorageBuffer());
  425. EXPECT_TRUE(type->IsVulkanUniformBuffer());
  426. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  427. EXPECT_TRUE(variable->IsReadOnlyVariable());
  428. }
  429. TEST_F(DescriptorTypeTest, NonWritableIsReadOnly) {
  430. const std::string text = R"(
  431. OpCapability Shader
  432. %1 = OpExtInstImport "GLSL.std.450"
  433. OpMemoryModel Logical GLSL450
  434. OpEntryPoint Fragment %2 "main"
  435. OpExecutionMode %2 OriginUpperLeft
  436. OpSource GLSL 430
  437. OpName %3 "myStorageImage"
  438. OpDecorate %3 DescriptorSet 0
  439. OpDecorate %3 Binding 0
  440. OpDecorate %9 BufferBlock
  441. OpDecorate %3 NonWritable
  442. %4 = OpTypeVoid
  443. %5 = OpTypeFunction %4
  444. %6 = OpTypeFloat 32
  445. %7 = OpTypeVector %6 4
  446. %8 = OpTypeRuntimeArray %7
  447. %9 = OpTypeStruct %8
  448. %10 = OpTypePointer Uniform %9
  449. %3 = OpVariable %10 Uniform
  450. %2 = OpFunction %4 None %5
  451. %11 = OpLabel
  452. OpReturn
  453. OpFunctionEnd
  454. )";
  455. std::unique_ptr<IRContext> context =
  456. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  457. Instruction* variable = context->get_def_use_mgr()->GetDef(3);
  458. EXPECT_TRUE(variable->IsReadOnlyVariable());
  459. }
  460. TEST_F(OpaqueTypeTest, BaseOpaqueTypesShader) {
  461. const std::string text = R"(
  462. OpCapability Shader
  463. %1 = OpExtInstImport "GLSL.std.450"
  464. OpMemoryModel Logical GLSL450
  465. OpEntryPoint Fragment %2 "main"
  466. OpExecutionMode %2 OriginUpperLeft
  467. OpSource GLSL 430
  468. %3 = OpTypeVoid
  469. %4 = OpTypeFunction %3
  470. %5 = OpTypeFloat 32
  471. %6 = OpTypeImage %5 2D 1 0 0 1 Unknown
  472. %7 = OpTypeSampler
  473. %8 = OpTypeSampledImage %6
  474. %9 = OpTypeRuntimeArray %5
  475. %2 = OpFunction %3 None %4
  476. %10 = OpLabel
  477. OpReturn
  478. OpFunctionEnd
  479. )";
  480. std::unique_ptr<IRContext> context =
  481. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  482. Instruction* image_type = context->get_def_use_mgr()->GetDef(6);
  483. EXPECT_TRUE(image_type->IsOpaqueType());
  484. Instruction* sampler_type = context->get_def_use_mgr()->GetDef(7);
  485. EXPECT_TRUE(sampler_type->IsOpaqueType());
  486. Instruction* sampled_image_type = context->get_def_use_mgr()->GetDef(8);
  487. EXPECT_TRUE(sampled_image_type->IsOpaqueType());
  488. Instruction* runtime_array_type = context->get_def_use_mgr()->GetDef(9);
  489. EXPECT_TRUE(runtime_array_type->IsOpaqueType());
  490. Instruction* float_type = context->get_def_use_mgr()->GetDef(5);
  491. EXPECT_FALSE(float_type->IsOpaqueType());
  492. Instruction* void_type = context->get_def_use_mgr()->GetDef(3);
  493. EXPECT_FALSE(void_type->IsOpaqueType());
  494. }
  495. TEST_F(OpaqueTypeTest, OpaqueStructTypes) {
  496. const std::string text = R"(
  497. OpCapability Shader
  498. %1 = OpExtInstImport "GLSL.std.450"
  499. OpMemoryModel Logical GLSL450
  500. OpEntryPoint Fragment %2 "main"
  501. OpExecutionMode %2 OriginUpperLeft
  502. OpSource GLSL 430
  503. %3 = OpTypeVoid
  504. %4 = OpTypeFunction %3
  505. %5 = OpTypeFloat 32
  506. %6 = OpTypeRuntimeArray %5
  507. %7 = OpTypeStruct %6 %6
  508. %8 = OpTypeStruct %5 %6
  509. %9 = OpTypeStruct %6 %5
  510. %10 = OpTypeStruct %7
  511. %2 = OpFunction %3 None %4
  512. %11 = OpLabel
  513. OpReturn
  514. OpFunctionEnd
  515. )";
  516. std::unique_ptr<IRContext> context =
  517. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  518. for (int i = 7; i <= 10; i++) {
  519. Instruction* type = context->get_def_use_mgr()->GetDef(i);
  520. EXPECT_TRUE(type->IsOpaqueType());
  521. }
  522. }
  523. TEST_F(GetBaseTest, SampleImage) {
  524. const std::string text = R"(
  525. OpCapability Shader
  526. %1 = OpExtInstImport "GLSL.std.450"
  527. OpMemoryModel Logical GLSL450
  528. OpEntryPoint Fragment %2 "main"
  529. OpExecutionMode %2 OriginUpperLeft
  530. OpSource GLSL 430
  531. OpName %3 "myStorageImage"
  532. OpDecorate %3 DescriptorSet 0
  533. OpDecorate %3 Binding 0
  534. %4 = OpTypeVoid
  535. %5 = OpTypeFunction %4
  536. %6 = OpTypeFloat 32
  537. %7 = OpTypeVector %6 2
  538. %8 = OpTypeVector %6 4
  539. %9 = OpConstant %6 0
  540. %10 = OpConstantComposite %7 %9 %9
  541. %11 = OpTypeImage %6 2D 0 0 0 1 R32f
  542. %12 = OpTypePointer UniformConstant %11
  543. %3 = OpVariable %12 UniformConstant
  544. %13 = OpTypeSampledImage %11
  545. %14 = OpTypeSampler
  546. %15 = OpTypePointer UniformConstant %14
  547. %16 = OpVariable %15 UniformConstant
  548. %2 = OpFunction %4 None %5
  549. %17 = OpLabel
  550. %18 = OpLoad %11 %3
  551. %19 = OpLoad %14 %16
  552. %20 = OpSampledImage %13 %18 %19
  553. %21 = OpImageSampleImplicitLod %8 %20 %10
  554. OpReturn
  555. OpFunctionEnd
  556. )";
  557. std::unique_ptr<IRContext> context =
  558. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  559. Instruction* load = context->get_def_use_mgr()->GetDef(21);
  560. Instruction* base = context->get_def_use_mgr()->GetDef(20);
  561. EXPECT_TRUE(load->GetBaseAddress() == base);
  562. }
  563. TEST_F(GetBaseTest, PtrAccessChain) {
  564. const std::string text = R"(
  565. OpCapability VariablePointers
  566. OpMemoryModel Logical GLSL450
  567. OpEntryPoint Fragment %1 "PSMain" %2
  568. OpExecutionMode %1 OriginUpperLeft
  569. %void = OpTypeVoid
  570. %4 = OpTypeFunction %void
  571. %float = OpTypeFloat 32
  572. %v4float = OpTypeVector %float 4
  573. %int = OpTypeInt 32 8388353
  574. %int_0 = OpConstant %int 0
  575. %_ptr_Function_v4float = OpTypePointer Function %v4float
  576. %2 = OpVariable %_ptr_Function_v4float Input
  577. %1 = OpFunction %void None %4
  578. %10 = OpLabel
  579. %11 = OpPtrAccessChain %_ptr_Function_v4float %2 %int_0
  580. %12 = OpLoad %v4float %11
  581. OpReturn
  582. OpFunctionEnd
  583. )";
  584. std::unique_ptr<IRContext> context =
  585. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  586. Instruction* load = context->get_def_use_mgr()->GetDef(12);
  587. Instruction* base = context->get_def_use_mgr()->GetDef(2);
  588. EXPECT_TRUE(load->GetBaseAddress() == base);
  589. }
  590. TEST_F(GetBaseTest, ImageRead) {
  591. const std::string text = R"(
  592. OpCapability Shader
  593. %1 = OpExtInstImport "GLSL.std.450"
  594. OpMemoryModel Logical GLSL450
  595. OpEntryPoint Fragment %2 "main"
  596. OpExecutionMode %2 OriginUpperLeft
  597. OpSource GLSL 430
  598. OpName %3 "myStorageImage"
  599. OpDecorate %3 DescriptorSet 0
  600. OpDecorate %3 Binding 0
  601. %4 = OpTypeVoid
  602. %5 = OpTypeFunction %4
  603. %6 = OpTypeInt 32 0
  604. %7 = OpTypeVector %6 2
  605. %8 = OpConstant %6 0
  606. %9 = OpConstantComposite %7 %8 %8
  607. %10 = OpTypeImage %6 2D 0 0 0 2 R32f
  608. %11 = OpTypePointer UniformConstant %10
  609. %3 = OpVariable %11 UniformConstant
  610. %2 = OpFunction %4 None %5
  611. %12 = OpLabel
  612. %13 = OpLoad %10 %3
  613. %14 = OpImageRead %6 %13 %9
  614. OpReturn
  615. OpFunctionEnd
  616. )";
  617. std::unique_ptr<IRContext> context =
  618. BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
  619. Instruction* load = context->get_def_use_mgr()->GetDef(14);
  620. Instruction* base = context->get_def_use_mgr()->GetDef(13);
  621. EXPECT_TRUE(load->GetBaseAddress() == base);
  622. }
  623. TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointersStorageBuffer) {
  624. const std::string text = R"(
  625. OpCapability Shader
  626. OpMemoryModel Logical GLSL450
  627. OpEntryPoint Fragment %1 "func"
  628. %2 = OpTypeVoid
  629. %3 = OpTypeInt 32 0
  630. %4 = OpTypePointer StorageBuffer %3
  631. %5 = OpVariable %4 StorageBuffer
  632. %6 = OpTypeFunction %2
  633. %7 = OpTypeBool
  634. %8 = OpConstantTrue %7
  635. %1 = OpFunction %2 None %6
  636. %9 = OpLabel
  637. %10 = OpSelect %4 %8 %5 %5
  638. OpReturn
  639. OpFunctionEnd
  640. )";
  641. std::unique_ptr<IRContext> context =
  642. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  643. EXPECT_NE(context, nullptr);
  644. Instruction* select = context->get_def_use_mgr()->GetDef(10);
  645. EXPECT_NE(select, nullptr);
  646. EXPECT_FALSE(select->IsValidBasePointer());
  647. }
  648. TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointers) {
  649. const std::string text = R"(
  650. OpCapability Shader
  651. OpCapability VariablePointersStorageBuffer
  652. OpMemoryModel Logical GLSL450
  653. OpEntryPoint Fragment %1 "func"
  654. %2 = OpTypeVoid
  655. %3 = OpTypeInt 32 0
  656. %4 = OpTypePointer Workgroup %3
  657. %5 = OpVariable %4 Workgroup
  658. %6 = OpTypeFunction %2
  659. %7 = OpTypeBool
  660. %8 = OpConstantTrue %7
  661. %1 = OpFunction %2 None %6
  662. %9 = OpLabel
  663. %10 = OpSelect %4 %8 %5 %5
  664. OpReturn
  665. OpFunctionEnd
  666. )";
  667. std::unique_ptr<IRContext> context =
  668. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  669. EXPECT_NE(context, nullptr);
  670. Instruction* select = context->get_def_use_mgr()->GetDef(10);
  671. EXPECT_NE(select, nullptr);
  672. EXPECT_FALSE(select->IsValidBasePointer());
  673. }
  674. TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointersStorageBuffer) {
  675. const std::string text = R"(
  676. OpCapability Shader
  677. OpCapability VariablePointersStorageBuffer
  678. OpMemoryModel Logical GLSL450
  679. OpEntryPoint Fragment %1 "func"
  680. %2 = OpTypeVoid
  681. %3 = OpTypeInt 32 0
  682. %4 = OpTypePointer StorageBuffer %3
  683. %5 = OpVariable %4 StorageBuffer
  684. %6 = OpTypeFunction %2
  685. %7 = OpTypeBool
  686. %8 = OpConstantTrue %7
  687. %1 = OpFunction %2 None %6
  688. %9 = OpLabel
  689. %10 = OpSelect %4 %8 %5 %5
  690. OpReturn
  691. OpFunctionEnd
  692. )";
  693. std::unique_ptr<IRContext> context =
  694. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  695. EXPECT_NE(context, nullptr);
  696. Instruction* select = context->get_def_use_mgr()->GetDef(10);
  697. EXPECT_NE(select, nullptr);
  698. EXPECT_TRUE(select->IsValidBasePointer());
  699. }
  700. TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointers) {
  701. const std::string text = R"(
  702. OpCapability Shader
  703. OpCapability VariablePointers
  704. OpMemoryModel Logical GLSL450
  705. OpEntryPoint Fragment %1 "func"
  706. %2 = OpTypeVoid
  707. %3 = OpTypeInt 32 0
  708. %4 = OpTypePointer Workgroup %3
  709. %5 = OpVariable %4 Workgroup
  710. %6 = OpTypeFunction %2
  711. %7 = OpTypeBool
  712. %8 = OpConstantTrue %7
  713. %1 = OpFunction %2 None %6
  714. %9 = OpLabel
  715. %10 = OpSelect %4 %8 %5 %5
  716. OpReturn
  717. OpFunctionEnd
  718. )";
  719. std::unique_ptr<IRContext> context =
  720. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  721. EXPECT_NE(context, nullptr);
  722. Instruction* select = context->get_def_use_mgr()->GetDef(10);
  723. EXPECT_NE(select, nullptr);
  724. EXPECT_TRUE(select->IsValidBasePointer());
  725. }
  726. TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointersStorageBuffer) {
  727. const std::string text = R"(
  728. OpCapability Shader
  729. OpMemoryModel Logical GLSL450
  730. OpEntryPoint Fragment %1 "func"
  731. %2 = OpTypeVoid
  732. %3 = OpTypeInt 32 0
  733. %4 = OpTypePointer StorageBuffer %3
  734. %5 = OpConstantNull %4
  735. %6 = OpTypeFunction %2
  736. %1 = OpFunction %2 None %6
  737. %7 = OpLabel
  738. OpReturn
  739. OpFunctionEnd
  740. )";
  741. std::unique_ptr<IRContext> context =
  742. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  743. EXPECT_NE(context, nullptr);
  744. Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
  745. EXPECT_NE(null_inst, nullptr);
  746. EXPECT_FALSE(null_inst->IsValidBasePointer());
  747. }
  748. TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointers) {
  749. const std::string text = R"(
  750. OpCapability Shader
  751. OpCapability VariablePointersStorageBuffer
  752. OpMemoryModel Logical GLSL450
  753. OpEntryPoint Fragment %1 "func"
  754. %2 = OpTypeVoid
  755. %3 = OpTypeInt 32 0
  756. %4 = OpTypePointer Workgroup %3
  757. %5 = OpConstantNull %4
  758. %6 = OpTypeFunction %2
  759. %1 = OpFunction %2 None %6
  760. %7 = OpLabel
  761. OpReturn
  762. OpFunctionEnd
  763. )";
  764. std::unique_ptr<IRContext> context =
  765. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  766. EXPECT_NE(context, nullptr);
  767. Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
  768. EXPECT_NE(null_inst, nullptr);
  769. EXPECT_FALSE(null_inst->IsValidBasePointer());
  770. }
  771. TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointersStorageBuffer) {
  772. const std::string text = R"(
  773. OpCapability Shader
  774. OpCapability VariablePointersStorageBuffer
  775. OpMemoryModel Logical GLSL450
  776. OpEntryPoint Fragment %1 "func"
  777. %2 = OpTypeVoid
  778. %3 = OpTypeInt 32 0
  779. %4 = OpTypePointer StorageBuffer %3
  780. %5 = OpConstantNull %4
  781. %6 = OpTypeFunction %2
  782. %1 = OpFunction %2 None %6
  783. %9 = OpLabel
  784. OpReturn
  785. OpFunctionEnd
  786. )";
  787. std::unique_ptr<IRContext> context =
  788. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  789. EXPECT_NE(context, nullptr);
  790. Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
  791. EXPECT_NE(null_inst, nullptr);
  792. EXPECT_TRUE(null_inst->IsValidBasePointer());
  793. }
  794. TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointers) {
  795. const std::string text = R"(
  796. OpCapability Shader
  797. OpCapability VariablePointers
  798. OpMemoryModel Logical GLSL450
  799. OpEntryPoint Fragment %1 "func"
  800. %2 = OpTypeVoid
  801. %3 = OpTypeInt 32 0
  802. %4 = OpTypePointer Workgroup %3
  803. %5 = OpConstantNull %4
  804. %6 = OpTypeFunction %2
  805. %1 = OpFunction %2 None %6
  806. %7 = OpLabel
  807. OpReturn
  808. OpFunctionEnd
  809. )";
  810. std::unique_ptr<IRContext> context =
  811. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  812. EXPECT_NE(context, nullptr);
  813. Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
  814. EXPECT_NE(null_inst, nullptr);
  815. EXPECT_TRUE(null_inst->IsValidBasePointer());
  816. }
  817. TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointersStorageBuffer) {
  818. const std::string text = R"(
  819. OpCapability Shader
  820. OpMemoryModel Logical GLSL450
  821. OpEntryPoint Fragment %1 "func"
  822. %2 = OpTypeVoid
  823. %3 = OpTypeInt 32 0
  824. %4 = OpTypePointer StorageBuffer %3
  825. %5 = OpVariable %4 StorageBuffer
  826. %6 = OpTypeFunction %2
  827. %1 = OpFunction %2 None %6
  828. %7 = OpLabel
  829. OpBranch %8
  830. %8 = OpLabel
  831. %9 = OpPhi %4 %5 %7
  832. OpReturn
  833. OpFunctionEnd
  834. )";
  835. std::unique_ptr<IRContext> context =
  836. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  837. EXPECT_NE(context, nullptr);
  838. Instruction* phi = context->get_def_use_mgr()->GetDef(9);
  839. EXPECT_NE(phi, nullptr);
  840. EXPECT_FALSE(phi->IsValidBasePointer());
  841. }
  842. TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointers) {
  843. const std::string text = R"(
  844. OpCapability Shader
  845. OpCapability VariablePointersStorageBuffer
  846. OpMemoryModel Logical GLSL450
  847. OpEntryPoint Fragment %1 "func"
  848. %2 = OpTypeVoid
  849. %3 = OpTypeInt 32 0
  850. %4 = OpTypePointer Workgroup %3
  851. %5 = OpVariable %4 Workgroup
  852. %6 = OpTypeFunction %2
  853. %1 = OpFunction %2 None %6
  854. %7 = OpLabel
  855. OpBranch %8
  856. %8 = OpLabel
  857. %9 = OpPhi %4 %5 %7
  858. OpReturn
  859. OpFunctionEnd
  860. )";
  861. std::unique_ptr<IRContext> context =
  862. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  863. EXPECT_NE(context, nullptr);
  864. Instruction* phi = context->get_def_use_mgr()->GetDef(9);
  865. EXPECT_NE(phi, nullptr);
  866. EXPECT_FALSE(phi->IsValidBasePointer());
  867. }
  868. TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointersStorageBuffer) {
  869. const std::string text = R"(
  870. OpCapability Shader
  871. OpCapability VariablePointersStorageBuffer
  872. OpMemoryModel Logical GLSL450
  873. OpEntryPoint Fragment %1 "func"
  874. %2 = OpTypeVoid
  875. %3 = OpTypeInt 32 0
  876. %4 = OpTypePointer StorageBuffer %3
  877. %5 = OpVariable %4 StorageBuffer
  878. %6 = OpTypeFunction %2
  879. %1 = OpFunction %2 None %6
  880. %7 = OpLabel
  881. OpBranch %8
  882. %8 = OpLabel
  883. %9 = OpPhi %4 %5 %7
  884. OpReturn
  885. OpFunctionEnd
  886. )";
  887. std::unique_ptr<IRContext> context =
  888. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  889. EXPECT_NE(context, nullptr);
  890. Instruction* phi = context->get_def_use_mgr()->GetDef(9);
  891. EXPECT_NE(phi, nullptr);
  892. EXPECT_TRUE(phi->IsValidBasePointer());
  893. }
  894. TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointers) {
  895. const std::string text = R"(
  896. OpCapability Shader
  897. OpCapability VariablePointers
  898. OpMemoryModel Logical GLSL450
  899. OpEntryPoint Fragment %1 "func"
  900. %2 = OpTypeVoid
  901. %3 = OpTypeInt 32 0
  902. %4 = OpTypePointer Workgroup %3
  903. %5 = OpVariable %4 Workgroup
  904. %6 = OpTypeFunction %2
  905. %1 = OpFunction %2 None %6
  906. %7 = OpLabel
  907. OpBranch %8
  908. %8 = OpLabel
  909. %9 = OpPhi %4 %5 %7
  910. OpReturn
  911. OpFunctionEnd
  912. )";
  913. std::unique_ptr<IRContext> context =
  914. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  915. EXPECT_NE(context, nullptr);
  916. Instruction* phi = context->get_def_use_mgr()->GetDef(9);
  917. EXPECT_NE(phi, nullptr);
  918. EXPECT_TRUE(phi->IsValidBasePointer());
  919. }
  920. TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointersStorageBuffer) {
  921. const std::string text = R"(
  922. OpCapability Shader
  923. OpMemoryModel Logical GLSL450
  924. OpEntryPoint Fragment %1 "func"
  925. %2 = OpTypeVoid
  926. %3 = OpTypeInt 32 0
  927. %4 = OpTypePointer StorageBuffer %3
  928. %5 = OpConstantNull %4
  929. %6 = OpTypeFunction %2
  930. %7 = OpTypeFunction %4
  931. %1 = OpFunction %2 None %6
  932. %8 = OpLabel
  933. %9 = OpFunctionCall %4 %10
  934. OpReturn
  935. OpFunctionEnd
  936. %10 = OpFunction %4 None %7
  937. %11 = OpLabel
  938. OpReturnValue %5
  939. OpFunctionEnd
  940. )";
  941. std::unique_ptr<IRContext> context =
  942. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  943. EXPECT_NE(context, nullptr);
  944. Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
  945. EXPECT_NE(null_inst, nullptr);
  946. EXPECT_FALSE(null_inst->IsValidBasePointer());
  947. }
  948. TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointers) {
  949. const std::string text = R"(
  950. OpCapability Shader
  951. OpCapability VariablePointersStorageBuffer
  952. OpMemoryModel Logical GLSL450
  953. OpEntryPoint Fragment %1 "func"
  954. %2 = OpTypeVoid
  955. %3 = OpTypeInt 32 0
  956. %4 = OpTypePointer Workgroup %3
  957. %5 = OpConstantNull %4
  958. %6 = OpTypeFunction %2
  959. %7 = OpTypeFunction %4
  960. %1 = OpFunction %2 None %6
  961. %8 = OpLabel
  962. %9 = OpFunctionCall %4 %10
  963. OpReturn
  964. OpFunctionEnd
  965. %10 = OpFunction %4 None %7
  966. %11 = OpLabel
  967. OpReturnValue %5
  968. OpFunctionEnd
  969. )";
  970. std::unique_ptr<IRContext> context =
  971. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  972. EXPECT_NE(context, nullptr);
  973. Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
  974. EXPECT_NE(null_inst, nullptr);
  975. EXPECT_FALSE(null_inst->IsValidBasePointer());
  976. }
  977. TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointersStorageBuffer) {
  978. const std::string text = R"(
  979. OpCapability Shader
  980. OpCapability VariablePointersStorageBuffer
  981. OpMemoryModel Logical GLSL450
  982. OpEntryPoint Fragment %1 "func"
  983. %2 = OpTypeVoid
  984. %3 = OpTypeInt 32 0
  985. %4 = OpTypePointer StorageBuffer %3
  986. %5 = OpConstantNull %4
  987. %6 = OpTypeFunction %2
  988. %7 = OpTypeFunction %4
  989. %1 = OpFunction %2 None %6
  990. %8 = OpLabel
  991. %9 = OpFunctionCall %4 %10
  992. OpReturn
  993. OpFunctionEnd
  994. %10 = OpFunction %4 None %7
  995. %11 = OpLabel
  996. OpReturnValue %5
  997. OpFunctionEnd
  998. )";
  999. std::unique_ptr<IRContext> context =
  1000. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  1001. EXPECT_NE(context, nullptr);
  1002. Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
  1003. EXPECT_NE(null_inst, nullptr);
  1004. EXPECT_TRUE(null_inst->IsValidBasePointer());
  1005. }
  1006. TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointers) {
  1007. const std::string text = R"(
  1008. OpCapability Shader
  1009. OpCapability VariablePointers
  1010. OpMemoryModel Logical GLSL450
  1011. OpEntryPoint Fragment %1 "func"
  1012. %2 = OpTypeVoid
  1013. %3 = OpTypeInt 32 0
  1014. %4 = OpTypePointer Workgroup %3
  1015. %5 = OpConstantNull %4
  1016. %6 = OpTypeFunction %2
  1017. %7 = OpTypeFunction %4
  1018. %1 = OpFunction %2 None %6
  1019. %8 = OpLabel
  1020. %9 = OpFunctionCall %4 %10
  1021. OpReturn
  1022. OpFunctionEnd
  1023. %10 = OpFunction %4 None %7
  1024. %11 = OpLabel
  1025. OpReturnValue %5
  1026. OpFunctionEnd
  1027. )";
  1028. std::unique_ptr<IRContext> context =
  1029. BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
  1030. EXPECT_NE(context, nullptr);
  1031. Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
  1032. EXPECT_NE(null_inst, nullptr);
  1033. EXPECT_TRUE(null_inst->IsValidBasePointer());
  1034. }
  1035. } // namespace
  1036. } // namespace opt
  1037. } // namespace spvtools