1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief SPIR-V assembly tests for workgroup memory.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmWorkgroupMemoryTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "tcuStringTemplate.hpp"
28 #include "tcuFloat.hpp"
29
30 namespace vkt
31 {
32 namespace SpirVAssembly
33 {
34
35 using namespace vk;
36 using std::map;
37 using std::string;
38 using std::vector;
39 using tcu::IVec3;
40 using tcu::Vec4;
41 using tcu::StringTemplate;
42 using tcu::Float16;
43 using tcu::Float32;
44
45 namespace
46 {
47
48 struct DataType
49 {
50 string name;
51 string type;
52 deUint32 sizeBytes;
53 };
54
checkResultsFloat16(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocs,const vector<Resource> & expectedOutputs,tcu::TestLog & log)55 bool checkResultsFloat16 (const vector<Resource>& inputs,
56 const vector<AllocationSp>& outputAllocs,
57 const vector<Resource>& expectedOutputs,
58 tcu::TestLog& log)
59 {
60 DE_UNREF(inputs);
61 DE_UNREF(log);
62
63 std::vector<deUint8> expectedBytes;
64 expectedOutputs.front().getBuffer()->getPackedBytes(expectedBytes);
65
66 const deUint16* results = reinterpret_cast<const deUint16*>(outputAllocs.front()->getHostPtr());
67 const deUint16* expected = reinterpret_cast<const deUint16*>(&expectedBytes[0]);
68
69 for (size_t i = 0; i < expectedBytes.size() / sizeof (deUint16); i++)
70 {
71 if (results[i] == expected[i])
72 continue;
73
74 if (Float16(results[i]).isNaN() && Float16(expected[i]).isNaN())
75 continue;
76
77 return false;
78 }
79
80 return true;
81 }
82
83
checkResultsFloat32(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocs,const vector<Resource> & expectedOutputs,tcu::TestLog & log)84 bool checkResultsFloat32 (const vector<Resource>& inputs,
85 const vector<AllocationSp>& outputAllocs,
86 const vector<Resource>& expectedOutputs,
87 tcu::TestLog& log)
88 {
89 DE_UNREF(inputs);
90 DE_UNREF(log);
91
92 std::vector<deUint8> expectedBytes;
93 expectedOutputs.front().getBuffer()->getPackedBytes(expectedBytes);
94
95 const deUint32* results = reinterpret_cast<const deUint32*>(outputAllocs.front()->getHostPtr());
96 const deUint32* expected = reinterpret_cast<const deUint32*>(&expectedBytes[0]);
97
98 for (size_t i = 0; i < expectedBytes.size() / sizeof (deUint32); i++)
99 {
100 if (results[i] == expected[i])
101 continue;
102
103 if (Float32(results[i]).isNaN() && Float32(expected[i]).isNaN())
104 continue;
105
106 return false;
107 }
108
109 return true;
110 }
111
isNanFloat64(deUint64 f)112 bool isNanFloat64 (deUint64 f)
113 {
114 // NaN has full exponent bits and non-zero mantissa.
115 const deUint64 exponentBits = 0x7ff0000000000000;
116 const deUint64 mantissaBits = 0x000fffffffffffff;
117 return ((f & exponentBits) == exponentBits && (f & mantissaBits) != 0);
118 }
119
checkResultsFloat64(const vector<Resource> & inputs,const vector<AllocationSp> & outputAllocs,const vector<Resource> & expectedOutputs,tcu::TestLog & log)120 bool checkResultsFloat64 (const vector<Resource>& inputs,
121 const vector<AllocationSp>& outputAllocs,
122 const vector<Resource>& expectedOutputs,
123 tcu::TestLog& log)
124 {
125 DE_UNREF(inputs);
126 DE_UNREF(log);
127
128 std::vector<deUint8> expectedBytes;
129 expectedOutputs.front().getBuffer()->getPackedBytes(expectedBytes);
130
131 const deUint64* results = reinterpret_cast<const deUint64*>(outputAllocs.front()->getHostPtr());
132 const deUint64* expected = reinterpret_cast<const deUint64*>(&expectedBytes[0]);
133
134 for (size_t i = 0; i < expectedBytes.size() / sizeof (deUint64); i++)
135 {
136 if (results[i] == expected[i])
137 continue;
138
139 if (isNanFloat64(results[i]) && isNanFloat64(expected[i]))
140 continue;
141
142 return false;
143 }
144
145 return true;
146 }
147
addComputeWorkgroupMemoryTests(tcu::TestCaseGroup * group)148 void addComputeWorkgroupMemoryTests (tcu::TestCaseGroup* group)
149 {
150 tcu::TestContext& testCtx = group->getTestContext();
151 de::Random rnd (deStringHash(group->getName()));
152 const int numElements = 128;
153
154 /*
155 For each data type (TYPE) run the following shader:
156
157 #version 430
158
159 layout (local_size_x = 16, local_size_y = 4, local_size_z = 2) in;
160
161 layout (binding = 0) buffer Input
162 {
163 TYPE data[128];
164 } dataInput;
165
166 layout (binding = 1) buffer Output
167 {
168 TYPE data[128];
169 } dataOutput;
170
171 shared TYPE sharedData[128];
172
173 void main()
174 {
175 uint idx = gl_LocalInvocationID.z * 64 + gl_LocalInvocationID.y * 16 + gl_LocalInvocationID.x;
176 sharedData[idx] = dataInput.data[idx];
177 memoryBarrierShared();
178 barrier();
179 dataOutput.data[idx] = sharedData[127-idx];
180 }
181 */
182
183 const StringTemplate shaderSource (
184 " OpCapability Shader\n"
185 "${capabilities:opt}"
186 "${extensions:opt}"
187 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
188 " OpMemoryModel Logical GLSL450\n"
189 " OpEntryPoint GLCompute %main \"main\" %gl_LocalInvocationID\n"
190 " OpExecutionMode %main LocalSize 16 4 2\n"
191 " OpSource GLSL 430\n"
192 " OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId\n"
193 " OpDecorate %_arr_uint_128_0 ArrayStride ${sizeBytes}\n"
194 " OpMemberDecorate %Input 0 Offset 0\n"
195 " OpDecorate %Input BufferBlock\n"
196 " OpDecorate %dataInput DescriptorSet 0\n"
197 " OpDecorate %dataInput Binding 0\n"
198 " OpDecorate %_arr_uint_128_1 ArrayStride ${sizeBytes}\n"
199 " OpMemberDecorate %Output 0 Offset 0\n"
200 " OpDecorate %Output BufferBlock\n"
201 " OpDecorate %dataOutput DescriptorSet 0\n"
202 " OpDecorate %dataOutput Binding 1\n"
203 " OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize\n"
204 " %void = OpTypeVoid\n"
205 " %3 = OpTypeFunction %void\n"
206 " %u32 = OpTypeInt 32 0\n"
207 " %_ptr_Function_uint = OpTypePointer Function %u32\n"
208 " %v3uint = OpTypeVector %u32 3\n"
209 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
210 " %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
211 " %uint_2 = OpConstant %u32 2\n"
212 " %_ptr_Input_uint = OpTypePointer Input %u32\n"
213 " %uint_64 = OpConstant %u32 64\n"
214 " %uint_1 = OpConstant %u32 1\n"
215 " %uint_16 = OpConstant %u32 16\n"
216 " %uint_0 = OpConstant %u32 0\n"
217 " %uint_127 = OpConstant %u32 127\n"
218 " %uint_4 = OpConstant %u32 4\n"
219 " %i32 = OpTypeInt 32 1\n"
220 "${dataTypeDecl}\n"
221 " %uint_128 = OpConstant %u32 128\n"
222 " %_arr_uint_128 = OpTypeArray %${dataType} %uint_128\n"
223 " %_ptr_Workgroup__arr_uint_128 = OpTypePointer Workgroup %_arr_uint_128\n"
224 " %sharedData = OpVariable %_ptr_Workgroup__arr_uint_128 Workgroup\n"
225 " %_arr_uint_128_0 = OpTypeArray %${dataType} %uint_128\n"
226 " %Input = OpTypeStruct %_arr_uint_128_0\n"
227 " %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
228 " %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
229 " %int_0 = OpConstant %i32 0\n"
230 " %_ptr_Uniform = OpTypePointer Uniform %${dataType}\n"
231 " %_ptr_Workgroup = OpTypePointer Workgroup %${dataType}\n"
232 " %uint_264 = OpConstant %u32 264\n"
233 " %_arr_uint_128_1 = OpTypeArray %${dataType} %uint_128\n"
234 " %Output = OpTypeStruct %_arr_uint_128_1\n"
235 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
236 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
237 " %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_16 %uint_4 %uint_2\n"
238 " %main = OpFunction %void None %3\n"
239 " %5 = OpLabel\n"
240 " %idx = OpVariable %_ptr_Function_uint Function\n"
241 " %14 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_2\n"
242 " %15 = OpLoad %u32 %14\n"
243 " %17 = OpIMul %u32 %15 %uint_64\n"
244 " %19 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_1\n"
245 " %20 = OpLoad %u32 %19\n"
246 " %22 = OpIMul %u32 %20 %uint_16\n"
247 " %23 = OpIAdd %u32 %17 %22\n"
248 " %25 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0\n"
249 " %26 = OpLoad %u32 %25\n"
250 " %27 = OpIAdd %u32 %23 %26\n"
251 " OpStore %idx %27\n"
252 " %33 = OpLoad %u32 %idx\n"
253 " %39 = OpLoad %u32 %idx\n"
254 " %41 = OpAccessChain %_ptr_Uniform %dataInput %int_0 %39\n"
255 " %42 = OpLoad %${dataType} %41\n"
256 " %44 = OpAccessChain %_ptr_Workgroup %sharedData %33\n"
257 " OpStore %44 %42\n"
258 " OpMemoryBarrier %uint_1 %uint_264\n"
259 " OpControlBarrier %uint_2 %uint_2 %uint_264\n"
260 " %50 = OpLoad %u32 %idx\n"
261 " %52 = OpLoad %u32 %idx\n"
262 " %53 = OpISub %u32 %uint_127 %52\n"
263 " %54 = OpAccessChain %_ptr_Workgroup %sharedData %53\n"
264 " %55 = OpLoad %${dataType} %54\n"
265 " %56 = OpAccessChain %_ptr_Uniform %dataOutput %int_0 %50\n"
266 " OpStore %56 %55\n"
267 " OpReturn\n"
268 " OpFunctionEnd\n");
269
270 // float64
271 {
272 VulkanFeatures features;
273 map<string, string> shaderSpec;
274
275 shaderSpec["sizeBytes"] = "8";
276 shaderSpec["dataTypeDecl"] = "%f64 = OpTypeFloat 64";
277 shaderSpec["dataType"] = "f64";
278 shaderSpec["capabilities"] = "OpCapability Float64\n";
279
280 features.coreFeatures.shaderFloat64 = VK_TRUE;
281
282 vector<double> inputData = getFloat64s(rnd, numElements);
283 vector<double> outputData;
284 ComputeShaderSpec spec;
285
286 outputData.reserve(numElements);
287 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
288 outputData.push_back(inputData[numElements - numIdx - 1]);
289
290 spec.assembly = shaderSource.specialize(shaderSpec);
291 spec.numWorkGroups = IVec3(1, 1, 1);
292 spec.verifyIO = checkResultsFloat64;
293 spec.requestedVulkanFeatures = features;
294
295 spec.inputs.push_back(Resource(BufferSp(new Float64Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
296 spec.outputs.push_back(Resource(BufferSp(new Float64Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
297
298 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float64", "", spec));
299 }
300
301 // float32
302 {
303 map<string, string> shaderSpec;
304
305 shaderSpec["sizeBytes"] = "4";
306 shaderSpec["dataTypeDecl"] = "%f32 = OpTypeFloat 32";
307 shaderSpec["dataType"] = "f32";
308
309 vector<float> inputData = getFloat32s(rnd, numElements);
310 vector<float> outputData;
311 ComputeShaderSpec spec;
312
313 outputData.reserve(numElements);
314 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
315 outputData.push_back(inputData[numElements - numIdx - 1]);
316
317 spec.assembly = shaderSource.specialize(shaderSpec);
318 spec.numWorkGroups = IVec3(1, 1, 1);
319 spec.verifyIO = checkResultsFloat32;
320
321 spec.inputs.push_back(Resource(BufferSp(new Float32Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
322 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
323
324 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float32", "", spec));
325 }
326
327 // float16
328 {
329 VulkanFeatures features;
330 map<string, string> shaderSpec;
331
332 shaderSpec["sizeBytes"] = "2";
333 shaderSpec["dataTypeDecl"] = "%f16 = OpTypeFloat 16";
334 shaderSpec["dataType"] = "f16";
335 shaderSpec["extensions"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
336 shaderSpec["capabilities"] = "OpCapability StorageUniformBufferBlock16\n";
337
338 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
339
340 vector<deFloat16> inputData = getFloat16s(rnd, numElements);
341 vector<deFloat16> outputData;
342 ComputeShaderSpec spec;
343
344 outputData.reserve(numElements);
345 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
346 outputData.push_back(inputData[numElements - numIdx - 1]);
347
348 spec.assembly = shaderSource.specialize(shaderSpec);
349 spec.numWorkGroups = IVec3(1, 1, 1);
350 spec.extensions.push_back("VK_KHR_16bit_storage");
351 spec.requestedVulkanFeatures = features;
352 spec.verifyIO = checkResultsFloat16;
353
354 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
355 spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
356
357 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float16", "", spec));
358 }
359
360 // int64
361 {
362 VulkanFeatures features;
363 map<string, string> shaderSpec;
364
365 shaderSpec["sizeBytes"] = "8";
366 shaderSpec["dataTypeDecl"] = "%i64 = OpTypeInt 64 1";
367 shaderSpec["dataType"] = "i64";
368 shaderSpec["capabilities"] = "OpCapability Int64\n";
369
370 features.coreFeatures.shaderInt64 = VK_TRUE;
371
372 vector<deInt64> inputData = getInt64s(rnd, numElements);
373 vector<deInt64> outputData;
374 ComputeShaderSpec spec;
375
376 outputData.reserve(numElements);
377 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
378 outputData.push_back(inputData[numElements - numIdx - 1]);
379
380 spec.assembly = shaderSource.specialize(shaderSpec);
381 spec.numWorkGroups = IVec3(1, 1, 1);
382 spec.requestedVulkanFeatures = features;
383
384 spec.inputs.push_back(Resource(BufferSp(new Int64Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
385 spec.outputs.push_back(Resource(BufferSp(new Int64Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
386
387 group->addChild(new SpvAsmComputeShaderCase(testCtx, "int64", "", spec));
388 }
389
390 // int32
391 {
392 map<string, string> shaderSpec;
393
394 shaderSpec["sizeBytes"] = "4";
395 shaderSpec["dataTypeDecl"] = "";
396 shaderSpec["dataType"] = "i32";
397
398 vector<deInt32> inputData = getInt32s(rnd, numElements);
399 vector<deInt32> outputData;
400 ComputeShaderSpec spec;
401
402 outputData.reserve(numElements);
403 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
404 outputData.push_back(inputData[numElements - numIdx - 1]);
405
406 spec.assembly = shaderSource.specialize(shaderSpec);
407 spec.numWorkGroups = IVec3(1, 1, 1);
408
409 spec.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
410 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
411
412 group->addChild(new SpvAsmComputeShaderCase(testCtx, "int32", "", spec));
413 }
414
415 // int16
416 {
417 VulkanFeatures features;
418 map<string, string> shaderSpec;
419
420 shaderSpec["sizeBytes"] = "2";
421 shaderSpec["dataTypeDecl"] = "%i16 = OpTypeInt 16 1";
422 shaderSpec["dataType"] = "i16";
423 shaderSpec["extensions"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
424 shaderSpec["capabilities"] = "OpCapability Int16\n";
425
426 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
427
428 vector<deInt16> inputData = getInt16s(rnd, numElements);
429 vector<deInt16> outputData;
430 ComputeShaderSpec spec;
431
432 outputData.reserve(numElements);
433 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
434 outputData.push_back(inputData[numElements - numIdx - 1]);
435
436 spec.assembly = shaderSource.specialize(shaderSpec);
437 spec.numWorkGroups = IVec3(1, 1, 1);
438 spec.extensions.push_back("VK_KHR_16bit_storage");
439 spec.requestedVulkanFeatures = features;
440
441 spec.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
442 spec.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
443
444 group->addChild(new SpvAsmComputeShaderCase(testCtx, "int16", "", spec));
445 }
446
447 // int8
448 {
449 VulkanFeatures features;
450 map<string, string> shaderSpec;
451
452 shaderSpec["sizeBytes"] = "1";
453 shaderSpec["dataTypeDecl"] = "%i8 = OpTypeInt 8 1";
454 shaderSpec["dataType"] = "i8";
455 shaderSpec["capabilities"] = "OpCapability UniformAndStorageBuffer8BitAccess\n";
456 shaderSpec["extensions"] = "OpExtension \"SPV_KHR_8bit_storage\"\n";
457
458 features.ext8BitStorage = EXT8BITSTORAGEFEATURES_UNIFORM_STORAGE_BUFFER;
459
460 vector<deInt8> inputData = getInt8s(rnd, numElements);
461 vector<deInt8> outputData;
462 ComputeShaderSpec spec;
463
464 outputData.reserve(numElements);
465 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
466 outputData.push_back(inputData[numElements - numIdx - 1]);
467
468 spec.assembly = shaderSource.specialize(shaderSpec);
469 spec.numWorkGroups = IVec3(1, 1, 1);
470 spec.extensions.push_back("VK_KHR_8bit_storage");
471 spec.requestedVulkanFeatures = features;
472
473 spec.inputs.push_back(Resource(BufferSp(new Int8Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
474 spec.outputs.push_back(Resource(BufferSp(new Int8Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
475
476 group->addChild(new SpvAsmComputeShaderCase(testCtx, "int8", "", spec));
477 }
478
479 // uint64
480 {
481 VulkanFeatures features;
482 map<string, string> shaderSpec;
483
484 shaderSpec["sizeBytes"] = "8";
485 shaderSpec["dataTypeDecl"] = "%u64 = OpTypeInt 64 0";
486 shaderSpec["dataType"] = "u64";
487 shaderSpec["capabilities"] = "OpCapability Int64\n";
488
489 features.coreFeatures.shaderInt64 = VK_TRUE;
490
491 vector<deUint64> inputData;
492 vector<deUint64> outputData;
493 ComputeShaderSpec spec;
494
495 inputData.reserve(numElements);
496 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
497 inputData.push_back(rnd.getUint64());
498
499 outputData.reserve(numElements);
500 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
501 outputData.push_back(inputData[numElements - numIdx - 1]);
502
503 spec.assembly = shaderSource.specialize(shaderSpec);
504 spec.numWorkGroups = IVec3(1, 1, 1);
505 spec.requestedVulkanFeatures = features;
506
507 spec.inputs.push_back(Resource(BufferSp(new Uint64Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
508 spec.outputs.push_back(Resource(BufferSp(new Uint64Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
509
510 group->addChild(new SpvAsmComputeShaderCase(testCtx, "uint64", "", spec));
511 }
512
513 // uint32
514 {
515 map<string, string> shaderSpec;
516
517 shaderSpec["sizeBytes"] = "4";
518 shaderSpec["dataTypeDecl"] = "";
519 shaderSpec["dataType"] = "u32";
520
521 vector<deUint32> inputData;
522 vector<deUint32> outputData;
523 ComputeShaderSpec spec;
524
525 inputData.reserve(numElements);
526 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
527 inputData.push_back(rnd.getUint32());
528
529 outputData.reserve(numElements);
530 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
531 outputData.push_back(inputData[numElements - numIdx - 1]);
532
533 spec.assembly = shaderSource.specialize(shaderSpec);
534 spec.numWorkGroups = IVec3(1, 1, 1);
535
536 spec.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
537 spec.outputs.push_back(Resource(BufferSp(new Uint32Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
538
539 group->addChild(new SpvAsmComputeShaderCase(testCtx, "uint32", "", spec));
540 }
541
542 // uint16
543 {
544 VulkanFeatures features;
545 map<string, string> shaderSpec;
546
547 shaderSpec["sizeBytes"] = "2";
548 shaderSpec["dataTypeDecl"] = "%u16 = OpTypeInt 16 0";
549 shaderSpec["dataType"] = "u16";
550 shaderSpec["capabilities"] = "OpCapability Int16\n";
551 shaderSpec["extensions"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
552
553 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
554
555 vector<deUint16> inputData;
556 vector<deUint16> outputData;
557 ComputeShaderSpec spec;
558
559 inputData.reserve(numElements);
560 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
561 inputData.push_back(rnd.getUint16());
562
563 outputData.reserve(numElements);
564 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
565 outputData.push_back(inputData[numElements - numIdx - 1]);
566
567 spec.assembly = shaderSource.specialize(shaderSpec);
568 spec.numWorkGroups = IVec3(1, 1, 1);
569 spec.extensions.push_back("VK_KHR_16bit_storage");
570 spec.requestedVulkanFeatures = features;
571
572 spec.inputs.push_back(Resource(BufferSp(new Uint16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
573 spec.outputs.push_back(Resource(BufferSp(new Uint16Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
574
575 group->addChild(new SpvAsmComputeShaderCase(testCtx, "uint16", "", spec));
576 }
577
578 // uint8
579 {
580 VulkanFeatures features;
581 map<string, string> shaderSpec;
582
583 shaderSpec["sizeBytes"] = "1";
584 shaderSpec["dataTypeDecl"] = "%u8 = OpTypeInt 8 0";
585 shaderSpec["dataType"] = "u8";
586 shaderSpec["capabilities"] = "OpCapability UniformAndStorageBuffer8BitAccess\n";
587 shaderSpec["extensions"] = "OpExtension \"SPV_KHR_8bit_storage\"\n";
588
589 features.ext8BitStorage = EXT8BITSTORAGEFEATURES_UNIFORM_STORAGE_BUFFER;
590
591 vector<deUint8> inputData;
592 vector<deUint8> outputData;
593 ComputeShaderSpec spec;
594
595 inputData.reserve(numElements);
596 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
597 inputData.push_back(rnd.getUint8());
598
599 outputData.reserve(numElements);
600 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
601 outputData.push_back(inputData[numElements - numIdx - 1]);
602
603 spec.assembly = shaderSource.specialize(shaderSpec);
604 spec.numWorkGroups = IVec3(1, 1, 1);
605 spec.extensions.push_back("VK_KHR_8bit_storage");
606 spec.requestedVulkanFeatures = features;
607
608 spec.inputs.push_back(Resource(BufferSp(new Uint8Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
609 spec.outputs.push_back(Resource(BufferSp(new Uint8Buffer(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
610
611 group->addChild(new SpvAsmComputeShaderCase(testCtx, "uint8", "", spec));
612 }
613 }
614
615 } // anonymous
616
createWorkgroupMemoryComputeGroup(tcu::TestContext & testCtx)617 tcu::TestCaseGroup* createWorkgroupMemoryComputeGroup (tcu::TestContext& testCtx)
618 {
619 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "workgroup_memory", "Compute tests for workgroup memory.."));
620 addComputeWorkgroupMemoryTests(group.get());
621
622 return group.release();
623 }
624
625 } // SpirVAssembly
626 } // vkt
627