blob: d2bfcc51c6c305a4e5605d6055b9189d990149d5 [file] [log] [blame]
Nicolas Capens513a1162018-11-13 13:40:29 -05001// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
Alexis Hetu0b3d56a2018-10-18 10:41:32 -04002//
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
Nicolas Capens513a1162018-11-13 13:40:29 -050015// Vulkan unit tests that provide coverage for functionality not tested by
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040016// the dEQP test suite. Also used as a smoke test.
17
Ben Clayton654540e2019-02-01 13:08:23 +000018#include "Driver.hpp"
Ben Claytonabb57852019-03-01 14:33:35 +000019#include "Device.hpp"
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040020
Ben Clayton654540e2019-02-01 13:08:23 +000021#include "gmock/gmock.h"
22#include "gtest/gtest.h"
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040023
Ben Claytonabb57852019-03-01 14:33:35 +000024#include "spirv-tools/libspirv.hpp"
25
26#include <sstream>
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040027#include <cstring>
28
Ben Clayton756b54d2019-03-21 18:31:29 +000029namespace
30{
31 size_t alignUp(size_t val, size_t alignment)
32 {
33 return alignment * ((val + alignment - 1) / alignment);
34 }
35} // anonymous namespace
36
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040037class SwiftShaderVulkanTest : public testing::Test
38{
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040039};
40
Nicolas Capensdc853642018-11-19 15:50:18 -050041TEST_F(SwiftShaderVulkanTest, ICD_Check)
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040042{
Ben Clayton654540e2019-02-01 13:08:23 +000043 Driver driver;
44 ASSERT_TRUE(driver.loadSwiftShader());
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040045
Ben Clayton654540e2019-02-01 13:08:23 +000046 auto createInstance = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance");
47 EXPECT_NE(createInstance, nullptr);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040048
Ben Clayton654540e2019-02-01 13:08:23 +000049 auto enumerateInstanceExtensionProperties =
50 driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
51 EXPECT_NE(enumerateInstanceExtensionProperties, nullptr);
Nicolas Capensdc853642018-11-19 15:50:18 -050052
Ben Clayton654540e2019-02-01 13:08:23 +000053 auto enumerateInstanceLayerProperties =
54 driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties");
55 EXPECT_NE(enumerateInstanceLayerProperties, nullptr);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040056
Ben Clayton654540e2019-02-01 13:08:23 +000057 auto enumerateInstanceVersion = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
58 EXPECT_NE(enumerateInstanceVersion, nullptr);
59
60 auto bad_function = driver.vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "bad_function");
61 EXPECT_EQ(bad_function, nullptr);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040062}
63
64TEST_F(SwiftShaderVulkanTest, Version)
65{
Ben Clayton654540e2019-02-01 13:08:23 +000066 Driver driver;
67 ASSERT_TRUE(driver.loadSwiftShader());
Nicolas Capensdc853642018-11-19 15:50:18 -050068
Ben Clayton654540e2019-02-01 13:08:23 +000069 uint32_t apiVersion = 0;
70 VkResult result = driver.vkEnumerateInstanceVersion(&apiVersion);
71 EXPECT_EQ(apiVersion, (uint32_t)VK_API_VERSION_1_1);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040072
Ben Clayton654540e2019-02-01 13:08:23 +000073 const VkInstanceCreateInfo createInfo = {
74 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
75 nullptr, // pNext
76 0, // flags
77 nullptr, // pApplicationInfo
78 0, // enabledLayerCount
79 nullptr, // ppEnabledLayerNames
80 0, // enabledExtensionCount
81 nullptr, // ppEnabledExtensionNames
82 };
83 VkInstance instance = VK_NULL_HANDLE;
84 result = driver.vkCreateInstance(&createInfo, nullptr, &instance);
85 EXPECT_EQ(result, VK_SUCCESS);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040086
Ben Clayton654540e2019-02-01 13:08:23 +000087 ASSERT_TRUE(driver.resolve(instance));
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040088
Ben Clayton654540e2019-02-01 13:08:23 +000089 uint32_t pPhysicalDeviceCount = 0;
90 result = driver.vkEnumeratePhysicalDevices(instance, &pPhysicalDeviceCount, nullptr);
91 EXPECT_EQ(result, VK_SUCCESS);
92 EXPECT_EQ(pPhysicalDeviceCount, 1U);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -040093
Ben Clayton654540e2019-02-01 13:08:23 +000094 VkPhysicalDevice pPhysicalDevice = VK_NULL_HANDLE;
95 result = driver.vkEnumeratePhysicalDevices(instance, &pPhysicalDeviceCount, &pPhysicalDevice);
96 EXPECT_EQ(result, VK_SUCCESS);
97 EXPECT_NE(pPhysicalDevice, (VkPhysicalDevice)VK_NULL_HANDLE);
98
99 VkPhysicalDeviceProperties physicalDeviceProperties;
100 driver.vkGetPhysicalDeviceProperties(pPhysicalDevice, &physicalDeviceProperties);
101 EXPECT_EQ(physicalDeviceProperties.apiVersion, (uint32_t)VK_API_VERSION_1_1);
102 EXPECT_EQ(physicalDeviceProperties.deviceID, 0xC0DEU);
103 EXPECT_EQ(physicalDeviceProperties.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
104
105 EXPECT_EQ(strncmp(physicalDeviceProperties.deviceName, "SwiftShader Device", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE), 0);
Alexis Hetu0b3d56a2018-10-18 10:41:32 -0400106}
Ben Claytonabb57852019-03-01 14:33:35 +0000107
108std::vector<uint32_t> compileSpirv(const char* assembly)
109{
110 spvtools::SpirvTools core(SPV_ENV_VULKAN_1_0);
111
112 core.SetMessageConsumer([](spv_message_level_t, const char*, const spv_position_t& p, const char* m) {
113 FAIL() << p.line << ":" << p.column << ": " << m;
114 });
115
116 std::vector<uint32_t> spirv;
117 EXPECT_TRUE(core.Assemble(assembly, &spirv));
118 EXPECT_TRUE(core.Validate(spirv));
119
120 // Warn if the disassembly does not match the source assembly.
121 // We do this as debugging tests in the debugger is often made much harder
122 // if the SSA names (%X) in the debugger do not match the source.
123 std::string disassembled;
124 core.Disassemble(spirv, &disassembled, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
125 if (disassembled != assembly)
126 {
127 printf("-- WARNING: Disassembly does not match assembly: ---\n\n");
128
129 auto splitLines = [](const std::string& str) -> std::vector<std::string>
130 {
131 std::stringstream ss(str);
132 std::vector<std::string> out;
133 std::string line;
134 while (std::getline(ss, line, '\n')) { out.push_back(line); }
135 return out;
136 };
137
138 auto srcLines = splitLines(std::string(assembly));
139 auto disLines = splitLines(disassembled);
140
141 for (size_t line = 0; line < srcLines.size() && line < disLines.size(); line++)
142 {
143 auto srcLine = (line < srcLines.size()) ? srcLines[line] : "<missing>";
144 auto disLine = (line < disLines.size()) ? disLines[line] : "<missing>";
145 if (srcLine != disLine)
146 {
147 printf("%zu: '%s' != '%s'\n", line, srcLine.c_str(), disLine.c_str());
148 }
149 }
150 printf("\n\n---\n");
151 }
152
153 return spirv;
154}
155
156#define VK_ASSERT(x) ASSERT_EQ(x, VK_SUCCESS)
157
158struct ComputeParams
159{
Ben Claytone37ce612019-03-13 19:57:42 +0000160 size_t numElements;
Ben Claytonabb57852019-03-01 14:33:35 +0000161 int localSizeX;
162 int localSizeY;
163 int localSizeZ;
Ben Claytone37ce612019-03-13 19:57:42 +0000164
165 friend std::ostream& operator<<(std::ostream& os, const ComputeParams& params) {
166 return os << "ComputeParams{" <<
167 "numElements: " << params.numElements << ", " <<
168 "localSizeX: " << params.localSizeX << ", " <<
169 "localSizeY: " << params.localSizeY << ", " <<
170 "localSizeZ: " << params.localSizeZ <<
171 "}";
172 }
Ben Claytonabb57852019-03-01 14:33:35 +0000173};
174
Ben Claytone37ce612019-03-13 19:57:42 +0000175// Base class for compute tests that read from an input buffer and write to an
176// output buffer of same length.
177class SwiftShaderVulkanBufferToBufferComputeTest : public testing::TestWithParam<ComputeParams>
Ben Claytonabb57852019-03-01 14:33:35 +0000178{
Ben Claytone37ce612019-03-13 19:57:42 +0000179public:
180 void test(const std::string& shader,
181 std::function<uint32_t(uint32_t idx)> input,
182 std::function<uint32_t(uint32_t idx)> expected);
183};
184
185void SwiftShaderVulkanBufferToBufferComputeTest::test(
186 const std::string& shader,
187 std::function<uint32_t(uint32_t idx)> input,
188 std::function<uint32_t(uint32_t idx)> expected)
189{
190 auto code = compileSpirv(shader.c_str());
191
Ben Claytonabb57852019-03-01 14:33:35 +0000192 Driver driver;
193 ASSERT_TRUE(driver.loadSwiftShader());
194
Ben Claytonabb57852019-03-01 14:33:35 +0000195 const VkInstanceCreateInfo createInfo = {
196 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
197 nullptr, // pNext
198 0, // flags
199 nullptr, // pApplicationInfo
200 0, // enabledLayerCount
201 nullptr, // ppEnabledLayerNames
202 0, // enabledExtensionCount
203 nullptr, // ppEnabledExtensionNames
204 };
205
206 VkInstance instance = VK_NULL_HANDLE;
207 VK_ASSERT(driver.vkCreateInstance(&createInfo, nullptr, &instance));
208
209 ASSERT_TRUE(driver.resolve(instance));
210
Ben Clayton40f3d982019-03-21 18:26:46 +0000211 std::unique_ptr<Device> device;
212 VK_ASSERT(Device::CreateComputeDevice(&driver, instance, device));
213 ASSERT_TRUE(device->IsValid());
Ben Claytonabb57852019-03-01 14:33:35 +0000214
Ben Claytone37ce612019-03-13 19:57:42 +0000215 // struct Buffers
216 // {
Ben Clayton756b54d2019-03-21 18:31:29 +0000217 // uint32_t pad0[63];
Ben Claytone37ce612019-03-13 19:57:42 +0000218 // uint32_t magic0;
Ben Clayton756b54d2019-03-21 18:31:29 +0000219 // uint32_t in[NUM_ELEMENTS]; // Aligned to 0x100
Ben Claytone37ce612019-03-13 19:57:42 +0000220 // uint32_t magic1;
Ben Clayton756b54d2019-03-21 18:31:29 +0000221 // uint32_t pad1[N];
Ben Claytone37ce612019-03-13 19:57:42 +0000222 // uint32_t magic2;
Ben Clayton756b54d2019-03-21 18:31:29 +0000223 // uint32_t out[NUM_ELEMENTS]; // Aligned to 0x100
224 // uint32_t magic3;
Ben Claytone37ce612019-03-13 19:57:42 +0000225 // };
226 static constexpr uint32_t magic0 = 0x01234567;
227 static constexpr uint32_t magic1 = 0x89abcdef;
228 static constexpr uint32_t magic2 = 0xfedcba99;
Ben Clayton756b54d2019-03-21 18:31:29 +0000229 static constexpr uint32_t magic3 = 0x87654321;
Ben Claytone37ce612019-03-13 19:57:42 +0000230 size_t numElements = GetParam().numElements;
Ben Clayton756b54d2019-03-21 18:31:29 +0000231 size_t alignElements = 0x100 / sizeof(uint32_t);
232 size_t magic0Offset = alignElements - 1;
Ben Claytone37ce612019-03-13 19:57:42 +0000233 size_t inOffset = 1 + magic0Offset;
234 size_t magic1Offset = numElements + inOffset;
Ben Clayton756b54d2019-03-21 18:31:29 +0000235 size_t magic2Offset = alignUp(magic1Offset+1, alignElements) - 1;
236 size_t outOffset = 1 + magic2Offset;
237 size_t magic3Offset = numElements + outOffset;
238 size_t buffersTotalElements = alignUp(1 + magic3Offset, alignElements);
Ben Claytone37ce612019-03-13 19:57:42 +0000239 size_t buffersSize = sizeof(uint32_t) * buffersTotalElements;
Ben Claytonabb57852019-03-01 14:33:35 +0000240
241 VkDeviceMemory memory;
Ben Clayton40f3d982019-03-21 18:26:46 +0000242 VK_ASSERT(device->AllocateMemory(buffersSize,
Ben Claytonabb57852019-03-01 14:33:35 +0000243 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
244 &memory));
245
Ben Claytone37ce612019-03-13 19:57:42 +0000246 uint32_t* buffers;
Ben Clayton40f3d982019-03-21 18:26:46 +0000247 VK_ASSERT(device->MapMemory(memory, 0, buffersSize, 0, (void**)&buffers));
Ben Claytonabb57852019-03-01 14:33:35 +0000248
Ben Claytone37ce612019-03-13 19:57:42 +0000249 buffers[magic0Offset] = magic0;
250 buffers[magic1Offset] = magic1;
251 buffers[magic2Offset] = magic2;
Ben Clayton756b54d2019-03-21 18:31:29 +0000252 buffers[magic3Offset] = magic3;
Ben Claytonabb57852019-03-01 14:33:35 +0000253
Ben Claytone37ce612019-03-13 19:57:42 +0000254 for(size_t i = 0; i < numElements; i++)
Ben Claytonabb57852019-03-01 14:33:35 +0000255 {
Ben Claytone37ce612019-03-13 19:57:42 +0000256 buffers[inOffset + i] = input(i);
Ben Claytonabb57852019-03-01 14:33:35 +0000257 }
258
Ben Clayton40f3d982019-03-21 18:26:46 +0000259 device->UnmapMemory(memory);
Ben Claytonabb57852019-03-01 14:33:35 +0000260 buffers = nullptr;
261
262 VkBuffer bufferIn;
Ben Clayton40f3d982019-03-21 18:26:46 +0000263 VK_ASSERT(device->CreateStorageBuffer(memory,
Ben Claytone37ce612019-03-13 19:57:42 +0000264 sizeof(uint32_t) * numElements,
265 sizeof(uint32_t) * inOffset,
266 &bufferIn));
Ben Claytonabb57852019-03-01 14:33:35 +0000267
268 VkBuffer bufferOut;
Ben Clayton40f3d982019-03-21 18:26:46 +0000269 VK_ASSERT(device->CreateStorageBuffer(memory,
Ben Claytone37ce612019-03-13 19:57:42 +0000270 sizeof(uint32_t) * numElements,
271 sizeof(uint32_t) * outOffset,
272 &bufferOut));
Ben Claytonabb57852019-03-01 14:33:35 +0000273
274 VkShaderModule shaderModule;
Ben Clayton40f3d982019-03-21 18:26:46 +0000275 VK_ASSERT(device->CreateShaderModule(code, &shaderModule));
Ben Claytonabb57852019-03-01 14:33:35 +0000276
277 std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings =
278 {
279 {
280 0, // binding
281 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
282 1, // descriptorCount
283 VK_SHADER_STAGE_COMPUTE_BIT, // stageFlags
284 0, // pImmutableSamplers
285 },
286 {
287 1, // binding
288 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
289 1, // descriptorCount
290 VK_SHADER_STAGE_COMPUTE_BIT, // stageFlags
291 0, // pImmutableSamplers
292 }
293 };
294
295 VkDescriptorSetLayout descriptorSetLayout;
Ben Clayton40f3d982019-03-21 18:26:46 +0000296 VK_ASSERT(device->CreateDescriptorSetLayout(descriptorSetLayoutBindings, &descriptorSetLayout));
Ben Claytonabb57852019-03-01 14:33:35 +0000297
298 VkPipelineLayout pipelineLayout;
Ben Clayton40f3d982019-03-21 18:26:46 +0000299 VK_ASSERT(device->CreatePipelineLayout(descriptorSetLayout, &pipelineLayout));
Ben Claytonabb57852019-03-01 14:33:35 +0000300
301 VkPipeline pipeline;
Ben Clayton40f3d982019-03-21 18:26:46 +0000302 VK_ASSERT(device->CreateComputePipeline(shaderModule, pipelineLayout, &pipeline));
Ben Claytonabb57852019-03-01 14:33:35 +0000303
304 VkDescriptorPool descriptorPool;
Ben Clayton40f3d982019-03-21 18:26:46 +0000305 VK_ASSERT(device->CreateStorageBufferDescriptorPool(2, &descriptorPool));
Ben Claytonabb57852019-03-01 14:33:35 +0000306
307 VkDescriptorSet descriptorSet;
Ben Clayton40f3d982019-03-21 18:26:46 +0000308 VK_ASSERT(device->AllocateDescriptorSet(descriptorPool, descriptorSetLayout, &descriptorSet));
Ben Claytonabb57852019-03-01 14:33:35 +0000309
310 std::vector<VkDescriptorBufferInfo> descriptorBufferInfos =
311 {
312 {
313 bufferIn, // buffer
314 0, // offset
315 VK_WHOLE_SIZE, // range
316 },
317 {
318 bufferOut, // buffer
319 0, // offset
320 VK_WHOLE_SIZE, // range
321 }
322 };
Ben Clayton40f3d982019-03-21 18:26:46 +0000323 device->UpdateStorageBufferDescriptorSets(descriptorSet, descriptorBufferInfos);
Ben Claytonabb57852019-03-01 14:33:35 +0000324
325 VkCommandPool commandPool;
Ben Clayton40f3d982019-03-21 18:26:46 +0000326 VK_ASSERT(device->CreateCommandPool(&commandPool));
Ben Claytonabb57852019-03-01 14:33:35 +0000327
328 VkCommandBuffer commandBuffer;
Ben Clayton40f3d982019-03-21 18:26:46 +0000329 VK_ASSERT(device->AllocateCommandBuffer(commandPool, &commandBuffer));
Ben Claytonabb57852019-03-01 14:33:35 +0000330
Ben Clayton40f3d982019-03-21 18:26:46 +0000331 VK_ASSERT(device->BeginCommandBuffer(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, commandBuffer));
Ben Claytonabb57852019-03-01 14:33:35 +0000332
333 driver.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
334
335 driver.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descriptorSet,
336 0, nullptr);
337
Ben Claytone37ce612019-03-13 19:57:42 +0000338 driver.vkCmdDispatch(commandBuffer, numElements / GetParam().localSizeX, 1, 1);
Ben Claytonabb57852019-03-01 14:33:35 +0000339
340 VK_ASSERT(driver.vkEndCommandBuffer(commandBuffer));
341
Ben Clayton40f3d982019-03-21 18:26:46 +0000342 VK_ASSERT(device->QueueSubmitAndWait(commandBuffer));
Ben Claytonabb57852019-03-01 14:33:35 +0000343
Ben Clayton40f3d982019-03-21 18:26:46 +0000344 VK_ASSERT(device->MapMemory(memory, 0, buffersSize, 0, (void**)&buffers));
Ben Claytonabb57852019-03-01 14:33:35 +0000345
Ben Claytone37ce612019-03-13 19:57:42 +0000346 for (size_t i = 0; i < numElements; ++i)
Ben Claytonabb57852019-03-01 14:33:35 +0000347 {
Ben Claytone37ce612019-03-13 19:57:42 +0000348 auto got = buffers[i + outOffset];
349 EXPECT_EQ(expected(i), got) << "Unexpected output at " << i;
Ben Claytonabb57852019-03-01 14:33:35 +0000350 }
351
352 // Check for writes outside of bounds.
Ben Claytone37ce612019-03-13 19:57:42 +0000353 EXPECT_EQ(buffers[magic0Offset], magic0);
354 EXPECT_EQ(buffers[magic1Offset], magic1);
355 EXPECT_EQ(buffers[magic2Offset], magic2);
Ben Clayton756b54d2019-03-21 18:31:29 +0000356 EXPECT_EQ(buffers[magic3Offset], magic3);
Ben Claytonabb57852019-03-01 14:33:35 +0000357
Ben Clayton40f3d982019-03-21 18:26:46 +0000358 device->UnmapMemory(memory);
Ben Claytonabb57852019-03-01 14:33:35 +0000359 buffers = nullptr;
360}
Ben Claytone37ce612019-03-13 19:57:42 +0000361
362INSTANTIATE_TEST_CASE_P(ComputeParams, SwiftShaderVulkanBufferToBufferComputeTest, testing::Values(
363 ComputeParams{512, 1, 1, 1},
364 ComputeParams{512, 2, 1, 1},
365 ComputeParams{512, 4, 1, 1},
366 ComputeParams{512, 8, 1, 1},
367 ComputeParams{512, 16, 1, 1},
368 ComputeParams{512, 32, 1, 1},
369
370 // Non-multiple of SIMD-lane.
371 ComputeParams{3, 1, 1, 1},
372 ComputeParams{2, 1, 1, 1}
373));
374
375TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, Memcpy)
376{
377 std::stringstream src;
378 src <<
379 "OpCapability Shader\n"
380 "OpMemoryModel Logical GLSL450\n"
381 "OpEntryPoint GLCompute %1 \"main\" %2\n"
382 "OpExecutionMode %1 LocalSize " <<
383 GetParam().localSizeX << " " <<
384 GetParam().localSizeY << " " <<
385 GetParam().localSizeZ << "\n" <<
386 "OpDecorate %3 ArrayStride 4\n"
387 "OpMemberDecorate %4 0 Offset 0\n"
388 "OpDecorate %4 BufferBlock\n"
389 "OpDecorate %5 DescriptorSet 0\n"
390 "OpDecorate %5 Binding 1\n"
391 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
392 "OpDecorate %6 DescriptorSet 0\n"
393 "OpDecorate %6 Binding 0\n"
394 "%7 = OpTypeVoid\n"
395 "%8 = OpTypeFunction %7\n" // void()
396 "%9 = OpTypeInt 32 1\n" // int32
397 "%10 = OpTypeInt 32 0\n" // uint32
398 "%3 = OpTypeRuntimeArray %9\n" // int32[]
399 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
400 "%11 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
401 "%5 = OpVariable %11 Uniform\n" // struct{ int32[] }* in
402 "%12 = OpConstant %9 0\n" // int32(0)
403 "%13 = OpConstant %10 0\n" // uint32(0)
Nicolas Capens2dc03032019-03-19 13:55:25 -0400404 "%14 = OpTypeVector %10 3\n" // vec3<int32>
405 "%15 = OpTypePointer Input %14\n" // vec3<int32>*
Ben Claytone37ce612019-03-13 19:57:42 +0000406 "%2 = OpVariable %15 Input\n" // gl_GlobalInvocationId
407 "%16 = OpTypePointer Input %10\n" // uint32*
408 "%6 = OpVariable %11 Uniform\n" // struct{ int32[] }* out
409 "%17 = OpTypePointer Uniform %9\n" // int32*
410 "%1 = OpFunction %7 None %8\n" // -- Function begin --
411 "%18 = OpLabel\n"
412 "%19 = OpAccessChain %16 %2 %13\n" // &gl_GlobalInvocationId.x
413 "%20 = OpLoad %10 %19\n" // gl_GlobalInvocationId.x
414 "%21 = OpAccessChain %17 %6 %12 %20\n" // &in.arr[gl_GlobalInvocationId.x]
415 "%22 = OpLoad %9 %21\n" // out.arr[gl_GlobalInvocationId.x]
416 "%23 = OpAccessChain %17 %5 %12 %20\n" // &out.arr[gl_GlobalInvocationId.x]
417 "OpStore %23 %22\n" // out.arr[gl_GlobalInvocationId.x] = in[gl_GlobalInvocationId.x]
418 "OpReturn\n"
419 "OpFunctionEnd\n";
420
421 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i; });
422}
423
Ben Clayton49d81582019-03-12 20:05:04 +0000424TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, GlobalInvocationId)
425{
426 std::stringstream src;
427 src <<
428 "OpCapability Shader\n"
429 "OpMemoryModel Logical GLSL450\n"
430 "OpEntryPoint GLCompute %1 \"main\" %2\n"
431 "OpExecutionMode %1 LocalSize " <<
432 GetParam().localSizeX << " " <<
433 GetParam().localSizeY << " " <<
434 GetParam().localSizeZ << "\n" <<
435 "OpDecorate %3 ArrayStride 4\n"
436 "OpMemberDecorate %4 0 Offset 0\n"
437 "OpDecorate %4 BufferBlock\n"
438 "OpDecorate %5 DescriptorSet 0\n"
439 "OpDecorate %5 Binding 1\n"
440 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
441 "OpDecorate %6 DescriptorSet 0\n"
442 "OpDecorate %6 Binding 0\n"
443 "%7 = OpTypeVoid\n"
444 "%8 = OpTypeFunction %7\n" // void()
445 "%9 = OpTypeInt 32 1\n" // int32
446 "%10 = OpTypeInt 32 0\n" // uint32
447 "%3 = OpTypeRuntimeArray %9\n" // int32[]
448 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
449 "%11 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
450 "%5 = OpVariable %11 Uniform\n" // struct{ int32[] }* in
451 "%12 = OpConstant %9 0\n" // int32(0)
452 "%13 = OpConstant %9 1\n" // int32(1)
453 "%14 = OpConstant %10 0\n" // uint32(0)
454 "%15 = OpConstant %10 1\n" // uint32(1)
455 "%16 = OpConstant %10 2\n" // uint32(2)
Nicolas Capens2dc03032019-03-19 13:55:25 -0400456 "%17 = OpTypeVector %10 3\n" // vec3<int32>
457 "%18 = OpTypePointer Input %17\n" // vec3<int32>*
Ben Clayton49d81582019-03-12 20:05:04 +0000458 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
459 "%19 = OpTypePointer Input %10\n" // uint32*
460 "%6 = OpVariable %11 Uniform\n" // struct{ int32[] }* out
461 "%20 = OpTypePointer Uniform %9\n" // int32*
462 "%1 = OpFunction %7 None %8\n" // -- Function begin --
463 "%21 = OpLabel\n"
464 "%22 = OpAccessChain %19 %2 %14\n" // &gl_GlobalInvocationId.x
465 "%23 = OpAccessChain %19 %2 %15\n" // &gl_GlobalInvocationId.y
466 "%24 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.z
467 "%25 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
468 "%26 = OpLoad %10 %23\n" // gl_GlobalInvocationId.y
469 "%27 = OpLoad %10 %24\n" // gl_GlobalInvocationId.z
470 "%28 = OpAccessChain %20 %6 %12 %25\n" // &in.arr[gl_GlobalInvocationId.x]
471 "%29 = OpLoad %9 %28\n" // out.arr[gl_GlobalInvocationId.x]
472 "%30 = OpIAdd %9 %29 %26\n" // in[gl_GlobalInvocationId.x] + gl_GlobalInvocationId.y
473 "%31 = OpIAdd %9 %30 %27\n" // in[gl_GlobalInvocationId.x] + gl_GlobalInvocationId.y + gl_GlobalInvocationId.z
474 "%32 = OpAccessChain %20 %5 %12 %25\n" // &out.arr[gl_GlobalInvocationId.x]
475 "OpStore %32 %31\n" // out.arr[gl_GlobalInvocationId.x] = in[gl_GlobalInvocationId.x] + gl_GlobalInvocationId.y + gl_GlobalInvocationId.z
476 "OpReturn\n"
477 "OpFunctionEnd\n";
478
479 // gl_GlobalInvocationId.y and gl_GlobalInvocationId.z should both be zero.
480 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i; });
481}
482
Ben Claytone37ce612019-03-13 19:57:42 +0000483TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchSimple)
484{
485 std::stringstream src;
486 src <<
487 "OpCapability Shader\n"
488 "OpMemoryModel Logical GLSL450\n"
489 "OpEntryPoint GLCompute %1 \"main\" %2\n"
490 "OpExecutionMode %1 LocalSize " <<
491 GetParam().localSizeX << " " <<
492 GetParam().localSizeY << " " <<
493 GetParam().localSizeZ << "\n" <<
494 "OpDecorate %3 ArrayStride 4\n"
495 "OpMemberDecorate %4 0 Offset 0\n"
496 "OpDecorate %4 BufferBlock\n"
497 "OpDecorate %5 DescriptorSet 0\n"
498 "OpDecorate %5 Binding 1\n"
499 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
500 "OpDecorate %6 DescriptorSet 0\n"
501 "OpDecorate %6 Binding 0\n"
502 "%7 = OpTypeVoid\n"
503 "%8 = OpTypeFunction %7\n" // void()
504 "%9 = OpTypeInt 32 1\n" // int32
505 "%10 = OpTypeInt 32 0\n" // uint32
506 "%3 = OpTypeRuntimeArray %9\n" // int32[]
507 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
508 "%11 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
509 "%5 = OpVariable %11 Uniform\n" // struct{ int32[] }* in
510 "%12 = OpConstant %9 0\n" // int32(0)
511 "%13 = OpConstant %10 0\n" // uint32(0)
Nicolas Capens2dc03032019-03-19 13:55:25 -0400512 "%14 = OpTypeVector %10 3\n" // vec3<int32>
513 "%15 = OpTypePointer Input %14\n" // vec3<int32>*
Ben Claytone37ce612019-03-13 19:57:42 +0000514 "%2 = OpVariable %15 Input\n" // gl_GlobalInvocationId
515 "%16 = OpTypePointer Input %10\n" // uint32*
516 "%6 = OpVariable %11 Uniform\n" // struct{ int32[] }* out
517 "%17 = OpTypePointer Uniform %9\n" // int32*
518 "%1 = OpFunction %7 None %8\n" // -- Function begin --
519 "%18 = OpLabel\n"
520 "%19 = OpAccessChain %16 %2 %13\n" // &gl_GlobalInvocationId.x
521 "%20 = OpLoad %10 %19\n" // gl_GlobalInvocationId.x
522 "%21 = OpAccessChain %17 %6 %12 %20\n" // &in.arr[gl_GlobalInvocationId.x]
523 "%22 = OpLoad %9 %21\n" // in.arr[gl_GlobalInvocationId.x]
524 "%23 = OpAccessChain %17 %5 %12 %20\n" // &out.arr[gl_GlobalInvocationId.x]
525 // Start of branch logic
526 // %22 = in value
527 "OpBranch %24\n"
528 "%24 = OpLabel\n"
529 "OpBranch %25\n"
530 "%25 = OpLabel\n"
531 "OpBranch %26\n"
532 "%26 = OpLabel\n"
533 // %22 = out value
534 // End of branch logic
535 "OpStore %23 %22\n"
536 "OpReturn\n"
537 "OpFunctionEnd\n";
538
539 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i; });
540}
541
542TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchDeclareSSA)
543{
544 std::stringstream src;
545 src <<
546 "OpCapability Shader\n"
547 "OpMemoryModel Logical GLSL450\n"
548 "OpEntryPoint GLCompute %1 \"main\" %2\n"
549 "OpExecutionMode %1 LocalSize " <<
550 GetParam().localSizeX << " " <<
551 GetParam().localSizeY << " " <<
552 GetParam().localSizeZ << "\n" <<
553 "OpDecorate %3 ArrayStride 4\n"
554 "OpMemberDecorate %4 0 Offset 0\n"
555 "OpDecorate %4 BufferBlock\n"
556 "OpDecorate %5 DescriptorSet 0\n"
557 "OpDecorate %5 Binding 1\n"
558 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
559 "OpDecorate %6 DescriptorSet 0\n"
560 "OpDecorate %6 Binding 0\n"
561 "%7 = OpTypeVoid\n"
562 "%8 = OpTypeFunction %7\n" // void()
563 "%9 = OpTypeInt 32 1\n" // int32
564 "%10 = OpTypeInt 32 0\n" // uint32
565 "%3 = OpTypeRuntimeArray %9\n" // int32[]
566 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
567 "%11 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
568 "%5 = OpVariable %11 Uniform\n" // struct{ int32[] }* in
569 "%12 = OpConstant %9 0\n" // int32(0)
570 "%13 = OpConstant %10 0\n" // uint32(0)
Nicolas Capens2dc03032019-03-19 13:55:25 -0400571 "%14 = OpTypeVector %10 3\n" // vec3<int32>
572 "%15 = OpTypePointer Input %14\n" // vec3<int32>*
Ben Claytone37ce612019-03-13 19:57:42 +0000573 "%2 = OpVariable %15 Input\n" // gl_GlobalInvocationId
574 "%16 = OpTypePointer Input %10\n" // uint32*
575 "%6 = OpVariable %11 Uniform\n" // struct{ int32[] }* out
576 "%17 = OpTypePointer Uniform %9\n" // int32*
577 "%1 = OpFunction %7 None %8\n" // -- Function begin --
578 "%18 = OpLabel\n"
579 "%19 = OpAccessChain %16 %2 %13\n" // &gl_GlobalInvocationId.x
580 "%20 = OpLoad %10 %19\n" // gl_GlobalInvocationId.x
581 "%21 = OpAccessChain %17 %6 %12 %20\n" // &in.arr[gl_GlobalInvocationId.x]
582 "%22 = OpLoad %9 %21\n" // in.arr[gl_GlobalInvocationId.x]
583 "%23 = OpAccessChain %17 %5 %12 %20\n" // &out.arr[gl_GlobalInvocationId.x]
584 // Start of branch logic
585 // %22 = in value
586 "OpBranch %24\n"
587 "%24 = OpLabel\n"
588 "%25 = OpIAdd %9 %22 %22\n" // %25 = in*2
589 "OpBranch %26\n"
590 "%26 = OpLabel\n"
591 "OpBranch %27\n"
592 "%27 = OpLabel\n"
593 // %25 = out value
594 // End of branch logic
595 "OpStore %23 %25\n" // use SSA value from previous block
596 "OpReturn\n"
597 "OpFunctionEnd\n";
598
599 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i * 2; });
Ben Clayton9fd02e02019-03-21 18:47:15 +0000600}
601
602TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchConditionalSimple)
603{
604 std::stringstream src;
605 src <<
606 "OpCapability Shader\n"
607 "OpMemoryModel Logical GLSL450\n"
608 "OpEntryPoint GLCompute %1 \"main\" %2\n"
609 "OpExecutionMode %1 LocalSize " <<
610 GetParam().localSizeX << " " <<
611 GetParam().localSizeY << " " <<
612 GetParam().localSizeZ << "\n" <<
613 "OpDecorate %3 ArrayStride 4\n"
614 "OpMemberDecorate %4 0 Offset 0\n"
615 "OpDecorate %4 BufferBlock\n"
616 "OpDecorate %5 DescriptorSet 0\n"
617 "OpDecorate %5 Binding 1\n"
618 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
619 "OpDecorate %6 DescriptorSet 0\n"
620 "OpDecorate %6 Binding 0\n"
621 "%7 = OpTypeVoid\n"
622 "%8 = OpTypeFunction %7\n" // void()
623 "%9 = OpTypeInt 32 1\n" // int32
624 "%10 = OpTypeInt 32 0\n" // uint32
625 "%11 = OpTypeBool\n"
626 "%3 = OpTypeRuntimeArray %9\n" // int32[]
627 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
628 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
629 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
630 "%13 = OpConstant %9 0\n" // int32(0)
631 "%14 = OpConstant %9 2\n" // int32(2)
632 "%15 = OpConstant %10 0\n" // uint32(0)
633 "%16 = OpTypeVector %10 3\n" // vec4<int32>
634 "%17 = OpTypePointer Input %16\n" // vec4<int32>*
635 "%2 = OpVariable %17 Input\n" // gl_GlobalInvocationId
636 "%18 = OpTypePointer Input %10\n" // uint32*
637 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
638 "%19 = OpTypePointer Uniform %9\n" // int32*
639 "%1 = OpFunction %7 None %8\n" // -- Function begin --
640 "%20 = OpLabel\n"
641 "%21 = OpAccessChain %18 %2 %15\n" // &gl_GlobalInvocationId.x
642 "%22 = OpLoad %10 %21\n" // gl_GlobalInvocationId.x
643 "%23 = OpAccessChain %19 %6 %13 %22\n" // &in.arr[gl_GlobalInvocationId.x]
644 "%24 = OpLoad %9 %23\n" // in.arr[gl_GlobalInvocationId.x]
645 "%25 = OpAccessChain %19 %5 %13 %22\n" // &out.arr[gl_GlobalInvocationId.x]
646 // Start of branch logic
647 // %24 = in value
648 "%26 = OpSMod %9 %24 %14\n" // in % 2
649 "%27 = OpIEqual %11 %26 %13\n" // (in % 2) == 0
650 "OpSelectionMerge %28 None\n"
651 "OpBranchConditional %27 %28 %28\n" // Both go to %28
652 "%28 = OpLabel\n"
653 // %26 = out value
654 // End of branch logic
655 "OpStore %25 %26\n" // use SSA value from previous block
656 "OpReturn\n"
657 "OpFunctionEnd\n";
658
659 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i%2; });
660}
661
662TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchConditionalTwoEmptyBlocks)
663{
664 std::stringstream src;
665 src <<
666 "OpCapability Shader\n"
667 "OpMemoryModel Logical GLSL450\n"
668 "OpEntryPoint GLCompute %1 \"main\" %2\n"
669 "OpExecutionMode %1 LocalSize " <<
670 GetParam().localSizeX << " " <<
671 GetParam().localSizeY << " " <<
672 GetParam().localSizeZ << "\n" <<
673 "OpDecorate %3 ArrayStride 4\n"
674 "OpMemberDecorate %4 0 Offset 0\n"
675 "OpDecorate %4 BufferBlock\n"
676 "OpDecorate %5 DescriptorSet 0\n"
677 "OpDecorate %5 Binding 1\n"
678 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
679 "OpDecorate %6 DescriptorSet 0\n"
680 "OpDecorate %6 Binding 0\n"
681 "%7 = OpTypeVoid\n"
682 "%8 = OpTypeFunction %7\n" // void()
683 "%9 = OpTypeInt 32 1\n" // int32
684 "%10 = OpTypeInt 32 0\n" // uint32
685 "%11 = OpTypeBool\n"
686 "%3 = OpTypeRuntimeArray %9\n" // int32[]
687 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
688 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
689 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
690 "%13 = OpConstant %9 0\n" // int32(0)
691 "%14 = OpConstant %9 2\n" // int32(2)
692 "%15 = OpConstant %10 0\n" // uint32(0)
693 "%16 = OpTypeVector %10 3\n" // vec4<int32>
694 "%17 = OpTypePointer Input %16\n" // vec4<int32>*
695 "%2 = OpVariable %17 Input\n" // gl_GlobalInvocationId
696 "%18 = OpTypePointer Input %10\n" // uint32*
697 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
698 "%19 = OpTypePointer Uniform %9\n" // int32*
699 "%1 = OpFunction %7 None %8\n" // -- Function begin --
700 "%20 = OpLabel\n"
701 "%21 = OpAccessChain %18 %2 %15\n" // &gl_GlobalInvocationId.x
702 "%22 = OpLoad %10 %21\n" // gl_GlobalInvocationId.x
703 "%23 = OpAccessChain %19 %6 %13 %22\n" // &in.arr[gl_GlobalInvocationId.x]
704 "%24 = OpLoad %9 %23\n" // in.arr[gl_GlobalInvocationId.x]
705 "%25 = OpAccessChain %19 %5 %13 %22\n" // &out.arr[gl_GlobalInvocationId.x]
706 // Start of branch logic
707 // %24 = in value
708 "%26 = OpSMod %9 %24 %14\n" // in % 2
709 "%27 = OpIEqual %11 %26 %13\n" // (in % 2) == 0
710 "OpSelectionMerge %28 None\n"
711 "OpBranchConditional %27 %29 %30\n"
712 "%29 = OpLabel\n" // (in % 2) == 0
713 "OpBranch %28\n"
714 "%30 = OpLabel\n" // (in % 2) != 0
715 "OpBranch %28\n"
716 "%28 = OpLabel\n"
717 // %26 = out value
718 // End of branch logic
719 "OpStore %25 %26\n" // use SSA value from previous block
720 "OpReturn\n"
721 "OpFunctionEnd\n";
722
723 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i%2; });
724}
725
726// TODO: Test for parallel assignment
727TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchConditionalStore)
728{
729 std::stringstream src;
730 src <<
731 "OpCapability Shader\n"
732 "OpMemoryModel Logical GLSL450\n"
733 "OpEntryPoint GLCompute %1 \"main\" %2\n"
734 "OpExecutionMode %1 LocalSize " <<
735 GetParam().localSizeX << " " <<
736 GetParam().localSizeY << " " <<
737 GetParam().localSizeZ << "\n" <<
738 "OpDecorate %3 ArrayStride 4\n"
739 "OpMemberDecorate %4 0 Offset 0\n"
740 "OpDecorate %4 BufferBlock\n"
741 "OpDecorate %5 DescriptorSet 0\n"
742 "OpDecorate %5 Binding 1\n"
743 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
744 "OpDecorate %6 DescriptorSet 0\n"
745 "OpDecorate %6 Binding 0\n"
746 "%7 = OpTypeVoid\n"
747 "%8 = OpTypeFunction %7\n" // void()
748 "%9 = OpTypeInt 32 1\n" // int32
749 "%10 = OpTypeInt 32 0\n" // uint32
750 "%11 = OpTypeBool\n"
751 "%3 = OpTypeRuntimeArray %9\n" // int32[]
752 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
753 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
754 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
755 "%13 = OpConstant %9 0\n" // int32(0)
756 "%14 = OpConstant %9 1\n" // int32(1)
757 "%15 = OpConstant %9 2\n" // int32(2)
758 "%16 = OpConstant %10 0\n" // uint32(0)
759 "%17 = OpTypeVector %10 3\n" // vec4<int32>
760 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
761 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
762 "%19 = OpTypePointer Input %10\n" // uint32*
763 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
764 "%20 = OpTypePointer Uniform %9\n" // int32*
765 "%1 = OpFunction %7 None %8\n" // -- Function begin --
766 "%21 = OpLabel\n"
767 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
768 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
769 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
770 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
771 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
772 // Start of branch logic
773 // %25 = in value
774 "%27 = OpSMod %9 %25 %15\n" // in % 2
775 "%28 = OpIEqual %11 %27 %13\n" // (in % 2) == 0
776 "OpSelectionMerge %29 None\n"
777 "OpBranchConditional %28 %30 %31\n"
778 "%30 = OpLabel\n" // (in % 2) == 0
779 "OpStore %26 %14\n" // write 1
780 "OpBranch %29\n"
781 "%31 = OpLabel\n" // (in % 2) != 0
782 "OpStore %26 %15\n" // write 2
783 "OpBranch %29\n"
784 "%29 = OpLabel\n"
785 // End of branch logic
786 "OpReturn\n"
787 "OpFunctionEnd\n";
788
789 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 0 ? 1 : 2; });
790}
791
792TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchConditionalReturnTrue)
793{
794 std::stringstream src;
795 src <<
796 "OpCapability Shader\n"
797 "OpMemoryModel Logical GLSL450\n"
798 "OpEntryPoint GLCompute %1 \"main\" %2\n"
799 "OpExecutionMode %1 LocalSize " <<
800 GetParam().localSizeX << " " <<
801 GetParam().localSizeY << " " <<
802 GetParam().localSizeZ << "\n" <<
803 "OpDecorate %3 ArrayStride 4\n"
804 "OpMemberDecorate %4 0 Offset 0\n"
805 "OpDecorate %4 BufferBlock\n"
806 "OpDecorate %5 DescriptorSet 0\n"
807 "OpDecorate %5 Binding 1\n"
808 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
809 "OpDecorate %6 DescriptorSet 0\n"
810 "OpDecorate %6 Binding 0\n"
811 "%7 = OpTypeVoid\n"
812 "%8 = OpTypeFunction %7\n" // void()
813 "%9 = OpTypeInt 32 1\n" // int32
814 "%10 = OpTypeInt 32 0\n" // uint32
815 "%11 = OpTypeBool\n"
816 "%3 = OpTypeRuntimeArray %9\n" // int32[]
817 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
818 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
819 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
820 "%13 = OpConstant %9 0\n" // int32(0)
821 "%14 = OpConstant %9 1\n" // int32(1)
822 "%15 = OpConstant %9 2\n" // int32(2)
823 "%16 = OpConstant %10 0\n" // uint32(0)
824 "%17 = OpTypeVector %10 3\n" // vec4<int32>
825 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
826 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
827 "%19 = OpTypePointer Input %10\n" // uint32*
828 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
829 "%20 = OpTypePointer Uniform %9\n" // int32*
830 "%1 = OpFunction %7 None %8\n" // -- Function begin --
831 "%21 = OpLabel\n"
832 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
833 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
834 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
835 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
836 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
837 // Start of branch logic
838 // %25 = in value
839 "%27 = OpSMod %9 %25 %15\n" // in % 2
840 "%28 = OpIEqual %11 %27 %13\n" // (in % 2) == 0
841 "OpSelectionMerge %29 None\n"
842 "OpBranchConditional %28 %30 %29\n"
843 "%30 = OpLabel\n" // (in % 2) == 0
844 "OpReturn\n"
845 "%29 = OpLabel\n" // merge
846 "OpStore %26 %15\n" // write 2
847 // End of branch logic
848 "OpReturn\n"
849 "OpFunctionEnd\n";
850
851 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 0 ? 0 : 2; });
852}
853
854// TODO: Test for parallel assignment
855TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, BranchConditionalPhi)
856{
857 std::stringstream src;
858 src <<
859 "OpCapability Shader\n"
860 "OpMemoryModel Logical GLSL450\n"
861 "OpEntryPoint GLCompute %1 \"main\" %2\n"
862 "OpExecutionMode %1 LocalSize " <<
863 GetParam().localSizeX << " " <<
864 GetParam().localSizeY << " " <<
865 GetParam().localSizeZ << "\n" <<
866 "OpDecorate %3 ArrayStride 4\n"
867 "OpMemberDecorate %4 0 Offset 0\n"
868 "OpDecorate %4 BufferBlock\n"
869 "OpDecorate %5 DescriptorSet 0\n"
870 "OpDecorate %5 Binding 1\n"
871 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
872 "OpDecorate %6 DescriptorSet 0\n"
873 "OpDecorate %6 Binding 0\n"
874 "%7 = OpTypeVoid\n"
875 "%8 = OpTypeFunction %7\n" // void()
876 "%9 = OpTypeInt 32 1\n" // int32
877 "%10 = OpTypeInt 32 0\n" // uint32
878 "%11 = OpTypeBool\n"
879 "%3 = OpTypeRuntimeArray %9\n" // int32[]
880 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
881 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
882 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
883 "%13 = OpConstant %9 0\n" // int32(0)
884 "%14 = OpConstant %9 1\n" // int32(1)
885 "%15 = OpConstant %9 2\n" // int32(2)
886 "%16 = OpConstant %10 0\n" // uint32(0)
887 "%17 = OpTypeVector %10 3\n" // vec4<int32>
888 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
889 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
890 "%19 = OpTypePointer Input %10\n" // uint32*
891 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
892 "%20 = OpTypePointer Uniform %9\n" // int32*
893 "%1 = OpFunction %7 None %8\n" // -- Function begin --
894 "%21 = OpLabel\n"
895 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
896 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
897 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
898 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
899 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
900 // Start of branch logic
901 // %25 = in value
902 "%27 = OpSMod %9 %25 %15\n" // in % 2
903 "%28 = OpIEqual %11 %27 %13\n" // (in % 2) == 0
904 "OpSelectionMerge %29 None\n"
905 "OpBranchConditional %28 %30 %31\n"
906 "%30 = OpLabel\n" // (in % 2) == 0
907 "OpBranch %29\n"
908 "%31 = OpLabel\n" // (in % 2) != 0
909 "OpBranch %29\n"
910 "%29 = OpLabel\n"
911 "%32 = OpPhi %9 %14 %30 %15 %31\n" // (in % 2) == 0 ? 1 : 2
912 // End of branch logic
913 "OpStore %26 %32\n"
914 "OpReturn\n"
915 "OpFunctionEnd\n";
916
917 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 0 ? 1 : 2; });
918}
919
Ben Clayton213a8ce2019-03-21 18:57:23 +0000920TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchEmptyCases)
921{
922 std::stringstream src;
923 src <<
924 "OpCapability Shader\n"
925 "OpMemoryModel Logical GLSL450\n"
926 "OpEntryPoint GLCompute %1 \"main\" %2\n"
927 "OpExecutionMode %1 LocalSize " <<
928 GetParam().localSizeX << " " <<
929 GetParam().localSizeY << " " <<
930 GetParam().localSizeZ << "\n" <<
931 "OpDecorate %3 ArrayStride 4\n"
932 "OpMemberDecorate %4 0 Offset 0\n"
933 "OpDecorate %4 BufferBlock\n"
934 "OpDecorate %5 DescriptorSet 0\n"
935 "OpDecorate %5 Binding 1\n"
936 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
937 "OpDecorate %6 DescriptorSet 0\n"
938 "OpDecorate %6 Binding 0\n"
939 "%7 = OpTypeVoid\n"
940 "%8 = OpTypeFunction %7\n" // void()
941 "%9 = OpTypeInt 32 1\n" // int32
942 "%10 = OpTypeInt 32 0\n" // uint32
943 "%11 = OpTypeBool\n"
944 "%3 = OpTypeRuntimeArray %9\n" // int32[]
945 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
946 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
947 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
948 "%13 = OpConstant %9 0\n" // int32(0)
949 "%14 = OpConstant %9 2\n" // int32(2)
950 "%15 = OpConstant %10 0\n" // uint32(0)
951 "%16 = OpTypeVector %10 3\n" // vec4<int32>
952 "%17 = OpTypePointer Input %16\n" // vec4<int32>*
953 "%2 = OpVariable %17 Input\n" // gl_GlobalInvocationId
954 "%18 = OpTypePointer Input %10\n" // uint32*
955 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
956 "%19 = OpTypePointer Uniform %9\n" // int32*
957 "%1 = OpFunction %7 None %8\n" // -- Function begin --
958 "%20 = OpLabel\n"
959 "%21 = OpAccessChain %18 %2 %15\n" // &gl_GlobalInvocationId.x
960 "%22 = OpLoad %10 %21\n" // gl_GlobalInvocationId.x
961 "%23 = OpAccessChain %19 %6 %13 %22\n" // &in.arr[gl_GlobalInvocationId.x]
962 "%24 = OpLoad %9 %23\n" // in.arr[gl_GlobalInvocationId.x]
963 "%25 = OpAccessChain %19 %5 %13 %22\n" // &out.arr[gl_GlobalInvocationId.x]
964 // Start of branch logic
965 // %24 = in value
966 "%26 = OpSMod %9 %24 %14\n" // in % 2
967 "OpSelectionMerge %27 None\n"
968 "OpSwitch %26 %27 0 %28 1 %29\n"
969 "%28 = OpLabel\n" // (in % 2) == 0
970 "OpBranch %27\n"
971 "%29 = OpLabel\n" // (in % 2) == 1
972 "OpBranch %27\n"
973 "%27 = OpLabel\n"
974 // %26 = out value
975 // End of branch logic
976 "OpStore %25 %26\n" // use SSA value from previous block
977 "OpReturn\n"
978 "OpFunctionEnd\n";
979
980 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return i%2; });
981}
982
983TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchStore)
984{
985 std::stringstream src;
986 src <<
987 "OpCapability Shader\n"
988 "OpMemoryModel Logical GLSL450\n"
989 "OpEntryPoint GLCompute %1 \"main\" %2\n"
990 "OpExecutionMode %1 LocalSize " <<
991 GetParam().localSizeX << " " <<
992 GetParam().localSizeY << " " <<
993 GetParam().localSizeZ << "\n" <<
994 "OpDecorate %3 ArrayStride 4\n"
995 "OpMemberDecorate %4 0 Offset 0\n"
996 "OpDecorate %4 BufferBlock\n"
997 "OpDecorate %5 DescriptorSet 0\n"
998 "OpDecorate %5 Binding 1\n"
999 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1000 "OpDecorate %6 DescriptorSet 0\n"
1001 "OpDecorate %6 Binding 0\n"
1002 "%7 = OpTypeVoid\n"
1003 "%8 = OpTypeFunction %7\n" // void()
1004 "%9 = OpTypeInt 32 1\n" // int32
1005 "%10 = OpTypeInt 32 0\n" // uint32
1006 "%11 = OpTypeBool\n"
1007 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1008 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1009 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1010 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1011 "%13 = OpConstant %9 0\n" // int32(0)
1012 "%14 = OpConstant %9 1\n" // int32(1)
1013 "%15 = OpConstant %9 2\n" // int32(2)
1014 "%16 = OpConstant %10 0\n" // uint32(0)
1015 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1016 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1017 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1018 "%19 = OpTypePointer Input %10\n" // uint32*
1019 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1020 "%20 = OpTypePointer Uniform %9\n" // int32*
1021 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1022 "%21 = OpLabel\n"
1023 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1024 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1025 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1026 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1027 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1028 // Start of branch logic
1029 // %25 = in value
1030 "%27 = OpSMod %9 %25 %15\n" // in % 2
1031 "OpSelectionMerge %28 None\n"
1032 "OpSwitch %27 %28 0 %29 1 %30\n"
1033 "%29 = OpLabel\n" // (in % 2) == 0
1034 "OpStore %26 %15\n" // write 2
1035 "OpBranch %28\n"
1036 "%30 = OpLabel\n" // (in % 2) == 1
1037 "OpStore %26 %14\n" // write 1
1038 "OpBranch %28\n"
1039 "%28 = OpLabel\n"
1040 // End of branch logic
1041 "OpReturn\n"
1042 "OpFunctionEnd\n";
1043
1044 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 0 ? 2 : 1; });
1045}
1046
1047TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchCaseReturn)
1048{
1049 std::stringstream src;
1050 src <<
1051 "OpCapability Shader\n"
1052 "OpMemoryModel Logical GLSL450\n"
1053 "OpEntryPoint GLCompute %1 \"main\" %2\n"
1054 "OpExecutionMode %1 LocalSize " <<
1055 GetParam().localSizeX << " " <<
1056 GetParam().localSizeY << " " <<
1057 GetParam().localSizeZ << "\n" <<
1058 "OpDecorate %3 ArrayStride 4\n"
1059 "OpMemberDecorate %4 0 Offset 0\n"
1060 "OpDecorate %4 BufferBlock\n"
1061 "OpDecorate %5 DescriptorSet 0\n"
1062 "OpDecorate %5 Binding 1\n"
1063 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1064 "OpDecorate %6 DescriptorSet 0\n"
1065 "OpDecorate %6 Binding 0\n"
1066 "%7 = OpTypeVoid\n"
1067 "%8 = OpTypeFunction %7\n" // void()
1068 "%9 = OpTypeInt 32 1\n" // int32
1069 "%10 = OpTypeInt 32 0\n" // uint32
1070 "%11 = OpTypeBool\n"
1071 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1072 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1073 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1074 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1075 "%13 = OpConstant %9 0\n" // int32(0)
1076 "%14 = OpConstant %9 1\n" // int32(1)
1077 "%15 = OpConstant %9 2\n" // int32(2)
1078 "%16 = OpConstant %10 0\n" // uint32(0)
1079 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1080 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1081 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1082 "%19 = OpTypePointer Input %10\n" // uint32*
1083 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1084 "%20 = OpTypePointer Uniform %9\n" // int32*
1085 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1086 "%21 = OpLabel\n"
1087 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1088 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1089 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1090 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1091 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1092 // Start of branch logic
1093 // %25 = in value
1094 "%27 = OpSMod %9 %25 %15\n" // in % 2
1095 "OpSelectionMerge %28 None\n"
1096 "OpSwitch %27 %28 0 %29 1 %30\n"
1097 "%29 = OpLabel\n" // (in % 2) == 0
1098 "OpBranch %28\n"
1099 "%30 = OpLabel\n" // (in % 2) == 1
1100 "OpReturn\n"
1101 "%28 = OpLabel\n"
1102 "OpStore %26 %14\n" // write 1
1103 // End of branch logic
1104 "OpReturn\n"
1105 "OpFunctionEnd\n";
1106
1107 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 1 ? 0 : 1; });
1108}
1109
1110TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchDefaultReturn)
1111{
1112 std::stringstream src;
1113 src <<
1114 "OpCapability Shader\n"
1115 "OpMemoryModel Logical GLSL450\n"
1116 "OpEntryPoint GLCompute %1 \"main\" %2\n"
1117 "OpExecutionMode %1 LocalSize " <<
1118 GetParam().localSizeX << " " <<
1119 GetParam().localSizeY << " " <<
1120 GetParam().localSizeZ << "\n" <<
1121 "OpDecorate %3 ArrayStride 4\n"
1122 "OpMemberDecorate %4 0 Offset 0\n"
1123 "OpDecorate %4 BufferBlock\n"
1124 "OpDecorate %5 DescriptorSet 0\n"
1125 "OpDecorate %5 Binding 1\n"
1126 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1127 "OpDecorate %6 DescriptorSet 0\n"
1128 "OpDecorate %6 Binding 0\n"
1129 "%7 = OpTypeVoid\n"
1130 "%8 = OpTypeFunction %7\n" // void()
1131 "%9 = OpTypeInt 32 1\n" // int32
1132 "%10 = OpTypeInt 32 0\n" // uint32
1133 "%11 = OpTypeBool\n"
1134 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1135 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1136 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1137 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1138 "%13 = OpConstant %9 0\n" // int32(0)
1139 "%14 = OpConstant %9 1\n" // int32(1)
1140 "%15 = OpConstant %9 2\n" // int32(2)
1141 "%16 = OpConstant %10 0\n" // uint32(0)
1142 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1143 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1144 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1145 "%19 = OpTypePointer Input %10\n" // uint32*
1146 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1147 "%20 = OpTypePointer Uniform %9\n" // int32*
1148 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1149 "%21 = OpLabel\n"
1150 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1151 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1152 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1153 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1154 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1155 // Start of branch logic
1156 // %25 = in value
1157 "%27 = OpSMod %9 %25 %15\n" // in % 2
1158 "OpSelectionMerge %28 None\n"
1159 "OpSwitch %27 %29 1 %30\n"
1160 "%30 = OpLabel\n" // (in % 2) == 1
1161 "OpBranch %28\n"
1162 "%29 = OpLabel\n" // (in % 2) != 1
1163 "OpReturn\n"
1164 "%28 = OpLabel\n" // merge
1165 "OpStore %26 %14\n" // write 1
1166 // End of branch logic
1167 "OpReturn\n"
1168 "OpFunctionEnd\n";
1169
1170 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 1 ? 1 : 0; });
1171}
1172
1173TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchCaseFallthrough)
1174{
1175 std::stringstream src;
1176 src <<
1177 "OpCapability Shader\n"
1178 "OpMemoryModel Logical GLSL450\n"
1179 "OpEntryPoint GLCompute %1 \"main\" %2\n"
1180 "OpExecutionMode %1 LocalSize " <<
1181 GetParam().localSizeX << " " <<
1182 GetParam().localSizeY << " " <<
1183 GetParam().localSizeZ << "\n" <<
1184 "OpDecorate %3 ArrayStride 4\n"
1185 "OpMemberDecorate %4 0 Offset 0\n"
1186 "OpDecorate %4 BufferBlock\n"
1187 "OpDecorate %5 DescriptorSet 0\n"
1188 "OpDecorate %5 Binding 1\n"
1189 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1190 "OpDecorate %6 DescriptorSet 0\n"
1191 "OpDecorate %6 Binding 0\n"
1192 "%7 = OpTypeVoid\n"
1193 "%8 = OpTypeFunction %7\n" // void()
1194 "%9 = OpTypeInt 32 1\n" // int32
1195 "%10 = OpTypeInt 32 0\n" // uint32
1196 "%11 = OpTypeBool\n"
1197 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1198 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1199 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1200 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1201 "%13 = OpConstant %9 0\n" // int32(0)
1202 "%14 = OpConstant %9 1\n" // int32(1)
1203 "%15 = OpConstant %9 2\n" // int32(2)
1204 "%16 = OpConstant %10 0\n" // uint32(0)
1205 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1206 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1207 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1208 "%19 = OpTypePointer Input %10\n" // uint32*
1209 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1210 "%20 = OpTypePointer Uniform %9\n" // int32*
1211 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1212 "%21 = OpLabel\n"
1213 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1214 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1215 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1216 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1217 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1218 // Start of branch logic
1219 // %25 = in value
1220 "%27 = OpSMod %9 %25 %15\n" // in % 2
1221 "OpSelectionMerge %28 None\n"
1222 "OpSwitch %27 %29 0 %30 1 %31\n"
1223 "%30 = OpLabel\n" // (in % 2) == 0
1224 "%32 = OpIAdd %9 %27 %14\n" // generate an intermediate
1225 "OpStore %26 %32\n" // write a value (overwritten later)
1226 "OpBranch %31\n" // fallthrough
1227 "%31 = OpLabel\n" // (in % 2) == 1
1228 "OpStore %26 %15\n" // write 2
1229 "OpBranch %28\n"
1230 "%29 = OpLabel\n" // unreachable
1231 "OpUnreachable\n"
1232 "%28 = OpLabel\n" // merge
1233 // End of branch logic
1234 "OpReturn\n"
1235 "OpFunctionEnd\n";
1236
1237 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return 2; });
1238}
1239
1240TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchDefaultFallthrough)
1241{
1242 std::stringstream src;
1243 src <<
1244 "OpCapability Shader\n"
1245 "OpMemoryModel Logical GLSL450\n"
1246 "OpEntryPoint GLCompute %1 \"main\" %2\n"
1247 "OpExecutionMode %1 LocalSize " <<
1248 GetParam().localSizeX << " " <<
1249 GetParam().localSizeY << " " <<
1250 GetParam().localSizeZ << "\n" <<
1251 "OpDecorate %3 ArrayStride 4\n"
1252 "OpMemberDecorate %4 0 Offset 0\n"
1253 "OpDecorate %4 BufferBlock\n"
1254 "OpDecorate %5 DescriptorSet 0\n"
1255 "OpDecorate %5 Binding 1\n"
1256 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1257 "OpDecorate %6 DescriptorSet 0\n"
1258 "OpDecorate %6 Binding 0\n"
1259 "%7 = OpTypeVoid\n"
1260 "%8 = OpTypeFunction %7\n" // void()
1261 "%9 = OpTypeInt 32 1\n" // int32
1262 "%10 = OpTypeInt 32 0\n" // uint32
1263 "%11 = OpTypeBool\n"
1264 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1265 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1266 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1267 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1268 "%13 = OpConstant %9 0\n" // int32(0)
1269 "%14 = OpConstant %9 1\n" // int32(1)
1270 "%15 = OpConstant %9 2\n" // int32(2)
1271 "%16 = OpConstant %10 0\n" // uint32(0)
1272 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1273 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1274 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1275 "%19 = OpTypePointer Input %10\n" // uint32*
1276 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1277 "%20 = OpTypePointer Uniform %9\n" // int32*
1278 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1279 "%21 = OpLabel\n"
1280 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1281 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1282 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1283 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1284 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1285 // Start of branch logic
1286 // %25 = in value
1287 "%27 = OpSMod %9 %25 %15\n" // in % 2
1288 "OpSelectionMerge %28 None\n"
1289 "OpSwitch %27 %29 0 %30 1 %31\n"
1290 "%30 = OpLabel\n" // (in % 2) == 0
1291 "%32 = OpIAdd %9 %27 %14\n" // generate an intermediate
1292 "OpStore %26 %32\n" // write a value (overwritten later)
1293 "OpBranch %29\n" // fallthrough
1294 "%29 = OpLabel\n" // default
1295 "%33 = OpIAdd %9 %27 %14\n" // generate an intermediate
1296 "OpStore %26 %33\n" // write a value (overwritten later)
1297 "OpBranch %31\n" // fallthrough
1298 "%31 = OpLabel\n" // (in % 2) == 1
1299 "OpStore %26 %15\n" // write 2
1300 "OpBranch %28\n"
1301 "%28 = OpLabel\n" // merge
1302 // End of branch logic
1303 "OpReturn\n"
1304 "OpFunctionEnd\n";
1305
1306 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return 2; });
1307}
1308
1309TEST_P(SwiftShaderVulkanBufferToBufferComputeTest, SwitchPhi)
1310{
1311 std::stringstream src;
1312 src <<
1313 "OpCapability Shader\n"
1314 "OpMemoryModel Logical GLSL450\n"
1315 "OpEntryPoint GLCompute %1 \"main\" %2\n"
1316 "OpExecutionMode %1 LocalSize " <<
1317 GetParam().localSizeX << " " <<
1318 GetParam().localSizeY << " " <<
1319 GetParam().localSizeZ << "\n" <<
1320 "OpDecorate %3 ArrayStride 4\n"
1321 "OpMemberDecorate %4 0 Offset 0\n"
1322 "OpDecorate %4 BufferBlock\n"
1323 "OpDecorate %5 DescriptorSet 0\n"
1324 "OpDecorate %5 Binding 1\n"
1325 "OpDecorate %2 BuiltIn GlobalInvocationId\n"
1326 "OpDecorate %6 DescriptorSet 0\n"
1327 "OpDecorate %6 Binding 0\n"
1328 "%7 = OpTypeVoid\n"
1329 "%8 = OpTypeFunction %7\n" // void()
1330 "%9 = OpTypeInt 32 1\n" // int32
1331 "%10 = OpTypeInt 32 0\n" // uint32
1332 "%11 = OpTypeBool\n"
1333 "%3 = OpTypeRuntimeArray %9\n" // int32[]
1334 "%4 = OpTypeStruct %3\n" // struct{ int32[] }
1335 "%12 = OpTypePointer Uniform %4\n" // struct{ int32[] }*
1336 "%5 = OpVariable %12 Uniform\n" // struct{ int32[] }* in
1337 "%13 = OpConstant %9 0\n" // int32(0)
1338 "%14 = OpConstant %9 1\n" // int32(1)
1339 "%15 = OpConstant %9 2\n" // int32(2)
1340 "%16 = OpConstant %10 0\n" // uint32(0)
1341 "%17 = OpTypeVector %10 3\n" // vec4<int32>
1342 "%18 = OpTypePointer Input %17\n" // vec4<int32>*
1343 "%2 = OpVariable %18 Input\n" // gl_GlobalInvocationId
1344 "%19 = OpTypePointer Input %10\n" // uint32*
1345 "%6 = OpVariable %12 Uniform\n" // struct{ int32[] }* out
1346 "%20 = OpTypePointer Uniform %9\n" // int32*
1347 "%1 = OpFunction %7 None %8\n" // -- Function begin --
1348 "%21 = OpLabel\n"
1349 "%22 = OpAccessChain %19 %2 %16\n" // &gl_GlobalInvocationId.x
1350 "%23 = OpLoad %10 %22\n" // gl_GlobalInvocationId.x
1351 "%24 = OpAccessChain %20 %6 %13 %23\n" // &in.arr[gl_GlobalInvocationId.x]
1352 "%25 = OpLoad %9 %24\n" // in.arr[gl_GlobalInvocationId.x]
1353 "%26 = OpAccessChain %20 %5 %13 %23\n" // &out.arr[gl_GlobalInvocationId.x]
1354 // Start of branch logic
1355 // %25 = in value
1356 "%27 = OpSMod %9 %25 %15\n" // in % 2
1357 "OpSelectionMerge %28 None\n"
1358 "OpSwitch %27 %29 1 %30\n"
1359 "%30 = OpLabel\n" // (in % 2) == 1
1360 "OpBranch %28\n"
1361 "%29 = OpLabel\n" // (in % 2) != 1
1362 "OpBranch %28\n"
1363 "%28 = OpLabel\n" // merge
1364 "%31 = OpPhi %9 %14 %30 %15 %29\n" // (in % 2) == 1 ? 1 : 2
1365 "OpStore %26 %31\n"
1366 // End of branch logic
1367 "OpReturn\n"
1368 "OpFunctionEnd\n";
1369
1370 test(src.str(), [](uint32_t i) { return i; }, [](uint32_t i) { return (i % 2) == 1 ? 1 : 2; });
1371}