Refactor: Compatible compute and graphics VerifyIO
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsm16bitStorageTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 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 the VK_KHR_16bit_storage
22  *//*--------------------------------------------------------------------*/
23
24 // VK_KHR_16bit_storage
25 //
26 // \todo [2017-02-08 antiagainst] Additional corner cases to check:
27 //
28 // * Test {StorageInputOutput16} 16-to-16 one value to two:
29 //     Like the current 16-to-16 tests, but write X16 to two different output variables.
30 //     (Checks that the 16-bit intermediate value can be used twice.)
31 //     Note: The current framework allows only one interface to be used.
32 //     Maybe the best solution is to add custom shaders that manually use two interfaces.
33
34 #include "vktSpvAsm16bitStorageTests.hpp"
35
36 #include "tcuFloat.hpp"
37 #include "tcuRGBA.hpp"
38 #include "tcuStringTemplate.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuVectorUtil.hpp"
41
42 #include "vkDefs.hpp"
43 #include "vkDeviceUtil.hpp"
44 #include "vkMemUtil.hpp"
45 #include "vkPlatform.hpp"
46 #include "vkPrograms.hpp"
47 #include "vkQueryUtil.hpp"
48 #include "vkRef.hpp"
49 #include "vkRefUtil.hpp"
50 #include "vkStrUtil.hpp"
51 #include "vkTypeUtil.hpp"
52
53 #include "deRandom.hpp"
54 #include "deStringUtil.hpp"
55 #include "deUniquePtr.hpp"
56 #include "deMath.h"
57
58 #include "vktSpvAsmComputeShaderCase.hpp"
59 #include "vktSpvAsmComputeShaderTestUtil.hpp"
60 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
61 #include "vktTestCaseUtil.hpp"
62 #include "vktTestGroupUtil.hpp"
63
64 #include <limits>
65 #include <map>
66 #include <string>
67 #include <sstream>
68 #include <utility>
69
70 namespace vkt
71 {
72 namespace SpirVAssembly
73 {
74
75 using namespace vk;
76 using std::map;
77 using std::string;
78 using std::vector;
79 using tcu::Float16;
80 using tcu::IVec3;
81 using tcu::IVec4;
82 using tcu::RGBA;
83 using tcu::TestLog;
84 using tcu::TestStatus;
85 using tcu::Vec4;
86 using de::UniquePtr;
87 using tcu::StringTemplate;
88 using tcu::Vec4;
89
90 namespace
91 {
92
93 enum ShaderTemplate
94 {
95         SHADERTEMPLATE_TYPES = 0,
96         SHADERTEMPLATE_STRIDE32BIT_STD140,
97         SHADERTEMPLATE_STRIDE32BIT_STD430,
98         SHADERTEMPLATE_STRIDE16BIT_STD140,
99         SHADERTEMPLATE_STRIDE16BIT_STD430,
100         SHADERTEMPLATE_STRIDEMIX_STD140,
101         SHADERTEMPLATE_STRIDEMIX_STD430
102 };
103
104 bool compare16Bit (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
105 {
106         return compare16BitFloat (original, returned, flags, log);
107 }
108
109 bool compare16Bit (deUint16 original, float returned, RoundingModeFlags flags, tcu::TestLog& log)
110 {
111         DE_UNREF(flags);
112         return compare16BitFloat (original, returned, log);
113 }
114
115 bool compare16Bit (deInt16 original, deInt16 returned, RoundingModeFlags flags, tcu::TestLog& log)
116 {
117         DE_UNREF(flags);
118         DE_UNREF(log);
119         return (returned == original);
120 }
121
122 struct StructTestData
123 {
124         const int structArraySize; //Size of Struct Array
125         const int nestedArraySize; //Max size of any nested arrays
126 };
127
128 struct Capability
129 {
130         const char*                             name;
131         const char*                             cap;
132         const char*                             decor;
133         vk::VkDescriptorType    dtype;
134 };
135
136 static const Capability CAPABILITIES[]  =
137 {
138         {"uniform_buffer_block",        "StorageUniformBufferBlock16",  "BufferBlock",  VK_DESCRIPTOR_TYPE_STORAGE_BUFFER},
139         {"uniform",                                     "StorageUniform16",                             "Block",                VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER},
140 };
141
142 static const StructTestData structData = {7, 11};
143
144 VulkanFeatures  get16BitStorageFeatures (const char* cap)
145 {
146         VulkanFeatures features;
147         if (string(cap) == "uniform_buffer_block")
148                 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
149         else if (string(cap) == "uniform")
150                 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM;
151         else
152                 DE_ASSERT(false && "not supported");
153
154         return features;
155 }
156
157 int getStructSize(const ShaderTemplate  shaderTemplate)
158 {
159         switch (shaderTemplate)
160         {
161         case SHADERTEMPLATE_STRIDE16BIT_STD140:
162                 return 600 * structData.structArraySize;                //size of struct in f16 with offsets
163         case SHADERTEMPLATE_STRIDE16BIT_STD430:
164                 return 184 * structData.structArraySize;                //size of struct in f16 with offsets
165         case SHADERTEMPLATE_STRIDE32BIT_STD140:
166                 return 304 * structData.structArraySize;                //size of struct in f32 with offsets
167         case SHADERTEMPLATE_STRIDE32BIT_STD430:
168                 return 184 * structData.structArraySize;                //size of struct in f32 with offset
169         case SHADERTEMPLATE_STRIDEMIX_STD140:
170                 return 4480 * structData.structArraySize / 2;   //size of struct in 16b with offset
171         case SHADERTEMPLATE_STRIDEMIX_STD430:
172                 return 1216 * structData.structArraySize / 2;   //size of struct in 16b with offset
173         default:
174                 DE_ASSERT(0);
175         }
176         return 0;
177 }
178
179 // Batch function to check arrays of 16-bit floats.
180 //
181 // For comparing 16-bit floats, we need to consider both RTZ and RTE. So we can only recalculate
182 // the expected values here instead of get the expected values directly from the test case.
183 // Thus we need original floats here but not expected outputs.
184 template<RoundingModeFlags RoundingMode>
185 bool graphicsCheck16BitFloats (const std::vector<Resource>&     originalFloats,
186                                                            const vector<AllocationSp>&  outputAllocs,
187                                                            const std::vector<Resource>& expectedOutputs,
188                                                            tcu::TestLog&                                log)
189 {
190         if (outputAllocs.size() != originalFloats.size())
191                 return false;
192
193         for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
194         {
195                 vector<deUint8> originalBytes;
196                 originalFloats[outputNdx].getBytes(originalBytes);
197
198                 const deUint16* returned        = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
199                 const float*    original        = reinterpret_cast<const float*>(&originalBytes.front());
200                 const deUint32  count           = static_cast<deUint32>(expectedOutputs[outputNdx].getByteSize() / sizeof(deUint16));
201                 const deUint32  inputStride     = static_cast<deUint32>(originalBytes.size() / sizeof(float)) / count;
202
203                 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
204                         if (!compare16BitFloat(original[numNdx * inputStride], returned[numNdx], RoundingMode, log))
205                                 return false;
206         }
207
208         return true;
209 }
210
211 bool computeCheckBuffersFloats (const std::vector<Resource>&    originalFloats,
212                                                                 const vector<AllocationSp>&             outputAllocs,
213                                                                 const std::vector<Resource>&    /*expectedOutputs*/,
214                                                                 tcu::TestLog&                                   /*log*/)
215 {
216         std::vector<deUint8> result;
217         originalFloats.front().getBytes(result);
218
219         const deUint16 * results = reinterpret_cast<const deUint16 *>(&result[0]);
220         const deUint16 * expected = reinterpret_cast<const deUint16 *>(outputAllocs.front()->getHostPtr());
221
222         for (size_t i = 0; i < result.size() / sizeof (deUint16); ++i)
223         {
224                 if (results[i] == expected[i])
225                         continue;
226
227                 if (Float16(results[i]).isNaN() && Float16(expected[i]).isNaN())
228                         continue;
229
230                 return false;
231         }
232
233         return true;
234 }
235
236 template<RoundingModeFlags RoundingMode>
237 bool computeCheck16BitFloats (const std::vector<Resource>&      originalFloats,
238                                                           const vector<AllocationSp>&   outputAllocs,
239                                                           const std::vector<Resource>&  expectedOutputs,
240                                                           tcu::TestLog&                                 log)
241 {
242         if (outputAllocs.size() != originalFloats.size())
243                 return false;
244
245         for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
246         {
247                 vector<deUint8> originalBytes;
248                 originalFloats[outputNdx].getBytes(originalBytes);
249
250                 const deUint16* returned        = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
251                 const float*    original        = reinterpret_cast<const float*>(&originalBytes.front());
252                 const deUint32  count           = static_cast<deUint32>(expectedOutputs[outputNdx].getByteSize() / sizeof(deUint16));
253                 const deUint32  inputStride     = static_cast<deUint32>(originalBytes.size() / sizeof(float)) / count;
254
255                 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
256                         if (!compare16BitFloat(original[numNdx * inputStride], returned[numNdx], RoundingMode, log))
257                                 return false;
258         }
259
260         return true;
261 }
262
263 // Batch function to check arrays of 32-bit floats.
264 //
265 // For comparing 32-bit floats, we just need the expected value precomputed in the test case.
266 // So we need expected outputs here but not original floats.
267 bool check32BitFloats (const std::vector<Resource>&             /* originalFloats */,
268                                            const std::vector<AllocationSp>& outputAllocs,
269                                            const std::vector<Resource>&         expectedOutputs,
270                                            tcu::TestLog&                                        log)
271 {
272         if (outputAllocs.size() != expectedOutputs.size())
273                 return false;
274
275         for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
276         {
277                 vector<deUint8> expectedBytes;
278                 expectedOutputs[outputNdx].getBytes(expectedBytes);
279
280                 const float*    returnedAsFloat = static_cast<const float*>(outputAllocs[outputNdx]->getHostPtr());
281                 const float*    expectedAsFloat = reinterpret_cast<const float*>(&expectedBytes.front());
282                 const deUint32  count                   = static_cast<deUint32>(expectedBytes.size() / sizeof(float));
283
284                 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
285                         if (!compare32BitFloat(expectedAsFloat[numNdx], returnedAsFloat[numNdx], log))
286                                 return false;
287         }
288
289         return true;
290 }
291
292 // Generate and return 32-bit integers.
293 //
294 // Expected count to be at least 16.
295 vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count)
296 {
297         vector<deInt32>         data;
298
299         data.reserve(count);
300
301         // Make sure we have boundary numbers.
302         data.push_back(deInt32(0x00000000));  // 0
303         data.push_back(deInt32(0x00000001));  // 1
304         data.push_back(deInt32(0x0000002a));  // 42
305         data.push_back(deInt32(0x00007fff));  // 32767
306         data.push_back(deInt32(0x00008000));  // 32768
307         data.push_back(deInt32(0x0000ffff));  // 65535
308         data.push_back(deInt32(0x00010000));  // 65536
309         data.push_back(deInt32(0x7fffffff));  // 2147483647
310         data.push_back(deInt32(0x80000000));  // -2147483648
311         data.push_back(deInt32(0x80000001));  // -2147483647
312         data.push_back(deInt32(0xffff0000));  // -65536
313         data.push_back(deInt32(0xffff0001));  // -65535
314         data.push_back(deInt32(0xffff8000));  // -32768
315         data.push_back(deInt32(0xffff8001));  // -32767
316         data.push_back(deInt32(0xffffffd6));  // -42
317         data.push_back(deInt32(0xffffffff));  // -1
318
319         DE_ASSERT(count >= data.size());
320
321         for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
322                 data.push_back(static_cast<deInt32>(rnd.getUint32()));
323
324         return data;
325 }
326
327 // Generate and return 16-bit integers.
328 //
329 // Expected count to be at least 8.
330 vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count)
331 {
332         vector<deInt16>         data;
333
334         data.reserve(count);
335
336         // Make sure we have boundary numbers.
337         data.push_back(deInt16(0x0000));  // 0
338         data.push_back(deInt16(0x0001));  // 1
339         data.push_back(deInt16(0x002a));  // 42
340         data.push_back(deInt16(0x7fff));  // 32767
341         data.push_back(deInt16(0x8000));  // -32868
342         data.push_back(deInt16(0x8001));  // -32767
343         data.push_back(deInt16(0xffd6));  // -42
344         data.push_back(deInt16(0xffff));  // -1
345
346         DE_ASSERT(count >= data.size());
347
348         for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx)
349                 data.push_back(static_cast<deInt16>(rnd.getUint16()));
350
351         return data;
352 }
353
354 // IEEE-754 floating point numbers:
355 // +--------+------+----------+-------------+
356 // | binary | sign | exponent | significand |
357 // +--------+------+----------+-------------+
358 // | 16-bit |  1   |    5     |     10      |
359 // +--------+------+----------+-------------+
360 // | 32-bit |  1   |    8     |     23      |
361 // +--------+------+----------+-------------+
362 //
363 // 16-bit floats:
364 //
365 // 0   000 00   00 0000 0001 (0x0001: 2e-24:         minimum positive denormalized)
366 // 0   000 00   11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
367 // 0   000 01   00 0000 0000 (0x0400: 2e-14:         minimum positive normalized)
368 //
369 // 32-bit floats:
370 //
371 // 0   011 1110 1   001 0000 0000 0000 0000 0000 (0x3e900000: 0.28125: with exact match in 16-bit normalized)
372 // 0   011 1000 1   000 0000 0011 0000 0000 0000 (0x38803000: exact half way within two 16-bit normalized; round to zero: 0x0401)
373 // 1   011 1000 1   000 0000 0011 0000 0000 0000 (0xb8803000: exact half way within two 16-bit normalized; round to zero: 0x8402)
374 // 0   011 1000 1   000 0000 1111 1111 0000 0000 (0x3880ff00: not exact half way within two 16-bit normalized; round to zero: 0x0403)
375 // 1   011 1000 1   000 0000 1111 1111 0000 0000 (0xb880ff00: not exact half way within two 16-bit normalized; round to zero: 0x8404)
376
377 // Generate and return 32-bit floats
378 //
379 // The first 24 number pairs are manually picked, while the rest are randomly generated.
380 // Expected count to be at least 24 (numPicks).
381 vector<float> getFloat32s (de::Random& rnd, deUint32 count)
382 {
383         vector<float>           float32;
384
385         float32.reserve(count);
386
387         // Zero
388         float32.push_back(0.f);
389         float32.push_back(-0.f);
390         // Infinity
391         float32.push_back(std::numeric_limits<float>::infinity());
392         float32.push_back(-std::numeric_limits<float>::infinity());
393         // SNaN
394         float32.push_back(std::numeric_limits<float>::signaling_NaN());
395         float32.push_back(-std::numeric_limits<float>::signaling_NaN());
396         // QNaN
397         float32.push_back(std::numeric_limits<float>::quiet_NaN());
398         float32.push_back(-std::numeric_limits<float>::quiet_NaN());
399
400         // Denormalized 32-bit float matching 0 in 16-bit
401         float32.push_back(deFloatLdExp(1.f, -127));
402         float32.push_back(-deFloatLdExp(1.f, -127));
403
404         // Normalized 32-bit float matching 0 in 16-bit
405         float32.push_back(deFloatLdExp(1.f, -100));
406         float32.push_back(-deFloatLdExp(1.f, -100));
407         // Normalized 32-bit float with exact denormalized match in 16-bit
408         float32.push_back(deFloatLdExp(1.f, -24));  // 2e-24: minimum 16-bit positive denormalized
409         float32.push_back(-deFloatLdExp(1.f, -24)); // 2e-24: maximum 16-bit negative denormalized
410         // Normalized 32-bit float with exact normalized match in 16-bit
411         float32.push_back(deFloatLdExp(1.f, -14));  // 2e-14: minimum 16-bit positive normalized
412         float32.push_back(-deFloatLdExp(1.f, -14)); // 2e-14: maximum 16-bit negative normalized
413         // Normalized 32-bit float falling above half way within two 16-bit normalized
414         float32.push_back(bitwiseCast<float>(deUint32(0x3880ff00)));
415         float32.push_back(bitwiseCast<float>(deUint32(0xb880ff00)));
416         // Normalized 32-bit float falling exact half way within two 16-bit normalized
417         float32.push_back(bitwiseCast<float>(deUint32(0x38803000)));
418         float32.push_back(bitwiseCast<float>(deUint32(0xb8803000)));
419         // Some number
420         float32.push_back(0.28125f);
421         float32.push_back(-0.28125f);
422         // Normalized 32-bit float matching infinity in 16-bit
423         float32.push_back(deFloatLdExp(1.f, 100));
424         float32.push_back(-deFloatLdExp(1.f, 100));
425
426         const deUint32          numPicks        = static_cast<deUint32>(float32.size());
427
428         DE_ASSERT(count >= numPicks);
429         count -= numPicks;
430
431         for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
432                 float32.push_back(rnd.getFloat());
433
434         return float32;
435 }
436
437 // IEEE-754 floating point numbers:
438 // +--------+------+----------+-------------+
439 // | binary | sign | exponent | significand |
440 // +--------+------+----------+-------------+
441 // | 16-bit |  1   |    5     |     10      |
442 // +--------+------+----------+-------------+
443 // | 32-bit |  1   |    8     |     23      |
444 // +--------+------+----------+-------------+
445 //
446 // 16-bit floats:
447 //
448 // 0   000 00   00 0000 0001 (0x0001: 2e-24:         minimum positive denormalized)
449 // 0   000 00   11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
450 // 0   000 01   00 0000 0000 (0x0400: 2e-14:         minimum positive normalized)
451 //
452 // 0   000 00   00 0000 0000 (0x0000: +0)
453 // 0   111 11   00 0000 0000 (0x7c00: +Inf)
454 // 0   000 00   11 1111 0000 (0x03f0: +Denorm)
455 // 0   000 01   00 0000 0001 (0x0401: +Norm)
456 // 0   111 11   00 0000 1111 (0x7c0f: +SNaN)
457 // 0   111 11   00 1111 0000 (0x7c0f: +QNaN)
458
459
460 // Generate and return 16-bit floats and their corresponding 32-bit values.
461 //
462 // The first 14 number pairs are manually picked, while the rest are randomly generated.
463 // Expected count to be at least 14 (numPicks).
464 vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count)
465 {
466         vector<deFloat16>       float16;
467
468         float16.reserve(count);
469
470         // Zero
471         float16.push_back(deUint16(0x0000));
472         float16.push_back(deUint16(0x8000));
473         // Infinity
474         float16.push_back(deUint16(0x7c00));
475         float16.push_back(deUint16(0xfc00));
476         // SNaN
477         float16.push_back(deUint16(0x7c0f));
478         float16.push_back(deUint16(0xfc0f));
479         // QNaN
480         float16.push_back(deUint16(0x7cf0));
481         float16.push_back(deUint16(0xfcf0));
482
483         // Denormalized
484         float16.push_back(deUint16(0x03f0));
485         float16.push_back(deUint16(0x83f0));
486         // Normalized
487         float16.push_back(deUint16(0x0401));
488         float16.push_back(deUint16(0x8401));
489         // Some normal number
490         float16.push_back(deUint16(0x14cb));
491         float16.push_back(deUint16(0x94cb));
492
493         const deUint32          numPicks        = static_cast<deUint32>(float16.size());
494
495         DE_ASSERT(count >= numPicks);
496         count -= numPicks;
497
498         for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
499                 float16.push_back(rnd.getUint16());
500
501         return float16;
502 }
503
504 void addInfo(vector<bool>& info, int& ndx, const int count, bool isData)
505 {
506         for (int index = 0; index < count; ++index)
507                 info[ndx++] = isData;
508 }
509
510 vector<deFloat16> data16bitStd140 (de::Random& rnd)
511 {
512         return getFloat16s(rnd, getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD140));
513 }
514
515 vector<bool> info16bitStd140 (void)
516 {
517         int                             ndx                     = 0u;
518         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD140));
519
520         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
521         {
522                 infoData[ndx++] = true;                                         //f16
523                 infoData[ndx++] = false;                                        //offset
524
525                 infoData[ndx++] = true;                                         //v2f16
526                 infoData[ndx++] = true;                                         //v2f16
527
528                 addInfo(infoData, ndx, 3, true);                        //v3f16
529                 infoData[ndx++] = false;                                        //offset
530
531                 addInfo(infoData, ndx, 4, true);                        //v4f16
532                 addInfo(infoData, ndx, 4, false);                       //offset
533
534                 //f16[3];
535                 for (int i = 0; i < 3; ++i)
536                 {
537                         infoData[ndx++] = true;                                 //f16[0];
538                         addInfo(infoData, ndx, 7, false);               //offset
539                 }
540
541                 //struct {f16, v2f16[3]} [11]
542                 for (int i = 0; i < structData.nestedArraySize; ++i)
543                 {
544                         //struct.f16
545                         infoData[ndx++] = true;                                 //f16
546                         addInfo(infoData, ndx, 7, false);               //offset
547                         //struct.f16.v2f16[3]
548                         for (int j = 0; j < 3; ++j)
549                         {
550                                 infoData[ndx++] = true;                         //v2f16
551                                 infoData[ndx++] = true;                         //v2f16
552                                 addInfo(infoData, ndx, 6, false);       //offset
553                         }
554                 }
555
556                 //vec2[11];
557                 for (int i = 0; i < structData.nestedArraySize; ++i)
558                 {
559                         infoData[ndx++] = true;                                 //v2f16
560                         infoData[ndx++] = true;                                 //v2f16
561                         addInfo(infoData, ndx, 6, false);               //offset
562                 }
563
564                 //f16
565                 infoData[ndx++] = true;                                         //f16
566                 addInfo(infoData, ndx, 7, false);                       //offset
567
568                 //vec3[11]
569                 for (int i = 0; i < structData.nestedArraySize; ++i)
570                 {
571                         addInfo(infoData, ndx, 3, true);                //vec3
572                         addInfo(infoData, ndx, 5, false);               //offset
573                 }
574
575                 //vec4[3]
576                 for (int i = 0; i < 3; ++i)
577                 {
578                         addInfo(infoData, ndx, 4, true);                //vec4
579                         addInfo(infoData, ndx, 4, false);               //offset
580                 }
581         }
582
583         //Please check the data and offset
584         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
585
586         return infoData;
587 }
588
589 vector<deFloat16> data16bitStd430 (de::Random& rnd)
590 {
591         return getFloat16s(rnd, getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430));
592 }
593
594 vector<bool> info16bitStd430 (void)
595 {
596         int                             ndx                     = 0u;
597         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430));
598
599         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
600         {
601                 infoData[ndx++] = true;                                 //f16
602                 infoData[ndx++] = false;                                //offset
603
604                 infoData[ndx++] = true;                                 //v2f16
605                 infoData[ndx++] = true;                                 //v2f16
606
607                 addInfo(infoData, ndx, 3, true);                //v3f16
608                 infoData[ndx++] = false;                                //offset
609
610                 addInfo(infoData, ndx, 4, true);                //v4f16
611
612                 //f16[3];
613                 for (int i = 0; i < 3; ++i)
614                 {
615                         infoData[ndx++] = true;                         //f16;
616                 }
617                 addInfo(infoData, ndx, 1, false);               //offset
618
619                 //struct {f16, v2f16[3]} [11]
620                 for (int i = 0; i < structData.nestedArraySize; ++i)
621                 {
622                         //struct.f16
623                         infoData[ndx++] = true;                         //f16
624                         infoData[ndx++] = false;                        //offset
625                         //struct.f16.v2f16[3]
626                         for (int j = 0; j < 3; ++j)
627                         {
628                                 infoData[ndx++] = true;                 //v2f16
629                                 infoData[ndx++] = true;                 //v2f16
630                         }
631                 }
632
633                 //vec2[11];
634                 for (int i = 0; i < structData.nestedArraySize; ++i)
635                 {
636                         infoData[ndx++] = true;                         //v2f16
637                         infoData[ndx++] = true;                         //v2f16
638                 }
639
640                 //f16
641                 infoData[ndx++] = true;                                 //f16
642                 infoData[ndx++] = false;                                //offset
643
644                 //vec3[11]
645                 for (int i = 0; i < structData.nestedArraySize; ++i)
646                 {
647                         addInfo(infoData, ndx, 3, true);        //vec3
648                         infoData[ndx++] = false;                        //offset
649                 }
650
651                 //vec4[3]
652                 for (int i = 0; i < 3; ++i)
653                 {
654                         addInfo(infoData, ndx, 4, true);        //vec4
655                 }
656         }
657
658         //Please check the data and offset
659         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
660         return infoData;
661 }
662
663 vector<float> data32bitStd140 (de::Random& rnd)
664 {
665         return getFloat32s(rnd, getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD140));
666 }
667
668 vector<bool> info32bitStd140 (void)
669 {
670         int                             ndx                     = 0u;
671         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD140));
672
673         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
674         {
675                 infoData[ndx++] = true;                                 //f32
676                 infoData[ndx++] = false;                                //offset
677
678                 infoData[ndx++] = true;                                 //v2f32
679                 infoData[ndx++] = true;                                 //v2f32
680
681                 addInfo(infoData, ndx, 3, true);                //v3f32
682                 infoData[ndx++] = false;                                //offset
683
684                 addInfo(infoData, ndx, 4, true);                //v4f16
685
686                 //f32[3];
687                 for (int i = 0; i < 3; ++i)
688                 {
689                         infoData[ndx++] = true;                         //f32;
690                         addInfo(infoData, ndx, 3, false);       //offset
691                 }
692
693                 //struct {f32, v2f32[3]} [11]
694                 for (int i = 0; i < structData.nestedArraySize; ++i)
695                 {
696                         //struct.f32
697                         infoData[ndx++] = true;                         //f32
698                         addInfo(infoData, ndx, 3, false);       //offset
699                         //struct.f32.v2f16[3]
700                         for (int j = 0; j < 3; ++j)
701                         {
702                                 infoData[ndx++] = true;                 //v2f32
703                                 infoData[ndx++] = true;                 //v2f32
704                                 infoData[ndx++] = false;                //offset
705                                 infoData[ndx++] = false;                //offset
706                         }
707                 }
708
709                 //v2f32[11];
710                 for (int i = 0; i < structData.nestedArraySize; ++i)
711                 {
712                         infoData[ndx++] = true;                         //v2f32
713                         infoData[ndx++] = true;                         //v2f32
714                         infoData[ndx++] = false;                        //offset
715                         infoData[ndx++] = false;                        //offset
716                 }
717
718                 //f16
719                 infoData[ndx++] = true;                                 //f16
720                 addInfo(infoData, ndx, 3, false);               //offset
721
722                 //vec3[11]
723                 for (int i = 0; i < structData.nestedArraySize; ++i)
724                 {
725                         addInfo(infoData, ndx, 3, true);        //v3f32
726                         infoData[ndx++] = false;                        //offset
727                 }
728
729                 //vec4[3]
730                 for (int i = 0; i < 3; ++i)
731                 {
732                         addInfo(infoData, ndx, 4, true);        //vec4
733                 }
734         }
735
736         //Please check the data and offset
737         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
738         return infoData;
739 }
740
741 vector<float> data32bitStd430 (de::Random& rnd)
742 {
743         return getFloat32s(rnd, getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430));
744 }
745
746 vector<bool> info32bitStd430 (void)
747 {
748         int                             ndx                     = 0u;
749         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430));
750
751         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
752         {
753                 infoData[ndx++] = true;                                 //f32
754                 infoData[ndx++] = false;                                //offset
755
756                 infoData[ndx++] = true;                                 //v2f32
757                 infoData[ndx++] = true;                                 //v2f32
758
759                 addInfo(infoData, ndx, 3, true);                //v3f32
760                 infoData[ndx++] = false;                                //offset
761
762                 addInfo(infoData, ndx, 4, true);                //v4f16
763
764                 //f32[3];
765                 for (int i = 0; i < 3; ++i)
766                 {
767                         infoData[ndx++] = true;                         //f32;
768                 }
769                 infoData[ndx++] = false;                                //offset
770
771                 //struct {f32, v2f32[3]} [11]
772                 for (int i = 0; i < structData.nestedArraySize; ++i)
773                 {
774                         //struct.f32
775                         infoData[ndx++] = true;                         //f32
776                         infoData[ndx++] = false;                        //offset
777                         //struct.f32.v2f16[3]
778                         for (int j = 0; j < 3; ++j)
779                         {
780                                 infoData[ndx++] = true;                 //v2f32
781                                 infoData[ndx++] = true;                 //v2f32
782                         }
783                 }
784
785                 //v2f32[11];
786                 for (int i = 0; i < structData.nestedArraySize; ++i)
787                 {
788                         infoData[ndx++] = true;                         //v2f32
789                         infoData[ndx++] = true;                         //v2f32
790                 }
791
792                 //f32
793                 infoData[ndx++] = true;                                 //f32
794                 infoData[ndx++] = false;                                //offset
795
796                 //vec3[11]
797                 for (int i = 0; i < structData.nestedArraySize; ++i)
798                 {
799                         addInfo(infoData, ndx, 3, true);        //v3f32
800                         infoData[ndx++] = false;                        //offset
801                 }
802
803                 //vec4[3]
804                 for (int i = 0; i < 3; ++i)
805                 {
806                         addInfo(infoData, ndx, 4, true);        //vec4
807                 }
808         }
809
810         //Please check the data and offset
811         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
812         return infoData;
813 }
814
815 vector<deInt16> dataMixStd140 (de::Random& rnd)
816 {
817         return getInt16s(rnd, getStructSize(SHADERTEMPLATE_STRIDEMIX_STD140));
818 }
819
820 vector<bool> infoMixStd140 (void)
821 {
822         int                             ndx                     = 0u;
823         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD140));
824         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
825         {
826                 infoData[ndx++] = true;                         //16b
827                 addInfo(infoData, ndx, 1, false);               //offset
828
829                 addInfo(infoData, ndx, 2, true);                //32b
830
831                 addInfo(infoData, ndx, 2, true);                //v2b16
832                 addInfo(infoData, ndx, 2, false);               //offset
833
834                 addInfo(infoData, ndx, 4, true);                //v2b32
835
836                 addInfo(infoData, ndx, 3, true);                //v3b16
837                 addInfo(infoData, ndx, 1, false);               //offset
838
839                 addInfo(infoData, ndx, 6, true);                //v3b32
840                 addInfo(infoData, ndx, 2, false);               //offset
841
842                 addInfo(infoData, ndx, 4, true);                //v4b16
843                 addInfo(infoData, ndx, 4, false);               //offset
844
845                 addInfo(infoData, ndx, 8, true);                //v4b32
846
847                 //strut {b16, b32, v2b16[11], b32[11]}
848                 for (int i = 0; i < structData.nestedArraySize; ++i)
849                 {
850                         infoData[ndx++] = true;                         //16b
851                         addInfo(infoData, ndx, 1, false);       //offset
852
853                         addInfo(infoData, ndx, 2, true);        //32b
854                         addInfo(infoData, ndx, 4, false);       //offset
855
856                         for (int j = 0; j < structData.nestedArraySize; ++j)
857                         {
858                                 addInfo(infoData, ndx, 2, true);        //v2b16[11]
859                                 addInfo(infoData, ndx, 6, false);       //offset
860                         }
861
862                         for (int j = 0; j < structData.nestedArraySize; ++j)
863                         {
864                                 addInfo(infoData, ndx, 2, true);        //b32[11]
865                                 addInfo(infoData, ndx, 6, false);       //offset
866                         }
867                 }
868
869                 for (int i = 0; i < structData.nestedArraySize; ++i)
870                 {
871                         infoData[ndx++] = true;                         //16b[11]
872                         addInfo(infoData, ndx, 7, false);               //offset
873                 }
874
875                 for (int i = 0; i < structData.nestedArraySize; ++i)
876                 {
877                         addInfo(infoData, ndx, 2, true);        //b32bIn[11]
878                         addInfo(infoData, ndx, 6, false);       //offset
879                 }
880         }
881
882         //Please check the data and offset
883         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
884         return infoData;
885 }
886
887 vector<deInt16> dataMixStd430 (de::Random& rnd)
888 {
889         return getInt16s(rnd, getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430));
890 }
891
892 vector<bool> infoMixStd430 (void)
893 {
894         int                             ndx                     = 0u;
895         vector<bool>    infoData        (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430));
896         for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
897         {
898                 infoData[ndx++] = true;                         //16b
899                 addInfo(infoData, ndx, 1, false);               //offset
900
901                 addInfo(infoData, ndx, 2, true);                //32b
902
903                 addInfo(infoData, ndx, 2, true);                //v2b16
904                 addInfo(infoData, ndx, 2, false);               //offset
905
906                 addInfo(infoData, ndx, 4, true);                //v2b32
907
908                 addInfo(infoData, ndx, 3, true);                //v3b16
909                 addInfo(infoData, ndx, 1, false);               //offset
910
911                 addInfo(infoData, ndx, 6, true);                //v3b32
912                 addInfo(infoData, ndx, 2, false);               //offset
913
914                 addInfo(infoData, ndx, 4, true);                //v4b16
915                 addInfo(infoData, ndx, 4, false);               //offset
916
917                 addInfo(infoData, ndx, 8, true);                //v4b32
918
919                 //strut {b16, b32, v2b16[11], b32[11]}
920                 for (int i = 0; i < structData.nestedArraySize; ++i)
921                 {
922                         infoData[ndx++] = true;                 //16b
923                         addInfo(infoData, ndx, 1, false);       //offset
924
925                         addInfo(infoData, ndx, 2, true);        //32b
926
927                         addInfo(infoData, ndx, 22, true);       //v2b16[11]
928
929                         addInfo(infoData, ndx, 22, true);       //b32[11]
930                 }
931
932                 addInfo(infoData, ndx, 11, true);               //16b[11]
933                 infoData[ndx++] = false;                                //offset
934
935                 addInfo(infoData, ndx, 22, true);               //32b[11]
936                 addInfo(infoData, ndx, 6, false);               //offset
937         }
938
939         //Please check the data and offset
940         DE_ASSERT(ndx == static_cast<int>(infoData.size()));
941         return infoData;
942 }
943
944 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
945 bool compareStruct(const resultType* returned, const originType* original, tcu::TestLog& log)
946 {
947                 vector<bool>            resultInfo;
948                 vector<bool>            originInfo;
949                 vector<resultType>      resultToCompare;
950                 vector<originType>      originToCompare;
951
952                 switch(funcOrigin)
953                 {
954                 case SHADERTEMPLATE_STRIDE16BIT_STD140:
955                         originInfo = info16bitStd140();
956                         break;
957                 case SHADERTEMPLATE_STRIDE16BIT_STD430:
958                         originInfo = info16bitStd430();
959                         break;
960                 case SHADERTEMPLATE_STRIDE32BIT_STD140:
961                         originInfo = info32bitStd140();
962                         break;
963                 case SHADERTEMPLATE_STRIDE32BIT_STD430:
964                         originInfo = info32bitStd430();
965                         break;
966                 case SHADERTEMPLATE_STRIDEMIX_STD140:
967                         originInfo = infoMixStd140();
968                         break;
969                 case SHADERTEMPLATE_STRIDEMIX_STD430:
970                         originInfo = infoMixStd430();
971                         break;
972                 default:
973                         DE_ASSERT(0);
974                 }
975
976                 switch(funcResult)
977                 {
978                 case SHADERTEMPLATE_STRIDE16BIT_STD140:
979                         resultInfo = info16bitStd140();
980                         break;
981                 case SHADERTEMPLATE_STRIDE16BIT_STD430:
982                         resultInfo = info16bitStd430();
983                         break;
984                 case SHADERTEMPLATE_STRIDE32BIT_STD140:
985                         resultInfo = info32bitStd140();
986                         break;
987                 case SHADERTEMPLATE_STRIDE32BIT_STD430:
988                         resultInfo = info32bitStd430();
989                         break;
990                 case SHADERTEMPLATE_STRIDEMIX_STD140:
991                         resultInfo = infoMixStd140();
992                         break;
993                 case SHADERTEMPLATE_STRIDEMIX_STD430:
994                         resultInfo = infoMixStd430();
995                         break;
996                 default:
997                         DE_ASSERT(0);
998                 }
999
1000                 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(resultInfo.size()); ++ndx)
1001                 {
1002                         if (resultInfo[ndx])
1003                                 resultToCompare.push_back(returned[ndx]);
1004                 }
1005
1006                 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(originInfo.size()); ++ndx)
1007                 {
1008                         if (originInfo[ndx])
1009                                 originToCompare.push_back(original[ndx]);
1010                 }
1011
1012                 //Different offset but that same amount of data
1013                 DE_ASSERT(originToCompare.size() == resultToCompare.size());
1014                 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(originToCompare.size()); ++ndx)
1015                 {
1016                         if (!compare16Bit(originToCompare[ndx], resultToCompare[ndx], RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ), log))
1017                                 return false;
1018                 }
1019                 return true;
1020 }
1021
1022 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
1023 bool computeCheckStruct (const std::vector<Resource>&   originalFloats,
1024                                                  const vector<AllocationSp>&    outputAllocs,
1025                                                  const std::vector<Resource>&   /* expectedOutputs */,
1026                                                  tcu::TestLog&                                  log)
1027 {
1028         for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
1029         {
1030                 vector<deUint8> originalBytes;
1031                 originalFloats[outputNdx].getBytes(originalBytes);
1032
1033                 const resultType*       returned        = static_cast<const resultType*>(outputAllocs[outputNdx]->getHostPtr());
1034                 const originType*       original        = reinterpret_cast<const originType*>(&originalBytes.front());
1035
1036                 if(!compareStruct<originType, resultType, funcOrigin, funcResult>(returned, original, log))
1037                         return false;
1038         }
1039         return true;
1040 }
1041
1042 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
1043 bool graphicsCheckStruct (const std::vector<Resource>&  originalFloats,
1044                                                            const vector<AllocationSp>&  outputAllocs,
1045                                                            const std::vector<Resource>& /* expectedOutputs */,
1046                                                            tcu::TestLog&                                log)
1047 {
1048         for (deUint32 outputNdx = 0; outputNdx < static_cast<deUint32>(outputAllocs.size()); ++outputNdx)
1049         {
1050                 vector<deUint8> originalBytes;
1051                 originalFloats[outputNdx].getBytes(originalBytes);
1052
1053                 const resultType*       returned        = static_cast<const resultType*>(outputAllocs[outputNdx]->getHostPtr());
1054                 const originType*       original        = reinterpret_cast<const originType*>(&originalBytes.front());
1055
1056                 if(!compareStruct<originType, resultType, funcOrigin, funcResult>(returned, original, log))
1057                         return false;
1058         }
1059         return true;
1060 }
1061
1062 string getStructShaderComponet (const ShaderTemplate component)
1063 {
1064         switch(component)
1065         {
1066         case SHADERTEMPLATE_TYPES:
1067                 return string(
1068                 "%f16       = OpTypeFloat 16\n"
1069                 "%v2f16     = OpTypeVector %f16 2\n"
1070                 "%v3f16     = OpTypeVector %f16 3\n"
1071                 "%v4f16     = OpTypeVector %f16 4\n"
1072                 "%f16ptr    = OpTypePointer Uniform %f16\n"
1073                 "%v2f16ptr  = OpTypePointer Uniform %v2f16\n"
1074                 "%v3f16ptr  = OpTypePointer Uniform %v3f16\n"
1075                 "%v4f16ptr  = OpTypePointer Uniform %v4f16\n"
1076                 "\n"
1077                 "%f32ptr   = OpTypePointer Uniform %f32\n"
1078                 "%v2f32ptr = OpTypePointer Uniform %v2f32\n"
1079                 "%v3f32ptr = OpTypePointer Uniform %v3f32\n"
1080                 "%v4f32ptr = OpTypePointer Uniform %v4f32\n");
1081         case SHADERTEMPLATE_STRIDE16BIT_STD140:
1082                 return string(
1083                 //struct {f16, v2f16[3]} [11]
1084                 "OpDecorate %v2f16arr3 ArrayStride 16\n"
1085                 "OpMemberDecorate %struct16 0 Offset 0\n"
1086                 "OpMemberDecorate %struct16 1 Offset 16\n"
1087                 "OpDecorate %struct16arr11 ArrayStride 64\n"
1088
1089                 "OpDecorate %f16arr3       ArrayStride 16\n"
1090                 "OpDecorate %v2f16arr11    ArrayStride 16\n"
1091                 "OpDecorate %v3f16arr11    ArrayStride 16\n"
1092                 "OpDecorate %v4f16arr3     ArrayStride 16\n"
1093                 "OpDecorate %f16StructArr7 ArrayStride 1200\n"
1094                 "\n"
1095                 "OpMemberDecorate %f16Struct 0 Offset 0\n"              //f16
1096                 "OpMemberDecorate %f16Struct 1 Offset 4\n"              //v2f16
1097                 "OpMemberDecorate %f16Struct 2 Offset 8\n"              //v3f16
1098                 "OpMemberDecorate %f16Struct 3 Offset 16\n"             //v4f16
1099                 "OpMemberDecorate %f16Struct 4 Offset 32\n"             //f16[3]
1100                 "OpMemberDecorate %f16Struct 5 Offset 80\n"             //struct {f16, v2f16[3]} [11]
1101                 "OpMemberDecorate %f16Struct 6 Offset 784\n"    //v2f16[11]
1102                 "OpMemberDecorate %f16Struct 7 Offset 960\n"    //f16
1103                 "OpMemberDecorate %f16Struct 8 Offset 976\n"    //v3f16[11]
1104                 "OpMemberDecorate %f16Struct 9 Offset 1152\n"); //v4f16[3]
1105
1106         case SHADERTEMPLATE_STRIDE16BIT_STD430:
1107                 return string(
1108                 //struct {f16, v2f16[3]} [11]
1109                 "OpDecorate %v2f16arr3 ArrayStride 4\n"
1110                 "OpMemberDecorate %struct16 0 Offset 0\n"
1111                 "OpMemberDecorate %struct16 1 Offset 4\n"
1112                 "OpDecorate %struct16arr11 ArrayStride 16\n"
1113
1114                 "OpDecorate %f16arr3    ArrayStride 2\n"
1115                 "OpDecorate %v2f16arr11 ArrayStride 4\n"
1116                 "OpDecorate %v3f16arr11 ArrayStride 8\n"
1117                 "OpDecorate %v4f16arr3  ArrayStride 8\n"
1118                 "OpDecorate %f16StructArr7 ArrayStride 368\n"
1119                 "\n"
1120                 "OpMemberDecorate %f16Struct 0 Offset 0\n"              //f16
1121                 "OpMemberDecorate %f16Struct 1 Offset 4\n"              //v2f16
1122                 "OpMemberDecorate %f16Struct 2 Offset 8\n"              //v3f16
1123                 "OpMemberDecorate %f16Struct 3 Offset 16\n"             //v4f16
1124                 "OpMemberDecorate %f16Struct 4 Offset 24\n"             //f16[3]
1125                 "OpMemberDecorate %f16Struct 5 Offset 32\n"             //struct {f16, v2f16[3]} [11]
1126                 "OpMemberDecorate %f16Struct 6 Offset 208\n"    //v2f16[11]
1127                 "OpMemberDecorate %f16Struct 7 Offset 252\n"    //f16
1128                 "OpMemberDecorate %f16Struct 8 Offset 256\n"    //v3f16[11]
1129                 "OpMemberDecorate %f16Struct 9 Offset 344\n");  //v4f16[3]
1130         case SHADERTEMPLATE_STRIDE32BIT_STD140:
1131                 return string (
1132                 //struct {f32, v2f32[3]} [11]
1133                 "OpDecorate %v2f32arr3 ArrayStride 16\n"
1134                 "OpMemberDecorate %struct32 0 Offset 0\n"
1135                 "OpMemberDecorate %struct32 1 Offset 16\n"
1136                 "OpDecorate %struct32arr11 ArrayStride 64\n"
1137
1138                 "OpDecorate %f32arr3   ArrayStride 16\n"
1139                 "OpDecorate %v2f32arr11 ArrayStride 16\n"
1140                 "OpDecorate %v3f32arr11 ArrayStride 16\n"
1141                 "OpDecorate %v4f32arr3 ArrayStride 16\n"
1142                 "OpDecorate %f32StructArr7 ArrayStride 1216\n"
1143                 "\n"
1144
1145                 "OpMemberDecorate %f32Struct 0 Offset 0\n"              //f32
1146                 "OpMemberDecorate %f32Struct 1 Offset 8\n"              //v2f32
1147                 "OpMemberDecorate %f32Struct 2 Offset 16\n"             //v3f32
1148                 "OpMemberDecorate %f32Struct 3 Offset 32\n"             //v4f32
1149                 "OpMemberDecorate %f32Struct 4 Offset 48\n"             //f32[3]
1150                 "OpMemberDecorate %f32Struct 5 Offset 96\n"             //struct {f32, v2f32[3]} [11]
1151                 "OpMemberDecorate %f32Struct 6 Offset 800\n"    //v2f32[11]
1152                 "OpMemberDecorate %f32Struct 7 Offset 976\n"    //f32
1153                 "OpMemberDecorate %f32Struct 8 Offset 992\n"    //v3f32[11]
1154                 "OpMemberDecorate %f32Struct 9 Offset 1168\n"); //v4f32[3]
1155
1156         case SHADERTEMPLATE_STRIDE32BIT_STD430:
1157                 return string(
1158                 //struct {f32, v2f32[3]} [11]
1159                 "OpDecorate %v2f32arr3 ArrayStride 8\n"
1160                 "OpMemberDecorate %struct32 0 Offset 0\n"
1161                 "OpMemberDecorate %struct32 1 Offset 8\n"
1162                 "OpDecorate %struct32arr11 ArrayStride 32\n"
1163
1164                 "OpDecorate %f32arr3    ArrayStride 4\n"
1165                 "OpDecorate %v2f32arr11 ArrayStride 8\n"
1166                 "OpDecorate %v3f32arr11 ArrayStride 16\n"
1167                 "OpDecorate %v4f32arr3  ArrayStride 16\n"
1168                 "OpDecorate %f32StructArr7 ArrayStride 736\n"
1169                 "\n"
1170
1171                 "OpMemberDecorate %f32Struct 0 Offset 0\n"              //f32
1172                 "OpMemberDecorate %f32Struct 1 Offset 8\n"              //v2f32
1173                 "OpMemberDecorate %f32Struct 2 Offset 16\n"             //v3f32
1174                 "OpMemberDecorate %f32Struct 3 Offset 32\n"             //v4f32
1175                 "OpMemberDecorate %f32Struct 4 Offset 48\n"             //f32[3]
1176                 "OpMemberDecorate %f32Struct 5 Offset 64\n"             //struct {f32, v2f32[3]}[11]
1177                 "OpMemberDecorate %f32Struct 6 Offset 416\n"    //v2f32[11]
1178                 "OpMemberDecorate %f32Struct 7 Offset 504\n"    //f32
1179                 "OpMemberDecorate %f32Struct 8 Offset 512\n"    //v3f32[11]
1180                 "OpMemberDecorate %f32Struct 9 Offset 688\n");  //v4f32[3]
1181         case SHADERTEMPLATE_STRIDEMIX_STD140:
1182                 return string(
1183                 "\n"//strutNestedIn {b16, b32, v2b16[11], b32[11]}
1184                 "OpDecorate %v2b16NestedArr11${InOut} ArrayStride 16\n" //v2b16[11]
1185                 "OpDecorate %b32NestedArr11${InOut} ArrayStride 16\n"   //b32[11]
1186                 "OpMemberDecorate %sNested${InOut} 0 Offset 0\n"                //b16
1187                 "OpMemberDecorate %sNested${InOut} 1 Offset 4\n"                //b32
1188                 "OpMemberDecorate %sNested${InOut} 2 Offset 16\n"               //v2b16[11]
1189                 "OpMemberDecorate %sNested${InOut} 3 Offset 192\n"              //b32[11]
1190                 "OpDecorate %sNestedArr11${InOut} ArrayStride 368\n"    //strutNestedIn[11]
1191                 "\n"//strutIn {b16, b32, v2b16, v2b32, v3b16, v3b32, v4b16, v4b32, strutNestedIn[11], b16In[11], b32bIn[11]}
1192                 "OpDecorate %sb16Arr11${InOut} ArrayStride 16\n"                //b16In[11]
1193                 "OpDecorate %sb32Arr11${InOut} ArrayStride 16\n"                //b32bIn[11]
1194                 "OpMemberDecorate %struct${InOut} 0 Offset 0\n"                 //b16
1195                 "OpMemberDecorate %struct${InOut} 1 Offset 4\n"                 //b32
1196                 "OpMemberDecorate %struct${InOut} 2 Offset 8\n"                 //v2b16
1197                 "OpMemberDecorate %struct${InOut} 3 Offset 16\n"                //v2b32
1198                 "OpMemberDecorate %struct${InOut} 4 Offset 24\n"                //v3b16
1199                 "OpMemberDecorate %struct${InOut} 5 Offset 32\n"                //v3b32
1200                 "OpMemberDecorate %struct${InOut} 6 Offset 48\n"                //v4b16
1201                 "OpMemberDecorate %struct${InOut} 7 Offset 64\n"                //v4b32
1202                 "OpMemberDecorate %struct${InOut} 8 Offset 80\n"                //strutNestedIn[11]
1203                 "OpMemberDecorate %struct${InOut} 9 Offset 4128\n"              //b16In[11]
1204                 "OpMemberDecorate %struct${InOut} 10 Offset 4304\n"             //b32bIn[11]
1205                 "OpDecorate %structArr7${InOut} ArrayStride 4480\n");   //strutIn[7]
1206         case SHADERTEMPLATE_STRIDEMIX_STD430:
1207                 return string(
1208                 "\n"//strutNestedOut {b16, b32, v2b16[11], b32[11]}
1209                 "OpDecorate %v2b16NestedArr11${InOut} ArrayStride 4\n"  //v2b16[11]
1210                 "OpDecorate %b32NestedArr11${InOut}  ArrayStride 4\n"   //b32[11]
1211                 "OpMemberDecorate %sNested${InOut} 0 Offset 0\n"                //b16
1212                 "OpMemberDecorate %sNested${InOut} 1 Offset 4\n"                //b32
1213                 "OpMemberDecorate %sNested${InOut} 2 Offset 8\n"                //v2b16[11]
1214                 "OpMemberDecorate %sNested${InOut} 3 Offset 52\n"               //b32[11]
1215                 "OpDecorate %sNestedArr11${InOut} ArrayStride 96\n"             //strutNestedOut[11]
1216                 "\n"//strutOut {b16, b32, v2b16, v2b32, v3b16, v3b32, v4b16, v4b32, strutNestedOut[11], b16Out[11], b32bOut[11]}
1217                 "OpDecorate %sb16Arr11${InOut} ArrayStride 2\n"                 //b16Out[11]
1218                 "OpDecorate %sb32Arr11${InOut} ArrayStride 4\n"                 //b32bOut[11]
1219                 "OpMemberDecorate %struct${InOut} 0 Offset 0\n"                 //b16
1220                 "OpMemberDecorate %struct${InOut} 1 Offset 4\n"                 //b32
1221                 "OpMemberDecorate %struct${InOut} 2 Offset 8\n"                 //v2b16
1222                 "OpMemberDecorate %struct${InOut} 3 Offset 16\n"                //v2b32
1223                 "OpMemberDecorate %struct${InOut} 4 Offset 24\n"                //v3b16
1224                 "OpMemberDecorate %struct${InOut} 5 Offset 32\n"                //v3b32
1225                 "OpMemberDecorate %struct${InOut} 6 Offset 48\n"                //v4b16
1226                 "OpMemberDecorate %struct${InOut} 7 Offset 64\n"                //v4b32
1227                 "OpMemberDecorate %struct${InOut} 8 Offset 80\n"                //strutNestedOut[11]
1228                 "OpMemberDecorate %struct${InOut} 9 Offset 1136\n"              //b16Out[11]
1229                 "OpMemberDecorate %struct${InOut} 10 Offset 1160\n"             //b32bOut[11]
1230                 "OpDecorate %structArr7${InOut} ArrayStride 1216\n");   //strutOut[7]
1231
1232         default:
1233                 return string("");
1234         }
1235 }
1236
1237 /*Return string contains spirv loop begin.
1238  the spec should contains "exeCount" - with name of const i32, it is number of executions
1239  the spec should contains "loopName" - suffix for all local names
1240  %Val${loopName} - index which can be used inside loop
1241  "%ndxArr${loopName}   = OpVariable %fp_i32  Function\n" - has to be defined outside
1242  The function should be always use with endLoop function*/
1243 std::string beginLoop(const std::map<std::string, std::string>& spec)
1244 {
1245         const tcu::StringTemplate       loopBegin       (
1246         "OpStore %ndxArr${loopName} %zero\n"
1247         "OpBranch %Loop${loopName}\n"
1248         "%Loop${loopName} = OpLabel\n"
1249         "OpLoopMerge %MergeLabel1${loopName} %MergeLabel2${loopName} None\n"
1250         "OpBranch %Label1${loopName}\n"
1251         "%Label1${loopName} = OpLabel\n"
1252         "%Val${loopName} = OpLoad %i32 %ndxArr${loopName}\n"
1253         "%LessThan${loopName} = OpSLessThan %bool %Val${loopName} %${exeCount}\n"
1254         "OpBranchConditional %LessThan${loopName} %ifLabel${loopName} %MergeLabel1${loopName}\n"
1255         "%ifLabel${loopName} = OpLabel\n");
1256         return loopBegin.specialize(spec);
1257 }
1258 /*Return string contains spirv loop end.
1259  the spec should contains "loopName" - suffix for all local names, suffix should be the same in beginLoop
1260 The function should be always use with beginLoop function*/
1261 std::string endLoop(const std::map<std::string, std::string>& spec)
1262 {
1263         const tcu::StringTemplate       loopEnd (
1264         "OpBranch %MergeLabel2${loopName}\n"
1265         "%MergeLabel2${loopName} = OpLabel\n"
1266         "%plusOne${loopName} = OpIAdd %i32 %Val${loopName} %c_i32_1\n"
1267         "OpStore %ndxArr${loopName} %plusOne${loopName}\n"
1268         "OpBranch %Loop${loopName}\n"
1269         "%MergeLabel1${loopName} = OpLabel\n");
1270         return loopEnd.specialize(spec);
1271 }
1272
1273 void addCompute16bitStorageUniform16To32Group (tcu::TestCaseGroup* group)
1274 {
1275         tcu::TestContext&                               testCtx                 = group->getTestContext();
1276         de::Random                                              rnd                             (deStringHash(group->getName()));
1277         const int                                               numElements             = 128;
1278
1279         const StringTemplate                    shaderTemplate  (
1280                 "OpCapability Shader\n"
1281                 "OpCapability ${capability}\n"
1282                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
1283                 "OpMemoryModel Logical GLSL450\n"
1284                 "OpEntryPoint GLCompute %main \"main\" %id\n"
1285                 "OpExecutionMode %main LocalSize 1 1 1\n"
1286                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1287
1288                 "${stride}"
1289
1290                 "OpMemberDecorate %SSBO32 0 Offset 0\n"
1291                 "OpMemberDecorate %SSBO16 0 Offset 0\n"
1292                 "OpDecorate %SSBO32 BufferBlock\n"
1293                 "OpDecorate %SSBO16 ${storage}\n"
1294                 "OpDecorate %ssbo32 DescriptorSet 0\n"
1295                 "OpDecorate %ssbo16 DescriptorSet 0\n"
1296                 "OpDecorate %ssbo32 Binding 1\n"
1297                 "OpDecorate %ssbo16 Binding 0\n"
1298
1299                 "${matrix_decor:opt}\n"
1300
1301                 "%bool      = OpTypeBool\n"
1302                 "%void      = OpTypeVoid\n"
1303                 "%voidf     = OpTypeFunction %void\n"
1304                 "%u32       = OpTypeInt 32 0\n"
1305                 "%i32       = OpTypeInt 32 1\n"
1306                 "%f32       = OpTypeFloat 32\n"
1307                 "%v3u32     = OpTypeVector %u32 3\n"
1308                 "%uvec3ptr  = OpTypePointer Input %v3u32\n"
1309                 "%i32ptr    = OpTypePointer Uniform %i32\n"
1310                 "%f32ptr    = OpTypePointer Uniform %f32\n"
1311
1312                 "%zero      = OpConstant %i32 0\n"
1313                 "%c_i32_1   = OpConstant %i32 1\n"
1314                 "%c_i32_2   = OpConstant %i32 2\n"
1315                 "%c_i32_3   = OpConstant %i32 3\n"
1316                 "%c_i32_16  = OpConstant %i32 16\n"
1317                 "%c_i32_32  = OpConstant %i32 32\n"
1318                 "%c_i32_64  = OpConstant %i32 64\n"
1319                 "%c_i32_128 = OpConstant %i32 128\n"
1320                 "%c_i32_ci  = OpConstant %i32 ${constarrayidx}\n"
1321
1322                 "%i32arr    = OpTypeArray %i32 %c_i32_128\n"
1323                 "%f32arr    = OpTypeArray %f32 %c_i32_128\n"
1324
1325                 "${types}\n"
1326                 "${matrix_types:opt}\n"
1327
1328                 "%SSBO32    = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
1329                 "%SSBO16    = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
1330                 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
1331                 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
1332                 "%ssbo32    = OpVariable %up_SSBO32 Uniform\n"
1333                 "%ssbo16    = OpVariable %up_SSBO16 Uniform\n"
1334
1335                 "%id        = OpVariable %uvec3ptr Input\n"
1336
1337                 "%main      = OpFunction %void None %voidf\n"
1338                 "%label     = OpLabel\n"
1339                 "%idval     = OpLoad %v3u32 %id\n"
1340                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1341                 "%inloc     = OpAccessChain %${base16}ptr %ssbo16 %zero %${arrayindex} ${index0:opt}\n"
1342                 "%val16     = OpLoad %${base16} %inloc\n"
1343                 "%val32     = ${convert} %${base32} %val16\n"
1344                 "%outloc    = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
1345                 "             OpStore %outloc %val32\n"
1346                 "${matrix_store:opt}\n"
1347                 "             OpReturn\n"
1348                 "             OpFunctionEnd\n");
1349
1350         {  // floats
1351                 const char                                                                              floatTypes[]    =
1352                         "%f16       = OpTypeFloat 16\n"
1353                         "%f16ptr    = OpTypePointer Uniform %f16\n"
1354                         "%f16arr    = OpTypeArray %f16 %c_i32_128\n"
1355                         "%v2f16     = OpTypeVector %f16 2\n"
1356                         "%v2f32     = OpTypeVector %f32 2\n"
1357                         "%v2f16ptr  = OpTypePointer Uniform %v2f16\n"
1358                         "%v2f32ptr  = OpTypePointer Uniform %v2f32\n"
1359                         "%v2f16arr  = OpTypeArray %v2f16 %c_i32_64\n"
1360                         "%v2f32arr  = OpTypeArray %v2f32 %c_i32_64\n";
1361
1362                 struct CompositeType
1363                 {
1364                         const char*     name;
1365                         const char*     base32;
1366                         const char*     base16;
1367                         const char*     stride;
1368                         bool            useConstantIndex;
1369                         unsigned        constantIndex;
1370                         unsigned        count;
1371                         unsigned        inputStride;
1372                 };
1373
1374                 const CompositeType     cTypes[2][5]            =
1375                 {
1376                         {
1377                                 {"scalar",                              "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                                 false,  0,      numElements,            1},
1378                                 {"scalar_const_idx_5",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                                 true,   5,      numElements,            1},
1379                                 {"scalar_const_idx_8",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                                 true,   8,      numElements,            1},
1380                                 {"vector",                              "v2f32",        "v2f16",        "OpDecorate %v2f32arr ArrayStride 8\nOpDecorate %v2f16arr ArrayStride 4\n",                             false,  0,      numElements / 2,        2},
1381                                 {"matrix",                              "v2f32",        "v2f16",        "OpDecorate %m4v2f32arr ArrayStride 32\nOpDecorate %m4v2f16arr ArrayStride 16\n",               false,  0,      numElements / 8,        8}
1382                         },
1383                         {
1384                                 {"scalar",                              "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n",                                false,  0,      numElements,            8},
1385                                 {"scalar_const_idx_5",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n",                                true,   5,      numElements,            8},
1386                                 {"scalar_const_idx_8",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n",                                true,   8,      numElements,            8},
1387                                 {"vector",                              "v2f32",        "v2f16",        "OpDecorate %v2f32arr ArrayStride 8\nOpDecorate %v2f16arr ArrayStride 16\n",                    false,  0,      numElements / 2,        8},
1388                                 {"matrix",                              "v2f32",        "v2f16",        "OpDecorate %m4v2f32arr ArrayStride 32\nOpDecorate %m4v2f16arr ArrayStride 16\n",               false,  0,      numElements / 8,        8}
1389                         }
1390                 };
1391
1392                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1393                         for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
1394                         {
1395                                 ComputeShaderSpec               spec;
1396                                 map<string, string>             specs;
1397                                 string                                  testName                = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name + "_float";
1398
1399                                 specs["capability"]             = CAPABILITIES[capIdx].cap;
1400                                 specs["storage"]                = CAPABILITIES[capIdx].decor;
1401                                 specs["stride"]                 = cTypes[capIdx][tyIdx].stride;
1402                                 specs["base32"]                 = cTypes[capIdx][tyIdx].base32;
1403                                 specs["base16"]                 = cTypes[capIdx][tyIdx].base16;
1404                                 specs["types"]                  = floatTypes;
1405                                 specs["convert"]                = "OpFConvert";
1406                                 specs["constarrayidx"]  = de::toString(cTypes[capIdx][tyIdx].constantIndex);
1407                                 if (cTypes[capIdx][tyIdx].useConstantIndex)
1408                                         specs["arrayindex"] = "c_i32_ci";
1409                                 else
1410                                         specs["arrayindex"] = "x";
1411
1412                                 const deUint32                  inputStride             = cTypes[capIdx][tyIdx].inputStride;
1413                                 const deUint32                  count                   = cTypes[capIdx][tyIdx].count;
1414                                 const deUint32                  scalarsPerItem  = numElements / count;
1415                                 vector<deFloat16>               float16Data             = getFloat16s(rnd, numElements * inputStride);
1416                                 vector<float>                   float32Data;
1417
1418                                 float32Data.reserve(numElements);
1419                                 for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
1420                                         for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; scalarIdx++)
1421                                                 float32Data.push_back(deFloat16To32(float16Data[numIdx * inputStride + scalarIdx]));
1422
1423                                 vector<float>                   float32DataConstIdx;
1424                                 if (cTypes[capIdx][tyIdx].useConstantIndex)
1425                                 {
1426                                         const deUint32 numFloats = numElements / cTypes[capIdx][tyIdx].count;
1427                                         for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1428                                                 float32DataConstIdx.push_back(float32Data[cTypes[capIdx][tyIdx].constantIndex * numFloats + numIdx % numFloats]);
1429                                 }
1430
1431                                 if (strcmp(cTypes[capIdx][tyIdx].name, "matrix") == 0)
1432                                 {
1433                                         specs["index0"]                 = "%zero";
1434                                         specs["matrix_prefix"]  = "m4";
1435                                         specs["matrix_types"]   =
1436                                                 "%m4v2f16 = OpTypeMatrix %v2f16 4\n"
1437                                                 "%m4v2f32 = OpTypeMatrix %v2f32 4\n"
1438                                                 "%m4v2f16arr = OpTypeArray %m4v2f16 %c_i32_16\n"
1439                                                 "%m4v2f32arr = OpTypeArray %m4v2f32 %c_i32_16\n";
1440                                         specs["matrix_decor"]   =
1441                                                 "OpMemberDecorate %SSBO32 0 ColMajor\n"
1442                                                 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n"
1443                                                 "OpMemberDecorate %SSBO16 0 ColMajor\n"
1444                                                 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n";
1445                                         specs["matrix_store"]   =
1446                                                 "%inloc_1  = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_1\n"
1447                                                 "%val16_1  = OpLoad %v2f16 %inloc_1\n"
1448                                                 "%val32_1  = OpFConvert %v2f32 %val16_1\n"
1449                                                 "%outloc_1 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_1\n"
1450                                                 "            OpStore %outloc_1 %val32_1\n"
1451
1452                                                 "%inloc_2  = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_2\n"
1453                                                 "%val16_2  = OpLoad %v2f16 %inloc_2\n"
1454                                                 "%val32_2  = OpFConvert %v2f32 %val16_2\n"
1455                                                 "%outloc_2 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_2\n"
1456                                                 "            OpStore %outloc_2 %val32_2\n"
1457
1458                                                 "%inloc_3  = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_3\n"
1459                                                 "%val16_3  = OpLoad %v2f16 %inloc_3\n"
1460                                                 "%val32_3  = OpFConvert %v2f32 %val16_3\n"
1461                                                 "%outloc_3 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_3\n"
1462                                                 "            OpStore %outloc_3 %val32_3\n";
1463                                 }
1464
1465                                 spec.assembly                   = shaderTemplate.specialize(specs);
1466                                 spec.numWorkGroups              = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
1467                                 spec.verifyIO                   = check32BitFloats;
1468
1469                                 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), CAPABILITIES[capIdx].dtype));
1470                                 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(cTypes[capIdx][tyIdx].useConstantIndex ? float32DataConstIdx : float32Data))));
1471                                 spec.extensions.push_back("VK_KHR_16bit_storage");
1472                                 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1473
1474                                 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1475                         }
1476         }
1477
1478         {  // Integers
1479                 const char              sintTypes[]             =
1480                         "%i16       = OpTypeInt 16 1\n"
1481                         "%i16ptr    = OpTypePointer Uniform %i16\n"
1482                         "%i16arr    = OpTypeArray %i16 %c_i32_128\n"
1483                         "%v4i16     = OpTypeVector %i16 4\n"
1484                         "%v4i32     = OpTypeVector %i32 4\n"
1485                         "%v4i16ptr  = OpTypePointer Uniform %v4i16\n"
1486                         "%v4i32ptr  = OpTypePointer Uniform %v4i32\n"
1487                         "%v4i16arr  = OpTypeArray %v4i16 %c_i32_32\n"
1488                         "%v4i32arr  = OpTypeArray %v4i32 %c_i32_32\n";
1489
1490                 const char              uintTypes[]             =
1491                         "%u16       = OpTypeInt 16 0\n"
1492                         "%u16ptr    = OpTypePointer Uniform %u16\n"
1493                         "%u32ptr    = OpTypePointer Uniform %u32\n"
1494                         "%u16arr    = OpTypeArray %u16 %c_i32_128\n"
1495                         "%u32arr    = OpTypeArray %u32 %c_i32_128\n"
1496                         "%v4u16     = OpTypeVector %u16 4\n"
1497                         "%v4u32     = OpTypeVector %u32 4\n"
1498                         "%v4u16ptr  = OpTypePointer Uniform %v4u16\n"
1499                         "%v4u32ptr  = OpTypePointer Uniform %v4u32\n"
1500                         "%v4u16arr  = OpTypeArray %v4u16 %c_i32_32\n"
1501                         "%v4u32arr  = OpTypeArray %v4u32 %c_i32_32\n";
1502
1503                 struct CompositeType
1504                 {
1505                         const char*     name;
1506                         bool            isSigned;
1507                         const char* types;
1508                         const char*     base32;
1509                         const char*     base16;
1510                         const char* opcode;
1511                         const char*     stride;
1512                         bool            useConstantIndex;
1513                         unsigned        constantIndex;
1514                         unsigned        count;
1515                         unsigned        inputStride;
1516                 };
1517
1518                 const CompositeType     cTypes[2][8]    =
1519                 {
1520                         {
1521                                 {"scalar_sint",                         true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 false,  0,      numElements,            1},
1522                                 {"scalar_sint_const_idx_5",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 true,   5,      numElements,            1},
1523                                 {"scalar_sint_const_idx_8",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 true,   8,      numElements,            1},
1524                                 {"scalar_uint",                         false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 false,  0,      numElements,            1},
1525                                 {"scalar_uint_const_idx_5",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 true,   5,      numElements,            1},
1526                                 {"scalar_uint_const_idx_8",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 true,   8,      numElements,            1},
1527                                 {"vector_sint",                         true,   sintTypes,      "v4i32",        "v4i16",        "OpSConvert",   "OpDecorate %v4i32arr ArrayStride 16\nOpDecorate %v4i16arr ArrayStride 8\n",    false,  0,      numElements / 4,        4},
1528                                 {"vector_uint",                         false,  uintTypes,      "v4u32",        "v4u16",        "OpUConvert",   "OpDecorate %v4u32arr ArrayStride 16\nOpDecorate %v4u16arr ArrayStride 8\n",    false,  0,      numElements / 4,        4}
1529                         },
1530                         {
1531                                 {"scalar_sint",                         true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n",                false,  0,      numElements,            8},
1532                                 {"scalar_sint_const_idx_5",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n",                true,   5,      numElements,            8},
1533                                 {"scalar_sint_const_idx_8",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n",                true,   8,      numElements,            8},
1534                                 {"scalar_uint",                         false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n",                false,  0,      numElements,            8},
1535                                 {"scalar_uint_const_idx_5",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n",                true,   5,      numElements,            8},
1536                                 {"scalar_uint_const_idx_8",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n",                true,   8,      numElements,            8},
1537                                 {"vector_sint",                         true,   sintTypes,      "v4i32",        "v4i16",        "OpSConvert",   "OpDecorate %v4i32arr ArrayStride 16\nOpDecorate %v4i16arr ArrayStride 16\n",   false,  0,      numElements / 4,        8},
1538                                 {"vector_uint",                         false,  uintTypes,      "v4u32",        "v4u16",        "OpUConvert",   "OpDecorate %v4u32arr ArrayStride 16\nOpDecorate %v4u16arr ArrayStride 16\n",   false,  0,      numElements / 4,        8}
1539                         }
1540                 };
1541
1542                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1543                         for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
1544                         {
1545                                 ComputeShaderSpec       spec;
1546                                 map<string, string>     specs;
1547                                 string                          testName                = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name;
1548                                 const deUint32          inputStride             = cTypes[capIdx][tyIdx].inputStride;
1549                                 vector<deInt16>         inputs                  = getInt16s(rnd, numElements * inputStride);
1550                                 vector<deInt32>         sOutputs;
1551                                 vector<deInt32>         uOutputs;
1552                                 const deUint16          signBitMask             = 0x8000;
1553                                 const deUint32          signExtendMask  = 0xffff0000;
1554                                 const deUint32          count                   = cTypes[capIdx][tyIdx].count;
1555                                 const deUint32          scalarsPerItem  = numElements / count;
1556
1557                                 sOutputs.reserve(numElements);
1558                                 uOutputs.reserve(numElements);
1559
1560                                 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
1561                                         for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; ++scalarIdx)
1562                                         {
1563                                                 const deInt16 input = inputs[numNdx * inputStride + scalarIdx];
1564
1565                                                 uOutputs.push_back(static_cast<deUint16>(input));
1566                                                 if (input & signBitMask)
1567                                                         sOutputs.push_back(static_cast<deInt32>(input | signExtendMask));
1568                                                 else
1569                                                         sOutputs.push_back(static_cast<deInt32>(input));
1570                                         }
1571
1572                                 vector<deInt32>         intDataConstIdx;
1573
1574                                 if (cTypes[capIdx][tyIdx].useConstantIndex)
1575                                 {
1576                                         for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1577                                         {
1578                                                 const deInt32 idx = cTypes[capIdx][tyIdx].constantIndex * scalarsPerItem + numIdx % scalarsPerItem;
1579
1580                                                 if (cTypes[capIdx][tyIdx].isSigned)
1581                                                         intDataConstIdx.push_back(sOutputs[idx]);
1582                                                 else
1583                                                         intDataConstIdx.push_back(uOutputs[idx]);
1584                                         }
1585                                 }
1586
1587                                 specs["capability"]             = CAPABILITIES[capIdx].cap;
1588                                 specs["storage"]                = CAPABILITIES[capIdx].decor;
1589                                 specs["stride"]                 = cTypes[capIdx][tyIdx].stride;
1590                                 specs["base32"]                 = cTypes[capIdx][tyIdx].base32;
1591                                 specs["base16"]                 = cTypes[capIdx][tyIdx].base16;
1592                                 specs["types"]                  = cTypes[capIdx][tyIdx].types;
1593                                 specs["convert"]                = cTypes[capIdx][tyIdx].opcode;
1594                                 specs["constarrayidx"]  = de::toString(cTypes[capIdx][tyIdx].constantIndex);
1595                                 if (cTypes[capIdx][tyIdx].useConstantIndex)
1596                                         specs["arrayindex"] = "c_i32_ci";
1597                                 else
1598                                         specs["arrayindex"] = "x";
1599
1600                                 spec.assembly                   = shaderTemplate.specialize(specs);
1601                                 spec.numWorkGroups              = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
1602
1603                                 spec.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputs)), CAPABILITIES[capIdx].dtype));
1604                                 if (cTypes[capIdx][tyIdx].useConstantIndex)
1605                                         spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(intDataConstIdx))));
1606                                 else if (cTypes[capIdx][tyIdx].isSigned)
1607                                         spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs))));
1608                                 else
1609                                         spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs))));
1610                                 spec.extensions.push_back("VK_KHR_16bit_storage");
1611                                 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1612
1613                                 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1614                         }
1615         }
1616 }
1617
1618 void addCompute16bitStorageUniform16To32ChainAccessGroup (tcu::TestCaseGroup* group)
1619 {
1620         tcu::TestContext&                               testCtx                 = group->getTestContext();
1621         de::Random                                              rnd                             (deStringHash(group->getName()));
1622         const deUint32                                  structSize              = 128; // In number of 16bit items. Includes padding.
1623         vector<deFloat16>                               inputDataFloat  = getFloat16s(rnd, structSize * 4);
1624         vector<deInt16>                                 inputDataInt    = getInt16s(rnd, structSize * 4);
1625         vector<float>                                   outputDataFloat;
1626         vector<deInt32>                                 outputDataSInt;
1627         vector<deInt32>                                 outputDataUInt;
1628         vector<tcu::UVec4>                              indices;
1629
1630         // Input is an array of a struct that varies on 16bit data type being tested:
1631         //
1632         // Float:
1633         //
1634         // float16 scalars[3]
1635         // mat4x3  matrix
1636         // vec3    vector
1637         //
1638         // Int:
1639         //
1640         // int16 scalars[3]
1641         // int16 array2D[4][3]
1642         // ivec3 vector
1643         //
1644         // UInt:
1645         //
1646         // uint16 scalars[3]
1647         // uint16 array2D[4][3]
1648         // uvec3  vector
1649
1650         const StringTemplate                    shaderTemplate  (
1651                 "                              OpCapability Shader\n"
1652                 "                              OpCapability ${capability}\n"
1653                 "                              OpExtension \"SPV_KHR_16bit_storage\"\n"
1654                 "                         %1 = OpExtInstImport \"GLSL.std.450\"\n"
1655                 "                              OpMemoryModel Logical GLSL450\n"
1656                 "                              OpEntryPoint GLCompute %main \"main\"\n"
1657                 "                              OpExecutionMode %main LocalSize 1 1 1\n"
1658                 "                              OpSource GLSL 430\n"
1659                 "                              OpDecorate %Output BufferBlock\n"
1660                 "                              OpDecorate %dataOutput DescriptorSet 0\n"
1661                 "                              OpDecorate %dataOutput Binding 1\n"
1662                 "                              OpDecorate %scalarArray ArrayStride 16\n"
1663                 "                              OpDecorate %scalarArray2D ArrayStride 48\n"
1664                 "                              OpMemberDecorate %S 0 Offset 0\n"
1665                 "                              OpMemberDecorate %S 1 Offset 48\n"
1666                 "                              ${decoration:opt}\n"
1667                 "                              OpMemberDecorate %S 2 Offset 240\n"
1668                 "                              OpDecorate %_arr_S_uint_4 ArrayStride 256\n"
1669                 "                              OpMemberDecorate %Input 0 Offset 0\n"
1670                 "                              OpMemberDecorate %Output 0 Offset 0\n"
1671                 "                              OpDecorate %Input ${storage}\n"
1672                 "                              OpDecorate %dataInput DescriptorSet 0\n"
1673                 "                              OpDecorate %dataInput Binding 0\n"
1674                 "                       %f16 = OpTypeFloat 16\n"
1675                 "                       %f32 = OpTypeFloat 32\n"
1676                 "                       %i16 = OpTypeInt 16 1\n"
1677                 "                       %i32 = OpTypeInt 32 1\n"
1678                 "                       %u16 = OpTypeInt 16 0\n"
1679                 "                       %u32 = OpTypeInt 32 0\n"
1680                 "                      %void = OpTypeVoid\n"
1681                 "                  %voidFunc = OpTypeFunction %void\n"
1682                 "        %_ptr_Function_uint = OpTypePointer Function %u32\n"
1683                 "                     %v3u32 = OpTypeVector %u32 3\n"
1684                 "          %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
1685                 "                     %int_0 = OpConstant %i32 0\n"
1686                 "                    %uint_3 = OpConstant %u32 3\n"
1687                 "                    %uint_4 = OpConstant %u32 4\n"
1688                 "                        %s0 = OpConstant %u32 ${s0}\n"
1689                 "                        %s1 = OpConstant %u32 ${s1}\n"
1690                 "                        %s2 = OpConstant %u32 ${s2}\n"
1691                 "                        %s3 = OpConstant %u32 ${s3}\n"
1692                 "                    %Output = OpTypeStruct %${type}32\n"
1693                 "       %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
1694                 "                %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
1695                 "               %scalarArray = OpTypeArray %${type}16 %uint_3\n"
1696                 "                     %v3f16 = OpTypeVector %f16 3\n"
1697                 "                     %v3i16 = OpTypeVector %i16 3\n"
1698                 "                     %v3u16 = OpTypeVector %u16 3\n"
1699                 "                    %matrix = OpTypeMatrix %v3f16 4\n"
1700                 "             %scalarArray2D = OpTypeArray %scalarArray %uint_4\n"
1701                 "                         %S = OpTypeStruct %scalarArray %${type2D} %v3${type}16\n"
1702                 "             %_arr_S_uint_4 = OpTypeArray %S %uint_4\n"
1703                 "                     %Input = OpTypeStruct %_arr_S_uint_4\n"
1704                 "        %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
1705                 "                 %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
1706                 "   %_ptr_Uniform_16bit_data = OpTypePointer Uniform %${type}16\n"
1707                 "   %_ptr_Uniform_32bit_data = OpTypePointer Uniform %${type}32\n"
1708                 "                      %main = OpFunction %void None %voidFunc\n"
1709                 "                     %entry = OpLabel\n"
1710                 "                   %dataPtr = ${accessChain}\n"
1711                 "                      %data = OpLoad %${type}16 %dataPtr\n"
1712                 "                 %converted = ${convert}\n"
1713                 "                    %outPtr = OpAccessChain %_ptr_Uniform_32bit_data %dataOutput %int_0\n"
1714                 "                              OpStore %outPtr %converted\n"
1715                 "                              OpReturn\n"
1716                 "                              OpFunctionEnd\n");
1717
1718         // Generate constant indices for OpChainAccess. We need to use constant values
1719         // when indexing into structures. This loop generates all permutations.
1720         for (deUint32 idx0 = 0; idx0 < 4; ++idx0)
1721                 for (deUint32 idx1 = 0; idx1 < 3; ++idx1)
1722                         for (deUint32 idx2 = 0; idx2 < (idx1 == 1u ? 4u : 3u); ++idx2)
1723                                 for (deUint32 idx3 = 0; idx3 < (idx1 == 1u ? 3u : 1u); ++idx3)
1724                                         indices.push_back(tcu::UVec4(idx0, idx1, idx2, idx3));
1725
1726
1727         for (deUint32 numIdx = 0; numIdx < (deUint32)indices.size(); ++numIdx)
1728         {
1729                 const deUint16          signBitMask                     = 0x8000;
1730                 const deUint32          signExtendMask          = 0xffff0000;
1731                 // Determine the selected output float for the selected indices.
1732                 const tcu::UVec4        vec                                     = indices[numIdx];
1733                 // Offsets are in multiples of 16bits. Floats are using matrix as the
1734                 // second field, which has different layout rules than 2D array.
1735                 // Therefore separate offset tables are needed.
1736                 const deUint32          fieldOffsetsFloat[3][3] =
1737                 {
1738                         {0u,    8u,             0u},
1739                         {24,    24u,    1u},
1740                         {120u,  1u,             0u}
1741                 };
1742                 const deUint32          fieldOffsetsInt[3][3]   =
1743                 {
1744                         {0u,    8u,             0u},
1745                         {24,    24u,    8u},
1746                         {120u,  1u,             0u}
1747                 };
1748                 const deUint32          offsetFloat                             = vec.x() * structSize + fieldOffsetsFloat[vec.y()][0] + fieldOffsetsFloat[vec.y()][1] * vec.z() + fieldOffsetsFloat[vec.y()][2] * vec.w();
1749                 const deUint32          offsetInt                               = vec.x() * structSize + fieldOffsetsInt[vec.y()][0] + fieldOffsetsInt[vec.y()][1] * vec.z() + fieldOffsetsInt[vec.y()][2] * vec.w();
1750                 const bool                      hasSign                                 = inputDataInt[offsetInt] & signBitMask;
1751
1752                 outputDataFloat.push_back(deFloat16To32(inputDataFloat[offsetFloat]));
1753                 outputDataUInt.push_back((deUint16)inputDataInt[offsetInt]);
1754                 outputDataSInt.push_back((deInt32)(inputDataInt[offsetInt] | (hasSign ? signExtendMask : 0u)));
1755         }
1756
1757         for (deUint32 indicesIdx = 0; indicesIdx < (deUint32)indices.size(); ++indicesIdx)
1758                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1759                 {
1760                         string                                          indexString             = de::toString(indices[indicesIdx].x()) + "_" + de::toString(indices[indicesIdx].y()) + "_" + de::toString(indices[indicesIdx].z());
1761                         if (indices[indicesIdx].y() == 1)
1762                                 indexString += string("_") + de::toString(indices[indicesIdx].w());
1763
1764                         const string                            testNameBase    = string(CAPABILITIES[capIdx].name) + "_" + indexString + "_";
1765                         const ComputeTestFeatures       features                = COMPUTE_TEST_USES_NONE;
1766
1767                         struct DataType
1768                         {
1769                                 string          name;
1770                                 string          type;
1771                                 string          convert;
1772                                 string          type2D; // Matrix when using floats. 2D array otherwise.
1773                                 BufferSp        inputs;
1774                                 BufferSp        outputs;
1775                         };
1776
1777                         const DataType                          dataTypes[]             =
1778                         {
1779                                 { "float",      "f", "OpFConvert %f32 %data",   "matrix",                       BufferSp(new Float16Buffer(inputDataFloat)),    BufferSp(new Float32Buffer(vector<float>(1, outputDataFloat[indicesIdx])))      },
1780                                 { "int",        "i", "OpSConvert %i32 %data",   "scalarArray2D",        BufferSp(new Int16Buffer(inputDataInt)),                BufferSp(new Int32Buffer(vector<deInt32>(1, outputDataSInt[indicesIdx])))       },
1781                                 { "uint",       "u", "OpUConvert %u32 %data",   "scalarArray2D",        BufferSp(new Int16Buffer(inputDataInt)),                BufferSp(new Int32Buffer(vector<deInt32>(1, outputDataUInt[indicesIdx])))       }
1782                         };
1783
1784                         for (deUint32 dataTypeIdx = 0; dataTypeIdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeIdx)
1785                         {
1786                                 const string                            testName        = testNameBase + dataTypes[dataTypeIdx].name;
1787                                 map<string, string>                     specs;
1788                                 ComputeShaderSpec                       spec;
1789
1790                                 specs["capability"]                                             = CAPABILITIES[capIdx].cap;
1791                                 specs["storage"]                                                = CAPABILITIES[capIdx].decor;
1792                                 specs["s0"]                                                             = de::toString(indices[indicesIdx].x());
1793                                 specs["s1"]                                                             = de::toString(indices[indicesIdx].y());
1794                                 specs["s2"]                                                             = de::toString(indices[indicesIdx].z());
1795                                 specs["s3"]                                                             = de::toString(indices[indicesIdx].w());
1796                                 specs["type"]                                                   = dataTypes[dataTypeIdx].type;
1797                                 specs["convert"]                                                = dataTypes[dataTypeIdx].convert;
1798                                 specs["type2D"]                                                 = dataTypes[dataTypeIdx].type2D;
1799
1800                                 if (indices[indicesIdx].y() == 1)
1801                                         specs["accessChain"]                            = "OpAccessChain %_ptr_Uniform_16bit_data %dataInput %int_0 %s0 %s1 %s2 %s3";
1802                                 else
1803                                         specs["accessChain"]                            = "OpAccessChain %_ptr_Uniform_16bit_data %dataInput %int_0 %s0 %s1 %s2";
1804
1805                                 if (dataTypeIdx == 0)
1806                                 {
1807                                         spec.verifyIO           = check32BitFloats;
1808                                         specs["decoration"]     = "OpMemberDecorate %S 1 ColMajor\nOpMemberDecorate %S 1 MatrixStride 48\n";
1809                                 }
1810
1811                                 spec.assembly                                                   = shaderTemplate.specialize(specs);
1812                                 spec.numWorkGroups                                              = IVec3(1, 1, 1);
1813                                 spec.extensions.push_back                               ("VK_KHR_16bit_storage");
1814                                 spec.requestedVulkanFeatures                    = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1815                                 spec.inputs.push_back(Resource(dataTypes[dataTypeIdx].inputs, CAPABILITIES[capIdx].dtype));
1816                                 spec.outputs.push_back(Resource(dataTypes[dataTypeIdx].outputs));
1817
1818                                 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec, features));
1819                         }
1820                 }
1821 }
1822
1823 void addCompute16bitStoragePushConstant16To32Group (tcu::TestCaseGroup* group)
1824 {
1825         tcu::TestContext&                               testCtx                 = group->getTestContext();
1826         de::Random                                              rnd                             (deStringHash(group->getName()));
1827         const int                                               numElements             = 64;
1828
1829         const StringTemplate                    shaderTemplate  (
1830                 "OpCapability Shader\n"
1831                 "OpCapability StoragePushConstant16\n"
1832                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
1833                 "OpMemoryModel Logical GLSL450\n"
1834                 "OpEntryPoint GLCompute %main \"main\" %id\n"
1835                 "OpExecutionMode %main LocalSize 1 1 1\n"
1836                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1837
1838                 "${stride}"
1839
1840                 "OpDecorate %PC16 BufferBlock\n"
1841                 "OpMemberDecorate %PC16 0 Offset 0\n"
1842                 "OpMemberDecorate %SSBO32 0 Offset 0\n"
1843                 "OpDecorate %SSBO32 BufferBlock\n"
1844                 "OpDecorate %ssbo32 DescriptorSet 0\n"
1845                 "OpDecorate %ssbo32 Binding 0\n"
1846
1847                 "${matrix_decor:opt}\n"
1848
1849                 "%void      = OpTypeVoid\n"
1850                 "%voidf     = OpTypeFunction %void\n"
1851                 "%u32       = OpTypeInt 32 0\n"
1852                 "%i32       = OpTypeInt 32 1\n"
1853                 "%f32       = OpTypeFloat 32\n"
1854                 "%v3u32     = OpTypeVector %u32 3\n"
1855                 "%uvec3ptr  = OpTypePointer Input %v3u32\n"
1856                 "%i32ptr    = OpTypePointer Uniform %i32\n"
1857                 "%f32ptr    = OpTypePointer Uniform %f32\n"
1858
1859                 "%zero      = OpConstant %i32 0\n"
1860                 "%c_i32_1   = OpConstant %i32 1\n"
1861                 "%c_i32_8   = OpConstant %i32 8\n"
1862                 "%c_i32_16  = OpConstant %i32 16\n"
1863                 "%c_i32_32  = OpConstant %i32 32\n"
1864                 "%c_i32_64  = OpConstant %i32 64\n"
1865                 "%c_i32_ci  = OpConstant %i32 ${constarrayidx}\n"
1866
1867                 "%i32arr    = OpTypeArray %i32 %c_i32_64\n"
1868                 "%f32arr    = OpTypeArray %f32 %c_i32_64\n"
1869
1870                 "${types}\n"
1871                 "${matrix_types:opt}\n"
1872
1873                 "%PC16      = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
1874                 "%pp_PC16   = OpTypePointer PushConstant %PC16\n"
1875                 "%pc16      = OpVariable %pp_PC16 PushConstant\n"
1876                 "%SSBO32    = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
1877                 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
1878                 "%ssbo32    = OpVariable %up_SSBO32 Uniform\n"
1879
1880                 "%id        = OpVariable %uvec3ptr Input\n"
1881
1882                 "%main      = OpFunction %void None %voidf\n"
1883                 "%label     = OpLabel\n"
1884                 "%idval     = OpLoad %v3u32 %id\n"
1885                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1886                 "%inloc     = OpAccessChain %${base16}ptr %pc16 %zero %${arrayindex} ${index0:opt}\n"
1887                 "%val16     = OpLoad %${base16} %inloc\n"
1888                 "%val32     = ${convert} %${base32} %val16\n"
1889                 "%outloc    = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
1890                 "             OpStore %outloc %val32\n"
1891                 "${matrix_store:opt}\n"
1892                 "             OpReturn\n"
1893                 "             OpFunctionEnd\n");
1894
1895         {  // floats
1896                 const char                                                                              floatTypes[]    =
1897                         "%f16       = OpTypeFloat 16\n"
1898                         "%f16ptr    = OpTypePointer PushConstant %f16\n"
1899                         "%f16arr    = OpTypeArray %f16 %c_i32_64\n"
1900                         "%v4f16     = OpTypeVector %f16 4\n"
1901                         "%v4f32     = OpTypeVector %f32 4\n"
1902                         "%v4f16ptr  = OpTypePointer PushConstant %v4f16\n"
1903                         "%v4f32ptr  = OpTypePointer Uniform %v4f32\n"
1904                         "%v4f16arr  = OpTypeArray %v4f16 %c_i32_16\n"
1905                         "%v4f32arr  = OpTypeArray %v4f32 %c_i32_16\n";
1906
1907                 struct CompositeType
1908                 {
1909                         const char*     name;
1910                         const char*     base32;
1911                         const char*     base16;
1912                         const char*     stride;
1913                         bool            useConstantIndex;
1914                         unsigned        constantIndex;
1915                         unsigned        count;
1916                 };
1917
1918                 const CompositeType     cTypes[]        =
1919                 {
1920                         {"scalar",                              "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                         false,  0,      numElements},
1921                         {"scalar_const_idx_5",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                         true,   5,      numElements},
1922                         {"scalar_const_idx_8",  "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                         true,   8,      numElements},
1923                         {"vector",                              "v4f32",        "v4f16",        "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n",            false,  0,      numElements / 4},
1924                         {"matrix",                              "v4f32",        "v4f16",        "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n",       false,  0,      numElements / 8},
1925                 };
1926
1927                 vector<deFloat16>       float16Data                     = getFloat16s(rnd, numElements);
1928                 vector<float>           float32Data;
1929
1930                 float32Data.reserve(numElements);
1931                 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1932                         float32Data.push_back(deFloat16To32(float16Data[numIdx]));
1933
1934                 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
1935                 {
1936                         ComputeShaderSpec               spec;
1937                         map<string, string>             specs;
1938                         string                                  testName        = string(cTypes[tyIdx].name) + "_float";
1939
1940                         vector<float>                   float32DataConstIdx;
1941                         if (cTypes[tyIdx].useConstantIndex)
1942                         {
1943                                 const deUint32 numFloats = numElements / cTypes[tyIdx].count;
1944                                 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1945                                         float32DataConstIdx.push_back(float32Data[cTypes[tyIdx].constantIndex * numFloats + numIdx % numFloats]);
1946                         }
1947
1948                         specs["stride"]                 = cTypes[tyIdx].stride;
1949                         specs["base32"]                 = cTypes[tyIdx].base32;
1950                         specs["base16"]                 = cTypes[tyIdx].base16;
1951                         specs["types"]                  = floatTypes;
1952                         specs["convert"]                = "OpFConvert";
1953                         specs["constarrayidx"]  = de::toString(cTypes[tyIdx].constantIndex);
1954                         if (cTypes[tyIdx].useConstantIndex)
1955                                 specs["arrayindex"] = "c_i32_ci";
1956                         else
1957                                 specs["arrayindex"] = "x";
1958
1959                         if (strcmp(cTypes[tyIdx].name, "matrix") == 0)
1960                         {
1961                                 specs["index0"]                 = "%zero";
1962                                 specs["matrix_prefix"]  = "m2";
1963                                 specs["matrix_types"]   =
1964                                         "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
1965                                         "%m2v4f32 = OpTypeMatrix %v4f32 2\n"
1966                                         "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_8\n"
1967                                         "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_8\n";
1968                                 specs["matrix_decor"]   =
1969                                         "OpMemberDecorate %SSBO32 0 ColMajor\n"
1970                                         "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
1971                                         "OpMemberDecorate %PC16 0 ColMajor\n"
1972                                         "OpMemberDecorate %PC16 0 MatrixStride 8\n";
1973                                 specs["matrix_store"]   =
1974                                         "%inloc_1  = OpAccessChain %v4f16ptr %pc16 %zero %x %c_i32_1\n"
1975                                         "%val16_1  = OpLoad %v4f16 %inloc_1\n"
1976                                         "%val32_1  = OpFConvert %v4f32 %val16_1\n"
1977                                         "%outloc_1 = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n"
1978                                         "            OpStore %outloc_1 %val32_1\n";
1979                         }
1980
1981                         spec.assembly                   = shaderTemplate.specialize(specs);
1982                         spec.numWorkGroups              = IVec3(cTypes[tyIdx].count, 1, 1);
1983                         spec.verifyIO                   = check32BitFloats;
1984                         spec.pushConstants              = BufferSp(new Float16Buffer(float16Data));
1985
1986                         spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(cTypes[tyIdx].useConstantIndex ? float32DataConstIdx : float32Data))));
1987                         spec.extensions.push_back("VK_KHR_16bit_storage");
1988                         spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
1989
1990                         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1991                 }
1992         }
1993         {// integers
1994                 const char              sintTypes[]             =
1995                         "%i16       = OpTypeInt 16 1\n"
1996                         "%i16ptr    = OpTypePointer PushConstant %i16\n"
1997                         "%i16arr    = OpTypeArray %i16 %c_i32_64\n"
1998                         "%v2i16     = OpTypeVector %i16 2\n"
1999                         "%v2i32     = OpTypeVector %i32 2\n"
2000                         "%v2i16ptr  = OpTypePointer PushConstant %v2i16\n"
2001                         "%v2i32ptr  = OpTypePointer Uniform %v2i32\n"
2002                         "%v2i16arr  = OpTypeArray %v2i16 %c_i32_32\n"
2003                         "%v2i32arr  = OpTypeArray %v2i32 %c_i32_32\n";
2004
2005                 const char              uintTypes[]             =
2006                         "%u16       = OpTypeInt 16 0\n"
2007                         "%u16ptr    = OpTypePointer PushConstant %u16\n"
2008                         "%u32ptr    = OpTypePointer Uniform %u32\n"
2009                         "%u16arr    = OpTypeArray %u16 %c_i32_64\n"
2010                         "%u32arr    = OpTypeArray %u32 %c_i32_64\n"
2011                         "%v2u16     = OpTypeVector %u16 2\n"
2012                         "%v2u32     = OpTypeVector %u32 2\n"
2013                         "%v2u16ptr  = OpTypePointer PushConstant %v2u16\n"
2014                         "%v2u32ptr  = OpTypePointer Uniform %v2u32\n"
2015                         "%v2u16arr  = OpTypeArray %v2u16 %c_i32_32\n"
2016                         "%v2u32arr  = OpTypeArray %v2u32 %c_i32_32\n";
2017
2018                 struct CompositeType
2019                 {
2020                         const char*     name;
2021                         bool            isSigned;
2022                         const char* types;
2023                         const char*     base32;
2024                         const char*     base16;
2025                         const char* opcode;
2026                         const char*     stride;
2027                         bool            useConstantIndex;
2028                         unsigned        constantIndex;
2029                         unsigned        count;
2030                 };
2031
2032                 const CompositeType     cTypes[]        =
2033                 {
2034                         {"scalar_sint",                         true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 false,  0,      numElements},
2035                         {"scalar_sint_const_idx_5",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 true,   5,      numElements},
2036                         {"scalar_sint_const_idx_8",     true,   sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",                 true,   8,      numElements},
2037                         {"scalar_uint",                         false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 false,  0,      numElements},
2038                         {"scalar_uint_const_idx_5",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 true,   5,      numElements},
2039                         {"scalar_uint_const_idx_8",     false,  uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",                 true,   8,      numElements},
2040                         {"vector_sint",                         true,   sintTypes,      "v2i32",        "v2i16",        "OpSConvert",   "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n",             false,  0,      numElements / 2},
2041                         {"vector_uint",                         false,  uintTypes,      "v2u32",        "v2u16",        "OpUConvert",   "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n",             false,  0,      numElements / 2},
2042                 };
2043
2044                 vector<deInt16> inputs                  = getInt16s(rnd, numElements);
2045                 vector<deInt32> sOutputs;
2046                 vector<deInt32> uOutputs;
2047                 const deUint16  signBitMask             = 0x8000;
2048                 const deUint32  signExtendMask  = 0xffff0000;
2049
2050                 sOutputs.reserve(inputs.size());
2051                 uOutputs.reserve(inputs.size());
2052
2053                 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
2054                 {
2055                         uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
2056                         if (inputs[numNdx] & signBitMask)
2057                                 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
2058                         else
2059                                 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
2060                 }
2061
2062                 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
2063                 {
2064                         ComputeShaderSpec               spec;
2065                         map<string, string>             specs;
2066                         const char*                             testName        = cTypes[tyIdx].name;
2067                         vector<deInt32>                 intDataConstIdx;
2068
2069                         if (cTypes[tyIdx].useConstantIndex)
2070                         {
2071                                 const deUint32 numInts = numElements / cTypes[tyIdx].count;
2072
2073                                 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
2074                                 {
2075                                         const deInt32 idx = cTypes[tyIdx].constantIndex * numInts + numIdx % numInts;
2076
2077                                         if (cTypes[tyIdx].isSigned)
2078                                                 intDataConstIdx.push_back(sOutputs[idx]);
2079                                         else
2080                                                 intDataConstIdx.push_back(uOutputs[idx]);
2081                                 }
2082                         }
2083
2084                         specs["stride"]                 = cTypes[tyIdx].stride;
2085                         specs["base32"]                 = cTypes[tyIdx].base32;
2086                         specs["base16"]                 = cTypes[tyIdx].base16;
2087                         specs["types"]                  = cTypes[tyIdx].types;
2088                         specs["convert"]                = cTypes[tyIdx].opcode;
2089                         specs["constarrayidx"]  = de::toString(cTypes[tyIdx].constantIndex);
2090                         if (cTypes[tyIdx].useConstantIndex)
2091                                 specs["arrayindex"] = "c_i32_ci";
2092                         else
2093                                 specs["arrayindex"] = "x";
2094
2095                         spec.assembly                   = shaderTemplate.specialize(specs);
2096                         spec.numWorkGroups              = IVec3(cTypes[tyIdx].count, 1, 1);
2097                         spec.pushConstants              = BufferSp(new Int16Buffer(inputs));
2098
2099                         if (cTypes[tyIdx].useConstantIndex)
2100                                 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(intDataConstIdx))));
2101                         else if (cTypes[tyIdx].isSigned)
2102                                 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs))));
2103                         else
2104                                 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs))));
2105                         spec.extensions.push_back("VK_KHR_16bit_storage");
2106                         spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
2107
2108                         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName, testName, spec));
2109                 }
2110         }
2111 }
2112
2113 void addGraphics16BitStorageUniformInt32To16Group (tcu::TestCaseGroup* testGroup)
2114 {
2115         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
2116         map<string, string>                                     fragments;
2117         const deUint32                                          numDataPoints           = 256;
2118         RGBA                                                            defaultColors[4];
2119         vector<string>                                          extensions;
2120         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
2121         // inputs and outputs are declared to be vectors of signed integers.
2122         // However, depending on the test, they may be interpreted as unsiged
2123         // integers. That won't be a problem as long as we passed the bits
2124         // in faithfully to the pipeline.
2125         vector<deInt32>                                         inputs                          = getInt32s(rnd, numDataPoints);
2126         vector<deInt16>                                         outputs;
2127
2128         outputs.reserve(inputs.size());
2129         for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
2130                 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx]));
2131
2132
2133         extensions.push_back("VK_KHR_16bit_storage");
2134         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
2135
2136         getDefaultColors(defaultColors);
2137
2138         struct IntegerFacts
2139         {
2140                 const char*     name;
2141                 const char*     type32;
2142                 const char*     type16;
2143                 const char* opcode;
2144                 const char*     isSigned;
2145         };
2146
2147         const IntegerFacts      intFacts[]              =
2148         {
2149                 {"sint",        "%i32",         "%i16",         "OpSConvert",   "1"},
2150                 {"uint",        "%u32",         "%u16",         "OpUConvert",   "0"},
2151         };
2152
2153         const StringTemplate    scalarPreMain(
2154                         "${itype16} = OpTypeInt 16 ${signed}\n"
2155                         "%c_i32_256 = OpConstant %i32 256\n"
2156                         "   %up_i32 = OpTypePointer Uniform ${itype32}\n"
2157                         "   %up_i16 = OpTypePointer Uniform ${itype16}\n"
2158                         "   %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n"
2159                         "   %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n"
2160                         "   %SSBO32 = OpTypeStruct %ra_i32\n"
2161                         "   %SSBO16 = OpTypeStruct %ra_i16\n"
2162                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2163                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2164                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
2165                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
2166
2167         const StringTemplate    scalarDecoration(
2168                         "OpDecorate %ra_i32 ArrayStride ${arraystride}\n"
2169                         "OpDecorate %ra_i16 ArrayStride 2\n"
2170                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
2171                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
2172                         "OpDecorate %SSBO32 ${indecor}\n"
2173                         "OpDecorate %SSBO16 BufferBlock\n"
2174                         "OpDecorate %ssbo32 DescriptorSet 0\n"
2175                         "OpDecorate %ssbo16 DescriptorSet 0\n"
2176                         "OpDecorate %ssbo32 Binding 0\n"
2177                         "OpDecorate %ssbo16 Binding 1\n");
2178
2179         const StringTemplate    scalarTestFunc(
2180                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
2181                         "    %param = OpFunctionParameter %v4f32\n"
2182
2183                         "%entry = OpLabel\n"
2184                         "    %i = OpVariable %fp_i32 Function\n"
2185                         "         OpStore %i %c_i32_0\n"
2186                         "         OpBranch %loop\n"
2187
2188                         " %loop = OpLabel\n"
2189                         "   %15 = OpLoad %i32 %i\n"
2190                         "   %lt = OpSLessThan %bool %15 %c_i32_256\n"
2191                         "         OpLoopMerge %merge %inc None\n"
2192                         "         OpBranchConditional %lt %write %merge\n"
2193
2194                         "%write = OpLabel\n"
2195                         "   %30 = OpLoad %i32 %i\n"
2196                         "  %src = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n"
2197                         "%val32 = OpLoad ${itype32} %src\n"
2198                         "%val16 = ${convert} ${itype16} %val32\n"
2199                         "  %dst = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %30\n"
2200                         "         OpStore %dst %val16\n"
2201                         "         OpBranch %inc\n"
2202
2203                         "  %inc = OpLabel\n"
2204                         "   %37 = OpLoad %i32 %i\n"
2205                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
2206                         "         OpStore %i %39\n"
2207                         "         OpBranch %loop\n"
2208
2209                         "%merge = OpLabel\n"
2210                         "         OpReturnValue %param\n"
2211
2212                         "OpFunctionEnd\n");
2213
2214         const StringTemplate    vecPreMain(
2215                         "${itype16} = OpTypeInt 16 ${signed}\n"
2216                         " %c_i32_64 = OpConstant %i32 64\n"
2217                         "%v4itype16 = OpTypeVector ${itype16} 4\n"
2218                         " %up_v4i32 = OpTypePointer Uniform ${v4itype32}\n"
2219                         " %up_v4i16 = OpTypePointer Uniform %v4itype16\n"
2220                         " %ra_v4i32 = OpTypeArray ${v4itype32} %c_i32_64\n"
2221                         " %ra_v4i16 = OpTypeArray %v4itype16 %c_i32_64\n"
2222                         "   %SSBO32 = OpTypeStruct %ra_v4i32\n"
2223                         "   %SSBO16 = OpTypeStruct %ra_v4i16\n"
2224                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2225                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2226                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
2227                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
2228
2229         const StringTemplate    vecDecoration(
2230                         "OpDecorate %ra_v4i32 ArrayStride 16\n"
2231                         "OpDecorate %ra_v4i16 ArrayStride 8\n"
2232                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
2233                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
2234                         "OpDecorate %SSBO32 ${indecor}\n"
2235                         "OpDecorate %SSBO16 BufferBlock\n"
2236                         "OpDecorate %ssbo32 DescriptorSet 0\n"
2237                         "OpDecorate %ssbo16 DescriptorSet 0\n"
2238                         "OpDecorate %ssbo32 Binding 0\n"
2239                         "OpDecorate %ssbo16 Binding 1\n");
2240
2241         const StringTemplate    vecTestFunc(
2242                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
2243                         "    %param = OpFunctionParameter %v4f32\n"
2244
2245                         "%entry = OpLabel\n"
2246                         "    %i = OpVariable %fp_i32 Function\n"
2247                         "         OpStore %i %c_i32_0\n"
2248                         "         OpBranch %loop\n"
2249
2250                         " %loop = OpLabel\n"
2251                         "   %15 = OpLoad %i32 %i\n"
2252                         "   %lt = OpSLessThan %bool %15 %c_i32_64\n"
2253                         "         OpLoopMerge %merge %inc None\n"
2254                         "         OpBranchConditional %lt %write %merge\n"
2255
2256                         "%write = OpLabel\n"
2257                         "   %30 = OpLoad %i32 %i\n"
2258                         "  %src = OpAccessChain %up_v4i32 %ssbo32 %c_i32_0 %30\n"
2259                         "%val32 = OpLoad ${v4itype32} %src\n"
2260                         "%val16 = ${convert} %v4itype16 %val32\n"
2261                         "  %dst = OpAccessChain %up_v4i16 %ssbo16 %c_i32_0 %30\n"
2262                         "         OpStore %dst %val16\n"
2263                         "         OpBranch %inc\n"
2264
2265                         "  %inc = OpLabel\n"
2266                         "   %37 = OpLoad %i32 %i\n"
2267                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
2268                         "         OpStore %i %39\n"
2269                         "         OpBranch %loop\n"
2270
2271                         "%merge = OpLabel\n"
2272                         "         OpReturnValue %param\n"
2273
2274                         "OpFunctionEnd\n");
2275
2276         // Scalar
2277         {
2278                 const deUint32  arrayStrides[]          = {4, 16};
2279
2280                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2281                         for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
2282                         {
2283                                 map<string, string>     specs;
2284                                 string                          name            = string(CAPABILITIES[capIdx].name) + "_scalar_" + intFacts[factIdx].name;
2285
2286                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
2287                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
2288                                 specs["itype32"]                                = intFacts[factIdx].type32;
2289                                 specs["v4itype32"]                              = "%v4" + string(intFacts[factIdx].type32).substr(1);
2290                                 specs["itype16"]                                = intFacts[factIdx].type16;
2291                                 specs["signed"]                                 = intFacts[factIdx].isSigned;
2292                                 specs["convert"]                                = intFacts[factIdx].opcode;
2293                                 specs["arraystride"]                    = de::toString(arrayStrides[capIdx]);
2294
2295                                 fragments["pre_main"]                   = scalarPreMain.specialize(specs);
2296                                 fragments["testfun"]                    = scalarTestFunc.specialize(specs);
2297                                 fragments["capability"]                 = capabilities.specialize(specs);
2298                                 fragments["decoration"]                 = scalarDecoration.specialize(specs);
2299
2300                                 vector<deInt32>         inputsPadded;
2301                                 for (size_t dataIdx = 0; dataIdx < inputs.size(); ++dataIdx)
2302                                 {
2303                                         inputsPadded.push_back(inputs[dataIdx]);
2304                                         for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 4 - 1; ++padIdx)
2305                                                 inputsPadded.push_back(0);
2306                                 }
2307                                 GraphicsResources       resources;
2308                                 resources.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputsPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2309                                 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2310
2311                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
2312
2313                                 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
2314                         }
2315         }
2316         // Vector
2317         {
2318                 GraphicsResources       resources;
2319                 resources.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2320                 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2321
2322                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2323                         for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
2324                         {
2325                                 map<string, string>     specs;
2326                                 string                          name            = string(CAPABILITIES[capIdx].name) + "_vector_" + intFacts[factIdx].name;
2327
2328                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
2329                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
2330                                 specs["itype32"]                                = intFacts[factIdx].type32;
2331                                 specs["v4itype32"]                              = "%v4" + string(intFacts[factIdx].type32).substr(1);
2332                                 specs["itype16"]                                = intFacts[factIdx].type16;
2333                                 specs["signed"]                                 = intFacts[factIdx].isSigned;
2334                                 specs["convert"]                                = intFacts[factIdx].opcode;
2335
2336                                 fragments["pre_main"]                   = vecPreMain.specialize(specs);
2337                                 fragments["testfun"]                    = vecTestFunc.specialize(specs);
2338                                 fragments["capability"]                 = capabilities.specialize(specs);
2339                                 fragments["decoration"]                 = vecDecoration.specialize(specs);
2340
2341                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
2342
2343                                 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
2344                         }
2345         }
2346 }
2347
2348 void addCompute16bitStorageUniform16To16Group (tcu::TestCaseGroup* group)
2349 {
2350         tcu::TestContext&               testCtx                         = group->getTestContext();
2351         de::Random                              rnd                                     (deStringHash(group->getName()));
2352         const int                               numElements                     = 128;
2353         const vector<deFloat16> float16Data                     = getFloat16s(rnd, numElements);
2354         const vector<deFloat16> float16DummyData        (numElements, 0);
2355         ComputeShaderSpec               spec;
2356
2357         std::ostringstream              shaderTemplate;
2358                 shaderTemplate<<"OpCapability Shader\n"
2359                         << "OpCapability StorageUniformBufferBlock16\n"
2360                         << "OpExtension \"SPV_KHR_16bit_storage\"\n"
2361                         << "OpMemoryModel Logical GLSL450\n"
2362                         << "OpEntryPoint GLCompute %main \"main\" %id\n"
2363                         << "OpExecutionMode %main LocalSize 1 1 1\n"
2364                         << "OpDecorate %id BuiltIn GlobalInvocationId\n"
2365                         << "OpDecorate %f16arr ArrayStride 2\n"
2366                         << "OpMemberDecorate %SSBO_IN 0 Coherent\n"
2367                         << "OpMemberDecorate %SSBO_OUT 0 Coherent\n"
2368                         << "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2369                         << "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2370                         << "OpDecorate %SSBO_IN BufferBlock\n"
2371                         << "OpDecorate %SSBO_OUT BufferBlock\n"
2372                         << "OpDecorate %ssboIN DescriptorSet 0\n"
2373                         << "OpDecorate %ssboOUT DescriptorSet 0\n"
2374                         << "OpDecorate %ssboIN Binding 0\n"
2375                         << "OpDecorate %ssboOUT Binding 1\n"
2376                         << "\n"
2377                         << "%bool      = OpTypeBool\n"
2378                         << "%void      = OpTypeVoid\n"
2379                         << "%voidf     = OpTypeFunction %void\n"
2380                         << "%u32       = OpTypeInt 32 0\n"
2381                         << "%i32       = OpTypeInt 32 1\n"
2382                         << "%uvec3     = OpTypeVector %u32 3\n"
2383                         << "%uvec3ptr  = OpTypePointer Input %uvec3\n"
2384                         << "%f16       = OpTypeFloat 16\n"
2385                         << "%f16ptr    = OpTypePointer Uniform %f16\n"
2386                         << "\n"
2387                         << "%zero      = OpConstant %i32 0\n"
2388                         << "%c_size    = OpConstant %i32 " << numElements << "\n"
2389                         << "\n"
2390                         << "%f16arr    = OpTypeArray %f16 %c_size\n"
2391                         << "%SSBO_IN   = OpTypeStruct %f16arr\n"
2392                         << "%SSBO_OUT  = OpTypeStruct %f16arr\n"
2393                         << "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
2394                         << "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
2395                         << "%ssboIN    = OpVariable %up_SSBOIN Uniform\n"
2396                         << "%ssboOUT   = OpVariable %up_SSBOOUT Uniform\n"
2397                         << "\n"
2398                         << "%id        = OpVariable %uvec3ptr Input\n"
2399                         << "%main      = OpFunction %void None %voidf\n"
2400                         << "%label     = OpLabel\n"
2401                         << "%idval     = OpLoad %uvec3 %id\n"
2402                         << "%x         = OpCompositeExtract %u32 %idval 0\n"
2403                         << "%y         = OpCompositeExtract %u32 %idval 1\n"
2404                         << "\n"
2405                         << "%inlocx     = OpAccessChain %f16ptr %ssboIN %zero %x \n"
2406                         << "%valx       = OpLoad %f16 %inlocx\n"
2407                         << "%outlocx    = OpAccessChain %f16ptr %ssboOUT %zero %x \n"
2408                         << "             OpStore %outlocx %valx\n"
2409
2410                         << "%inlocy    = OpAccessChain %f16ptr %ssboIN %zero %y \n"
2411                         << "%valy      = OpLoad %f16 %inlocy\n"
2412                         << "%outlocy   = OpAccessChain %f16ptr %ssboOUT %zero %y \n"
2413                         << "             OpStore %outlocy %valy\n"
2414                         << "\n"
2415                         << "             OpReturn\n"
2416                         << "             OpFunctionEnd\n";
2417
2418         spec.assembly                   = shaderTemplate.str();
2419         spec.numWorkGroups              = IVec3(numElements, numElements, 1);
2420         spec.verifyIO                   = computeCheckBuffersFloats;
2421         spec.coherentMemory             = true;
2422         spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data))));
2423         spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16DummyData))));
2424         spec.extensions.push_back("VK_KHR_16bit_storage");
2425         spec.requestedVulkanFeatures = get16BitStorageFeatures("uniform_buffer_block");
2426
2427         group->addChild(new SpvAsmComputeShaderCase(testCtx, "stress_test", "Granularity stress test", spec));
2428 }
2429
2430 void addCompute16bitStorageUniform32To16Group (tcu::TestCaseGroup* group)
2431 {
2432         tcu::TestContext&                               testCtx                 = group->getTestContext();
2433         de::Random                                              rnd                             (deStringHash(group->getName()));
2434         const int                                               numElements             = 128;
2435
2436         const StringTemplate                    shaderTemplate  (
2437                 "OpCapability Shader\n"
2438                 "OpCapability ${capability}\n"
2439                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2440                 "OpMemoryModel Logical GLSL450\n"
2441                 "OpEntryPoint GLCompute %main \"main\" %id\n"
2442                 "OpExecutionMode %main LocalSize 1 1 1\n"
2443                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2444
2445                 "${stride}"
2446
2447                 "OpMemberDecorate %SSBO32 0 Offset 0\n"
2448                 "OpMemberDecorate %SSBO16 0 Offset 0\n"
2449                 "OpDecorate %SSBO32 ${storage}\n"
2450                 "OpDecorate %SSBO16 BufferBlock\n"
2451                 "OpDecorate %ssbo32 DescriptorSet 0\n"
2452                 "OpDecorate %ssbo16 DescriptorSet 0\n"
2453                 "OpDecorate %ssbo32 Binding 0\n"
2454                 "OpDecorate %ssbo16 Binding 1\n"
2455
2456                 "${matrix_decor:opt}\n"
2457
2458                 "${rounding:opt}\n"
2459
2460                 "%bool      = OpTypeBool\n"
2461                 "%void      = OpTypeVoid\n"
2462                 "%voidf     = OpTypeFunction %void\n"
2463                 "%u32       = OpTypeInt 32 0\n"
2464                 "%i32       = OpTypeInt 32 1\n"
2465                 "%f32       = OpTypeFloat 32\n"
2466                 "%uvec3     = OpTypeVector %u32 3\n"
2467                 "%uvec3ptr  = OpTypePointer Input %uvec3\n"
2468                 "%i32ptr    = OpTypePointer Uniform %i32\n"
2469                 "%f32ptr    = OpTypePointer Uniform %f32\n"
2470
2471                 "%zero      = OpConstant %i32 0\n"
2472                 "%c_i32_1   = OpConstant %i32 1\n"
2473                 "%c_i32_16  = OpConstant %i32 16\n"
2474                 "%c_i32_32  = OpConstant %i32 32\n"
2475                 "%c_i32_64  = OpConstant %i32 64\n"
2476                 "%c_i32_128 = OpConstant %i32 128\n"
2477
2478                 "%i32arr    = OpTypeArray %i32 %c_i32_128\n"
2479                 "%f32arr    = OpTypeArray %f32 %c_i32_128\n"
2480
2481                 "${types}\n"
2482                 "${matrix_types:opt}\n"
2483
2484                 "%SSBO32    = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
2485                 "%SSBO16    = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
2486                 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2487                 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2488                 "%ssbo32    = OpVariable %up_SSBO32 Uniform\n"
2489                 "%ssbo16    = OpVariable %up_SSBO16 Uniform\n"
2490
2491                 "%id        = OpVariable %uvec3ptr Input\n"
2492
2493                 "%main      = OpFunction %void None %voidf\n"
2494                 "%label     = OpLabel\n"
2495                 "%idval     = OpLoad %uvec3 %id\n"
2496                 "%x         = OpCompositeExtract %u32 %idval 0\n"
2497                 "%inloc     = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
2498                 "%val32     = OpLoad %${base32} %inloc\n"
2499                 "%val16     = ${convert} %${base16} %val32\n"
2500                 "%outloc    = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n"
2501                 "             OpStore %outloc %val16\n"
2502                 "${matrix_store:opt}\n"
2503                 "             OpReturn\n"
2504                 "             OpFunctionEnd\n");
2505
2506         {  // Floats
2507                 const char                                      floatTypes[]    =
2508                         "%f16       = OpTypeFloat 16\n"
2509                         "%f16ptr    = OpTypePointer Uniform %f16\n"
2510                         "%f16arr    = OpTypeArray %f16 %c_i32_128\n"
2511                         "%v4f16     = OpTypeVector %f16 4\n"
2512                         "%v4f32     = OpTypeVector %f32 4\n"
2513                         "%v4f16ptr  = OpTypePointer Uniform %v4f16\n"
2514                         "%v4f32ptr  = OpTypePointer Uniform %v4f32\n"
2515                         "%v4f16arr  = OpTypeArray %v4f16 %c_i32_32\n"
2516                         "%v4f32arr  = OpTypeArray %v4f32 %c_i32_32\n";
2517
2518                 struct RndMode
2519                 {
2520                         const char*                             name;
2521                         const char*                             decor;
2522                         VerifyIOFunc                    func;
2523                 };
2524
2525                 const RndMode           rndModes[]              =
2526                 {
2527                         {"rtz",                                         "OpDecorate %val16  FPRoundingMode RTZ",        computeCheck16BitFloats<ROUNDINGMODE_RTZ>},
2528                         {"rte",                                         "OpDecorate %val16  FPRoundingMode RTE",        computeCheck16BitFloats<ROUNDINGMODE_RTE>},
2529                         {"unspecified_rnd_mode",        "",                                                                                     computeCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
2530                 };
2531
2532                 struct CompositeType
2533                 {
2534                         const char*     name;
2535                         const char*     base32;
2536                         const char*     base16;
2537                         const char*     stride;
2538                         unsigned        count;
2539                         unsigned        inputStride;
2540                 };
2541
2542                 const CompositeType     cTypes[2][3]    =
2543                 {
2544                         { // BufferBlock
2545                                 {"scalar",      "f32",          "f16",          "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n",                         numElements,            1},
2546                                 {"vector",      "v4f32",        "v4f16",        "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n",            numElements / 4,        1},
2547                                 {"matrix",      "v4f32",        "v4f16",        "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n",       numElements / 8,        1}
2548                         },
2549                         { // Block
2550                                 {"scalar",      "f32",          "f16",          "OpDecorate %f32arr ArrayStride 16\nOpDecorate %f16arr ArrayStride 2\n",                        numElements,            4},
2551                                 {"vector",      "v4f32",        "v4f16",        "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n",            numElements / 4,        1},
2552                                 {"matrix",      "v4f32",        "v4f16",        "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n",       numElements / 8,        1}
2553                         }
2554                 };
2555
2556                 vector<deFloat16>       float16DummyData        (numElements, 0);
2557
2558                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2559                         for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
2560                                 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
2561                                 {
2562                                         ComputeShaderSpec               spec;
2563                                         map<string, string>             specs;
2564                                         string                                  testName                        = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name + "_float_" + rndModes[rndModeIdx].name;
2565                                         vector<float>                   float32Data                     = getFloat32s(rnd, numElements * cTypes[capIdx][tyIdx].inputStride);
2566
2567                                         specs["capability"]             = CAPABILITIES[capIdx].cap;
2568                                         specs["storage"]                = CAPABILITIES[capIdx].decor;
2569                                         specs["stride"]                 = cTypes[capIdx][tyIdx].stride;
2570                                         specs["base32"]                 = cTypes[capIdx][tyIdx].base32;
2571                                         specs["base16"]                 = cTypes[capIdx][tyIdx].base16;
2572                                         specs["rounding"]               = rndModes[rndModeIdx].decor;
2573                                         specs["types"]                  = floatTypes;
2574                                         specs["convert"]                = "OpFConvert";
2575
2576                                         if (strcmp(cTypes[capIdx][tyIdx].name, "matrix") == 0)
2577                                         {
2578                                                 if (strcmp(rndModes[rndModeIdx].name, "rtz") == 0)
2579                                                         specs["rounding"] += "\nOpDecorate %val16_1  FPRoundingMode RTZ\n";
2580                                                 else if (strcmp(rndModes[rndModeIdx].name, "rte") == 0)
2581                                                         specs["rounding"] += "\nOpDecorate %val16_1  FPRoundingMode RTE\n";
2582
2583                                                 specs["index0"]                 = "%zero";
2584                                                 specs["matrix_prefix"]  = "m2";
2585                                                 specs["matrix_types"]   =
2586                                                         "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
2587                                                         "%m2v4f32 = OpTypeMatrix %v4f32 2\n"
2588                                                         "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_16\n"
2589                                                         "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_16\n";
2590                                                 specs["matrix_decor"]   =
2591                                                         "OpMemberDecorate %SSBO32 0 ColMajor\n"
2592                                                         "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
2593                                                         "OpMemberDecorate %SSBO16 0 ColMajor\n"
2594                                                         "OpMemberDecorate %SSBO16 0 MatrixStride 8\n";
2595                                                 specs["matrix_store"]   =
2596                                                         "%inloc_1  = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n"
2597                                                         "%val32_1  = OpLoad %v4f32 %inloc_1\n"
2598                                                         "%val16_1  = OpFConvert %v4f16 %val32_1\n"
2599                                                         "%outloc_1 = OpAccessChain %v4f16ptr %ssbo16 %zero %x %c_i32_1\n"
2600                                                         "            OpStore %outloc_1 %val16_1\n";
2601                                         }
2602
2603                                         spec.assembly                   = shaderTemplate.specialize(specs);
2604                                         spec.numWorkGroups              = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
2605                                         spec.verifyIO                   = rndModes[rndModeIdx].func;
2606
2607                                         spec.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), CAPABILITIES[capIdx].dtype));
2608                                         // We provided a custom verifyIO in the above in which inputs will be used for checking.
2609                                         // So put dummy data in the expected values.
2610                                         spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16DummyData))));
2611                                         spec.extensions.push_back("VK_KHR_16bit_storage");
2612                                         spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2613
2614                                         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2615                                 }
2616         }
2617
2618         {  // Integers
2619                 const char              sintTypes[]     =
2620                         "%i16       = OpTypeInt 16 1\n"
2621                         "%i16ptr    = OpTypePointer Uniform %i16\n"
2622                         "%i16arr    = OpTypeArray %i16 %c_i32_128\n"
2623                         "%v2i16     = OpTypeVector %i16 2\n"
2624                         "%v2i32     = OpTypeVector %i32 2\n"
2625                         "%v2i16ptr  = OpTypePointer Uniform %v2i16\n"
2626                         "%v2i32ptr  = OpTypePointer Uniform %v2i32\n"
2627                         "%v2i16arr  = OpTypeArray %v2i16 %c_i32_64\n"
2628                         "%v2i32arr  = OpTypeArray %v2i32 %c_i32_64\n";
2629
2630                 const char              uintTypes[]     =
2631                         "%u16       = OpTypeInt 16 0\n"
2632                         "%u16ptr    = OpTypePointer Uniform %u16\n"
2633                         "%u32ptr    = OpTypePointer Uniform %u32\n"
2634                         "%u16arr    = OpTypeArray %u16 %c_i32_128\n"
2635                         "%u32arr    = OpTypeArray %u32 %c_i32_128\n"
2636                         "%v2u16     = OpTypeVector %u16 2\n"
2637                         "%v2u32     = OpTypeVector %u32 2\n"
2638                         "%v2u16ptr  = OpTypePointer Uniform %v2u16\n"
2639                         "%v2u32ptr  = OpTypePointer Uniform %v2u32\n"
2640                         "%v2u16arr  = OpTypeArray %v2u16 %c_i32_64\n"
2641                         "%v2u32arr  = OpTypeArray %v2u32 %c_i32_64\n";
2642
2643                 struct CompositeType
2644                 {
2645                         const char*     name;
2646                         const char* types;
2647                         const char*     base32;
2648                         const char*     base16;
2649                         const char* opcode;
2650                         const char*     stride;
2651                         unsigned        count;
2652                         unsigned        inputStride;
2653                 };
2654
2655                 const CompositeType     cTypes[2][4]    =
2656                 {
2657                         {
2658                                 {"scalar_sint", sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n",         numElements,                    1},
2659                                 {"scalar_uint", uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n",         numElements,                    1},
2660                                 {"vector_sint", sintTypes,      "v2i32",        "v2i16",        "OpSConvert",   "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n",     numElements / 2,                2},
2661                                 {"vector_uint", uintTypes,      "v2u32",        "v2u16",        "OpUConvert",   "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n",     numElements / 2,                2}
2662                         },
2663                         {
2664                                 {"scalar_sint", sintTypes,      "i32",          "i16",          "OpSConvert",   "OpDecorate %i32arr ArrayStride 16\nOpDecorate %i16arr ArrayStride 2\n",                numElements,            4},
2665                                 {"scalar_uint", uintTypes,      "u32",          "u16",          "OpUConvert",   "OpDecorate %u32arr ArrayStride 16\nOpDecorate %u16arr ArrayStride 2\n",                numElements,            4},
2666                                 {"vector_sint", sintTypes,      "v2i32",        "v2i16",        "OpSConvert",   "OpDecorate %v2i32arr ArrayStride 16\nOpDecorate %v2i16arr ArrayStride 4\n",    numElements / 2,        4},
2667                                 {"vector_uint", uintTypes,      "v2u32",        "v2u16",        "OpUConvert",   "OpDecorate %v2u32arr ArrayStride 16\nOpDecorate %v2u16arr ArrayStride 4\n",    numElements / 2,        4}
2668                         }
2669                 };
2670
2671                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2672                         for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
2673                         {
2674                                 ComputeShaderSpec               spec;
2675                                 map<string, string>             specs;
2676                                 string                                  testName                = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name;
2677                                 const deUint32                  inputStride             = cTypes[capIdx][tyIdx].inputStride;
2678                                 const deUint32                  count                   = cTypes[capIdx][tyIdx].count;
2679                                 const deUint32                  scalarsPerItem  = numElements / count;
2680
2681                                 vector<deInt32> inputs                                  = getInt32s(rnd, numElements * inputStride);
2682                                 vector<deInt16> outputs;
2683
2684                                 outputs.reserve(numElements);
2685                                 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
2686                                         for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; scalarIdx++)
2687                                                 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx * inputStride + scalarIdx]));
2688
2689                                 specs["capability"]             = CAPABILITIES[capIdx].cap;
2690                                 specs["storage"]                = CAPABILITIES[capIdx].decor;
2691                                 specs["stride"]                 = cTypes[capIdx][tyIdx].stride;
2692                                 specs["base32"]                 = cTypes[capIdx][tyIdx].base32;
2693                                 specs["base16"]                 = cTypes[capIdx][tyIdx].base16;
2694                                 specs["types"]                  = cTypes[capIdx][tyIdx].types;
2695                                 specs["convert"]                = cTypes[capIdx][tyIdx].opcode;
2696
2697                                 spec.assembly                   = shaderTemplate.specialize(specs);
2698                                 spec.numWorkGroups              = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
2699
2700                                 spec.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputs)), CAPABILITIES[capIdx].dtype));
2701                                 spec.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs))));
2702                                 spec.extensions.push_back("VK_KHR_16bit_storage");
2703                                 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2704
2705                                 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2706                         }
2707         }
2708 }
2709
2710 void addCompute16bitStorageUniform16StructTo32StructGroup (tcu::TestCaseGroup* group)
2711 {
2712         tcu::TestContext&                               testCtx                 = group->getTestContext();
2713         de::Random                                              rnd                             (deStringHash(group->getName()));
2714         const StringTemplate                    shaderTemplate  (
2715                 "OpCapability Shader\n"
2716                 "OpCapability ${capability}\n"
2717                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2718                 "OpMemoryModel Logical GLSL450\n"
2719                 "OpEntryPoint GLCompute %main \"main\" %id\n"
2720                 "OpExecutionMode %main LocalSize 1 1 1\n"
2721                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2722                 "\n"
2723                 "${strideF16}"
2724                 "\n"
2725                 "${strideF32}"
2726                 "\n"
2727                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2728                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2729                 "OpDecorate %SSBO_IN ${storage}\n"
2730                 "OpDecorate %SSBO_OUT BufferBlock\n"
2731                 "OpDecorate %ssboIN DescriptorSet 0\n"
2732                 "OpDecorate %ssboOUT DescriptorSet 0\n"
2733                 "OpDecorate %ssboIN Binding 0\n"
2734                 "OpDecorate %ssboOUT Binding 1\n"
2735                 "\n"
2736                 "%bool     = OpTypeBool\n"
2737                 "%void     = OpTypeVoid\n"
2738                 "%voidf    = OpTypeFunction %void\n"
2739                 "%u32      = OpTypeInt 32 0\n"
2740                 "%uvec3    = OpTypeVector %u32 3\n"
2741                 "%uvec3ptr = OpTypePointer Input %uvec3\n"
2742                 "\n"
2743                 "%i32      = OpTypeInt 32 1\n"
2744                 "%v2i32    = OpTypeVector %i32 2\n"
2745                 "%v4i32    = OpTypeVector %i32 4\n"
2746                 "\n"
2747                 "%f32      = OpTypeFloat 32\n"
2748                 "%v2f32    = OpTypeVector %f32 2\n"
2749                 "%v3f32    = OpTypeVector %f32 3\n"
2750                 "%v4f32    = OpTypeVector %f32 4\n"
2751                 "${types}\n"
2752                 "\n"
2753                 "%zero = OpConstant %i32 0\n"
2754                 "%c_i32_1 = OpConstant %i32 1\n"
2755                 "%c_i32_2 = OpConstant %i32 2\n"
2756                 "%c_i32_3 = OpConstant %i32 3\n"
2757                 "%c_i32_4 = OpConstant %i32 4\n"
2758                 "%c_i32_5 = OpConstant %i32 5\n"
2759                 "%c_i32_6 = OpConstant %i32 6\n"
2760                 "%c_i32_7 = OpConstant %i32 7\n"
2761                 "%c_i32_8 = OpConstant %i32 8\n"
2762                 "%c_i32_9 = OpConstant %i32 9\n"
2763                 "\n"
2764                 "%c_u32_1 = OpConstant %u32 1\n"
2765                 "%c_u32_3 = OpConstant %u32 3\n"
2766                 "%c_u32_7 = OpConstant %u32 7\n"
2767                 "%c_u32_11 = OpConstant %u32 11\n"
2768                 "\n"
2769                 "%f16arr3       = OpTypeArray %f16 %c_u32_3\n"
2770                 "%v2f16arr3    = OpTypeArray %v2f16 %c_u32_3\n"
2771                 "%v2f16arr11    = OpTypeArray %v2f16 %c_u32_11\n"
2772                 "%v3f16arr11    = OpTypeArray %v3f16 %c_u32_11\n"
2773                 "%v4f16arr3     = OpTypeArray %v4f16 %c_u32_3\n"
2774                 "%struct16      = OpTypeStruct %f16 %v2f16arr3\n"
2775                 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
2776                 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
2777                 "\n"
2778                 "%f32arr3   = OpTypeArray %f32 %c_u32_3\n"
2779                 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
2780                 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
2781                 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
2782                 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
2783                 "%struct32      = OpTypeStruct %f32 %v2f32arr3\n"
2784                 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
2785                 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
2786                 "\n"
2787                 "%f16StructArr7      = OpTypeArray %f16Struct %c_u32_7\n"
2788                 "%f32StructArr7      = OpTypeArray %f32Struct %c_u32_7\n"
2789                 "%SSBO_IN            = OpTypeStruct %f16StructArr7\n"
2790                 "%SSBO_OUT           = OpTypeStruct %f32StructArr7\n"
2791                 "%up_SSBOIN          = OpTypePointer Uniform %SSBO_IN\n"
2792                 "%up_SSBOOUT         = OpTypePointer Uniform %SSBO_OUT\n"
2793                 "%ssboIN             = OpVariable %up_SSBOIN Uniform\n"
2794                 "%ssboOUT            = OpVariable %up_SSBOOUT Uniform\n"
2795                 "\n"
2796                 "%id        = OpVariable %uvec3ptr Input\n"
2797                 "%main      = OpFunction %void None %voidf\n"
2798                 "%label     = OpLabel\n"
2799                 "\n"
2800                 "%idval     = OpLoad %uvec3 %id\n"
2801                 "%x         = OpCompositeExtract %u32 %idval 0\n"
2802                 "%y         = OpCompositeExtract %u32 %idval 1\n"
2803                 "\n"
2804                 "%f16src  = OpAccessChain %f16ptr %ssboIN %zero %x %zero\n"
2805                 "%val_f16 = OpLoad %f16 %f16src\n"
2806                 "%val_f32 = OpFConvert %f32 %val_f16\n"
2807                 "%f32dst  = OpAccessChain %f32ptr %ssboOUT %zero %x %zero\n"
2808                 "OpStore %f32dst %val_f32\n"
2809                 "\n"
2810                 "%v2f16src  = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_1\n"
2811                 "%val_v2f16 = OpLoad %v2f16 %v2f16src\n"
2812                 "%val_v2f32 = OpFConvert %v2f32 %val_v2f16\n"
2813                 "%v2f32dst  = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_1\n"
2814                 "OpStore %v2f32dst %val_v2f32\n"
2815                 "\n"
2816                 "%v3f16src  = OpAccessChain %v3f16ptr %ssboIN %zero %x %c_i32_2\n"
2817                 "%val_v3f16 = OpLoad %v3f16 %v3f16src\n"
2818                 "%val_v3f32 = OpFConvert %v3f32 %val_v3f16\n"
2819                 "%v3f32dst  = OpAccessChain %v3f32ptr %ssboOUT %zero %x %c_i32_2\n"
2820                 "OpStore %v3f32dst %val_v3f32\n"
2821                 "\n"
2822                 "%v4f16src  = OpAccessChain %v4f16ptr %ssboIN %zero %x %c_i32_3\n"
2823                 "%val_v4f16 = OpLoad %v4f16 %v4f16src\n"
2824                 "%val_v4f32 = OpFConvert %v4f32 %val_v4f16\n"
2825                 "%v4f32dst  = OpAccessChain %v4f32ptr %ssboOUT %zero %x %c_i32_3\n"
2826                 "OpStore %v4f32dst %val_v4f32\n"
2827                 "\n"
2828                 //struct {f16, v2f16[3]}
2829                 "%Sf16src  = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_5 %y %zero\n"
2830                 "%Sval_f16 = OpLoad %f16 %Sf16src\n"
2831                 "%Sval_f32 = OpFConvert %f32 %Sval_f16\n"
2832                 "%Sf32dst2  = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_5 %y %zero\n"
2833                 "OpStore %Sf32dst2 %Sval_f32\n"
2834                 "\n"
2835                 "%Sv2f16src0   = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2836                 "%Sv2f16_0     = OpLoad %v2f16 %Sv2f16src0\n"
2837                 "%Sv2f32_0     = OpFConvert %v2f32 %Sv2f16_0\n"
2838                 "%Sv2f32dst_0  = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2839                 "OpStore %Sv2f32dst_0 %Sv2f32_0\n"
2840                 "\n"
2841                 "%Sv2f16src1  = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2842                 "%Sv2f16_1 = OpLoad %v2f16 %Sv2f16src1\n"
2843                 "%Sv2f32_1 = OpFConvert %v2f32 %Sv2f16_1\n"
2844                 "%Sv2f32dst_1  = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2845                 "OpStore %Sv2f32dst_1 %Sv2f32_1\n"
2846                 "\n"
2847                 "%Sv2f16src2  = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2848                 "%Sv2f16_2 = OpLoad %v2f16 %Sv2f16src2\n"
2849                 "%Sv2f32_2 = OpFConvert %v2f32 %Sv2f16_2\n"
2850                 "%Sv2f32dst_2  = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2851                 "OpStore %Sv2f32dst_2 %Sv2f32_2\n"
2852                 "\n"
2853
2854                 "%v2f16src2  = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_6 %y\n"
2855                 "%val2_v2f16 = OpLoad %v2f16 %v2f16src2\n"
2856                 "%val2_v2f32 = OpFConvert %v2f32 %val2_v2f16\n"
2857                 "%v2f32dst2  = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_6 %y\n"
2858                 "OpStore %v2f32dst2 %val2_v2f32\n"
2859                 "\n"
2860                 "%f16src2  = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_7\n"
2861                 "%val2_f16 = OpLoad %f16 %f16src2\n"
2862                 "%val2_f32 = OpFConvert %f32 %val2_f16\n"
2863                 "%f32dst2  = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_7\n"
2864                 "OpStore %f32dst2 %val2_f32\n"
2865                 "\n"
2866                 "%v3f16src2  = OpAccessChain %v3f16ptr %ssboIN %zero %x %c_i32_8 %y\n"
2867                 "%val2_v3f16 = OpLoad %v3f16 %v3f16src2\n"
2868                 "%val2_v3f32 = OpFConvert %v3f32 %val2_v3f16\n"
2869                 "%v3f32dst2  = OpAccessChain %v3f32ptr %ssboOUT %zero %x %c_i32_8 %y\n"
2870                 "OpStore %v3f32dst2 %val2_v3f32\n"
2871                 "\n"
2872
2873                 //Array with 3 elements
2874                 "%LessThan3 = OpSLessThan %bool %y %c_i32_3\n"
2875                 "OpSelectionMerge %BlockIf None\n"
2876                 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
2877                 "%LabelIf = OpLabel\n"
2878                 "  %f16src3  = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_4 %y\n"
2879                 "  %val3_f16 = OpLoad %f16 %f16src3\n"
2880                 "  %val3_f32 = OpFConvert %f32 %val3_f16\n"
2881                 "  %f32dst3  = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_4 %y\n"
2882                 "  OpStore %f32dst3 %val3_f32\n"
2883                 "\n"
2884                 "  %v4f16src2  = OpAccessChain %v4f16ptr %ssboIN %zero %x %c_i32_9 %y\n"
2885                 "  %val2_v4f16 = OpLoad %v4f16 %v4f16src2\n"
2886                 "  %val2_v4f32 = OpFConvert %v4f32 %val2_v4f16\n"
2887                 "  %v4f32dst2  = OpAccessChain %v4f32ptr %ssboOUT %zero %x %c_i32_9 %y\n"
2888                 "  OpStore %v4f32dst2 %val2_v4f32\n"
2889                 "OpBranch %BlockIf\n"
2890                 "%BlockIf = OpLabel\n"
2891
2892                 "   OpReturn\n"
2893                 "   OpFunctionEnd\n");
2894
2895         {  // Floats
2896                 vector<float>                   float32Data             (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430), 0.0f);
2897
2898                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2899                 {
2900                         vector<deFloat16>               float16DData    = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data16bitStd430(rnd) : data16bitStd140(rnd);
2901                         ComputeShaderSpec               spec;
2902                         map<string, string>             specs;
2903                         string                                  testName                = string(CAPABILITIES[capIdx].name);
2904
2905                         specs["capability"]             = CAPABILITIES[capIdx].cap;
2906                         specs["storage"]                = CAPABILITIES[capIdx].decor;
2907                         specs["strideF16"]              = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE16BIT_STD430 : SHADERTEMPLATE_STRIDE16BIT_STD140);
2908                         specs["strideF32"]              = getStructShaderComponet(SHADERTEMPLATE_STRIDE32BIT_STD430);
2909                         specs["types"]                  = getStructShaderComponet(SHADERTEMPLATE_TYPES);
2910
2911                         spec.assembly                   = shaderTemplate.specialize(specs);
2912                         spec.numWorkGroups              = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
2913                         spec.verifyIO                   = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? computeCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD430, SHADERTEMPLATE_STRIDE32BIT_STD430>
2914                                                                                                                                                                                                                 : computeCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD140, SHADERTEMPLATE_STRIDE32BIT_STD430>;
2915                         spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16DData)), CAPABILITIES[capIdx].dtype));
2916                         spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data))));
2917                         spec.extensions.push_back("VK_KHR_16bit_storage");
2918                         spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2919
2920                         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2921                 }
2922         }
2923 }
2924
2925 void addCompute16bitStorageUniform32StructTo16StructGroup (tcu::TestCaseGroup* group)
2926 {
2927         tcu::TestContext&                               testCtx                 = group->getTestContext();
2928         de::Random                                              rnd                             (deStringHash(group->getName()));
2929
2930         const StringTemplate                    shaderTemplate  (
2931                 "OpCapability Shader\n"
2932                 "OpCapability ${capability}\n"
2933                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2934                 "OpMemoryModel Logical GLSL450\n"
2935                 "OpEntryPoint GLCompute %main \"main\" %id\n"
2936                 "OpExecutionMode %main LocalSize 1 1 1\n"
2937                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2938                 "\n"
2939                 "${strideF16}"
2940                 "\n"
2941                 "${strideF32}"
2942                 "\n"
2943                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2944                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2945                 "OpDecorate %SSBO_IN ${storage}\n"
2946                 "OpDecorate %SSBO_OUT BufferBlock\n"
2947                 "OpDecorate %ssboIN DescriptorSet 0\n"
2948                 "OpDecorate %ssboOUT DescriptorSet 0\n"
2949                 "OpDecorate %ssboIN Binding 0\n"
2950                 "OpDecorate %ssboOUT Binding 1\n"
2951                 "\n"
2952                 "%bool     = OpTypeBool\n"
2953                 "%void     = OpTypeVoid\n"
2954                 "%voidf    = OpTypeFunction %void\n"
2955                 "%u32      = OpTypeInt 32 0\n"
2956                 "%uvec3    = OpTypeVector %u32 3\n"
2957                 "%uvec3ptr = OpTypePointer Input %uvec3\n"
2958                 "\n"
2959                 "%i32      = OpTypeInt 32 1\n"
2960                 "%v2i32    = OpTypeVector %i32 2\n"
2961                 "%v4i32    = OpTypeVector %i32 4\n"
2962                 "\n"
2963                 "%f32      = OpTypeFloat 32\n"
2964                 "%v2f32    = OpTypeVector %f32 2\n"
2965                 "%v3f32    = OpTypeVector %f32 3\n"
2966                 "%v4f32    = OpTypeVector %f32 4\n"
2967                 "${types}\n"
2968                 "\n"
2969                 "%zero = OpConstant %i32 0\n"
2970                 "%c_i32_1 = OpConstant %i32 1\n"
2971                 "%c_i32_2 = OpConstant %i32 2\n"
2972                 "%c_i32_3 = OpConstant %i32 3\n"
2973                 "%c_i32_4 = OpConstant %i32 4\n"
2974                 "%c_i32_5 = OpConstant %i32 5\n"
2975                 "%c_i32_6 = OpConstant %i32 6\n"
2976                 "%c_i32_7 = OpConstant %i32 7\n"
2977                 "%c_i32_8 = OpConstant %i32 8\n"
2978                 "%c_i32_9 = OpConstant %i32 9\n"
2979                 "\n"
2980                 "%c_u32_1 = OpConstant %u32 1\n"
2981                 "%c_u32_3 = OpConstant %u32 3\n"
2982                 "%c_u32_7 = OpConstant %u32 7\n"
2983                 "%c_u32_11 = OpConstant %u32 11\n"
2984                 "\n"
2985                 "%f16arr3       = OpTypeArray %f16 %c_u32_3\n"
2986                 "%v2f16arr3    = OpTypeArray %v2f16 %c_u32_3\n"
2987                 "%v2f16arr11    = OpTypeArray %v2f16 %c_u32_11\n"
2988                 "%v3f16arr11    = OpTypeArray %v3f16 %c_u32_11\n"
2989                 "%v4f16arr3     = OpTypeArray %v4f16 %c_u32_3\n"
2990                 "%struct16      = OpTypeStruct %f16 %v2f16arr3\n"
2991                 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
2992                 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
2993                 "\n"
2994                 "%f32arr3   = OpTypeArray %f32 %c_u32_3\n"
2995                 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
2996                 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
2997                 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
2998                 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
2999                 "%struct32      = OpTypeStruct %f32 %v2f32arr3\n"
3000                 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
3001                 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
3002                 "\n"
3003                 "%f16StructArr7      = OpTypeArray %f16Struct %c_u32_7\n"
3004                 "%f32StructArr7      = OpTypeArray %f32Struct %c_u32_7\n"
3005                 "%SSBO_IN            = OpTypeStruct %f32StructArr7\n"
3006                 "%SSBO_OUT           = OpTypeStruct %f16StructArr7\n"
3007                 "%up_SSBOIN          = OpTypePointer Uniform %SSBO_IN\n"
3008                 "%up_SSBOOUT         = OpTypePointer Uniform %SSBO_OUT\n"
3009                 "%ssboIN             = OpVariable %up_SSBOIN Uniform\n"
3010                 "%ssboOUT            = OpVariable %up_SSBOOUT Uniform\n"
3011                 "\n"
3012                 "%id        = OpVariable %uvec3ptr Input\n"
3013                 "%main      = OpFunction %void None %voidf\n"
3014                 "%label     = OpLabel\n"
3015                 "\n"
3016                 "%idval     = OpLoad %uvec3 %id\n"
3017                 "%x         = OpCompositeExtract %u32 %idval 0\n"
3018                 "%y         = OpCompositeExtract %u32 %idval 1\n"
3019                 "\n"
3020                 "%f32src  = OpAccessChain %f32ptr %ssboIN %zero %x %zero\n"
3021                 "%val_f32 = OpLoad %f32 %f32src\n"
3022                 "%val_f16 = OpFConvert %f16 %val_f32\n"
3023                 "%f16dst  = OpAccessChain %f16ptr %ssboOUT %zero %x %zero\n"
3024                 "OpStore %f16dst %val_f16\n"
3025                 "\n"
3026                 "%v2f32src  = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_1\n"
3027                 "%val_v2f32 = OpLoad %v2f32 %v2f32src\n"
3028                 "%val_v2f16 = OpFConvert %v2f16 %val_v2f32\n"
3029                 "%v2f16dst  = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_1\n"
3030                 "OpStore %v2f16dst %val_v2f16\n"
3031                 "\n"
3032                 "%v3f32src  = OpAccessChain %v3f32ptr %ssboIN %zero %x %c_i32_2\n"
3033                 "%val_v3f32 = OpLoad %v3f32 %v3f32src\n"
3034                 "%val_v3f16 = OpFConvert %v3f16 %val_v3f32\n"
3035                 "%v3f16dst  = OpAccessChain %v3f16ptr %ssboOUT %zero %x %c_i32_2\n"
3036                 "OpStore %v3f16dst %val_v3f16\n"
3037                 "\n"
3038                 "%v4f32src  = OpAccessChain %v4f32ptr %ssboIN %zero %x %c_i32_3\n"
3039                 "%val_v4f32 = OpLoad %v4f32 %v4f32src\n"
3040                 "%val_v4f16 = OpFConvert %v4f16 %val_v4f32\n"
3041                 "%v4f16dst  = OpAccessChain %v4f16ptr %ssboOUT %zero %x %c_i32_3\n"
3042                 "OpStore %v4f16dst %val_v4f16\n"
3043                 "\n"
3044
3045                 //struct {f16, v2f16[3]}
3046                 "%Sf32src  = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_5 %y %zero\n"
3047                 "%Sval_f32 = OpLoad %f32 %Sf32src\n"
3048                 "%Sval_f16 = OpFConvert %f16 %Sval_f32\n"
3049                 "%Sf16dst2  = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_5 %y %zero\n"
3050                 "OpStore %Sf16dst2 %Sval_f16\n"
3051                 "\n"
3052                 "%Sv2f32src0   = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
3053                 "%Sv2f32_0     = OpLoad %v2f32 %Sv2f32src0\n"
3054                 "%Sv2f16_0     = OpFConvert %v2f16 %Sv2f32_0\n"
3055                 "%Sv2f16dst_0  = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
3056                 "OpStore %Sv2f16dst_0 %Sv2f16_0\n"
3057                 "\n"
3058                 "%Sv2f32src1  = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
3059                 "%Sv2f32_1 = OpLoad %v2f32 %Sv2f32src1\n"
3060                 "%Sv2f16_1 = OpFConvert %v2f16 %Sv2f32_1\n"
3061                 "%Sv2f16dst_1  = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
3062                 "OpStore %Sv2f16dst_1 %Sv2f16_1\n"
3063                 "\n"
3064                 "%Sv2f32src2  = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
3065                 "%Sv2f32_2 = OpLoad %v2f32 %Sv2f32src2\n"
3066                 "%Sv2f16_2 = OpFConvert %v2f16 %Sv2f32_2\n"
3067                 "%Sv2f16dst_2  = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
3068                 "OpStore %Sv2f16dst_2 %Sv2f16_2\n"
3069                 "\n"
3070
3071                 "%v2f32src2  = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_6 %y\n"
3072                 "%val2_v2f32 = OpLoad %v2f32 %v2f32src2\n"
3073                 "%val2_v2f16 = OpFConvert %v2f16 %val2_v2f32\n"
3074                 "%v2f16dst2  = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_6 %y\n"
3075                 "OpStore %v2f16dst2 %val2_v2f16\n"
3076                 "\n"
3077                 "%f32src2  = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_7\n"
3078                 "%val2_f32 = OpLoad %f32 %f32src2\n"
3079                 "%val2_f16 = OpFConvert %f16 %val2_f32\n"
3080                 "%f16dst2  = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_7\n"
3081                 "OpStore %f16dst2 %val2_f16\n"
3082                 "\n"
3083                 "%v3f32src2  = OpAccessChain %v3f32ptr %ssboIN %zero %x %c_i32_8 %y\n"
3084                 "%val2_v3f32 = OpLoad %v3f32 %v3f32src2\n"
3085                 "%val2_v3f16 = OpFConvert %v3f16 %val2_v3f32\n"
3086                 "%v3f16dst2  = OpAccessChain %v3f16ptr %ssboOUT %zero %x %c_i32_8 %y\n"
3087                 "OpStore %v3f16dst2 %val2_v3f16\n"
3088                 "\n"
3089
3090                 //Array with 3 elements
3091                 "%LessThan3 = OpSLessThan %bool %y %c_i32_3\n"
3092                 "OpSelectionMerge %BlockIf None\n"
3093                 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
3094                 "  %LabelIf = OpLabel\n"
3095                 "  %f32src3  = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_4 %y\n"
3096                 "  %val3_f32 = OpLoad %f32 %f32src3\n"
3097                 "  %val3_f16 = OpFConvert %f16 %val3_f32\n"
3098                 "  %f16dst3  = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_4 %y\n"
3099                 "  OpStore %f16dst3 %val3_f16\n"
3100                 "\n"
3101                 "  %v4f32src2  = OpAccessChain %v4f32ptr %ssboIN %zero %x %c_i32_9 %y\n"
3102                 "  %val2_v4f32 = OpLoad %v4f32 %v4f32src2\n"
3103                 "  %val2_v4f16 = OpFConvert %v4f16 %val2_v4f32\n"
3104                 "  %v4f16dst2  = OpAccessChain %v4f16ptr %ssboOUT %zero %x %c_i32_9 %y\n"
3105                 "  OpStore %v4f16dst2 %val2_v4f16\n"
3106                 "OpBranch %BlockIf\n"
3107                 "%BlockIf = OpLabel\n"
3108
3109                 "   OpReturn\n"
3110                 "   OpFunctionEnd\n");
3111
3112         {  // Floats
3113                 vector<deFloat16>               float16Data             (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430), 0u);
3114
3115                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3116                 {
3117                         ComputeShaderSpec               spec;
3118                         map<string, string>             specs;
3119                         string                                  testName                = string(CAPABILITIES[capIdx].name);
3120                         vector<float>                   float32DData    = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data32bitStd430(rnd) : data32bitStd140(rnd);
3121
3122                         specs["capability"]             = CAPABILITIES[capIdx].cap;
3123                         specs["storage"]                = CAPABILITIES[capIdx].decor;
3124                         specs["strideF16"]              = getStructShaderComponet(SHADERTEMPLATE_STRIDE16BIT_STD430);
3125                         specs["strideF32"]              = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE32BIT_STD430 : SHADERTEMPLATE_STRIDE32BIT_STD140);
3126                         specs["types"]                  = getStructShaderComponet(SHADERTEMPLATE_TYPES);
3127
3128                         spec.assembly                   = shaderTemplate.specialize(specs);
3129                         spec.numWorkGroups              = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
3130                         spec.verifyIO                   = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? computeCheckStruct<float, deFloat16, SHADERTEMPLATE_STRIDE32BIT_STD430, SHADERTEMPLATE_STRIDE16BIT_STD430> : computeCheckStruct<float, deFloat16, SHADERTEMPLATE_STRIDE32BIT_STD140, SHADERTEMPLATE_STRIDE16BIT_STD430>;
3131
3132                         spec.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32DData)), CAPABILITIES[capIdx].dtype));
3133                         spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data))));
3134                         spec.extensions.push_back("VK_KHR_16bit_storage");
3135                         spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3136
3137                         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
3138                 }
3139         }
3140 }
3141
3142 void addCompute16bitStructMixedTypesGroup (tcu::TestCaseGroup* group)
3143 {
3144         tcu::TestContext&               testCtx                 = group->getTestContext();
3145         de::Random                              rnd                             (deStringHash(group->getName()));
3146         vector<deInt16>                 outData                 (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430), 0u);
3147
3148         const StringTemplate    shaderTemplate  (
3149                 "OpCapability Shader\n"
3150                 "OpCapability StorageUniformBufferBlock16\n"
3151                 "${capability}\n"
3152                 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
3153                 "OpExtension \"SPV_KHR_16bit_storage\"\n"
3154                 "OpMemoryModel Logical GLSL450\n"
3155                 "OpEntryPoint GLCompute %main \"main\" %id\n"
3156                 "OpExecutionMode %main LocalSize 1 1 1\n"
3157                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3158                 "${OutOffsets}"
3159                 "${InOffsets}"
3160                 "\n"//SSBO IN
3161                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
3162                 "OpDecorate %ssboIN DescriptorSet 0\n"
3163                 "OpDecorate %SSBO_IN ${storage}\n"
3164                 "OpDecorate %SSBO_OUT BufferBlock\n"
3165                 "OpDecorate %ssboIN Binding 0\n"
3166                 "\n"//SSBO OUT
3167                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
3168                 "OpDecorate %ssboOUT DescriptorSet 0\n"
3169                 "OpDecorate %ssboOUT Binding 1\n"
3170                 "\n"//Types
3171                 "%void  = OpTypeVoid\n"
3172                 "%bool  = OpTypeBool\n"
3173                 "%i16   = OpTypeInt 16 1\n"
3174                 "%v2i16 = OpTypeVector %i16 2\n"
3175                 "%v3i16 = OpTypeVector %i16 3\n"
3176                 "%v4i16 = OpTypeVector %i16 4\n"
3177                 "%i32   = OpTypeInt 32 1\n"
3178                 "%v2i32 = OpTypeVector %i32 2\n"
3179                 "%v3i32 = OpTypeVector %i32 3\n"
3180                 "%v4i32 = OpTypeVector %i32 4\n"
3181                 "%u32   = OpTypeInt 32 0\n"
3182                 "%uvec3 = OpTypeVector %u32 3\n"
3183                 "%f32   = OpTypeFloat 32\n"
3184                 "%v4f32 = OpTypeVector %f32  4\n"
3185                 "%voidf = OpTypeFunction %void\n"
3186                 "\n"//Consta value
3187                 "%zero     = OpConstant %i32 0\n"
3188                 "%c_i32_1  = OpConstant %i32 1\n"
3189                 "%c_i32_2  = OpConstant %i32 2\n"
3190                 "%c_i32_3  = OpConstant %i32 3\n"
3191                 "%c_i32_4  = OpConstant %i32 4\n"
3192                 "%c_i32_5  = OpConstant %i32 5\n"
3193                 "%c_i32_6  = OpConstant %i32 6\n"
3194                 "%c_i32_7  = OpConstant %i32 7\n"
3195                 "%c_i32_8  = OpConstant %i32 8\n"
3196                 "%c_i32_9  = OpConstant %i32 9\n"
3197                 "%c_i32_10 = OpConstant %i32 10\n"
3198                 "%c_i32_11 = OpConstant %i32 11\n"
3199                 "%c_u32_1  = OpConstant %u32 1\n"
3200                 "%c_u32_7  = OpConstant %u32 7\n"
3201                 "%c_u32_11 = OpConstant %u32 11\n"
3202                 "\n"//Arrays & Structs
3203                 "%v2b16NestedArr11In  = OpTypeArray %v2i16 %c_u32_11\n"
3204                 "%b32NestedArr11In    = OpTypeArray %i32 %c_u32_11\n"
3205                 "%sb16Arr11In         = OpTypeArray %i16 %c_u32_11\n"
3206                 "%sb32Arr11In         = OpTypeArray %i32 %c_u32_11\n"
3207                 "%sNestedIn           = OpTypeStruct %i16 %i32 %v2b16NestedArr11In %b32NestedArr11In\n"
3208                 "%sNestedArr11In      = OpTypeArray %sNestedIn %c_u32_11\n"
3209                 "%structIn            = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11In %sb16Arr11In %sb32Arr11In\n"
3210                 "%structArr7In        = OpTypeArray %structIn %c_u32_7\n"
3211                 "%v2b16NestedArr11Out = OpTypeArray %v2i16 %c_u32_11\n"
3212                 "%b32NestedArr11Out   = OpTypeArray %i32 %c_u32_11\n"
3213                 "%sb16Arr11Out        = OpTypeArray %i16 %c_u32_11\n"
3214                 "%sb32Arr11Out        = OpTypeArray %i32 %c_u32_11\n"
3215                 "%sNestedOut          = OpTypeStruct %i16 %i32 %v2b16NestedArr11Out %b32NestedArr11Out\n"
3216                 "%sNestedArr11Out     = OpTypeArray %sNestedOut %c_u32_11\n"
3217                 "%structOut           = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11Out %sb16Arr11Out %sb32Arr11Out\n"
3218                 "%structArr7Out       = OpTypeArray %structOut %c_u32_7\n"
3219                 "\n"//Pointers
3220                 "%i16outPtr   = OpTypePointer Uniform %i16\n"
3221                 "%v2i16outPtr = OpTypePointer Uniform %v2i16\n"
3222                 "%v3i16outPtr = OpTypePointer Uniform %v3i16\n"
3223                 "%v4i16outPtr = OpTypePointer Uniform %v4i16\n"
3224                 "%i32outPtr   = OpTypePointer Uniform %i32\n"
3225                 "%v2i32outPtr = OpTypePointer Uniform %v2i32\n"
3226                 "%v3i32outPtr = OpTypePointer Uniform %v3i32\n"
3227                 "%v4i32outPtr = OpTypePointer Uniform %v4i32\n"
3228                 "%fp_i32      = OpTypePointer Function %i32\n"
3229                 "%uvec3ptr    = OpTypePointer Input %uvec3\n"
3230                 "\n"//SSBO IN
3231                 "%SSBO_IN    = OpTypeStruct %structArr7In\n"
3232                 "%up_SSBOIN  = OpTypePointer Uniform %SSBO_IN\n"
3233                 "%ssboIN     = OpVariable %up_SSBOIN Uniform\n"
3234                 "\n"//SSBO OUT
3235                 "%SSBO_OUT   = OpTypeStruct %structArr7Out\n"
3236                 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
3237                 "%ssboOUT    = OpVariable %up_SSBOOUT Uniform\n"
3238                 "\n"//MAIN
3239                 "%id      = OpVariable %uvec3ptr Input\n"
3240                 "%main    = OpFunction %void None %voidf\n"
3241                 "%label   = OpLabel\n"
3242                 "%ndxArrz = OpVariable %fp_i32  Function\n"
3243                 "%idval   = OpLoad %uvec3 %id\n"
3244                 "%x       = OpCompositeExtract %u32 %idval 0\n"
3245                 "%y       = OpCompositeExtract %u32 %idval 1\n"
3246                 "\n"//strutOut.b16 = strutIn.b16
3247                 "%inP1  = OpAccessChain %i16${inPtr} %ssboIN %zero %x %zero\n"
3248                 "%inV1  = OpLoad %i16 %inP1\n"
3249                 "%outP1 = OpAccessChain %i16outPtr %ssboOUT %zero %x %zero\n"
3250                 "OpStore %outP1 %inV1\n"
3251                 "\n"//strutOut.b32 = strutIn.b32
3252                 "%inP2  = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_1\n"
3253                 "%inV2  = OpLoad %i32 %inP2\n"
3254                 "%outP2 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_1\n"
3255                 "OpStore %outP2 %inV2\n"
3256                 "\n"//strutOut.v2b16 = strutIn.v2b16
3257                 "%inP3  = OpAccessChain %v2i16${inPtr} %ssboIN %zero %x %c_i32_2\n"
3258                 "%inV3  = OpLoad %v2i16 %inP3\n"
3259                 "%outP3 = OpAccessChain %v2i16outPtr %ssboOUT %zero %x %c_i32_2\n"
3260                 "OpStore %outP3 %inV3\n"
3261                 "\n"//strutOut.v2b32 = strutIn.v2b32
3262                 "%inP4  = OpAccessChain %v2i32${inPtr} %ssboIN %zero %x %c_i32_3\n"
3263                 "%inV4  = OpLoad %v2i32 %inP4\n"
3264                 "%outP4 = OpAccessChain %v2i32outPtr %ssboOUT %zero %x %c_i32_3\n"
3265                 "OpStore %outP4 %inV4\n"
3266                 "\n"//strutOut.v3b16 = strutIn.v3b16
3267                 "%inP5  = OpAccessChain %v3i16${inPtr} %ssboIN %zero %x %c_i32_4\n"
3268                 "%inV5  = OpLoad %v3i16 %inP5\n"
3269                 "%outP5 = OpAccessChain %v3i16outPtr %ssboOUT %zero %x %c_i32_4\n"
3270                 "OpStore %outP5 %inV5\n"
3271                 "\n"//strutOut.v3b32 = strutIn.v3b32
3272                 "%inP6  = OpAccessChain %v3i32${inPtr} %ssboIN %zero %x %c_i32_5\n"
3273                 "%inV6  = OpLoad %v3i32 %inP6\n"
3274                 "%outP6 = OpAccessChain %v3i32outPtr %ssboOUT %zero %x %c_i32_5\n"
3275                 "OpStore %outP6 %inV6\n"
3276                 "\n"//strutOut.v4b16 = strutIn.v4b16
3277                 "%inP7  = OpAccessChain %v4i16${inPtr} %ssboIN %zero %x %c_i32_6\n"
3278                 "%inV7  = OpLoad %v4i16 %inP7\n"
3279                 "%outP7 = OpAccessChain %v4i16outPtr %ssboOUT %zero %x %c_i32_6\n"
3280                 "OpStore %outP7 %inV7\n"
3281                 "\n"//strutOut.v4b32 = strutIn.v4b32
3282                 "%inP8  = OpAccessChain %v4i32${inPtr} %ssboIN %zero %x %c_i32_7\n"
3283                 "%inV8  = OpLoad %v4i32 %inP8\n"
3284                 "%outP8 = OpAccessChain %v4i32outPtr %ssboOUT %zero %x %c_i32_7\n"
3285                 "OpStore %outP8 %inV8\n"
3286                 "\n"//strutOut.b16[y] = strutIn.b16[y]
3287                 "%inP9  = OpAccessChain %i16${inPtr} %ssboIN %zero %x %c_i32_9 %y\n"
3288                 "%inV9  = OpLoad %i16 %inP9\n"
3289                 "%outP9 = OpAccessChain %i16outPtr %ssboOUT %zero %x %c_i32_9 %y\n"
3290                 "OpStore %outP9 %inV9\n"
3291                 "\n"//strutOut.b32[y] = strutIn.b32[y]
3292                 "%inP10  = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_10 %y\n"
3293                 "%inV10  = OpLoad %i32 %inP10\n"
3294                 "%outP10 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_10 %y\n"
3295                 "OpStore %outP10 %inV10\n"
3296                 "\n"//strutOut.strutNestedOut[y].b16 = strutIn.strutNestedIn[y].b16
3297                 "%inP11 = OpAccessChain %i16${inPtr} %ssboIN %zero %x %c_i32_8 %y %zero\n"
3298                 "%inV11 = OpLoad %i16 %inP11\n"
3299                 "%outP11 = OpAccessChain %i16outPtr %ssboOUT %zero %x %c_i32_8 %y %zero\n"
3300                 "OpStore %outP11 %inV11\n"
3301                 "\n"//strutOut.strutNestedOut[y].b32 = strutIn.strutNestedIn[y].b32
3302                 "%inP12 = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_1\n"
3303                 "%inV12 = OpLoad %i32 %inP12\n"
3304                 "%outP12 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_1\n"
3305                 "OpStore %outP12 %inV12\n"
3306                 "\n"
3307                 "${zBeginLoop}"
3308                 "\n"//strutOut.strutNestedOut[y].v2b16[valNdx] = strutIn.strutNestedIn[y].v2b16[valNdx]
3309                 "%inP13  = OpAccessChain %v2i16${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_2 %Valz\n"
3310                 "%inV13  = OpLoad %v2i16 %inP13\n"
3311                 "%outP13 = OpAccessChain %v2i16outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_2 %Valz\n"
3312                 "OpStore %outP13 %inV13\n"
3313                 "\n"//strutOut.strutNestedOut[y].b32[valNdx] = strutIn.strutNestedIn[y].b32[valNdx]
3314                 "%inP14  = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_3 %Valz\n"
3315                 "%inV14  = OpLoad %i32 %inP14\n"
3316                 "%outP14 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_3 %Valz\n"
3317                 "OpStore %outP14 %inV14\n"
3318                 "\n${zEndLoop}\n"
3319                 "OpBranch %exitLabel\n"
3320                 "%exitLabel = OpLabel\n"
3321                 "OpReturn\n"
3322                 "OpFunctionEnd\n");
3323
3324         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3325         {  // int
3326                 const bool                              isUniform       = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == CAPABILITIES[capIdx].dtype;
3327                 vector<deInt16>                 inData          = isUniform ? dataMixStd140(rnd) : dataMixStd430(rnd);
3328                 ComputeShaderSpec               spec;
3329                 map<string, string>             specsOffset;
3330                 map<string, string>             specsLoop;
3331                 map<string, string>             specs;
3332                 string                                  testName        = string(CAPABILITIES[capIdx].name);
3333
3334                 specsLoop["exeCount"]   = "c_i32_11";
3335                 specsLoop["loopName"]   = "z";
3336                 specs["zBeginLoop"]             = beginLoop(specsLoop);
3337                 specs["zEndLoop"]               = endLoop(specsLoop);
3338                 specs["capability"]             = isUniform ? "OpCapability " + string(CAPABILITIES[capIdx].cap) : " ";
3339                 specs["inPtr"]                  = "outPtr";
3340                 specs["storage"]                = isUniform ? "Block" : "BufferBlock";
3341                 specsOffset["InOut"]    = "In";
3342                 specs["InOffsets"]              = StringTemplate(isUniform ? getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD140) : getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
3343                 specsOffset["InOut"]    = "Out";
3344                 specs["OutOffsets"]             = StringTemplate(getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
3345
3346                 spec.assembly                                   = shaderTemplate.specialize(specs);
3347                 spec.numWorkGroups                              = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
3348                 spec.verifyIO                                   = isUniform ? computeCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD140, SHADERTEMPLATE_STRIDEMIX_STD430> : computeCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD430, SHADERTEMPLATE_STRIDEMIX_STD430>;
3349                 spec.inputs.push_back                   (Resource(BufferSp(new Int16Buffer(inData)), CAPABILITIES[capIdx].dtype));
3350                 spec.outputs.push_back                  (Resource(BufferSp(new Int16Buffer(outData))));
3351                 spec.extensions.push_back               ("VK_KHR_16bit_storage");
3352                 spec.requestedVulkanFeatures    = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3353
3354                 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
3355         }
3356 }
3357
3358 void addGraphics16BitStorageUniformFloat32To16Group (tcu::TestCaseGroup* testGroup)
3359 {
3360         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
3361         map<string, string>                                     fragments;
3362         vector<string>                                          extensions;
3363         const deUint32                                          numDataPoints           = 256;
3364         RGBA                                                            defaultColors[4];
3365         const vector<float>                                     float32Data                     = getFloat32s(rnd, numDataPoints);
3366         vector<float>                                           float32DataPadded;
3367         vector<deFloat16>                                       float16DummyData        (numDataPoints, 0);
3368         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
3369
3370         for (size_t dataIdx = 0; dataIdx < float32Data.size(); ++dataIdx)
3371         {
3372                 float32DataPadded.push_back(float32Data[dataIdx]);
3373                 float32DataPadded.push_back(0.0f);
3374                 float32DataPadded.push_back(0.0f);
3375                 float32DataPadded.push_back(0.0f);
3376         }
3377
3378         extensions.push_back("VK_KHR_16bit_storage");
3379         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
3380
3381         struct RndMode
3382         {
3383                 const char*                             name;
3384                 const char*                             decor;
3385                 VerifyIOFunc                    f;
3386         };
3387
3388         getDefaultColors(defaultColors);
3389
3390         {  // scalar cases
3391                 fragments["pre_main"]                           =
3392                         "      %f16 = OpTypeFloat 16\n"
3393                         "%c_i32_256 = OpConstant %i32 256\n"
3394                         "   %up_f32 = OpTypePointer Uniform %f32\n"
3395                         "   %up_f16 = OpTypePointer Uniform %f16\n"
3396                         "   %ra_f32 = OpTypeArray %f32 %c_i32_256\n"
3397                         "   %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
3398                         "   %SSBO32 = OpTypeStruct %ra_f32\n"
3399                         "   %SSBO16 = OpTypeStruct %ra_f16\n"
3400                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3401                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3402                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3403                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3404
3405                 const StringTemplate decoration         (
3406                         "OpDecorate %ra_f32 ArrayStride ${arraystride}\n"
3407                         "OpDecorate %ra_f16 ArrayStride 2\n"
3408                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
3409                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
3410                         "OpDecorate %SSBO32 ${indecor}\n"
3411                         "OpDecorate %SSBO16 BufferBlock\n"
3412                         "OpDecorate %ssbo32 DescriptorSet 0\n"
3413                         "OpDecorate %ssbo16 DescriptorSet 0\n"
3414                         "OpDecorate %ssbo32 Binding 0\n"
3415                         "OpDecorate %ssbo16 Binding 1\n"
3416                         "${rounddecor}\n");
3417
3418                 fragments["testfun"]                            =
3419                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3420                         "    %param = OpFunctionParameter %v4f32\n"
3421
3422                         "%entry = OpLabel\n"
3423                         "    %i = OpVariable %fp_i32 Function\n"
3424                         "         OpStore %i %c_i32_0\n"
3425                         "         OpBranch %loop\n"
3426
3427                         " %loop = OpLabel\n"
3428                         "   %15 = OpLoad %i32 %i\n"
3429                         "   %lt = OpSLessThan %bool %15 %c_i32_256\n"
3430                         "         OpLoopMerge %merge %inc None\n"
3431                         "         OpBranchConditional %lt %write %merge\n"
3432
3433                         "%write = OpLabel\n"
3434                         "   %30 = OpLoad %i32 %i\n"
3435                         "  %src = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n"
3436                         "%val32 = OpLoad %f32 %src\n"
3437                         "%val16 = OpFConvert %f16 %val32\n"
3438                         "  %dst = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n"
3439                         "         OpStore %dst %val16\n"
3440                         "         OpBranch %inc\n"
3441
3442                         "  %inc = OpLabel\n"
3443                         "   %37 = OpLoad %i32 %i\n"
3444                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
3445                         "         OpStore %i %39\n"
3446                         "         OpBranch %loop\n"
3447
3448                         "%merge = OpLabel\n"
3449                         "         OpReturnValue %param\n"
3450
3451                         "OpFunctionEnd\n";
3452
3453                 const RndMode   rndModes[]                      =
3454                 {
3455                         {"rtz",                                         "OpDecorate %val16  FPRoundingMode RTZ",        graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3456                         {"rte",                                         "OpDecorate %val16  FPRoundingMode RTE",        graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3457                         {"unspecified_rnd_mode",        "",                                                                                     graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3458                 };
3459
3460                 const deUint32  arrayStrides[]          = {4, 16};
3461
3462                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3463                         for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3464                         {
3465                                 map<string, string>     specs;
3466                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_scalar_float_" + rndModes[rndModeIdx].name;
3467
3468                                 GraphicsResources       resources;
3469                                 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(arrayStrides[capIdx] == 4 ? float32Data : float32DataPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3470                                 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
3471                                 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16DummyData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3472
3473                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
3474                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
3475                                 specs["arraystride"]                    = de::toString(arrayStrides[capIdx]);
3476                                 specs["rounddecor"]                             = rndModes[rndModeIdx].decor;
3477
3478                                 fragments["capability"]                 = capabilities.specialize(specs);
3479                                 fragments["decoration"]                 = decoration.specialize(specs);
3480
3481                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3482                                 resources.verifyIO                              = rndModes[rndModeIdx].f;
3483                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
3484                         }
3485         }
3486
3487         // Non-scalar cases can use the same resources.
3488         GraphicsResources       resources;
3489         resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3490         // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
3491         resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16DummyData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3492
3493         {  // vector cases
3494                 fragments["pre_main"]                           =
3495                         "      %f16 = OpTypeFloat 16\n"
3496                         " %c_i32_64 = OpConstant %i32 64\n"
3497                         "        %v4f16 = OpTypeVector %f16 4\n"
3498                         " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
3499                         " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
3500                         " %ra_v4f32 = OpTypeArray %v4f32 %c_i32_64\n"
3501                         " %ra_v4f16 = OpTypeArray %v4f16 %c_i32_64\n"
3502                         "   %SSBO32 = OpTypeStruct %ra_v4f32\n"
3503                         "   %SSBO16 = OpTypeStruct %ra_v4f16\n"
3504                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3505                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3506                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3507                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3508
3509                 const StringTemplate decoration         (
3510                         "OpDecorate %ra_v4f32 ArrayStride 16\n"
3511                         "OpDecorate %ra_v4f16 ArrayStride 8\n"
3512                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
3513                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
3514                         "OpDecorate %SSBO32 ${indecor}\n"
3515                         "OpDecorate %SSBO16 BufferBlock\n"
3516                         "OpDecorate %ssbo32 DescriptorSet 0\n"
3517                         "OpDecorate %ssbo16 DescriptorSet 0\n"
3518                         "OpDecorate %ssbo32 Binding 0\n"
3519                         "OpDecorate %ssbo16 Binding 1\n"
3520                         "${rounddecor}\n");
3521
3522                 // ssbo16[] <- convert ssbo32[] to 16bit float
3523                 fragments["testfun"]                            =
3524                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3525                         "    %param = OpFunctionParameter %v4f32\n"
3526
3527                         "%entry = OpLabel\n"
3528                         "    %i = OpVariable %fp_i32 Function\n"
3529                         "         OpStore %i %c_i32_0\n"
3530                         "         OpBranch %loop\n"
3531
3532                         " %loop = OpLabel\n"
3533                         "   %15 = OpLoad %i32 %i\n"
3534                         "   %lt = OpSLessThan %bool %15 %c_i32_64\n"
3535                         "         OpLoopMerge %merge %inc None\n"
3536                         "         OpBranchConditional %lt %write %merge\n"
3537
3538                         "%write = OpLabel\n"
3539                         "   %30 = OpLoad %i32 %i\n"
3540                         "  %src = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30\n"
3541                         "%val32 = OpLoad %v4f32 %src\n"
3542                         "%val16 = OpFConvert %v4f16 %val32\n"
3543                         "  %dst = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30\n"
3544                         "         OpStore %dst %val16\n"
3545                         "         OpBranch %inc\n"
3546
3547                         "  %inc = OpLabel\n"
3548                         "   %37 = OpLoad %i32 %i\n"
3549                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
3550                         "         OpStore %i %39\n"
3551                         "         OpBranch %loop\n"
3552
3553                         "%merge = OpLabel\n"
3554                         "         OpReturnValue %param\n"
3555
3556                         "OpFunctionEnd\n";
3557
3558                 const RndMode   rndModes[] =
3559                 {
3560                         {"rtz",                                         "OpDecorate %val16  FPRoundingMode RTZ",        graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3561                         {"rte",                                         "OpDecorate %val16  FPRoundingMode RTE",        graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3562                         {"unspecified_rnd_mode",        "",                                                                                     graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3563                 };
3564
3565                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3566                         for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3567                         {
3568                                 map<string, string>     specs;
3569                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_vector_float_" + rndModes[rndModeIdx].name;
3570
3571                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
3572                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
3573                                 specs["rounddecor"]                             = rndModes[rndModeIdx].decor;
3574
3575                                 fragments["capability"]                 = capabilities.specialize(specs);
3576                                 fragments["decoration"]                 = decoration.specialize(specs);
3577
3578                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3579                                 resources.verifyIO                              = rndModes[rndModeIdx].f;
3580
3581
3582                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
3583                         }
3584         }
3585
3586         {  // matrix cases
3587                 fragments["pre_main"]                           =
3588                         "       %f16 = OpTypeFloat 16\n"
3589                         "  %c_i32_16 = OpConstant %i32 16\n"
3590                         "     %v4f16 = OpTypeVector %f16 4\n"
3591                         "   %m4x4f32 = OpTypeMatrix %v4f32 4\n"
3592                         "   %m4x4f16 = OpTypeMatrix %v4f16 4\n"
3593                         "  %up_v4f32 = OpTypePointer Uniform %v4f32\n"
3594                         "  %up_v4f16 = OpTypePointer Uniform %v4f16\n"
3595                         "%a16m4x4f32 = OpTypeArray %m4x4f32 %c_i32_16\n"
3596                         "%a16m4x4f16 = OpTypeArray %m4x4f16 %c_i32_16\n"
3597                         "    %SSBO32 = OpTypeStruct %a16m4x4f32\n"
3598                         "    %SSBO16 = OpTypeStruct %a16m4x4f16\n"
3599                         " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3600                         " %up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3601                         "    %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3602                         "    %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3603
3604                 const StringTemplate decoration         (
3605                         "OpDecorate %a16m4x4f32 ArrayStride 64\n"
3606                         "OpDecorate %a16m4x4f16 ArrayStride 32\n"
3607                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
3608                         "OpMemberDecorate %SSBO32 0 ColMajor\n"
3609                         "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
3610                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
3611                         "OpMemberDecorate %SSBO16 0 ColMajor\n"
3612                         "OpMemberDecorate %SSBO16 0 MatrixStride 8\n"
3613                         "OpDecorate %SSBO32 ${indecor}\n"
3614                         "OpDecorate %SSBO16 BufferBlock\n"
3615                         "OpDecorate %ssbo32 DescriptorSet 0\n"
3616                         "OpDecorate %ssbo16 DescriptorSet 0\n"
3617                         "OpDecorate %ssbo32 Binding 0\n"
3618                         "OpDecorate %ssbo16 Binding 1\n"
3619                         "${rounddecor}\n");
3620
3621                 fragments["testfun"]                            =
3622                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3623                         "    %param = OpFunctionParameter %v4f32\n"
3624
3625                         "%entry = OpLabel\n"
3626                         "    %i = OpVariable %fp_i32 Function\n"
3627                         "         OpStore %i %c_i32_0\n"
3628                         "         OpBranch %loop\n"
3629
3630                         " %loop = OpLabel\n"
3631                         "   %15 = OpLoad %i32 %i\n"
3632                         "   %lt = OpSLessThan %bool %15 %c_i32_16\n"
3633                         "         OpLoopMerge %merge %inc None\n"
3634                         "         OpBranchConditional %lt %write %merge\n"
3635
3636                         "  %write = OpLabel\n"
3637                         "     %30 = OpLoad %i32 %i\n"
3638                         "  %src_0 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n"
3639                         "  %src_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
3640                         "  %src_2 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n"
3641                         "  %src_3 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n"
3642                         "%val32_0 = OpLoad %v4f32 %src_0\n"
3643                         "%val32_1 = OpLoad %v4f32 %src_1\n"
3644                         "%val32_2 = OpLoad %v4f32 %src_2\n"
3645                         "%val32_3 = OpLoad %v4f32 %src_3\n"
3646                         "%val16_0 = OpFConvert %v4f16 %val32_0\n"
3647                         "%val16_1 = OpFConvert %v4f16 %val32_1\n"
3648                         "%val16_2 = OpFConvert %v4f16 %val32_2\n"
3649                         "%val16_3 = OpFConvert %v4f16 %val32_3\n"
3650                         "  %dst_0 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
3651                         "  %dst_1 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
3652                         "  %dst_2 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
3653                         "  %dst_3 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
3654                         "           OpStore %dst_0 %val16_0\n"
3655                         "           OpStore %dst_1 %val16_1\n"
3656                         "           OpStore %dst_2 %val16_2\n"
3657                         "           OpStore %dst_3 %val16_3\n"
3658                         "           OpBranch %inc\n"
3659
3660                         "  %inc = OpLabel\n"
3661                         "   %37 = OpLoad %i32 %i\n"
3662                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
3663                         "         OpStore %i %39\n"
3664                         "         OpBranch %loop\n"
3665
3666                         "%merge = OpLabel\n"
3667                         "         OpReturnValue %param\n"
3668
3669                         "OpFunctionEnd\n";
3670
3671                 const RndMode   rndModes[] =
3672                 {
3673                         {"rte",                                         "OpDecorate %val16_0  FPRoundingMode RTE\nOpDecorate %val16_1  FPRoundingMode RTE\nOpDecorate %val16_2  FPRoundingMode RTE\nOpDecorate %val16_3  FPRoundingMode RTE",   graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3674                         {"rtz",                                         "OpDecorate %val16_0  FPRoundingMode RTZ\nOpDecorate %val16_1  FPRoundingMode RTZ\nOpDecorate %val16_2  FPRoundingMode RTZ\nOpDecorate %val16_3  FPRoundingMode RTZ",   graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3675                         {"unspecified_rnd_mode",        "",                                                                                                                                                                                                                                                                                                                                             graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3676                 };
3677
3678                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3679                         for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3680                         {
3681                                 map<string, string>     specs;
3682                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_matrix_float_" + rndModes[rndModeIdx].name;
3683
3684                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
3685                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
3686                                 specs["rounddecor"]                             = rndModes[rndModeIdx].decor;
3687
3688                                 fragments["capability"]                 = capabilities.specialize(specs);
3689                                 fragments["decoration"]                 = decoration.specialize(specs);
3690
3691                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3692                                 resources.verifyIO                              = rndModes[rndModeIdx].f;
3693
3694
3695                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
3696                         }
3697         }
3698 }
3699
3700 void addGraphics16BitStorageInputOutputFloat32To16Group (tcu::TestCaseGroup* testGroup)
3701 {
3702         de::Random                      rnd                                     (deStringHash(testGroup->getName()));
3703         RGBA                            defaultColors[4];
3704         vector<string>          extensions;
3705         map<string, string>     fragments                       = passthruFragments();
3706         const deUint32          numDataPoints           = 64;
3707         vector<float>           float32Data                     = getFloat32s(rnd, numDataPoints);
3708
3709         extensions.push_back("VK_KHR_16bit_storage");
3710
3711         fragments["capability"]                         = "OpCapability StorageInputOutput16\n";
3712         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3713
3714         getDefaultColors(defaultColors);
3715
3716         struct RndMode
3717         {
3718                 const char*                             name;
3719                 const char*                             decor;
3720                 const char*                             decor_tessc;
3721                 RoundingModeFlags               flags;
3722         };
3723
3724         const RndMode           rndModes[]              =
3725         {
3726                 {"rtz",
3727                  "OpDecorate %ret0  FPRoundingMode RTZ\n",
3728                  "OpDecorate %ret1  FPRoundingMode RTZ\n"
3729                  "OpDecorate %ret2  FPRoundingMode RTZ\n",
3730                  ROUNDINGMODE_RTZ},
3731                 {"rte",
3732                  "OpDecorate %ret0  FPRoundingMode RTE\n",
3733                  "OpDecorate %ret1  FPRoundingMode RTE\n"
3734                  "OpDecorate %ret2  FPRoundingMode RTE\n",
3735                   ROUNDINGMODE_RTE},
3736                 {"unspecified_rnd_mode",        "",             "",                     RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)},
3737         };
3738
3739         struct Case
3740         {
3741                 const char*     name;
3742                 const char*     interfaceOpFunc;
3743                 const char* postInterfaceOp;
3744                 const char* postInterfaceOpGeom;
3745                 const char* postInterfaceOpTessc;
3746                 const char*     preMain;
3747                 const char*     inputType;
3748                 const char*     outputType;
3749                 deUint32        numPerCase;
3750                 deUint32        numElements;
3751         };
3752
3753         const Case      cases[]         =
3754         {
3755                 { // Scalar cases
3756                         "scalar",
3757                   // Passthrough interface_op_func
3758                         "%interface_op_func = OpFunction %f16 None %f16_f32_function\n"
3759                         "        %io_param1 = OpFunctionParameter %f32\n"
3760                         "            %entry = OpLabel\n"
3761                         "                     OpReturnValue %f16_0\n"
3762                         "                     OpFunctionEnd\n",
3763
3764                         "             %ret0 = OpFConvert %f16 %IF_input_val\n"
3765                         "                OpStore %IF_output %ret0\n",
3766
3767                         "             %ret0 = OpFConvert %f16 %IF_input_val0\n"
3768                         "                OpStore %IF_output %ret0\n",
3769
3770                         "             %ret0 = OpFConvert %f16 %IF_input_val0\n"
3771                         "                OpStore %IF_output_ptr0 %ret0\n"
3772                         "             %ret1 = OpFConvert %f16 %IF_input_val1\n"
3773                         "                OpStore %IF_output_ptr1 %ret1\n"
3774                         "             %ret2 = OpFConvert %f16 %IF_input_val2\n"
3775                         "                OpStore %IF_output_ptr2 %ret2\n",
3776
3777                         "             %f16 = OpTypeFloat 16\n"
3778                         "          %op_f16 = OpTypePointer Output %f16\n"
3779                         "           %a3f16 = OpTypeArray %f16 %c_i32_3\n"
3780                         "        %op_a3f16 = OpTypePointer Output %a3f16\n"
3781                         "%f16_f32_function = OpTypeFunction %f16 %f32\n"
3782                         "           %a3f32 = OpTypeArray %f32 %c_i32_3\n"
3783                         "        %ip_a3f32 = OpTypePointer Input %a3f32\n"
3784                         "           %f16_0 = OpConstant %f16 0\n",
3785
3786                         "f32",
3787                         "f16",
3788                         4,
3789                         1,
3790                 },
3791                 { // Vector cases
3792                         "vector",
3793
3794                         "%interface_op_func = OpFunction %v2f16 None %v2f16_v2f32_function\n"
3795                         "        %io_param1 = OpFunctionParameter %v2f32\n"
3796                         "            %entry = OpLabel\n"
3797                         "                     OpReturnValue %v2f16_0\n"
3798                         "                     OpFunctionEnd\n",
3799
3800                         "             %ret0 = OpFConvert %v2f16 %IF_input_val\n"
3801                         "                OpStore %IF_output %ret0\n",
3802
3803                         "             %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
3804                         "                OpStore %IF_output %ret0\n",
3805
3806                         "             %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
3807                         "                OpStore %IF_output_ptr0 %ret0\n"
3808                         "             %ret1 = OpFConvert %v2f16 %IF_input_val1\n"
3809                         "                OpStore %IF_output_ptr1 %ret1\n"
3810                         "             %ret2 = OpFConvert %v2f16 %IF_input_val2\n"
3811                         "                OpStore %IF_output_ptr2 %ret2\n",
3812
3813                         "                 %f16 = OpTypeFloat 16\n"
3814                         "               %v2f16 = OpTypeVector %f16 2\n"
3815                         "            %op_v2f16 = OpTypePointer Output %v2f16\n"
3816                         "             %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
3817                         "          %op_a3v2f16 = OpTypePointer Output %a3v2f16\n"
3818                         "%v2f16_v2f32_function = OpTypeFunction %v2f16 %v2f32\n"
3819                         "             %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n"
3820                         "          %ip_a3v2f32 = OpTypePointer Input %a3v2f32\n"
3821                         "               %f16_0 = OpConstant %f16 0\n"
3822                         "             %v2f16_0 = OpConstantComposite %v2f16 %f16_0 %f16_0\n",
3823
3824                         "v2f32",
3825                         "v2f16",
3826                         2 * 4,
3827                         2,
3828                 }
3829         };
3830
3831         VulkanFeatures  requiredFeatures;
3832         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
3833
3834         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
3835                 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3836                 {
3837                         fragments["interface_op_func"]                  = cases[caseIdx].interfaceOpFunc;
3838                         fragments["post_interface_op_frag"]             = cases[caseIdx].postInterfaceOp;
3839                         fragments["post_interface_op_vert"]             = cases[caseIdx].postInterfaceOp;
3840                         fragments["post_interface_op_geom"]             = cases[caseIdx].postInterfaceOpGeom;
3841                         fragments["post_interface_op_tesse"]    = cases[caseIdx].postInterfaceOpGeom;
3842                         fragments["post_interface_op_tessc"]    = cases[caseIdx].postInterfaceOpTessc;
3843                         fragments["pre_main"]                                   = cases[caseIdx].preMain;
3844                         fragments["decoration"]                                 = rndModes[rndModeIdx].decor;
3845                         fragments["decoration_tessc"]                   = rndModes[rndModeIdx].decor_tessc;
3846
3847                         fragments["input_type"]                                 = cases[caseIdx].inputType;
3848                         fragments["output_type"]                                = cases[caseIdx].outputType;
3849
3850                         GraphicsInterfaces      interfaces;
3851                         const deUint32          numPerCase      = cases[caseIdx].numPerCase;
3852                         vector<float>           subInputs       (numPerCase);
3853                         vector<deFloat16>       subOutputs      (numPerCase);
3854
3855                         // The pipeline need this to call compare16BitFloat() when checking the result.
3856                         interfaces.setRoundingMode(rndModes[rndModeIdx].flags);
3857
3858                         for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
3859                         {
3860                                 string          testName        = string(cases[caseIdx].name) + numberToString(caseNdx) + "_" + rndModes[rndModeIdx].name;
3861
3862                                 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
3863                                 {
3864                                         subInputs[numNdx]       = float32Data[caseNdx * numPerCase + numNdx];
3865                                         // We derive the expected result from inputs directly in the graphics pipeline.
3866                                         subOutputs[numNdx]      = 0;
3867                                 }
3868                                 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subInputs))),
3869                                                                                   std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs))));
3870                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
3871                         }
3872                 }
3873 }
3874
3875 void addGraphics16BitStorageInputOutputFloat16To32Group (tcu::TestCaseGroup* testGroup)
3876 {
3877         de::Random                              rnd                                     (deStringHash(testGroup->getName()));
3878         RGBA                                    defaultColors[4];
3879         vector<string>                  extensions;
3880         map<string, string>             fragments                       = passthruFragments();
3881         const deUint32                  numDataPoints           = 64;
3882         vector<deFloat16>               float16Data                     (getFloat16s(rnd, numDataPoints));
3883         vector<float>                   float32Data;
3884
3885         float32Data.reserve(numDataPoints);
3886         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
3887                 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
3888
3889         extensions.push_back("VK_KHR_16bit_storage");
3890
3891         fragments["capability"]                         = "OpCapability StorageInputOutput16\n";
3892         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3893
3894         getDefaultColors(defaultColors);
3895
3896         struct Case
3897         {
3898                 const char*     name;
3899                 const char*     interfaceOpFunc;
3900                 const char*     preMain;
3901                 const char*     inputType;
3902                 const char*     outputType;
3903                 deUint32        numPerCase;
3904                 deUint32        numElements;
3905         };
3906
3907         Case    cases[]         =
3908         {
3909                 { // Scalar cases
3910                         "scalar",
3911
3912                         "%interface_op_func = OpFunction %f32 None %f32_f16_function\n"
3913                         "        %io_param1 = OpFunctionParameter %f16\n"
3914                         "            %entry = OpLabel\n"
3915                         "                          %ret = OpFConvert %f32 %io_param1\n"
3916                         "                     OpReturnValue %ret\n"
3917                         "                     OpFunctionEnd\n",
3918
3919                         "             %f16 = OpTypeFloat 16\n"
3920                         "          %ip_f16 = OpTypePointer Input %f16\n"
3921                         "           %a3f16 = OpTypeArray %f16 %c_i32_3\n"
3922                         "        %ip_a3f16 = OpTypePointer Input %a3f16\n"
3923                         "%f32_f16_function = OpTypeFunction %f32 %f16\n"
3924                         "           %a3f32 = OpTypeArray %f32 %c_i32_3\n"
3925                         "        %op_a3f32 = OpTypePointer Output %a3f32\n",
3926
3927                         "f16",
3928                         "f32",
3929                         4,
3930                         1,
3931                 },
3932                 { // Vector cases
3933                         "vector",
3934
3935                         "%interface_op_func = OpFunction %v2f32 None %v2f32_v2f16_function\n"
3936                         "        %io_param1 = OpFunctionParameter %v2f16\n"
3937                         "            %entry = OpLabel\n"
3938                         "                          %ret = OpFConvert %v2f32 %io_param1\n"
3939                         "                     OpReturnValue %ret\n"
3940                         "                     OpFunctionEnd\n",
3941
3942                         "                 %f16 = OpTypeFloat 16\n"
3943                         "                       %v2f16 = OpTypeVector %f16 2\n"
3944                         "            %ip_v2f16 = OpTypePointer Input %v2f16\n"
3945                         "             %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
3946                         "          %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
3947                         "%v2f32_v2f16_function = OpTypeFunction %v2f32 %v2f16\n"
3948                         "             %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n"
3949                         "          %op_a3v2f32 = OpTypePointer Output %a3v2f32\n",
3950
3951                         "v2f16",
3952                         "v2f32",
3953                         2 * 4,
3954                         2,
3955                 }
3956         };
3957
3958         VulkanFeatures  requiredFeatures;
3959         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
3960
3961         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
3962         {
3963                 fragments["interface_op_func"]  = cases[caseIdx].interfaceOpFunc;
3964                 fragments["pre_main"]                   = cases[caseIdx].preMain;
3965
3966                 fragments["input_type"]                 = cases[caseIdx].inputType;
3967                 fragments["output_type"]                = cases[caseIdx].outputType;
3968
3969                 GraphicsInterfaces      interfaces;
3970                 const deUint32          numPerCase      = cases[caseIdx].numPerCase;
3971                 vector<deFloat16>       subInputs       (numPerCase);
3972                 vector<float>           subOutputs      (numPerCase);
3973
3974                 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
3975                 {
3976                         string                  testName        = string(cases[caseIdx].name) + numberToString(caseNdx);
3977
3978                         for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
3979                         {
3980                                 subInputs[numNdx]       = float16Data[caseNdx * numPerCase + numNdx];
3981                                 subOutputs[numNdx]      = float32Data[caseNdx * numPerCase + numNdx];
3982                         }
3983                         interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))),
3984                                                                           std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subOutputs))));
3985                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
3986                 }
3987         }
3988 }
3989
3990 void addGraphics16BitStorageInputOutputFloat16To16Group (tcu::TestCaseGroup* testGroup)
3991 {
3992         de::Random                      rnd                                     (deStringHash(testGroup->getName()));
3993         RGBA                            defaultColors[4];
3994         vector<string>          extensions;
3995         map<string, string>     fragments                       = passthruFragments();
3996         const deUint32          numDataPoints           = 64;
3997         vector<deFloat16>       float16Data                     (getFloat16s(rnd, numDataPoints));
3998         VulkanFeatures          requiredFeatures;
3999
4000         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
4001         extensions.push_back("VK_KHR_16bit_storage");
4002
4003         fragments["capability"]                                 = "OpCapability StorageInputOutput16\n";
4004         fragments["extension"]                                  = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4005
4006         getDefaultColors(defaultColors);
4007
4008         struct Case
4009         {
4010                 const char*     name;
4011                 const char*     interfaceOpFunc;
4012                 const char*     preMain;
4013                 const char*     inputType;
4014                 const char*     outputType;
4015                 deUint32        numPerCase;
4016                 deUint32        numElements;
4017         };
4018
4019         Case                            cases[]                         =
4020         {
4021                 { // Scalar cases
4022                         "scalar",
4023
4024                         "%interface_op_func = OpFunction %f16 None %f16_f16_function\n"
4025                         "        %io_param1 = OpFunctionParameter %f16\n"
4026                         "            %entry = OpLabel\n"
4027                         "              %ret = OpCopyObject %f16 %io_param1\n"
4028                         "                     OpReturnValue %ret\n"
4029                         "                     OpFunctionEnd\n",
4030
4031                         "             %f16 = OpTypeFloat 16\n"
4032                         "          %ip_f16 = OpTypePointer Input %f16\n"
4033                         "           %a3f16 = OpTypeArray %f16 %c_i32_3\n"
4034                         "        %ip_a3f16 = OpTypePointer Input %a3f16\n"
4035                         "%f16_f16_function = OpTypeFunction %f16 %f16\n"
4036                         "          %op_f16 = OpTypePointer Output %f16\n"
4037                         "        %op_a3f16 = OpTypePointer Output %a3f16\n",
4038
4039                         "f16",
4040                         "f16",
4041                         4,
4042                         1,
4043                 },
4044                 { // Vector cases
4045                         "vector",
4046
4047                         "%interface_op_func = OpFunction %v2f16 None %v2f16_v2f16_function\n"
4048                         "        %io_param1 = OpFunctionParameter %v2f16\n"
4049                         "            %entry = OpLabel\n"
4050                         "              %ret = OpCopyObject %v2f16 %io_param1\n"
4051                         "                     OpReturnValue %ret\n"
4052                         "                     OpFunctionEnd\n",
4053
4054                         "                 %f16 = OpTypeFloat 16\n"
4055                         "               %v2f16 = OpTypeVector %f16 2\n"
4056                         "            %ip_v2f16 = OpTypePointer Input %v2f16\n"
4057                         "             %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
4058                         "          %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
4059                         "%v2f16_v2f16_function = OpTypeFunction %v2f16 %v2f16\n"
4060                         "            %op_v2f16 = OpTypePointer Output %v2f16\n"
4061                         "          %op_a3v2f16 = OpTypePointer Output %a3v2f16\n",
4062
4063                         "v2f16",
4064                         "v2f16",
4065                         2 * 4,
4066                         2,
4067                 }
4068         };
4069
4070         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4071         {
4072                 fragments["interface_op_func"]                  = cases[caseIdx].interfaceOpFunc;
4073                 fragments["pre_main"]                                   = cases[caseIdx].preMain;
4074
4075                 fragments["input_type"]                                 = cases[caseIdx].inputType;
4076                 fragments["output_type"]                                = cases[caseIdx].outputType;
4077
4078                 GraphicsInterfaces      interfaces;
4079                 const deUint32          numPerCase                      = cases[caseIdx].numPerCase;
4080                 vector<deFloat16>       subInputsOutputs        (numPerCase);
4081
4082                 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4083                 {
4084                         string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4085
4086                         for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4087                                 subInputsOutputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx];
4088
4089                         interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputsOutputs))),
4090                                                                           std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputsOutputs))));
4091
4092                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4093                 }
4094         }
4095 }
4096
4097 void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testGroup)
4098 {
4099         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
4100         RGBA                                                            defaultColors[4];
4101         vector<string>                                          extensions;
4102         map<string, string>                                     fragments                       = passthruFragments();
4103         const deUint32                                          numDataPoints           = 64;
4104         // inputs and outputs are declared to be vectors of signed integers.
4105         // However, depending on the test, they may be interpreted as unsiged
4106         // integers. That won't be a problem as long as we passed the bits
4107         // in faithfully to the pipeline.
4108         vector<deInt32>                                         inputs                          = getInt32s(rnd, numDataPoints);
4109         vector<deInt16>                                         outputs;
4110
4111         outputs.reserve(inputs.size());
4112         for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4113                 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx]));
4114
4115         extensions.push_back("VK_KHR_16bit_storage");
4116
4117         fragments["capability"]                         = "OpCapability StorageInputOutput16\n";
4118         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4119
4120         getDefaultColors(defaultColors);
4121
4122         const StringTemplate    scalarInterfaceOpFunc(
4123                         "%interface_op_func = OpFunction %${type16} None %${type16}_${type32}_function\n"
4124                         "        %io_param1 = OpFunctionParameter %${type32}\n"
4125                         "            %entry = OpLabel\n"
4126                         "                          %ret = ${convert} %${type16} %io_param1\n"
4127                         "                     OpReturnValue %ret\n"
4128                         "                     OpFunctionEnd\n");
4129
4130         const StringTemplate    scalarPreMain(
4131                         "             %${type16} = OpTypeInt 16 ${signed}\n"
4132                         "          %op_${type16} = OpTypePointer Output %${type16}\n"
4133                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4134                         "        %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4135                         "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4136                         "           %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4137                         "        %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4138
4139         const StringTemplate    vecInterfaceOpFunc(
4140                         "%interface_op_func = OpFunction %${type16} None %${type16}_${type32}_function\n"
4141                         "        %io_param1 = OpFunctionParameter %${type32}\n"
4142                         "            %entry = OpLabel\n"
4143                         "                          %ret = ${convert} %${type16} %io_param1\n"
4144                         "                     OpReturnValue %ret\n"
4145                         "                     OpFunctionEnd\n");
4146
4147         const StringTemplate    vecPreMain(
4148                         "                       %i16 = OpTypeInt 16 1\n"
4149                         "                       %u16 = OpTypeInt 16 0\n"
4150                         "                 %v4i16 = OpTypeVector %i16 4\n"
4151                         "                 %v4u16 = OpTypeVector %u16 4\n"
4152                         "          %op_${type16} = OpTypePointer Output %${type16}\n"
4153                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4154                         "        %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4155                         "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4156                         "           %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4157                         "        %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4158
4159         struct Case
4160         {
4161                 const char*                             name;
4162                 const StringTemplate&   interfaceOpFunc;
4163                 const StringTemplate&   preMain;
4164                 const char*                             type32;
4165                 const char*                             type16;
4166                 const char*                             sign;
4167                 const char*                             opcode;
4168                 deUint32                                numPerCase;
4169                 deUint32                                numElements;
4170         };
4171
4172         Case    cases[]         =
4173         {
4174                 {"scalar_sint", scalarInterfaceOpFunc,  scalarPreMain,  "i32",          "i16",          "1",    "OpSConvert",   4,              1},
4175                 {"scalar_uint", scalarInterfaceOpFunc,  scalarPreMain,  "u32",          "u16",          "0",    "OpUConvert",   4,              1},
4176                 {"vector_sint", vecInterfaceOpFunc,             vecPreMain,             "v4i32",        "v4i16",        "1",    "OpSConvert",   4 * 4,  4},
4177                 {"vector_uint", vecInterfaceOpFunc,             vecPreMain,             "v4u32",        "v4u16",        "0",    "OpUConvert",   4 * 4,  4},
4178         };
4179
4180         VulkanFeatures  requiredFeatures;
4181         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
4182
4183         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4184         {
4185                 map<string, string>                             specs;
4186
4187                 specs["type32"]                                 = cases[caseIdx].type32;
4188                 specs["type16"]                                 = cases[caseIdx].type16;
4189                 specs["signed"]                                 = cases[caseIdx].sign;
4190                 specs["convert"]                                = cases[caseIdx].opcode;
4191
4192                 fragments["pre_main"]                   = cases[caseIdx].preMain.specialize(specs);
4193                 fragments["interface_op_func"]  = cases[caseIdx].interfaceOpFunc.specialize(specs);
4194                 fragments["input_type"]                 = cases[caseIdx].type32;
4195                 fragments["output_type"]                = cases[caseIdx].type16;
4196
4197                 GraphicsInterfaces                              interfaces;
4198                 const deUint32                                  numPerCase      = cases[caseIdx].numPerCase;
4199                 vector<deInt32>                                 subInputs       (numPerCase);
4200                 vector<deInt16>                                 subOutputs      (numPerCase);
4201
4202                 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4203                 {
4204                         string                  testName        = string(cases[caseIdx].name) + numberToString(caseNdx);
4205
4206                         for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4207                         {
4208                                 subInputs[numNdx]       = inputs[caseNdx * numPerCase + numNdx];
4209                                 subOutputs[numNdx]      = outputs[caseNdx * numPerCase + numNdx];
4210                         }
4211                         if (strcmp(cases[caseIdx].sign, "1") == 0)
4212                         {
4213                                 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subInputs))),
4214                                                                                   std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subOutputs))));
4215                         }
4216                         else
4217                         {
4218                                 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subInputs))),
4219                                                                                   std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subOutputs))));
4220                         }
4221                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4222                 }
4223         }
4224 }
4225
4226 void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testGroup)
4227 {
4228         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
4229         RGBA                                                            defaultColors[4];
4230         vector<string>                                          extensions;
4231         map<string, string>                                     fragments                       = passthruFragments();
4232         const deUint32                                          numDataPoints           = 64;
4233         // inputs and outputs are declared to be vectors of signed integers.
4234         // However, depending on the test, they may be interpreted as unsiged
4235         // integers. That won't be a problem as long as we passed the bits
4236         // in faithfully to the pipeline.
4237         vector<deInt16>                                         inputs                          = getInt16s(rnd, numDataPoints);
4238         vector<deInt32>                                         sOutputs;
4239         vector<deInt32>                                         uOutputs;
4240         const deUint16                                          signBitMask                     = 0x8000;
4241         const deUint32                                          signExtendMask          = 0xffff0000;
4242
4243         sOutputs.reserve(inputs.size());
4244         uOutputs.reserve(inputs.size());
4245
4246         for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4247         {
4248                 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
4249                 if (inputs[numNdx] & signBitMask)
4250                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
4251                 else
4252                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
4253         }
4254
4255         extensions.push_back("VK_KHR_16bit_storage");
4256
4257         fragments["capability"]                         = "OpCapability StorageInputOutput16\n";
4258         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4259
4260         getDefaultColors(defaultColors);
4261
4262         const StringTemplate scalarIfOpFunc     (
4263                         "%interface_op_func = OpFunction %${type32} None %${type32}_${type16}_function\n"
4264                         "        %io_param1 = OpFunctionParameter %${type16}\n"
4265                         "            %entry = OpLabel\n"
4266                         "                          %ret = ${convert} %${type32} %io_param1\n"
4267                         "                     OpReturnValue %ret\n"
4268                         "                     OpFunctionEnd\n");
4269
4270         const StringTemplate scalarPreMain      (
4271                         "             %${type16} = OpTypeInt 16 ${signed}\n"
4272                         "          %ip_${type16} = OpTypePointer Input %${type16}\n"
4273                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4274                         "        %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4275                         "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4276                         "           %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4277                         "        %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4278
4279         const StringTemplate vecIfOpFunc        (
4280                         "%interface_op_func = OpFunction %${type32} None %${type32}_${type16}_function\n"
4281                         "        %io_param1 = OpFunctionParameter %${type16}\n"
4282                         "            %entry = OpLabel\n"
4283                         "                          %ret = ${convert} %${type32} %io_param1\n"
4284                         "                     OpReturnValue %ret\n"
4285                         "                     OpFunctionEnd\n");
4286
4287         const StringTemplate vecPreMain (
4288                         "                       %i16 = OpTypeInt 16 1\n"
4289                         "                       %u16 = OpTypeInt 16 0\n"
4290                         "                 %v4i16 = OpTypeVector %i16 4\n"
4291                         "                 %v4u16 = OpTypeVector %u16 4\n"
4292                         "          %ip_${type16} = OpTypePointer Input %${type16}\n"
4293                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4294                         "        %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4295                         "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4296                         "           %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4297                         "        %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4298
4299         struct Case
4300         {
4301                 const char*                             name;
4302                 const StringTemplate&   interfaceOpFunc;
4303                 const StringTemplate&   preMain;
4304                 const char*                             type32;
4305                 const char*                             type16;
4306                 const char*                             sign;
4307                 const char*                             opcode;
4308                 deUint32                                numPerCase;
4309                 deUint32                                numElements;
4310         };
4311
4312         Case    cases[]         =
4313         {
4314                 {"scalar_sint", scalarIfOpFunc, scalarPreMain,  "i32",          "i16",          "1",    "OpSConvert",   4,              1},
4315                 {"scalar_uint", scalarIfOpFunc, scalarPreMain,  "u32",          "u16",          "0",    "OpUConvert",   4,              1},
4316                 {"vector_sint", vecIfOpFunc,    vecPreMain,             "v4i32",        "v4i16",        "1",    "OpSConvert",   4 * 4,  4},
4317                 {"vector_uint", vecIfOpFunc,    vecPreMain,             "v4u32",        "v4u16",        "0",    "OpUConvert",   4 * 4,  4},
4318         };
4319
4320         VulkanFeatures  requiredFeatures;
4321         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
4322
4323         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4324         {
4325                 map<string, string>                             specs;
4326
4327                 specs["type32"]                                 = cases[caseIdx].type32;
4328                 specs["type16"]                                 = cases[caseIdx].type16;
4329                 specs["signed"]                                 = cases[caseIdx].sign;
4330                 specs["convert"]                                = cases[caseIdx].opcode;
4331
4332                 fragments["pre_main"]                   = cases[caseIdx].preMain.specialize(specs);
4333                 fragments["interface_op_func"]  = cases[caseIdx].interfaceOpFunc.specialize(specs);
4334                 fragments["input_type"]                 = cases[caseIdx].type16;
4335                 fragments["output_type"]                = cases[caseIdx].type32;
4336
4337                 GraphicsInterfaces                              interfaces;
4338                 const deUint32                                  numPerCase      = cases[caseIdx].numPerCase;
4339                 vector<deInt16>                                 subInputs       (numPerCase);
4340                 vector<deInt32>                                 subOutputs      (numPerCase);
4341
4342                 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4343                 {
4344                         string                  testName        = string(cases[caseIdx].name) + numberToString(caseNdx);
4345
4346                         for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4347                         {
4348                                 subInputs[numNdx]       = inputs[caseNdx * numPerCase + numNdx];
4349                                 if (cases[caseIdx].sign[0] == '1')
4350                                         subOutputs[numNdx]      = sOutputs[caseNdx * numPerCase + numNdx];
4351                                 else
4352                                         subOutputs[numNdx]      = uOutputs[caseNdx * numPerCase + numNdx];
4353                         }
4354                         if (strcmp(cases[caseIdx].sign, "1") == 0)
4355                         {
4356                                 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subInputs))),
4357                                                                                   std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subOutputs))));
4358                         }
4359                         else
4360                         {
4361                                 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subInputs))),
4362                                                                                   std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subOutputs))));
4363                         }
4364                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4365                 }
4366         }
4367 }
4368
4369 void addGraphics16BitStorageInputOutputInt16To16Group (tcu::TestCaseGroup* testGroup)
4370 {
4371         de::Random                              rnd                                     (deStringHash(testGroup->getName()));
4372         RGBA                                    defaultColors[4];
4373         vector<string>                  extensions;
4374         map<string, string>             fragments                       = passthruFragments();
4375         const deUint32                  numDataPoints           = 64;
4376         // inputs and outputs are declared to be vectors of signed integers.
4377         // However, depending on the test, they may be interpreted as unsiged
4378         // integers. That won't be a problem as long as we passed the bits
4379         // in faithfully to the pipeline.
4380         vector<deInt16>                 inputs                          = getInt16s(rnd, numDataPoints);
4381         VulkanFeatures                  requiredFeatures;
4382
4383         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
4384         extensions.push_back("VK_KHR_16bit_storage");
4385
4386         fragments["capability"]                                         = "OpCapability StorageInputOutput16\n";
4387         fragments["extension"]                                          = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4388
4389         getDefaultColors(defaultColors);
4390
4391         const StringTemplate    scalarIfOpFunc          (
4392                         "%interface_op_func = OpFunction %${type16} None %${type16}_${type16}_function\n"
4393                         "        %io_param1 = OpFunctionParameter %${type16}\n"
4394                         "            %entry = OpLabel\n"
4395                         "              %ret = OpCopyObject %${type16} %io_param1\n"
4396                         "                     OpReturnValue %ret\n"
4397                         "                     OpFunctionEnd\n");
4398
4399         const StringTemplate    scalarPreMain           (
4400                         "             %${type16} = OpTypeInt 16 ${signed}\n"
4401                         "          %ip_${type16} = OpTypePointer Input %${type16}\n"
4402                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4403                         "        %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4404                         "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4405                         "          %op_${type16} = OpTypePointer Output %${type16}\n"
4406                         "        %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4407
4408         const StringTemplate    vecIfOpFunc                     (
4409                         "%interface_op_func = OpFunction %${type16} None %${type16}_${type16}_function\n"
4410                         "        %io_param1 = OpFunctionParameter %${type16}\n"
4411                         "            %entry = OpLabel\n"
4412                         "              %ret = OpCopyObject %${type16} %io_param1\n"
4413                         "                     OpReturnValue %ret\n"
4414                         "                     OpFunctionEnd\n");
4415
4416         const StringTemplate    vecPreMain                      (
4417                         "                   %i16 = OpTypeInt 16 1\n"
4418                         "                   %u16 = OpTypeInt 16 0\n"
4419                         "                 %v4i16 = OpTypeVector %i16 4\n"
4420                         "                 %v4u16 = OpTypeVector %u16 4\n"
4421                         "          %ip_${type16} = OpTypePointer Input %${type16}\n"
4422                         "           %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4423                         "        %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4424                         "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4425                         "          %op_${type16} = OpTypePointer Output %${type16}\n"
4426                         "        %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4427
4428         struct Case
4429         {
4430                 const char*                             name;
4431                 const StringTemplate&   interfaceOpFunc;
4432                 const StringTemplate&   preMain;
4433                 const char*                             type16;
4434                 const char*                             sign;
4435                 deUint32                                numPerCase;
4436                 deUint32                                numElements;
4437         };
4438
4439         Case                                    cases[]                         =
4440         {
4441                 {"scalar_sint", scalarIfOpFunc, scalarPreMain,  "i16",          "1",    4,              1},
4442                 {"scalar_uint", scalarIfOpFunc, scalarPreMain,  "u16",          "0",    4,              1},
4443                 {"vector_sint", vecIfOpFunc,    vecPreMain,             "v4i16",        "1",    4 * 4,  4},
4444                 {"vector_uint", vecIfOpFunc,    vecPreMain,             "v4u16",        "0",    4 * 4,  4},
4445         };
4446
4447         for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4448         {
4449                 map<string, string>                             specs;
4450
4451                 specs["type16"]                                 = cases[caseIdx].type16;
4452                 specs["signed"]                                 = cases[caseIdx].sign;
4453
4454                 fragments["pre_main"]                   = cases[caseIdx].preMain.specialize(specs);
4455                 fragments["interface_op_func"]  = cases[caseIdx].interfaceOpFunc.specialize(specs);
4456                 fragments["input_type"]                 = cases[caseIdx].type16;
4457                 fragments["output_type"]                = cases[caseIdx].type16;
4458
4459                 GraphicsInterfaces                              interfaces;
4460                 const deUint32                                  numPerCase                      = cases[caseIdx].numPerCase;
4461                 vector<deInt16>                                 subInputsOutputs        (numPerCase);
4462                 const NumberType                                numberType                      = strcmp(cases[caseIdx].sign, "1") == 0 ? NUMBERTYPE_INT16 : NUMBERTYPE_UINT16;
4463
4464                 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4465                 {
4466                         string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4467
4468                         for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4469                                 subInputsOutputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4470
4471                         interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))),
4472                                                                           std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))));
4473
4474                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4475                 }
4476         }
4477 }
4478
4479 void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* testGroup)
4480 {
4481         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
4482         map<string, string>                                     fragments;
4483         RGBA                                                            defaultColors[4];
4484         vector<string>                                          extensions;
4485         GraphicsResources                                       resources;
4486         PushConstants                                           pcs;
4487         const deUint32                                          numDataPoints           = 64;
4488         vector<deFloat16>                                       float16Data                     (getFloat16s(rnd, numDataPoints));
4489         vector<float>                                           float32Data;
4490         VulkanFeatures                                          requiredFeatures;
4491
4492         struct ConstantIndex
4493         {
4494                 bool            useConstantIndex;
4495                 deUint32        constantIndex;
4496         };
4497
4498         ConstantIndex   constantIndices[] =
4499         {
4500                 { false,        0 },
4501                 { true,         4 },
4502                 { true,         5 },
4503                 { true,         6 }
4504         };
4505
4506         float32Data.reserve(numDataPoints);
4507         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4508                 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
4509
4510         extensions.push_back("VK_KHR_16bit_storage");
4511         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
4512
4513         fragments["capability"]                         = "OpCapability StoragePushConstant16\n";
4514         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"";
4515
4516         pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data)));
4517         resources.verifyIO = check32BitFloats;
4518
4519         getDefaultColors(defaultColors);
4520
4521         const StringTemplate    testFun         (
4522                 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
4523                 "    %param = OpFunctionParameter %v4f32\n"
4524
4525                 "%entry = OpLabel\n"
4526                 "    %i = OpVariable %fp_i32 Function\n"
4527                 "         OpStore %i %c_i32_0\n"
4528                 "         OpBranch %loop\n"
4529
4530                 " %loop = OpLabel\n"
4531                 "   %15 = OpLoad %i32 %i\n"
4532                 "   %lt = OpSLessThan %bool %15 ${count}\n"
4533                 "         OpLoopMerge %merge %inc None\n"
4534                 "         OpBranchConditional %lt %write %merge\n"
4535
4536                 "%write = OpLabel\n"
4537                 "   %30 = OpLoad %i32 %i\n"
4538                 "  %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %${arrayindex} ${index0:opt}\n"
4539                 "%val16 = OpLoad ${f_type16} %src\n"
4540                 "%val32 = OpFConvert ${f_type32} %val16\n"
4541                 "  %dst = OpAccessChain ${up_type32} %ssbo32 %c_i32_0 %30 ${index0:opt}\n"
4542                 "         OpStore %dst %val32\n"
4543
4544                 "${store:opt}\n"
4545
4546                 "         OpBranch %inc\n"
4547
4548                 "  %inc = OpLabel\n"
4549                 "   %37 = OpLoad %i32 %i\n"
4550                 "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
4551                 "         OpStore %i %39\n"
4552                 "         OpBranch %loop\n"
4553
4554                 "%merge = OpLabel\n"
4555                 "         OpReturnValue %param\n"
4556
4557                 "OpFunctionEnd\n");
4558
4559         {  // Scalar cases
4560                 const StringTemplate    preMain         (
4561                         "      %f16 = OpTypeFloat 16\n"
4562                         " %c_i32_64 = OpConstant %i32 64\n"
4563                         " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4564                         "  %a64f16 = OpTypeArray %f16 %c_i32_64\n"
4565                         "  %a64f32 = OpTypeArray %f32 %c_i32_64\n"
4566                         "   %pp_f16 = OpTypePointer PushConstant %f16\n"
4567                         "   %up_f32 = OpTypePointer Uniform %f32\n"
4568                         "   %SSBO32 = OpTypeStruct %a64f32\n"
4569                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4570                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4571                         "     %PC16 = OpTypeStruct %a64f16\n"
4572                         "  %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4573                         "     %pc16 = OpVariable %pp_PC16 PushConstant\n");
4574
4575                 fragments["decoration"]                         =
4576                         "OpDecorate %a64f16 ArrayStride 2\n"
4577                         "OpDecorate %a64f32 ArrayStride 4\n"
4578                         "OpDecorate %SSBO32 BufferBlock\n"
4579                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
4580                         "OpDecorate %PC16 BufferBlock\n"
4581                         "OpMemberDecorate %PC16 0 Offset 0\n"
4582                         "OpDecorate %ssbo32 DescriptorSet 0\n"
4583                         "OpDecorate %ssbo32 Binding 0\n";
4584
4585                 map<string, string>             specs;
4586
4587                 specs["count"]                  = "%c_i32_64";
4588                 specs["pp_type16"]              = "%pp_f16";
4589                 specs["f_type16"]               = "%f16";
4590                 specs["f_type32"]               = "%f32";
4591                 specs["up_type32"]              = "%up_f32";
4592
4593                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4594                 {
4595                         bool                    useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
4596                         deUint32                constIdx                = constantIndices[constIndexIdx].constantIndex;
4597                         string                  testName                = "scalar";
4598                         vector<float>   float32ConstIdxData;
4599
4600                         if (useConstIdx)
4601                         {
4602                                 float32ConstIdxData.reserve(numDataPoints);
4603
4604                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4605                                         float32ConstIdxData.push_back(float32Data[constIdx]);
4606                         }
4607
4608                         specs["constarrayidx"]  = de::toString(constIdx);
4609                         if (useConstIdx)
4610                                 specs["arrayindex"] = "c_i32_ci";
4611                         else
4612                                 specs["arrayindex"] = "30";
4613
4614                         resources.outputs.clear();
4615                         resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4616
4617                         fragments["pre_main"]           = preMain.specialize(specs);
4618                         fragments["testfun"]            = testFun.specialize(specs);
4619
4620                         if (useConstIdx)
4621                                 testName += string("_const_idx_") + de::toString(constIdx);
4622
4623                         createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4624                 }
4625         }
4626
4627         {  // Vector cases
4628                 const StringTemplate    preMain         (
4629                         "      %f16 = OpTypeFloat 16\n"
4630                         "    %v4f16 = OpTypeVector %f16 4\n"
4631                         " %c_i32_16 = OpConstant %i32 16\n"
4632                         " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4633                         " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n"
4634                         " %a16v4f32 = OpTypeArray %v4f32 %c_i32_16\n"
4635                         " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
4636                         " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
4637                         "   %SSBO32 = OpTypeStruct %a16v4f32\n"
4638                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4639                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4640                         "     %PC16 = OpTypeStruct %a16v4f16\n"
4641                         "  %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4642                         "     %pc16 = OpVariable %pp_PC16 PushConstant\n");
4643
4644                 fragments["decoration"]                         =
4645                         "OpDecorate %a16v4f16 ArrayStride 8\n"
4646                         "OpDecorate %a16v4f32 ArrayStride 16\n"
4647                         "OpDecorate %SSBO32 BufferBlock\n"
4648                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
4649                         "OpDecorate %PC16 BufferBlock\n"
4650                         "OpMemberDecorate %PC16 0 Offset 0\n"
4651                         "OpDecorate %ssbo32 DescriptorSet 0\n"
4652                         "OpDecorate %ssbo32 Binding 0\n";
4653
4654                 map<string, string>             specs;
4655
4656                 specs["count"]                  = "%c_i32_16";
4657                 specs["pp_type16"]              = "%pp_v4f16";
4658                 specs["f_type16"]               = "%v4f16";
4659                 specs["f_type32"]               = "%v4f32";
4660                 specs["up_type32"]              = "%up_v4f32";
4661
4662                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4663                 {
4664                         bool                    useConstIdx                     = constantIndices[constIndexIdx].useConstantIndex;
4665                         deUint32                constIdx                        = constantIndices[constIndexIdx].constantIndex;
4666                         string                  testName                        = "vector";
4667                         vector<float>   float32ConstIdxData;
4668
4669                         if (useConstIdx)
4670                         {
4671                                 float32ConstIdxData.reserve(numDataPoints);
4672
4673                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4674                                         float32ConstIdxData.push_back(float32Data[constIdx * 4 + numIdx % 4]);
4675                         }
4676
4677                         specs["constarrayidx"]  = de::toString(constIdx);
4678                         if (useConstIdx)
4679                                 specs["arrayindex"] = "c_i32_ci";
4680                         else
4681                                 specs["arrayindex"] = "30";
4682
4683                         resources.outputs.clear();
4684                         resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4685
4686                         fragments["pre_main"]   = preMain.specialize(specs);
4687                         fragments["testfun"]    = testFun.specialize(specs);
4688
4689                         if (useConstIdx)
4690                                 testName += string("_const_idx_") + de::toString(constIdx);
4691
4692                         createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4693                 }
4694         }
4695
4696         {  // Matrix cases
4697                 const StringTemplate    preMain         (
4698                         "   %c_i32_8 = OpConstant %i32 8\n"
4699                         "  %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4700                         "      %f16  = OpTypeFloat 16\n"
4701                         "    %v4f16  = OpTypeVector %f16 4\n"
4702                         "  %m2v4f16  = OpTypeMatrix %v4f16 2\n"
4703                         "  %m2v4f32  = OpTypeMatrix %v4f32 2\n"
4704                         " %a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n"
4705                         " %a8m2v4f32 = OpTypeArray %m2v4f32 %c_i32_8\n"
4706                         " %pp_v4f16  = OpTypePointer PushConstant %v4f16\n"
4707                         " %up_v4f32  = OpTypePointer Uniform %v4f32\n"
4708                         "   %SSBO32  = OpTypeStruct %a8m2v4f32\n"
4709                         "%up_SSBO32  = OpTypePointer Uniform %SSBO32\n"
4710                         "   %ssbo32  = OpVariable %up_SSBO32 Uniform\n"
4711                         "     %PC16  = OpTypeStruct %a8m2v4f16\n"
4712                         "  %pp_PC16  = OpTypePointer PushConstant %PC16\n"
4713                         "     %pc16  = OpVariable %pp_PC16 PushConstant\n");
4714
4715                 fragments["decoration"]                         =
4716                         "OpDecorate %a8m2v4f16 ArrayStride 16\n"
4717                         "OpDecorate %a8m2v4f32 ArrayStride 32\n"
4718                         "OpDecorate %SSBO32 BufferBlock\n"
4719                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
4720                         "OpMemberDecorate %SSBO32 0 ColMajor\n"
4721                         "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
4722                         "OpDecorate %PC16 BufferBlock\n"
4723                         "OpMemberDecorate %PC16 0 Offset 0\n"
4724                         "OpMemberDecorate %PC16 0 ColMajor\n"
4725                         "OpMemberDecorate %PC16 0 MatrixStride 8\n"
4726                         "OpDecorate %ssbo32 DescriptorSet 0\n"
4727                         "OpDecorate %ssbo32 Binding 0\n";
4728
4729                 map<string, string>             specs;
4730
4731                 specs["count"]                  = "%c_i32_8";
4732                 specs["pp_type16"]              = "%pp_v4f16";
4733                 specs["up_type32"]              = "%up_v4f32";
4734                 specs["f_type16"]               = "%v4f16";
4735                 specs["f_type32"]               = "%v4f32";
4736                 specs["index0"]                 = "%c_i32_0";
4737
4738                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4739                 {
4740                         bool                                    useConstIdx                     = constantIndices[constIndexIdx].useConstantIndex;
4741                         deUint32                                constIdx                        = constantIndices[constIndexIdx].constantIndex;
4742                         string                                  testName                        = "matrix";
4743                         vector<float>                   float32ConstIdxData;
4744                         const StringTemplate    store                           (
4745                                 "  %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %${arrayindex} %c_i32_1\n"
4746                                 "%val16_1 = OpLoad %v4f16 %src_1\n"
4747                                 "%val32_1 = OpFConvert %v4f32 %val16_1\n"
4748                                 "  %dst_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
4749                                 "           OpStore %dst_1 %val32_1\n");
4750
4751                         if (useConstIdx)
4752                         {
4753                                 float32ConstIdxData.reserve(numDataPoints);
4754
4755                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4756                                         float32ConstIdxData.push_back(float32Data[constIdx * 8 + numIdx % 8]);
4757                         }
4758
4759                         specs["constarrayidx"]  = de::toString(constIdx);
4760                         if (useConstIdx)
4761                                 specs["arrayindex"] = "c_i32_ci";
4762                         else
4763                                 specs["arrayindex"] = "30";
4764
4765                         specs["store"] = store.specialize(specs);
4766
4767                         resources.outputs.clear();
4768                         resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4769
4770                         fragments["pre_main"]           = preMain.specialize(specs);
4771                         fragments["testfun"]            = testFun.specialize(specs);
4772
4773                         if (useConstIdx)
4774                                 testName += string("_const_idx_") + de::toString(constIdx);
4775
4776                         createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4777                 }
4778         }
4779 }
4780
4781 void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* testGroup)
4782 {
4783         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
4784         map<string, string>                                     fragments;
4785         RGBA                                                            defaultColors[4];
4786         const deUint32                                          numDataPoints           = 64;
4787         vector<deInt16>                                         inputs                          = getInt16s(rnd, numDataPoints);
4788         vector<deInt32>                                         sOutputs;
4789         vector<deInt32>                                         uOutputs;
4790         PushConstants                                           pcs;
4791         GraphicsResources                                       resources;
4792         vector<string>                                          extensions;
4793         const deUint16                                          signBitMask                     = 0x8000;
4794         const deUint32                                          signExtendMask          = 0xffff0000;
4795         VulkanFeatures                                          requiredFeatures;
4796
4797         struct ConstantIndex
4798         {
4799                 bool            useConstantIndex;
4800                 deUint32        constantIndex;
4801         };
4802
4803         ConstantIndex   constantIndices[] =
4804         {
4805                 { false,        0 },
4806                 { true,         4 },
4807                 { true,         5 },
4808                 { true,         6 }
4809         };
4810
4811         sOutputs.reserve(inputs.size());
4812         uOutputs.reserve(inputs.size());
4813
4814         for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4815         {
4816                 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
4817                 if (inputs[numNdx] & signBitMask)
4818                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
4819                 else
4820                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
4821         }
4822
4823         extensions.push_back("VK_KHR_16bit_storage");
4824         requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
4825
4826         fragments["capability"]                         = "OpCapability StoragePushConstant16\n";
4827         fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"";
4828
4829         pcs.setPushConstant(BufferSp(new Int16Buffer(inputs)));
4830
4831         getDefaultColors(defaultColors);
4832
4833         const StringTemplate    testFun         (
4834                 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
4835                 "    %param = OpFunctionParameter %v4f32\n"
4836
4837                 "%entry = OpLabel\n"
4838                 "    %i = OpVariable %fp_i32 Function\n"
4839                 "         OpStore %i %c_i32_0\n"
4840                 "         OpBranch %loop\n"
4841
4842                 " %loop = OpLabel\n"
4843                 "   %15 = OpLoad %i32 %i\n"
4844                 "   %lt = OpSLessThan %bool %15 %c_i32_${count}\n"
4845                 "         OpLoopMerge %merge %inc None\n"
4846                 "         OpBranchConditional %lt %write %merge\n"
4847
4848                 "%write = OpLabel\n"
4849                 "   %30 = OpLoad %i32 %i\n"
4850                 "  %src = OpAccessChain %pp_${type16} %pc16 %c_i32_0 %${arrayindex}\n"
4851                 "%val16 = OpLoad %${type16} %src\n"
4852                 "%val32 = ${convert} %${type32} %val16\n"
4853                 "  %dst = OpAccessChain %up_${type32} %ssbo32 %c_i32_0 %30\n"
4854                 "         OpStore %dst %val32\n"
4855                 "         OpBranch %inc\n"
4856
4857                 "  %inc = OpLabel\n"
4858                 "   %37 = OpLoad %i32 %i\n"
4859                 "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
4860                 "         OpStore %i %39\n"
4861                 "         OpBranch %loop\n"
4862
4863                 "%merge = OpLabel\n"
4864                 "         OpReturnValue %param\n"
4865
4866                 "OpFunctionEnd\n");
4867
4868         {  // Scalar cases
4869                 const StringTemplate    preMain         (
4870                         "         %${type16} = OpTypeInt 16 ${signed}\n"
4871                         "    %c_i32_${count} = OpConstant %i32 ${count}\n"                                      // Should be the same as numDataPoints
4872                         "          %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4873                         "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
4874                         "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
4875                         "      %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
4876                         "      %up_${type32} = OpTypePointer Uniform      %${type32}\n"
4877                         "            %SSBO32 = OpTypeStruct %a${count}${type32}\n"
4878                         "         %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4879                         "            %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4880                         "              %PC16 = OpTypeStruct %a${count}${type16}\n"
4881                         "           %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4882                         "              %pc16 = OpVariable %pp_PC16 PushConstant\n");
4883
4884                 const StringTemplate    decoration      (
4885                         "OpDecorate %a${count}${type16} ArrayStride 2\n"
4886                         "OpDecorate %a${count}${type32} ArrayStride 4\n"
4887                         "OpDecorate %SSBO32 BufferBlock\n"
4888                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
4889                         "OpDecorate %PC16 BufferBlock\n"
4890                         "OpMemberDecorate %PC16 0 Offset 0\n"
4891                         "OpDecorate %ssbo32 DescriptorSet 0\n"
4892                         "OpDecorate %ssbo32 Binding 0\n");
4893
4894                 {  // signed int
4895                         map<string, string>             specs;
4896
4897                         specs["type16"]                 = "i16";
4898                         specs["type32"]                 = "i32";
4899                         specs["signed"]                 = "1";
4900                         specs["count"]                  = "64";
4901                         specs["convert"]                = "OpSConvert";
4902
4903                         for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4904                         {
4905                                 bool                    useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
4906                                 deUint32                constIdx                = constantIndices[constIndexIdx].constantIndex;
4907                                 string                  testName                = "sint_scalar";
4908                                 vector<deInt32> constIdxData;
4909
4910                                 if (useConstIdx)
4911                                 {
4912                                         constIdxData.reserve(numDataPoints);
4913
4914                                         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4915                                                 constIdxData.push_back(sOutputs[constIdx]);
4916                                 }
4917
4918                                 specs["constarrayidx"]  = de::toString(constIdx);
4919                                 if (useConstIdx)
4920                                         specs["arrayindex"] = "c_i32_ci";
4921                                 else
4922                                         specs["arrayindex"] = "30";
4923
4924                                 if (useConstIdx)
4925                                         testName += string("_const_idx_") + de::toString(constIdx);
4926
4927                                 resources.outputs.clear();
4928                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4929
4930                                 fragments["testfun"]    = testFun.specialize(specs);
4931                                 fragments["pre_main"]   = preMain.specialize(specs);
4932                                 fragments["decoration"] = decoration.specialize(specs);
4933
4934                                 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4935                         }
4936                 }
4937                 {  // unsigned int
4938                         map<string, string>             specs;
4939
4940                         specs["type16"]                 = "u16";
4941                         specs["type32"]                 = "u32";
4942                         specs["signed"]                 = "0";
4943                         specs["count"]                  = "64";
4944                         specs["convert"]                = "OpUConvert";
4945
4946                         for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4947                         {
4948                                 bool                    useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
4949                                 deUint32                constIdx                = constantIndices[constIndexIdx].constantIndex;
4950                                 string                  testName                = "uint_scalar";
4951                                 vector<deInt32> constIdxData;
4952
4953                                 if (useConstIdx)
4954                                 {
4955                                         constIdxData.reserve(numDataPoints);
4956
4957                                         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4958                                                 constIdxData.push_back(uOutputs[constIdx]);
4959                                 }
4960
4961                                 specs["constarrayidx"]  = de::toString(constIdx);
4962                                 if (useConstIdx)
4963                                         specs["arrayindex"] = "c_i32_ci";
4964                                 else
4965                                         specs["arrayindex"] = "30";
4966
4967                                 if (useConstIdx)
4968                                         testName += string("_const_idx_") + de::toString(constIdx);
4969
4970                                 resources.outputs.clear();
4971                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4972
4973                                 fragments["testfun"]    = testFun.specialize(specs);
4974                                 fragments["pre_main"]   = preMain.specialize(specs);
4975                                 fragments["decoration"] = decoration.specialize(specs);
4976
4977                                 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4978                         }
4979                 }
4980         }
4981
4982         {  // Vector cases
4983                 const StringTemplate    preMain         (
4984                         "    %${base_type16} = OpTypeInt 16 ${signed}\n"
4985                         "         %${type16} = OpTypeVector %${base_type16} 2\n"
4986                         "    %c_i32_${count} = OpConstant %i32 ${count}\n"
4987                         "          %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4988                         "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
4989                         "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
4990                         "      %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
4991                         "      %up_${type32} = OpTypePointer Uniform      %${type32}\n"
4992                         "            %SSBO32 = OpTypeStruct %a${count}${type32}\n"
4993                         "         %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4994                         "            %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4995                         "              %PC16 = OpTypeStruct %a${count}${type16}\n"
4996                         "           %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4997                         "              %pc16 = OpVariable %pp_PC16 PushConstant\n");
4998
4999                 const StringTemplate    decoration      (
5000                         "OpDecorate %a${count}${type16} ArrayStride 4\n"
5001                         "OpDecorate %a${count}${type32} ArrayStride 8\n"
5002                         "OpDecorate %SSBO32 BufferBlock\n"
5003                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5004                         "OpDecorate %PC16 BufferBlock\n"
5005                         "OpMemberDecorate %PC16 0 Offset 0\n"
5006                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5007                         "OpDecorate %ssbo32 Binding 0\n");
5008
5009                 {  // signed int
5010                         map<string, string>             specs;
5011
5012                         specs["base_type16"]    = "i16";
5013                         specs["type16"]                 = "v2i16";
5014                         specs["type32"]                 = "v2i32";
5015                         specs["signed"]                 = "1";
5016                         specs["count"]                  = "32";
5017                         specs["convert"]                = "OpSConvert";
5018
5019                         for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5020                         {
5021                                 bool                    useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
5022                                 deUint32                constIdx                = constantIndices[constIndexIdx].constantIndex;
5023                                 string                  testName                = "sint_vector";
5024                                 vector<deInt32> constIdxData;
5025
5026                                 if (useConstIdx)
5027                                 {
5028                                         constIdxData.reserve(numDataPoints);
5029
5030                                         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5031                                                 constIdxData.push_back(sOutputs[constIdx * 2 + numIdx % 2]);
5032                                 }
5033
5034                                 specs["constarrayidx"]  = de::toString(constIdx);
5035                                 if (useConstIdx)
5036                                         specs["arrayindex"] = "c_i32_ci";
5037                                 else
5038                                         specs["arrayindex"] = "30";
5039
5040                                 if (useConstIdx)
5041                                         testName += string("_const_idx_") + de::toString(constIdx);
5042
5043                                 resources.outputs.clear();
5044                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5045
5046                                 fragments["testfun"]    = testFun.specialize(specs);
5047                                 fragments["pre_main"]   = preMain.specialize(specs);
5048                                 fragments["decoration"] = decoration.specialize(specs);
5049
5050                                 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5051                         }
5052                 }
5053                 {  // unsigned int
5054                         map<string, string>             specs;
5055
5056                         specs["base_type16"]    = "u16";
5057                         specs["type16"]                 = "v2u16";
5058                         specs["type32"]                 = "v2u32";
5059                         specs["signed"]                 = "0";
5060                         specs["count"]                  = "32";
5061                         specs["convert"]                = "OpUConvert";
5062
5063                         for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5064                         {
5065                                 bool                    useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
5066                                 deUint32                constIdx                = constantIndices[constIndexIdx].constantIndex;
5067                                 string                  testName                = "uint_vector";
5068                                 vector<deInt32> constIdxData;
5069
5070                                 if (useConstIdx)
5071                                 {
5072                                         constIdxData.reserve(numDataPoints);
5073
5074                                         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5075                                                 constIdxData.push_back(uOutputs[constIdx * 2 + numIdx % 2]);
5076                                 }
5077
5078                                 specs["constarrayidx"]  = de::toString(constIdx);
5079                                 if (useConstIdx)
5080                                         specs["arrayindex"] = "c_i32_ci";
5081                                 else
5082                                         specs["arrayindex"] = "30";
5083
5084                                 if (useConstIdx)
5085                                         testName += string("_const_idx_") + de::toString(constIdx);
5086
5087                                 resources.outputs.clear();
5088                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5089
5090                                 fragments["testfun"]    = testFun.specialize(specs);
5091                                 fragments["pre_main"]   = preMain.specialize(specs);
5092                                 fragments["decoration"] = decoration.specialize(specs);
5093
5094                                 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5095                         }
5096                 }
5097         }
5098 }
5099
5100 void addGraphics16BitStorageUniformInt16To32Group (tcu::TestCaseGroup* testGroup)
5101 {
5102         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
5103         map<string, string>                                     fragments;
5104         const deUint32                                          numDataPoints           = 256;
5105         RGBA                                                            defaultColors[4];
5106         vector<deInt16>                                         inputs                          = getInt16s(rnd, numDataPoints);
5107         vector<deInt32>                                         sOutputs;
5108         vector<deInt32>                                         uOutputs;
5109         vector<string>                                          extensions;
5110         const deUint16                                          signBitMask                     = 0x8000;
5111         const deUint32                                          signExtendMask          = 0xffff0000;
5112         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
5113
5114         sOutputs.reserve(inputs.size());
5115         uOutputs.reserve(inputs.size());
5116
5117         for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
5118         {
5119                 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
5120                 if (inputs[numNdx] & signBitMask)
5121                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
5122                 else
5123                         sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
5124         }
5125
5126         extensions.push_back("VK_KHR_16bit_storage");
5127         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
5128
5129         getDefaultColors(defaultColors);
5130
5131         struct IntegerFacts
5132         {
5133                 const char*     name;
5134                 const char*     type32;
5135                 const char*     type16;
5136                 const char* opcode;
5137                 bool            isSigned;
5138         };
5139
5140         const IntegerFacts      intFacts[]      =
5141         {
5142                 {"sint",        "%i32",         "%i16",         "OpSConvert",   true},
5143                 {"uint",        "%u32",         "%u16",         "OpUConvert",   false},
5144         };
5145
5146         struct ConstantIndex
5147         {
5148                 bool            useConstantIndex;
5149                 deUint32        constantIndex;
5150         };
5151
5152         ConstantIndex   constantIndices[] =
5153         {
5154                 { false,        0 },
5155                 { true,         4 },
5156                 { true,         5 },
5157                 { true,         6 }
5158         };
5159
5160         const StringTemplate scalarPreMain              (
5161                         "${itype16} = OpTypeInt 16 ${signed}\n"
5162                         "%c_i32_256 = OpConstant %i32 256\n"
5163                         "%c_i32_ci  = OpConstant %i32 ${constarrayidx}\n"
5164                         "   %up_i32 = OpTypePointer Uniform ${itype32}\n"
5165                         "   %up_i16 = OpTypePointer Uniform ${itype16}\n"
5166                         "   %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n"
5167                         "   %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n"
5168                         "   %SSBO32 = OpTypeStruct %ra_i32\n"
5169                         "   %SSBO16 = OpTypeStruct %ra_i16\n"
5170                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5171                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5172                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5173                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5174
5175         const StringTemplate scalarDecoration           (
5176                         "OpDecorate %ra_i32 ArrayStride 4\n"
5177                         "OpDecorate %ra_i16 ArrayStride ${arraystride}\n"
5178                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5179                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
5180                         "OpDecorate %SSBO32 BufferBlock\n"
5181                         "OpDecorate %SSBO16 ${indecor}\n"
5182                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5183                         "OpDecorate %ssbo16 DescriptorSet 0\n"
5184                         "OpDecorate %ssbo32 Binding 1\n"
5185                         "OpDecorate %ssbo16 Binding 0\n");
5186
5187         const StringTemplate scalarTestFunc     (
5188                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5189                         "    %param = OpFunctionParameter %v4f32\n"
5190
5191                         "%entry = OpLabel\n"
5192                         "    %i = OpVariable %fp_i32 Function\n"
5193                         "         OpStore %i %c_i32_0\n"
5194                         "         OpBranch %loop\n"
5195
5196                         " %loop = OpLabel\n"
5197                         "   %15 = OpLoad %i32 %i\n"
5198                         "   %lt = OpSLessThan %bool %15 %c_i32_256\n"
5199                         "         OpLoopMerge %merge %inc None\n"
5200                         "         OpBranchConditional %lt %write %merge\n"
5201
5202                         "%write = OpLabel\n"
5203                         "   %30 = OpLoad %i32 %i\n"
5204                         "  %src = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5205                         "%val16 = OpLoad ${itype16} %src\n"
5206                         "%val32 = ${convert} ${itype32} %val16\n"
5207                         "  %dst = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n"
5208                         "         OpStore %dst %val32\n"
5209                         "         OpBranch %inc\n"
5210
5211                         "  %inc = OpLabel\n"
5212                         "   %37 = OpLoad %i32 %i\n"
5213                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
5214                         "         OpStore %i %39\n"
5215                         "         OpBranch %loop\n"
5216                         "%merge = OpLabel\n"
5217                         "         OpReturnValue %param\n"
5218
5219                         "OpFunctionEnd\n");
5220
5221         const StringTemplate vecPreMain         (
5222                         "${itype16} = OpTypeInt 16 ${signed}\n"
5223                         "%c_i32_128 = OpConstant %i32 128\n"
5224                         "%c_i32_ci  = OpConstant %i32 ${constarrayidx}\n"
5225                         "%v2itype16 = OpTypeVector ${itype16} 2\n"
5226                         " %up_v2i32 = OpTypePointer Uniform ${v2itype32}\n"
5227                         " %up_v2i16 = OpTypePointer Uniform %v2itype16\n"
5228                         " %ra_v2i32 = OpTypeArray ${v2itype32} %c_i32_128\n"
5229                         " %ra_v2i16 = OpTypeArray %v2itype16 %c_i32_128\n"
5230                         "   %SSBO32 = OpTypeStruct %ra_v2i32\n"
5231                         "   %SSBO16 = OpTypeStruct %ra_v2i16\n"
5232                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5233                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5234                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5235                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5236
5237         const StringTemplate vecDecoration              (
5238                         "OpDecorate %ra_v2i32 ArrayStride 8\n"
5239                         "OpDecorate %ra_v2i16 ArrayStride ${arraystride}\n"
5240                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5241                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
5242                         "OpDecorate %SSBO32 BufferBlock\n"
5243                         "OpDecorate %SSBO16 ${indecor}\n"
5244                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5245                         "OpDecorate %ssbo16 DescriptorSet 0\n"
5246                         "OpDecorate %ssbo32 Binding 1\n"
5247                         "OpDecorate %ssbo16 Binding 0\n");
5248
5249         const StringTemplate vecTestFunc                (
5250                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5251                         "    %param = OpFunctionParameter %v4f32\n"
5252
5253                         "%entry = OpLabel\n"
5254                         "    %i = OpVariable %fp_i32 Function\n"
5255                         "         OpStore %i %c_i32_0\n"
5256                         "         OpBranch %loop\n"
5257
5258                         " %loop = OpLabel\n"
5259                         "   %15 = OpLoad %i32 %i\n"
5260                         "   %lt = OpSLessThan %bool %15 %c_i32_128\n"
5261                         "         OpLoopMerge %merge %inc None\n"
5262                         "         OpBranchConditional %lt %write %merge\n"
5263
5264                         "%write = OpLabel\n"
5265                         "   %30 = OpLoad %i32 %i\n"
5266                         "  %src = OpAccessChain %up_v2i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5267                         "%val16 = OpLoad %v2itype16 %src\n"
5268                         "%val32 = ${convert} ${v2itype32} %val16\n"
5269                         "  %dst = OpAccessChain %up_v2i32 %ssbo32 %c_i32_0 %30\n"
5270                         "         OpStore %dst %val32\n"
5271                         "         OpBranch %inc\n"
5272
5273                         "  %inc = OpLabel\n"
5274                         "   %37 = OpLoad %i32 %i\n"
5275                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
5276                         "         OpStore %i %39\n"
5277                         "         OpBranch %loop\n"
5278                         "%merge = OpLabel\n"
5279                         "         OpReturnValue %param\n"
5280
5281                         "OpFunctionEnd\n");
5282
5283         struct Category
5284         {
5285                 const char*                             name;
5286                 const StringTemplate&   preMain;
5287                 const StringTemplate&   decoration;
5288                 const StringTemplate&   testFunction;
5289                 const deUint32                  numElements;
5290         };
5291
5292         const Category          categories[]            =
5293         {
5294                 {"scalar",      scalarPreMain,  scalarDecoration,       scalarTestFunc, 1},
5295                 {"vector",      vecPreMain,             vecDecoration,          vecTestFunc,    2},
5296         };
5297
5298         const deUint32          minArrayStride[]        = {2, 16};
5299
5300         for (deUint32 catIdx = 0; catIdx < DE_LENGTH_OF_ARRAY(categories); ++catIdx)
5301                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5302                         for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
5303                                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5304                                 {
5305                                         bool                            useConstIdx             = constantIndices[constIndexIdx].useConstantIndex;
5306                                         deUint32                        constIdx                = constantIndices[constIndexIdx].constantIndex;
5307                                         map<string, string>     specs;
5308                                         string                          name                    = string(CAPABILITIES[capIdx].name) + "_" + categories[catIdx].name + "_" + intFacts[factIdx].name;
5309                                         const deUint32          numElements             = categories[catIdx].numElements;
5310                                         const deUint32          arrayStride             = de::max(numElements * 2, minArrayStride[capIdx]);
5311
5312                                         specs["cap"]                                            = CAPABILITIES[capIdx].cap;
5313                                         specs["indecor"]                                        = CAPABILITIES[capIdx].decor;
5314                                         specs["arraystride"]                            = de::toString(arrayStride);
5315                                         specs["itype32"]                                        = intFacts[factIdx].type32;
5316                                         specs["v2itype32"]                                      = "%v2" + string(intFacts[factIdx].type32).substr(1);
5317                                         specs["v3itype32"]                                      = "%v3" + string(intFacts[factIdx].type32).substr(1);
5318                                         specs["itype16"]                                        = intFacts[factIdx].type16;
5319                                         if (intFacts[factIdx].isSigned)
5320                                                 specs["signed"]                                 = "1";
5321                                         else
5322                                                 specs["signed"]                                 = "0";
5323                                         specs["convert"]                                        = intFacts[factIdx].opcode;
5324                                         specs["constarrayidx"]                          = de::toString(constIdx);
5325                                         if (useConstIdx)
5326                                                 specs["arrayindex"] = "c_i32_ci";
5327                                         else
5328                                                 specs["arrayindex"] = "30";
5329
5330                                         fragments["pre_main"]                           = categories[catIdx].preMain.specialize(specs);
5331                                         fragments["testfun"]                            = categories[catIdx].testFunction.specialize(specs);
5332                                         fragments["capability"]                         = capabilities.specialize(specs);
5333                                         fragments["decoration"]                         = categories[catIdx].decoration.specialize(specs);
5334
5335                                         GraphicsResources       resources;
5336                                         vector<deInt16>         inputsPadded;
5337                                         for (size_t dataIdx = 0; dataIdx < inputs.size() / numElements; ++dataIdx)
5338                                         {
5339                                                 for (deUint32 elementIdx = 0; elementIdx < numElements; ++elementIdx)
5340                                                         inputsPadded.push_back(inputs[dataIdx * numElements + elementIdx]);
5341                                                 for (deUint32 padIdx = 0; padIdx < arrayStride / 2 - numElements; ++padIdx)
5342                                                         inputsPadded.push_back(0);
5343                                         }
5344
5345                                         resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputsPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5346
5347                                         vector<deInt32>         constIdxOutputs;
5348                                         if (useConstIdx)
5349                                         {
5350                                                 name += string("_const_idx_") + de::toString(constIdx);
5351                                                 for (deUint32 i = 0; i < numDataPoints; i++)
5352                                                 {
5353                                                         deUint32 idx = constIdx * numElements + i % numElements;
5354                                                         constIdxOutputs.push_back(intFacts[factIdx].isSigned ? sOutputs[idx] : uOutputs[idx]);
5355                                                 }
5356                                         }
5357
5358                                         resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5359                                         resources.outputs.clear();
5360                                         if (useConstIdx)
5361                                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(constIdxOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5362                                         else if (intFacts[factIdx].isSigned)
5363                                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5364                                         else
5365                                                 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5366
5367                                         createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
5368                                 }
5369 }
5370
5371 void addGraphics16BitStorageUniformFloat16To32Group (tcu::TestCaseGroup* testGroup)
5372 {
5373         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
5374         map<string, string>                                     fragments;
5375         vector<string>                                          extensions;
5376         const deUint32                                          numDataPoints           = 256;
5377         RGBA                                                            defaultColors[4];
5378         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
5379         vector<deFloat16>                                       float16Data                     = getFloat16s(rnd, numDataPoints);
5380
5381         struct ConstantIndex
5382         {
5383                 bool            useConstantIndex;
5384                 deUint32        constantIndex;
5385         };
5386
5387         ConstantIndex   constantIndices[] =
5388         {
5389                 { false,        0 },
5390                 { true,         4 },
5391                 { true,         5 },
5392                 { true,         6 }
5393         };
5394
5395         extensions.push_back("VK_KHR_16bit_storage");
5396         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
5397
5398         getDefaultColors(defaultColors);
5399
5400         { // scalar cases
5401                 const StringTemplate preMain            (
5402                         "      %f16 = OpTypeFloat 16\n"
5403                         "%c_i32_256 = OpConstant %i32 256\n"
5404                         " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5405                         "   %up_f32 = OpTypePointer Uniform %f32\n"
5406                         "   %up_f16 = OpTypePointer Uniform %f16\n"
5407                         "   %ra_f32 = OpTypeArray %f32 %c_i32_256\n"
5408                         "   %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
5409                         "   %SSBO32 = OpTypeStruct %ra_f32\n"
5410                         "   %SSBO16 = OpTypeStruct %ra_f16\n"
5411                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5412                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5413                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5414                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5415
5416                 const StringTemplate decoration         (
5417                         "OpDecorate %ra_f32 ArrayStride 4\n"
5418                         "OpDecorate %ra_f16 ArrayStride ${arraystride}\n"
5419                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5420                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
5421                         "OpDecorate %SSBO32 BufferBlock\n"
5422                         "OpDecorate %SSBO16 ${indecor}\n"
5423                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5424                         "OpDecorate %ssbo16 DescriptorSet 0\n"
5425                         "OpDecorate %ssbo32 Binding 1\n"
5426                         "OpDecorate %ssbo16 Binding 0\n");
5427
5428                 // ssbo32[] <- convert ssbo16[] to 32bit float
5429                 const StringTemplate testFun            (
5430                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5431                         "    %param = OpFunctionParameter %v4f32\n"
5432
5433                         "%entry = OpLabel\n"
5434                         "    %i = OpVariable %fp_i32 Function\n"
5435                         "         OpStore %i %c_i32_0\n"
5436                         "         OpBranch %loop\n"
5437
5438                         " %loop = OpLabel\n"
5439                         "   %15 = OpLoad %i32 %i\n"
5440                         "   %lt = OpSLessThan %bool %15 %c_i32_256\n"
5441                         "         OpLoopMerge %merge %inc None\n"
5442                         "         OpBranchConditional %lt %write %merge\n"
5443
5444                         "%write = OpLabel\n"
5445                         "   %30 = OpLoad %i32 %i\n"
5446                         "  %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5447                         "%val16 = OpLoad %f16 %src\n"
5448                         "%val32 = OpFConvert %f32 %val16\n"
5449                         "  %dst = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n"
5450                         "         OpStore %dst %val32\n"
5451                         "         OpBranch %inc\n"
5452
5453                         "  %inc = OpLabel\n"
5454                         "   %37 = OpLoad %i32 %i\n"
5455                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
5456                         "         OpStore %i %39\n"
5457                         "         OpBranch %loop\n"
5458
5459                         "%merge = OpLabel\n"
5460                         "         OpReturnValue %param\n"
5461
5462                         "OpFunctionEnd\n");
5463
5464                 const deUint32  arrayStrides[]          = {2, 16};
5465
5466                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5467                 {
5468                         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5469                         {
5470                                 GraphicsResources       resources;
5471                                 map<string, string>     specs;
5472                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_scalar_float";
5473                                 bool                            useConstIdx     = constantIndices[constIndexIdx].useConstantIndex;
5474                                 deUint32                        constIdx        = constantIndices[constIndexIdx].constantIndex;
5475
5476                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
5477                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
5478                                 specs["arraystride"]                    = de::toString(arrayStrides[capIdx]);
5479                                 specs["constarrayidx"]                  = de::toString(constIdx);
5480                                 if (useConstIdx)
5481                                         specs["arrayindex"] = "c_i32_ci";
5482                                 else
5483                                         specs["arrayindex"] = "30";
5484
5485                                 fragments["capability"]                 = capabilities.specialize(specs);
5486                                 fragments["decoration"]                 = decoration.specialize(specs);
5487                                 fragments["pre_main"]                   = preMain.specialize(specs);
5488                                 fragments["testfun"]                    = testFun.specialize(specs);
5489
5490                                 vector<deFloat16>       inputData;
5491                                 for (size_t dataIdx = 0; dataIdx < float16Data.size(); ++dataIdx)
5492                                 {
5493                                         inputData.push_back(float16Data[dataIdx]);
5494                                         for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 1; ++padIdx)
5495                                                 inputData.push_back(deFloat16(0.0f));
5496                                 }
5497
5498                                 vector<float>           float32Data;
5499                                 float32Data.reserve(numDataPoints);
5500                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5501                                         float32Data.push_back(deFloat16To32(float16Data[useConstIdx ? constIdx : numIdx]));
5502
5503                                 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5504                                 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5505                                 resources.verifyIO = check32BitFloats;
5506                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5507
5508                                 if (useConstIdx)
5509                                         testName += string("_const_idx_") + de::toString(constIdx);
5510
5511                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
5512                         }
5513                 }
5514         }
5515
5516         { // vector cases
5517                 const StringTemplate preMain            (
5518                         "      %f16 = OpTypeFloat 16\n"
5519                         "%c_i32_128 = OpConstant %i32 128\n"
5520                         "%c_i32_ci  = OpConstant %i32 ${constarrayidx}\n"
5521                         "        %v2f16 = OpTypeVector %f16 2\n"
5522                         " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5523                         " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5524                         " %ra_v2f32 = OpTypeArray %v2f32 %c_i32_128\n"
5525                         " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n"
5526                         "   %SSBO32 = OpTypeStruct %ra_v2f32\n"
5527                         "   %SSBO16 = OpTypeStruct %ra_v2f16\n"
5528                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5529                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5530                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5531                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5532
5533                 const StringTemplate decoration         (
5534                         "OpDecorate %ra_v2f32 ArrayStride 8\n"
5535                         "OpDecorate %ra_v2f16 ArrayStride ${arraystride}\n"
5536                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5537                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
5538                         "OpDecorate %SSBO32 BufferBlock\n"
5539                         "OpDecorate %SSBO16 ${indecor}\n"
5540                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5541                         "OpDecorate %ssbo16 DescriptorSet 0\n"
5542                         "OpDecorate %ssbo32 Binding 1\n"
5543                         "OpDecorate %ssbo16 Binding 0\n");
5544
5545                 // ssbo32[] <- convert ssbo16[] to 32bit float
5546                 const StringTemplate testFun            (
5547                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5548                         "    %param = OpFunctionParameter %v4f32\n"
5549
5550                         "%entry = OpLabel\n"
5551                         "    %i = OpVariable %fp_i32 Function\n"
5552                         "         OpStore %i %c_i32_0\n"
5553                         "         OpBranch %loop\n"
5554
5555                         " %loop = OpLabel\n"
5556                         "   %15 = OpLoad %i32 %i\n"
5557                         "   %lt = OpSLessThan %bool %15 %c_i32_128\n"
5558                         "         OpLoopMerge %merge %inc None\n"
5559                         "         OpBranchConditional %lt %write %merge\n"
5560
5561                         "%write = OpLabel\n"
5562                         "   %30 = OpLoad %i32 %i\n"
5563                         "  %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5564                         "%val16 = OpLoad %v2f16 %src\n"
5565                         "%val32 = OpFConvert %v2f32 %val16\n"
5566                         "  %dst = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30\n"
5567                         "         OpStore %dst %val32\n"
5568                         "         OpBranch %inc\n"
5569
5570                         "  %inc = OpLabel\n"
5571                         "   %37 = OpLoad %i32 %i\n"
5572                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
5573                         "         OpStore %i %39\n"
5574                         "         OpBranch %loop\n"
5575
5576                         "%merge = OpLabel\n"
5577                         "         OpReturnValue %param\n"
5578
5579                         "OpFunctionEnd\n");
5580
5581                 const deUint32  arrayStrides[]          = {4, 16};
5582
5583                 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5584                 {
5585                         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5586                         {
5587                                 GraphicsResources       resources;
5588                                 map<string, string>     specs;
5589                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_vector_float";
5590                                 bool                            useConstIdx     = constantIndices[constIndexIdx].useConstantIndex;
5591                                 deUint32                        constIdx        = constantIndices[constIndexIdx].constantIndex;
5592
5593                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
5594                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
5595                                 specs["arraystride"]                    = de::toString(arrayStrides[capIdx]);
5596                                 specs["constarrayidx"]                  = de::toString(constIdx);
5597                                 if (useConstIdx)
5598                                         specs["arrayindex"] = "c_i32_ci";
5599                                 else
5600                                         specs["arrayindex"] = "30";
5601
5602                                 fragments["capability"]                 = capabilities.specialize(specs);
5603                                 fragments["decoration"]                 = decoration.specialize(specs);
5604                                 fragments["pre_main"]                   = preMain.specialize(specs);
5605                                 fragments["testfun"]                    = testFun.specialize(specs);
5606
5607                                 vector<deFloat16>       inputData;
5608                                 for (size_t dataIdx = 0; dataIdx < float16Data.size() / 2; ++dataIdx)
5609                                 {
5610                                         inputData.push_back(float16Data[dataIdx * 2]);
5611                                         inputData.push_back(float16Data[dataIdx * 2 + 1]);
5612                                         for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 2; ++padIdx)
5613                                                 inputData.push_back(deFloat16(0.0f));
5614                                 }
5615
5616                                 vector<float>           float32Data;
5617                                 float32Data.reserve(numDataPoints);
5618                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5619                                         float32Data.push_back(deFloat16To32(float16Data[constantIndices[constIndexIdx].useConstantIndex ? (constantIndices[constIndexIdx].constantIndex * 2 + numIdx % 2) : numIdx]));
5620
5621                                 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5622                                 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5623                                 resources.verifyIO = check32BitFloats;
5624                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5625
5626                                 if (constantIndices[constIndexIdx].useConstantIndex)
5627                                         testName += string("_const_idx_") + de::toString(constantIndices[constIndexIdx].constantIndex);
5628
5629                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
5630                         }
5631                 }
5632         }
5633
5634         { // matrix cases
5635                 fragments["pre_main"]                           =
5636                         " %c_i32_32 = OpConstant %i32 32\n"
5637                         "      %f16 = OpTypeFloat 16\n"
5638                         "    %v2f16 = OpTypeVector %f16 2\n"
5639                         "  %m4x2f32 = OpTypeMatrix %v2f32 4\n"
5640                         "  %m4x2f16 = OpTypeMatrix %v2f16 4\n"
5641                         " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5642                         " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5643                         "%a8m4x2f32 = OpTypeArray %m4x2f32 %c_i32_32\n"
5644                         "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n"
5645                         "   %SSBO32 = OpTypeStruct %a8m4x2f32\n"
5646                         "   %SSBO16 = OpTypeStruct %a8m4x2f16\n"
5647                         "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5648                         "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5649                         "   %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5650                         "   %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
5651
5652                 const StringTemplate decoration         (
5653                         "OpDecorate %a8m4x2f32 ArrayStride 32\n"
5654                         "OpDecorate %a8m4x2f16 ArrayStride 16\n"
5655                         "OpMemberDecorate %SSBO32 0 Offset 0\n"
5656                         "OpMemberDecorate %SSBO32 0 ColMajor\n"
5657                         "OpMemberDecorate %SSBO32 0 MatrixStride 8\n"
5658                         "OpMemberDecorate %SSBO16 0 Offset 0\n"
5659                         "OpMemberDecorate %SSBO16 0 ColMajor\n"
5660                         "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"
5661                         "OpDecorate %SSBO32 BufferBlock\n"
5662                         "OpDecorate %SSBO16 ${indecor}\n"
5663                         "OpDecorate %ssbo32 DescriptorSet 0\n"
5664                         "OpDecorate %ssbo16 DescriptorSet 0\n"
5665                         "OpDecorate %ssbo32 Binding 1\n"
5666                         "OpDecorate %ssbo16 Binding 0\n");
5667
5668                 fragments["testfun"]                            =
5669                         "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5670                         "    %param = OpFunctionParameter %v4f32\n"
5671
5672                         "%entry = OpLabel\n"
5673                         "    %i = OpVariable %fp_i32 Function\n"
5674                         "         OpStore %i %c_i32_0\n"
5675                         "         OpBranch %loop\n"
5676
5677                         " %loop = OpLabel\n"
5678                         "   %15 = OpLoad %i32 %i\n"
5679                         "   %lt = OpSLessThan %bool %15 %c_i32_32\n"
5680                         "         OpLoopMerge %merge %inc None\n"
5681                         "         OpBranchConditional %lt %write %merge\n"
5682
5683                         "  %write = OpLabel\n"
5684                         "     %30 = OpLoad %i32 %i\n"
5685                         "  %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
5686                         "  %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
5687                         "  %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
5688                         "  %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
5689                         "%val16_0 = OpLoad %v2f16 %src_0\n"
5690                         "%val16_1 = OpLoad %v2f16 %src_1\n"
5691                         "%val16_2 = OpLoad %v2f16 %src_2\n"
5692                         "%val16_3 = OpLoad %v2f16 %src_3\n"
5693                         "%val32_0 = OpFConvert %v2f32 %val16_0\n"
5694                         "%val32_1 = OpFConvert %v2f32 %val16_1\n"
5695                         "%val32_2 = OpFConvert %v2f32 %val16_2\n"
5696                         "%val32_3 = OpFConvert %v2f32 %val16_3\n"
5697                         "  %dst_0 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n"
5698                         "  %dst_1 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
5699                         "  %dst_2 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n"
5700                         "  %dst_3 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n"
5701                         "           OpStore %dst_0 %val32_0\n"
5702                         "           OpStore %dst_1 %val32_1\n"
5703                         "           OpStore %dst_2 %val32_2\n"
5704                         "           OpStore %dst_3 %val32_3\n"
5705                         "           OpBranch %inc\n"
5706
5707                         "  %inc = OpLabel\n"
5708                         "   %37 = OpLoad %i32 %i\n"
5709                         "   %39 = OpIAdd %i32 %37 %c_i32_1\n"
5710                         "         OpStore %i %39\n"
5711                         "         OpBranch %loop\n"
5712
5713                         "%merge = OpLabel\n"
5714                         "         OpReturnValue %param\n"
5715
5716                         "OpFunctionEnd\n";
5717
5718                         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5719                         {
5720                                 GraphicsResources       resources;
5721                                 map<string, string>     specs;
5722                                 string                          testName        = string(CAPABILITIES[capIdx].name) + "_matrix_float";
5723
5724                                 specs["cap"]                                    = CAPABILITIES[capIdx].cap;
5725                                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
5726
5727                                 fragments["capability"]                 = capabilities.specialize(specs);
5728                                 fragments["decoration"]                 = decoration.specialize(specs);
5729
5730                                 vector<float>           float32Data;
5731                                 float32Data.reserve(numDataPoints);
5732                                 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5733                                         float32Data.push_back(deFloat16To32(float16Data[numIdx]));
5734
5735                                 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5736                                 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5737                                 resources.verifyIO = check32BitFloats;
5738                                 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5739
5740                                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
5741                 }
5742         }
5743 }
5744
5745 void addGraphics16BitStorageUniformStructFloat16To32Group (tcu::TestCaseGroup* testGroup)
5746 {
5747         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
5748         map<string, string>                                     fragments;
5749         vector<string>                                          extensions;
5750         RGBA                                                            defaultColors[4];
5751         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
5752         vector<float>                                           float32Data                     (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430), 0.0f);
5753
5754         extensions.push_back("VK_KHR_16bit_storage");
5755         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
5756
5757         getDefaultColors(defaultColors);
5758
5759         const StringTemplate preMain            (
5760                 "\n"
5761                 "${types}\n"
5762                 "\n"
5763                 "%zero = OpConstant %i32 0\n"
5764                 "%c_i32_5 = OpConstant %i32 5\n"
5765                 "%c_i32_6 = OpConstant %i32 6\n"
5766                 "%c_i32_7 = OpConstant %i32 7\n"
5767                 "%c_i32_8 = OpConstant %i32 8\n"
5768                 "%c_i32_9 = OpConstant %i32 9\n"
5769                 "%c_i32_11 = OpConstant %i32 11\n"
5770                 "\n"
5771                 "%c_u32_7 = OpConstant %u32 7\n"
5772                 "%c_u32_11 = OpConstant %u32 11\n"
5773                 "\n"
5774                 "%f16arr3       = OpTypeArray %f16 %c_u32_3\n"
5775                 "%v2f16arr3    = OpTypeArray %v2f16 %c_u32_3\n"
5776                 "%v2f16arr11    = OpTypeArray %v2f16 %c_u32_11\n"
5777                 "%v3f16arr11    = OpTypeArray %v3f16 %c_u32_11\n"
5778                 "%v4f16arr3     = OpTypeArray %v4f16 %c_u32_3\n"
5779                 "%struct16      = OpTypeStruct %f16 %v2f16arr3\n"
5780                 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
5781                 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
5782                 "\n"
5783                 "%f32arr3   = OpTypeArray %f32 %c_u32_3\n"
5784                 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
5785                 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
5786                 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
5787                 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
5788                 "%struct32      = OpTypeStruct %f32 %v2f32arr3\n"
5789                 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
5790                 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
5791                 "\n"
5792                 "%f16StructArr7      = OpTypeArray %f16Struct %c_u32_7\n"
5793                 "%f32StructArr7      = OpTypeArray %f32Struct %c_u32_7\n"
5794                 "%SSBO_IN            = OpTypeStruct %f16StructArr7\n"
5795                 "%SSBO_OUT           = OpTypeStruct %f32StructArr7\n"
5796                 "%up_SSBOIN          = OpTypePointer Uniform %SSBO_IN\n"
5797                 "%up_SSBOOUT         = OpTypePointer Uniform %SSBO_OUT\n"
5798                 "%ssboIN             = OpVariable %up_SSBOIN Uniform\n"
5799                 "%ssboOUT            = OpVariable %up_SSBOOUT Uniform\n"
5800                 "\n");
5801
5802         const StringTemplate decoration         (
5803                 "${strideF16}"
5804                 "\n"
5805                 "${strideF32}"
5806                 "\n"
5807                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
5808                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
5809                 "OpDecorate %SSBO_IN ${indecor}\n"
5810                 "OpDecorate %SSBO_OUT BufferBlock\n"
5811                 "OpDecorate %ssboIN DescriptorSet 0\n"
5812                 "OpDecorate %ssboOUT DescriptorSet 0\n"
5813                 "OpDecorate %ssboIN Binding 0\n"
5814                 "OpDecorate %ssboOUT Binding 1\n"
5815                 "\n");
5816
5817         fragments["testfun"]                    =
5818                 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5819                 "    %param = OpFunctionParameter %v4f32\n"
5820                 "%label     = OpLabel\n"
5821                 "%loopNdx    = OpVariable %fp_i32 Function\n"
5822                 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
5823
5824                 "OpStore %loopNdx %zero\n"
5825                 "OpBranch %loop\n"
5826                 "%loop = OpLabel\n"
5827                 "OpLoopMerge %merge %13 None\n"
5828                 "OpBranch %14\n"
5829                 "%14 = OpLabel\n"
5830                 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
5831                 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
5832                 "OpBranchConditional %18 %11 %merge\n"
5833                 "%11 = OpLabel\n"
5834                 "\n"
5835                 "%f16src  = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %zero\n"
5836                 "%val_f16 = OpLoad %f16 %f16src\n"
5837                 "%val_f32 = OpFConvert %f32 %val_f16\n"
5838                 "%f32dst  = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %zero\n"
5839                 "OpStore %f32dst %val_f32\n"
5840                 "\n"
5841                 "%v2f16src  = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
5842                 "%val_v2f16 = OpLoad %v2f16 %v2f16src\n"
5843                 "%val_v2f32 = OpFConvert %v2f32 %val_v2f16\n"
5844                 "%v2f32dst  = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
5845                 "OpStore %v2f32dst %val_v2f32\n"
5846                 "\n"
5847                 "%v3f16src  = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
5848                 "%val_v3f16 = OpLoad %v3f16 %v3f16src\n"
5849                 "%val_v3f32 = OpFConvert %v3f32 %val_v3f16\n"
5850                 "%v3f32dst  = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
5851                 "OpStore %v3f32dst %val_v3f32\n"
5852                 "\n"
5853                 "%v4f16src  = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
5854                 "%val_v4f16 = OpLoad %v4f16 %v4f16src\n"
5855                 "%val_v4f32 = OpFConvert %v4f32 %val_v4f16\n"
5856                 "%v4f32dst  = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
5857                 "OpStore %v4f32dst %val_v4f32\n"
5858                 "\n"
5859                 "%f16src2  = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
5860                 "%val2_f16 = OpLoad %f16 %f16src2\n"
5861                 "%val2_f32 = OpFConvert %f32 %val2_f16\n"
5862                 "%f32dst2  = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
5863                 "OpStore %f32dst2 %val2_f32\n"
5864                 "\n"
5865                 "OpStore %insideLoopNdx %zero\n"
5866                 "OpBranch %loopInside\n"
5867                 "%loopInside = OpLabel\n"
5868                 "OpLoopMerge %92 %93 None\n"
5869                 "OpBranch %94\n"
5870                 "%94 = OpLabel\n"
5871                 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
5872                 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
5873                 "OpBranchConditional %96 %91 %92\n"
5874                 "\n"
5875                 "%91 = OpLabel\n"
5876                 "\n"
5877                 "%v2f16src2  = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
5878                 "%val2_v2f16 = OpLoad %v2f16 %v2f16src2\n"
5879                 "%val2_v2f32 = OpFConvert %v2f32 %val2_v2f16\n"
5880                 "%v2f32dst2  = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
5881                 "OpStore %v2f32dst2 %val2_v2f32\n"
5882                 "\n"
5883                 "%v3f16src2  = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
5884                 "%val2_v3f16 = OpLoad %v3f16 %v3f16src2\n"
5885                 "%val2_v3f32 = OpFConvert %v3f32 %val2_v3f16\n"
5886                 "%v3f32dst2  = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
5887                 "OpStore %v3f32dst2 %val2_v3f32\n"
5888                 "\n"
5889                 //struct {f16, v2f16[3]}
5890                 "%Sf16src  = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
5891                 "%Sval_f16 = OpLoad %f16 %Sf16src\n"
5892                 "%Sval_f32 = OpFConvert %f32 %Sval_f16\n"
5893                 "%Sf32dst2  = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
5894                 "OpStore %Sf32dst2 %Sval_f32\n"
5895                 "\n"
5896                 "%Sv2f16src0   = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
5897                 "%Sv2f16_0     = OpLoad %v2f16 %Sv2f16src0\n"
5898                 "%Sv2f32_0     = OpFConvert %v2f32 %Sv2f16_0\n"
5899                 "%Sv2f32dst_0  = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
5900                 "OpStore %Sv2f32dst_0 %Sv2f32_0\n"
5901                 "\n"
5902                 "%Sv2f16src1  = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
5903                 "%Sv2f16_1 = OpLoad %v2f16 %Sv2f16src1\n"
5904                 "%Sv2f32_1 = OpFConvert %v2f32 %Sv2f16_1\n"
5905                 "%Sv2f32dst_1  = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
5906                 "OpStore %Sv2f32dst_1 %Sv2f32_1\n"
5907                 "\n"
5908                 "%Sv2f16src2  = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
5909                 "%Sv2f16_2 = OpLoad %v2f16 %Sv2f16src2\n"
5910                 "%Sv2f32_2 = OpFConvert %v2f32 %Sv2f16_2\n"
5911                 "%Sv2f32dst_2  = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
5912                 "OpStore %Sv2f32dst_2 %Sv2f32_2\n"
5913                 "\n"
5914                 //Array with 3 elements
5915                 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
5916                 "OpSelectionMerge %BlockIf None\n"
5917                 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
5918                 "%LabelIf = OpLabel\n"
5919                 "  %f16src3  = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
5920                 "  %val3_f16 = OpLoad %f16 %f16src3\n"
5921                 "  %val3_f32 = OpFConvert %f32 %val3_f16\n"
5922                 "  %f32dst3  = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
5923                 "  OpStore %f32dst3 %val3_f32\n"
5924                 "\n"
5925                 "  %v4f16src2  = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
5926                 "  %val2_v4f16 = OpLoad %v4f16 %v4f16src2\n"
5927                 "  %val2_v4f32 = OpFConvert %v4f32 %val2_v4f16\n"
5928                 "  %v4f32dst2  = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
5929                 "  OpStore %v4f32dst2 %val2_v4f32\n"
5930                 "OpBranch %BlockIf\n"
5931                 "%BlockIf = OpLabel\n"
5932                 "\n"
5933                 "OpBranch %93\n"
5934                 "%93 = OpLabel\n"
5935                 "%132 = OpLoad %i32 %insideLoopNdx\n"
5936                 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
5937                 "OpStore %insideLoopNdx %133\n"
5938                 "OpBranch %loopInside\n"
5939                 "\n"
5940                 "%92 = OpLabel\n"
5941                 "OpBranch %13\n"
5942                 "%13 = OpLabel\n"
5943                 "%134 = OpLoad %i32 %loopNdx\n"
5944                 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
5945                 "OpStore %loopNdx %135\n"
5946                 "OpBranch %loop\n"
5947
5948                 "%merge = OpLabel\n"
5949                 "         OpReturnValue %param\n"
5950                 "         OpFunctionEnd\n";
5951
5952                 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5953                 {
5954                         vector<deFloat16>       float16Data     = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data16bitStd430(rnd) :  data16bitStd140(rnd);
5955                         GraphicsResources       resources;
5956                         map<string, string>     specs;
5957                         string                          testName        = string(CAPABILITIES[capIdx].name);
5958
5959                         specs["cap"]                                    = CAPABILITIES[capIdx].cap;
5960                         specs["indecor"]                                = CAPABILITIES[capIdx].decor;
5961                         specs["strideF16"]                              = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE16BIT_STD430 : SHADERTEMPLATE_STRIDE16BIT_STD140);
5962                         specs["strideF32"]                              = getStructShaderComponet(SHADERTEMPLATE_STRIDE32BIT_STD430);
5963                         specs["types"]                                  = getStructShaderComponet(SHADERTEMPLATE_TYPES);
5964
5965                         fragments["capability"]                 = capabilities.specialize(specs);
5966                         fragments["decoration"]                 = decoration.specialize(specs);
5967                         fragments["pre_main"]                   = preMain.specialize(specs);
5968
5969                         resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), CAPABILITIES[capIdx].dtype));
5970                         resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5971                         resources.verifyIO = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? graphicsCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD430, SHADERTEMPLATE_STRIDE32BIT_STD430> : graphicsCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD140, SHADERTEMPLATE_STRIDE32BIT_STD430>;
5972
5973                         createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
5974                 }
5975 }
5976
5977 void addGraphics16BitStorageUniformStructFloat32To16Group (tcu::TestCaseGroup* testGroup)
5978 {
5979         de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
5980         map<string, string>                                     fragments;
5981         vector<string>                                          extensions;
5982         RGBA                                                            defaultColors[4];
5983         const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
5984         vector<deUint16>                                        float16Data                     (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430), 0u);
5985
5986         extensions.push_back("VK_KHR_16bit_storage");
5987         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"";
5988
5989         getDefaultColors(defaultColors);
5990
5991         const StringTemplate preMain            (
5992                 "\n"
5993                 "${types}\n"
5994                 "\n"
5995                 "%zero = OpConstant %i32 0\n"
5996                 "%c_i32_5 = OpConstant %i32 5\n"
5997                 "%c_i32_6 = OpConstant %i32 6\n"
5998                 "%c_i32_7 = OpConstant %i32 7\n"
5999                 "%c_i32_8 = OpConstant %i32 8\n"
6000                 "%c_i32_9 = OpConstant %i32 9\n"
6001                 "%c_i32_11 = OpConstant %i32 11\n"
6002                 "\n"
6003                 "%c_u32_7 = OpConstant %u32 7\n"
6004                 "%c_u32_11 = OpConstant %u32 11\n"
6005                 "\n"
6006                 "%f16arr3       = OpTypeArray %f16 %c_u32_3\n"
6007                 "%v2f16arr3    = OpTypeArray %v2f16 %c_u32_3\n"
6008                 "%v2f16arr11    = OpTypeArray %v2f16 %c_u32_11\n"
6009                 "%v3f16arr11    = OpTypeArray %v3f16 %c_u32_11\n"
6010                 "%v4f16arr3     = OpTypeArray %v4f16 %c_u32_3\n"
6011                 "%struct16      = OpTypeStruct %f16 %v2f16arr3\n"
6012                 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
6013                 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
6014                 "\n"
6015                 "%f32arr3   = OpTypeArray %f32 %c_u32_3\n"
6016                 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
6017                 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
6018                 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
6019                 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
6020                 "%struct32      = OpTypeStruct %f32 %v2f32arr3\n"
6021                 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
6022                 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
6023                 "\n"
6024                 "%f16StructArr7      = OpTypeArray %f16Struct %c_u32_7\n"
6025                 "%f32StructArr7      = OpTypeArray %f32Struct %c_u32_7\n"
6026                 "%SSBO_IN            = OpTypeStruct %f32StructArr7\n"
6027                 "%SSBO_OUT           = OpTypeStruct %f16StructArr7\n"
6028                 "%up_SSBOIN          = OpTypePointer Uniform %SSBO_IN\n"
6029                 "%up_SSBOOUT         = OpTypePointer Uniform %SSBO_OUT\n"
6030                 "%ssboIN             = OpVariable %up_SSBOIN Uniform\n"
6031                 "%ssboOUT            = OpVariable %up_SSBOOUT Uniform\n"
6032                 "\n");
6033
6034         const StringTemplate decoration         (
6035                 "${strideF16}"
6036                 "\n"
6037                 "${strideF32}"
6038                 "\n"
6039                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6040                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6041                 "OpDecorate %SSBO_IN ${indecor}\n"
6042                 "OpDecorate %SSBO_OUT BufferBlock\n"
6043                 "OpDecorate %ssboIN DescriptorSet 0\n"
6044                 "OpDecorate %ssboOUT DescriptorSet 0\n"
6045                 "OpDecorate %ssboIN Binding 0\n"
6046                 "OpDecorate %ssboOUT Binding 1\n"
6047                 "\n");
6048
6049         fragments["testfun"]                    =
6050                 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6051                 "%param = OpFunctionParameter %v4f32\n"
6052                 "%label     = OpLabel\n"
6053                 "%loopNdx    = OpVariable %fp_i32 Function\n"
6054                 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
6055
6056                 "OpStore %loopNdx %zero\n"
6057                 "OpBranch %loop\n"
6058                 "%loop = OpLabel\n"
6059                 "OpLoopMerge %merge %13 None\n"
6060                 "OpBranch %14\n"
6061                 "%14 = OpLabel\n"
6062                 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
6063                 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
6064                 "OpBranchConditional %18 %11 %merge\n"
6065                 "%11 = OpLabel\n"
6066                 "\n"
6067                 "%f32src  = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %zero\n"
6068                 "%val_f32 = OpLoad %f32 %f32src\n"
6069                 "%val_f16 = OpFConvert %f16 %val_f32\n"
6070                 "%f16dst  = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %zero\n"
6071                 "OpStore %f16dst %val_f16\n"
6072                 "\n"
6073                 "%v2f32src  = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
6074                 "%val_v2f32 = OpLoad %v2f32 %v2f32src\n"
6075                 "%val_v2f16 = OpFConvert %v2f16 %val_v2f32\n"
6076                 "%v2f16dst  = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
6077                 "OpStore %v2f16dst %val_v2f16\n"
6078                 "\n"
6079                 "%v3f32src  = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
6080                 "%val_v3f32 = OpLoad %v3f32 %v3f32src\n"
6081                 "%val_v3f16 = OpFConvert %v3f16 %val_v3f32\n"
6082                 "%v3f16dst  = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
6083                 "OpStore %v3f16dst %val_v3f16\n"
6084                 "\n"
6085                 "%v4f32src  = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
6086                 "%val_v4f32 = OpLoad %v4f32 %v4f32src\n"
6087                 "%val_v4f16 = OpFConvert %v4f16 %val_v4f32\n"
6088                 "%v4f16dst  = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
6089                 "OpStore %v4f16dst %val_v4f16\n"
6090                 "\n"
6091                 "%f32src2  = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
6092                 "%val2_f32 = OpLoad %f32 %f32src2\n"
6093                 "%val2_f16 = OpFConvert %f16 %val2_f32\n"
6094                 "%f16dst2  = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
6095                 "OpStore %f16dst2 %val2_f16\n"
6096                 "\n"
6097                 "OpStore %insideLoopNdx %zero\n"
6098                 "OpBranch %loopInside\n"
6099                 "%loopInside = OpLabel\n"
6100                 "OpLoopMerge %92 %93 None\n"
6101                 "OpBranch %94\n"
6102                 "%94 = OpLabel\n"
6103                 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
6104                 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
6105                 "OpBranchConditional %96 %91 %92\n"
6106                 "\n"
6107                 "%91 = OpLabel\n"
6108                 "\n"
6109                 //struct {f16, v2f16[3]}
6110                 "%Sf32src  = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6111                 "%Sval_f32 = OpLoad %f32 %Sf32src\n"
6112                 "%Sval_f16 = OpFConvert %f16 %Sval_f32\n"
6113                 "%Sf16dst2  = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6114                 "OpStore %Sf16dst2 %Sval_f16\n"
6115                 "\n"
6116                 "%Sv2f32src0   = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6117                 "%Sv2f32_0     = OpLoad %v2f32 %Sv2f32src0\n"
6118                 "%Sv2f16_0     = OpFConvert %v2f16 %Sv2f32_0\n"
6119                 "%Sv2f16dst_0  = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6120                 "OpStore %Sv2f16dst_0 %Sv2f16_0\n"
6121                 "\n"
6122                 "%Sv2f32src1  = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6123                 "%Sv2f32_1 = OpLoad %v2f32 %Sv2f32src1\n"
6124                 "%Sv2f16_1 = OpFConvert %v2f16 %Sv2f32_1\n"
6125                 "%Sv2f16dst_1  = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6126                 "OpStore %Sv2f16dst_1 %Sv2f16_1\n"
6127                 "\n"
6128                 "%Sv2f32src2  = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6129                 "%Sv2f32_2 = OpLoad %v2f32 %Sv2f32src2\n"
6130                 "%Sv2f16_2 = OpFConvert %v2f16 %Sv2f32_2\n"
6131                 "%Sv2f16dst_2  = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6132                 "OpStore %Sv2f16dst_2 %Sv2f16_2\n"
6133                 "\n"
6134
6135                 "%v2f32src2  = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6136                 "%val2_v2f32 = OpLoad %v2f32 %v2f32src2\n"
6137                 "%val2_v2f16 = OpFConvert %v2f16 %val2_v2f32\n"
6138                 "%v2f16dst2  = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6139                 "OpStore %v2f16dst2 %val2_v2f16\n"
6140                 "\n"
6141                 "%v3f32src2  = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6142                 "%val2_v3f32 = OpLoad %v3f32 %v3f32src2\n"
6143                 "%val2_v3f16 = OpFConvert %v3f16 %val2_v3f32\n"
6144                 "%v3f16dst2  = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6145                 "OpStore %v3f16dst2 %val2_v3f16\n"
6146                 "\n"
6147
6148                 //Array with 3 elements
6149                 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
6150                 "OpSelectionMerge %BlockIf None\n"
6151                 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
6152                 "  %LabelIf = OpLabel\n"
6153                 "  %f32src3  = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6154                 "  %val3_f32 = OpLoad %f32 %f32src3\n"
6155                 "  %val3_f16 = OpFConvert %f16 %val3_f32\n"
6156                 "  %f16dst3  = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6157                 "  OpStore %f16dst3 %val3_f16\n"
6158                 "\n"
6159                 "  %v4f32src2  = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6160                 "  %val2_v4f32 = OpLoad %v4f32 %v4f32src2\n"
6161                 "  %val2_v4f16 = OpFConvert %v4f16 %val2_v4f32\n"
6162                 "  %v4f16dst2  = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6163                 "  OpStore %v4f16dst2 %val2_v4f16\n"
6164                 "OpBranch %BlockIf\n"
6165                 "%BlockIf = OpLabel\n"
6166
6167                 "OpBranch %93\n"
6168                 "%93 = OpLabel\n"
6169                 "%132 = OpLoad %i32 %insideLoopNdx\n"
6170                 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
6171                 "OpStore %insideLoopNdx %133\n"
6172                 "OpBranch %loopInside\n"
6173                 "\n"
6174                 "%92 = OpLabel\n"
6175                 "OpBranch %13\n"
6176                 "%13 = OpLabel\n"
6177                 "%134 = OpLoad %i32 %loopNdx\n"
6178                 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
6179                 "OpStore %loopNdx %135\n"
6180                 "OpBranch %loop\n"
6181
6182                 "%merge = OpLabel\n"
6183                 "         OpReturnValue %param\n"
6184                 "         OpFunctionEnd\n";
6185
6186         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6187         {
6188                 map<string, string>     specs;
6189                 string                          testName        = string(CAPABILITIES[capIdx].name);
6190                 vector<float>           float32Data     = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data32bitStd430(rnd) : data32bitStd140(rnd);
6191                 GraphicsResources       resources;
6192
6193                 specs["cap"]                                    = "StorageUniformBufferBlock16";
6194                 specs["indecor"]                                = CAPABILITIES[capIdx].decor;
6195                 specs["strideF16"]                              = getStructShaderComponet(SHADERTEMPLATE_STRIDE16BIT_STD430);
6196                 specs["strideF32"]                              = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE32BIT_STD430 : SHADERTEMPLATE_STRIDE32BIT_STD140);
6197                 specs["types"]                                  = getStructShaderComponet(SHADERTEMPLATE_TYPES);
6198
6199                 fragments["capability"]                 = capabilities.specialize(specs);
6200                 fragments["decoration"]                 = decoration.specialize(specs);
6201                 fragments["pre_main"]                   = preMain.specialize(specs);
6202
6203                 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), CAPABILITIES[capIdx].dtype));
6204                 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6205                 resources.verifyIO                              =  (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? graphicsCheckStruct<float, deFloat16, SHADERTEMPLATE_STRIDE32BIT_STD430, SHADERTEMPLATE_STRIDE16BIT_STD430> : graphicsCheckStruct<float, deFloat16, SHADERTEMPLATE_STRIDE32BIT_STD140, SHADERTEMPLATE_STRIDE16BIT_STD430>;
6206
6207                 VulkanFeatures features;
6208                 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
6209
6210                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6211         }
6212 }
6213
6214 void addGraphics16bitStructMixedTypesGroup (tcu::TestCaseGroup* group)
6215 {
6216         de::Random                                                      rnd                                     (deStringHash(group->getName()));
6217         map<string, string>                                     fragments;
6218         vector<string>                                          extensions;
6219         RGBA                                                            defaultColors[4];
6220         const StringTemplate                            capabilities            ("OpCapability StorageUniformBufferBlock16\n"
6221                                                                                                                         "${cap}\n");
6222         vector<deInt16>                                         outData                         (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430), 0u);
6223
6224         extensions.push_back("VK_KHR_16bit_storage");
6225         fragments["extension"]  = "OpExtension \"SPV_KHR_16bit_storage\"\n";
6226
6227         getDefaultColors(defaultColors);
6228
6229         const StringTemplate                            preMain                         (
6230                 "\n"//Types
6231                 "%i16    = OpTypeInt 16 1\n"
6232                 "%v2i16  = OpTypeVector %i16 2\n"
6233                 "%v3i16  = OpTypeVector %i16 3\n"
6234                 "%v4i16  = OpTypeVector %i16 4\n"
6235                 "\n"//Consta value
6236                 "%zero     = OpConstant %i32 0\n"
6237                 "%c_i32_5  = OpConstant %i32 5\n"
6238                 "%c_i32_6  = OpConstant %i32 6\n"
6239                 "%c_i32_7  = OpConstant %i32 7\n"
6240                 "%c_i32_8  = OpConstant %i32 8\n"
6241                 "%c_i32_9  = OpConstant %i32 9\n"
6242                 "%c_i32_10 = OpConstant %i32 10\n"
6243                 "%c_i32_11 = OpConstant %i32 11\n"
6244                 "%c_u32_7  = OpConstant %u32 7\n"
6245                 "%c_u32_11 = OpConstant %u32 11\n"
6246                 "\n"//Arrays & Structs
6247                 "%v2b16NestedArr11In  = OpTypeArray %v2i16 %c_u32_11\n"
6248                 "%b32NestedArr11In   = OpTypeArray %i32 %c_u32_11\n"
6249                 "%sb16Arr11In         = OpTypeArray %i16 %c_u32_11\n"
6250                 "%sb32Arr11In        = OpTypeArray %i32 %c_u32_11\n"
6251                 "%sNestedIn          = OpTypeStruct %i16 %i32 %v2b16NestedArr11In %b32NestedArr11In\n"
6252                 "%sNestedArr11In     = OpTypeArray %sNestedIn %c_u32_11\n"
6253                 "%structIn           = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11In %sb16Arr11In %sb32Arr11In\n"
6254                 "%structArr7In       = OpTypeArray %structIn %c_u32_7\n"
6255                 "%v2b16NestedArr11Out = OpTypeArray %v2i16 %c_u32_11\n"
6256                 "%b32NestedArr11Out  = OpTypeArray %i32 %c_u32_11\n"
6257                 "%sb16Arr11Out        = OpTypeArray %i16 %c_u32_11\n"
6258                 "%sb32Arr11Out       = OpTypeArray %i32 %c_u32_11\n"
6259                 "%sNestedOut         = OpTypeStruct %i16 %i32 %v2b16NestedArr11Out %b32NestedArr11Out\n"
6260                 "%sNestedArr11Out    = OpTypeArray %sNestedOut %c_u32_11\n"
6261                 "%structOut          = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11Out %sb16Arr11Out %sb32Arr11Out\n"
6262                 "%structArr7Out      = OpTypeArray %structOut %c_u32_7\n"
6263                 "\n"//Pointers
6264                 "%i16outPtr    = OpTypePointer Uniform %i16\n"
6265                 "%v2i16outPtr  = OpTypePointer Uniform %v2i16\n"
6266                 "%v3i16outPtr  = OpTypePointer Uniform %v3i16\n"
6267                 "%v4i16outPtr  = OpTypePointer Uniform %v4i16\n"
6268                 "%i32outPtr   = OpTypePointer Uniform %i32\n"
6269                 "%v2i32outPtr = OpTypePointer Uniform %v2i32\n"
6270                 "%v3i32outPtr = OpTypePointer Uniform %v3i32\n"
6271                 "%v4i32outPtr = OpTypePointer Uniform %v4i32\n"
6272                 "%uvec3ptr = OpTypePointer Input %v3u32\n"
6273                 "\n"//SSBO IN
6274                 "%SSBO_IN    = OpTypeStruct %structArr7In\n"
6275                 "%up_SSBOIN  = OpTypePointer Uniform %SSBO_IN\n"
6276                 "%ssboIN     = OpVariable %up_SSBOIN Uniform\n"
6277                 "\n"//SSBO OUT
6278                 "%SSBO_OUT   = OpTypeStruct %structArr7Out\n"
6279                 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6280                 "%ssboOUT    = OpVariable %up_SSBOOUT Uniform\n");
6281
6282                 const StringTemplate                    decoration                      (
6283                 "${OutOffsets}"
6284                 "${InOffsets}"
6285                 "\n"//SSBO IN
6286                 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6287                 "OpDecorate %ssboIN DescriptorSet 0\n"
6288                 "OpDecorate %SSBO_IN ${storage}\n"
6289                 "OpDecorate %SSBO_OUT BufferBlock\n"
6290                 "OpDecorate %ssboIN Binding 0\n"
6291                 "\n"//SSBO OUT
6292                 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6293                 "OpDecorate %ssboOUT DescriptorSet 0\n"
6294                 "OpDecorate %ssboOUT Binding 1\n");
6295
6296                 const StringTemplate                    testFun                         (
6297                 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6298                 "%param     = OpFunctionParameter %v4f32\n"
6299                 "%label     = OpLabel\n"
6300                 "%ndxArrx   = OpVariable %fp_i32  Function\n"
6301                 "%ndxArry   = OpVariable %fp_i32  Function\n"
6302                 "%ndxArrz   = OpVariable %fp_i32  Function\n"
6303                 "${xBeginLoop}"
6304                 "\n"//strutOut.b16 = strutIn.b16
6305                 "%inP1  = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %zero\n"
6306                 "%inV1  = OpLoad %i16 %inP1\n"
6307                 "%outP1 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %zero\n"
6308                 "OpStore %outP1 %inV1\n"
6309                 "\n"//strutOut.b32 = strutIn.b32
6310                 "%inP2  = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_1\n"
6311                 "%inV2  = OpLoad %i32 %inP2\n"
6312                 "%outP2 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_1\n"
6313                 "OpStore %outP2 %inV2\n"
6314                 "\n"//strutOut.v2b16 = strutIn.v2b16
6315                 "%inP3  = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_2\n"
6316                 "%inV3  = OpLoad %v2i16 %inP3\n"
6317                 "%outP3 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_2\n"
6318                 "OpStore %outP3 %inV3\n"
6319                 "\n"//strutOut.v2b32 = strutIn.v2b32
6320                 "%inP4  = OpAccessChain %v2i32${inPtr} %ssboIN %zero %Valx %c_i32_3\n"
6321                 "%inV4  = OpLoad %v2i32 %inP4\n"
6322                 "%outP4 = OpAccessChain %v2i32outPtr %ssboOUT %zero %Valx %c_i32_3\n"
6323                 "OpStore %outP4 %inV4\n"
6324                 "\n"//strutOut.v3b16 = strutIn.v3b16
6325                 "%inP5  = OpAccessChain %v3i16${inPtr} %ssboIN %zero %Valx %c_i32_4\n"
6326                 "%inV5  = OpLoad %v3i16 %inP5\n"
6327                 "%outP5 = OpAccessChain %v3i16outPtr %ssboOUT %zero %Valx %c_i32_4\n"
6328                 "OpStore %outP5 %inV5\n"
6329                 "\n"//strutOut.v3b32 = strutIn.v3b32
6330                 "%inP6  = OpAccessChain %v3i32${inPtr} %ssboIN %zero %Valx %c_i32_5\n"
6331                 "%inV6  = OpLoad %v3i32 %inP6\n"
6332                 "%outP6 = OpAccessChain %v3i32outPtr %ssboOUT %zero %Valx %c_i32_5\n"
6333                 "OpStore %outP6 %inV6\n"
6334                 "\n"//strutOut.v4b16 = strutIn.v4b16
6335                 "%inP7  = OpAccessChain %v4i16${inPtr} %ssboIN %zero %Valx %c_i32_6\n"
6336                 "%inV7  = OpLoad %v4i16 %inP7\n"
6337                 "%outP7 = OpAccessChain %v4i16outPtr %ssboOUT %zero %Valx %c_i32_6\n"
6338                 "OpStore %outP7 %inV7\n"
6339                 "\n"//strutOut.v4b32 = strutIn.v4b32
6340                 "%inP8  = OpAccessChain %v4i32${inPtr} %ssboIN %zero %Valx %c_i32_7\n"
6341                 "%inV8  = OpLoad %v4i32 %inP8\n"
6342                 "%outP8 = OpAccessChain %v4i32outPtr %ssboOUT %zero %Valx %c_i32_7\n"
6343                 "OpStore %outP8 %inV8\n"
6344                 "${yBeginLoop}"
6345                 "\n"//strutOut.b16[y] = strutIn.b16[y]
6346                 "%inP9  = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_9 %Valy\n"
6347                 "%inV9  = OpLoad %i16 %inP9\n"
6348                 "%outP9 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_9 %Valy\n"
6349                 "OpStore %outP9 %inV9\n"
6350                 "\n"//strutOut.b32[y] = strutIn.b32[y]
6351                 "%inP10  = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_10 %Valy\n"
6352                 "%inV10  = OpLoad %i32 %inP10\n"
6353                 "%outP10 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_10 %Valy\n"
6354                 "OpStore %outP10 %inV10\n"
6355                 "\n"//strutOut.strutNestedOut[y].b16 = strutIn.strutNestedIn[y].b16
6356                 "%inP11 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %zero\n"
6357                 "%inV11 = OpLoad %i16 %inP11\n"
6358                 "%outP11 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %zero\n"
6359                 "OpStore %outP11 %inV11\n"
6360                 "\n"//strutOut.strutNestedOut[y].b32 = strutIn.strutNestedIn[y].b32
6361                 "%inP12 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6362                 "%inV12 = OpLoad %i32 %inP12\n"
6363                 "%outP12 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6364                 "OpStore %outP12 %inV12\n"
6365                 "${zBeginLoop}"
6366                 "\n"//strutOut.strutNestedOut[y].v2b16[valNdx] = strutIn.strutNestedIn[y].v2b16[valNdx]
6367                 "%inP13  = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6368                 "%inV13  = OpLoad %v2i16 %inP13\n"
6369                 "%outP13 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6370                 "OpStore %outP13 %inV13\n"
6371                 "\n"//strutOut.strutNestedOut[y].b32[valNdx] = strutIn.strutNestedIn[y].b32[valNdx]
6372                 "%inP14  = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6373                 "%inV14  = OpLoad %i32 %inP14\n"
6374                 "%outP14 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6375                 "OpStore %outP14 %inV14\n"
6376                 "${zEndLoop}"
6377                 "${yEndLoop}"
6378                 "${xEndLoop}"
6379                 "\n"
6380                 "OpBranch %ExitLabel\n"
6381                 "%ExitLabel = OpLabel\n"
6382                 "OpReturnValue %param\n"
6383                 "OpFunctionEnd\n");
6384
6385         for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6386         {  // int
6387                 const bool                              isUniform       = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == CAPABILITIES[capIdx].dtype;
6388                 vector<deInt16>                 inData          = isUniform ? dataMixStd140(rnd) : dataMixStd430(rnd);
6389                 GraphicsResources               resources;
6390                 map<string, string>             specsLoop;
6391                 map<string, string>             specsOffset;
6392                 map<string, string>             specs;
6393                 string                                  testName        = string(CAPABILITIES[capIdx].name);
6394
6395                 specsLoop["exeCount"]   = "c_i32_7";
6396                 specsLoop["loopName"]   = "x";
6397                 specs["xBeginLoop"]             = beginLoop(specsLoop);
6398                 specs["xEndLoop"]               = endLoop(specsLoop);
6399
6400                 specsLoop["exeCount"]   = "c_i32_11";
6401                 specsLoop["loopName"]   = "y";
6402                 specs["yBeginLoop"]             = beginLoop(specsLoop);
6403                 specs["yEndLoop"]               = endLoop(specsLoop);
6404
6405                 specsLoop["exeCount"]   = "c_i32_11";
6406                 specsLoop["loopName"]   = "z";
6407                 specs["zBeginLoop"]             = beginLoop(specsLoop);
6408                 specs["zEndLoop"]               = endLoop(specsLoop);
6409
6410                 specs["storage"]                = isUniform ? "Block" : "BufferBlock";
6411                 specs["cap"]                    = isUniform ?"OpCapability " + string( CAPABILITIES[capIdx].cap) : "";
6412                 specs["inPtr"]                  = "outPtr";
6413                 specsOffset["InOut"]    = "In";
6414                 specs["InOffsets"]              = StringTemplate(isUniform ? getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD140) : getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6415                 specsOffset["InOut"]    = "Out";
6416                 specs["OutOffsets"]             = StringTemplate(getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6417
6418                 fragments["capability"]                 = capabilities.specialize(specs);
6419                 fragments["decoration"]                 = decoration.specialize(specs);
6420                 fragments["pre_main"]                   = preMain.specialize(specs);
6421                 fragments["testfun"]                    = testFun.specialize(specs);
6422
6423                 resources.verifyIO                              = isUniform ? graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD140, SHADERTEMPLATE_STRIDEMIX_STD430> : graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD430, SHADERTEMPLATE_STRIDEMIX_STD430>;
6424                 resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inData)), CAPABILITIES[capIdx].dtype));
6425                 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6426
6427                 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, group, get16BitStorageFeatures(CAPABILITIES[capIdx].name));
6428         }
6429 }
6430
6431 } // anonymous
6432
6433 tcu::TestCaseGroup* create16BitStorageComputeGroup (tcu::TestContext& testCtx)
6434 {
6435         de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Compute tests for VK_KHR_16bit_storage extension"));
6436         addTestGroup(group.get(), "uniform_32_to_16", "32bit floats/ints to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform32To16Group);
6437         addTestGroup(group.get(), "uniform_16_to_32", "16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To32Group);
6438         addTestGroup(group.get(), "push_constant_16_to_32", "16bit floats/ints to 32bit tests under capability StoragePushConstant16", addCompute16bitStoragePushConstant16To32Group);
6439         addTestGroup(group.get(), "uniform_16struct_to_32struct", "16bit floats struct to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16StructTo32StructGroup);
6440         addTestGroup(group.get(), "uniform_32struct_to_16struct", "32bit floats struct to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform32StructTo16StructGroup);
6441         addTestGroup(group.get(), "struct_mixed_types", "mixed type of 8bit and 32bit struct", addCompute16bitStructMixedTypesGroup);
6442         addTestGroup(group.get(), "uniform_16_to_16", "16bit floats/ints to 16bit tests under capability StorageUniformBufferBlock16", addCompute16bitStorageUniform16To16Group);
6443         addTestGroup(group.get(), "uniform_16_to_32_chainaccess", "chain access 16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To32ChainAccessGroup);
6444
6445         return group.release();
6446 }
6447
6448 tcu::TestCaseGroup* create16BitStorageGraphicsGroup (tcu::TestContext& testCtx)
6449 {
6450         de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Graphics tests for VK_KHR_16bit_storage extension"));
6451
6452         addTestGroup(group.get(), "uniform_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat32To16Group);
6453         addTestGroup(group.get(), "uniform_float_16_to_32", "16-bit floats into 32-bit testsunder capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat16To32Group);
6454         addTestGroup(group.get(), "uniform_int_32_to_16", "32-bit int into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt32To16Group);
6455         addTestGroup(group.get(), "uniform_int_16_to_32", "16-bit int into 32-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt16To32Group);
6456         addTestGroup(group.get(), "input_output_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat32To16Group);
6457         addTestGroup(group.get(), "input_output_float_16_to_32", "16-bit floats into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To32Group);
6458         addTestGroup(group.get(), "input_output_float_16_to_16", "16-bit floats pass-through tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To16Group);
6459         addTestGroup(group.get(), "input_output_int_32_to_16", "32-bit int into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt32To16Group);
6460         addTestGroup(group.get(), "input_output_int_16_to_32", "16-bit int into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To32Group);
6461         addTestGroup(group.get(), "input_output_int_16_to_16", "16-bit int into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To16Group);
6462         addTestGroup(group.get(), "push_constant_float_16_to_32", "16-bit floats into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantFloat16To32Group);
6463         addTestGroup(group.get(), "push_constant_int_16_to_32", "16-bit int into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantInt16To32Group);
6464         addTestGroup(group.get(), "uniform_16struct_to_32struct", "16-bit float struct into 32-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformStructFloat16To32Group);
6465         addTestGroup(group.get(), "uniform_32struct_to_16struct", "32-bit float struct into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformStructFloat32To16Group);
6466         addTestGroup(group.get(), "struct_mixed_types", "mixed type of 8bit and 32bit struct", addGraphics16bitStructMixedTypesGroup);
6467
6468         return group.release();
6469 }
6470
6471 } // SpirVAssembly
6472 } // vkt