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 #include "vktSpvAsm16bitStorageTests.hpp"
25
26 #include "tcuFloat.hpp"
27 #include "tcuRGBA.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuVectorUtil.hpp"
31
32 #include "vkDefs.hpp"
33 #include "vkDeviceUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkPlatform.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkStrUtil.hpp"
41 #include "vkTypeUtil.hpp"
42
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deMath.h"
47
48 #include "vktSpvAsmComputeShaderCase.hpp"
49 #include "vktSpvAsmComputeShaderTestUtil.hpp"
50 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
51 #include "vktSpvAsmUtils.hpp"
52 #include "vktTestCaseUtil.hpp"
53 #include "vktTestGroupUtil.hpp"
54
55 #include <limits>
56 #include <map>
57 #include <string>
58 #include <sstream>
59 #include <utility>
60
61 namespace vkt
62 {
63 namespace SpirVAssembly
64 {
65
66 using namespace vk;
67 using std::map;
68 using std::string;
69 using std::vector;
70 using tcu::Float16;
71 using tcu::IVec3;
72 using tcu::IVec4;
73 using tcu::RGBA;
74 using tcu::TestLog;
75 using tcu::TestStatus;
76 using tcu::Vec4;
77 using de::UniquePtr;
78 using tcu::StringTemplate;
79 using tcu::Vec4;
80
81 namespace
82 {
83
84 enum ShaderTemplate
85 {
86 SHADERTEMPLATE_TYPES = 0,
87 SHADERTEMPLATE_STRIDE32BIT_STD140,
88 SHADERTEMPLATE_STRIDE32BIT_STD430,
89 SHADERTEMPLATE_STRIDE16BIT_STD140,
90 SHADERTEMPLATE_STRIDE16BIT_STD430,
91 SHADERTEMPLATE_STRIDEMIX_STD140,
92 SHADERTEMPLATE_STRIDEMIX_STD430
93 };
94
compare16Bit(float original,deUint16 returned,RoundingModeFlags flags,tcu::TestLog & log)95 bool compare16Bit (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
96 {
97 return compare16BitFloat (original, returned, flags, log);
98 }
99
compare16Bit(deUint16 original,float returned,RoundingModeFlags flags,tcu::TestLog & log)100 bool compare16Bit (deUint16 original, float returned, RoundingModeFlags flags, tcu::TestLog& log)
101 {
102 DE_UNREF(flags);
103 return compare16BitFloat (original, returned, log);
104 }
105
compare16Bit(deInt16 original,deInt16 returned,RoundingModeFlags flags,tcu::TestLog & log)106 bool compare16Bit (deInt16 original, deInt16 returned, RoundingModeFlags flags, tcu::TestLog& log)
107 {
108 DE_UNREF(flags);
109 DE_UNREF(log);
110 return (returned == original);
111 }
112
113 struct StructTestData
114 {
115 const int structArraySize; //Size of Struct Array
116 const int nestedArraySize; //Max size of any nested arrays
117 };
118
119 struct Capability
120 {
121 const char* name;
122 const char* cap;
123 const char* decor;
124 vk::VkDescriptorType dtype;
125 };
126
127 static const Capability CAPABILITIES[] =
128 {
129 {"uniform_buffer_block", "StorageUniformBufferBlock16", "BufferBlock", VK_DESCRIPTOR_TYPE_STORAGE_BUFFER},
130 {"uniform", "StorageUniform16", "Block", VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER},
131 };
132
133 static const StructTestData structData = {7, 11};
134
135 enum TestDefDataType
136 {
137 DATATYPE_FLOAT,
138 DATATYPE_VEC2,
139 DATATYPE_INT,
140 DATATYPE_UINT,
141 DATATYPE_IVEC2,
142 DATATYPE_UVEC2
143 };
144
145 struct TestDefinition
146 {
147 InstanceContext instanceContext;
148 TestDefDataType dataType;
149 };
150
get16BitStorageFeatures(const char * cap)151 VulkanFeatures get16BitStorageFeatures (const char* cap)
152 {
153 VulkanFeatures features;
154 if (string(cap) == "uniform_buffer_block")
155 features.ext16BitStorage.storageBuffer16BitAccess = true;
156 else if (string(cap) == "uniform")
157 features.ext16BitStorage.uniformAndStorageBuffer16BitAccess = true;
158 else
159 DE_ASSERT(false && "not supported");
160
161 return features;
162 }
163
getStructSize(const ShaderTemplate shaderTemplate)164 int getStructSize(const ShaderTemplate shaderTemplate)
165 {
166 switch (shaderTemplate)
167 {
168 case SHADERTEMPLATE_STRIDE16BIT_STD140:
169 return 600 * structData.structArraySize; //size of struct in f16 with offsets
170 case SHADERTEMPLATE_STRIDE16BIT_STD430:
171 return 184 * structData.structArraySize; //size of struct in f16 with offsets
172 case SHADERTEMPLATE_STRIDE32BIT_STD140:
173 return 304 * structData.structArraySize; //size of struct in f32 with offsets
174 case SHADERTEMPLATE_STRIDE32BIT_STD430:
175 return 184 * structData.structArraySize; //size of struct in f32 with offset
176 case SHADERTEMPLATE_STRIDEMIX_STD140:
177 return 4480 * structData.structArraySize / 2; //size of struct in 16b with offset
178 case SHADERTEMPLATE_STRIDEMIX_STD430:
179 return 1216 * structData.structArraySize / 2; //size of struct in 16b with offset
180 default:
181 DE_ASSERT(0);
182 }
183 return 0;
184 }
185
186 // Batch function to check arrays of 16-bit floats.
187 //
188 // For comparing 16-bit floats, we need to consider both RTZ and RTE. So we can only recalculate
189 // the expected values here instead of get the expected values directly from the test case.
190 // Thus we need original floats here but not expected outputs.
191 template<RoundingModeFlags RoundingMode>
graphicsCheck16BitFloats(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog & log)192 bool graphicsCheck16BitFloats (const std::vector<Resource>& originalFloats,
193 const vector<AllocationSp>& outputAllocs,
194 const std::vector<Resource>& expectedOutputs,
195 tcu::TestLog& log)
196 {
197 if (outputAllocs.size() != originalFloats.size())
198 return false;
199
200 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
201 {
202 vector<deUint8> originalBytes;
203 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
204
205 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
206 const float* original = reinterpret_cast<const float*>(&originalBytes.front());
207 const deUint32 count = static_cast<deUint32>(expectedOutputs[outputNdx].getByteSize() / sizeof(deUint16));
208 const deUint32 inputStride = static_cast<deUint32>(originalBytes.size() / sizeof(float)) / count;
209
210 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
211 if (!compare16BitFloat(original[numNdx * inputStride], returned[numNdx], RoundingMode, log))
212 return false;
213 }
214
215 return true;
216 }
217
218 template<RoundingModeFlags RoundingMode>
graphicsCheck16BitFloats64(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,tcu::TestLog & log)219 bool graphicsCheck16BitFloats64 (const std::vector<Resource>& originalFloats,
220 const vector<AllocationSp>& outputAllocs,
221 const std::vector<Resource>& /* expectedOutputs */,
222 tcu::TestLog& log)
223 {
224 if (outputAllocs.size() != originalFloats.size())
225 return false;
226
227 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
228 {
229 vector<deUint8> originalBytes;
230 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
231
232 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
233 const double* original = reinterpret_cast<const double*>(&originalBytes.front());
234 const deUint32 count = static_cast<deUint32>(originalBytes.size() / sizeof(double));
235
236 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
237 if (!compare16BitFloat64(original[numNdx], returned[numNdx], RoundingMode, log))
238 return false;
239 }
240
241 return true;
242 }
243
computeCheckBuffersFloats(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,tcu::TestLog &)244 bool computeCheckBuffersFloats (const std::vector<Resource>& originalFloats,
245 const vector<AllocationSp>& outputAllocs,
246 const std::vector<Resource>& /*expectedOutputs*/,
247 tcu::TestLog& /*log*/)
248 {
249 std::vector<deUint8> result;
250 originalFloats.front().getBuffer()->getPackedBytes(result);
251
252 const deUint16 * results = reinterpret_cast<const deUint16 *>(&result[0]);
253 const deUint16 * expected = reinterpret_cast<const deUint16 *>(outputAllocs.front()->getHostPtr());
254
255 for (size_t i = 0; i < result.size() / sizeof (deUint16); ++i)
256 {
257 if (results[i] == expected[i])
258 continue;
259
260 if (Float16(results[i]).isNaN() && Float16(expected[i]).isNaN())
261 continue;
262
263 return false;
264 }
265
266 return true;
267 }
268
269 template<RoundingModeFlags RoundingMode>
computeCheck16BitFloats(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog & log)270 bool computeCheck16BitFloats (const std::vector<Resource>& originalFloats,
271 const vector<AllocationSp>& outputAllocs,
272 const std::vector<Resource>& expectedOutputs,
273 tcu::TestLog& log)
274 {
275 if (outputAllocs.size() != originalFloats.size())
276 return false;
277
278 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
279 {
280 vector<deUint8> originalBytes;
281 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
282
283 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
284 const float* original = reinterpret_cast<const float*>(&originalBytes.front());
285 const deUint32 count = static_cast<deUint32>(expectedOutputs[outputNdx].getByteSize() / sizeof(deUint16));
286 const deUint32 inputStride = static_cast<deUint32>(originalBytes.size() / sizeof(float)) / count;
287
288 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
289 if (!compare16BitFloat(original[numNdx * inputStride], returned[numNdx], RoundingMode, log))
290 return false;
291 }
292
293 return true;
294 }
295
296 template<RoundingModeFlags RoundingMode>
computeCheck16BitFloats64(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,tcu::TestLog & log)297 bool computeCheck16BitFloats64 (const std::vector<Resource>& originalFloats,
298 const vector<AllocationSp>& outputAllocs,
299 const std::vector<Resource>& /* expectedOutputs */,
300 tcu::TestLog& log)
301 {
302 if (outputAllocs.size() != originalFloats.size())
303 return false;
304
305 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
306 {
307 vector<deUint8> originalBytes;
308 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
309
310 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr());
311 const double* original = reinterpret_cast<const double*>(&originalBytes.front());
312 const deUint32 count = static_cast<deUint32>(originalBytes.size() / sizeof(double));
313
314 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
315 if (!compare16BitFloat64(original[numNdx], returned[numNdx], RoundingMode, log))
316 return false;
317 }
318
319 return true;
320 }
321
322 // Batch function to check arrays of 64-bit floats.
323 //
324 // For comparing 64-bit floats, we just need the expected value precomputed in the test case.
325 // So we need expected outputs here but not original floats.
check64BitFloats(const std::vector<Resource> &,const std::vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog & log)326 bool check64BitFloats (const std::vector<Resource>& /* originalFloats */,
327 const std::vector<AllocationSp>& outputAllocs,
328 const std::vector<Resource>& expectedOutputs,
329 tcu::TestLog& log)
330 {
331 if (outputAllocs.size() != expectedOutputs.size())
332 return false;
333
334 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
335 {
336 vector<deUint8> expectedBytes;
337 expectedOutputs[outputNdx].getBuffer()->getPackedBytes(expectedBytes);
338
339 const double* returnedAsDouble = static_cast<const double*>(outputAllocs[outputNdx]->getHostPtr());
340 const double* expectedAsDouble = reinterpret_cast<const double*>(&expectedBytes.front());
341 const deUint32 count = static_cast<deUint32>(expectedBytes.size() / sizeof(double));
342
343 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
344 if (!compare64BitFloat(expectedAsDouble[numNdx], returnedAsDouble[numNdx], log))
345 return false;
346 }
347
348 return true;
349 }
350
351 // Batch function to check arrays of 32-bit floats.
352 //
353 // For comparing 32-bit floats, we just need the expected value precomputed in the test case.
354 // So we need expected outputs here but not original floats.
check32BitFloats(const std::vector<Resource> &,const std::vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog & log)355 bool check32BitFloats (const std::vector<Resource>& /* originalFloats */,
356 const std::vector<AllocationSp>& outputAllocs,
357 const std::vector<Resource>& expectedOutputs,
358 tcu::TestLog& log)
359 {
360 if (outputAllocs.size() != expectedOutputs.size())
361 return false;
362
363 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
364 {
365 vector<deUint8> expectedBytes;
366 expectedOutputs[outputNdx].getBuffer()->getPackedBytes(expectedBytes);
367
368 const float* returnedAsFloat = static_cast<const float*>(outputAllocs[outputNdx]->getHostPtr());
369 const float* expectedAsFloat = reinterpret_cast<const float*>(&expectedBytes.front());
370 const deUint32 count = static_cast<deUint32>(expectedBytes.size() / sizeof(float));
371
372 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
373 if (!compare32BitFloat(expectedAsFloat[numNdx], returnedAsFloat[numNdx], log))
374 return false;
375 }
376
377 return true;
378 }
379
addInfo(vector<bool> & info,int & ndx,const int count,bool isData)380 void addInfo(vector<bool>& info, int& ndx, const int count, bool isData)
381 {
382 for (int index = 0; index < count; ++index)
383 info[ndx++] = isData;
384 }
385
data16bitStd140(de::Random & rnd)386 vector<deFloat16> data16bitStd140 (de::Random& rnd)
387 {
388 return getFloat16s(rnd, getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD140));
389 }
390
info16bitStd140(void)391 vector<bool> info16bitStd140 (void)
392 {
393 int ndx = 0u;
394 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD140));
395
396 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
397 {
398 infoData[ndx++] = true; //f16
399 infoData[ndx++] = false; //offset
400
401 infoData[ndx++] = true; //v2f16
402 infoData[ndx++] = true; //v2f16
403
404 addInfo(infoData, ndx, 3, true); //v3f16
405 infoData[ndx++] = false; //offset
406
407 addInfo(infoData, ndx, 4, true); //v4f16
408 addInfo(infoData, ndx, 4, false); //offset
409
410 //f16[3];
411 for (int i = 0; i < 3; ++i)
412 {
413 infoData[ndx++] = true; //f16[0];
414 addInfo(infoData, ndx, 7, false); //offset
415 }
416
417 //struct {f16, v2f16[3]} [11]
418 for (int i = 0; i < structData.nestedArraySize; ++i)
419 {
420 //struct.f16
421 infoData[ndx++] = true; //f16
422 addInfo(infoData, ndx, 7, false); //offset
423 //struct.f16.v2f16[3]
424 for (int j = 0; j < 3; ++j)
425 {
426 infoData[ndx++] = true; //v2f16
427 infoData[ndx++] = true; //v2f16
428 addInfo(infoData, ndx, 6, false); //offset
429 }
430 }
431
432 //vec2[11];
433 for (int i = 0; i < structData.nestedArraySize; ++i)
434 {
435 infoData[ndx++] = true; //v2f16
436 infoData[ndx++] = true; //v2f16
437 addInfo(infoData, ndx, 6, false); //offset
438 }
439
440 //f16
441 infoData[ndx++] = true; //f16
442 addInfo(infoData, ndx, 7, false); //offset
443
444 //vec3[11]
445 for (int i = 0; i < structData.nestedArraySize; ++i)
446 {
447 addInfo(infoData, ndx, 3, true); //vec3
448 addInfo(infoData, ndx, 5, false); //offset
449 }
450
451 //vec4[3]
452 for (int i = 0; i < 3; ++i)
453 {
454 addInfo(infoData, ndx, 4, true); //vec4
455 addInfo(infoData, ndx, 4, false); //offset
456 }
457 }
458
459 //Please check the data and offset
460 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
461
462 return infoData;
463 }
464
data16bitStd430(de::Random & rnd)465 vector<deFloat16> data16bitStd430 (de::Random& rnd)
466 {
467 return getFloat16s(rnd, getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430));
468 }
469
info16bitStd430(void)470 vector<bool> info16bitStd430 (void)
471 {
472 int ndx = 0u;
473 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430));
474
475 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
476 {
477 infoData[ndx++] = true; //f16
478 infoData[ndx++] = false; //offset
479
480 infoData[ndx++] = true; //v2f16
481 infoData[ndx++] = true; //v2f16
482
483 addInfo(infoData, ndx, 3, true); //v3f16
484 infoData[ndx++] = false; //offset
485
486 addInfo(infoData, ndx, 4, true); //v4f16
487
488 //f16[3];
489 for (int i = 0; i < 3; ++i)
490 {
491 infoData[ndx++] = true; //f16;
492 }
493 addInfo(infoData, ndx, 1, false); //offset
494
495 //struct {f16, v2f16[3]} [11]
496 for (int i = 0; i < structData.nestedArraySize; ++i)
497 {
498 //struct.f16
499 infoData[ndx++] = true; //f16
500 infoData[ndx++] = false; //offset
501 //struct.f16.v2f16[3]
502 for (int j = 0; j < 3; ++j)
503 {
504 infoData[ndx++] = true; //v2f16
505 infoData[ndx++] = true; //v2f16
506 }
507 }
508
509 //vec2[11];
510 for (int i = 0; i < structData.nestedArraySize; ++i)
511 {
512 infoData[ndx++] = true; //v2f16
513 infoData[ndx++] = true; //v2f16
514 }
515
516 //f16
517 infoData[ndx++] = true; //f16
518 infoData[ndx++] = false; //offset
519
520 //vec3[11]
521 for (int i = 0; i < structData.nestedArraySize; ++i)
522 {
523 addInfo(infoData, ndx, 3, true); //vec3
524 infoData[ndx++] = false; //offset
525 }
526
527 //vec4[3]
528 for (int i = 0; i < 3; ++i)
529 {
530 addInfo(infoData, ndx, 4, true); //vec4
531 }
532 }
533
534 //Please check the data and offset
535 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
536 return infoData;
537 }
538
data32bitStd140(de::Random & rnd)539 vector<float> data32bitStd140 (de::Random& rnd)
540 {
541 return getFloat32s(rnd, getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD140));
542 }
543
info32bitStd140(void)544 vector<bool> info32bitStd140 (void)
545 {
546 int ndx = 0u;
547 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD140));
548
549 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
550 {
551 infoData[ndx++] = true; //f32
552 infoData[ndx++] = false; //offset
553
554 infoData[ndx++] = true; //v2f32
555 infoData[ndx++] = true; //v2f32
556
557 addInfo(infoData, ndx, 3, true); //v3f32
558 infoData[ndx++] = false; //offset
559
560 addInfo(infoData, ndx, 4, true); //v4f16
561
562 //f32[3];
563 for (int i = 0; i < 3; ++i)
564 {
565 infoData[ndx++] = true; //f32;
566 addInfo(infoData, ndx, 3, false); //offset
567 }
568
569 //struct {f32, v2f32[3]} [11]
570 for (int i = 0; i < structData.nestedArraySize; ++i)
571 {
572 //struct.f32
573 infoData[ndx++] = true; //f32
574 addInfo(infoData, ndx, 3, false); //offset
575 //struct.f32.v2f16[3]
576 for (int j = 0; j < 3; ++j)
577 {
578 infoData[ndx++] = true; //v2f32
579 infoData[ndx++] = true; //v2f32
580 infoData[ndx++] = false; //offset
581 infoData[ndx++] = false; //offset
582 }
583 }
584
585 //v2f32[11];
586 for (int i = 0; i < structData.nestedArraySize; ++i)
587 {
588 infoData[ndx++] = true; //v2f32
589 infoData[ndx++] = true; //v2f32
590 infoData[ndx++] = false; //offset
591 infoData[ndx++] = false; //offset
592 }
593
594 //f16
595 infoData[ndx++] = true; //f16
596 addInfo(infoData, ndx, 3, false); //offset
597
598 //vec3[11]
599 for (int i = 0; i < structData.nestedArraySize; ++i)
600 {
601 addInfo(infoData, ndx, 3, true); //v3f32
602 infoData[ndx++] = false; //offset
603 }
604
605 //vec4[3]
606 for (int i = 0; i < 3; ++i)
607 {
608 addInfo(infoData, ndx, 4, true); //vec4
609 }
610 }
611
612 //Please check the data and offset
613 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
614 return infoData;
615 }
616
data32bitStd430(de::Random & rnd)617 vector<float> data32bitStd430 (de::Random& rnd)
618 {
619 return getFloat32s(rnd, getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430));
620 }
621
info32bitStd430(void)622 vector<bool> info32bitStd430 (void)
623 {
624 int ndx = 0u;
625 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430));
626
627 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
628 {
629 infoData[ndx++] = true; //f32
630 infoData[ndx++] = false; //offset
631
632 infoData[ndx++] = true; //v2f32
633 infoData[ndx++] = true; //v2f32
634
635 addInfo(infoData, ndx, 3, true); //v3f32
636 infoData[ndx++] = false; //offset
637
638 addInfo(infoData, ndx, 4, true); //v4f16
639
640 //f32[3];
641 for (int i = 0; i < 3; ++i)
642 {
643 infoData[ndx++] = true; //f32;
644 }
645 infoData[ndx++] = false; //offset
646
647 //struct {f32, v2f32[3]} [11]
648 for (int i = 0; i < structData.nestedArraySize; ++i)
649 {
650 //struct.f32
651 infoData[ndx++] = true; //f32
652 infoData[ndx++] = false; //offset
653 //struct.f32.v2f16[3]
654 for (int j = 0; j < 3; ++j)
655 {
656 infoData[ndx++] = true; //v2f32
657 infoData[ndx++] = true; //v2f32
658 }
659 }
660
661 //v2f32[11];
662 for (int i = 0; i < structData.nestedArraySize; ++i)
663 {
664 infoData[ndx++] = true; //v2f32
665 infoData[ndx++] = true; //v2f32
666 }
667
668 //f32
669 infoData[ndx++] = true; //f32
670 infoData[ndx++] = false; //offset
671
672 //vec3[11]
673 for (int i = 0; i < structData.nestedArraySize; ++i)
674 {
675 addInfo(infoData, ndx, 3, true); //v3f32
676 infoData[ndx++] = false; //offset
677 }
678
679 //vec4[3]
680 for (int i = 0; i < 3; ++i)
681 {
682 addInfo(infoData, ndx, 4, true); //vec4
683 }
684 }
685
686 //Please check the data and offset
687 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
688 return infoData;
689 }
690
dataMixStd140(de::Random & rnd)691 vector<deInt16> dataMixStd140 (de::Random& rnd)
692 {
693 return getInt16s(rnd, getStructSize(SHADERTEMPLATE_STRIDEMIX_STD140));
694 }
695
infoMixStd140(void)696 vector<bool> infoMixStd140 (void)
697 {
698 int ndx = 0u;
699 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD140));
700 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
701 {
702 infoData[ndx++] = true; //16b
703 addInfo(infoData, ndx, 1, false); //offset
704
705 addInfo(infoData, ndx, 2, true); //32b
706
707 addInfo(infoData, ndx, 2, true); //v2b16
708 addInfo(infoData, ndx, 2, false); //offset
709
710 addInfo(infoData, ndx, 4, true); //v2b32
711
712 addInfo(infoData, ndx, 3, true); //v3b16
713 addInfo(infoData, ndx, 1, false); //offset
714
715 addInfo(infoData, ndx, 6, true); //v3b32
716 addInfo(infoData, ndx, 2, false); //offset
717
718 addInfo(infoData, ndx, 4, true); //v4b16
719 addInfo(infoData, ndx, 4, false); //offset
720
721 addInfo(infoData, ndx, 8, true); //v4b32
722
723 //strut {b16, b32, v2b16[11], b32[11]}
724 for (int i = 0; i < structData.nestedArraySize; ++i)
725 {
726 infoData[ndx++] = true; //16b
727 addInfo(infoData, ndx, 1, false); //offset
728
729 addInfo(infoData, ndx, 2, true); //32b
730 addInfo(infoData, ndx, 4, false); //offset
731
732 for (int j = 0; j < structData.nestedArraySize; ++j)
733 {
734 addInfo(infoData, ndx, 2, true); //v2b16[11]
735 addInfo(infoData, ndx, 6, false); //offset
736 }
737
738 for (int j = 0; j < structData.nestedArraySize; ++j)
739 {
740 addInfo(infoData, ndx, 2, true); //b32[11]
741 addInfo(infoData, ndx, 6, false); //offset
742 }
743 }
744
745 for (int i = 0; i < structData.nestedArraySize; ++i)
746 {
747 infoData[ndx++] = true; //16b[11]
748 addInfo(infoData, ndx, 7, false); //offset
749 }
750
751 for (int i = 0; i < structData.nestedArraySize; ++i)
752 {
753 addInfo(infoData, ndx, 2, true); //b32bIn[11]
754 addInfo(infoData, ndx, 6, false); //offset
755 }
756 }
757
758 //Please check the data and offset
759 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
760 return infoData;
761 }
762
dataMixStd430(de::Random & rnd)763 vector<deInt16> dataMixStd430 (de::Random& rnd)
764 {
765 return getInt16s(rnd, getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430));
766 }
767
infoMixStd430(void)768 vector<bool> infoMixStd430 (void)
769 {
770 int ndx = 0u;
771 vector<bool> infoData (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430));
772 for(int elementNdx = 0; elementNdx < structData.structArraySize; ++elementNdx)
773 {
774 infoData[ndx++] = true; //16b
775 addInfo(infoData, ndx, 1, false); //offset
776
777 addInfo(infoData, ndx, 2, true); //32b
778
779 addInfo(infoData, ndx, 2, true); //v2b16
780 addInfo(infoData, ndx, 2, false); //offset
781
782 addInfo(infoData, ndx, 4, true); //v2b32
783
784 addInfo(infoData, ndx, 3, true); //v3b16
785 addInfo(infoData, ndx, 1, false); //offset
786
787 addInfo(infoData, ndx, 6, true); //v3b32
788 addInfo(infoData, ndx, 2, false); //offset
789
790 addInfo(infoData, ndx, 4, true); //v4b16
791 addInfo(infoData, ndx, 4, false); //offset
792
793 addInfo(infoData, ndx, 8, true); //v4b32
794
795 //strut {b16, b32, v2b16[11], b32[11]}
796 for (int i = 0; i < structData.nestedArraySize; ++i)
797 {
798 infoData[ndx++] = true; //16b
799 addInfo(infoData, ndx, 1, false); //offset
800
801 addInfo(infoData, ndx, 2, true); //32b
802
803 addInfo(infoData, ndx, 22, true); //v2b16[11]
804
805 addInfo(infoData, ndx, 22, true); //b32[11]
806 }
807
808 addInfo(infoData, ndx, 11, true); //16b[11]
809 infoData[ndx++] = false; //offset
810
811 addInfo(infoData, ndx, 22, true); //32b[11]
812 addInfo(infoData, ndx, 6, false); //offset
813 }
814
815 //Please check the data and offset
816 DE_ASSERT(ndx == static_cast<int>(infoData.size()));
817 return infoData;
818 }
819
820 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
compareStruct(const resultType * returned,const originType * original,tcu::TestLog & log)821 bool compareStruct(const resultType* returned, const originType* original, tcu::TestLog& log)
822 {
823 vector<bool> resultInfo;
824 vector<bool> originInfo;
825 vector<resultType> resultToCompare;
826 vector<originType> originToCompare;
827
828 switch(funcOrigin)
829 {
830 case SHADERTEMPLATE_STRIDE16BIT_STD140:
831 originInfo = info16bitStd140();
832 break;
833 case SHADERTEMPLATE_STRIDE16BIT_STD430:
834 originInfo = info16bitStd430();
835 break;
836 case SHADERTEMPLATE_STRIDE32BIT_STD140:
837 originInfo = info32bitStd140();
838 break;
839 case SHADERTEMPLATE_STRIDE32BIT_STD430:
840 originInfo = info32bitStd430();
841 break;
842 case SHADERTEMPLATE_STRIDEMIX_STD140:
843 originInfo = infoMixStd140();
844 break;
845 case SHADERTEMPLATE_STRIDEMIX_STD430:
846 originInfo = infoMixStd430();
847 break;
848 default:
849 DE_ASSERT(0);
850 }
851
852 switch(funcResult)
853 {
854 case SHADERTEMPLATE_STRIDE16BIT_STD140:
855 resultInfo = info16bitStd140();
856 break;
857 case SHADERTEMPLATE_STRIDE16BIT_STD430:
858 resultInfo = info16bitStd430();
859 break;
860 case SHADERTEMPLATE_STRIDE32BIT_STD140:
861 resultInfo = info32bitStd140();
862 break;
863 case SHADERTEMPLATE_STRIDE32BIT_STD430:
864 resultInfo = info32bitStd430();
865 break;
866 case SHADERTEMPLATE_STRIDEMIX_STD140:
867 resultInfo = infoMixStd140();
868 break;
869 case SHADERTEMPLATE_STRIDEMIX_STD430:
870 resultInfo = infoMixStd430();
871 break;
872 default:
873 DE_ASSERT(0);
874 }
875
876 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(resultInfo.size()); ++ndx)
877 {
878 if (resultInfo[ndx])
879 resultToCompare.push_back(returned[ndx]);
880 }
881
882 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(originInfo.size()); ++ndx)
883 {
884 if (originInfo[ndx])
885 originToCompare.push_back(original[ndx]);
886 }
887
888 //Different offset but that same amount of data
889 DE_ASSERT(originToCompare.size() == resultToCompare.size());
890 for (unsigned int ndx = 0; ndx < static_cast<unsigned int>(originToCompare.size()); ++ndx)
891 {
892 if (!compare16Bit(originToCompare[ndx], resultToCompare[ndx], RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ), log))
893 return false;
894 }
895 return true;
896 }
897
898 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
computeCheckStruct(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,tcu::TestLog & log)899 bool computeCheckStruct (const std::vector<Resource>& originalFloats,
900 const vector<AllocationSp>& outputAllocs,
901 const std::vector<Resource>& /* expectedOutputs */,
902 tcu::TestLog& log)
903 {
904 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
905 {
906 vector<deUint8> originalBytes;
907 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
908
909 const resultType* returned = static_cast<const resultType*>(outputAllocs[outputNdx]->getHostPtr());
910 const originType* original = reinterpret_cast<const originType*>(&originalBytes.front());
911
912 if(!compareStruct<originType, resultType, funcOrigin, funcResult>(returned, original, log))
913 return false;
914 }
915 return true;
916 }
917
918 template<typename originType, typename resultType, ShaderTemplate funcOrigin, ShaderTemplate funcResult>
graphicsCheckStruct(const std::vector<Resource> & originalFloats,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> &,tcu::TestLog & log)919 bool graphicsCheckStruct (const std::vector<Resource>& originalFloats,
920 const vector<AllocationSp>& outputAllocs,
921 const std::vector<Resource>& /* expectedOutputs */,
922 tcu::TestLog& log)
923 {
924 for (deUint32 outputNdx = 0; outputNdx < static_cast<deUint32>(outputAllocs.size()); ++outputNdx)
925 {
926 vector<deUint8> originalBytes;
927 originalFloats[outputNdx].getBuffer()->getPackedBytes(originalBytes);
928
929 const resultType* returned = static_cast<const resultType*>(outputAllocs[outputNdx]->getHostPtr());
930 const originType* original = reinterpret_cast<const originType*>(&originalBytes.front());
931
932 if(!compareStruct<originType, resultType, funcOrigin, funcResult>(returned, original, log))
933 return false;
934 }
935 return true;
936 }
937
getStructShaderComponet(const ShaderTemplate component)938 string getStructShaderComponet (const ShaderTemplate component)
939 {
940 switch(component)
941 {
942 case SHADERTEMPLATE_TYPES:
943 return string(
944 "%f16 = OpTypeFloat 16\n"
945 "%v2f16 = OpTypeVector %f16 2\n"
946 "%v3f16 = OpTypeVector %f16 3\n"
947 "%v4f16 = OpTypeVector %f16 4\n"
948 "%f16ptr = OpTypePointer Uniform %f16\n"
949 "%v2f16ptr = OpTypePointer Uniform %v2f16\n"
950 "%v3f16ptr = OpTypePointer Uniform %v3f16\n"
951 "%v4f16ptr = OpTypePointer Uniform %v4f16\n"
952 "\n"
953 "%f32ptr = OpTypePointer Uniform %f32\n"
954 "%v2f32ptr = OpTypePointer Uniform %v2f32\n"
955 "%v3f32ptr = OpTypePointer Uniform %v3f32\n"
956 "%v4f32ptr = OpTypePointer Uniform %v4f32\n");
957 case SHADERTEMPLATE_STRIDE16BIT_STD140:
958 return string(
959 //struct {f16, v2f16[3]} [11]
960 "OpDecorate %v2f16arr3 ArrayStride 16\n"
961 "OpMemberDecorate %struct16 0 Offset 0\n"
962 "OpMemberDecorate %struct16 1 Offset 16\n"
963 "OpDecorate %struct16arr11 ArrayStride 64\n"
964
965 "OpDecorate %f16arr3 ArrayStride 16\n"
966 "OpDecorate %v2f16arr11 ArrayStride 16\n"
967 "OpDecorate %v3f16arr11 ArrayStride 16\n"
968 "OpDecorate %v4f16arr3 ArrayStride 16\n"
969 "OpDecorate %f16StructArr7 ArrayStride 1200\n"
970 "\n"
971 "OpMemberDecorate %f16Struct 0 Offset 0\n" //f16
972 "OpMemberDecorate %f16Struct 1 Offset 4\n" //v2f16
973 "OpMemberDecorate %f16Struct 2 Offset 8\n" //v3f16
974 "OpMemberDecorate %f16Struct 3 Offset 16\n" //v4f16
975 "OpMemberDecorate %f16Struct 4 Offset 32\n" //f16[3]
976 "OpMemberDecorate %f16Struct 5 Offset 80\n" //struct {f16, v2f16[3]} [11]
977 "OpMemberDecorate %f16Struct 6 Offset 784\n" //v2f16[11]
978 "OpMemberDecorate %f16Struct 7 Offset 960\n" //f16
979 "OpMemberDecorate %f16Struct 8 Offset 976\n" //v3f16[11]
980 "OpMemberDecorate %f16Struct 9 Offset 1152\n"); //v4f16[3]
981
982 case SHADERTEMPLATE_STRIDE16BIT_STD430:
983 return string(
984 //struct {f16, v2f16[3]} [11]
985 "OpDecorate %v2f16arr3 ArrayStride 4\n"
986 "OpMemberDecorate %struct16 0 Offset 0\n"
987 "OpMemberDecorate %struct16 1 Offset 4\n"
988 "OpDecorate %struct16arr11 ArrayStride 16\n"
989
990 "OpDecorate %f16arr3 ArrayStride 2\n"
991 "OpDecorate %v2f16arr11 ArrayStride 4\n"
992 "OpDecorate %v3f16arr11 ArrayStride 8\n"
993 "OpDecorate %v4f16arr3 ArrayStride 8\n"
994 "OpDecorate %f16StructArr7 ArrayStride 368\n"
995 "\n"
996 "OpMemberDecorate %f16Struct 0 Offset 0\n" //f16
997 "OpMemberDecorate %f16Struct 1 Offset 4\n" //v2f16
998 "OpMemberDecorate %f16Struct 2 Offset 8\n" //v3f16
999 "OpMemberDecorate %f16Struct 3 Offset 16\n" //v4f16
1000 "OpMemberDecorate %f16Struct 4 Offset 24\n" //f16[3]
1001 "OpMemberDecorate %f16Struct 5 Offset 32\n" //struct {f16, v2f16[3]} [11]
1002 "OpMemberDecorate %f16Struct 6 Offset 208\n" //v2f16[11]
1003 "OpMemberDecorate %f16Struct 7 Offset 252\n" //f16
1004 "OpMemberDecorate %f16Struct 8 Offset 256\n" //v3f16[11]
1005 "OpMemberDecorate %f16Struct 9 Offset 344\n"); //v4f16[3]
1006 case SHADERTEMPLATE_STRIDE32BIT_STD140:
1007 return string (
1008 //struct {f32, v2f32[3]} [11]
1009 "OpDecorate %v2f32arr3 ArrayStride 16\n"
1010 "OpMemberDecorate %struct32 0 Offset 0\n"
1011 "OpMemberDecorate %struct32 1 Offset 16\n"
1012 "OpDecorate %struct32arr11 ArrayStride 64\n"
1013
1014 "OpDecorate %f32arr3 ArrayStride 16\n"
1015 "OpDecorate %v2f32arr11 ArrayStride 16\n"
1016 "OpDecorate %v3f32arr11 ArrayStride 16\n"
1017 "OpDecorate %v4f32arr3 ArrayStride 16\n"
1018 "OpDecorate %f32StructArr7 ArrayStride 1216\n"
1019 "\n"
1020
1021 "OpMemberDecorate %f32Struct 0 Offset 0\n" //f32
1022 "OpMemberDecorate %f32Struct 1 Offset 8\n" //v2f32
1023 "OpMemberDecorate %f32Struct 2 Offset 16\n" //v3f32
1024 "OpMemberDecorate %f32Struct 3 Offset 32\n" //v4f32
1025 "OpMemberDecorate %f32Struct 4 Offset 48\n" //f32[3]
1026 "OpMemberDecorate %f32Struct 5 Offset 96\n" //struct {f32, v2f32[3]} [11]
1027 "OpMemberDecorate %f32Struct 6 Offset 800\n" //v2f32[11]
1028 "OpMemberDecorate %f32Struct 7 Offset 976\n" //f32
1029 "OpMemberDecorate %f32Struct 8 Offset 992\n" //v3f32[11]
1030 "OpMemberDecorate %f32Struct 9 Offset 1168\n"); //v4f32[3]
1031
1032 case SHADERTEMPLATE_STRIDE32BIT_STD430:
1033 return string(
1034 //struct {f32, v2f32[3]} [11]
1035 "OpDecorate %v2f32arr3 ArrayStride 8\n"
1036 "OpMemberDecorate %struct32 0 Offset 0\n"
1037 "OpMemberDecorate %struct32 1 Offset 8\n"
1038 "OpDecorate %struct32arr11 ArrayStride 32\n"
1039
1040 "OpDecorate %f32arr3 ArrayStride 4\n"
1041 "OpDecorate %v2f32arr11 ArrayStride 8\n"
1042 "OpDecorate %v3f32arr11 ArrayStride 16\n"
1043 "OpDecorate %v4f32arr3 ArrayStride 16\n"
1044 "OpDecorate %f32StructArr7 ArrayStride 736\n"
1045 "\n"
1046
1047 "OpMemberDecorate %f32Struct 0 Offset 0\n" //f32
1048 "OpMemberDecorate %f32Struct 1 Offset 8\n" //v2f32
1049 "OpMemberDecorate %f32Struct 2 Offset 16\n" //v3f32
1050 "OpMemberDecorate %f32Struct 3 Offset 32\n" //v4f32
1051 "OpMemberDecorate %f32Struct 4 Offset 48\n" //f32[3]
1052 "OpMemberDecorate %f32Struct 5 Offset 64\n" //struct {f32, v2f32[3]}[11]
1053 "OpMemberDecorate %f32Struct 6 Offset 416\n" //v2f32[11]
1054 "OpMemberDecorate %f32Struct 7 Offset 504\n" //f32
1055 "OpMemberDecorate %f32Struct 8 Offset 512\n" //v3f32[11]
1056 "OpMemberDecorate %f32Struct 9 Offset 688\n"); //v4f32[3]
1057 case SHADERTEMPLATE_STRIDEMIX_STD140:
1058 return string(
1059 "\n"//strutNestedIn {b16, b32, v2b16[11], b32[11]}
1060 "OpDecorate %v2b16NestedArr11${InOut} ArrayStride 16\n" //v2b16[11]
1061 "OpDecorate %b32NestedArr11${InOut} ArrayStride 16\n" //b32[11]
1062 "OpMemberDecorate %sNested${InOut} 0 Offset 0\n" //b16
1063 "OpMemberDecorate %sNested${InOut} 1 Offset 4\n" //b32
1064 "OpMemberDecorate %sNested${InOut} 2 Offset 16\n" //v2b16[11]
1065 "OpMemberDecorate %sNested${InOut} 3 Offset 192\n" //b32[11]
1066 "OpDecorate %sNestedArr11${InOut} ArrayStride 368\n" //strutNestedIn[11]
1067 "\n"//strutIn {b16, b32, v2b16, v2b32, v3b16, v3b32, v4b16, v4b32, strutNestedIn[11], b16In[11], b32bIn[11]}
1068 "OpDecorate %sb16Arr11${InOut} ArrayStride 16\n" //b16In[11]
1069 "OpDecorate %sb32Arr11${InOut} ArrayStride 16\n" //b32bIn[11]
1070 "OpMemberDecorate %struct${InOut} 0 Offset 0\n" //b16
1071 "OpMemberDecorate %struct${InOut} 1 Offset 4\n" //b32
1072 "OpMemberDecorate %struct${InOut} 2 Offset 8\n" //v2b16
1073 "OpMemberDecorate %struct${InOut} 3 Offset 16\n" //v2b32
1074 "OpMemberDecorate %struct${InOut} 4 Offset 24\n" //v3b16
1075 "OpMemberDecorate %struct${InOut} 5 Offset 32\n" //v3b32
1076 "OpMemberDecorate %struct${InOut} 6 Offset 48\n" //v4b16
1077 "OpMemberDecorate %struct${InOut} 7 Offset 64\n" //v4b32
1078 "OpMemberDecorate %struct${InOut} 8 Offset 80\n" //strutNestedIn[11]
1079 "OpMemberDecorate %struct${InOut} 9 Offset 4128\n" //b16In[11]
1080 "OpMemberDecorate %struct${InOut} 10 Offset 4304\n" //b32bIn[11]
1081 "OpDecorate %structArr7${InOut} ArrayStride 4480\n"); //strutIn[7]
1082 case SHADERTEMPLATE_STRIDEMIX_STD430:
1083 return string(
1084 "\n"//strutNestedOut {b16, b32, v2b16[11], b32[11]}
1085 "OpDecorate %v2b16NestedArr11${InOut} ArrayStride 4\n" //v2b16[11]
1086 "OpDecorate %b32NestedArr11${InOut} ArrayStride 4\n" //b32[11]
1087 "OpMemberDecorate %sNested${InOut} 0 Offset 0\n" //b16
1088 "OpMemberDecorate %sNested${InOut} 1 Offset 4\n" //b32
1089 "OpMemberDecorate %sNested${InOut} 2 Offset 8\n" //v2b16[11]
1090 "OpMemberDecorate %sNested${InOut} 3 Offset 52\n" //b32[11]
1091 "OpDecorate %sNestedArr11${InOut} ArrayStride 96\n" //strutNestedOut[11]
1092 "\n"//strutOut {b16, b32, v2b16, v2b32, v3b16, v3b32, v4b16, v4b32, strutNestedOut[11], b16Out[11], b32bOut[11]}
1093 "OpDecorate %sb16Arr11${InOut} ArrayStride 2\n" //b16Out[11]
1094 "OpDecorate %sb32Arr11${InOut} ArrayStride 4\n" //b32bOut[11]
1095 "OpMemberDecorate %struct${InOut} 0 Offset 0\n" //b16
1096 "OpMemberDecorate %struct${InOut} 1 Offset 4\n" //b32
1097 "OpMemberDecorate %struct${InOut} 2 Offset 8\n" //v2b16
1098 "OpMemberDecorate %struct${InOut} 3 Offset 16\n" //v2b32
1099 "OpMemberDecorate %struct${InOut} 4 Offset 24\n" //v3b16
1100 "OpMemberDecorate %struct${InOut} 5 Offset 32\n" //v3b32
1101 "OpMemberDecorate %struct${InOut} 6 Offset 48\n" //v4b16
1102 "OpMemberDecorate %struct${InOut} 7 Offset 64\n" //v4b32
1103 "OpMemberDecorate %struct${InOut} 8 Offset 80\n" //strutNestedOut[11]
1104 "OpMemberDecorate %struct${InOut} 9 Offset 1136\n" //b16Out[11]
1105 "OpMemberDecorate %struct${InOut} 10 Offset 1160\n" //b32bOut[11]
1106 "OpDecorate %structArr7${InOut} ArrayStride 1216\n"); //strutOut[7]
1107
1108 default:
1109 return string("");
1110 }
1111 }
1112
1113 /*Return string contains spirv loop begin.
1114 the spec should contains "exeCount" - with name of const i32, it is number of executions
1115 the spec should contains "loopName" - suffix for all local names
1116 %Val${loopName} - index which can be used inside loop
1117 "%ndxArr${loopName} = OpVariable %fp_i32 Function\n" - has to be defined outside
1118 The function should be always use with endLoop function*/
beginLoop(const std::map<std::string,std::string> & spec)1119 std::string beginLoop(const std::map<std::string, std::string>& spec)
1120 {
1121 const tcu::StringTemplate loopBegin (
1122 "OpStore %ndxArr${loopName} %zero\n"
1123 "OpBranch %Loop${loopName}\n"
1124 "%Loop${loopName} = OpLabel\n"
1125 "OpLoopMerge %MergeLabel1${loopName} %MergeLabel2${loopName} None\n"
1126 "OpBranch %Label1${loopName}\n"
1127 "%Label1${loopName} = OpLabel\n"
1128 "%Val${loopName} = OpLoad %i32 %ndxArr${loopName}\n"
1129 "%LessThan${loopName} = OpSLessThan %bool %Val${loopName} %${exeCount}\n"
1130 "OpBranchConditional %LessThan${loopName} %ifLabel${loopName} %MergeLabel1${loopName}\n"
1131 "%ifLabel${loopName} = OpLabel\n");
1132 return loopBegin.specialize(spec);
1133 }
1134 /*Return string contains spirv loop end.
1135 the spec should contains "loopName" - suffix for all local names, suffix should be the same in beginLoop
1136 The function should be always use with beginLoop function*/
endLoop(const std::map<std::string,std::string> & spec)1137 std::string endLoop(const std::map<std::string, std::string>& spec)
1138 {
1139 const tcu::StringTemplate loopEnd (
1140 "OpBranch %MergeLabel2${loopName}\n"
1141 "%MergeLabel2${loopName} = OpLabel\n"
1142 "%plusOne${loopName} = OpIAdd %i32 %Val${loopName} %c_i32_1\n"
1143 "OpStore %ndxArr${loopName} %plusOne${loopName}\n"
1144 "OpBranch %Loop${loopName}\n"
1145 "%MergeLabel1${loopName} = OpLabel\n");
1146 return loopEnd.specialize(spec);
1147 }
1148
addCompute16bitStorageUniform16To32Group(tcu::TestCaseGroup * group)1149 void addCompute16bitStorageUniform16To32Group (tcu::TestCaseGroup* group)
1150 {
1151 tcu::TestContext& testCtx = group->getTestContext();
1152 de::Random rnd (deStringHash(group->getName()));
1153 const int numElements = 128;
1154
1155 const StringTemplate shaderTemplate (
1156 "OpCapability Shader\n"
1157 "OpCapability ${capability}\n"
1158 "OpExtension \"SPV_KHR_16bit_storage\"\n"
1159 "OpMemoryModel Logical GLSL450\n"
1160 "OpEntryPoint GLCompute %main \"main\" %id\n"
1161 "OpExecutionMode %main LocalSize 1 1 1\n"
1162 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1163
1164 "${stride}\n"
1165
1166 "OpMemberDecorate %SSBO32 0 Offset 0\n"
1167 "OpMemberDecorate %SSBO16 0 Offset 0\n"
1168 "OpDecorate %SSBO32 BufferBlock\n"
1169 "OpDecorate %SSBO16 ${storage}\n"
1170 "OpDecorate %ssbo32 DescriptorSet 0\n"
1171 "OpDecorate %ssbo16 DescriptorSet 0\n"
1172 "OpDecorate %ssbo32 Binding 1\n"
1173 "OpDecorate %ssbo16 Binding 0\n"
1174
1175 "${matrix_decor:opt}\n"
1176
1177 "%bool = OpTypeBool\n"
1178 "%void = OpTypeVoid\n"
1179 "%voidf = OpTypeFunction %void\n"
1180 "%u32 = OpTypeInt 32 0\n"
1181 "%i32 = OpTypeInt 32 1\n"
1182 "%f32 = OpTypeFloat 32\n"
1183 "%v3u32 = OpTypeVector %u32 3\n"
1184 "%uvec3ptr = OpTypePointer Input %v3u32\n"
1185 "%i32ptr = OpTypePointer Uniform %i32\n"
1186 "%f32ptr = OpTypePointer Uniform %f32\n"
1187
1188 "%zero = OpConstant %i32 0\n"
1189 "%c_i32_1 = OpConstant %i32 1\n"
1190 "%c_i32_2 = OpConstant %i32 2\n"
1191 "%c_i32_3 = OpConstant %i32 3\n"
1192 "%c_i32_16 = OpConstant %i32 16\n"
1193 "%c_i32_32 = OpConstant %i32 32\n"
1194 "%c_i32_64 = OpConstant %i32 64\n"
1195 "%c_i32_128 = OpConstant %i32 128\n"
1196 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
1197
1198 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
1199 "%f32arr = OpTypeArray %f32 %c_i32_128\n"
1200
1201 "${types}\n"
1202 "${matrix_types:opt}\n"
1203
1204 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
1205 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
1206 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
1207 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
1208 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n"
1209 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
1210
1211 "%id = OpVariable %uvec3ptr Input\n"
1212
1213 "%main = OpFunction %void None %voidf\n"
1214 "%label = OpLabel\n"
1215 "%idval = OpLoad %v3u32 %id\n"
1216 "%x = OpCompositeExtract %u32 %idval 0\n"
1217 "%inloc = OpAccessChain %${base16}ptr %ssbo16 %zero %${arrayindex} ${index0:opt}\n"
1218 "%val16 = OpLoad %${base16} %inloc\n"
1219 "%val32 = ${convert} %${base32} %val16\n"
1220 "%outloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
1221 " OpStore %outloc %val32\n"
1222 "${matrix_store:opt}\n"
1223 " OpReturn\n"
1224 " OpFunctionEnd\n");
1225
1226 { // floats
1227 const char floatTypes[] =
1228 "%f16 = OpTypeFloat 16\n"
1229 "%f16ptr = OpTypePointer Uniform %f16\n"
1230 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
1231 "%v2f16 = OpTypeVector %f16 2\n"
1232 "%v2f32 = OpTypeVector %f32 2\n"
1233 "%v2f16ptr = OpTypePointer Uniform %v2f16\n"
1234 "%v2f32ptr = OpTypePointer Uniform %v2f32\n"
1235 "%v2f16arr = OpTypeArray %v2f16 %c_i32_64\n"
1236 "%v2f32arr = OpTypeArray %v2f32 %c_i32_64\n";
1237
1238 struct CompositeType
1239 {
1240 const char* name;
1241 const char* base32;
1242 const char* base16;
1243 const char* stride;
1244 bool useConstantIndex;
1245 unsigned constantIndex;
1246 unsigned count;
1247 unsigned inputStride;
1248 };
1249
1250 const CompositeType cTypes[2][5] =
1251 {
1252 {
1253 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", false, 0, numElements, 1},
1254 {"scalar_const_idx_5", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", true, 5, numElements, 1},
1255 {"scalar_const_idx_8", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", true, 8, numElements, 1},
1256 {"vector", "v2f32", "v2f16", "OpDecorate %v2f32arr ArrayStride 8\nOpDecorate %v2f16arr ArrayStride 4\n", false, 0, numElements / 2, 2},
1257 {"matrix", "v2f32", "v2f16", "OpDecorate %m4v2f32arr ArrayStride 32\nOpDecorate %m4v2f16arr ArrayStride 16\n", false, 0, numElements / 8, 8}
1258 },
1259 {
1260 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n", false, 0, numElements, 8},
1261 {"scalar_const_idx_5", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n", true, 5, numElements, 8},
1262 {"scalar_const_idx_8", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 16\n", true, 8, numElements, 8},
1263 {"vector", "v2f32", "v2f16", "OpDecorate %v2f32arr ArrayStride 8\nOpDecorate %v2f16arr ArrayStride 16\n", false, 0, numElements / 2, 8},
1264 {"matrix", "v2f32", "v2f16", "OpDecorate %m4v2f32arr ArrayStride 32\nOpDecorate %m4v2f16arr ArrayStride 16\n", false, 0, numElements / 8, 8}
1265 }
1266 };
1267
1268 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1269 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
1270 {
1271 ComputeShaderSpec spec;
1272 map<string, string> specs;
1273 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name + "_float";
1274
1275 specs["capability"] = CAPABILITIES[capIdx].cap;
1276 specs["storage"] = CAPABILITIES[capIdx].decor;
1277 specs["stride"] = cTypes[capIdx][tyIdx].stride;
1278 specs["base32"] = cTypes[capIdx][tyIdx].base32;
1279 specs["base16"] = cTypes[capIdx][tyIdx].base16;
1280 specs["types"] = floatTypes;
1281 specs["convert"] = "OpFConvert";
1282 specs["constarrayidx"] = de::toString(cTypes[capIdx][tyIdx].constantIndex);
1283 if (cTypes[capIdx][tyIdx].useConstantIndex)
1284 specs["arrayindex"] = "c_i32_ci";
1285 else
1286 specs["arrayindex"] = "x";
1287
1288 const deUint32 inputStride = cTypes[capIdx][tyIdx].inputStride;
1289 const deUint32 count = cTypes[capIdx][tyIdx].count;
1290 const deUint32 scalarsPerItem = numElements / count;
1291 vector<deFloat16> float16Data = getFloat16s(rnd, numElements * inputStride);
1292 vector<float> float32Data;
1293
1294 float32Data.reserve(numElements);
1295 for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
1296 for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; scalarIdx++)
1297 float32Data.push_back(deFloat16To32(float16Data[numIdx * inputStride + scalarIdx]));
1298
1299 vector<float> float32DataConstIdx;
1300 if (cTypes[capIdx][tyIdx].useConstantIndex)
1301 {
1302 const deUint32 numFloats = numElements / cTypes[capIdx][tyIdx].count;
1303 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1304 float32DataConstIdx.push_back(float32Data[cTypes[capIdx][tyIdx].constantIndex * numFloats + numIdx % numFloats]);
1305 }
1306
1307 if (strcmp(cTypes[capIdx][tyIdx].name, "matrix") == 0)
1308 {
1309 specs["index0"] = "%zero";
1310 specs["matrix_prefix"] = "m4";
1311 specs["matrix_types"] =
1312 "%m4v2f16 = OpTypeMatrix %v2f16 4\n"
1313 "%m4v2f32 = OpTypeMatrix %v2f32 4\n"
1314 "%m4v2f16arr = OpTypeArray %m4v2f16 %c_i32_16\n"
1315 "%m4v2f32arr = OpTypeArray %m4v2f32 %c_i32_16\n";
1316 specs["matrix_decor"] =
1317 "OpMemberDecorate %SSBO32 0 ColMajor\n"
1318 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n"
1319 "OpMemberDecorate %SSBO16 0 ColMajor\n"
1320 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n";
1321 specs["matrix_store"] =
1322 "%inloc_1 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_1\n"
1323 "%val16_1 = OpLoad %v2f16 %inloc_1\n"
1324 "%val32_1 = OpFConvert %v2f32 %val16_1\n"
1325 "%outloc_1 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_1\n"
1326 " OpStore %outloc_1 %val32_1\n"
1327
1328 "%inloc_2 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_2\n"
1329 "%val16_2 = OpLoad %v2f16 %inloc_2\n"
1330 "%val32_2 = OpFConvert %v2f32 %val16_2\n"
1331 "%outloc_2 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_2\n"
1332 " OpStore %outloc_2 %val32_2\n"
1333
1334 "%inloc_3 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_3\n"
1335 "%val16_3 = OpLoad %v2f16 %inloc_3\n"
1336 "%val32_3 = OpFConvert %v2f32 %val16_3\n"
1337 "%outloc_3 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_3\n"
1338 " OpStore %outloc_3 %val32_3\n";
1339 }
1340
1341 spec.assembly = shaderTemplate.specialize(specs);
1342 spec.numWorkGroups = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
1343 spec.verifyIO = check32BitFloats;
1344
1345 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), CAPABILITIES[capIdx].dtype));
1346 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(cTypes[capIdx][tyIdx].useConstantIndex ? float32DataConstIdx : float32Data))));
1347 spec.extensions.push_back("VK_KHR_16bit_storage");
1348 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1349
1350 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1351 }
1352 }
1353
1354 { // Integers
1355 const char sintTypes[] =
1356 "%i16 = OpTypeInt 16 1\n"
1357 "%i16ptr = OpTypePointer Uniform %i16\n"
1358 "%i16arr = OpTypeArray %i16 %c_i32_128\n"
1359 "%v4i16 = OpTypeVector %i16 4\n"
1360 "%v4i32 = OpTypeVector %i32 4\n"
1361 "%v4i16ptr = OpTypePointer Uniform %v4i16\n"
1362 "%v4i32ptr = OpTypePointer Uniform %v4i32\n"
1363 "%v4i16arr = OpTypeArray %v4i16 %c_i32_32\n"
1364 "%v4i32arr = OpTypeArray %v4i32 %c_i32_32\n";
1365
1366 const char uintTypes[] =
1367 "%u16 = OpTypeInt 16 0\n"
1368 "%u16ptr = OpTypePointer Uniform %u16\n"
1369 "%u32ptr = OpTypePointer Uniform %u32\n"
1370 "%u16arr = OpTypeArray %u16 %c_i32_128\n"
1371 "%u32arr = OpTypeArray %u32 %c_i32_128\n"
1372 "%v4u16 = OpTypeVector %u16 4\n"
1373 "%v4u32 = OpTypeVector %u32 4\n"
1374 "%v4u16ptr = OpTypePointer Uniform %v4u16\n"
1375 "%v4u32ptr = OpTypePointer Uniform %v4u32\n"
1376 "%v4u16arr = OpTypeArray %v4u16 %c_i32_32\n"
1377 "%v4u32arr = OpTypeArray %v4u32 %c_i32_32\n";
1378
1379 struct CompositeType
1380 {
1381 const char* name;
1382 bool isSigned;
1383 const char* types;
1384 const char* base32;
1385 const char* base16;
1386 const char* opcode;
1387 const char* stride;
1388 bool useConstantIndex;
1389 unsigned constantIndex;
1390 unsigned count;
1391 unsigned inputStride;
1392 };
1393
1394 const CompositeType cTypes[2][8] =
1395 {
1396 {
1397 {"scalar_sint", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", false, 0, numElements, 1},
1398 {"scalar_sint_const_idx_5", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", true, 5, numElements, 1},
1399 {"scalar_sint_const_idx_8", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", true, 8, numElements, 1},
1400 {"scalar_uint", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", false, 0, numElements, 1},
1401 {"scalar_uint_const_idx_5", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", true, 5, numElements, 1},
1402 {"scalar_uint_const_idx_8", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", true, 8, numElements, 1},
1403 {"vector_sint", true, sintTypes, "v4i32", "v4i16", "OpSConvert", "OpDecorate %v4i32arr ArrayStride 16\nOpDecorate %v4i16arr ArrayStride 8\n", false, 0, numElements / 4, 4},
1404 {"vector_uint", false, uintTypes, "v4u32", "v4u16", "OpUConvert", "OpDecorate %v4u32arr ArrayStride 16\nOpDecorate %v4u16arr ArrayStride 8\n", false, 0, numElements / 4, 4}
1405 },
1406 {
1407 {"scalar_sint", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n", false, 0, numElements, 8},
1408 {"scalar_sint_const_idx_5", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n", true, 5, numElements, 8},
1409 {"scalar_sint_const_idx_8", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 16\n", true, 8, numElements, 8},
1410 {"scalar_uint", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n", false, 0, numElements, 8},
1411 {"scalar_uint_const_idx_5", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n", true, 5, numElements, 8},
1412 {"scalar_uint_const_idx_8", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 16\n", true, 8, numElements, 8},
1413 {"vector_sint", true, sintTypes, "v4i32", "v4i16", "OpSConvert", "OpDecorate %v4i32arr ArrayStride 16\nOpDecorate %v4i16arr ArrayStride 16\n", false, 0, numElements / 4, 8},
1414 {"vector_uint", false, uintTypes, "v4u32", "v4u16", "OpUConvert", "OpDecorate %v4u32arr ArrayStride 16\nOpDecorate %v4u16arr ArrayStride 16\n", false, 0, numElements / 4, 8}
1415 }
1416 };
1417
1418 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1419 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
1420 {
1421 ComputeShaderSpec spec;
1422 map<string, string> specs;
1423 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name;
1424 const deUint32 inputStride = cTypes[capIdx][tyIdx].inputStride;
1425 vector<deInt16> inputs = getInt16s(rnd, numElements * inputStride);
1426 vector<deInt32> sOutputs;
1427 vector<deInt32> uOutputs;
1428 const deUint16 signBitMask = 0x8000;
1429 const deUint32 signExtendMask = 0xffff0000;
1430 const deUint32 count = cTypes[capIdx][tyIdx].count;
1431 const deUint32 scalarsPerItem = numElements / count;
1432
1433 sOutputs.reserve(numElements);
1434 uOutputs.reserve(numElements);
1435
1436 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
1437 for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; ++scalarIdx)
1438 {
1439 const deInt16 input = inputs[numNdx * inputStride + scalarIdx];
1440
1441 uOutputs.push_back(static_cast<deUint16>(input));
1442 if (input & signBitMask)
1443 sOutputs.push_back(static_cast<deInt32>(input | signExtendMask));
1444 else
1445 sOutputs.push_back(static_cast<deInt32>(input));
1446 }
1447
1448 vector<deInt32> intDataConstIdx;
1449
1450 if (cTypes[capIdx][tyIdx].useConstantIndex)
1451 {
1452 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1453 {
1454 const deInt32 idx = cTypes[capIdx][tyIdx].constantIndex * scalarsPerItem + numIdx % scalarsPerItem;
1455
1456 if (cTypes[capIdx][tyIdx].isSigned)
1457 intDataConstIdx.push_back(sOutputs[idx]);
1458 else
1459 intDataConstIdx.push_back(uOutputs[idx]);
1460 }
1461 }
1462
1463 specs["capability"] = CAPABILITIES[capIdx].cap;
1464 specs["storage"] = CAPABILITIES[capIdx].decor;
1465 specs["stride"] = cTypes[capIdx][tyIdx].stride;
1466 specs["base32"] = cTypes[capIdx][tyIdx].base32;
1467 specs["base16"] = cTypes[capIdx][tyIdx].base16;
1468 specs["types"] = cTypes[capIdx][tyIdx].types;
1469 specs["convert"] = cTypes[capIdx][tyIdx].opcode;
1470 specs["constarrayidx"] = de::toString(cTypes[capIdx][tyIdx].constantIndex);
1471 if (cTypes[capIdx][tyIdx].useConstantIndex)
1472 specs["arrayindex"] = "c_i32_ci";
1473 else
1474 specs["arrayindex"] = "x";
1475
1476 spec.assembly = shaderTemplate.specialize(specs);
1477 spec.numWorkGroups = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
1478
1479 spec.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputs)), CAPABILITIES[capIdx].dtype));
1480 if (cTypes[capIdx][tyIdx].useConstantIndex)
1481 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(intDataConstIdx))));
1482 else if (cTypes[capIdx][tyIdx].isSigned)
1483 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs))));
1484 else
1485 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs))));
1486 spec.extensions.push_back("VK_KHR_16bit_storage");
1487 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1488
1489 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1490 }
1491 }
1492 }
1493
addCompute16bitStorageUniform16To32ChainAccessGroup(tcu::TestCaseGroup * group)1494 void addCompute16bitStorageUniform16To32ChainAccessGroup (tcu::TestCaseGroup* group)
1495 {
1496 tcu::TestContext& testCtx = group->getTestContext();
1497 de::Random rnd (deStringHash(group->getName()));
1498 const deUint32 structSize = 128; // In number of 16bit items. Includes padding.
1499 vector<deFloat16> inputDataFloat = getFloat16s(rnd, structSize * 4);
1500 vector<deInt16> inputDataInt = getInt16s(rnd, structSize * 4);
1501 vector<float> outputDataFloat;
1502 vector<deInt32> outputDataSInt;
1503 vector<deInt32> outputDataUInt;
1504 vector<tcu::UVec4> indices;
1505
1506 // Input is an array of a struct that varies on 16bit data type being tested:
1507 //
1508 // Float:
1509 //
1510 // float16 scalars[3]
1511 // mat4x3 matrix
1512 // vec3 vector
1513 //
1514 // Int:
1515 //
1516 // int16 scalars[3]
1517 // int16 array2D[4][3]
1518 // ivec3 vector
1519 //
1520 // UInt:
1521 //
1522 // uint16 scalars[3]
1523 // uint16 array2D[4][3]
1524 // uvec3 vector
1525
1526 const StringTemplate shaderTemplate (
1527 " OpCapability Shader\n"
1528 " OpCapability ${capability}\n"
1529 " OpExtension \"SPV_KHR_16bit_storage\"\n"
1530 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
1531 " OpMemoryModel Logical GLSL450\n"
1532 " OpEntryPoint GLCompute %main \"main\"\n"
1533 " OpExecutionMode %main LocalSize 1 1 1\n"
1534 " OpSource GLSL 430\n"
1535 " OpDecorate %Output BufferBlock\n"
1536 " OpDecorate %dataOutput DescriptorSet 0\n"
1537 " OpDecorate %dataOutput Binding 1\n"
1538 " OpDecorate %scalarArray ArrayStride 16\n"
1539 " OpDecorate %scalarArray2D ArrayStride 48\n"
1540 " OpMemberDecorate %S 0 Offset 0\n"
1541 " OpMemberDecorate %S 1 Offset 48\n"
1542 " ${decoration:opt}\n"
1543 " OpMemberDecorate %S 2 Offset 240\n"
1544 " OpDecorate %_arr_S_uint_4 ArrayStride 256\n"
1545 " OpMemberDecorate %Input 0 Offset 0\n"
1546 " OpMemberDecorate %Output 0 Offset 0\n"
1547 " OpDecorate %Input ${storage}\n"
1548 " OpDecorate %dataInput DescriptorSet 0\n"
1549 " OpDecorate %dataInput Binding 0\n"
1550 " %f16 = OpTypeFloat 16\n"
1551 " %f32 = OpTypeFloat 32\n"
1552 " %i16 = OpTypeInt 16 1\n"
1553 " %i32 = OpTypeInt 32 1\n"
1554 " %u16 = OpTypeInt 16 0\n"
1555 " %u32 = OpTypeInt 32 0\n"
1556 " %void = OpTypeVoid\n"
1557 " %voidFunc = OpTypeFunction %void\n"
1558 " %_ptr_Function_uint = OpTypePointer Function %u32\n"
1559 " %v3u32 = OpTypeVector %u32 3\n"
1560 " %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
1561 " %int_0 = OpConstant %i32 0\n"
1562 " %uint_3 = OpConstant %u32 3\n"
1563 " %uint_4 = OpConstant %u32 4\n"
1564 " %s0 = OpConstant %u32 ${s0}\n"
1565 " %s1 = OpConstant %u32 ${s1}\n"
1566 " %s2 = OpConstant %u32 ${s2}\n"
1567 " %s3 = OpConstant %u32 ${s3}\n"
1568 " %Output = OpTypeStruct %${type}32\n"
1569 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
1570 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
1571 " %scalarArray = OpTypeArray %${type}16 %uint_3\n"
1572 " %v3f16 = OpTypeVector %f16 3\n"
1573 " %v3i16 = OpTypeVector %i16 3\n"
1574 " %v3u16 = OpTypeVector %u16 3\n"
1575 " %matrix = OpTypeMatrix %v3f16 4\n"
1576 " %scalarArray2D = OpTypeArray %scalarArray %uint_4\n"
1577 " %S = OpTypeStruct %scalarArray %${type2D} %v3${type}16\n"
1578 " %_arr_S_uint_4 = OpTypeArray %S %uint_4\n"
1579 " %Input = OpTypeStruct %_arr_S_uint_4\n"
1580 " %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
1581 " %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
1582 " %_ptr_Uniform_16bit_data = OpTypePointer Uniform %${type}16\n"
1583 " %_ptr_Uniform_32bit_data = OpTypePointer Uniform %${type}32\n"
1584 " %main = OpFunction %void None %voidFunc\n"
1585 " %entry = OpLabel\n"
1586 " %dataPtr = ${accessChain}\n"
1587 " %data = OpLoad %${type}16 %dataPtr\n"
1588 " %converted = ${convert}\n"
1589 " %outPtr = OpAccessChain %_ptr_Uniform_32bit_data %dataOutput %int_0\n"
1590 " OpStore %outPtr %converted\n"
1591 " OpReturn\n"
1592 " OpFunctionEnd\n");
1593
1594 // Generate constant indices for OpChainAccess. We need to use constant values
1595 // when indexing into structures. This loop generates all permutations.
1596 for (deUint32 idx0 = 0; idx0 < 4; ++idx0)
1597 for (deUint32 idx1 = 0; idx1 < 3; ++idx1)
1598 for (deUint32 idx2 = 0; idx2 < (idx1 == 1u ? 4u : 3u); ++idx2)
1599 for (deUint32 idx3 = 0; idx3 < (idx1 == 1u ? 3u : 1u); ++idx3)
1600 indices.push_back(tcu::UVec4(idx0, idx1, idx2, idx3));
1601
1602
1603 for (deUint32 numIdx = 0; numIdx < (deUint32)indices.size(); ++numIdx)
1604 {
1605 const deUint16 signBitMask = 0x8000;
1606 const deUint32 signExtendMask = 0xffff0000;
1607 // Determine the selected output float for the selected indices.
1608 const tcu::UVec4 vec = indices[numIdx];
1609 // Offsets are in multiples of 16bits. Floats are using matrix as the
1610 // second field, which has different layout rules than 2D array.
1611 // Therefore separate offset tables are needed.
1612 const deUint32 fieldOffsetsFloat[3][3] =
1613 {
1614 {0u, 8u, 0u},
1615 {24, 24u, 1u},
1616 {120u, 1u, 0u}
1617 };
1618 const deUint32 fieldOffsetsInt[3][3] =
1619 {
1620 {0u, 8u, 0u},
1621 {24, 24u, 8u},
1622 {120u, 1u, 0u}
1623 };
1624 const deUint32 offsetFloat = vec.x() * structSize + fieldOffsetsFloat[vec.y()][0] + fieldOffsetsFloat[vec.y()][1] * vec.z() + fieldOffsetsFloat[vec.y()][2] * vec.w();
1625 const deUint32 offsetInt = vec.x() * structSize + fieldOffsetsInt[vec.y()][0] + fieldOffsetsInt[vec.y()][1] * vec.z() + fieldOffsetsInt[vec.y()][2] * vec.w();
1626 const bool hasSign = inputDataInt[offsetInt] & signBitMask;
1627
1628 outputDataFloat.push_back(deFloat16To32(inputDataFloat[offsetFloat]));
1629 outputDataUInt.push_back((deUint16)inputDataInt[offsetInt]);
1630 outputDataSInt.push_back((deInt32)(inputDataInt[offsetInt] | (hasSign ? signExtendMask : 0u)));
1631 }
1632
1633 for (deUint32 indicesIdx = 0; indicesIdx < (deUint32)indices.size(); ++indicesIdx)
1634 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
1635 {
1636 string indexString = de::toString(indices[indicesIdx].x()) + "_" + de::toString(indices[indicesIdx].y()) + "_" + de::toString(indices[indicesIdx].z());
1637 if (indices[indicesIdx].y() == 1)
1638 indexString += string("_") + de::toString(indices[indicesIdx].w());
1639
1640 const string testNameBase = string(CAPABILITIES[capIdx].name) + "_" + indexString + "_";
1641
1642 struct DataType
1643 {
1644 string name;
1645 string type;
1646 string convert;
1647 string type2D; // Matrix when using floats. 2D array otherwise.
1648 BufferSp inputs;
1649 BufferSp outputs;
1650 };
1651
1652 const DataType dataTypes[] =
1653 {
1654 { "float", "f", "OpFConvert %f32 %data", "matrix", BufferSp(new Float16Buffer(inputDataFloat)), BufferSp(new Float32Buffer(vector<float>(1, outputDataFloat[indicesIdx]))) },
1655 { "int", "i", "OpSConvert %i32 %data", "scalarArray2D", BufferSp(new Int16Buffer(inputDataInt)), BufferSp(new Int32Buffer(vector<deInt32>(1, outputDataSInt[indicesIdx]))) },
1656 { "uint", "u", "OpUConvert %u32 %data", "scalarArray2D", BufferSp(new Int16Buffer(inputDataInt)), BufferSp(new Int32Buffer(vector<deInt32>(1, outputDataUInt[indicesIdx]))) }
1657 };
1658
1659 for (deUint32 dataTypeIdx = 0; dataTypeIdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeIdx)
1660 {
1661 const string testName = testNameBase + dataTypes[dataTypeIdx].name;
1662 map<string, string> specs;
1663 ComputeShaderSpec spec;
1664
1665 specs["capability"] = CAPABILITIES[capIdx].cap;
1666 specs["storage"] = CAPABILITIES[capIdx].decor;
1667 specs["s0"] = de::toString(indices[indicesIdx].x());
1668 specs["s1"] = de::toString(indices[indicesIdx].y());
1669 specs["s2"] = de::toString(indices[indicesIdx].z());
1670 specs["s3"] = de::toString(indices[indicesIdx].w());
1671 specs["type"] = dataTypes[dataTypeIdx].type;
1672 specs["convert"] = dataTypes[dataTypeIdx].convert;
1673 specs["type2D"] = dataTypes[dataTypeIdx].type2D;
1674
1675 if (indices[indicesIdx].y() == 1)
1676 specs["accessChain"] = "OpAccessChain %_ptr_Uniform_16bit_data %dataInput %int_0 %s0 %s1 %s2 %s3";
1677 else
1678 specs["accessChain"] = "OpAccessChain %_ptr_Uniform_16bit_data %dataInput %int_0 %s0 %s1 %s2";
1679
1680 if (dataTypeIdx == 0)
1681 {
1682 spec.verifyIO = check32BitFloats;
1683 specs["decoration"] = "OpMemberDecorate %S 1 ColMajor\nOpMemberDecorate %S 1 MatrixStride 48\n";
1684 }
1685
1686 spec.assembly = shaderTemplate.specialize(specs);
1687 spec.numWorkGroups = IVec3(1, 1, 1);
1688 spec.extensions.push_back ("VK_KHR_16bit_storage");
1689 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
1690 spec.inputs.push_back(Resource(dataTypes[dataTypeIdx].inputs, CAPABILITIES[capIdx].dtype));
1691 spec.outputs.push_back(Resource(dataTypes[dataTypeIdx].outputs));
1692
1693 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1694 }
1695 }
1696 }
1697
addCompute16bitStoragePushConstant16To32Group(tcu::TestCaseGroup * group)1698 void addCompute16bitStoragePushConstant16To32Group (tcu::TestCaseGroup* group)
1699 {
1700 tcu::TestContext& testCtx = group->getTestContext();
1701 de::Random rnd (deStringHash(group->getName()));
1702 const int numElements = 64;
1703
1704 const StringTemplate shaderTemplate (
1705 "OpCapability Shader\n"
1706 "OpCapability StoragePushConstant16\n"
1707 "OpExtension \"SPV_KHR_16bit_storage\"\n"
1708 "OpMemoryModel Logical GLSL450\n"
1709 "OpEntryPoint GLCompute %main \"main\" %id\n"
1710 "OpExecutionMode %main LocalSize 1 1 1\n"
1711 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1712
1713 "${stride}"
1714
1715 "OpDecorate %PC16 Block\n"
1716 "OpMemberDecorate %PC16 0 Offset 0\n"
1717 "OpMemberDecorate %SSBO32 0 Offset 0\n"
1718 "OpDecorate %SSBO32 BufferBlock\n"
1719 "OpDecorate %ssbo32 DescriptorSet 0\n"
1720 "OpDecorate %ssbo32 Binding 0\n"
1721
1722 "${matrix_decor:opt}\n"
1723
1724 "%void = OpTypeVoid\n"
1725 "%voidf = OpTypeFunction %void\n"
1726 "%u32 = OpTypeInt 32 0\n"
1727 "%i32 = OpTypeInt 32 1\n"
1728 "%f32 = OpTypeFloat 32\n"
1729 "%v3u32 = OpTypeVector %u32 3\n"
1730 "%uvec3ptr = OpTypePointer Input %v3u32\n"
1731 "%i32ptr = OpTypePointer Uniform %i32\n"
1732 "%f32ptr = OpTypePointer Uniform %f32\n"
1733
1734 "%zero = OpConstant %i32 0\n"
1735 "%c_i32_1 = OpConstant %i32 1\n"
1736 "%c_i32_8 = OpConstant %i32 8\n"
1737 "%c_i32_16 = OpConstant %i32 16\n"
1738 "%c_i32_32 = OpConstant %i32 32\n"
1739 "%c_i32_64 = OpConstant %i32 64\n"
1740 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
1741
1742 "%i32arr = OpTypeArray %i32 %c_i32_64\n"
1743 "%f32arr = OpTypeArray %f32 %c_i32_64\n"
1744
1745 "${types}\n"
1746 "${matrix_types:opt}\n"
1747
1748 "%PC16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
1749 "%pp_PC16 = OpTypePointer PushConstant %PC16\n"
1750 "%pc16 = OpVariable %pp_PC16 PushConstant\n"
1751 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
1752 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
1753 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n"
1754
1755 "%id = OpVariable %uvec3ptr Input\n"
1756
1757 "%main = OpFunction %void None %voidf\n"
1758 "%label = OpLabel\n"
1759 "%idval = OpLoad %v3u32 %id\n"
1760 "%x = OpCompositeExtract %u32 %idval 0\n"
1761 "%inloc = OpAccessChain %${base16}ptr %pc16 %zero %${arrayindex} ${index0:opt}\n"
1762 "%val16 = OpLoad %${base16} %inloc\n"
1763 "%val32 = ${convert} %${base32} %val16\n"
1764 "%outloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
1765 " OpStore %outloc %val32\n"
1766 "${matrix_store:opt}\n"
1767 " OpReturn\n"
1768 " OpFunctionEnd\n");
1769
1770 { // floats
1771 const char floatTypes[] =
1772 "%f16 = OpTypeFloat 16\n"
1773 "%f16ptr = OpTypePointer PushConstant %f16\n"
1774 "%f16arr = OpTypeArray %f16 %c_i32_64\n"
1775 "%v4f16 = OpTypeVector %f16 4\n"
1776 "%v4f32 = OpTypeVector %f32 4\n"
1777 "%v4f16ptr = OpTypePointer PushConstant %v4f16\n"
1778 "%v4f32ptr = OpTypePointer Uniform %v4f32\n"
1779 "%v4f16arr = OpTypeArray %v4f16 %c_i32_16\n"
1780 "%v4f32arr = OpTypeArray %v4f32 %c_i32_16\n";
1781
1782 struct CompositeType
1783 {
1784 const char* name;
1785 const char* base32;
1786 const char* base16;
1787 const char* stride;
1788 bool useConstantIndex;
1789 unsigned constantIndex;
1790 unsigned count;
1791 };
1792
1793 const CompositeType cTypes[] =
1794 {
1795 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", false, 0, numElements},
1796 {"scalar_const_idx_5", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", true, 5, numElements},
1797 {"scalar_const_idx_8", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", true, 8, numElements},
1798 {"vector", "v4f32", "v4f16", "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n", false, 0, numElements / 4},
1799 {"matrix", "v4f32", "v4f16", "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n", false, 0, numElements / 8},
1800 };
1801
1802 vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
1803 vector<float> float32Data;
1804
1805 float32Data.reserve(numElements);
1806 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1807 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
1808
1809 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
1810 {
1811 ComputeShaderSpec spec;
1812 map<string, string> specs;
1813 string testName = string(cTypes[tyIdx].name) + "_float";
1814
1815 vector<float> float32DataConstIdx;
1816 if (cTypes[tyIdx].useConstantIndex)
1817 {
1818 const deUint32 numFloats = numElements / cTypes[tyIdx].count;
1819 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1820 float32DataConstIdx.push_back(float32Data[cTypes[tyIdx].constantIndex * numFloats + numIdx % numFloats]);
1821 }
1822
1823 specs["stride"] = cTypes[tyIdx].stride;
1824 specs["base32"] = cTypes[tyIdx].base32;
1825 specs["base16"] = cTypes[tyIdx].base16;
1826 specs["types"] = floatTypes;
1827 specs["convert"] = "OpFConvert";
1828 specs["constarrayidx"] = de::toString(cTypes[tyIdx].constantIndex);
1829 if (cTypes[tyIdx].useConstantIndex)
1830 specs["arrayindex"] = "c_i32_ci";
1831 else
1832 specs["arrayindex"] = "x";
1833
1834 if (strcmp(cTypes[tyIdx].name, "matrix") == 0)
1835 {
1836 specs["index0"] = "%zero";
1837 specs["matrix_prefix"] = "m2";
1838 specs["matrix_types"] =
1839 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
1840 "%m2v4f32 = OpTypeMatrix %v4f32 2\n"
1841 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_8\n"
1842 "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_8\n";
1843 specs["matrix_decor"] =
1844 "OpMemberDecorate %SSBO32 0 ColMajor\n"
1845 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
1846 "OpMemberDecorate %PC16 0 ColMajor\n"
1847 "OpMemberDecorate %PC16 0 MatrixStride 8\n";
1848 specs["matrix_store"] =
1849 "%inloc_1 = OpAccessChain %v4f16ptr %pc16 %zero %x %c_i32_1\n"
1850 "%val16_1 = OpLoad %v4f16 %inloc_1\n"
1851 "%val32_1 = OpFConvert %v4f32 %val16_1\n"
1852 "%outloc_1 = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n"
1853 " OpStore %outloc_1 %val32_1\n";
1854 }
1855
1856 spec.assembly = shaderTemplate.specialize(specs);
1857 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
1858 spec.verifyIO = check32BitFloats;
1859 spec.pushConstants = BufferSp(new Float16Buffer(float16Data));
1860
1861 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(cTypes[tyIdx].useConstantIndex ? float32DataConstIdx : float32Data))));
1862 spec.extensions.push_back("VK_KHR_16bit_storage");
1863 spec.requestedVulkanFeatures.ext16BitStorage.storagePushConstant16 = true;
1864
1865 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
1866 }
1867 }
1868 {// integers
1869 const char sintTypes[] =
1870 "%i16 = OpTypeInt 16 1\n"
1871 "%i16ptr = OpTypePointer PushConstant %i16\n"
1872 "%i16arr = OpTypeArray %i16 %c_i32_64\n"
1873 "%v2i16 = OpTypeVector %i16 2\n"
1874 "%v2i32 = OpTypeVector %i32 2\n"
1875 "%v2i16ptr = OpTypePointer PushConstant %v2i16\n"
1876 "%v2i32ptr = OpTypePointer Uniform %v2i32\n"
1877 "%v2i16arr = OpTypeArray %v2i16 %c_i32_32\n"
1878 "%v2i32arr = OpTypeArray %v2i32 %c_i32_32\n";
1879
1880 const char uintTypes[] =
1881 "%u16 = OpTypeInt 16 0\n"
1882 "%u16ptr = OpTypePointer PushConstant %u16\n"
1883 "%u32ptr = OpTypePointer Uniform %u32\n"
1884 "%u16arr = OpTypeArray %u16 %c_i32_64\n"
1885 "%u32arr = OpTypeArray %u32 %c_i32_64\n"
1886 "%v2u16 = OpTypeVector %u16 2\n"
1887 "%v2u32 = OpTypeVector %u32 2\n"
1888 "%v2u16ptr = OpTypePointer PushConstant %v2u16\n"
1889 "%v2u32ptr = OpTypePointer Uniform %v2u32\n"
1890 "%v2u16arr = OpTypeArray %v2u16 %c_i32_32\n"
1891 "%v2u32arr = OpTypeArray %v2u32 %c_i32_32\n";
1892
1893 struct CompositeType
1894 {
1895 const char* name;
1896 bool isSigned;
1897 const char* types;
1898 const char* base32;
1899 const char* base16;
1900 const char* opcode;
1901 const char* stride;
1902 bool useConstantIndex;
1903 unsigned constantIndex;
1904 unsigned count;
1905 };
1906
1907 const CompositeType cTypes[] =
1908 {
1909 {"scalar_sint", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", false, 0, numElements},
1910 {"scalar_sint_const_idx_5", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", true, 5, numElements},
1911 {"scalar_sint_const_idx_8", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", true, 8, numElements},
1912 {"scalar_uint", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", false, 0, numElements},
1913 {"scalar_uint_const_idx_5", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", true, 5, numElements},
1914 {"scalar_uint_const_idx_8", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", true, 8, numElements},
1915 {"vector_sint", true, sintTypes, "v2i32", "v2i16", "OpSConvert", "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n", false, 0, numElements / 2},
1916 {"vector_uint", false, uintTypes, "v2u32", "v2u16", "OpUConvert", "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n", false, 0, numElements / 2},
1917 };
1918
1919 vector<deInt16> inputs = getInt16s(rnd, numElements);
1920 vector<deInt32> sOutputs;
1921 vector<deInt32> uOutputs;
1922 const deUint16 signBitMask = 0x8000;
1923 const deUint32 signExtendMask = 0xffff0000;
1924
1925 sOutputs.reserve(inputs.size());
1926 uOutputs.reserve(inputs.size());
1927
1928 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
1929 {
1930 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
1931 if (inputs[numNdx] & signBitMask)
1932 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
1933 else
1934 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
1935 }
1936
1937 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
1938 {
1939 ComputeShaderSpec spec;
1940 map<string, string> specs;
1941 const char* testName = cTypes[tyIdx].name;
1942 vector<deInt32> intDataConstIdx;
1943
1944 if (cTypes[tyIdx].useConstantIndex)
1945 {
1946 const deUint32 numInts = numElements / cTypes[tyIdx].count;
1947
1948 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
1949 {
1950 const deInt32 idx = cTypes[tyIdx].constantIndex * numInts + numIdx % numInts;
1951
1952 if (cTypes[tyIdx].isSigned)
1953 intDataConstIdx.push_back(sOutputs[idx]);
1954 else
1955 intDataConstIdx.push_back(uOutputs[idx]);
1956 }
1957 }
1958
1959 specs["stride"] = cTypes[tyIdx].stride;
1960 specs["base32"] = cTypes[tyIdx].base32;
1961 specs["base16"] = cTypes[tyIdx].base16;
1962 specs["types"] = cTypes[tyIdx].types;
1963 specs["convert"] = cTypes[tyIdx].opcode;
1964 specs["constarrayidx"] = de::toString(cTypes[tyIdx].constantIndex);
1965 if (cTypes[tyIdx].useConstantIndex)
1966 specs["arrayindex"] = "c_i32_ci";
1967 else
1968 specs["arrayindex"] = "x";
1969
1970 spec.assembly = shaderTemplate.specialize(specs);
1971 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
1972 spec.pushConstants = BufferSp(new Int16Buffer(inputs));
1973
1974 if (cTypes[tyIdx].useConstantIndex)
1975 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(intDataConstIdx))));
1976 else if (cTypes[tyIdx].isSigned)
1977 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs))));
1978 else
1979 spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs))));
1980 spec.extensions.push_back("VK_KHR_16bit_storage");
1981 spec.requestedVulkanFeatures.ext16BitStorage.storagePushConstant16 = true;
1982
1983 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName, testName, spec));
1984 }
1985 }
1986 }
1987
addGraphics16BitStorageUniformInt32To16Group(tcu::TestCaseGroup * testGroup)1988 void addGraphics16BitStorageUniformInt32To16Group (tcu::TestCaseGroup* testGroup)
1989 {
1990 de::Random rnd (deStringHash(testGroup->getName()));
1991 map<string, string> fragments;
1992 const deUint32 numDataPoints = 256;
1993 RGBA defaultColors[4];
1994 vector<string> extensions;
1995 const StringTemplate capabilities ("OpCapability ${cap}\n");
1996 // inputs and outputs are declared to be vectors of signed integers.
1997 // However, depending on the test, they may be interpreted as unsiged
1998 // integers. That won't be a problem as long as we passed the bits
1999 // in faithfully to the pipeline.
2000 vector<deInt32> inputs = getInt32s(rnd, numDataPoints);
2001 vector<deInt16> outputs;
2002
2003 outputs.reserve(inputs.size());
2004 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
2005 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx]));
2006
2007 extensions.push_back("VK_KHR_16bit_storage");
2008 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
2009
2010 getDefaultColors(defaultColors);
2011
2012 struct IntegerFacts
2013 {
2014 const char* name;
2015 const char* type32;
2016 const char* type16;
2017 const char* opcode;
2018 const char* isSigned;
2019 };
2020
2021 const IntegerFacts intFacts[] =
2022 {
2023 {"sint", "%i32", "%i16", "OpSConvert", "1"},
2024 {"uint", "%u32", "%u16", "OpUConvert", "0"},
2025 };
2026
2027 const StringTemplate scalarPreMain(
2028 "${itype16} = OpTypeInt 16 ${signed}\n"
2029 "%c_i32_256 = OpConstant %i32 256\n"
2030 " %up_i32 = OpTypePointer Uniform ${itype32}\n"
2031 " %up_i16 = OpTypePointer Uniform ${itype16}\n"
2032 " %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n"
2033 " %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n"
2034 " %SSBO32 = OpTypeStruct %ra_i32\n"
2035 " %SSBO16 = OpTypeStruct %ra_i16\n"
2036 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2037 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2038 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
2039 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
2040
2041 const StringTemplate scalarDecoration(
2042 "OpDecorate %ra_i32 ArrayStride ${arraystride}\n"
2043 "OpDecorate %ra_i16 ArrayStride 2\n"
2044 "OpMemberDecorate %SSBO32 0 Offset 0\n"
2045 "OpMemberDecorate %SSBO16 0 Offset 0\n"
2046 "OpDecorate %SSBO32 ${indecor}\n"
2047 "OpDecorate %SSBO16 BufferBlock\n"
2048 "OpDecorate %ssbo32 DescriptorSet 0\n"
2049 "OpDecorate %ssbo16 DescriptorSet 0\n"
2050 "OpDecorate %ssbo32 Binding 0\n"
2051 "OpDecorate %ssbo16 Binding 1\n");
2052
2053 const StringTemplate scalarTestFunc(
2054 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
2055 " %param = OpFunctionParameter %v4f32\n"
2056
2057 "%entry = OpLabel\n"
2058 " %i = OpVariable %fp_i32 Function\n"
2059 " OpStore %i %c_i32_0\n"
2060 " OpBranch %loop\n"
2061
2062 " %loop = OpLabel\n"
2063 " %15 = OpLoad %i32 %i\n"
2064 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
2065 " OpLoopMerge %merge %inc None\n"
2066 " OpBranchConditional %lt %write %merge\n"
2067
2068 "%write = OpLabel\n"
2069 " %30 = OpLoad %i32 %i\n"
2070 " %src = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n"
2071 "%val32 = OpLoad ${itype32} %src\n"
2072 "%val16 = ${convert} ${itype16} %val32\n"
2073 " %dst = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %30\n"
2074 " OpStore %dst %val16\n"
2075 " OpBranch %inc\n"
2076
2077 " %inc = OpLabel\n"
2078 " %37 = OpLoad %i32 %i\n"
2079 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
2080 " OpStore %i %39\n"
2081 " OpBranch %loop\n"
2082
2083 "%merge = OpLabel\n"
2084 " OpReturnValue %param\n"
2085
2086 "OpFunctionEnd\n");
2087
2088 const StringTemplate vecPreMain(
2089 "${itype16} = OpTypeInt 16 ${signed}\n"
2090 " %c_i32_64 = OpConstant %i32 64\n"
2091 "%v4itype16 = OpTypeVector ${itype16} 4\n"
2092 " %up_v4i32 = OpTypePointer Uniform ${v4itype32}\n"
2093 " %up_v4i16 = OpTypePointer Uniform %v4itype16\n"
2094 " %ra_v4i32 = OpTypeArray ${v4itype32} %c_i32_64\n"
2095 " %ra_v4i16 = OpTypeArray %v4itype16 %c_i32_64\n"
2096 " %SSBO32 = OpTypeStruct %ra_v4i32\n"
2097 " %SSBO16 = OpTypeStruct %ra_v4i16\n"
2098 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2099 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2100 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
2101 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
2102
2103 const StringTemplate vecDecoration(
2104 "OpDecorate %ra_v4i32 ArrayStride 16\n"
2105 "OpDecorate %ra_v4i16 ArrayStride 8\n"
2106 "OpMemberDecorate %SSBO32 0 Offset 0\n"
2107 "OpMemberDecorate %SSBO16 0 Offset 0\n"
2108 "OpDecorate %SSBO32 ${indecor}\n"
2109 "OpDecorate %SSBO16 BufferBlock\n"
2110 "OpDecorate %ssbo32 DescriptorSet 0\n"
2111 "OpDecorate %ssbo16 DescriptorSet 0\n"
2112 "OpDecorate %ssbo32 Binding 0\n"
2113 "OpDecorate %ssbo16 Binding 1\n");
2114
2115 const StringTemplate vecTestFunc(
2116 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
2117 " %param = OpFunctionParameter %v4f32\n"
2118
2119 "%entry = OpLabel\n"
2120 " %i = OpVariable %fp_i32 Function\n"
2121 " OpStore %i %c_i32_0\n"
2122 " OpBranch %loop\n"
2123
2124 " %loop = OpLabel\n"
2125 " %15 = OpLoad %i32 %i\n"
2126 " %lt = OpSLessThan %bool %15 %c_i32_64\n"
2127 " OpLoopMerge %merge %inc None\n"
2128 " OpBranchConditional %lt %write %merge\n"
2129
2130 "%write = OpLabel\n"
2131 " %30 = OpLoad %i32 %i\n"
2132 " %src = OpAccessChain %up_v4i32 %ssbo32 %c_i32_0 %30\n"
2133 "%val32 = OpLoad ${v4itype32} %src\n"
2134 "%val16 = ${convert} %v4itype16 %val32\n"
2135 " %dst = OpAccessChain %up_v4i16 %ssbo16 %c_i32_0 %30\n"
2136 " OpStore %dst %val16\n"
2137 " OpBranch %inc\n"
2138
2139 " %inc = OpLabel\n"
2140 " %37 = OpLoad %i32 %i\n"
2141 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
2142 " OpStore %i %39\n"
2143 " OpBranch %loop\n"
2144
2145 "%merge = OpLabel\n"
2146 " OpReturnValue %param\n"
2147
2148 "OpFunctionEnd\n");
2149
2150 // Scalar
2151 {
2152 const deUint32 arrayStrides[] = {4, 16};
2153
2154 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2155 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
2156 {
2157 map<string, string> specs;
2158 string name = string(CAPABILITIES[capIdx].name) + "_scalar_" + intFacts[factIdx].name;
2159
2160 specs["cap"] = CAPABILITIES[capIdx].cap;
2161 specs["indecor"] = CAPABILITIES[capIdx].decor;
2162 specs["itype32"] = intFacts[factIdx].type32;
2163 specs["v4itype32"] = "%v4" + string(intFacts[factIdx].type32).substr(1);
2164 specs["itype16"] = intFacts[factIdx].type16;
2165 specs["signed"] = intFacts[factIdx].isSigned;
2166 specs["convert"] = intFacts[factIdx].opcode;
2167 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
2168
2169 fragments["pre_main"] = scalarPreMain.specialize(specs);
2170 fragments["testfun"] = scalarTestFunc.specialize(specs);
2171 fragments["capability"] = capabilities.specialize(specs);
2172 fragments["decoration"] = scalarDecoration.specialize(specs);
2173
2174 vector<deInt32> inputsPadded;
2175 for (size_t dataIdx = 0; dataIdx < inputs.size(); ++dataIdx)
2176 {
2177 inputsPadded.push_back(inputs[dataIdx]);
2178 for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 4 - 1; ++padIdx)
2179 inputsPadded.push_back(0);
2180 }
2181
2182 GraphicsResources resources;
2183 VulkanFeatures features;
2184
2185 resources.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputsPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2186 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2187 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
2188
2189 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2190 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
2191 features.coreFeatures.fragmentStoresAndAtomics = true;
2192
2193 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
2194 }
2195 }
2196 // Vector
2197 {
2198 GraphicsResources resources;
2199 resources.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2200 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
2201
2202 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2203 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
2204 {
2205 map<string, string> specs;
2206 string name = string(CAPABILITIES[capIdx].name) + "_vector_" + intFacts[factIdx].name;
2207 VulkanFeatures features;
2208
2209 specs["cap"] = CAPABILITIES[capIdx].cap;
2210 specs["indecor"] = CAPABILITIES[capIdx].decor;
2211 specs["itype32"] = intFacts[factIdx].type32;
2212 specs["v4itype32"] = "%v4" + string(intFacts[factIdx].type32).substr(1);
2213 specs["itype16"] = intFacts[factIdx].type16;
2214 specs["signed"] = intFacts[factIdx].isSigned;
2215 specs["convert"] = intFacts[factIdx].opcode;
2216
2217 fragments["pre_main"] = vecPreMain.specialize(specs);
2218 fragments["testfun"] = vecTestFunc.specialize(specs);
2219 fragments["capability"] = capabilities.specialize(specs);
2220 fragments["decoration"] = vecDecoration.specialize(specs);
2221
2222 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
2223
2224 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2225 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
2226 features.coreFeatures.fragmentStoresAndAtomics = true;
2227
2228 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
2229 }
2230 }
2231 }
2232
addCompute16bitStorageUniform16To16Group(tcu::TestCaseGroup * group)2233 void addCompute16bitStorageUniform16To16Group (tcu::TestCaseGroup* group)
2234 {
2235 tcu::TestContext& testCtx = group->getTestContext();
2236 de::Random rnd (deStringHash(group->getName()));
2237 const int numElements = 128;
2238 const vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
2239 const vector<deFloat16> float16UnusedData (numElements, 0);
2240 ComputeShaderSpec spec;
2241
2242 std::ostringstream shaderTemplate;
2243 shaderTemplate<<"OpCapability Shader\n"
2244 << "OpCapability StorageUniformBufferBlock16\n"
2245 << "OpExtension \"SPV_KHR_16bit_storage\"\n"
2246 << "OpMemoryModel Logical GLSL450\n"
2247 << "OpEntryPoint GLCompute %main \"main\" %id\n"
2248 << "OpExecutionMode %main LocalSize 1 1 1\n"
2249 << "OpDecorate %id BuiltIn GlobalInvocationId\n"
2250 << "OpDecorate %f16arr ArrayStride 2\n"
2251 << "OpMemberDecorate %SSBO_IN 0 Coherent\n"
2252 << "OpMemberDecorate %SSBO_OUT 0 Coherent\n"
2253 << "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2254 << "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2255 << "OpDecorate %SSBO_IN BufferBlock\n"
2256 << "OpDecorate %SSBO_OUT BufferBlock\n"
2257 << "OpDecorate %ssboIN DescriptorSet 0\n"
2258 << "OpDecorate %ssboOUT DescriptorSet 0\n"
2259 << "OpDecorate %ssboIN Binding 0\n"
2260 << "OpDecorate %ssboOUT Binding 1\n"
2261 << "\n"
2262 << "%bool = OpTypeBool\n"
2263 << "%void = OpTypeVoid\n"
2264 << "%voidf = OpTypeFunction %void\n"
2265 << "%u32 = OpTypeInt 32 0\n"
2266 << "%i32 = OpTypeInt 32 1\n"
2267 << "%uvec3 = OpTypeVector %u32 3\n"
2268 << "%uvec3ptr = OpTypePointer Input %uvec3\n"
2269 << "%f16 = OpTypeFloat 16\n"
2270 << "%f16ptr = OpTypePointer Uniform %f16\n"
2271 << "\n"
2272 << "%zero = OpConstant %i32 0\n"
2273 << "%c_size = OpConstant %i32 " << numElements << "\n"
2274 << "\n"
2275 << "%f16arr = OpTypeArray %f16 %c_size\n"
2276 << "%SSBO_IN = OpTypeStruct %f16arr\n"
2277 << "%SSBO_OUT = OpTypeStruct %f16arr\n"
2278 << "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
2279 << "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
2280 << "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
2281 << "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
2282 << "\n"
2283 << "%id = OpVariable %uvec3ptr Input\n"
2284 << "%main = OpFunction %void None %voidf\n"
2285 << "%label = OpLabel\n"
2286 << "%idval = OpLoad %uvec3 %id\n"
2287 << "%x = OpCompositeExtract %u32 %idval 0\n"
2288 << "%y = OpCompositeExtract %u32 %idval 1\n"
2289 << "\n"
2290 << "%inlocx = OpAccessChain %f16ptr %ssboIN %zero %x \n"
2291 << "%valx = OpLoad %f16 %inlocx\n"
2292 << "%outlocx = OpAccessChain %f16ptr %ssboOUT %zero %x \n"
2293 << " OpStore %outlocx %valx\n"
2294
2295 << "%inlocy = OpAccessChain %f16ptr %ssboIN %zero %y \n"
2296 << "%valy = OpLoad %f16 %inlocy\n"
2297 << "%outlocy = OpAccessChain %f16ptr %ssboOUT %zero %y \n"
2298 << " OpStore %outlocy %valy\n"
2299 << "\n"
2300 << " OpReturn\n"
2301 << " OpFunctionEnd\n";
2302
2303 spec.assembly = shaderTemplate.str();
2304 spec.numWorkGroups = IVec3(numElements, numElements, 1);
2305 spec.verifyIO = computeCheckBuffersFloats;
2306 spec.coherentMemory = true;
2307 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data))));
2308 spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData))));
2309 spec.extensions.push_back("VK_KHR_16bit_storage");
2310 spec.requestedVulkanFeatures = get16BitStorageFeatures("uniform_buffer_block");
2311
2312 group->addChild(new SpvAsmComputeShaderCase(testCtx, "stress_test", "Granularity stress test", spec));
2313 }
2314
addCompute16bitStorageUniform32To16Group(tcu::TestCaseGroup * group)2315 void addCompute16bitStorageUniform32To16Group (tcu::TestCaseGroup* group)
2316 {
2317 tcu::TestContext& testCtx = group->getTestContext();
2318 de::Random rnd (deStringHash(group->getName()));
2319 const int numElements = 128;
2320
2321 const StringTemplate shaderTemplate (
2322 "OpCapability Shader\n"
2323 "OpCapability ${capability}\n"
2324 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2325 "OpMemoryModel Logical GLSL450\n"
2326 "OpEntryPoint GLCompute %main \"main\" %id\n"
2327 "OpExecutionMode %main LocalSize 1 1 1\n"
2328 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2329
2330 "${stride}"
2331
2332 "OpMemberDecorate %SSBO32 0 Offset 0\n"
2333 "OpMemberDecorate %SSBO16 0 Offset 0\n"
2334 "OpDecorate %SSBO32 ${storage}\n"
2335 "OpDecorate %SSBO16 BufferBlock\n"
2336 "OpDecorate %ssbo32 DescriptorSet 0\n"
2337 "OpDecorate %ssbo16 DescriptorSet 0\n"
2338 "OpDecorate %ssbo32 Binding 0\n"
2339 "OpDecorate %ssbo16 Binding 1\n"
2340
2341 "${matrix_decor:opt}\n"
2342
2343 "${rounding:opt}\n"
2344
2345 "%bool = OpTypeBool\n"
2346 "%void = OpTypeVoid\n"
2347 "%voidf = OpTypeFunction %void\n"
2348 "%u32 = OpTypeInt 32 0\n"
2349 "%i32 = OpTypeInt 32 1\n"
2350 "%f32 = OpTypeFloat 32\n"
2351 "%uvec3 = OpTypeVector %u32 3\n"
2352 "%uvec3ptr = OpTypePointer Input %uvec3\n"
2353 "%i32ptr = OpTypePointer Uniform %i32\n"
2354 "%f32ptr = OpTypePointer Uniform %f32\n"
2355
2356 "%zero = OpConstant %i32 0\n"
2357 "%c_i32_1 = OpConstant %i32 1\n"
2358 "%c_i32_16 = OpConstant %i32 16\n"
2359 "%c_i32_32 = OpConstant %i32 32\n"
2360 "%c_i32_64 = OpConstant %i32 64\n"
2361 "%c_i32_128 = OpConstant %i32 128\n"
2362
2363 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
2364 "%f32arr = OpTypeArray %f32 %c_i32_128\n"
2365
2366 "${types}\n"
2367 "${matrix_types:opt}\n"
2368
2369 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n"
2370 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
2371 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
2372 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
2373 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n"
2374 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
2375
2376 "%id = OpVariable %uvec3ptr Input\n"
2377
2378 "%main = OpFunction %void None %voidf\n"
2379 "%label = OpLabel\n"
2380 "%idval = OpLoad %uvec3 %id\n"
2381 "%x = OpCompositeExtract %u32 %idval 0\n"
2382 "%inloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n"
2383 "%val32 = OpLoad %${base32} %inloc\n"
2384 "%val16 = ${convert} %${base16} %val32\n"
2385 "%outloc = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n"
2386 " OpStore %outloc %val16\n"
2387 "${matrix_store:opt}\n"
2388 " OpReturn\n"
2389 " OpFunctionEnd\n");
2390
2391 { // Floats
2392 const char floatTypes[] =
2393 "%f16 = OpTypeFloat 16\n"
2394 "%f16ptr = OpTypePointer Uniform %f16\n"
2395 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
2396 "%v4f16 = OpTypeVector %f16 4\n"
2397 "%v4f32 = OpTypeVector %f32 4\n"
2398 "%v4f16ptr = OpTypePointer Uniform %v4f16\n"
2399 "%v4f32ptr = OpTypePointer Uniform %v4f32\n"
2400 "%v4f16arr = OpTypeArray %v4f16 %c_i32_32\n"
2401 "%v4f32arr = OpTypeArray %v4f32 %c_i32_32\n";
2402
2403 struct RndMode
2404 {
2405 const char* name;
2406 const char* decor;
2407 VerifyIOFunc func;
2408 };
2409
2410 const RndMode rndModes[] =
2411 {
2412 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", computeCheck16BitFloats<ROUNDINGMODE_RTZ>},
2413 {"rte", "OpDecorate %val16 FPRoundingMode RTE", computeCheck16BitFloats<ROUNDINGMODE_RTE>},
2414 {"unspecified_rnd_mode", "", computeCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
2415 };
2416
2417 struct CompositeType
2418 {
2419 const char* name;
2420 const char* base32;
2421 const char* base16;
2422 const char* stride;
2423 unsigned count;
2424 unsigned inputStride;
2425 };
2426
2427 const CompositeType cTypes[2][3] =
2428 {
2429 { // BufferBlock
2430 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", numElements, 1},
2431 {"vector", "v4f32", "v4f16", "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4, 1},
2432 {"matrix", "v4f32", "v4f16", "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8, 1}
2433 },
2434 { // Block
2435 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 16\nOpDecorate %f16arr ArrayStride 2\n", numElements, 4},
2436 {"vector", "v4f32", "v4f16", "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4, 1},
2437 {"matrix", "v4f32", "v4f16", "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8, 1}
2438 }
2439 };
2440
2441 vector<deFloat16> float16UnusedData (numElements, 0);
2442
2443 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2444 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
2445 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
2446 {
2447 ComputeShaderSpec spec;
2448 map<string, string> specs;
2449 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name + "_float_" + rndModes[rndModeIdx].name;
2450 vector<float> float32Data = getFloat32s(rnd, numElements * cTypes[capIdx][tyIdx].inputStride);
2451
2452 specs["capability"] = CAPABILITIES[capIdx].cap;
2453 specs["storage"] = CAPABILITIES[capIdx].decor;
2454 specs["stride"] = cTypes[capIdx][tyIdx].stride;
2455 specs["base32"] = cTypes[capIdx][tyIdx].base32;
2456 specs["base16"] = cTypes[capIdx][tyIdx].base16;
2457 specs["rounding"] = rndModes[rndModeIdx].decor;
2458 specs["types"] = floatTypes;
2459 specs["convert"] = "OpFConvert";
2460
2461 if (strcmp(cTypes[capIdx][tyIdx].name, "matrix") == 0)
2462 {
2463 if (strcmp(rndModes[rndModeIdx].name, "rtz") == 0)
2464 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTZ\n";
2465 else if (strcmp(rndModes[rndModeIdx].name, "rte") == 0)
2466 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTE\n";
2467
2468 specs["index0"] = "%zero";
2469 specs["matrix_prefix"] = "m2";
2470 specs["matrix_types"] =
2471 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
2472 "%m2v4f32 = OpTypeMatrix %v4f32 2\n"
2473 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_16\n"
2474 "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_16\n";
2475 specs["matrix_decor"] =
2476 "OpMemberDecorate %SSBO32 0 ColMajor\n"
2477 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
2478 "OpMemberDecorate %SSBO16 0 ColMajor\n"
2479 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n";
2480 specs["matrix_store"] =
2481 "%inloc_1 = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n"
2482 "%val32_1 = OpLoad %v4f32 %inloc_1\n"
2483 "%val16_1 = OpFConvert %v4f16 %val32_1\n"
2484 "%outloc_1 = OpAccessChain %v4f16ptr %ssbo16 %zero %x %c_i32_1\n"
2485 " OpStore %outloc_1 %val16_1\n";
2486 }
2487
2488 spec.assembly = shaderTemplate.specialize(specs);
2489 spec.numWorkGroups = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
2490 spec.verifyIO = rndModes[rndModeIdx].func;
2491
2492 spec.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), CAPABILITIES[capIdx].dtype));
2493 // We provided a custom verifyIO in the above in which inputs will be used for checking.
2494 // So put unused data in the expected values.
2495 spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData))));
2496 spec.extensions.push_back("VK_KHR_16bit_storage");
2497 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2498
2499 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2500 }
2501 }
2502
2503 { // Integers
2504 const char sintTypes[] =
2505 "%i16 = OpTypeInt 16 1\n"
2506 "%i16ptr = OpTypePointer Uniform %i16\n"
2507 "%i16arr = OpTypeArray %i16 %c_i32_128\n"
2508 "%v2i16 = OpTypeVector %i16 2\n"
2509 "%v2i32 = OpTypeVector %i32 2\n"
2510 "%v2i16ptr = OpTypePointer Uniform %v2i16\n"
2511 "%v2i32ptr = OpTypePointer Uniform %v2i32\n"
2512 "%v2i16arr = OpTypeArray %v2i16 %c_i32_64\n"
2513 "%v2i32arr = OpTypeArray %v2i32 %c_i32_64\n";
2514
2515 const char uintTypes[] =
2516 "%u16 = OpTypeInt 16 0\n"
2517 "%u16ptr = OpTypePointer Uniform %u16\n"
2518 "%u32ptr = OpTypePointer Uniform %u32\n"
2519 "%u16arr = OpTypeArray %u16 %c_i32_128\n"
2520 "%u32arr = OpTypeArray %u32 %c_i32_128\n"
2521 "%v2u16 = OpTypeVector %u16 2\n"
2522 "%v2u32 = OpTypeVector %u32 2\n"
2523 "%v2u16ptr = OpTypePointer Uniform %v2u16\n"
2524 "%v2u32ptr = OpTypePointer Uniform %v2u32\n"
2525 "%v2u16arr = OpTypeArray %v2u16 %c_i32_64\n"
2526 "%v2u32arr = OpTypeArray %v2u32 %c_i32_64\n";
2527
2528 struct CompositeType
2529 {
2530 const char* name;
2531 const char* types;
2532 const char* base32;
2533 const char* base16;
2534 const char* opcode;
2535 const char* stride;
2536 unsigned count;
2537 unsigned inputStride;
2538 };
2539
2540 const CompositeType cTypes[2][4] =
2541 {
2542 {
2543 {"scalar_sint", sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", numElements, 1},
2544 {"scalar_uint", uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", numElements, 1},
2545 {"vector_sint", sintTypes, "v2i32", "v2i16", "OpSConvert", "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n", numElements / 2, 2},
2546 {"vector_uint", uintTypes, "v2u32", "v2u16", "OpUConvert", "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n", numElements / 2, 2}
2547 },
2548 {
2549 {"scalar_sint", sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 16\nOpDecorate %i16arr ArrayStride 2\n", numElements, 4},
2550 {"scalar_uint", uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 16\nOpDecorate %u16arr ArrayStride 2\n", numElements, 4},
2551 {"vector_sint", sintTypes, "v2i32", "v2i16", "OpSConvert", "OpDecorate %v2i32arr ArrayStride 16\nOpDecorate %v2i16arr ArrayStride 4\n", numElements / 2, 4},
2552 {"vector_uint", uintTypes, "v2u32", "v2u16", "OpUConvert", "OpDecorate %v2u32arr ArrayStride 16\nOpDecorate %v2u16arr ArrayStride 4\n", numElements / 2, 4}
2553 }
2554 };
2555
2556 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2557 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes[capIdx]); ++tyIdx)
2558 {
2559 ComputeShaderSpec spec;
2560 map<string, string> specs;
2561 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[capIdx][tyIdx].name;
2562 const deUint32 inputStride = cTypes[capIdx][tyIdx].inputStride;
2563 const deUint32 count = cTypes[capIdx][tyIdx].count;
2564 const deUint32 scalarsPerItem = numElements / count;
2565
2566 vector<deInt32> inputs = getInt32s(rnd, numElements * inputStride);
2567 vector<deInt16> outputs;
2568
2569 outputs.reserve(numElements);
2570 for (deUint32 numNdx = 0; numNdx < count; ++numNdx)
2571 for (deUint32 scalarIdx = 0; scalarIdx < scalarsPerItem; scalarIdx++)
2572 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx * inputStride + scalarIdx]));
2573
2574 specs["capability"] = CAPABILITIES[capIdx].cap;
2575 specs["storage"] = CAPABILITIES[capIdx].decor;
2576 specs["stride"] = cTypes[capIdx][tyIdx].stride;
2577 specs["base32"] = cTypes[capIdx][tyIdx].base32;
2578 specs["base16"] = cTypes[capIdx][tyIdx].base16;
2579 specs["types"] = cTypes[capIdx][tyIdx].types;
2580 specs["convert"] = cTypes[capIdx][tyIdx].opcode;
2581
2582 spec.assembly = shaderTemplate.specialize(specs);
2583 spec.numWorkGroups = IVec3(cTypes[capIdx][tyIdx].count, 1, 1);
2584
2585 spec.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputs)), CAPABILITIES[capIdx].dtype));
2586 spec.outputs.push_back(Resource(BufferSp(new Int16Buffer(outputs))));
2587 spec.extensions.push_back("VK_KHR_16bit_storage");
2588 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2589
2590 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2591 }
2592 }
2593 }
2594
addCompute16bitStorageUniform16StructTo32StructGroup(tcu::TestCaseGroup * group)2595 void addCompute16bitStorageUniform16StructTo32StructGroup (tcu::TestCaseGroup* group)
2596 {
2597 tcu::TestContext& testCtx = group->getTestContext();
2598 de::Random rnd (deStringHash(group->getName()));
2599 const StringTemplate shaderTemplate (
2600 "OpCapability Shader\n"
2601 "OpCapability ${capability}\n"
2602 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2603 "OpMemoryModel Logical GLSL450\n"
2604 "OpEntryPoint GLCompute %main \"main\" %id\n"
2605 "OpExecutionMode %main LocalSize 1 1 1\n"
2606 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2607 "\n"
2608 "${strideF16}"
2609 "\n"
2610 "${strideF32}"
2611 "\n"
2612 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2613 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2614 "OpDecorate %SSBO_IN ${storage}\n"
2615 "OpDecorate %SSBO_OUT BufferBlock\n"
2616 "OpDecorate %ssboIN DescriptorSet 0\n"
2617 "OpDecorate %ssboOUT DescriptorSet 0\n"
2618 "OpDecorate %ssboIN Binding 0\n"
2619 "OpDecorate %ssboOUT Binding 1\n"
2620 "\n"
2621 "%bool = OpTypeBool\n"
2622 "%void = OpTypeVoid\n"
2623 "%voidf = OpTypeFunction %void\n"
2624 "%u32 = OpTypeInt 32 0\n"
2625 "%uvec3 = OpTypeVector %u32 3\n"
2626 "%uvec3ptr = OpTypePointer Input %uvec3\n"
2627 "\n"
2628 "%i32 = OpTypeInt 32 1\n"
2629 "%v2i32 = OpTypeVector %i32 2\n"
2630 "%v4i32 = OpTypeVector %i32 4\n"
2631 "\n"
2632 "%f32 = OpTypeFloat 32\n"
2633 "%v2f32 = OpTypeVector %f32 2\n"
2634 "%v3f32 = OpTypeVector %f32 3\n"
2635 "%v4f32 = OpTypeVector %f32 4\n"
2636 "${types}\n"
2637 "\n"
2638 "%zero = OpConstant %i32 0\n"
2639 "%c_i32_1 = OpConstant %i32 1\n"
2640 "%c_i32_2 = OpConstant %i32 2\n"
2641 "%c_i32_3 = OpConstant %i32 3\n"
2642 "%c_i32_4 = OpConstant %i32 4\n"
2643 "%c_i32_5 = OpConstant %i32 5\n"
2644 "%c_i32_6 = OpConstant %i32 6\n"
2645 "%c_i32_7 = OpConstant %i32 7\n"
2646 "%c_i32_8 = OpConstant %i32 8\n"
2647 "%c_i32_9 = OpConstant %i32 9\n"
2648 "\n"
2649 "%c_u32_1 = OpConstant %u32 1\n"
2650 "%c_u32_3 = OpConstant %u32 3\n"
2651 "%c_u32_7 = OpConstant %u32 7\n"
2652 "%c_u32_11 = OpConstant %u32 11\n"
2653 "\n"
2654 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
2655 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
2656 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
2657 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
2658 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
2659 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
2660 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
2661 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
2662 "\n"
2663 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
2664 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
2665 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
2666 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
2667 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
2668 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
2669 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
2670 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
2671 "\n"
2672 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
2673 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
2674 "%SSBO_IN = OpTypeStruct %f16StructArr7\n"
2675 "%SSBO_OUT = OpTypeStruct %f32StructArr7\n"
2676 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
2677 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
2678 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
2679 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
2680 "\n"
2681 "%id = OpVariable %uvec3ptr Input\n"
2682 "%main = OpFunction %void None %voidf\n"
2683 "%label = OpLabel\n"
2684 "\n"
2685 "%idval = OpLoad %uvec3 %id\n"
2686 "%x = OpCompositeExtract %u32 %idval 0\n"
2687 "%y = OpCompositeExtract %u32 %idval 1\n"
2688 "\n"
2689 "%f16src = OpAccessChain %f16ptr %ssboIN %zero %x %zero\n"
2690 "%val_f16 = OpLoad %f16 %f16src\n"
2691 "%val_f32 = OpFConvert %f32 %val_f16\n"
2692 "%f32dst = OpAccessChain %f32ptr %ssboOUT %zero %x %zero\n"
2693 "OpStore %f32dst %val_f32\n"
2694 "\n"
2695 "%v2f16src = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_1\n"
2696 "%val_v2f16 = OpLoad %v2f16 %v2f16src\n"
2697 "%val_v2f32 = OpFConvert %v2f32 %val_v2f16\n"
2698 "%v2f32dst = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_1\n"
2699 "OpStore %v2f32dst %val_v2f32\n"
2700 "\n"
2701 "%v3f16src = OpAccessChain %v3f16ptr %ssboIN %zero %x %c_i32_2\n"
2702 "%val_v3f16 = OpLoad %v3f16 %v3f16src\n"
2703 "%val_v3f32 = OpFConvert %v3f32 %val_v3f16\n"
2704 "%v3f32dst = OpAccessChain %v3f32ptr %ssboOUT %zero %x %c_i32_2\n"
2705 "OpStore %v3f32dst %val_v3f32\n"
2706 "\n"
2707 "%v4f16src = OpAccessChain %v4f16ptr %ssboIN %zero %x %c_i32_3\n"
2708 "%val_v4f16 = OpLoad %v4f16 %v4f16src\n"
2709 "%val_v4f32 = OpFConvert %v4f32 %val_v4f16\n"
2710 "%v4f32dst = OpAccessChain %v4f32ptr %ssboOUT %zero %x %c_i32_3\n"
2711 "OpStore %v4f32dst %val_v4f32\n"
2712 "\n"
2713 //struct {f16, v2f16[3]}
2714 "%Sf16src = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_5 %y %zero\n"
2715 "%Sval_f16 = OpLoad %f16 %Sf16src\n"
2716 "%Sval_f32 = OpFConvert %f32 %Sval_f16\n"
2717 "%Sf32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_5 %y %zero\n"
2718 "OpStore %Sf32dst2 %Sval_f32\n"
2719 "\n"
2720 "%Sv2f16src0 = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2721 "%Sv2f16_0 = OpLoad %v2f16 %Sv2f16src0\n"
2722 "%Sv2f32_0 = OpFConvert %v2f32 %Sv2f16_0\n"
2723 "%Sv2f32dst_0 = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2724 "OpStore %Sv2f32dst_0 %Sv2f32_0\n"
2725 "\n"
2726 "%Sv2f16src1 = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2727 "%Sv2f16_1 = OpLoad %v2f16 %Sv2f16src1\n"
2728 "%Sv2f32_1 = OpFConvert %v2f32 %Sv2f16_1\n"
2729 "%Sv2f32dst_1 = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2730 "OpStore %Sv2f32dst_1 %Sv2f32_1\n"
2731 "\n"
2732 "%Sv2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2733 "%Sv2f16_2 = OpLoad %v2f16 %Sv2f16src2\n"
2734 "%Sv2f32_2 = OpFConvert %v2f32 %Sv2f16_2\n"
2735 "%Sv2f32dst_2 = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2736 "OpStore %Sv2f32dst_2 %Sv2f32_2\n"
2737 "\n"
2738
2739 "%v2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %x %c_i32_6 %y\n"
2740 "%val2_v2f16 = OpLoad %v2f16 %v2f16src2\n"
2741 "%val2_v2f32 = OpFConvert %v2f32 %val2_v2f16\n"
2742 "%v2f32dst2 = OpAccessChain %v2f32ptr %ssboOUT %zero %x %c_i32_6 %y\n"
2743 "OpStore %v2f32dst2 %val2_v2f32\n"
2744 "\n"
2745 "%f16src2 = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_7\n"
2746 "%val2_f16 = OpLoad %f16 %f16src2\n"
2747 "%val2_f32 = OpFConvert %f32 %val2_f16\n"
2748 "%f32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_7\n"
2749 "OpStore %f32dst2 %val2_f32\n"
2750 "\n"
2751 "%v3f16src2 = OpAccessChain %v3f16ptr %ssboIN %zero %x %c_i32_8 %y\n"
2752 "%val2_v3f16 = OpLoad %v3f16 %v3f16src2\n"
2753 "%val2_v3f32 = OpFConvert %v3f32 %val2_v3f16\n"
2754 "%v3f32dst2 = OpAccessChain %v3f32ptr %ssboOUT %zero %x %c_i32_8 %y\n"
2755 "OpStore %v3f32dst2 %val2_v3f32\n"
2756 "\n"
2757
2758 //Array with 3 elements
2759 "%LessThan3 = OpSLessThan %bool %y %c_i32_3\n"
2760 "OpSelectionMerge %BlockIf None\n"
2761 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
2762 "%LabelIf = OpLabel\n"
2763 " %f16src3 = OpAccessChain %f16ptr %ssboIN %zero %x %c_i32_4 %y\n"
2764 " %val3_f16 = OpLoad %f16 %f16src3\n"
2765 " %val3_f32 = OpFConvert %f32 %val3_f16\n"
2766 " %f32dst3 = OpAccessChain %f32ptr %ssboOUT %zero %x %c_i32_4 %y\n"
2767 " OpStore %f32dst3 %val3_f32\n"
2768 "\n"
2769 " %v4f16src2 = OpAccessChain %v4f16ptr %ssboIN %zero %x %c_i32_9 %y\n"
2770 " %val2_v4f16 = OpLoad %v4f16 %v4f16src2\n"
2771 " %val2_v4f32 = OpFConvert %v4f32 %val2_v4f16\n"
2772 " %v4f32dst2 = OpAccessChain %v4f32ptr %ssboOUT %zero %x %c_i32_9 %y\n"
2773 " OpStore %v4f32dst2 %val2_v4f32\n"
2774 "OpBranch %BlockIf\n"
2775 "%BlockIf = OpLabel\n"
2776
2777 " OpReturn\n"
2778 " OpFunctionEnd\n");
2779
2780 { // Floats
2781 vector<float> float32Data (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430), 0.0f);
2782
2783 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
2784 {
2785 vector<deFloat16> float16DData = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data16bitStd430(rnd) : data16bitStd140(rnd);
2786 ComputeShaderSpec spec;
2787 map<string, string> specs;
2788 string testName = string(CAPABILITIES[capIdx].name);
2789
2790 specs["capability"] = CAPABILITIES[capIdx].cap;
2791 specs["storage"] = CAPABILITIES[capIdx].decor;
2792 specs["strideF16"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE16BIT_STD430 : SHADERTEMPLATE_STRIDE16BIT_STD140);
2793 specs["strideF32"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE32BIT_STD430);
2794 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
2795
2796 spec.assembly = shaderTemplate.specialize(specs);
2797 spec.numWorkGroups = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
2798 spec.verifyIO = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? computeCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD430, SHADERTEMPLATE_STRIDE32BIT_STD430>
2799 : computeCheckStruct<deFloat16, float, SHADERTEMPLATE_STRIDE16BIT_STD140, SHADERTEMPLATE_STRIDE32BIT_STD430>;
2800 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16DData)), CAPABILITIES[capIdx].dtype));
2801 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data))));
2802 spec.extensions.push_back("VK_KHR_16bit_storage");
2803 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
2804
2805 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
2806 }
2807 }
2808 }
2809
addCompute16bitStorageUniform32StructTo16StructGroup(tcu::TestCaseGroup * group)2810 void addCompute16bitStorageUniform32StructTo16StructGroup (tcu::TestCaseGroup* group)
2811 {
2812 tcu::TestContext& testCtx = group->getTestContext();
2813 de::Random rnd (deStringHash(group->getName()));
2814
2815 const StringTemplate shaderTemplate (
2816 "OpCapability Shader\n"
2817 "OpCapability ${capability}\n"
2818 "OpExtension \"SPV_KHR_16bit_storage\"\n"
2819 "OpMemoryModel Logical GLSL450\n"
2820 "OpEntryPoint GLCompute %main \"main\" %id\n"
2821 "OpExecutionMode %main LocalSize 1 1 1\n"
2822 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2823 "\n"
2824 "${strideF16}"
2825 "\n"
2826 "${strideF32}"
2827 "\n"
2828 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
2829 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
2830 "OpDecorate %SSBO_IN ${storage}\n"
2831 "OpDecorate %SSBO_OUT BufferBlock\n"
2832 "OpDecorate %ssboIN DescriptorSet 0\n"
2833 "OpDecorate %ssboOUT DescriptorSet 0\n"
2834 "OpDecorate %ssboIN Binding 0\n"
2835 "OpDecorate %ssboOUT Binding 1\n"
2836 "\n"
2837 "%bool = OpTypeBool\n"
2838 "%void = OpTypeVoid\n"
2839 "%voidf = OpTypeFunction %void\n"
2840 "%u32 = OpTypeInt 32 0\n"
2841 "%uvec3 = OpTypeVector %u32 3\n"
2842 "%uvec3ptr = OpTypePointer Input %uvec3\n"
2843 "\n"
2844 "%i32 = OpTypeInt 32 1\n"
2845 "%v2i32 = OpTypeVector %i32 2\n"
2846 "%v4i32 = OpTypeVector %i32 4\n"
2847 "\n"
2848 "%f32 = OpTypeFloat 32\n"
2849 "%v2f32 = OpTypeVector %f32 2\n"
2850 "%v3f32 = OpTypeVector %f32 3\n"
2851 "%v4f32 = OpTypeVector %f32 4\n"
2852 "${types}\n"
2853 "\n"
2854 "%zero = OpConstant %i32 0\n"
2855 "%c_i32_1 = OpConstant %i32 1\n"
2856 "%c_i32_2 = OpConstant %i32 2\n"
2857 "%c_i32_3 = OpConstant %i32 3\n"
2858 "%c_i32_4 = OpConstant %i32 4\n"
2859 "%c_i32_5 = OpConstant %i32 5\n"
2860 "%c_i32_6 = OpConstant %i32 6\n"
2861 "%c_i32_7 = OpConstant %i32 7\n"
2862 "%c_i32_8 = OpConstant %i32 8\n"
2863 "%c_i32_9 = OpConstant %i32 9\n"
2864 "\n"
2865 "%c_u32_1 = OpConstant %u32 1\n"
2866 "%c_u32_3 = OpConstant %u32 3\n"
2867 "%c_u32_7 = OpConstant %u32 7\n"
2868 "%c_u32_11 = OpConstant %u32 11\n"
2869 "\n"
2870 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
2871 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
2872 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
2873 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
2874 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
2875 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
2876 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
2877 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
2878 "\n"
2879 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
2880 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
2881 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
2882 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
2883 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
2884 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
2885 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
2886 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
2887 "\n"
2888 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
2889 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
2890 "%SSBO_IN = OpTypeStruct %f32StructArr7\n"
2891 "%SSBO_OUT = OpTypeStruct %f16StructArr7\n"
2892 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
2893 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
2894 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
2895 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
2896 "\n"
2897 "%id = OpVariable %uvec3ptr Input\n"
2898 "%main = OpFunction %void None %voidf\n"
2899 "%label = OpLabel\n"
2900 "\n"
2901 "%idval = OpLoad %uvec3 %id\n"
2902 "%x = OpCompositeExtract %u32 %idval 0\n"
2903 "%y = OpCompositeExtract %u32 %idval 1\n"
2904 "\n"
2905 "%f32src = OpAccessChain %f32ptr %ssboIN %zero %x %zero\n"
2906 "%val_f32 = OpLoad %f32 %f32src\n"
2907 "%val_f16 = OpFConvert %f16 %val_f32\n"
2908 "%f16dst = OpAccessChain %f16ptr %ssboOUT %zero %x %zero\n"
2909 "OpStore %f16dst %val_f16\n"
2910 "\n"
2911 "%v2f32src = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_1\n"
2912 "%val_v2f32 = OpLoad %v2f32 %v2f32src\n"
2913 "%val_v2f16 = OpFConvert %v2f16 %val_v2f32\n"
2914 "%v2f16dst = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_1\n"
2915 "OpStore %v2f16dst %val_v2f16\n"
2916 "\n"
2917 "%v3f32src = OpAccessChain %v3f32ptr %ssboIN %zero %x %c_i32_2\n"
2918 "%val_v3f32 = OpLoad %v3f32 %v3f32src\n"
2919 "%val_v3f16 = OpFConvert %v3f16 %val_v3f32\n"
2920 "%v3f16dst = OpAccessChain %v3f16ptr %ssboOUT %zero %x %c_i32_2\n"
2921 "OpStore %v3f16dst %val_v3f16\n"
2922 "\n"
2923 "%v4f32src = OpAccessChain %v4f32ptr %ssboIN %zero %x %c_i32_3\n"
2924 "%val_v4f32 = OpLoad %v4f32 %v4f32src\n"
2925 "%val_v4f16 = OpFConvert %v4f16 %val_v4f32\n"
2926 "%v4f16dst = OpAccessChain %v4f16ptr %ssboOUT %zero %x %c_i32_3\n"
2927 "OpStore %v4f16dst %val_v4f16\n"
2928 "\n"
2929
2930 //struct {f16, v2f16[3]}
2931 "%Sf32src = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_5 %y %zero\n"
2932 "%Sval_f32 = OpLoad %f32 %Sf32src\n"
2933 "%Sval_f16 = OpFConvert %f16 %Sval_f32\n"
2934 "%Sf16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_5 %y %zero\n"
2935 "OpStore %Sf16dst2 %Sval_f16\n"
2936 "\n"
2937 "%Sv2f32src0 = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2938 "%Sv2f32_0 = OpLoad %v2f32 %Sv2f32src0\n"
2939 "%Sv2f16_0 = OpFConvert %v2f16 %Sv2f32_0\n"
2940 "%Sv2f16dst_0 = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %zero\n"
2941 "OpStore %Sv2f16dst_0 %Sv2f16_0\n"
2942 "\n"
2943 "%Sv2f32src1 = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2944 "%Sv2f32_1 = OpLoad %v2f32 %Sv2f32src1\n"
2945 "%Sv2f16_1 = OpFConvert %v2f16 %Sv2f32_1\n"
2946 "%Sv2f16dst_1 = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_1\n"
2947 "OpStore %Sv2f16dst_1 %Sv2f16_1\n"
2948 "\n"
2949 "%Sv2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2950 "%Sv2f32_2 = OpLoad %v2f32 %Sv2f32src2\n"
2951 "%Sv2f16_2 = OpFConvert %v2f16 %Sv2f32_2\n"
2952 "%Sv2f16dst_2 = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_5 %y %c_i32_1 %c_i32_2\n"
2953 "OpStore %Sv2f16dst_2 %Sv2f16_2\n"
2954 "\n"
2955
2956 "%v2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %x %c_i32_6 %y\n"
2957 "%val2_v2f32 = OpLoad %v2f32 %v2f32src2\n"
2958 "%val2_v2f16 = OpFConvert %v2f16 %val2_v2f32\n"
2959 "%v2f16dst2 = OpAccessChain %v2f16ptr %ssboOUT %zero %x %c_i32_6 %y\n"
2960 "OpStore %v2f16dst2 %val2_v2f16\n"
2961 "\n"
2962 "%f32src2 = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_7\n"
2963 "%val2_f32 = OpLoad %f32 %f32src2\n"
2964 "%val2_f16 = OpFConvert %f16 %val2_f32\n"
2965 "%f16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_7\n"
2966 "OpStore %f16dst2 %val2_f16\n"
2967 "\n"
2968 "%v3f32src2 = OpAccessChain %v3f32ptr %ssboIN %zero %x %c_i32_8 %y\n"
2969 "%val2_v3f32 = OpLoad %v3f32 %v3f32src2\n"
2970 "%val2_v3f16 = OpFConvert %v3f16 %val2_v3f32\n"
2971 "%v3f16dst2 = OpAccessChain %v3f16ptr %ssboOUT %zero %x %c_i32_8 %y\n"
2972 "OpStore %v3f16dst2 %val2_v3f16\n"
2973 "\n"
2974
2975 //Array with 3 elements
2976 "%LessThan3 = OpSLessThan %bool %y %c_i32_3\n"
2977 "OpSelectionMerge %BlockIf None\n"
2978 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
2979 " %LabelIf = OpLabel\n"
2980 " %f32src3 = OpAccessChain %f32ptr %ssboIN %zero %x %c_i32_4 %y\n"
2981 " %val3_f32 = OpLoad %f32 %f32src3\n"
2982 " %val3_f16 = OpFConvert %f16 %val3_f32\n"
2983 " %f16dst3 = OpAccessChain %f16ptr %ssboOUT %zero %x %c_i32_4 %y\n"
2984 " OpStore %f16dst3 %val3_f16\n"
2985 "\n"
2986 " %v4f32src2 = OpAccessChain %v4f32ptr %ssboIN %zero %x %c_i32_9 %y\n"
2987 " %val2_v4f32 = OpLoad %v4f32 %v4f32src2\n"
2988 " %val2_v4f16 = OpFConvert %v4f16 %val2_v4f32\n"
2989 " %v4f16dst2 = OpAccessChain %v4f16ptr %ssboOUT %zero %x %c_i32_9 %y\n"
2990 " OpStore %v4f16dst2 %val2_v4f16\n"
2991 "OpBranch %BlockIf\n"
2992 "%BlockIf = OpLabel\n"
2993
2994 " OpReturn\n"
2995 " OpFunctionEnd\n");
2996
2997 { // Floats
2998 vector<deFloat16> float16Data (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430), 0u);
2999
3000 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3001 {
3002 ComputeShaderSpec spec;
3003 map<string, string> specs;
3004 string testName = string(CAPABILITIES[capIdx].name);
3005 vector<float> float32DData = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data32bitStd430(rnd) : data32bitStd140(rnd);
3006
3007 specs["capability"] = CAPABILITIES[capIdx].cap;
3008 specs["storage"] = CAPABILITIES[capIdx].decor;
3009 specs["strideF16"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE16BIT_STD430);
3010 specs["strideF32"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE32BIT_STD430 : SHADERTEMPLATE_STRIDE32BIT_STD140);
3011 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
3012
3013 spec.assembly = shaderTemplate.specialize(specs);
3014 spec.numWorkGroups = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
3015 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>;
3016
3017 spec.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32DData)), CAPABILITIES[capIdx].dtype));
3018 spec.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data))));
3019 spec.extensions.push_back("VK_KHR_16bit_storage");
3020 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3021
3022 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
3023 }
3024 }
3025 }
3026
addCompute16bitStructMixedTypesGroup(tcu::TestCaseGroup * group)3027 void addCompute16bitStructMixedTypesGroup (tcu::TestCaseGroup* group)
3028 {
3029 tcu::TestContext& testCtx = group->getTestContext();
3030 de::Random rnd (deStringHash(group->getName()));
3031 vector<deInt16> outData (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430), 0u);
3032
3033 const StringTemplate shaderTemplate (
3034 "OpCapability Shader\n"
3035 "OpCapability StorageUniformBufferBlock16\n"
3036 "${capability}\n"
3037 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
3038 "OpExtension \"SPV_KHR_16bit_storage\"\n"
3039 "OpMemoryModel Logical GLSL450\n"
3040 "OpEntryPoint GLCompute %main \"main\" %id\n"
3041 "OpExecutionMode %main LocalSize 1 1 1\n"
3042 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3043 "${OutOffsets}"
3044 "${InOffsets}"
3045 "\n"//SSBO IN
3046 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
3047 "OpDecorate %ssboIN DescriptorSet 0\n"
3048 "OpDecorate %SSBO_IN ${storage}\n"
3049 "OpDecorate %SSBO_OUT BufferBlock\n"
3050 "OpDecorate %ssboIN Binding 0\n"
3051 "\n"//SSBO OUT
3052 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
3053 "OpDecorate %ssboOUT DescriptorSet 0\n"
3054 "OpDecorate %ssboOUT Binding 1\n"
3055 "\n"//Types
3056 "%void = OpTypeVoid\n"
3057 "%bool = OpTypeBool\n"
3058 "%i16 = OpTypeInt 16 1\n"
3059 "%v2i16 = OpTypeVector %i16 2\n"
3060 "%v3i16 = OpTypeVector %i16 3\n"
3061 "%v4i16 = OpTypeVector %i16 4\n"
3062 "%i32 = OpTypeInt 32 1\n"
3063 "%v2i32 = OpTypeVector %i32 2\n"
3064 "%v3i32 = OpTypeVector %i32 3\n"
3065 "%v4i32 = OpTypeVector %i32 4\n"
3066 "%u32 = OpTypeInt 32 0\n"
3067 "%uvec3 = OpTypeVector %u32 3\n"
3068 "%f32 = OpTypeFloat 32\n"
3069 "%v4f32 = OpTypeVector %f32 4\n"
3070 "%voidf = OpTypeFunction %void\n"
3071 "\n"//Consta value
3072 "%zero = OpConstant %i32 0\n"
3073 "%c_i32_1 = OpConstant %i32 1\n"
3074 "%c_i32_2 = OpConstant %i32 2\n"
3075 "%c_i32_3 = OpConstant %i32 3\n"
3076 "%c_i32_4 = OpConstant %i32 4\n"
3077 "%c_i32_5 = OpConstant %i32 5\n"
3078 "%c_i32_6 = OpConstant %i32 6\n"
3079 "%c_i32_7 = OpConstant %i32 7\n"
3080 "%c_i32_8 = OpConstant %i32 8\n"
3081 "%c_i32_9 = OpConstant %i32 9\n"
3082 "%c_i32_10 = OpConstant %i32 10\n"
3083 "%c_i32_11 = OpConstant %i32 11\n"
3084 "%c_u32_1 = OpConstant %u32 1\n"
3085 "%c_u32_7 = OpConstant %u32 7\n"
3086 "%c_u32_11 = OpConstant %u32 11\n"
3087 "\n"//Arrays & Structs
3088 "%v2b16NestedArr11In = OpTypeArray %v2i16 %c_u32_11\n"
3089 "%b32NestedArr11In = OpTypeArray %i32 %c_u32_11\n"
3090 "%sb16Arr11In = OpTypeArray %i16 %c_u32_11\n"
3091 "%sb32Arr11In = OpTypeArray %i32 %c_u32_11\n"
3092 "%sNestedIn = OpTypeStruct %i16 %i32 %v2b16NestedArr11In %b32NestedArr11In\n"
3093 "%sNestedArr11In = OpTypeArray %sNestedIn %c_u32_11\n"
3094 "%structIn = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11In %sb16Arr11In %sb32Arr11In\n"
3095 "%structArr7In = OpTypeArray %structIn %c_u32_7\n"
3096 "%v2b16NestedArr11Out = OpTypeArray %v2i16 %c_u32_11\n"
3097 "%b32NestedArr11Out = OpTypeArray %i32 %c_u32_11\n"
3098 "%sb16Arr11Out = OpTypeArray %i16 %c_u32_11\n"
3099 "%sb32Arr11Out = OpTypeArray %i32 %c_u32_11\n"
3100 "%sNestedOut = OpTypeStruct %i16 %i32 %v2b16NestedArr11Out %b32NestedArr11Out\n"
3101 "%sNestedArr11Out = OpTypeArray %sNestedOut %c_u32_11\n"
3102 "%structOut = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11Out %sb16Arr11Out %sb32Arr11Out\n"
3103 "%structArr7Out = OpTypeArray %structOut %c_u32_7\n"
3104 "\n"//Pointers
3105 "%i16outPtr = OpTypePointer Uniform %i16\n"
3106 "%v2i16outPtr = OpTypePointer Uniform %v2i16\n"
3107 "%v3i16outPtr = OpTypePointer Uniform %v3i16\n"
3108 "%v4i16outPtr = OpTypePointer Uniform %v4i16\n"
3109 "%i32outPtr = OpTypePointer Uniform %i32\n"
3110 "%v2i32outPtr = OpTypePointer Uniform %v2i32\n"
3111 "%v3i32outPtr = OpTypePointer Uniform %v3i32\n"
3112 "%v4i32outPtr = OpTypePointer Uniform %v4i32\n"
3113 "%fp_i32 = OpTypePointer Function %i32\n"
3114 "%uvec3ptr = OpTypePointer Input %uvec3\n"
3115 "\n"//SSBO IN
3116 "%SSBO_IN = OpTypeStruct %structArr7In\n"
3117 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
3118 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
3119 "\n"//SSBO OUT
3120 "%SSBO_OUT = OpTypeStruct %structArr7Out\n"
3121 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
3122 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
3123 "\n"//MAIN
3124 "%id = OpVariable %uvec3ptr Input\n"
3125 "%main = OpFunction %void None %voidf\n"
3126 "%label = OpLabel\n"
3127 "%ndxArrz = OpVariable %fp_i32 Function\n"
3128 "%idval = OpLoad %uvec3 %id\n"
3129 "%x = OpCompositeExtract %u32 %idval 0\n"
3130 "%y = OpCompositeExtract %u32 %idval 1\n"
3131 "\n"//strutOut.b16 = strutIn.b16
3132 "%inP1 = OpAccessChain %i16${inPtr} %ssboIN %zero %x %zero\n"
3133 "%inV1 = OpLoad %i16 %inP1\n"
3134 "%outP1 = OpAccessChain %i16outPtr %ssboOUT %zero %x %zero\n"
3135 "OpStore %outP1 %inV1\n"
3136 "\n"//strutOut.b32 = strutIn.b32
3137 "%inP2 = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_1\n"
3138 "%inV2 = OpLoad %i32 %inP2\n"
3139 "%outP2 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_1\n"
3140 "OpStore %outP2 %inV2\n"
3141 "\n"//strutOut.v2b16 = strutIn.v2b16
3142 "%inP3 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %x %c_i32_2\n"
3143 "%inV3 = OpLoad %v2i16 %inP3\n"
3144 "%outP3 = OpAccessChain %v2i16outPtr %ssboOUT %zero %x %c_i32_2\n"
3145 "OpStore %outP3 %inV3\n"
3146 "\n"//strutOut.v2b32 = strutIn.v2b32
3147 "%inP4 = OpAccessChain %v2i32${inPtr} %ssboIN %zero %x %c_i32_3\n"
3148 "%inV4 = OpLoad %v2i32 %inP4\n"
3149 "%outP4 = OpAccessChain %v2i32outPtr %ssboOUT %zero %x %c_i32_3\n"
3150 "OpStore %outP4 %inV4\n"
3151 "\n"//strutOut.v3b16 = strutIn.v3b16
3152 "%inP5 = OpAccessChain %v3i16${inPtr} %ssboIN %zero %x %c_i32_4\n"
3153 "%inV5 = OpLoad %v3i16 %inP5\n"
3154 "%outP5 = OpAccessChain %v3i16outPtr %ssboOUT %zero %x %c_i32_4\n"
3155 "OpStore %outP5 %inV5\n"
3156 "\n"//strutOut.v3b32 = strutIn.v3b32
3157 "%inP6 = OpAccessChain %v3i32${inPtr} %ssboIN %zero %x %c_i32_5\n"
3158 "%inV6 = OpLoad %v3i32 %inP6\n"
3159 "%outP6 = OpAccessChain %v3i32outPtr %ssboOUT %zero %x %c_i32_5\n"
3160 "OpStore %outP6 %inV6\n"
3161 "\n"//strutOut.v4b16 = strutIn.v4b16
3162 "%inP7 = OpAccessChain %v4i16${inPtr} %ssboIN %zero %x %c_i32_6\n"
3163 "%inV7 = OpLoad %v4i16 %inP7\n"
3164 "%outP7 = OpAccessChain %v4i16outPtr %ssboOUT %zero %x %c_i32_6\n"
3165 "OpStore %outP7 %inV7\n"
3166 "\n"//strutOut.v4b32 = strutIn.v4b32
3167 "%inP8 = OpAccessChain %v4i32${inPtr} %ssboIN %zero %x %c_i32_7\n"
3168 "%inV8 = OpLoad %v4i32 %inP8\n"
3169 "%outP8 = OpAccessChain %v4i32outPtr %ssboOUT %zero %x %c_i32_7\n"
3170 "OpStore %outP8 %inV8\n"
3171 "\n"//strutOut.b16[y] = strutIn.b16[y]
3172 "%inP9 = OpAccessChain %i16${inPtr} %ssboIN %zero %x %c_i32_9 %y\n"
3173 "%inV9 = OpLoad %i16 %inP9\n"
3174 "%outP9 = OpAccessChain %i16outPtr %ssboOUT %zero %x %c_i32_9 %y\n"
3175 "OpStore %outP9 %inV9\n"
3176 "\n"//strutOut.b32[y] = strutIn.b32[y]
3177 "%inP10 = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_10 %y\n"
3178 "%inV10 = OpLoad %i32 %inP10\n"
3179 "%outP10 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_10 %y\n"
3180 "OpStore %outP10 %inV10\n"
3181 "\n"//strutOut.strutNestedOut[y].b16 = strutIn.strutNestedIn[y].b16
3182 "%inP11 = OpAccessChain %i16${inPtr} %ssboIN %zero %x %c_i32_8 %y %zero\n"
3183 "%inV11 = OpLoad %i16 %inP11\n"
3184 "%outP11 = OpAccessChain %i16outPtr %ssboOUT %zero %x %c_i32_8 %y %zero\n"
3185 "OpStore %outP11 %inV11\n"
3186 "\n"//strutOut.strutNestedOut[y].b32 = strutIn.strutNestedIn[y].b32
3187 "%inP12 = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_1\n"
3188 "%inV12 = OpLoad %i32 %inP12\n"
3189 "%outP12 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_1\n"
3190 "OpStore %outP12 %inV12\n"
3191 "\n"
3192 "${zBeginLoop}"
3193 "\n"//strutOut.strutNestedOut[y].v2b16[valNdx] = strutIn.strutNestedIn[y].v2b16[valNdx]
3194 "%inP13 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_2 %Valz\n"
3195 "%inV13 = OpLoad %v2i16 %inP13\n"
3196 "%outP13 = OpAccessChain %v2i16outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_2 %Valz\n"
3197 "OpStore %outP13 %inV13\n"
3198 "\n"//strutOut.strutNestedOut[y].b32[valNdx] = strutIn.strutNestedIn[y].b32[valNdx]
3199 "%inP14 = OpAccessChain %i32${inPtr} %ssboIN %zero %x %c_i32_8 %y %c_i32_3 %Valz\n"
3200 "%inV14 = OpLoad %i32 %inP14\n"
3201 "%outP14 = OpAccessChain %i32outPtr %ssboOUT %zero %x %c_i32_8 %y %c_i32_3 %Valz\n"
3202 "OpStore %outP14 %inV14\n"
3203 "\n${zEndLoop}\n"
3204 "OpBranch %exitLabel\n"
3205 "%exitLabel = OpLabel\n"
3206 "OpReturn\n"
3207 "OpFunctionEnd\n");
3208
3209 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3210 { // int
3211 const bool isUniform = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == CAPABILITIES[capIdx].dtype;
3212 vector<deInt16> inData = isUniform ? dataMixStd140(rnd) : dataMixStd430(rnd);
3213 ComputeShaderSpec spec;
3214 map<string, string> specsOffset;
3215 map<string, string> specsLoop;
3216 map<string, string> specs;
3217 string testName = string(CAPABILITIES[capIdx].name);
3218
3219 specsLoop["exeCount"] = "c_i32_11";
3220 specsLoop["loopName"] = "z";
3221 specs["zBeginLoop"] = beginLoop(specsLoop);
3222 specs["zEndLoop"] = endLoop(specsLoop);
3223 specs["capability"] = isUniform ? "OpCapability " + string(CAPABILITIES[capIdx].cap) : " ";
3224 specs["inPtr"] = "outPtr";
3225 specs["storage"] = isUniform ? "Block" : "BufferBlock";
3226 specsOffset["InOut"] = "In";
3227 specs["InOffsets"] = StringTemplate(isUniform ? getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD140) : getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
3228 specsOffset["InOut"] = "Out";
3229 specs["OutOffsets"] = StringTemplate(getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
3230
3231 spec.assembly = shaderTemplate.specialize(specs);
3232 spec.numWorkGroups = IVec3(structData.structArraySize, structData.nestedArraySize, 1);
3233 spec.verifyIO = isUniform ? computeCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD140, SHADERTEMPLATE_STRIDEMIX_STD430> : computeCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD430, SHADERTEMPLATE_STRIDEMIX_STD430>;
3234 spec.inputs.push_back (Resource(BufferSp(new Int16Buffer(inData)), CAPABILITIES[capIdx].dtype));
3235 spec.outputs.push_back (Resource(BufferSp(new Int16Buffer(outData))));
3236 spec.extensions.push_back ("VK_KHR_16bit_storage");
3237 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3238
3239 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
3240 }
3241 }
3242
addGraphics16BitStorageUniformFloat32To16Group(tcu::TestCaseGroup * testGroup)3243 void addGraphics16BitStorageUniformFloat32To16Group (tcu::TestCaseGroup* testGroup)
3244 {
3245 de::Random rnd (deStringHash(testGroup->getName()));
3246 map<string, string> fragments;
3247 vector<string> extensions;
3248 const deUint32 numDataPoints = 256;
3249 RGBA defaultColors[4];
3250 const vector<float> float32Data = getFloat32s(rnd, numDataPoints);
3251 vector<float> float32DataPadded;
3252 vector<deFloat16> float16UnusedData (numDataPoints, 0);
3253 const StringTemplate capabilities ("OpCapability ${cap}\n");
3254
3255 for (size_t dataIdx = 0; dataIdx < float32Data.size(); ++dataIdx)
3256 {
3257 float32DataPadded.push_back(float32Data[dataIdx]);
3258 float32DataPadded.push_back(0.0f);
3259 float32DataPadded.push_back(0.0f);
3260 float32DataPadded.push_back(0.0f);
3261 }
3262
3263 extensions.push_back("VK_KHR_16bit_storage");
3264 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
3265
3266 struct RndMode
3267 {
3268 const char* name;
3269 const char* decor;
3270 VerifyIOFunc f;
3271 };
3272
3273 getDefaultColors(defaultColors);
3274
3275 { // scalar cases
3276 fragments["pre_main"] =
3277 " %f16 = OpTypeFloat 16\n"
3278 "%c_i32_256 = OpConstant %i32 256\n"
3279 " %up_f32 = OpTypePointer Uniform %f32\n"
3280 " %up_f16 = OpTypePointer Uniform %f16\n"
3281 " %ra_f32 = OpTypeArray %f32 %c_i32_256\n"
3282 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
3283 " %SSBO32 = OpTypeStruct %ra_f32\n"
3284 " %SSBO16 = OpTypeStruct %ra_f16\n"
3285 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3286 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3287 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3288 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3289
3290 const StringTemplate decoration (
3291 "OpDecorate %ra_f32 ArrayStride ${arraystride}\n"
3292 "OpDecorate %ra_f16 ArrayStride 2\n"
3293 "OpMemberDecorate %SSBO32 0 Offset 0\n"
3294 "OpMemberDecorate %SSBO16 0 Offset 0\n"
3295 "OpDecorate %SSBO32 ${indecor}\n"
3296 "OpDecorate %SSBO16 BufferBlock\n"
3297 "OpDecorate %ssbo32 DescriptorSet 0\n"
3298 "OpDecorate %ssbo16 DescriptorSet 0\n"
3299 "OpDecorate %ssbo32 Binding 0\n"
3300 "OpDecorate %ssbo16 Binding 1\n"
3301 "${rounddecor}\n");
3302
3303 fragments["testfun"] =
3304 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3305 " %param = OpFunctionParameter %v4f32\n"
3306
3307 "%entry = OpLabel\n"
3308 " %i = OpVariable %fp_i32 Function\n"
3309 " OpStore %i %c_i32_0\n"
3310 " OpBranch %loop\n"
3311
3312 " %loop = OpLabel\n"
3313 " %15 = OpLoad %i32 %i\n"
3314 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
3315 " OpLoopMerge %merge %inc None\n"
3316 " OpBranchConditional %lt %write %merge\n"
3317
3318 "%write = OpLabel\n"
3319 " %30 = OpLoad %i32 %i\n"
3320 " %src = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n"
3321 "%val32 = OpLoad %f32 %src\n"
3322 "%val16 = OpFConvert %f16 %val32\n"
3323 " %dst = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n"
3324 " OpStore %dst %val16\n"
3325 " OpBranch %inc\n"
3326
3327 " %inc = OpLabel\n"
3328 " %37 = OpLoad %i32 %i\n"
3329 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
3330 " OpStore %i %39\n"
3331 " OpBranch %loop\n"
3332
3333 "%merge = OpLabel\n"
3334 " OpReturnValue %param\n"
3335
3336 "OpFunctionEnd\n";
3337
3338 const RndMode rndModes[] =
3339 {
3340 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3341 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3342 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3343 };
3344
3345 const deUint32 arrayStrides[] = {4, 16};
3346
3347 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3348 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3349 {
3350 map<string, string> specs;
3351 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float_" + rndModes[rndModeIdx].name;
3352 GraphicsResources resources;
3353 VulkanFeatures features;
3354
3355 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(arrayStrides[capIdx] == 4 ? float32Data : float32DataPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3356 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
3357 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3358
3359 specs["cap"] = CAPABILITIES[capIdx].cap;
3360 specs["indecor"] = CAPABILITIES[capIdx].decor;
3361 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
3362 specs["rounddecor"] = rndModes[rndModeIdx].decor;
3363
3364 fragments["capability"] = capabilities.specialize(specs);
3365 fragments["decoration"] = decoration.specialize(specs);
3366
3367 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3368 resources.verifyIO = rndModes[rndModeIdx].f;
3369
3370 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3371 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
3372 features.coreFeatures.fragmentStoresAndAtomics = true;
3373
3374 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
3375 }
3376 }
3377
3378 // Non-scalar cases can use the same resources.
3379 GraphicsResources resources;
3380 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3381 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
3382 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
3383
3384 { // vector cases
3385 fragments["pre_main"] =
3386 " %f16 = OpTypeFloat 16\n"
3387 " %c_i32_64 = OpConstant %i32 64\n"
3388 " %v4f16 = OpTypeVector %f16 4\n"
3389 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
3390 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
3391 " %ra_v4f32 = OpTypeArray %v4f32 %c_i32_64\n"
3392 " %ra_v4f16 = OpTypeArray %v4f16 %c_i32_64\n"
3393 " %SSBO32 = OpTypeStruct %ra_v4f32\n"
3394 " %SSBO16 = OpTypeStruct %ra_v4f16\n"
3395 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3396 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3397 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3398 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3399
3400 const StringTemplate decoration (
3401 "OpDecorate %ra_v4f32 ArrayStride 16\n"
3402 "OpDecorate %ra_v4f16 ArrayStride 8\n"
3403 "OpMemberDecorate %SSBO32 0 Offset 0\n"
3404 "OpMemberDecorate %SSBO16 0 Offset 0\n"
3405 "OpDecorate %SSBO32 ${indecor}\n"
3406 "OpDecorate %SSBO16 BufferBlock\n"
3407 "OpDecorate %ssbo32 DescriptorSet 0\n"
3408 "OpDecorate %ssbo16 DescriptorSet 0\n"
3409 "OpDecorate %ssbo32 Binding 0\n"
3410 "OpDecorate %ssbo16 Binding 1\n"
3411 "${rounddecor}\n");
3412
3413 // ssbo16[] <- convert ssbo32[] to 16bit float
3414 fragments["testfun"] =
3415 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3416 " %param = OpFunctionParameter %v4f32\n"
3417
3418 "%entry = OpLabel\n"
3419 " %i = OpVariable %fp_i32 Function\n"
3420 " OpStore %i %c_i32_0\n"
3421 " OpBranch %loop\n"
3422
3423 " %loop = OpLabel\n"
3424 " %15 = OpLoad %i32 %i\n"
3425 " %lt = OpSLessThan %bool %15 %c_i32_64\n"
3426 " OpLoopMerge %merge %inc None\n"
3427 " OpBranchConditional %lt %write %merge\n"
3428
3429 "%write = OpLabel\n"
3430 " %30 = OpLoad %i32 %i\n"
3431 " %src = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30\n"
3432 "%val32 = OpLoad %v4f32 %src\n"
3433 "%val16 = OpFConvert %v4f16 %val32\n"
3434 " %dst = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30\n"
3435 " OpStore %dst %val16\n"
3436 " OpBranch %inc\n"
3437
3438 " %inc = OpLabel\n"
3439 " %37 = OpLoad %i32 %i\n"
3440 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
3441 " OpStore %i %39\n"
3442 " OpBranch %loop\n"
3443
3444 "%merge = OpLabel\n"
3445 " OpReturnValue %param\n"
3446
3447 "OpFunctionEnd\n";
3448
3449 const RndMode rndModes[] =
3450 {
3451 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3452 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3453 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3454 };
3455
3456 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3457 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3458 {
3459 map<string, string> specs;
3460 VulkanFeatures features;
3461 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float_" + rndModes[rndModeIdx].name;
3462
3463 specs["cap"] = CAPABILITIES[capIdx].cap;
3464 specs["indecor"] = CAPABILITIES[capIdx].decor;
3465 specs["rounddecor"] = rndModes[rndModeIdx].decor;
3466
3467 fragments["capability"] = capabilities.specialize(specs);
3468 fragments["decoration"] = decoration.specialize(specs);
3469
3470 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3471 resources.verifyIO = rndModes[rndModeIdx].f;
3472
3473 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3474 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
3475 features.coreFeatures.fragmentStoresAndAtomics = true;
3476
3477 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
3478 }
3479 }
3480
3481 { // matrix cases
3482 fragments["pre_main"] =
3483 " %f16 = OpTypeFloat 16\n"
3484 " %c_i32_16 = OpConstant %i32 16\n"
3485 " %v4f16 = OpTypeVector %f16 4\n"
3486 " %m4x4f32 = OpTypeMatrix %v4f32 4\n"
3487 " %m4x4f16 = OpTypeMatrix %v4f16 4\n"
3488 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
3489 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
3490 "%a16m4x4f32 = OpTypeArray %m4x4f32 %c_i32_16\n"
3491 "%a16m4x4f16 = OpTypeArray %m4x4f16 %c_i32_16\n"
3492 " %SSBO32 = OpTypeStruct %a16m4x4f32\n"
3493 " %SSBO16 = OpTypeStruct %a16m4x4f16\n"
3494 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
3495 " %up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
3496 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
3497 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
3498
3499 const StringTemplate decoration (
3500 "OpDecorate %a16m4x4f32 ArrayStride 64\n"
3501 "OpDecorate %a16m4x4f16 ArrayStride 32\n"
3502 "OpMemberDecorate %SSBO32 0 Offset 0\n"
3503 "OpMemberDecorate %SSBO32 0 ColMajor\n"
3504 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
3505 "OpMemberDecorate %SSBO16 0 Offset 0\n"
3506 "OpMemberDecorate %SSBO16 0 ColMajor\n"
3507 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n"
3508 "OpDecorate %SSBO32 ${indecor}\n"
3509 "OpDecorate %SSBO16 BufferBlock\n"
3510 "OpDecorate %ssbo32 DescriptorSet 0\n"
3511 "OpDecorate %ssbo16 DescriptorSet 0\n"
3512 "OpDecorate %ssbo32 Binding 0\n"
3513 "OpDecorate %ssbo16 Binding 1\n"
3514 "${rounddecor}\n");
3515
3516 fragments["testfun"] =
3517 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
3518 " %param = OpFunctionParameter %v4f32\n"
3519
3520 "%entry = OpLabel\n"
3521 " %i = OpVariable %fp_i32 Function\n"
3522 " OpStore %i %c_i32_0\n"
3523 " OpBranch %loop\n"
3524
3525 " %loop = OpLabel\n"
3526 " %15 = OpLoad %i32 %i\n"
3527 " %lt = OpSLessThan %bool %15 %c_i32_16\n"
3528 " OpLoopMerge %merge %inc None\n"
3529 " OpBranchConditional %lt %write %merge\n"
3530
3531 " %write = OpLabel\n"
3532 " %30 = OpLoad %i32 %i\n"
3533 " %src_0 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n"
3534 " %src_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
3535 " %src_2 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n"
3536 " %src_3 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n"
3537 "%val32_0 = OpLoad %v4f32 %src_0\n"
3538 "%val32_1 = OpLoad %v4f32 %src_1\n"
3539 "%val32_2 = OpLoad %v4f32 %src_2\n"
3540 "%val32_3 = OpLoad %v4f32 %src_3\n"
3541 "%val16_0 = OpFConvert %v4f16 %val32_0\n"
3542 "%val16_1 = OpFConvert %v4f16 %val32_1\n"
3543 "%val16_2 = OpFConvert %v4f16 %val32_2\n"
3544 "%val16_3 = OpFConvert %v4f16 %val32_3\n"
3545 " %dst_0 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
3546 " %dst_1 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
3547 " %dst_2 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
3548 " %dst_3 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
3549 " OpStore %dst_0 %val16_0\n"
3550 " OpStore %dst_1 %val16_1\n"
3551 " OpStore %dst_2 %val16_2\n"
3552 " OpStore %dst_3 %val16_3\n"
3553 " OpBranch %inc\n"
3554
3555 " %inc = OpLabel\n"
3556 " %37 = OpLoad %i32 %i\n"
3557 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
3558 " OpStore %i %39\n"
3559 " OpBranch %loop\n"
3560
3561 "%merge = OpLabel\n"
3562 " OpReturnValue %param\n"
3563
3564 "OpFunctionEnd\n";
3565
3566 const RndMode rndModes[] =
3567 {
3568 {"rte", "OpDecorate %val16_0 FPRoundingMode RTE\nOpDecorate %val16_1 FPRoundingMode RTE\nOpDecorate %val16_2 FPRoundingMode RTE\nOpDecorate %val16_3 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>},
3569 {"rtz", "OpDecorate %val16_0 FPRoundingMode RTZ\nOpDecorate %val16_1 FPRoundingMode RTZ\nOpDecorate %val16_2 FPRoundingMode RTZ\nOpDecorate %val16_3 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>},
3570 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
3571 };
3572
3573 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
3574 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3575 {
3576 map<string, string> specs;
3577 VulkanFeatures features;
3578 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float_" + rndModes[rndModeIdx].name;
3579
3580 specs["cap"] = CAPABILITIES[capIdx].cap;
3581 specs["indecor"] = CAPABILITIES[capIdx].decor;
3582 specs["rounddecor"] = rndModes[rndModeIdx].decor;
3583
3584 fragments["capability"] = capabilities.specialize(specs);
3585 fragments["decoration"] = decoration.specialize(specs);
3586
3587 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
3588 resources.verifyIO = rndModes[rndModeIdx].f;
3589
3590 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
3591 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
3592 features.coreFeatures.fragmentStoresAndAtomics = true;
3593
3594 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
3595 }
3596 }
3597 }
3598
addGraphics16BitStorageInputOutputFloat32To16Group(tcu::TestCaseGroup * testGroup)3599 void addGraphics16BitStorageInputOutputFloat32To16Group (tcu::TestCaseGroup* testGroup)
3600 {
3601 de::Random rnd (deStringHash(testGroup->getName()));
3602 RGBA defaultColors[4];
3603 vector<string> extensions;
3604 map<string, string> fragments = passthruFragments();
3605 const deUint32 numDataPoints = 64;
3606 // Special values like inf/nan/denormal may not be preserved when float control features are not provided,
3607 // thus values generating special float16 values must be excluded in input data here.
3608 vector<float> float32Data = getFloat32s(rnd, numDataPoints, DE_FALSE);
3609
3610 extensions.push_back("VK_KHR_16bit_storage");
3611
3612 fragments["capability"] = "OpCapability StorageInputOutput16\n";
3613 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3614
3615 getDefaultColors(defaultColors);
3616
3617 struct RndMode
3618 {
3619 const char* name;
3620 const char* decor;
3621 const char* decor_tessc;
3622 RoundingModeFlags flags;
3623 };
3624
3625 const RndMode rndModes[] =
3626 {
3627 {"rtz",
3628 "OpDecorate %ret0 FPRoundingMode RTZ\n",
3629 "OpDecorate %ret1 FPRoundingMode RTZ\n"
3630 "OpDecorate %ret2 FPRoundingMode RTZ\n",
3631 ROUNDINGMODE_RTZ},
3632 {"rte",
3633 "OpDecorate %ret0 FPRoundingMode RTE\n",
3634 "OpDecorate %ret1 FPRoundingMode RTE\n"
3635 "OpDecorate %ret2 FPRoundingMode RTE\n",
3636 ROUNDINGMODE_RTE},
3637 {"unspecified_rnd_mode", "", "", RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)},
3638 };
3639
3640 struct Case
3641 {
3642 const char* name;
3643 const char* interfaceOpCall;
3644 const char* interfaceOpFunc;
3645 const char* postInterfaceOp;
3646 const char* postInterfaceOpGeom;
3647 const char* postInterfaceOpTessc;
3648 const char* preMain;
3649 const char* inputType;
3650 const char* outputType;
3651 deUint32 numPerCase;
3652 deUint32 numElements;
3653 };
3654
3655 const Case cases[] =
3656 {
3657 { // Scalar cases
3658 "scalar",
3659 "OpFConvert %f16",
3660 "",
3661
3662 " %ret0 = OpFConvert %f16 %IF_input_val\n"
3663 " OpStore %IF_output %ret0\n",
3664
3665 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
3666 " OpStore %IF_output %ret0\n",
3667
3668 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
3669 " OpStore %IF_output_ptr0 %ret0\n"
3670 " %ret1 = OpFConvert %f16 %IF_input_val1\n"
3671 " OpStore %IF_output_ptr1 %ret1\n"
3672 " %ret2 = OpFConvert %f16 %IF_input_val2\n"
3673 " OpStore %IF_output_ptr2 %ret2\n",
3674
3675 " %f16 = OpTypeFloat 16\n"
3676 " %op_f16 = OpTypePointer Output %f16\n"
3677 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
3678 " %op_a3f16 = OpTypePointer Output %a3f16\n"
3679 "%f16_f32_function = OpTypeFunction %f16 %f32\n"
3680 " %a3f32 = OpTypeArray %f32 %c_i32_3\n"
3681 " %ip_a3f32 = OpTypePointer Input %a3f32\n",
3682
3683 "f32",
3684 "f16",
3685 4,
3686 1,
3687 },
3688 { // Vector cases
3689 "vector",
3690
3691 "OpFConvert %v2f16",
3692 "",
3693
3694 " %ret0 = OpFConvert %v2f16 %IF_input_val\n"
3695 " OpStore %IF_output %ret0\n",
3696
3697 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
3698 " OpStore %IF_output %ret0\n",
3699
3700 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
3701 " OpStore %IF_output_ptr0 %ret0\n"
3702 " %ret1 = OpFConvert %v2f16 %IF_input_val1\n"
3703 " OpStore %IF_output_ptr1 %ret1\n"
3704 " %ret2 = OpFConvert %v2f16 %IF_input_val2\n"
3705 " OpStore %IF_output_ptr2 %ret2\n",
3706
3707 " %f16 = OpTypeFloat 16\n"
3708 " %v2f16 = OpTypeVector %f16 2\n"
3709 " %op_v2f16 = OpTypePointer Output %v2f16\n"
3710 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
3711 " %op_a3v2f16 = OpTypePointer Output %a3v2f16\n"
3712 "%v2f16_v2f32_function = OpTypeFunction %v2f16 %v2f32\n"
3713 " %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n"
3714 " %ip_a3v2f32 = OpTypePointer Input %a3v2f32\n",
3715
3716 "v2f32",
3717 "v2f16",
3718 2 * 4,
3719 2,
3720 }
3721 };
3722
3723 VulkanFeatures requiredFeatures;
3724 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
3725
3726 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
3727 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
3728 {
3729 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
3730 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
3731 fragments["post_interface_op_frag"] = cases[caseIdx].postInterfaceOp;
3732 fragments["post_interface_op_vert"] = cases[caseIdx].postInterfaceOp;
3733 fragments["post_interface_op_geom"] = cases[caseIdx].postInterfaceOpGeom;
3734 fragments["post_interface_op_tesse"] = cases[caseIdx].postInterfaceOpGeom;
3735 fragments["post_interface_op_tessc"] = cases[caseIdx].postInterfaceOpTessc;
3736 fragments["pre_main"] = cases[caseIdx].preMain;
3737 fragments["decoration"] = rndModes[rndModeIdx].decor;
3738 fragments["decoration_tessc"] = rndModes[rndModeIdx].decor_tessc;
3739
3740 fragments["input_type"] = cases[caseIdx].inputType;
3741 fragments["output_type"] = cases[caseIdx].outputType;
3742
3743 GraphicsInterfaces interfaces;
3744 const deUint32 numPerCase = cases[caseIdx].numPerCase;
3745 vector<float> subInputs (numPerCase);
3746 vector<deFloat16> subOutputs (numPerCase);
3747
3748 // The pipeline need this to call compare16BitFloat() when checking the result.
3749 interfaces.setRoundingMode(rndModes[rndModeIdx].flags);
3750
3751 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
3752 {
3753 string testName = string(cases[caseIdx].name) + numberToString(caseNdx) + "_" + rndModes[rndModeIdx].name;
3754
3755 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
3756 {
3757 subInputs[numNdx] = float32Data[caseNdx * numPerCase + numNdx];
3758 // We derive the expected result from inputs directly in the graphics pipeline.
3759 subOutputs[numNdx] = 0;
3760 }
3761 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subInputs))),
3762 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs))));
3763 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
3764 }
3765 }
3766 }
3767
addGraphics16BitStorageInputOutputFloat16To32Group(tcu::TestCaseGroup * testGroup)3768 void addGraphics16BitStorageInputOutputFloat16To32Group (tcu::TestCaseGroup* testGroup)
3769 {
3770 de::Random rnd (deStringHash(testGroup->getName()));
3771 RGBA defaultColors[4];
3772 vector<string> extensions;
3773 map<string, string> fragments = passthruFragments();
3774 const deUint32 numDataPoints = 64;
3775 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
3776 vector<float> float32Data;
3777
3778 float32Data.reserve(numDataPoints);
3779 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
3780 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
3781
3782 extensions.push_back("VK_KHR_16bit_storage");
3783
3784 fragments["capability"] = "OpCapability StorageInputOutput16\n";
3785 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3786
3787 getDefaultColors(defaultColors);
3788
3789 struct Case
3790 {
3791 const char* name;
3792 const char* interfaceOpCall;
3793 const char* interfaceOpFunc;
3794 const char* preMain;
3795 const char* inputType;
3796 const char* outputType;
3797 deUint32 numPerCase;
3798 deUint32 numElements;
3799 };
3800
3801 Case cases[] =
3802 {
3803 { // Scalar cases
3804 "scalar",
3805
3806 "OpFConvert %f32",
3807 "",
3808
3809 " %f16 = OpTypeFloat 16\n"
3810 " %ip_f16 = OpTypePointer Input %f16\n"
3811 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
3812 " %ip_a3f16 = OpTypePointer Input %a3f16\n"
3813 "%f32_f16_function = OpTypeFunction %f32 %f16\n"
3814 " %a3f32 = OpTypeArray %f32 %c_i32_3\n"
3815 " %op_a3f32 = OpTypePointer Output %a3f32\n",
3816
3817 "f16",
3818 "f32",
3819 4,
3820 1,
3821 },
3822 { // Vector cases
3823 "vector",
3824
3825 "OpFConvert %v2f32",
3826 "",
3827
3828 " %f16 = OpTypeFloat 16\n"
3829 " %v2f16 = OpTypeVector %f16 2\n"
3830 " %ip_v2f16 = OpTypePointer Input %v2f16\n"
3831 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
3832 " %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
3833 "%v2f32_v2f16_function = OpTypeFunction %v2f32 %v2f16\n"
3834 " %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n"
3835 " %op_a3v2f32 = OpTypePointer Output %a3v2f32\n",
3836
3837 "v2f16",
3838 "v2f32",
3839 2 * 4,
3840 2,
3841 }
3842 };
3843
3844 VulkanFeatures requiredFeatures;
3845 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
3846
3847 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
3848 {
3849 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
3850 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
3851 fragments["pre_main"] = cases[caseIdx].preMain;
3852
3853 fragments["input_type"] = cases[caseIdx].inputType;
3854 fragments["output_type"] = cases[caseIdx].outputType;
3855
3856 GraphicsInterfaces interfaces;
3857 const deUint32 numPerCase = cases[caseIdx].numPerCase;
3858 vector<deFloat16> subInputs (numPerCase);
3859 vector<float> subOutputs (numPerCase);
3860
3861 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
3862 {
3863 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
3864
3865 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
3866 {
3867 subInputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx];
3868 subOutputs[numNdx] = float32Data[caseNdx * numPerCase + numNdx];
3869 }
3870 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))),
3871 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subOutputs))));
3872 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
3873 }
3874 }
3875 }
3876
addGraphics16BitStorageInputOutputFloat16To16Group(tcu::TestCaseGroup * testGroup)3877 void addGraphics16BitStorageInputOutputFloat16To16Group (tcu::TestCaseGroup* testGroup)
3878 {
3879 de::Random rnd (deStringHash(testGroup->getName()));
3880 RGBA defaultColors[4];
3881 vector<string> extensions;
3882 map<string, string> fragments = passthruFragments();
3883 const deUint32 numDataPoints = 64;
3884 // Special values like inf/nan/denormal may not be preserved when float control features are not provided,
3885 // thus those values must be excluded in the input data here.
3886 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints, DE_FALSE));
3887 VulkanFeatures requiredFeatures;
3888
3889 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
3890 extensions.push_back("VK_KHR_16bit_storage");
3891
3892 fragments["capability"] = "OpCapability StorageInputOutput16\n";
3893 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3894
3895 getDefaultColors(defaultColors);
3896
3897 struct Case
3898 {
3899 const char* name;
3900 const char* interfaceOpCall;
3901 const char* interfaceOpFunc;
3902 const char* preMain;
3903 const char* inputType;
3904 const char* outputType;
3905 deUint32 numPerCase;
3906 deUint32 numElements;
3907 };
3908
3909 Case cases[] =
3910 {
3911 { // Scalar cases
3912 "scalar",
3913
3914 "OpCopyObject %f16",
3915 "",
3916
3917 " %f16 = OpTypeFloat 16\n"
3918 " %ip_f16 = OpTypePointer Input %f16\n"
3919 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
3920 " %ip_a3f16 = OpTypePointer Input %a3f16\n"
3921 "%f16_f16_function = OpTypeFunction %f16 %f16\n"
3922 " %op_f16 = OpTypePointer Output %f16\n"
3923 " %op_a3f16 = OpTypePointer Output %a3f16\n",
3924
3925 "f16",
3926 "f16",
3927 4,
3928 1,
3929 },
3930 { // Vector cases
3931 "vector",
3932
3933 "OpCopyObject %v2f16",
3934 "",
3935
3936 " %f16 = OpTypeFloat 16\n"
3937 " %v2f16 = OpTypeVector %f16 2\n"
3938 " %ip_v2f16 = OpTypePointer Input %v2f16\n"
3939 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
3940 " %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
3941 "%v2f16_v2f16_function = OpTypeFunction %v2f16 %v2f16\n"
3942 " %op_v2f16 = OpTypePointer Output %v2f16\n"
3943 " %op_a3v2f16 = OpTypePointer Output %a3v2f16\n",
3944
3945 "v2f16",
3946 "v2f16",
3947 2 * 4,
3948 2,
3949 }
3950 };
3951
3952 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
3953 {
3954 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
3955 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
3956 fragments["pre_main"] = cases[caseIdx].preMain;
3957
3958 fragments["input_type"] = cases[caseIdx].inputType;
3959 fragments["output_type"] = cases[caseIdx].outputType;
3960
3961 GraphicsInterfaces interfaces;
3962 const deUint32 numPerCase = cases[caseIdx].numPerCase;
3963 vector<deFloat16> subInputsOutputs (numPerCase);
3964
3965 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
3966 {
3967 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
3968
3969 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
3970 subInputsOutputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx];
3971
3972 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputsOutputs))),
3973 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputsOutputs))));
3974
3975 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
3976 }
3977 }
3978 }
3979
addShaderCode16BitStorageInputOutput16To16x2(vk::SourceCollections & dst,TestDefinition def)3980 void addShaderCode16BitStorageInputOutput16To16x2 (vk::SourceCollections& dst, TestDefinition def)
3981 {
3982 SpirvVersion targetSpirvVersion = def.instanceContext.resources.spirvVersion;
3983 const deUint32 vulkanVersion = dst.usedVulkanVersion;
3984 map<string, string> spec;
3985
3986 switch(def.dataType)
3987 {
3988 case DATATYPE_FLOAT:
3989 spec["type"] = "f";
3990 spec["convert"] = "OpFConvert";
3991 spec["scale"] = "%x = OpCopyObject %f32 %dataIn0_converted\n%y = OpCopyObject %f32 %dataIn1_converted\n";
3992 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %x %y %c_f32_1 %c_f32_1";
3993 spec["interpolation0"] = spec["interpolation1"] = "";
3994 break;
3995
3996 case DATATYPE_VEC2:
3997 spec["type"] = "v2f";
3998 spec["convert"] = "OpFConvert";
3999 spec["scale"] = "%xy = OpCopyObject %v2f32 %dataIn0_converted\n%zw = OpCopyObject %v2f32 %dataIn1_converted\n";
4000 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %xy %zw";
4001 spec["interpolation0"] = spec["interpolation1"] = "";
4002 break;
4003
4004 case DATATYPE_INT:
4005 spec["type"] = "i";
4006 spec["convert"] = "OpSConvert";
4007 spec["scale"] = "%x_unscaled = OpConvertSToF %f32 %dataIn0_converted\n%x = OpFDiv %f32 %x_unscaled %scale_f32\n%y_unscaled = OpConvertSToF %f32 %dataIn1_converted\n%y = OpFDiv %f32 %y_unscaled %scale_f32\n";
4008 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %x %y %c_f32_1 %c_f32_1";
4009 spec["interpolation0"] = "OpDecorate %dataIn0 Flat";
4010 spec["interpolation1"] = "OpDecorate %dataIn1 Flat";
4011 break;
4012
4013 case DATATYPE_UINT:
4014 spec["type"] = "u";
4015 spec["convert"] = "OpUConvert";
4016 spec["scale"] = "%x_unscaled = OpConvertUToF %f32 %dataIn0_converted\n%x = OpFDiv %f32 %x_unscaled %scale_f32\n%y_unscaled = OpConvertUToF %f32 %dataIn1_converted\n%y = OpFDiv %f32 %y_unscaled %scale_f32\n";
4017 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %x %y %c_f32_1 %c_f32_1";
4018 spec["interpolation0"] = "OpDecorate %dataIn0 Flat";
4019 spec["interpolation1"] = "OpDecorate %dataIn1 Flat";
4020 break;
4021
4022 case DATATYPE_IVEC2:
4023 spec["type"] = "v2i";
4024 spec["convert"] = "OpSConvert";
4025 spec["scale"] = "%xy_unscaled = OpConvertSToF %v2f32 %dataIn0_converted\n%xy = OpFDiv %v2f32 %xy_unscaled %scale_v2f32\n%zw_unscaled = OpConvertSToF %v2f32 %dataIn1_converted\n%zw = OpFDiv %v2f32 %zw_unscaled %scale_v2f32\n";
4026 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %xy %zw";
4027 spec["interpolation0"] = "OpDecorate %dataIn0 Flat";
4028 spec["interpolation1"] = "OpDecorate %dataIn1 Flat";
4029 break;
4030
4031 case DATATYPE_UVEC2:
4032 spec["type"] = "v2u";
4033 spec["convert"] = "OpUConvert";
4034 spec["scale"] = "%xy_unscaled = OpConvertUToF %v2f32 %dataIn0_converted\n%xy = OpFDiv %v2f32 %xy_unscaled %scale_v2f32\n%zw_unscaled = OpConvertUToF %v2f32 %dataIn1_converted\n%zw = OpFDiv %v2f32 %zw_unscaled %scale_v2f32\n";
4035 spec["colorConstruct"] = "OpCompositeConstruct %v4f32 %xy %zw";
4036 spec["interpolation0"] = "OpDecorate %dataIn0 Flat";
4037 spec["interpolation1"] = "OpDecorate %dataIn1 Flat";
4038 break;
4039
4040 default:
4041 DE_FATAL("Unexpected data type");
4042 break;
4043 }
4044
4045 // Read input data from binding 1, location 2. Should have value(s) of 0.5 in 16bit float or 32767 in 16bit int.
4046 // Store the value to two outputs (dataOut0 and 1).
4047 StringTemplate vertexShader (
4048 " OpCapability Shader\n"
4049 " OpCapability StorageInputOutput16\n"
4050 " OpExtension \"SPV_KHR_16bit_storage\"\n"
4051 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
4052 " OpMemoryModel Logical GLSL450\n"
4053 " OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %dataIn %color %dataOut0 %dataOut1\n"
4054 " OpSource GLSL 430\n"
4055 " OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
4056 " OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
4057 " OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
4058 " OpDecorate %gl_PerVertex Block\n"
4059 " OpDecorate %position Location 0\n"
4060 " OpDecorate %vtxColor Location 1\n"
4061 " OpDecorate %dataIn Location 2\n"
4062 " OpDecorate %color Location 1\n"
4063 " OpDecorate %dataOut0 Location 2\n"
4064 " OpDecorate %dataOut1 Location 3\n"
4065 " %void = OpTypeVoid\n"
4066 " %void_func = OpTypeFunction %void\n"
4067 " %f32 = OpTypeFloat 32\n"
4068 " %f16 = OpTypeFloat 16\n"
4069 " %i32 = OpTypeInt 32 1\n"
4070 " %i16 = OpTypeInt 16 1\n"
4071 " %u32 = OpTypeInt 32 0\n"
4072 " %u16 = OpTypeInt 16 0\n"
4073 " %v4f32 = OpTypeVector %f32 4\n"
4074 " %v2f32 = OpTypeVector %f32 2\n"
4075 " %v2f16 = OpTypeVector %f16 2\n"
4076 " %v2i32 = OpTypeVector %i32 2\n"
4077 " %v2i16 = OpTypeVector %i16 2\n"
4078 " %v2u32 = OpTypeVector %u32 2\n"
4079 " %v2u16 = OpTypeVector %u16 2\n"
4080 " %u32_0 = OpConstant %u32 0\n"
4081 " %u32_1 = OpConstant %u32 1\n"
4082 " %_arr_f32_u32_1 = OpTypeArray %f32 %u32_1\n"
4083 " %gl_PerVertex = OpTypeStruct %v4f32 %f32 %_arr_f32_u32_1\n"
4084 " %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
4085 " %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n"
4086 " %_ptr_Output_${type}16 = OpTypePointer Output %${type}16\n"
4087 " %_ptr_Input_${type}16 = OpTypePointer Input %${type}16\n"
4088 " %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n"
4089 " %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
4090 " %dataIn = OpVariable %_ptr_Input_${type}16 Input\n"
4091 " %position = OpVariable %_ptr_Input_v4f32 Input\n"
4092 " %color = OpVariable %_ptr_Input_v4f32 Input\n"
4093 " %vtxColor = OpVariable %_ptr_Output_v4f32 Output\n"
4094 " %dataOut0 = OpVariable %_ptr_Output_${type}16 Output\n"
4095 " %dataOut1 = OpVariable %_ptr_Output_${type}16 Output\n"
4096 " %main = OpFunction %void None %void_func\n"
4097 " %entry = OpLabel\n"
4098 " %posData = OpLoad %v4f32 %position\n"
4099 " %posOutputPtr = OpAccessChain %_ptr_Output_v4f32 %_ %u32_0\n"
4100 " OpStore %posOutputPtr %posData\n"
4101 " %colorData = OpLoad %v4f32 %color\n"
4102 " OpStore %vtxColor %colorData\n"
4103 " %d = OpLoad %${type}16 %dataIn\n"
4104 " OpStore %dataOut0 %d\n"
4105 " OpStore %dataOut1 %d\n"
4106 " OpReturn\n"
4107 " OpFunctionEnd\n");
4108
4109 // Scalar:
4110 // Read two 16bit values from vertex shader. Convert to 32bit and store as
4111 // fragment color of (val0, val1, 1.0, 1.0). Val0 and 1 should equal to 0.5.
4112 // Vector:
4113 // Read two 16bit vec2s from vertex shader. Convert to 32bit and store as
4114 // fragment color of (val0.x, val0.y, val1.x, val1.y). Val0 and 1 should equal to (0.5, 0.5).
4115 StringTemplate fragmentShader (
4116 " OpCapability Shader\n"
4117 " OpCapability StorageInputOutput16\n"
4118 " OpExtension \"SPV_KHR_16bit_storage\"\n"
4119 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
4120 " OpMemoryModel Logical GLSL450\n"
4121 " OpEntryPoint Fragment %main \"main\" %fragColor %dataOut %vtxColor %dataIn0 %dataIn1\n"
4122 " OpExecutionMode %main OriginUpperLeft\n"
4123 " OpSource GLSL 430\n"
4124 " OpDecorate %vtxColor Location 1\n"
4125 " OpDecorate %dataIn0 Location 2\n"
4126 " OpDecorate %dataIn1 Location 3\n"
4127 " ${interpolation0}\n"
4128 " ${interpolation1}\n"
4129 " OpDecorate %fragColor Location 0\n"
4130 " OpDecorate %dataOut Location 1\n"
4131 " %void = OpTypeVoid\n"
4132 " %void_func = OpTypeFunction %void\n"
4133 " %f32 = OpTypeFloat 32\n"
4134 " %f16 = OpTypeFloat 16\n"
4135 " %i32 = OpTypeInt 32 1\n"
4136 " %i16 = OpTypeInt 16 1\n"
4137 " %u32 = OpTypeInt 32 0\n"
4138 " %u16 = OpTypeInt 16 0\n"
4139 " %v2f32 = OpTypeVector %f32 2\n"
4140 " %v2f16 = OpTypeVector %f16 2\n"
4141 " %v4f32 = OpTypeVector %f32 4\n"
4142 " %v2i32 = OpTypeVector %i32 2\n"
4143 " %v2i16 = OpTypeVector %i16 2\n"
4144 " %v2u32 = OpTypeVector %u32 2\n"
4145 " %v2u16 = OpTypeVector %u16 2\n"
4146 " %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n"
4147 " %_ptr_Output_${type}16 = OpTypePointer Output %${type}16\n"
4148 " %fragColor = OpVariable %_ptr_Output_v4f32 Output\n"
4149 " %dataOut = OpVariable %_ptr_Output_${type}16 Output\n"
4150 " %_ptr_Input_${type}16 = OpTypePointer Input %${type}16\n"
4151 " %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n"
4152 " %vtxColor = OpVariable %_ptr_Input_v4f32 Input\n"
4153 " %dataIn0 = OpVariable %_ptr_Input_${type}16 Input\n"
4154 " %dataIn1 = OpVariable %_ptr_Input_${type}16 Input\n"
4155 " %c_f32_1 = OpConstant %f32 1\n"
4156 " %scale_f32 = OpConstant %f32 65534.0\n"
4157 " %scale_v2f32 = OpConstantComposite %v2f32 %scale_f32 %scale_f32\n"
4158 " %main = OpFunction %void None %void_func\n"
4159 " %entry = OpLabel\n"
4160 " %dataIn0_val = OpLoad %${type}16 %dataIn0\n"
4161 " %dataIn1_val = OpLoad %${type}16 %dataIn1\n"
4162 " %dataIn0_converted = ${convert} %${type}32 %dataIn0_val\n"
4163 " %dataIn1_converted = ${convert} %${type}32 %dataIn1_val\n"
4164 "${scale}"
4165 " %color = ${colorConstruct}\n"
4166 " OpStore %fragColor %color\n"
4167 " OpStore %dataOut %dataIn0_val\n"
4168 " OpReturn\n"
4169 " OpFunctionEnd\n");
4170
4171 dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
4172 dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
4173 }
4174
runAndVerifyDefaultPipeline(Context & context,TestDefinition testDef)4175 TestStatus runAndVerifyDefaultPipeline (Context& context, TestDefinition testDef)
4176 {
4177 return runAndVerifyDefaultPipeline (context, testDef.instanceContext);
4178 }
4179
addGraphics16BitStorageInputOutputFloat16To16x2Group(tcu::TestCaseGroup * testGroup)4180 void addGraphics16BitStorageInputOutputFloat16To16x2Group (tcu::TestCaseGroup* testGroup)
4181 {
4182 RGBA defaultColors[4];
4183 SpecConstants noSpecConstants;
4184 PushConstants noPushConstants;
4185 vector<string> extensions;
4186 map<string, string> noFragments;
4187 GraphicsResources noResources;
4188 StageToSpecConstantMap specConstantMap;
4189 VulkanFeatures requiredFeatures;
4190
4191 const ShaderElement pipelineStages[] =
4192 {
4193 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
4194 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
4195 };
4196
4197 specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = noSpecConstants;
4198 specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = noSpecConstants;
4199
4200 getDefaultColors(defaultColors);
4201
4202 extensions.push_back("VK_KHR_16bit_storage");
4203 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4204
4205 const struct
4206 {
4207 string name;
4208 deUint32 numElements;
4209 TestDefDataType dataType;
4210 NumberType numberType;
4211 bool isVector;
4212 } cases[] =
4213 {
4214 { "scalar", 1, DATATYPE_FLOAT, NUMBERTYPE_FLOAT16, false },
4215 { "vec2", 2, DATATYPE_VEC2, NUMBERTYPE_FLOAT16, true },
4216 };
4217
4218 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4219 {
4220 const RGBA outColor (128u, 128u, cases[caseIdx].isVector ? 128u : 255u, cases[caseIdx].isVector ? 128u : 255u);
4221 RGBA outputColors[4] = {outColor, outColor, outColor, outColor};
4222 vector<deFloat16> float16Data (4 * cases[caseIdx].numElements, deFloat32To16(0.5f));
4223 GraphicsInterfaces interfaces;
4224
4225 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Float16Buffer(float16Data))),
4226 std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Float16Buffer(float16Data))));
4227
4228 const InstanceContext& instanceContext = createInstanceContext(pipelineStages,
4229 defaultColors,
4230 outputColors,
4231 noFragments,
4232 specConstantMap,
4233 noPushConstants,
4234 noResources,
4235 interfaces,
4236 extensions,
4237 requiredFeatures,
4238 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
4239 QP_TEST_RESULT_FAIL,
4240 string());
4241
4242 TestDefinition testDef = {instanceContext, cases[caseIdx].dataType};
4243
4244 addFunctionCaseWithPrograms<TestDefinition>(testGroup,
4245 cases[caseIdx].name,
4246 "",
4247 addShaderCode16BitStorageInputOutput16To16x2,
4248 runAndVerifyDefaultPipeline,
4249 testDef);
4250 }
4251 }
4252
addGraphics16BitStorageInputOutputInt16To16x2Group(tcu::TestCaseGroup * testGroup)4253 void addGraphics16BitStorageInputOutputInt16To16x2Group (tcu::TestCaseGroup* testGroup)
4254 {
4255 map<string, string> fragments;
4256 RGBA defaultColors[4];
4257 SpecConstants noSpecConstants;
4258 PushConstants noPushConstants;
4259 vector<string> extensions;
4260 GraphicsResources noResources;
4261 StageToSpecConstantMap specConstantMap;
4262 VulkanFeatures requiredFeatures;
4263
4264 const ShaderElement pipelineStages[] =
4265 {
4266 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
4267 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
4268 };
4269
4270 specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = noSpecConstants;
4271 specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = noSpecConstants;
4272
4273 getDefaultColors(defaultColors);
4274
4275 extensions.push_back("VK_KHR_16bit_storage");
4276 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4277 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4278
4279 const struct
4280 {
4281 string name;
4282 deUint32 numElements;
4283 TestDefDataType dataType;
4284 NumberType numberType;
4285 bool isVector;
4286 } cases[] =
4287 {
4288 { "scalar_int", 1, DATATYPE_INT, NUMBERTYPE_INT16, false },
4289 { "scalar_uint", 1, DATATYPE_UINT, NUMBERTYPE_UINT16, false },
4290 { "ivec2", 2, DATATYPE_IVEC2, NUMBERTYPE_INT16, true },
4291 { "uvec2", 2, DATATYPE_UVEC2, NUMBERTYPE_UINT16, true }
4292 };
4293
4294 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4295 {
4296 const RGBA outColor (128u, 128u, cases[caseIdx].isVector ? 128u : 255u, cases[caseIdx].isVector ? 128u : 255u);
4297 RGBA outputColors[4] = {outColor, outColor, outColor, outColor};
4298 vector<deInt16> int16Data (4 * cases[caseIdx].numElements, 32767);
4299 GraphicsInterfaces interfaces;
4300
4301 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Int16Buffer(int16Data))),
4302 std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Int16Buffer(int16Data))));
4303
4304 const InstanceContext& instanceContext = createInstanceContext(pipelineStages,
4305 defaultColors,
4306 outputColors,
4307 fragments,
4308 specConstantMap,
4309 noPushConstants,
4310 noResources,
4311 interfaces,
4312 extensions,
4313 requiredFeatures,
4314 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
4315 QP_TEST_RESULT_FAIL,
4316 string());
4317
4318 TestDefinition testDef = {instanceContext, cases[caseIdx].dataType};
4319
4320 addFunctionCaseWithPrograms<TestDefinition>(testGroup,
4321 cases[caseIdx].name,
4322 "",
4323 addShaderCode16BitStorageInputOutput16To16x2,
4324 runAndVerifyDefaultPipeline,
4325 testDef);
4326 }
4327 }
4328
addGraphics16BitStorageInputOutputInt32To16Group(tcu::TestCaseGroup * testGroup)4329 void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testGroup)
4330 {
4331 de::Random rnd (deStringHash(testGroup->getName()));
4332 RGBA defaultColors[4];
4333 vector<string> extensions;
4334 map<string, string> fragments = passthruFragments();
4335 const deUint32 numDataPoints = 64;
4336 // inputs and outputs are declared to be vectors of signed integers.
4337 // However, depending on the test, they may be interpreted as unsiged
4338 // integers. That won't be a problem as long as we passed the bits
4339 // in faithfully to the pipeline.
4340 vector<deInt32> inputs = getInt32s(rnd, numDataPoints);
4341 vector<deInt16> outputs;
4342
4343 outputs.reserve(inputs.size());
4344 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4345 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx]));
4346
4347 extensions.push_back("VK_KHR_16bit_storage");
4348
4349 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4350 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4351
4352 getDefaultColors(defaultColors);
4353
4354 const StringTemplate scalarInterfaceOpCall(
4355 "${convert} %${type16}");
4356
4357 const StringTemplate scalarInterfaceOpFunc("");
4358
4359 const StringTemplate scalarPreMain(
4360 " %${type16} = OpTypeInt 16 ${signed}\n"
4361 " %op_${type16} = OpTypePointer Output %${type16}\n"
4362 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4363 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4364 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4365 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4366 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4367
4368 const StringTemplate vecInterfaceOpCall(
4369 "${convert} %${type16}");
4370
4371 const StringTemplate vecInterfaceOpFunc("");
4372
4373 const StringTemplate vecPreMain(
4374 " %i16 = OpTypeInt 16 1\n"
4375 " %u16 = OpTypeInt 16 0\n"
4376 " %v4i16 = OpTypeVector %i16 4\n"
4377 " %v4u16 = OpTypeVector %u16 4\n"
4378 " %op_${type16} = OpTypePointer Output %${type16}\n"
4379 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4380 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4381 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4382 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4383 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4384
4385 struct Case
4386 {
4387 const char* name;
4388 const StringTemplate& interfaceOpCall;
4389 const StringTemplate& interfaceOpFunc;
4390 const StringTemplate& preMain;
4391 const char* type32;
4392 const char* type16;
4393 const char* sign;
4394 const char* opcode;
4395 deUint32 numPerCase;
4396 deUint32 numElements;
4397 };
4398
4399 Case cases[] =
4400 {
4401 {"scalar_sint", scalarInterfaceOpCall, scalarInterfaceOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1},
4402 {"scalar_uint", scalarInterfaceOpCall, scalarInterfaceOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1},
4403 {"vector_sint", vecInterfaceOpCall, vecInterfaceOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4},
4404 {"vector_uint", vecInterfaceOpCall, vecInterfaceOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4},
4405 };
4406
4407 VulkanFeatures requiredFeatures;
4408 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4409 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4410
4411 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4412 {
4413 map<string, string> specs;
4414
4415 specs["type32"] = cases[caseIdx].type32;
4416 specs["type16"] = cases[caseIdx].type16;
4417 specs["signed"] = cases[caseIdx].sign;
4418 specs["convert"] = cases[caseIdx].opcode;
4419
4420 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4421 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4422 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4423 fragments["input_type"] = cases[caseIdx].type32;
4424 fragments["output_type"] = cases[caseIdx].type16;
4425
4426 GraphicsInterfaces interfaces;
4427 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4428 vector<deInt32> subInputs (numPerCase);
4429 vector<deInt16> subOutputs (numPerCase);
4430
4431 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4432 {
4433 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4434
4435 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4436 {
4437 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4438 subOutputs[numNdx] = outputs[caseNdx * numPerCase + numNdx];
4439 }
4440 if (strcmp(cases[caseIdx].sign, "1") == 0)
4441 {
4442 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subInputs))),
4443 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subOutputs))));
4444 }
4445 else
4446 {
4447 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subInputs))),
4448 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subOutputs))));
4449 }
4450 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4451 }
4452 }
4453 }
4454
addGraphics16BitStorageInputOutputInt16To32Group(tcu::TestCaseGroup * testGroup)4455 void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testGroup)
4456 {
4457 de::Random rnd (deStringHash(testGroup->getName()));
4458 RGBA defaultColors[4];
4459 vector<string> extensions;
4460 map<string, string> fragments = passthruFragments();
4461 const deUint32 numDataPoints = 64;
4462 // inputs and outputs are declared to be vectors of signed integers.
4463 // However, depending on the test, they may be interpreted as unsiged
4464 // integers. That won't be a problem as long as we passed the bits
4465 // in faithfully to the pipeline.
4466 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
4467 vector<deInt32> sOutputs;
4468 vector<deInt32> uOutputs;
4469 const deUint16 signBitMask = 0x8000;
4470 const deUint32 signExtendMask = 0xffff0000;
4471
4472 sOutputs.reserve(inputs.size());
4473 uOutputs.reserve(inputs.size());
4474
4475 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4476 {
4477 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
4478 if (inputs[numNdx] & signBitMask)
4479 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
4480 else
4481 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
4482 }
4483
4484 extensions.push_back("VK_KHR_16bit_storage");
4485
4486 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4487 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4488
4489 getDefaultColors(defaultColors);
4490
4491 const StringTemplate scalarIfOpCall (
4492 "${convert} %${type32}");
4493
4494 const StringTemplate scalarIfOpFunc ("");
4495
4496 const StringTemplate scalarPreMain (
4497 " %${type16} = OpTypeInt 16 ${signed}\n"
4498 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4499 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4500 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4501 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4502 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4503 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4504
4505 const StringTemplate vecIfOpCall (
4506 "${convert} %${type32}");
4507
4508 const StringTemplate vecIfOpFunc ("");
4509
4510 const StringTemplate vecPreMain (
4511 " %i16 = OpTypeInt 16 1\n"
4512 " %u16 = OpTypeInt 16 0\n"
4513 " %v4i16 = OpTypeVector %i16 4\n"
4514 " %v4u16 = OpTypeVector %u16 4\n"
4515 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4516 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4517 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4518 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4519 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4520 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4521
4522 struct Case
4523 {
4524 const char* name;
4525 const StringTemplate& interfaceOpCall;
4526 const StringTemplate& interfaceOpFunc;
4527 const StringTemplate& preMain;
4528 const char* type32;
4529 const char* type16;
4530 const char* sign;
4531 const char* opcode;
4532 deUint32 numPerCase;
4533 deUint32 numElements;
4534 };
4535
4536 Case cases[] =
4537 {
4538 {"scalar_sint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1},
4539 {"scalar_uint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1},
4540 {"vector_sint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4},
4541 {"vector_uint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4},
4542 };
4543
4544 VulkanFeatures requiredFeatures;
4545 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4546 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4547
4548 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4549 {
4550 map<string, string> specs;
4551
4552 specs["type32"] = cases[caseIdx].type32;
4553 specs["type16"] = cases[caseIdx].type16;
4554 specs["signed"] = cases[caseIdx].sign;
4555 specs["convert"] = cases[caseIdx].opcode;
4556
4557 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4558 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4559 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4560 fragments["input_type"] = cases[caseIdx].type16;
4561 fragments["output_type"] = cases[caseIdx].type32;
4562
4563 GraphicsInterfaces interfaces;
4564 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4565 vector<deInt16> subInputs (numPerCase);
4566 vector<deInt32> subOutputs (numPerCase);
4567
4568 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4569 {
4570 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4571
4572 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4573 {
4574 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4575 if (cases[caseIdx].sign[0] == '1')
4576 subOutputs[numNdx] = sOutputs[caseNdx * numPerCase + numNdx];
4577 else
4578 subOutputs[numNdx] = uOutputs[caseNdx * numPerCase + numNdx];
4579 }
4580 if (strcmp(cases[caseIdx].sign, "1") == 0)
4581 {
4582 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subInputs))),
4583 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subOutputs))));
4584 }
4585 else
4586 {
4587 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subInputs))),
4588 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subOutputs))));
4589 }
4590 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4591 }
4592 }
4593 }
4594
addGraphics16BitStorageInputOutputInt16To16Group(tcu::TestCaseGroup * testGroup)4595 void addGraphics16BitStorageInputOutputInt16To16Group (tcu::TestCaseGroup* testGroup)
4596 {
4597 de::Random rnd (deStringHash(testGroup->getName()));
4598 RGBA defaultColors[4];
4599 vector<string> extensions;
4600 map<string, string> fragments = passthruFragments();
4601 const deUint32 numDataPoints = 64;
4602 // inputs and outputs are declared to be vectors of signed integers.
4603 // However, depending on the test, they may be interpreted as unsiged
4604 // integers. That won't be a problem as long as we passed the bits
4605 // in faithfully to the pipeline.
4606 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
4607 VulkanFeatures requiredFeatures;
4608
4609 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4610 extensions.push_back("VK_KHR_16bit_storage");
4611
4612 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4613 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4614
4615 getDefaultColors(defaultColors);
4616
4617 const StringTemplate scalarIfOpCall (
4618 "OpCopyObject %${type16}");
4619
4620 const StringTemplate scalarIfOpFunc ("");
4621
4622 const StringTemplate scalarPreMain (
4623 " %${type16} = OpTypeInt 16 ${signed}\n"
4624 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4625 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4626 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4627 "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4628 " %op_${type16} = OpTypePointer Output %${type16}\n"
4629 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4630
4631 const StringTemplate vecIfOpCall (
4632 "OpCopyObject %${type16}");
4633
4634 const StringTemplate vecIfOpFunc ("");
4635
4636 const StringTemplate vecPreMain (
4637 " %i16 = OpTypeInt 16 1\n"
4638 " %u16 = OpTypeInt 16 0\n"
4639 " %v4i16 = OpTypeVector %i16 4\n"
4640 " %v4u16 = OpTypeVector %u16 4\n"
4641 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4642 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4643 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4644 "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4645 " %op_${type16} = OpTypePointer Output %${type16}\n"
4646 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4647
4648 struct Case
4649 {
4650 const char* name;
4651 const StringTemplate& interfaceOpCall;
4652 const StringTemplate& interfaceOpFunc;
4653 const StringTemplate& preMain;
4654 const char* type16;
4655 const char* sign;
4656 deUint32 numPerCase;
4657 deUint32 numElements;
4658 };
4659
4660 Case cases[] =
4661 {
4662 {"scalar_sint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "i16", "1", 4, 1},
4663 {"scalar_uint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "u16", "0", 4, 1},
4664 {"vector_sint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4i16", "1", 4 * 4, 4},
4665 {"vector_uint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4u16", "0", 4 * 4, 4},
4666 };
4667
4668 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4669 {
4670 map<string, string> specs;
4671
4672 specs["type16"] = cases[caseIdx].type16;
4673 specs["signed"] = cases[caseIdx].sign;
4674
4675 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4676 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4677 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4678 fragments["input_type"] = cases[caseIdx].type16;
4679 fragments["output_type"] = cases[caseIdx].type16;
4680
4681 GraphicsInterfaces interfaces;
4682 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4683 vector<deInt16> subInputsOutputs (numPerCase);
4684 const NumberType numberType = strcmp(cases[caseIdx].sign, "1") == 0 ? NUMBERTYPE_INT16 : NUMBERTYPE_UINT16;
4685
4686 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4687 {
4688 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4689
4690 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4691 subInputsOutputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4692
4693 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))),
4694 std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))));
4695
4696 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4697 }
4698 }
4699 }
4700
addGraphics16BitStoragePushConstantFloat16To32Group(tcu::TestCaseGroup * testGroup)4701 void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* testGroup)
4702 {
4703 de::Random rnd (deStringHash(testGroup->getName()));
4704 map<string, string> fragments;
4705 RGBA defaultColors[4];
4706 vector<string> extensions;
4707 GraphicsResources resources;
4708 PushConstants pcs;
4709 const deUint32 numDataPoints = 64;
4710 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
4711 vector<float> float32Data;
4712 VulkanFeatures requiredFeatures;
4713
4714 struct ConstantIndex
4715 {
4716 bool useConstantIndex;
4717 deUint32 constantIndex;
4718 };
4719
4720 ConstantIndex constantIndices[] =
4721 {
4722 { false, 0 },
4723 { true, 4 },
4724 { true, 5 },
4725 { true, 6 }
4726 };
4727
4728 float32Data.reserve(numDataPoints);
4729 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4730 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
4731
4732 extensions.push_back("VK_KHR_16bit_storage");
4733
4734 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
4735 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
4736 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
4737
4738 fragments["capability"] = "OpCapability StoragePushConstant16\n";
4739 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
4740
4741 pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data)));
4742 resources.verifyIO = check32BitFloats;
4743
4744 getDefaultColors(defaultColors);
4745
4746 const StringTemplate testFun (
4747 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
4748 " %param = OpFunctionParameter %v4f32\n"
4749
4750 "%entry = OpLabel\n"
4751 " %i = OpVariable %fp_i32 Function\n"
4752 " OpStore %i %c_i32_0\n"
4753 " OpBranch %loop\n"
4754
4755 " %loop = OpLabel\n"
4756 " %15 = OpLoad %i32 %i\n"
4757 " %lt = OpSLessThan %bool %15 ${count}\n"
4758 " OpLoopMerge %merge %inc None\n"
4759 " OpBranchConditional %lt %write %merge\n"
4760
4761 "%write = OpLabel\n"
4762 " %30 = OpLoad %i32 %i\n"
4763 " %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %${arrayindex} ${index0:opt}\n"
4764 "%val16 = OpLoad ${f_type16} %src\n"
4765 "%val32 = OpFConvert ${f_type32} %val16\n"
4766 " %dst = OpAccessChain ${up_type32} %ssbo32 %c_i32_0 %30 ${index0:opt}\n"
4767 " OpStore %dst %val32\n"
4768
4769 "${store:opt}\n"
4770
4771 " OpBranch %inc\n"
4772
4773 " %inc = OpLabel\n"
4774 " %37 = OpLoad %i32 %i\n"
4775 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
4776 " OpStore %i %39\n"
4777 " OpBranch %loop\n"
4778
4779 "%merge = OpLabel\n"
4780 " OpReturnValue %param\n"
4781
4782 "OpFunctionEnd\n");
4783
4784 { // Scalar cases
4785 const StringTemplate preMain (
4786 " %f16 = OpTypeFloat 16\n"
4787 " %c_i32_64 = OpConstant %i32 64\n"
4788 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4789 " %a64f16 = OpTypeArray %f16 %c_i32_64\n"
4790 " %a64f32 = OpTypeArray %f32 %c_i32_64\n"
4791 " %pp_f16 = OpTypePointer PushConstant %f16\n"
4792 " %up_f32 = OpTypePointer Uniform %f32\n"
4793 " %SSBO32 = OpTypeStruct %a64f32\n"
4794 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4795 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4796 " %PC16 = OpTypeStruct %a64f16\n"
4797 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4798 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4799
4800 fragments["decoration"] =
4801 "OpDecorate %a64f16 ArrayStride 2\n"
4802 "OpDecorate %a64f32 ArrayStride 4\n"
4803 "OpDecorate %SSBO32 BufferBlock\n"
4804 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4805 "OpDecorate %PC16 Block\n"
4806 "OpMemberDecorate %PC16 0 Offset 0\n"
4807 "OpDecorate %ssbo32 DescriptorSet 0\n"
4808 "OpDecorate %ssbo32 Binding 0\n";
4809
4810 map<string, string> specs;
4811
4812 specs["count"] = "%c_i32_64";
4813 specs["pp_type16"] = "%pp_f16";
4814 specs["f_type16"] = "%f16";
4815 specs["f_type32"] = "%f32";
4816 specs["up_type32"] = "%up_f32";
4817
4818 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4819 {
4820 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4821 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4822 string testName = "scalar";
4823 vector<float> float32ConstIdxData;
4824
4825 if (useConstIdx)
4826 {
4827 float32ConstIdxData.reserve(numDataPoints);
4828
4829 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4830 float32ConstIdxData.push_back(float32Data[constIdx]);
4831 }
4832
4833 specs["constarrayidx"] = de::toString(constIdx);
4834 if (useConstIdx)
4835 specs["arrayindex"] = "c_i32_ci";
4836 else
4837 specs["arrayindex"] = "30";
4838
4839 resources.outputs.clear();
4840 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4841
4842 fragments["pre_main"] = preMain.specialize(specs);
4843 fragments["testfun"] = testFun.specialize(specs);
4844
4845 if (useConstIdx)
4846 testName += string("_const_idx_") + de::toString(constIdx);
4847
4848 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4849 }
4850 }
4851
4852 { // Vector cases
4853 const StringTemplate preMain (
4854 " %f16 = OpTypeFloat 16\n"
4855 " %v4f16 = OpTypeVector %f16 4\n"
4856 " %c_i32_16 = OpConstant %i32 16\n"
4857 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4858 " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n"
4859 " %a16v4f32 = OpTypeArray %v4f32 %c_i32_16\n"
4860 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
4861 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
4862 " %SSBO32 = OpTypeStruct %a16v4f32\n"
4863 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4864 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4865 " %PC16 = OpTypeStruct %a16v4f16\n"
4866 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4867 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4868
4869 fragments["decoration"] =
4870 "OpDecorate %a16v4f16 ArrayStride 8\n"
4871 "OpDecorate %a16v4f32 ArrayStride 16\n"
4872 "OpDecorate %SSBO32 BufferBlock\n"
4873 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4874 "OpDecorate %PC16 Block\n"
4875 "OpMemberDecorate %PC16 0 Offset 0\n"
4876 "OpDecorate %ssbo32 DescriptorSet 0\n"
4877 "OpDecorate %ssbo32 Binding 0\n";
4878
4879 map<string, string> specs;
4880
4881 specs["count"] = "%c_i32_16";
4882 specs["pp_type16"] = "%pp_v4f16";
4883 specs["f_type16"] = "%v4f16";
4884 specs["f_type32"] = "%v4f32";
4885 specs["up_type32"] = "%up_v4f32";
4886
4887 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4888 {
4889 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4890 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4891 string testName = "vector";
4892 vector<float> float32ConstIdxData;
4893
4894 if (useConstIdx)
4895 {
4896 float32ConstIdxData.reserve(numDataPoints);
4897
4898 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4899 float32ConstIdxData.push_back(float32Data[constIdx * 4 + numIdx % 4]);
4900 }
4901
4902 specs["constarrayidx"] = de::toString(constIdx);
4903 if (useConstIdx)
4904 specs["arrayindex"] = "c_i32_ci";
4905 else
4906 specs["arrayindex"] = "30";
4907
4908 resources.outputs.clear();
4909 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4910
4911 fragments["pre_main"] = preMain.specialize(specs);
4912 fragments["testfun"] = testFun.specialize(specs);
4913
4914 if (useConstIdx)
4915 testName += string("_const_idx_") + de::toString(constIdx);
4916
4917 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4918 }
4919 }
4920
4921 { // Matrix cases
4922 const StringTemplate preMain (
4923 " %c_i32_8 = OpConstant %i32 8\n"
4924 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4925 " %f16 = OpTypeFloat 16\n"
4926 " %v4f16 = OpTypeVector %f16 4\n"
4927 " %m2v4f16 = OpTypeMatrix %v4f16 2\n"
4928 " %m2v4f32 = OpTypeMatrix %v4f32 2\n"
4929 " %a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n"
4930 " %a8m2v4f32 = OpTypeArray %m2v4f32 %c_i32_8\n"
4931 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
4932 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
4933 " %SSBO32 = OpTypeStruct %a8m2v4f32\n"
4934 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4935 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4936 " %PC16 = OpTypeStruct %a8m2v4f16\n"
4937 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4938 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4939
4940 fragments["decoration"] =
4941 "OpDecorate %a8m2v4f16 ArrayStride 16\n"
4942 "OpDecorate %a8m2v4f32 ArrayStride 32\n"
4943 "OpDecorate %SSBO32 BufferBlock\n"
4944 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4945 "OpMemberDecorate %SSBO32 0 ColMajor\n"
4946 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
4947 "OpDecorate %PC16 Block\n"
4948 "OpMemberDecorate %PC16 0 Offset 0\n"
4949 "OpMemberDecorate %PC16 0 ColMajor\n"
4950 "OpMemberDecorate %PC16 0 MatrixStride 8\n"
4951 "OpDecorate %ssbo32 DescriptorSet 0\n"
4952 "OpDecorate %ssbo32 Binding 0\n";
4953
4954 map<string, string> specs;
4955
4956 specs["count"] = "%c_i32_8";
4957 specs["pp_type16"] = "%pp_v4f16";
4958 specs["up_type32"] = "%up_v4f32";
4959 specs["f_type16"] = "%v4f16";
4960 specs["f_type32"] = "%v4f32";
4961 specs["index0"] = "%c_i32_0";
4962
4963 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4964 {
4965 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4966 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4967 string testName = "matrix";
4968 vector<float> float32ConstIdxData;
4969 const StringTemplate store (
4970 " %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %${arrayindex} %c_i32_1\n"
4971 "%val16_1 = OpLoad %v4f16 %src_1\n"
4972 "%val32_1 = OpFConvert %v4f32 %val16_1\n"
4973 " %dst_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
4974 " OpStore %dst_1 %val32_1\n");
4975
4976 if (useConstIdx)
4977 {
4978 float32ConstIdxData.reserve(numDataPoints);
4979
4980 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4981 float32ConstIdxData.push_back(float32Data[constIdx * 8 + numIdx % 8]);
4982 }
4983
4984 specs["constarrayidx"] = de::toString(constIdx);
4985 if (useConstIdx)
4986 specs["arrayindex"] = "c_i32_ci";
4987 else
4988 specs["arrayindex"] = "30";
4989
4990 specs["store"] = store.specialize(specs);
4991
4992 resources.outputs.clear();
4993 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4994
4995 fragments["pre_main"] = preMain.specialize(specs);
4996 fragments["testfun"] = testFun.specialize(specs);
4997
4998 if (useConstIdx)
4999 testName += string("_const_idx_") + de::toString(constIdx);
5000
5001 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5002 }
5003 }
5004 }
5005
addGraphics16BitStoragePushConstantInt16To32Group(tcu::TestCaseGroup * testGroup)5006 void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* testGroup)
5007 {
5008 de::Random rnd (deStringHash(testGroup->getName()));
5009 map<string, string> fragments;
5010 RGBA defaultColors[4];
5011 const deUint32 numDataPoints = 64;
5012 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
5013 vector<deInt32> sOutputs;
5014 vector<deInt32> uOutputs;
5015 PushConstants pcs;
5016 GraphicsResources resources;
5017 vector<string> extensions;
5018 const deUint16 signBitMask = 0x8000;
5019 const deUint32 signExtendMask = 0xffff0000;
5020 VulkanFeatures requiredFeatures;
5021
5022 struct ConstantIndex
5023 {
5024 bool useConstantIndex;
5025 deUint32 constantIndex;
5026 };
5027
5028 ConstantIndex constantIndices[] =
5029 {
5030 { false, 0 },
5031 { true, 4 },
5032 { true, 5 },
5033 { true, 6 }
5034 };
5035
5036 sOutputs.reserve(inputs.size());
5037 uOutputs.reserve(inputs.size());
5038
5039 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
5040 {
5041 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
5042 if (inputs[numNdx] & signBitMask)
5043 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
5044 else
5045 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
5046 }
5047
5048 extensions.push_back("VK_KHR_16bit_storage");
5049
5050 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
5051 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
5052 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
5053
5054 fragments["capability"] = "OpCapability StoragePushConstant16\n";
5055 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5056
5057 pcs.setPushConstant(BufferSp(new Int16Buffer(inputs)));
5058
5059 getDefaultColors(defaultColors);
5060
5061 const StringTemplate testFun (
5062 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5063 " %param = OpFunctionParameter %v4f32\n"
5064
5065 "%entry = OpLabel\n"
5066 " %i = OpVariable %fp_i32 Function\n"
5067 " OpStore %i %c_i32_0\n"
5068 " OpBranch %loop\n"
5069
5070 " %loop = OpLabel\n"
5071 " %15 = OpLoad %i32 %i\n"
5072 " %lt = OpSLessThan %bool %15 %c_i32_${count}\n"
5073 " OpLoopMerge %merge %inc None\n"
5074 " OpBranchConditional %lt %write %merge\n"
5075
5076 "%write = OpLabel\n"
5077 " %30 = OpLoad %i32 %i\n"
5078 " %src = OpAccessChain %pp_${type16} %pc16 %c_i32_0 %${arrayindex}\n"
5079 "%val16 = OpLoad %${type16} %src\n"
5080 "%val32 = ${convert} %${type32} %val16\n"
5081 " %dst = OpAccessChain %up_${type32} %ssbo32 %c_i32_0 %30\n"
5082 " OpStore %dst %val32\n"
5083 " OpBranch %inc\n"
5084
5085 " %inc = OpLabel\n"
5086 " %37 = OpLoad %i32 %i\n"
5087 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5088 " OpStore %i %39\n"
5089 " OpBranch %loop\n"
5090
5091 "%merge = OpLabel\n"
5092 " OpReturnValue %param\n"
5093
5094 "OpFunctionEnd\n");
5095
5096 { // Scalar cases
5097 const StringTemplate preMain (
5098 " %${type16} = OpTypeInt 16 ${signed}\n"
5099 " %c_i32_${count} = OpConstant %i32 ${count}\n" // Should be the same as numDataPoints
5100 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5101 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
5102 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
5103 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
5104 " %up_${type32} = OpTypePointer Uniform %${type32}\n"
5105 " %SSBO32 = OpTypeStruct %a${count}${type32}\n"
5106 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5107 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5108 " %PC16 = OpTypeStruct %a${count}${type16}\n"
5109 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
5110 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
5111
5112 const StringTemplate decoration (
5113 "OpDecorate %a${count}${type16} ArrayStride 2\n"
5114 "OpDecorate %a${count}${type32} ArrayStride 4\n"
5115 "OpDecorate %SSBO32 BufferBlock\n"
5116 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5117 "OpDecorate %PC16 Block\n"
5118 "OpMemberDecorate %PC16 0 Offset 0\n"
5119 "OpDecorate %ssbo32 DescriptorSet 0\n"
5120 "OpDecorate %ssbo32 Binding 0\n");
5121
5122 { // signed int
5123 map<string, string> specs;
5124
5125 specs["type16"] = "i16";
5126 specs["type32"] = "i32";
5127 specs["signed"] = "1";
5128 specs["count"] = "64";
5129 specs["convert"] = "OpSConvert";
5130
5131 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5132 {
5133 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5134 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5135 string testName = "sint_scalar";
5136 vector<deInt32> constIdxData;
5137
5138 if (useConstIdx)
5139 {
5140 constIdxData.reserve(numDataPoints);
5141
5142 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5143 constIdxData.push_back(sOutputs[constIdx]);
5144 }
5145
5146 specs["constarrayidx"] = de::toString(constIdx);
5147 if (useConstIdx)
5148 specs["arrayindex"] = "c_i32_ci";
5149 else
5150 specs["arrayindex"] = "30";
5151
5152 if (useConstIdx)
5153 testName += string("_const_idx_") + de::toString(constIdx);
5154
5155 resources.outputs.clear();
5156 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5157
5158 fragments["testfun"] = testFun.specialize(specs);
5159 fragments["pre_main"] = preMain.specialize(specs);
5160 fragments["decoration"] = decoration.specialize(specs);
5161
5162 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5163 }
5164 }
5165 { // unsigned int
5166 map<string, string> specs;
5167
5168 specs["type16"] = "u16";
5169 specs["type32"] = "u32";
5170 specs["signed"] = "0";
5171 specs["count"] = "64";
5172 specs["convert"] = "OpUConvert";
5173
5174 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5175 {
5176 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5177 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5178 string testName = "uint_scalar";
5179 vector<deInt32> constIdxData;
5180
5181 if (useConstIdx)
5182 {
5183 constIdxData.reserve(numDataPoints);
5184
5185 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5186 constIdxData.push_back(uOutputs[constIdx]);
5187 }
5188
5189 specs["constarrayidx"] = de::toString(constIdx);
5190 if (useConstIdx)
5191 specs["arrayindex"] = "c_i32_ci";
5192 else
5193 specs["arrayindex"] = "30";
5194
5195 if (useConstIdx)
5196 testName += string("_const_idx_") + de::toString(constIdx);
5197
5198 resources.outputs.clear();
5199 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5200
5201 fragments["testfun"] = testFun.specialize(specs);
5202 fragments["pre_main"] = preMain.specialize(specs);
5203 fragments["decoration"] = decoration.specialize(specs);
5204
5205 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5206 }
5207 }
5208 }
5209
5210 { // Vector cases
5211 const StringTemplate preMain (
5212 " %${base_type16} = OpTypeInt 16 ${signed}\n"
5213 " %${type16} = OpTypeVector %${base_type16} 2\n"
5214 " %c_i32_${count} = OpConstant %i32 ${count}\n"
5215 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5216 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
5217 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
5218 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
5219 " %up_${type32} = OpTypePointer Uniform %${type32}\n"
5220 " %SSBO32 = OpTypeStruct %a${count}${type32}\n"
5221 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5222 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5223 " %PC16 = OpTypeStruct %a${count}${type16}\n"
5224 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
5225 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
5226
5227 const StringTemplate decoration (
5228 "OpDecorate %a${count}${type16} ArrayStride 4\n"
5229 "OpDecorate %a${count}${type32} ArrayStride 8\n"
5230 "OpDecorate %SSBO32 BufferBlock\n"
5231 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5232 "OpDecorate %PC16 Block\n"
5233 "OpMemberDecorate %PC16 0 Offset 0\n"
5234 "OpDecorate %ssbo32 DescriptorSet 0\n"
5235 "OpDecorate %ssbo32 Binding 0\n");
5236
5237 { // signed int
5238 map<string, string> specs;
5239
5240 specs["base_type16"] = "i16";
5241 specs["type16"] = "v2i16";
5242 specs["type32"] = "v2i32";
5243 specs["signed"] = "1";
5244 specs["count"] = "32";
5245 specs["convert"] = "OpSConvert";
5246
5247 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5248 {
5249 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5250 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5251 string testName = "sint_vector";
5252 vector<deInt32> constIdxData;
5253
5254 if (useConstIdx)
5255 {
5256 constIdxData.reserve(numDataPoints);
5257
5258 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5259 constIdxData.push_back(sOutputs[constIdx * 2 + numIdx % 2]);
5260 }
5261
5262 specs["constarrayidx"] = de::toString(constIdx);
5263 if (useConstIdx)
5264 specs["arrayindex"] = "c_i32_ci";
5265 else
5266 specs["arrayindex"] = "30";
5267
5268 if (useConstIdx)
5269 testName += string("_const_idx_") + de::toString(constIdx);
5270
5271 resources.outputs.clear();
5272 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5273
5274 fragments["testfun"] = testFun.specialize(specs);
5275 fragments["pre_main"] = preMain.specialize(specs);
5276 fragments["decoration"] = decoration.specialize(specs);
5277
5278 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5279 }
5280 }
5281 { // unsigned int
5282 map<string, string> specs;
5283
5284 specs["base_type16"] = "u16";
5285 specs["type16"] = "v2u16";
5286 specs["type32"] = "v2u32";
5287 specs["signed"] = "0";
5288 specs["count"] = "32";
5289 specs["convert"] = "OpUConvert";
5290
5291 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5292 {
5293 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5294 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5295 string testName = "uint_vector";
5296 vector<deInt32> constIdxData;
5297
5298 if (useConstIdx)
5299 {
5300 constIdxData.reserve(numDataPoints);
5301
5302 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5303 constIdxData.push_back(uOutputs[constIdx * 2 + numIdx % 2]);
5304 }
5305
5306 specs["constarrayidx"] = de::toString(constIdx);
5307 if (useConstIdx)
5308 specs["arrayindex"] = "c_i32_ci";
5309 else
5310 specs["arrayindex"] = "30";
5311
5312 if (useConstIdx)
5313 testName += string("_const_idx_") + de::toString(constIdx);
5314
5315 resources.outputs.clear();
5316 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5317
5318 fragments["testfun"] = testFun.specialize(specs);
5319 fragments["pre_main"] = preMain.specialize(specs);
5320 fragments["decoration"] = decoration.specialize(specs);
5321
5322 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5323 }
5324 }
5325 }
5326 }
5327
addGraphics16BitStorageUniformInt16To32Group(tcu::TestCaseGroup * testGroup)5328 void addGraphics16BitStorageUniformInt16To32Group (tcu::TestCaseGroup* testGroup)
5329 {
5330 de::Random rnd (deStringHash(testGroup->getName()));
5331 map<string, string> fragments;
5332 const deUint32 numDataPoints = 256;
5333 RGBA defaultColors[4];
5334 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
5335 vector<deInt32> sOutputs;
5336 vector<deInt32> uOutputs;
5337 vector<string> extensions;
5338 const deUint16 signBitMask = 0x8000;
5339 const deUint32 signExtendMask = 0xffff0000;
5340 const StringTemplate capabilities ("OpCapability ${cap}\n");
5341
5342 sOutputs.reserve(inputs.size());
5343 uOutputs.reserve(inputs.size());
5344
5345 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
5346 {
5347 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
5348 if (inputs[numNdx] & signBitMask)
5349 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
5350 else
5351 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
5352 }
5353
5354 extensions.push_back("VK_KHR_16bit_storage");
5355 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5356
5357 getDefaultColors(defaultColors);
5358
5359 struct IntegerFacts
5360 {
5361 const char* name;
5362 const char* type32;
5363 const char* type16;
5364 const char* opcode;
5365 bool isSigned;
5366 };
5367
5368 const IntegerFacts intFacts[] =
5369 {
5370 {"sint", "%i32", "%i16", "OpSConvert", true},
5371 {"uint", "%u32", "%u16", "OpUConvert", false},
5372 };
5373
5374 struct ConstantIndex
5375 {
5376 bool useConstantIndex;
5377 deUint32 constantIndex;
5378 };
5379
5380 ConstantIndex constantIndices[] =
5381 {
5382 { false, 0 },
5383 { true, 4 },
5384 { true, 5 },
5385 { true, 6 }
5386 };
5387
5388 const StringTemplate scalarPreMain (
5389 "${itype16} = OpTypeInt 16 ${signed}\n"
5390 "%c_i32_256 = OpConstant %i32 256\n"
5391 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5392 " %up_i32 = OpTypePointer Uniform ${itype32}\n"
5393 " %up_i16 = OpTypePointer Uniform ${itype16}\n"
5394 " %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n"
5395 " %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n"
5396 " %SSBO32 = OpTypeStruct %ra_i32\n"
5397 " %SSBO16 = OpTypeStruct %ra_i16\n"
5398 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5399 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5400 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5401 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5402
5403 const StringTemplate scalarDecoration (
5404 "OpDecorate %ra_i32 ArrayStride 4\n"
5405 "OpDecorate %ra_i16 ArrayStride ${arraystride}\n"
5406 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5407 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5408 "OpDecorate %SSBO32 BufferBlock\n"
5409 "OpDecorate %SSBO16 ${indecor}\n"
5410 "OpDecorate %ssbo32 DescriptorSet 0\n"
5411 "OpDecorate %ssbo16 DescriptorSet 0\n"
5412 "OpDecorate %ssbo32 Binding 1\n"
5413 "OpDecorate %ssbo16 Binding 0\n");
5414
5415 const StringTemplate scalarTestFunc (
5416 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5417 " %param = OpFunctionParameter %v4f32\n"
5418
5419 "%entry = OpLabel\n"
5420 " %i = OpVariable %fp_i32 Function\n"
5421 " OpStore %i %c_i32_0\n"
5422 " OpBranch %loop\n"
5423
5424 " %loop = OpLabel\n"
5425 " %15 = OpLoad %i32 %i\n"
5426 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
5427 " OpLoopMerge %merge %inc None\n"
5428 " OpBranchConditional %lt %write %merge\n"
5429
5430 "%write = OpLabel\n"
5431 " %30 = OpLoad %i32 %i\n"
5432 " %src = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5433 "%val16 = OpLoad ${itype16} %src\n"
5434 "%val32 = ${convert} ${itype32} %val16\n"
5435 " %dst = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n"
5436 " OpStore %dst %val32\n"
5437 " OpBranch %inc\n"
5438
5439 " %inc = OpLabel\n"
5440 " %37 = OpLoad %i32 %i\n"
5441 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5442 " OpStore %i %39\n"
5443 " OpBranch %loop\n"
5444 "%merge = OpLabel\n"
5445 " OpReturnValue %param\n"
5446
5447 "OpFunctionEnd\n");
5448
5449 const StringTemplate vecPreMain (
5450 "${itype16} = OpTypeInt 16 ${signed}\n"
5451 "%c_i32_128 = OpConstant %i32 128\n"
5452 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5453 "%v2itype16 = OpTypeVector ${itype16} 2\n"
5454 " %up_v2i32 = OpTypePointer Uniform ${v2itype32}\n"
5455 " %up_v2i16 = OpTypePointer Uniform %v2itype16\n"
5456 " %ra_v2i32 = OpTypeArray ${v2itype32} %c_i32_128\n"
5457 " %ra_v2i16 = OpTypeArray %v2itype16 %c_i32_128\n"
5458 " %SSBO32 = OpTypeStruct %ra_v2i32\n"
5459 " %SSBO16 = OpTypeStruct %ra_v2i16\n"
5460 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5461 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5462 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5463 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5464
5465 const StringTemplate vecDecoration (
5466 "OpDecorate %ra_v2i32 ArrayStride 8\n"
5467 "OpDecorate %ra_v2i16 ArrayStride ${arraystride}\n"
5468 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5469 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5470 "OpDecorate %SSBO32 BufferBlock\n"
5471 "OpDecorate %SSBO16 ${indecor}\n"
5472 "OpDecorate %ssbo32 DescriptorSet 0\n"
5473 "OpDecorate %ssbo16 DescriptorSet 0\n"
5474 "OpDecorate %ssbo32 Binding 1\n"
5475 "OpDecorate %ssbo16 Binding 0\n");
5476
5477 const StringTemplate vecTestFunc (
5478 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5479 " %param = OpFunctionParameter %v4f32\n"
5480
5481 "%entry = OpLabel\n"
5482 " %i = OpVariable %fp_i32 Function\n"
5483 " OpStore %i %c_i32_0\n"
5484 " OpBranch %loop\n"
5485
5486 " %loop = OpLabel\n"
5487 " %15 = OpLoad %i32 %i\n"
5488 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
5489 " OpLoopMerge %merge %inc None\n"
5490 " OpBranchConditional %lt %write %merge\n"
5491
5492 "%write = OpLabel\n"
5493 " %30 = OpLoad %i32 %i\n"
5494 " %src = OpAccessChain %up_v2i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5495 "%val16 = OpLoad %v2itype16 %src\n"
5496 "%val32 = ${convert} ${v2itype32} %val16\n"
5497 " %dst = OpAccessChain %up_v2i32 %ssbo32 %c_i32_0 %30\n"
5498 " OpStore %dst %val32\n"
5499 " OpBranch %inc\n"
5500
5501 " %inc = OpLabel\n"
5502 " %37 = OpLoad %i32 %i\n"
5503 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5504 " OpStore %i %39\n"
5505 " OpBranch %loop\n"
5506 "%merge = OpLabel\n"
5507 " OpReturnValue %param\n"
5508
5509 "OpFunctionEnd\n");
5510
5511 struct Category
5512 {
5513 const char* name;
5514 const StringTemplate& preMain;
5515 const StringTemplate& decoration;
5516 const StringTemplate& testFunction;
5517 const deUint32 numElements;
5518 };
5519
5520 const Category categories[] =
5521 {
5522 {"scalar", scalarPreMain, scalarDecoration, scalarTestFunc, 1},
5523 {"vector", vecPreMain, vecDecoration, vecTestFunc, 2},
5524 };
5525
5526 const deUint32 minArrayStride[] = {2, 16};
5527
5528 for (deUint32 catIdx = 0; catIdx < DE_LENGTH_OF_ARRAY(categories); ++catIdx)
5529 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5530 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
5531 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5532 {
5533 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5534 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5535 map<string, string> specs;
5536 string name = string(CAPABILITIES[capIdx].name) + "_" + categories[catIdx].name + "_" + intFacts[factIdx].name;
5537 const deUint32 numElements = categories[catIdx].numElements;
5538 const deUint32 arrayStride = de::max(numElements * 2, minArrayStride[capIdx]);
5539
5540 specs["cap"] = CAPABILITIES[capIdx].cap;
5541 specs["indecor"] = CAPABILITIES[capIdx].decor;
5542 specs["arraystride"] = de::toString(arrayStride);
5543 specs["itype32"] = intFacts[factIdx].type32;
5544 specs["v2itype32"] = "%v2" + string(intFacts[factIdx].type32).substr(1);
5545 specs["v3itype32"] = "%v3" + string(intFacts[factIdx].type32).substr(1);
5546 specs["itype16"] = intFacts[factIdx].type16;
5547 if (intFacts[factIdx].isSigned)
5548 specs["signed"] = "1";
5549 else
5550 specs["signed"] = "0";
5551 specs["convert"] = intFacts[factIdx].opcode;
5552 specs["constarrayidx"] = de::toString(constIdx);
5553 if (useConstIdx)
5554 specs["arrayindex"] = "c_i32_ci";
5555 else
5556 specs["arrayindex"] = "30";
5557
5558 fragments["pre_main"] = categories[catIdx].preMain.specialize(specs);
5559 fragments["testfun"] = categories[catIdx].testFunction.specialize(specs);
5560 fragments["capability"] = capabilities.specialize(specs);
5561 fragments["decoration"] = categories[catIdx].decoration.specialize(specs);
5562
5563 GraphicsResources resources;
5564 vector<deInt16> inputsPadded;
5565 VulkanFeatures features;
5566
5567 for (size_t dataIdx = 0; dataIdx < inputs.size() / numElements; ++dataIdx)
5568 {
5569 for (deUint32 elementIdx = 0; elementIdx < numElements; ++elementIdx)
5570 inputsPadded.push_back(inputs[dataIdx * numElements + elementIdx]);
5571 for (deUint32 padIdx = 0; padIdx < arrayStride / 2 - numElements; ++padIdx)
5572 inputsPadded.push_back(0);
5573 }
5574
5575 resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputsPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5576
5577 vector<deInt32> constIdxOutputs;
5578 if (useConstIdx)
5579 {
5580 name += string("_const_idx_") + de::toString(constIdx);
5581 for (deUint32 i = 0; i < numDataPoints; i++)
5582 {
5583 deUint32 idx = constIdx * numElements + i % numElements;
5584 constIdxOutputs.push_back(intFacts[factIdx].isSigned ? sOutputs[idx] : uOutputs[idx]);
5585 }
5586 }
5587
5588 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5589 resources.outputs.clear();
5590 if (useConstIdx)
5591 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(constIdxOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5592 else if (intFacts[factIdx].isSigned)
5593 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5594 else
5595 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5596
5597 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5598 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5599 features.coreFeatures.fragmentStoresAndAtomics = true;
5600
5601 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5602 }
5603 }
5604
addGraphics16BitStorageUniformFloat16To32Group(tcu::TestCaseGroup * testGroup)5605 void addGraphics16BitStorageUniformFloat16To32Group (tcu::TestCaseGroup* testGroup)
5606 {
5607 de::Random rnd (deStringHash(testGroup->getName()));
5608 map<string, string> fragments;
5609 vector<string> extensions;
5610 const deUint32 numDataPoints = 256;
5611 RGBA defaultColors[4];
5612 const StringTemplate capabilities ("OpCapability ${cap}\n");
5613 vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints);
5614
5615 struct ConstantIndex
5616 {
5617 bool useConstantIndex;
5618 deUint32 constantIndex;
5619 };
5620
5621 ConstantIndex constantIndices[] =
5622 {
5623 { false, 0 },
5624 { true, 4 },
5625 { true, 5 },
5626 { true, 6 }
5627 };
5628
5629 extensions.push_back("VK_KHR_16bit_storage");
5630 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5631
5632 getDefaultColors(defaultColors);
5633
5634 { // scalar cases
5635 const StringTemplate preMain (
5636 " %f16 = OpTypeFloat 16\n"
5637 "%c_i32_256 = OpConstant %i32 256\n"
5638 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5639 " %up_f32 = OpTypePointer Uniform %f32\n"
5640 " %up_f16 = OpTypePointer Uniform %f16\n"
5641 " %ra_f32 = OpTypeArray %f32 %c_i32_256\n"
5642 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
5643 " %SSBO32 = OpTypeStruct %ra_f32\n"
5644 " %SSBO16 = OpTypeStruct %ra_f16\n"
5645 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5646 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5647 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5648 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5649
5650 const StringTemplate decoration (
5651 "OpDecorate %ra_f32 ArrayStride 4\n"
5652 "OpDecorate %ra_f16 ArrayStride ${arraystride}\n"
5653 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5654 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5655 "OpDecorate %SSBO32 BufferBlock\n"
5656 "OpDecorate %SSBO16 ${indecor}\n"
5657 "OpDecorate %ssbo32 DescriptorSet 0\n"
5658 "OpDecorate %ssbo16 DescriptorSet 0\n"
5659 "OpDecorate %ssbo32 Binding 1\n"
5660 "OpDecorate %ssbo16 Binding 0\n");
5661
5662 // ssbo32[] <- convert ssbo16[] to 32bit float
5663 const StringTemplate testFun (
5664 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5665 " %param = OpFunctionParameter %v4f32\n"
5666
5667 "%entry = OpLabel\n"
5668 " %i = OpVariable %fp_i32 Function\n"
5669 " OpStore %i %c_i32_0\n"
5670 " OpBranch %loop\n"
5671
5672 " %loop = OpLabel\n"
5673 " %15 = OpLoad %i32 %i\n"
5674 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
5675 " OpLoopMerge %merge %inc None\n"
5676 " OpBranchConditional %lt %write %merge\n"
5677
5678 "%write = OpLabel\n"
5679 " %30 = OpLoad %i32 %i\n"
5680 " %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5681 "%val16 = OpLoad %f16 %src\n"
5682 "%val32 = OpFConvert %f32 %val16\n"
5683 " %dst = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n"
5684 " OpStore %dst %val32\n"
5685 " OpBranch %inc\n"
5686
5687 " %inc = OpLabel\n"
5688 " %37 = OpLoad %i32 %i\n"
5689 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5690 " OpStore %i %39\n"
5691 " OpBranch %loop\n"
5692
5693 "%merge = OpLabel\n"
5694 " OpReturnValue %param\n"
5695
5696 "OpFunctionEnd\n");
5697
5698 const deUint32 arrayStrides[] = {2, 16};
5699
5700 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5701 {
5702 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5703 {
5704 GraphicsResources resources;
5705 map<string, string> specs;
5706 VulkanFeatures features;
5707 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float";
5708 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5709 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5710
5711 specs["cap"] = CAPABILITIES[capIdx].cap;
5712 specs["indecor"] = CAPABILITIES[capIdx].decor;
5713 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
5714 specs["constarrayidx"] = de::toString(constIdx);
5715 if (useConstIdx)
5716 specs["arrayindex"] = "c_i32_ci";
5717 else
5718 specs["arrayindex"] = "30";
5719
5720 fragments["capability"] = capabilities.specialize(specs);
5721 fragments["decoration"] = decoration.specialize(specs);
5722 fragments["pre_main"] = preMain.specialize(specs);
5723 fragments["testfun"] = testFun.specialize(specs);
5724
5725 vector<deFloat16> inputData;
5726 for (size_t dataIdx = 0; dataIdx < float16Data.size(); ++dataIdx)
5727 {
5728 inputData.push_back(float16Data[dataIdx]);
5729 for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 1; ++padIdx)
5730 inputData.push_back(deFloat16(0.0f));
5731 }
5732
5733 vector<float> float32Data;
5734 float32Data.reserve(numDataPoints);
5735 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5736 float32Data.push_back(deFloat16To32(float16Data[useConstIdx ? constIdx : numIdx]));
5737
5738 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5739 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5740 resources.verifyIO = check32BitFloats;
5741 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5742
5743 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5744 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5745 features.coreFeatures.fragmentStoresAndAtomics = true;
5746
5747 if (useConstIdx)
5748 testName += string("_const_idx_") + de::toString(constIdx);
5749
5750 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5751 }
5752 }
5753 }
5754
5755 { // vector cases
5756 const StringTemplate preMain (
5757 " %f16 = OpTypeFloat 16\n"
5758 "%c_i32_128 = OpConstant %i32 128\n"
5759 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5760 " %v2f16 = OpTypeVector %f16 2\n"
5761 " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5762 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5763 " %ra_v2f32 = OpTypeArray %v2f32 %c_i32_128\n"
5764 " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n"
5765 " %SSBO32 = OpTypeStruct %ra_v2f32\n"
5766 " %SSBO16 = OpTypeStruct %ra_v2f16\n"
5767 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5768 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5769 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5770 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5771
5772 const StringTemplate decoration (
5773 "OpDecorate %ra_v2f32 ArrayStride 8\n"
5774 "OpDecorate %ra_v2f16 ArrayStride ${arraystride}\n"
5775 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5776 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5777 "OpDecorate %SSBO32 BufferBlock\n"
5778 "OpDecorate %SSBO16 ${indecor}\n"
5779 "OpDecorate %ssbo32 DescriptorSet 0\n"
5780 "OpDecorate %ssbo16 DescriptorSet 0\n"
5781 "OpDecorate %ssbo32 Binding 1\n"
5782 "OpDecorate %ssbo16 Binding 0\n");
5783
5784 // ssbo32[] <- convert ssbo16[] to 32bit float
5785 const StringTemplate testFun (
5786 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5787 " %param = OpFunctionParameter %v4f32\n"
5788
5789 "%entry = OpLabel\n"
5790 " %i = OpVariable %fp_i32 Function\n"
5791 " OpStore %i %c_i32_0\n"
5792 " OpBranch %loop\n"
5793
5794 " %loop = OpLabel\n"
5795 " %15 = OpLoad %i32 %i\n"
5796 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
5797 " OpLoopMerge %merge %inc None\n"
5798 " OpBranchConditional %lt %write %merge\n"
5799
5800 "%write = OpLabel\n"
5801 " %30 = OpLoad %i32 %i\n"
5802 " %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5803 "%val16 = OpLoad %v2f16 %src\n"
5804 "%val32 = OpFConvert %v2f32 %val16\n"
5805 " %dst = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30\n"
5806 " OpStore %dst %val32\n"
5807 " OpBranch %inc\n"
5808
5809 " %inc = OpLabel\n"
5810 " %37 = OpLoad %i32 %i\n"
5811 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5812 " OpStore %i %39\n"
5813 " OpBranch %loop\n"
5814
5815 "%merge = OpLabel\n"
5816 " OpReturnValue %param\n"
5817
5818 "OpFunctionEnd\n");
5819
5820 const deUint32 arrayStrides[] = {4, 16};
5821
5822 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5823 {
5824 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5825 {
5826 GraphicsResources resources;
5827 map<string, string> specs;
5828 VulkanFeatures features;
5829 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float";
5830 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5831 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5832
5833 specs["cap"] = CAPABILITIES[capIdx].cap;
5834 specs["indecor"] = CAPABILITIES[capIdx].decor;
5835 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
5836 specs["constarrayidx"] = de::toString(constIdx);
5837 if (useConstIdx)
5838 specs["arrayindex"] = "c_i32_ci";
5839 else
5840 specs["arrayindex"] = "30";
5841
5842 fragments["capability"] = capabilities.specialize(specs);
5843 fragments["decoration"] = decoration.specialize(specs);
5844 fragments["pre_main"] = preMain.specialize(specs);
5845 fragments["testfun"] = testFun.specialize(specs);
5846
5847 vector<deFloat16> inputData;
5848 for (size_t dataIdx = 0; dataIdx < float16Data.size() / 2; ++dataIdx)
5849 {
5850 inputData.push_back(float16Data[dataIdx * 2]);
5851 inputData.push_back(float16Data[dataIdx * 2 + 1]);
5852 for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 2; ++padIdx)
5853 inputData.push_back(deFloat16(0.0f));
5854 }
5855
5856 vector<float> float32Data;
5857 float32Data.reserve(numDataPoints);
5858 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5859 float32Data.push_back(deFloat16To32(float16Data[constantIndices[constIndexIdx].useConstantIndex ? (constantIndices[constIndexIdx].constantIndex * 2 + numIdx % 2) : numIdx]));
5860
5861 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5862 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5863 resources.verifyIO = check32BitFloats;
5864 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5865
5866 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5867 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5868 features.coreFeatures.fragmentStoresAndAtomics = true;
5869
5870 if (constantIndices[constIndexIdx].useConstantIndex)
5871 testName += string("_const_idx_") + de::toString(constantIndices[constIndexIdx].constantIndex);
5872
5873 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5874 }
5875 }
5876 }
5877
5878 { // matrix cases
5879 fragments["pre_main"] =
5880 " %c_i32_32 = OpConstant %i32 32\n"
5881 " %f16 = OpTypeFloat 16\n"
5882 " %v2f16 = OpTypeVector %f16 2\n"
5883 " %m4x2f32 = OpTypeMatrix %v2f32 4\n"
5884 " %m4x2f16 = OpTypeMatrix %v2f16 4\n"
5885 " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5886 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5887 "%a8m4x2f32 = OpTypeArray %m4x2f32 %c_i32_32\n"
5888 "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n"
5889 " %SSBO32 = OpTypeStruct %a8m4x2f32\n"
5890 " %SSBO16 = OpTypeStruct %a8m4x2f16\n"
5891 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5892 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5893 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5894 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
5895
5896 const StringTemplate decoration (
5897 "OpDecorate %a8m4x2f32 ArrayStride 32\n"
5898 "OpDecorate %a8m4x2f16 ArrayStride 16\n"
5899 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5900 "OpMemberDecorate %SSBO32 0 ColMajor\n"
5901 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n"
5902 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5903 "OpMemberDecorate %SSBO16 0 ColMajor\n"
5904 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"
5905 "OpDecorate %SSBO32 BufferBlock\n"
5906 "OpDecorate %SSBO16 ${indecor}\n"
5907 "OpDecorate %ssbo32 DescriptorSet 0\n"
5908 "OpDecorate %ssbo16 DescriptorSet 0\n"
5909 "OpDecorate %ssbo32 Binding 1\n"
5910 "OpDecorate %ssbo16 Binding 0\n");
5911
5912 fragments["testfun"] =
5913 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5914 " %param = OpFunctionParameter %v4f32\n"
5915
5916 "%entry = OpLabel\n"
5917 " %i = OpVariable %fp_i32 Function\n"
5918 " OpStore %i %c_i32_0\n"
5919 " OpBranch %loop\n"
5920
5921 " %loop = OpLabel\n"
5922 " %15 = OpLoad %i32 %i\n"
5923 " %lt = OpSLessThan %bool %15 %c_i32_32\n"
5924 " OpLoopMerge %merge %inc None\n"
5925 " OpBranchConditional %lt %write %merge\n"
5926
5927 " %write = OpLabel\n"
5928 " %30 = OpLoad %i32 %i\n"
5929 " %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
5930 " %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
5931 " %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
5932 " %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
5933 "%val16_0 = OpLoad %v2f16 %src_0\n"
5934 "%val16_1 = OpLoad %v2f16 %src_1\n"
5935 "%val16_2 = OpLoad %v2f16 %src_2\n"
5936 "%val16_3 = OpLoad %v2f16 %src_3\n"
5937 "%val32_0 = OpFConvert %v2f32 %val16_0\n"
5938 "%val32_1 = OpFConvert %v2f32 %val16_1\n"
5939 "%val32_2 = OpFConvert %v2f32 %val16_2\n"
5940 "%val32_3 = OpFConvert %v2f32 %val16_3\n"
5941 " %dst_0 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n"
5942 " %dst_1 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
5943 " %dst_2 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n"
5944 " %dst_3 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n"
5945 " OpStore %dst_0 %val32_0\n"
5946 " OpStore %dst_1 %val32_1\n"
5947 " OpStore %dst_2 %val32_2\n"
5948 " OpStore %dst_3 %val32_3\n"
5949 " OpBranch %inc\n"
5950
5951 " %inc = OpLabel\n"
5952 " %37 = OpLoad %i32 %i\n"
5953 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5954 " OpStore %i %39\n"
5955 " OpBranch %loop\n"
5956
5957 "%merge = OpLabel\n"
5958 " OpReturnValue %param\n"
5959
5960 "OpFunctionEnd\n";
5961
5962 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5963 {
5964 GraphicsResources resources;
5965 map<string, string> specs;
5966 VulkanFeatures features;
5967 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float";
5968
5969 specs["cap"] = CAPABILITIES[capIdx].cap;
5970 specs["indecor"] = CAPABILITIES[capIdx].decor;
5971
5972 fragments["capability"] = capabilities.specialize(specs);
5973 fragments["decoration"] = decoration.specialize(specs);
5974
5975 vector<float> float32Data;
5976 float32Data.reserve(numDataPoints);
5977 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5978 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
5979
5980 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5981 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5982 resources.verifyIO = check32BitFloats;
5983 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5984
5985 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5986 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5987 features.coreFeatures.fragmentStoresAndAtomics = true;
5988
5989 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5990 }
5991 }
5992 }
5993
addGraphics16BitStorageUniformStructFloat16To32Group(tcu::TestCaseGroup * testGroup)5994 void addGraphics16BitStorageUniformStructFloat16To32Group (tcu::TestCaseGroup* testGroup)
5995 {
5996 de::Random rnd (deStringHash(testGroup->getName()));
5997 map<string, string> fragments;
5998 vector<string> extensions;
5999 RGBA defaultColors[4];
6000 const StringTemplate capabilities ("OpCapability ${cap}\n");
6001 vector<float> float32Data (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430), 0.0f);
6002
6003 extensions.push_back("VK_KHR_16bit_storage");
6004 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6005
6006 getDefaultColors(defaultColors);
6007
6008 const StringTemplate preMain (
6009 "\n"
6010 "${types}\n"
6011 "\n"
6012 "%zero = OpConstant %i32 0\n"
6013 "%c_i32_5 = OpConstant %i32 5\n"
6014 "%c_i32_6 = OpConstant %i32 6\n"
6015 "%c_i32_7 = OpConstant %i32 7\n"
6016 "%c_i32_8 = OpConstant %i32 8\n"
6017 "%c_i32_9 = OpConstant %i32 9\n"
6018 "%c_i32_11 = OpConstant %i32 11\n"
6019 "\n"
6020 "%c_u32_7 = OpConstant %u32 7\n"
6021 "%c_u32_11 = OpConstant %u32 11\n"
6022 "\n"
6023 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
6024 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
6025 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
6026 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
6027 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
6028 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
6029 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
6030 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
6031 "\n"
6032 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
6033 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
6034 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
6035 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
6036 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
6037 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
6038 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
6039 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
6040 "\n"
6041 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
6042 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
6043 "%SSBO_IN = OpTypeStruct %f16StructArr7\n"
6044 "%SSBO_OUT = OpTypeStruct %f32StructArr7\n"
6045 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6046 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6047 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6048 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
6049 "\n");
6050
6051 const StringTemplate decoration (
6052 "${strideF16}"
6053 "\n"
6054 "${strideF32}"
6055 "\n"
6056 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6057 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6058 "OpDecorate %SSBO_IN ${indecor}\n"
6059 "OpDecorate %SSBO_OUT BufferBlock\n"
6060 "OpDecorate %ssboIN DescriptorSet 0\n"
6061 "OpDecorate %ssboOUT DescriptorSet 0\n"
6062 "OpDecorate %ssboIN Binding 0\n"
6063 "OpDecorate %ssboOUT Binding 1\n"
6064 "\n");
6065
6066 fragments["testfun"] =
6067 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6068 " %param = OpFunctionParameter %v4f32\n"
6069 "%label = OpLabel\n"
6070 "%loopNdx = OpVariable %fp_i32 Function\n"
6071 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
6072
6073 "OpStore %loopNdx %zero\n"
6074 "OpBranch %loop\n"
6075 "%loop = OpLabel\n"
6076 "OpLoopMerge %merge %13 None\n"
6077 "OpBranch %14\n"
6078 "%14 = OpLabel\n"
6079 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
6080 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
6081 "OpBranchConditional %18 %11 %merge\n"
6082 "%11 = OpLabel\n"
6083 "\n"
6084 "%f16src = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %zero\n"
6085 "%val_f16 = OpLoad %f16 %f16src\n"
6086 "%val_f32 = OpFConvert %f32 %val_f16\n"
6087 "%f32dst = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %zero\n"
6088 "OpStore %f32dst %val_f32\n"
6089 "\n"
6090 "%v2f16src = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
6091 "%val_v2f16 = OpLoad %v2f16 %v2f16src\n"
6092 "%val_v2f32 = OpFConvert %v2f32 %val_v2f16\n"
6093 "%v2f32dst = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
6094 "OpStore %v2f32dst %val_v2f32\n"
6095 "\n"
6096 "%v3f16src = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
6097 "%val_v3f16 = OpLoad %v3f16 %v3f16src\n"
6098 "%val_v3f32 = OpFConvert %v3f32 %val_v3f16\n"
6099 "%v3f32dst = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
6100 "OpStore %v3f32dst %val_v3f32\n"
6101 "\n"
6102 "%v4f16src = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
6103 "%val_v4f16 = OpLoad %v4f16 %v4f16src\n"
6104 "%val_v4f32 = OpFConvert %v4f32 %val_v4f16\n"
6105 "%v4f32dst = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
6106 "OpStore %v4f32dst %val_v4f32\n"
6107 "\n"
6108 "%f16src2 = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
6109 "%val2_f16 = OpLoad %f16 %f16src2\n"
6110 "%val2_f32 = OpFConvert %f32 %val2_f16\n"
6111 "%f32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
6112 "OpStore %f32dst2 %val2_f32\n"
6113 "\n"
6114 "OpStore %insideLoopNdx %zero\n"
6115 "OpBranch %loopInside\n"
6116 "%loopInside = OpLabel\n"
6117 "OpLoopMerge %92 %93 None\n"
6118 "OpBranch %94\n"
6119 "%94 = OpLabel\n"
6120 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
6121 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
6122 "OpBranchConditional %96 %91 %92\n"
6123 "\n"
6124 "%91 = OpLabel\n"
6125 "\n"
6126 "%v2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6127 "%val2_v2f16 = OpLoad %v2f16 %v2f16src2\n"
6128 "%val2_v2f32 = OpFConvert %v2f32 %val2_v2f16\n"
6129 "%v2f32dst2 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6130 "OpStore %v2f32dst2 %val2_v2f32\n"
6131 "\n"
6132 "%v3f16src2 = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6133 "%val2_v3f16 = OpLoad %v3f16 %v3f16src2\n"
6134 "%val2_v3f32 = OpFConvert %v3f32 %val2_v3f16\n"
6135 "%v3f32dst2 = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6136 "OpStore %v3f32dst2 %val2_v3f32\n"
6137 "\n"
6138 //struct {f16, v2f16[3]}
6139 "%Sf16src = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6140 "%Sval_f16 = OpLoad %f16 %Sf16src\n"
6141 "%Sval_f32 = OpFConvert %f32 %Sval_f16\n"
6142 "%Sf32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6143 "OpStore %Sf32dst2 %Sval_f32\n"
6144 "\n"
6145 "%Sv2f16src0 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6146 "%Sv2f16_0 = OpLoad %v2f16 %Sv2f16src0\n"
6147 "%Sv2f32_0 = OpFConvert %v2f32 %Sv2f16_0\n"
6148 "%Sv2f32dst_0 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6149 "OpStore %Sv2f32dst_0 %Sv2f32_0\n"
6150 "\n"
6151 "%Sv2f16src1 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6152 "%Sv2f16_1 = OpLoad %v2f16 %Sv2f16src1\n"
6153 "%Sv2f32_1 = OpFConvert %v2f32 %Sv2f16_1\n"
6154 "%Sv2f32dst_1 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6155 "OpStore %Sv2f32dst_1 %Sv2f32_1\n"
6156 "\n"
6157 "%Sv2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6158 "%Sv2f16_2 = OpLoad %v2f16 %Sv2f16src2\n"
6159 "%Sv2f32_2 = OpFConvert %v2f32 %Sv2f16_2\n"
6160 "%Sv2f32dst_2 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6161 "OpStore %Sv2f32dst_2 %Sv2f32_2\n"
6162 "\n"
6163 //Array with 3 elements
6164 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
6165 "OpSelectionMerge %BlockIf None\n"
6166 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
6167 "%LabelIf = OpLabel\n"
6168 " %f16src3 = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6169 " %val3_f16 = OpLoad %f16 %f16src3\n"
6170 " %val3_f32 = OpFConvert %f32 %val3_f16\n"
6171 " %f32dst3 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6172 " OpStore %f32dst3 %val3_f32\n"
6173 "\n"
6174 " %v4f16src2 = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6175 " %val2_v4f16 = OpLoad %v4f16 %v4f16src2\n"
6176 " %val2_v4f32 = OpFConvert %v4f32 %val2_v4f16\n"
6177 " %v4f32dst2 = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6178 " OpStore %v4f32dst2 %val2_v4f32\n"
6179 "OpBranch %BlockIf\n"
6180 "%BlockIf = OpLabel\n"
6181 "\n"
6182 "OpBranch %93\n"
6183 "%93 = OpLabel\n"
6184 "%132 = OpLoad %i32 %insideLoopNdx\n"
6185 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
6186 "OpStore %insideLoopNdx %133\n"
6187 "OpBranch %loopInside\n"
6188 "\n"
6189 "%92 = OpLabel\n"
6190 "OpBranch %13\n"
6191 "%13 = OpLabel\n"
6192 "%134 = OpLoad %i32 %loopNdx\n"
6193 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
6194 "OpStore %loopNdx %135\n"
6195 "OpBranch %loop\n"
6196
6197 "%merge = OpLabel\n"
6198 " OpReturnValue %param\n"
6199 " OpFunctionEnd\n";
6200
6201 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6202 {
6203 vector<deFloat16> float16Data = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data16bitStd430(rnd) : data16bitStd140(rnd);
6204 GraphicsResources resources;
6205 map<string, string> specs;
6206 VulkanFeatures features;
6207 string testName = string(CAPABILITIES[capIdx].name);
6208
6209 specs["cap"] = CAPABILITIES[capIdx].cap;
6210 specs["indecor"] = CAPABILITIES[capIdx].decor;
6211 specs["strideF16"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE16BIT_STD430 : SHADERTEMPLATE_STRIDE16BIT_STD140);
6212 specs["strideF32"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE32BIT_STD430);
6213 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
6214
6215 fragments["capability"] = capabilities.specialize(specs);
6216 fragments["decoration"] = decoration.specialize(specs);
6217 fragments["pre_main"] = preMain.specialize(specs);
6218
6219 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), CAPABILITIES[capIdx].dtype));
6220 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6221 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>;
6222
6223 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6224 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6225 features.coreFeatures.fragmentStoresAndAtomics = true;
6226
6227 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6228 }
6229 }
6230
addGraphics16BitStorageUniformStructFloat32To16Group(tcu::TestCaseGroup * testGroup)6231 void addGraphics16BitStorageUniformStructFloat32To16Group (tcu::TestCaseGroup* testGroup)
6232 {
6233 de::Random rnd (deStringHash(testGroup->getName()));
6234 map<string, string> fragments;
6235 vector<string> extensions;
6236 RGBA defaultColors[4];
6237 const StringTemplate capabilities ("OpCapability ${cap}\n");
6238 vector<deUint16> float16Data (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430), 0u);
6239
6240 extensions.push_back("VK_KHR_16bit_storage");
6241 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6242
6243 getDefaultColors(defaultColors);
6244
6245 const StringTemplate preMain (
6246 "\n"
6247 "${types}\n"
6248 "\n"
6249 "%zero = OpConstant %i32 0\n"
6250 "%c_i32_5 = OpConstant %i32 5\n"
6251 "%c_i32_6 = OpConstant %i32 6\n"
6252 "%c_i32_7 = OpConstant %i32 7\n"
6253 "%c_i32_8 = OpConstant %i32 8\n"
6254 "%c_i32_9 = OpConstant %i32 9\n"
6255 "%c_i32_11 = OpConstant %i32 11\n"
6256 "\n"
6257 "%c_u32_7 = OpConstant %u32 7\n"
6258 "%c_u32_11 = OpConstant %u32 11\n"
6259 "\n"
6260 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
6261 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
6262 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
6263 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
6264 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
6265 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
6266 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
6267 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
6268 "\n"
6269 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
6270 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
6271 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
6272 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
6273 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
6274 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
6275 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
6276 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
6277 "\n"
6278 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
6279 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
6280 "%SSBO_IN = OpTypeStruct %f32StructArr7\n"
6281 "%SSBO_OUT = OpTypeStruct %f16StructArr7\n"
6282 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6283 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6284 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6285 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
6286 "\n");
6287
6288 const StringTemplate decoration (
6289 "${strideF16}"
6290 "\n"
6291 "${strideF32}"
6292 "\n"
6293 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6294 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6295 "OpDecorate %SSBO_IN ${indecor}\n"
6296 "OpDecorate %SSBO_OUT BufferBlock\n"
6297 "OpDecorate %ssboIN DescriptorSet 0\n"
6298 "OpDecorate %ssboOUT DescriptorSet 0\n"
6299 "OpDecorate %ssboIN Binding 0\n"
6300 "OpDecorate %ssboOUT Binding 1\n"
6301 "\n");
6302
6303 fragments["testfun"] =
6304 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6305 "%param = OpFunctionParameter %v4f32\n"
6306 "%label = OpLabel\n"
6307 "%loopNdx = OpVariable %fp_i32 Function\n"
6308 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
6309
6310 "OpStore %loopNdx %zero\n"
6311 "OpBranch %loop\n"
6312 "%loop = OpLabel\n"
6313 "OpLoopMerge %merge %13 None\n"
6314 "OpBranch %14\n"
6315 "%14 = OpLabel\n"
6316 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
6317 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
6318 "OpBranchConditional %18 %11 %merge\n"
6319 "%11 = OpLabel\n"
6320 "\n"
6321 "%f32src = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %zero\n"
6322 "%val_f32 = OpLoad %f32 %f32src\n"
6323 "%val_f16 = OpFConvert %f16 %val_f32\n"
6324 "%f16dst = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %zero\n"
6325 "OpStore %f16dst %val_f16\n"
6326 "\n"
6327 "%v2f32src = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
6328 "%val_v2f32 = OpLoad %v2f32 %v2f32src\n"
6329 "%val_v2f16 = OpFConvert %v2f16 %val_v2f32\n"
6330 "%v2f16dst = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
6331 "OpStore %v2f16dst %val_v2f16\n"
6332 "\n"
6333 "%v3f32src = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
6334 "%val_v3f32 = OpLoad %v3f32 %v3f32src\n"
6335 "%val_v3f16 = OpFConvert %v3f16 %val_v3f32\n"
6336 "%v3f16dst = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
6337 "OpStore %v3f16dst %val_v3f16\n"
6338 "\n"
6339 "%v4f32src = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
6340 "%val_v4f32 = OpLoad %v4f32 %v4f32src\n"
6341 "%val_v4f16 = OpFConvert %v4f16 %val_v4f32\n"
6342 "%v4f16dst = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
6343 "OpStore %v4f16dst %val_v4f16\n"
6344 "\n"
6345 "%f32src2 = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
6346 "%val2_f32 = OpLoad %f32 %f32src2\n"
6347 "%val2_f16 = OpFConvert %f16 %val2_f32\n"
6348 "%f16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
6349 "OpStore %f16dst2 %val2_f16\n"
6350 "\n"
6351 "OpStore %insideLoopNdx %zero\n"
6352 "OpBranch %loopInside\n"
6353 "%loopInside = OpLabel\n"
6354 "OpLoopMerge %92 %93 None\n"
6355 "OpBranch %94\n"
6356 "%94 = OpLabel\n"
6357 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
6358 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
6359 "OpBranchConditional %96 %91 %92\n"
6360 "\n"
6361 "%91 = OpLabel\n"
6362 "\n"
6363 //struct {f16, v2f16[3]}
6364 "%Sf32src = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6365 "%Sval_f32 = OpLoad %f32 %Sf32src\n"
6366 "%Sval_f16 = OpFConvert %f16 %Sval_f32\n"
6367 "%Sf16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6368 "OpStore %Sf16dst2 %Sval_f16\n"
6369 "\n"
6370 "%Sv2f32src0 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6371 "%Sv2f32_0 = OpLoad %v2f32 %Sv2f32src0\n"
6372 "%Sv2f16_0 = OpFConvert %v2f16 %Sv2f32_0\n"
6373 "%Sv2f16dst_0 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6374 "OpStore %Sv2f16dst_0 %Sv2f16_0\n"
6375 "\n"
6376 "%Sv2f32src1 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6377 "%Sv2f32_1 = OpLoad %v2f32 %Sv2f32src1\n"
6378 "%Sv2f16_1 = OpFConvert %v2f16 %Sv2f32_1\n"
6379 "%Sv2f16dst_1 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6380 "OpStore %Sv2f16dst_1 %Sv2f16_1\n"
6381 "\n"
6382 "%Sv2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6383 "%Sv2f32_2 = OpLoad %v2f32 %Sv2f32src2\n"
6384 "%Sv2f16_2 = OpFConvert %v2f16 %Sv2f32_2\n"
6385 "%Sv2f16dst_2 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6386 "OpStore %Sv2f16dst_2 %Sv2f16_2\n"
6387 "\n"
6388
6389 "%v2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6390 "%val2_v2f32 = OpLoad %v2f32 %v2f32src2\n"
6391 "%val2_v2f16 = OpFConvert %v2f16 %val2_v2f32\n"
6392 "%v2f16dst2 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6393 "OpStore %v2f16dst2 %val2_v2f16\n"
6394 "\n"
6395 "%v3f32src2 = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6396 "%val2_v3f32 = OpLoad %v3f32 %v3f32src2\n"
6397 "%val2_v3f16 = OpFConvert %v3f16 %val2_v3f32\n"
6398 "%v3f16dst2 = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6399 "OpStore %v3f16dst2 %val2_v3f16\n"
6400 "\n"
6401
6402 //Array with 3 elements
6403 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
6404 "OpSelectionMerge %BlockIf None\n"
6405 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
6406 " %LabelIf = OpLabel\n"
6407 " %f32src3 = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6408 " %val3_f32 = OpLoad %f32 %f32src3\n"
6409 " %val3_f16 = OpFConvert %f16 %val3_f32\n"
6410 " %f16dst3 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6411 " OpStore %f16dst3 %val3_f16\n"
6412 "\n"
6413 " %v4f32src2 = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6414 " %val2_v4f32 = OpLoad %v4f32 %v4f32src2\n"
6415 " %val2_v4f16 = OpFConvert %v4f16 %val2_v4f32\n"
6416 " %v4f16dst2 = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6417 " OpStore %v4f16dst2 %val2_v4f16\n"
6418 "OpBranch %BlockIf\n"
6419 "%BlockIf = OpLabel\n"
6420
6421 "OpBranch %93\n"
6422 "%93 = OpLabel\n"
6423 "%132 = OpLoad %i32 %insideLoopNdx\n"
6424 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
6425 "OpStore %insideLoopNdx %133\n"
6426 "OpBranch %loopInside\n"
6427 "\n"
6428 "%92 = OpLabel\n"
6429 "OpBranch %13\n"
6430 "%13 = OpLabel\n"
6431 "%134 = OpLoad %i32 %loopNdx\n"
6432 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
6433 "OpStore %loopNdx %135\n"
6434 "OpBranch %loop\n"
6435
6436 "%merge = OpLabel\n"
6437 " OpReturnValue %param\n"
6438 " OpFunctionEnd\n";
6439
6440 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6441 {
6442 map<string, string> specs;
6443 string testName = string(CAPABILITIES[capIdx].name);
6444 vector<float> float32Data = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data32bitStd430(rnd) : data32bitStd140(rnd);
6445 GraphicsResources resources;
6446
6447 specs["cap"] = "StorageUniformBufferBlock16";
6448 specs["indecor"] = CAPABILITIES[capIdx].decor;
6449 specs["strideF16"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE16BIT_STD430);
6450 specs["strideF32"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE32BIT_STD430 : SHADERTEMPLATE_STRIDE32BIT_STD140);
6451 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
6452
6453 fragments["capability"] = capabilities.specialize(specs);
6454 fragments["decoration"] = decoration.specialize(specs);
6455 fragments["pre_main"] = preMain.specialize(specs);
6456
6457 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), CAPABILITIES[capIdx].dtype));
6458 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6459 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>;
6460
6461 VulkanFeatures features;
6462
6463 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6464 features.coreFeatures.fragmentStoresAndAtomics = true;
6465 features.ext16BitStorage.storageBuffer16BitAccess = true;
6466
6467 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6468 }
6469 }
6470
addGraphics16bitStructMixedTypesGroup(tcu::TestCaseGroup * group)6471 void addGraphics16bitStructMixedTypesGroup (tcu::TestCaseGroup* group)
6472 {
6473 de::Random rnd (deStringHash(group->getName()));
6474 map<string, string> fragments;
6475 vector<string> extensions;
6476 RGBA defaultColors[4];
6477 const StringTemplate capabilities ("OpCapability StorageUniformBufferBlock16\n"
6478 "${cap}\n");
6479 vector<deInt16> outData (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430), 0u);
6480
6481 extensions.push_back("VK_KHR_16bit_storage");
6482 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
6483
6484 getDefaultColors(defaultColors);
6485
6486 const StringTemplate preMain (
6487 "\n"//Types
6488 "%i16 = OpTypeInt 16 1\n"
6489 "%v2i16 = OpTypeVector %i16 2\n"
6490 "%v3i16 = OpTypeVector %i16 3\n"
6491 "%v4i16 = OpTypeVector %i16 4\n"
6492 "\n"//Consta value
6493 "%zero = OpConstant %i32 0\n"
6494 "%c_i32_5 = OpConstant %i32 5\n"
6495 "%c_i32_6 = OpConstant %i32 6\n"
6496 "%c_i32_7 = OpConstant %i32 7\n"
6497 "%c_i32_8 = OpConstant %i32 8\n"
6498 "%c_i32_9 = OpConstant %i32 9\n"
6499 "%c_i32_10 = OpConstant %i32 10\n"
6500 "%c_i32_11 = OpConstant %i32 11\n"
6501 "%c_u32_7 = OpConstant %u32 7\n"
6502 "%c_u32_11 = OpConstant %u32 11\n"
6503 "\n"//Arrays & Structs
6504 "%v2b16NestedArr11In = OpTypeArray %v2i16 %c_u32_11\n"
6505 "%b32NestedArr11In = OpTypeArray %i32 %c_u32_11\n"
6506 "%sb16Arr11In = OpTypeArray %i16 %c_u32_11\n"
6507 "%sb32Arr11In = OpTypeArray %i32 %c_u32_11\n"
6508 "%sNestedIn = OpTypeStruct %i16 %i32 %v2b16NestedArr11In %b32NestedArr11In\n"
6509 "%sNestedArr11In = OpTypeArray %sNestedIn %c_u32_11\n"
6510 "%structIn = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11In %sb16Arr11In %sb32Arr11In\n"
6511 "%structArr7In = OpTypeArray %structIn %c_u32_7\n"
6512 "%v2b16NestedArr11Out = OpTypeArray %v2i16 %c_u32_11\n"
6513 "%b32NestedArr11Out = OpTypeArray %i32 %c_u32_11\n"
6514 "%sb16Arr11Out = OpTypeArray %i16 %c_u32_11\n"
6515 "%sb32Arr11Out = OpTypeArray %i32 %c_u32_11\n"
6516 "%sNestedOut = OpTypeStruct %i16 %i32 %v2b16NestedArr11Out %b32NestedArr11Out\n"
6517 "%sNestedArr11Out = OpTypeArray %sNestedOut %c_u32_11\n"
6518 "%structOut = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11Out %sb16Arr11Out %sb32Arr11Out\n"
6519 "%structArr7Out = OpTypeArray %structOut %c_u32_7\n"
6520 "\n"//Pointers
6521 "%i16outPtr = OpTypePointer Uniform %i16\n"
6522 "%v2i16outPtr = OpTypePointer Uniform %v2i16\n"
6523 "%v3i16outPtr = OpTypePointer Uniform %v3i16\n"
6524 "%v4i16outPtr = OpTypePointer Uniform %v4i16\n"
6525 "%i32outPtr = OpTypePointer Uniform %i32\n"
6526 "%v2i32outPtr = OpTypePointer Uniform %v2i32\n"
6527 "%v3i32outPtr = OpTypePointer Uniform %v3i32\n"
6528 "%v4i32outPtr = OpTypePointer Uniform %v4i32\n"
6529 "%uvec3ptr = OpTypePointer Input %v3u32\n"
6530 "\n"//SSBO IN
6531 "%SSBO_IN = OpTypeStruct %structArr7In\n"
6532 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6533 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6534 "\n"//SSBO OUT
6535 "%SSBO_OUT = OpTypeStruct %structArr7Out\n"
6536 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6537 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n");
6538
6539 const StringTemplate decoration (
6540 "${OutOffsets}"
6541 "${InOffsets}"
6542 "\n"//SSBO IN
6543 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6544 "OpDecorate %ssboIN DescriptorSet 0\n"
6545 "OpDecorate %SSBO_IN ${storage}\n"
6546 "OpDecorate %SSBO_OUT BufferBlock\n"
6547 "OpDecorate %ssboIN Binding 0\n"
6548 "\n"//SSBO OUT
6549 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6550 "OpDecorate %ssboOUT DescriptorSet 0\n"
6551 "OpDecorate %ssboOUT Binding 1\n");
6552
6553 const StringTemplate testFun (
6554 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6555 "%param = OpFunctionParameter %v4f32\n"
6556 "%label = OpLabel\n"
6557 "%ndxArrx = OpVariable %fp_i32 Function\n"
6558 "%ndxArry = OpVariable %fp_i32 Function\n"
6559 "%ndxArrz = OpVariable %fp_i32 Function\n"
6560 "${xBeginLoop}"
6561 "\n"//strutOut.b16 = strutIn.b16
6562 "%inP1 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %zero\n"
6563 "%inV1 = OpLoad %i16 %inP1\n"
6564 "%outP1 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %zero\n"
6565 "OpStore %outP1 %inV1\n"
6566 "\n"//strutOut.b32 = strutIn.b32
6567 "%inP2 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_1\n"
6568 "%inV2 = OpLoad %i32 %inP2\n"
6569 "%outP2 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_1\n"
6570 "OpStore %outP2 %inV2\n"
6571 "\n"//strutOut.v2b16 = strutIn.v2b16
6572 "%inP3 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_2\n"
6573 "%inV3 = OpLoad %v2i16 %inP3\n"
6574 "%outP3 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_2\n"
6575 "OpStore %outP3 %inV3\n"
6576 "\n"//strutOut.v2b32 = strutIn.v2b32
6577 "%inP4 = OpAccessChain %v2i32${inPtr} %ssboIN %zero %Valx %c_i32_3\n"
6578 "%inV4 = OpLoad %v2i32 %inP4\n"
6579 "%outP4 = OpAccessChain %v2i32outPtr %ssboOUT %zero %Valx %c_i32_3\n"
6580 "OpStore %outP4 %inV4\n"
6581 "\n"//strutOut.v3b16 = strutIn.v3b16
6582 "%inP5 = OpAccessChain %v3i16${inPtr} %ssboIN %zero %Valx %c_i32_4\n"
6583 "%inV5 = OpLoad %v3i16 %inP5\n"
6584 "%outP5 = OpAccessChain %v3i16outPtr %ssboOUT %zero %Valx %c_i32_4\n"
6585 "OpStore %outP5 %inV5\n"
6586 "\n"//strutOut.v3b32 = strutIn.v3b32
6587 "%inP6 = OpAccessChain %v3i32${inPtr} %ssboIN %zero %Valx %c_i32_5\n"
6588 "%inV6 = OpLoad %v3i32 %inP6\n"
6589 "%outP6 = OpAccessChain %v3i32outPtr %ssboOUT %zero %Valx %c_i32_5\n"
6590 "OpStore %outP6 %inV6\n"
6591 "\n"//strutOut.v4b16 = strutIn.v4b16
6592 "%inP7 = OpAccessChain %v4i16${inPtr} %ssboIN %zero %Valx %c_i32_6\n"
6593 "%inV7 = OpLoad %v4i16 %inP7\n"
6594 "%outP7 = OpAccessChain %v4i16outPtr %ssboOUT %zero %Valx %c_i32_6\n"
6595 "OpStore %outP7 %inV7\n"
6596 "\n"//strutOut.v4b32 = strutIn.v4b32
6597 "%inP8 = OpAccessChain %v4i32${inPtr} %ssboIN %zero %Valx %c_i32_7\n"
6598 "%inV8 = OpLoad %v4i32 %inP8\n"
6599 "%outP8 = OpAccessChain %v4i32outPtr %ssboOUT %zero %Valx %c_i32_7\n"
6600 "OpStore %outP8 %inV8\n"
6601 "${yBeginLoop}"
6602 "\n"//strutOut.b16[y] = strutIn.b16[y]
6603 "%inP9 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_9 %Valy\n"
6604 "%inV9 = OpLoad %i16 %inP9\n"
6605 "%outP9 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_9 %Valy\n"
6606 "OpStore %outP9 %inV9\n"
6607 "\n"//strutOut.b32[y] = strutIn.b32[y]
6608 "%inP10 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_10 %Valy\n"
6609 "%inV10 = OpLoad %i32 %inP10\n"
6610 "%outP10 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_10 %Valy\n"
6611 "OpStore %outP10 %inV10\n"
6612 "\n"//strutOut.strutNestedOut[y].b16 = strutIn.strutNestedIn[y].b16
6613 "%inP11 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %zero\n"
6614 "%inV11 = OpLoad %i16 %inP11\n"
6615 "%outP11 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %zero\n"
6616 "OpStore %outP11 %inV11\n"
6617 "\n"//strutOut.strutNestedOut[y].b32 = strutIn.strutNestedIn[y].b32
6618 "%inP12 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6619 "%inV12 = OpLoad %i32 %inP12\n"
6620 "%outP12 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6621 "OpStore %outP12 %inV12\n"
6622 "${zBeginLoop}"
6623 "\n"//strutOut.strutNestedOut[y].v2b16[valNdx] = strutIn.strutNestedIn[y].v2b16[valNdx]
6624 "%inP13 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6625 "%inV13 = OpLoad %v2i16 %inP13\n"
6626 "%outP13 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6627 "OpStore %outP13 %inV13\n"
6628 "\n"//strutOut.strutNestedOut[y].b32[valNdx] = strutIn.strutNestedIn[y].b32[valNdx]
6629 "%inP14 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6630 "%inV14 = OpLoad %i32 %inP14\n"
6631 "%outP14 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6632 "OpStore %outP14 %inV14\n"
6633 "${zEndLoop}"
6634 "${yEndLoop}"
6635 "${xEndLoop}"
6636 "\n"
6637 "OpBranch %ExitLabel\n"
6638 "%ExitLabel = OpLabel\n"
6639 "OpReturnValue %param\n"
6640 "OpFunctionEnd\n");
6641
6642 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6643 { // int
6644 const bool isUniform = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == CAPABILITIES[capIdx].dtype;
6645 vector<deInt16> inData = isUniform ? dataMixStd140(rnd) : dataMixStd430(rnd);
6646 GraphicsResources resources;
6647 map<string, string> specsLoop;
6648 map<string, string> specsOffset;
6649 map<string, string> specs;
6650 VulkanFeatures features;
6651 string testName = string(CAPABILITIES[capIdx].name);
6652
6653 specsLoop["exeCount"] = "c_i32_7";
6654 specsLoop["loopName"] = "x";
6655 specs["xBeginLoop"] = beginLoop(specsLoop);
6656 specs["xEndLoop"] = endLoop(specsLoop);
6657
6658 specsLoop["exeCount"] = "c_i32_11";
6659 specsLoop["loopName"] = "y";
6660 specs["yBeginLoop"] = beginLoop(specsLoop);
6661 specs["yEndLoop"] = endLoop(specsLoop);
6662
6663 specsLoop["exeCount"] = "c_i32_11";
6664 specsLoop["loopName"] = "z";
6665 specs["zBeginLoop"] = beginLoop(specsLoop);
6666 specs["zEndLoop"] = endLoop(specsLoop);
6667
6668 specs["storage"] = isUniform ? "Block" : "BufferBlock";
6669 specs["cap"] = isUniform ?"OpCapability " + string( CAPABILITIES[capIdx].cap) : "";
6670 specs["inPtr"] = "outPtr";
6671 specsOffset["InOut"] = "In";
6672 specs["InOffsets"] = StringTemplate(isUniform ? getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD140) : getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6673 specsOffset["InOut"] = "Out";
6674 specs["OutOffsets"] = StringTemplate(getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6675
6676 fragments["capability"] = capabilities.specialize(specs);
6677 fragments["decoration"] = decoration.specialize(specs);
6678 fragments["pre_main"] = preMain.specialize(specs);
6679 fragments["testfun"] = testFun.specialize(specs);
6680
6681 resources.verifyIO = isUniform ? graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD140, SHADERTEMPLATE_STRIDEMIX_STD430> : graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD430, SHADERTEMPLATE_STRIDEMIX_STD430>;
6682 resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inData)), CAPABILITIES[capIdx].dtype));
6683 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6684
6685 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6686 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6687 features.coreFeatures.fragmentStoresAndAtomics = true;
6688
6689 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, group, features);
6690 }
6691 }
6692
addGraphics16BitStorageInputOutputFloat16To64Group(tcu::TestCaseGroup * testGroup)6693 void addGraphics16BitStorageInputOutputFloat16To64Group (tcu::TestCaseGroup* testGroup)
6694 {
6695 de::Random rnd (deStringHash(testGroup->getName()));
6696 RGBA defaultColors[4];
6697 vector<string> extensions;
6698 map<string, string> fragments = passthruFragments();
6699 const deUint32 numDataPoints = 64;
6700 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
6701 vector<double> float64Data;
6702
6703 float64Data.reserve(numDataPoints);
6704 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
6705 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
6706
6707 extensions.push_back("VK_KHR_16bit_storage");
6708
6709 fragments["capability"] =
6710 "OpCapability StorageInputOutput16\n"
6711 "OpCapability Float64\n";
6712 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
6713
6714 getDefaultColors(defaultColors);
6715
6716 struct Case
6717 {
6718 const char* name;
6719 const char* interfaceOpCall;
6720 const char* interfaceOpFunc;
6721 const char* preMain;
6722 const char* inputType;
6723 const char* outputType;
6724 deUint32 numPerCase;
6725 deUint32 numElements;
6726 };
6727
6728 Case cases[] =
6729 {
6730 { // Scalar cases
6731 "scalar",
6732
6733 "OpFConvert %f64",
6734 "",
6735
6736 " %f16 = OpTypeFloat 16\n"
6737 " %f64 = OpTypeFloat 64\n"
6738 " %v4f64 = OpTypeVector %f64 4\n"
6739 " %ip_f16 = OpTypePointer Input %f16\n"
6740 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
6741 " %ip_a3f16 = OpTypePointer Input %a3f16\n"
6742 "%f64_f16_function = OpTypeFunction %f64 %f16\n"
6743 " %a3f64 = OpTypeArray %f64 %c_i32_3\n"
6744 " %op_f64 = OpTypePointer Output %f64\n"
6745 " %op_a3f64 = OpTypePointer Output %a3f64\n",
6746
6747 "f16",
6748 "f64",
6749 4,
6750 1,
6751 },
6752 { // Vector cases
6753 "vector",
6754
6755 "OpFConvert %v2f64",
6756 "",
6757
6758 " %f16 = OpTypeFloat 16\n"
6759 " %v2f16 = OpTypeVector %f16 2\n"
6760 " %f64 = OpTypeFloat 64\n"
6761 " %v2f64 = OpTypeVector %f64 2\n"
6762 " %v4f64 = OpTypeVector %f64 4\n"
6763 " %ip_v2f16 = OpTypePointer Input %v2f16\n"
6764 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
6765 " %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
6766 "%v2f64_v2f16_function = OpTypeFunction %v2f64 %v2f16\n"
6767 " %a3v2f64 = OpTypeArray %v2f64 %c_i32_3\n"
6768 " %op_f64 = OpTypePointer Output %f64\n"
6769 " %op_v2f64 = OpTypePointer Output %v2f64\n"
6770 " %op_v4f64 = OpTypePointer Output %v4f64\n"
6771 " %op_a3v2f64 = OpTypePointer Output %a3v2f64\n",
6772
6773 "v2f16",
6774 "v2f64",
6775 2 * 4,
6776 2,
6777 }
6778 };
6779
6780 VulkanFeatures requiredFeatures;
6781
6782 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
6783 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
6784
6785 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
6786 {
6787 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
6788 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
6789 fragments["pre_main"] = cases[caseIdx].preMain;
6790
6791 fragments["input_type"] = cases[caseIdx].inputType;
6792 fragments["output_type"] = cases[caseIdx].outputType;
6793
6794 GraphicsInterfaces interfaces;
6795 const deUint32 numPerCase = cases[caseIdx].numPerCase;
6796 vector<deFloat16> subInputs (numPerCase);
6797 vector<double> subOutputs (numPerCase);
6798
6799 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
6800 {
6801 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
6802
6803 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
6804 {
6805 subInputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx];
6806 subOutputs[numNdx] = float64Data[caseNdx * numPerCase + numNdx];
6807 }
6808 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))),
6809 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT64), BufferSp(new Float64Buffer(subOutputs))));
6810 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
6811 }
6812 }
6813 }
6814
addGraphics16BitStorageUniformFloat16To64Group(tcu::TestCaseGroup * testGroup)6815 void addGraphics16BitStorageUniformFloat16To64Group (tcu::TestCaseGroup* testGroup)
6816 {
6817 de::Random rnd (deStringHash(testGroup->getName()));
6818 map<string, string> fragments;
6819 vector<string> extensions;
6820 const deUint32 numDataPoints = 256;
6821 RGBA defaultColors[4];
6822 const StringTemplate capabilities ("OpCapability ${cap}\n"
6823 "OpCapability Float64\n");
6824 vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints);
6825
6826 struct ConstantIndex
6827 {
6828 bool useConstantIndex;
6829 deUint32 constantIndex;
6830 };
6831
6832 ConstantIndex constantIndices[] =
6833 {
6834 { false, 0 },
6835 { true, 4 },
6836 { true, 5 },
6837 { true, 6 }
6838 };
6839
6840 extensions.push_back("VK_KHR_16bit_storage");
6841
6842 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6843
6844 getDefaultColors(defaultColors);
6845
6846 { // scalar cases
6847 const StringTemplate preMain (
6848 " %f16 = OpTypeFloat 16\n"
6849 " %f64 = OpTypeFloat 64\n"
6850 "%c_i32_256 = OpConstant %i32 256\n"
6851 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
6852 " %up_f64 = OpTypePointer Uniform %f64\n"
6853 " %up_f16 = OpTypePointer Uniform %f16\n"
6854 " %ra_f64 = OpTypeArray %f64 %c_i32_256\n"
6855 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
6856 " %SSBO64 = OpTypeStruct %ra_f64\n"
6857 " %SSBO16 = OpTypeStruct %ra_f16\n"
6858 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
6859 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
6860 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
6861 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
6862
6863 const StringTemplate decoration (
6864 "OpDecorate %ra_f64 ArrayStride 8\n"
6865 "OpDecorate %ra_f16 ArrayStride ${stride16}\n"
6866 "OpMemberDecorate %SSBO64 0 Offset 0\n"
6867 "OpMemberDecorate %SSBO16 0 Offset 0\n"
6868 "OpDecorate %SSBO64 BufferBlock\n"
6869 "OpDecorate %SSBO16 ${indecor}\n"
6870 "OpDecorate %ssbo64 DescriptorSet 0\n"
6871 "OpDecorate %ssbo16 DescriptorSet 0\n"
6872 "OpDecorate %ssbo64 Binding 1\n"
6873 "OpDecorate %ssbo16 Binding 0\n");
6874
6875 // ssbo64[] <- convert ssbo16[] to 64bit float
6876 const StringTemplate testFun (
6877 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6878 " %param = OpFunctionParameter %v4f32\n"
6879
6880 "%entry = OpLabel\n"
6881 " %i = OpVariable %fp_i32 Function\n"
6882 " OpStore %i %c_i32_0\n"
6883 " OpBranch %loop\n"
6884
6885 " %loop = OpLabel\n"
6886 " %15 = OpLoad %i32 %i\n"
6887 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
6888 " OpLoopMerge %merge %inc None\n"
6889 " OpBranchConditional %lt %write %merge\n"
6890
6891 "%write = OpLabel\n"
6892 " %30 = OpLoad %i32 %i\n"
6893 " %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
6894 "%val16 = OpLoad %f16 %src\n"
6895 "%val64 = OpFConvert %f64 %val16\n"
6896 " %dst = OpAccessChain %up_f64 %ssbo64 %c_i32_0 %30\n"
6897 " OpStore %dst %val64\n"
6898 " OpBranch %inc\n"
6899
6900 " %inc = OpLabel\n"
6901 " %37 = OpLoad %i32 %i\n"
6902 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
6903 " OpStore %i %39\n"
6904 " OpBranch %loop\n"
6905
6906 "%merge = OpLabel\n"
6907 " OpReturnValue %param\n"
6908
6909 "OpFunctionEnd\n");
6910
6911 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
6912 {
6913 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6914 {
6915 GraphicsResources resources;
6916 map<string, string> specs;
6917 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float";
6918 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
6919 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
6920 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6921
6922 specs["cap"] = CAPABILITIES[capIdx].cap;
6923 specs["indecor"] = CAPABILITIES[capIdx].decor;
6924 specs["constarrayidx"] = de::toString(constIdx);
6925 specs["stride16"] = isUBO ? "16" : "2";
6926
6927 if (useConstIdx)
6928 specs["arrayindex"] = "c_i32_ci";
6929 else
6930 specs["arrayindex"] = "30";
6931
6932 fragments["capability"] = capabilities.specialize(specs);
6933 fragments["decoration"] = decoration.specialize(specs);
6934 fragments["pre_main"] = preMain.specialize(specs);
6935 fragments["testfun"] = testFun.specialize(specs);
6936
6937 vector<double> float64Data;
6938 float64Data.reserve(numDataPoints);
6939 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
6940 float64Data.push_back(deFloat16To64(float16Data[useConstIdx ? constIdx : numIdx]));
6941
6942 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data, isUBO ? 14 : 0)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6943 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6944 resources.verifyIO = check64BitFloats;
6945 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
6946
6947 if (useConstIdx)
6948 testName += string("_const_idx_") + de::toString(constIdx);
6949
6950 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6951
6952 features.coreFeatures.shaderFloat64 = DE_TRUE;
6953
6954 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6955 }
6956 }
6957 }
6958
6959 { // vector cases
6960 const StringTemplate preMain (
6961 " %f16 = OpTypeFloat 16\n"
6962 " %f64 = OpTypeFloat 64\n"
6963 "%c_i32_128 = OpConstant %i32 128\n"
6964 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
6965 " %v2f16 = OpTypeVector %f16 2\n"
6966 " %v2f64 = OpTypeVector %f64 2\n"
6967 " %up_v2f64 = OpTypePointer Uniform %v2f64\n"
6968 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
6969 " %ra_v2f64 = OpTypeArray %v2f64 %c_i32_128\n"
6970 " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n"
6971 " %SSBO64 = OpTypeStruct %ra_v2f64\n"
6972 " %SSBO16 = OpTypeStruct %ra_v2f16\n"
6973 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
6974 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
6975 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
6976 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
6977
6978 const StringTemplate decoration (
6979 "OpDecorate %ra_v2f64 ArrayStride 16\n"
6980 "OpDecorate %ra_v2f16 ArrayStride ${stride16}\n"
6981 "OpMemberDecorate %SSBO64 0 Offset 0\n"
6982 "OpMemberDecorate %SSBO16 0 Offset 0\n"
6983 "OpDecorate %SSBO64 BufferBlock\n"
6984 "OpDecorate %SSBO16 ${indecor}\n"
6985 "OpDecorate %ssbo64 DescriptorSet 0\n"
6986 "OpDecorate %ssbo16 DescriptorSet 0\n"
6987 "OpDecorate %ssbo64 Binding 1\n"
6988 "OpDecorate %ssbo16 Binding 0\n");
6989
6990 // ssbo64[] <- convert ssbo16[] to 64bit float
6991 const StringTemplate testFun (
6992 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6993 " %param = OpFunctionParameter %v4f32\n"
6994
6995 "%entry = OpLabel\n"
6996 " %i = OpVariable %fp_i32 Function\n"
6997 " OpStore %i %c_i32_0\n"
6998 " OpBranch %loop\n"
6999
7000 " %loop = OpLabel\n"
7001 " %15 = OpLoad %i32 %i\n"
7002 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
7003 " OpLoopMerge %merge %inc None\n"
7004 " OpBranchConditional %lt %write %merge\n"
7005
7006 "%write = OpLabel\n"
7007 " %30 = OpLoad %i32 %i\n"
7008 " %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
7009 "%val16 = OpLoad %v2f16 %src\n"
7010 "%val64 = OpFConvert %v2f64 %val16\n"
7011 " %dst = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30\n"
7012 " OpStore %dst %val64\n"
7013 " OpBranch %inc\n"
7014
7015 " %inc = OpLabel\n"
7016 " %37 = OpLoad %i32 %i\n"
7017 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7018 " OpStore %i %39\n"
7019 " OpBranch %loop\n"
7020
7021 "%merge = OpLabel\n"
7022 " OpReturnValue %param\n"
7023
7024 "OpFunctionEnd\n");
7025
7026 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
7027 {
7028 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7029 {
7030 GraphicsResources resources;
7031 map<string, string> specs;
7032 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float";
7033 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
7034 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
7035 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7036
7037 specs["cap"] = CAPABILITIES[capIdx].cap;
7038 specs["indecor"] = CAPABILITIES[capIdx].decor;
7039 specs["constarrayidx"] = de::toString(constIdx);
7040 specs["stride16"] = isUBO ? "16" : "4";
7041
7042 if (useConstIdx)
7043 specs["arrayindex"] = "c_i32_ci";
7044 else
7045 specs["arrayindex"] = "30";
7046
7047 fragments["capability"] = capabilities.specialize(specs);
7048 fragments["decoration"] = decoration.specialize(specs);
7049 fragments["pre_main"] = preMain.specialize(specs);
7050 fragments["testfun"] = testFun.specialize(specs);
7051
7052 vector<double> float64Data;
7053 float64Data.reserve(numDataPoints);
7054 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7055 float64Data.push_back(deFloat16To64(float16Data[constantIndices[constIndexIdx].useConstantIndex ? (constantIndices[constIndexIdx].constantIndex * 2 + numIdx % 2) : numIdx]));
7056
7057 vector<tcu::Vector<deFloat16, 2> > float16Vec2Data(float16Data.size() / 2);
7058 for (size_t elemIdx = 0; elemIdx < float16Data.size(); elemIdx++)
7059 {
7060 float16Vec2Data[elemIdx / 2][elemIdx % 2] = float16Data[elemIdx];
7061 }
7062 typedef Buffer<tcu::Vector<deFloat16, 2> > Float16Vec2Buffer;
7063 resources.inputs.push_back(Resource(BufferSp(new Float16Vec2Buffer(float16Vec2Data, isUBO ? 12 : 0)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7064 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7065 resources.verifyIO = check64BitFloats;
7066 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
7067
7068 if (constantIndices[constIndexIdx].useConstantIndex)
7069 testName += string("_const_idx_") + de::toString(constantIndices[constIndexIdx].constantIndex);
7070
7071 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7072
7073 features.coreFeatures.shaderFloat64 = DE_TRUE;
7074
7075 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7076 }
7077 }
7078 }
7079
7080 { // matrix cases
7081 fragments["pre_main"] =
7082 " %c_i32_32 = OpConstant %i32 32\n"
7083 " %f16 = OpTypeFloat 16\n"
7084 " %f64 = OpTypeFloat 64\n"
7085 " %v2f16 = OpTypeVector %f16 2\n"
7086 " %v2f64 = OpTypeVector %f64 2\n"
7087 " %m4x2f64 = OpTypeMatrix %v2f64 4\n"
7088 " %m4x2f16 = OpTypeMatrix %v2f16 4\n"
7089 " %up_v2f64 = OpTypePointer Uniform %v2f64\n"
7090 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
7091 "%a8m4x2f64 = OpTypeArray %m4x2f64 %c_i32_32\n"
7092 "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n"
7093 " %SSBO64 = OpTypeStruct %a8m4x2f64\n"
7094 " %SSBO16 = OpTypeStruct %a8m4x2f16\n"
7095 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7096 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7097 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7098 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7099
7100 const StringTemplate decoration (
7101 "OpDecorate %a8m4x2f64 ArrayStride 64\n"
7102 "OpDecorate %a8m4x2f16 ArrayStride 16\n"
7103 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7104 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7105 "OpMemberDecorate %SSBO64 0 MatrixStride 16\n"
7106 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7107 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7108 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"
7109 "OpDecorate %SSBO64 BufferBlock\n"
7110 "OpDecorate %SSBO16 ${indecor}\n"
7111 "OpDecorate %ssbo64 DescriptorSet 0\n"
7112 "OpDecorate %ssbo16 DescriptorSet 0\n"
7113 "OpDecorate %ssbo64 Binding 1\n"
7114 "OpDecorate %ssbo16 Binding 0\n");
7115
7116 fragments["testfun"] =
7117 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7118 " %param = OpFunctionParameter %v4f32\n"
7119
7120 "%entry = OpLabel\n"
7121 " %i = OpVariable %fp_i32 Function\n"
7122 " OpStore %i %c_i32_0\n"
7123 " OpBranch %loop\n"
7124
7125 " %loop = OpLabel\n"
7126 " %15 = OpLoad %i32 %i\n"
7127 " %lt = OpSLessThan %bool %15 %c_i32_32\n"
7128 " OpLoopMerge %merge %inc None\n"
7129 " OpBranchConditional %lt %write %merge\n"
7130
7131 " %write = OpLabel\n"
7132 " %30 = OpLoad %i32 %i\n"
7133 " %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
7134 " %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
7135 " %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
7136 " %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
7137 "%val16_0 = OpLoad %v2f16 %src_0\n"
7138 "%val16_1 = OpLoad %v2f16 %src_1\n"
7139 "%val16_2 = OpLoad %v2f16 %src_2\n"
7140 "%val16_3 = OpLoad %v2f16 %src_3\n"
7141 "%val64_0 = OpFConvert %v2f64 %val16_0\n"
7142 "%val64_1 = OpFConvert %v2f64 %val16_1\n"
7143 "%val64_2 = OpFConvert %v2f64 %val16_2\n"
7144 "%val64_3 = OpFConvert %v2f64 %val16_3\n"
7145 " %dst_0 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_0\n"
7146 " %dst_1 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7147 " %dst_2 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_2\n"
7148 " %dst_3 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_3\n"
7149 " OpStore %dst_0 %val64_0\n"
7150 " OpStore %dst_1 %val64_1\n"
7151 " OpStore %dst_2 %val64_2\n"
7152 " OpStore %dst_3 %val64_3\n"
7153 " OpBranch %inc\n"
7154
7155 " %inc = OpLabel\n"
7156 " %37 = OpLoad %i32 %i\n"
7157 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7158 " OpStore %i %39\n"
7159 " OpBranch %loop\n"
7160
7161 "%merge = OpLabel\n"
7162 " OpReturnValue %param\n"
7163
7164 "OpFunctionEnd\n";
7165
7166 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7167 {
7168 GraphicsResources resources;
7169 map<string, string> specs;
7170 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float";
7171
7172 specs["cap"] = CAPABILITIES[capIdx].cap;
7173 specs["indecor"] = CAPABILITIES[capIdx].decor;
7174
7175 fragments["capability"] = capabilities.specialize(specs);
7176 fragments["decoration"] = decoration.specialize(specs);
7177
7178 vector<double> float64Data;
7179 float64Data.reserve(numDataPoints);
7180 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7181 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
7182
7183 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7184 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7185 resources.verifyIO = check64BitFloats;
7186 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
7187
7188 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7189
7190 features.coreFeatures.shaderFloat64 = DE_TRUE;
7191
7192 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7193 }
7194 }
7195 }
7196
addGraphics16BitStoragePushConstantFloat16To64Group(tcu::TestCaseGroup * testGroup)7197 void addGraphics16BitStoragePushConstantFloat16To64Group (tcu::TestCaseGroup* testGroup)
7198 {
7199 de::Random rnd (deStringHash(testGroup->getName()));
7200 map<string, string> fragments;
7201 RGBA defaultColors[4];
7202 vector<string> extensions;
7203 GraphicsResources resources;
7204 PushConstants pcs;
7205 const deUint32 numDataPoints = 64;
7206 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
7207 vector<double> float64Data;
7208 VulkanFeatures requiredFeatures;
7209
7210 float64Data.reserve(numDataPoints);
7211 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7212 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
7213
7214 extensions.push_back("VK_KHR_16bit_storage");
7215
7216 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
7217 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
7218
7219 fragments["capability"] =
7220 "OpCapability StoragePushConstant16\n"
7221 "OpCapability Float64\n";
7222
7223 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
7224
7225 pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data)));
7226 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7227 resources.verifyIO = check64BitFloats;
7228
7229 getDefaultColors(defaultColors);
7230
7231 const StringTemplate testFun (
7232 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7233 " %param = OpFunctionParameter %v4f32\n"
7234
7235 "%entry = OpLabel\n"
7236 " %i = OpVariable %fp_i32 Function\n"
7237 " OpStore %i %c_i32_0\n"
7238 " OpBranch %loop\n"
7239
7240 " %loop = OpLabel\n"
7241 " %15 = OpLoad %i32 %i\n"
7242 " %lt = OpSLessThan %bool %15 ${count}\n"
7243 " OpLoopMerge %merge %inc None\n"
7244 " OpBranchConditional %lt %write %merge\n"
7245
7246 "%write = OpLabel\n"
7247 " %30 = OpLoad %i32 %i\n"
7248 " %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %30 ${index0:opt}\n"
7249 "%val16 = OpLoad ${f_type16} %src\n"
7250 "%val64 = OpFConvert ${f_type64} %val16\n"
7251 " %dst = OpAccessChain ${up_type64} %ssbo64 %c_i32_0 %30 ${index0:opt}\n"
7252 " OpStore %dst %val64\n"
7253
7254 "${store:opt}\n"
7255
7256 " OpBranch %inc\n"
7257
7258 " %inc = OpLabel\n"
7259 " %37 = OpLoad %i32 %i\n"
7260 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7261 " OpStore %i %39\n"
7262 " OpBranch %loop\n"
7263
7264 "%merge = OpLabel\n"
7265 " OpReturnValue %param\n"
7266
7267 "OpFunctionEnd\n");
7268
7269 { // Scalar cases
7270 fragments["pre_main"] =
7271 " %f16 = OpTypeFloat 16\n"
7272 " %f64 = OpTypeFloat 64\n"
7273 " %c_i32_64 = OpConstant %i32 64\n" // Should be the same as numDataPoints
7274 " %v4f64 = OpTypeVector %f64 4\n"
7275 " %a64f16 = OpTypeArray %f16 %c_i32_64\n"
7276 " %a64f64 = OpTypeArray %f64 %c_i32_64\n"
7277 " %pp_f16 = OpTypePointer PushConstant %f16\n"
7278 " %up_f64 = OpTypePointer Uniform %f64\n"
7279 " %SSBO64 = OpTypeStruct %a64f64\n"
7280 " %up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7281 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7282 " %PC16 = OpTypeStruct %a64f16\n"
7283 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7284 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7285
7286 fragments["decoration"] =
7287 "OpDecorate %a64f16 ArrayStride 2\n"
7288 "OpDecorate %a64f64 ArrayStride 8\n"
7289 "OpDecorate %SSBO64 BufferBlock\n"
7290 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7291 "OpDecorate %PC16 Block\n"
7292 "OpMemberDecorate %PC16 0 Offset 0\n"
7293 "OpDecorate %ssbo64 DescriptorSet 0\n"
7294 "OpDecorate %ssbo64 Binding 0\n";
7295
7296 map<string, string> specs;
7297
7298 specs["count"] = "%c_i32_64";
7299 specs["pp_type16"] = "%pp_f16";
7300 specs["f_type16"] = "%f16";
7301 specs["f_type64"] = "%f64";
7302 specs["up_type64"] = "%up_f64";
7303
7304 fragments["testfun"] = testFun.specialize(specs);
7305
7306 createTestsForAllStages("scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7307 }
7308
7309 { // Vector cases
7310 fragments["pre_main"] =
7311 " %f16 = OpTypeFloat 16\n"
7312 " %f64 = OpTypeFloat 64\n"
7313 " %v4f16 = OpTypeVector %f16 4\n"
7314 " %v4f64 = OpTypeVector %f64 4\n"
7315 " %v2f64 = OpTypeVector %f64 2\n"
7316 " %c_i32_16 = OpConstant %i32 16\n"
7317 " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n"
7318 " %a16v4f64 = OpTypeArray %v4f64 %c_i32_16\n"
7319 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
7320 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7321 " %SSBO64 = OpTypeStruct %a16v4f64\n"
7322 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7323 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7324 " %PC16 = OpTypeStruct %a16v4f16\n"
7325 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7326 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7327
7328 fragments["decoration"] =
7329 "OpDecorate %a16v4f16 ArrayStride 8\n"
7330 "OpDecorate %a16v4f64 ArrayStride 32\n"
7331 "OpDecorate %SSBO64 BufferBlock\n"
7332 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7333 "OpDecorate %PC16 Block\n"
7334 "OpMemberDecorate %PC16 0 Offset 0\n"
7335 "OpDecorate %ssbo64 DescriptorSet 0\n"
7336 "OpDecorate %ssbo64 Binding 0\n";
7337
7338 map<string, string> specs;
7339
7340 specs["count"] = "%c_i32_16";
7341 specs["pp_type16"] = "%pp_v4f16";
7342 specs["f_type16"] = "%v4f16";
7343 specs["f_type64"] = "%v4f64";
7344 specs["up_type64"] = "%up_v4f64";
7345
7346 fragments["testfun"] = testFun.specialize(specs);
7347
7348 createTestsForAllStages("vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7349 }
7350
7351 { // Matrix cases
7352 fragments["pre_main"] =
7353 " %c_i32_8 = OpConstant %i32 8\n"
7354 " %f16 = OpTypeFloat 16\n"
7355 " %v4f16 = OpTypeVector %f16 4\n"
7356 " %f64 = OpTypeFloat 64\n"
7357 " %v4f64 = OpTypeVector %f64 4\n"
7358 " %m2v4f16 = OpTypeMatrix %v4f16 2\n"
7359 " %m2v4f64 = OpTypeMatrix %v4f64 2\n"
7360 "%a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n"
7361 "%a8m2v4f64 = OpTypeArray %m2v4f64 %c_i32_8\n"
7362 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
7363 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7364 " %SSBO64 = OpTypeStruct %a8m2v4f64\n"
7365 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7366 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7367 " %PC16 = OpTypeStruct %a8m2v4f16\n"
7368 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7369 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7370
7371 fragments["decoration"] =
7372 "OpDecorate %a8m2v4f16 ArrayStride 16\n"
7373 "OpDecorate %a8m2v4f64 ArrayStride 64\n"
7374 "OpDecorate %SSBO64 BufferBlock\n"
7375 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7376 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7377 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7378 "OpDecorate %PC16 Block\n"
7379 "OpMemberDecorate %PC16 0 Offset 0\n"
7380 "OpMemberDecorate %PC16 0 ColMajor\n"
7381 "OpMemberDecorate %PC16 0 MatrixStride 8\n"
7382 "OpDecorate %ssbo64 DescriptorSet 0\n"
7383 "OpDecorate %ssbo64 Binding 0\n";
7384
7385 map<string, string> specs;
7386
7387 specs["count"] = "%c_i32_8";
7388 specs["pp_type16"] = "%pp_v4f16";
7389 specs["up_type64"] = "%up_v4f64";
7390 specs["f_type16"] = "%v4f16";
7391 specs["f_type64"] = "%v4f64";
7392 specs["index0"] = "%c_i32_0";
7393 specs["store"] =
7394 " %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %30 %c_i32_1\n"
7395 "%val16_1 = OpLoad %v4f16 %src_1\n"
7396 "%val64_1 = OpFConvert %v4f64 %val16_1\n"
7397 " %dst_1 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7398 " OpStore %dst_1 %val64_1\n";
7399
7400 fragments["testfun"] = testFun.specialize(specs);
7401
7402 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7403 }
7404 }
7405
addCompute16bitStorageUniform64To16Group(tcu::TestCaseGroup * group)7406 void addCompute16bitStorageUniform64To16Group (tcu::TestCaseGroup* group)
7407 {
7408 tcu::TestContext& testCtx = group->getTestContext();
7409 de::Random rnd (deStringHash(group->getName()));
7410 const int numElements = 128;
7411
7412 const StringTemplate shaderTemplate (
7413 "OpCapability Shader\n"
7414 "OpCapability ${capability}\n"
7415 "OpCapability Float64\n"
7416 "OpExtension \"SPV_KHR_16bit_storage\"\n"
7417 "OpMemoryModel Logical GLSL450\n"
7418 "OpEntryPoint GLCompute %main \"main\" %id\n"
7419 "OpExecutionMode %main LocalSize 1 1 1\n"
7420 "OpDecorate %id BuiltIn GlobalInvocationId\n"
7421
7422 "${stride}\n"
7423
7424 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7425 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7426 "OpDecorate %SSBO64 ${storage}\n"
7427 "OpDecorate %SSBO16 BufferBlock\n"
7428 "OpDecorate %ssbo64 DescriptorSet 0\n"
7429 "OpDecorate %ssbo16 DescriptorSet 0\n"
7430 "OpDecorate %ssbo64 Binding 0\n"
7431 "OpDecorate %ssbo16 Binding 1\n"
7432
7433 "${matrix_decor:opt}\n"
7434
7435 "${rounding:opt}\n"
7436
7437 "%bool = OpTypeBool\n"
7438 "%void = OpTypeVoid\n"
7439 "%voidf = OpTypeFunction %void\n"
7440 "%u32 = OpTypeInt 32 0\n"
7441 "%i32 = OpTypeInt 32 1\n"
7442 "%f32 = OpTypeFloat 32\n"
7443 "%f64 = OpTypeFloat 64\n"
7444 "%uvec3 = OpTypeVector %u32 3\n"
7445 "%fvec3 = OpTypeVector %f32 3\n"
7446 "%uvec3ptr = OpTypePointer Input %uvec3\n"
7447 "%i32ptr = OpTypePointer Uniform %i32\n"
7448 "%f64ptr = OpTypePointer Uniform %f64\n"
7449
7450 "%zero = OpConstant %i32 0\n"
7451 "%c_i32_1 = OpConstant %i32 1\n"
7452 "%c_i32_16 = OpConstant %i32 16\n"
7453 "%c_i32_32 = OpConstant %i32 32\n"
7454 "%c_i32_64 = OpConstant %i32 64\n"
7455 "%c_i32_128 = OpConstant %i32 128\n"
7456
7457 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
7458 "%f64arr = OpTypeArray %f64 %c_i32_128\n"
7459
7460 "${types}\n"
7461 "${matrix_types:opt}\n"
7462
7463 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
7464 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
7465 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7466 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7467 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7468 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
7469
7470 "%id = OpVariable %uvec3ptr Input\n"
7471
7472 "%main = OpFunction %void None %voidf\n"
7473 "%label = OpLabel\n"
7474 "%idval = OpLoad %uvec3 %id\n"
7475 "%x = OpCompositeExtract %u32 %idval 0\n"
7476 "%inloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
7477 "%val64 = OpLoad %${base64} %inloc\n"
7478 "%val16 = ${convert} %${base16} %val64\n"
7479 "%outloc = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n"
7480 " OpStore %outloc %val16\n"
7481 "${matrix_store:opt}\n"
7482 " OpReturn\n"
7483 " OpFunctionEnd\n");
7484
7485 { // Floats
7486 const char floatTypes[] =
7487 "%f16 = OpTypeFloat 16\n"
7488 "%f16ptr = OpTypePointer Uniform %f16\n"
7489 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
7490 "%v4f16 = OpTypeVector %f16 4\n"
7491 "%v4f64 = OpTypeVector %f64 4\n"
7492 "%v4f16ptr = OpTypePointer Uniform %v4f16\n"
7493 "%v4f64ptr = OpTypePointer Uniform %v4f64\n"
7494 "%v4f16arr = OpTypeArray %v4f16 %c_i32_32\n"
7495 "%v4f64arr = OpTypeArray %v4f64 %c_i32_32\n";
7496
7497 struct RndMode
7498 {
7499 const char* name;
7500 const char* decor;
7501 VerifyIOFunc func;
7502 };
7503
7504 const RndMode rndModes[] =
7505 {
7506 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", computeCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7507 {"rte", "OpDecorate %val16 FPRoundingMode RTE", computeCheck16BitFloats64<ROUNDINGMODE_RTE>},
7508 {"unspecified_rnd_mode", "", computeCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7509 };
7510
7511 struct CompositeType
7512 {
7513 const char* name;
7514 const char* base64;
7515 const char* base16;
7516 const char* strideStr;
7517 const char* stride64UBO;
7518 unsigned padding64UBO;
7519 const char* stride64SSBO;
7520 unsigned padding64SSBO;
7521 unsigned count;
7522 };
7523
7524 const CompositeType cTypes[] =
7525 {
7526 {"scalar", "f64", "f16", "OpDecorate %f16arr ArrayStride 2\nOpDecorate %f64arr ArrayStride ", "16", 8, "8", 0, numElements},
7527 {"vector", "v4f64", "v4f16", "OpDecorate %v4f16arr ArrayStride 8\nOpDecorate %v4f64arr ArrayStride ", "32", 0, "32", 0, numElements / 4},
7528 {"matrix", "v4f64", "v4f16", "OpDecorate %m2v4f16arr ArrayStride 16\nOpDecorate %m2v4f64arr ArrayStride ", "64", 0, "64", 0, numElements / 8},
7529 };
7530
7531 vector<double> float64Data = getFloat64s(rnd, numElements);
7532 vector<deFloat16> float16UnusedData (numElements, 0);
7533
7534 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7535 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
7536 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7537 {
7538 ComputeShaderSpec spec;
7539 map<string, string> specs;
7540 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float_" + rndModes[rndModeIdx].name;
7541 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7542
7543 specs["capability"] = CAPABILITIES[capIdx].cap;
7544 specs["storage"] = CAPABILITIES[capIdx].decor;
7545 specs["stride"] = cTypes[tyIdx].strideStr;
7546 specs["base64"] = cTypes[tyIdx].base64;
7547 specs["base16"] = cTypes[tyIdx].base16;
7548 specs["rounding"] = rndModes[rndModeIdx].decor;
7549 specs["types"] = floatTypes;
7550 specs["convert"] = "OpFConvert";
7551
7552 if (isUBO)
7553 specs["stride"] += cTypes[tyIdx].stride64UBO;
7554 else
7555 specs["stride"] += cTypes[tyIdx].stride64SSBO;
7556
7557 if (deStringEqual(cTypes[tyIdx].name, "matrix"))
7558 {
7559 if (strcmp(rndModes[rndModeIdx].name, "rtz") == 0)
7560 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTZ\n";
7561 else if (strcmp(rndModes[rndModeIdx].name, "rte") == 0)
7562 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTE\n";
7563
7564 specs["index0"] = "%zero";
7565 specs["matrix_prefix"] = "m2";
7566 specs["matrix_types"] =
7567 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
7568 "%m2v4f64 = OpTypeMatrix %v4f64 2\n"
7569 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_16\n"
7570 "%m2v4f64arr = OpTypeArray %m2v4f64 %c_i32_16\n";
7571 specs["matrix_decor"] =
7572 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7573 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7574 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7575 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n";
7576 specs["matrix_store"] =
7577 "%inloc_1 = OpAccessChain %v4f64ptr %ssbo64 %zero %x %c_i32_1\n"
7578 "%val64_1 = OpLoad %v4f64 %inloc_1\n"
7579 "%val16_1 = OpFConvert %v4f16 %val64_1\n"
7580 "%outloc_1 = OpAccessChain %v4f16ptr %ssbo16 %zero %x %c_i32_1\n"
7581 " OpStore %outloc_1 %val16_1\n";
7582 }
7583
7584 spec.assembly = shaderTemplate.specialize(specs);
7585 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
7586 spec.verifyIO = rndModes[rndModeIdx].func;
7587 const unsigned padding = isUBO ? cTypes[tyIdx].padding64UBO : cTypes[tyIdx].padding64SSBO;
7588
7589 spec.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data, padding)), CAPABILITIES[capIdx].dtype));
7590
7591 // We provided a custom verifyIO in the above in which inputs will be used for checking.
7592 // So put unused data in the expected values.
7593 spec.outputs.push_back(BufferSp(new Float16Buffer(float16UnusedData)));
7594
7595 spec.extensions.push_back("VK_KHR_16bit_storage");
7596
7597 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7598 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
7599
7600 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
7601 }
7602 }
7603 }
7604
addGraphics16BitStorageUniformFloat64To16Group(tcu::TestCaseGroup * testGroup)7605 void addGraphics16BitStorageUniformFloat64To16Group (tcu::TestCaseGroup* testGroup)
7606 {
7607 de::Random rnd (deStringHash(testGroup->getName()));
7608 map<string, string> fragments;
7609 GraphicsResources resources;
7610 vector<string> extensions;
7611 const deUint32 numDataPoints = 256;
7612 RGBA defaultColors[4];
7613 vector<double> float64Data = getFloat64s(rnd, numDataPoints);
7614 vector<deFloat16> float16UnusedData (numDataPoints, 0);
7615 const StringTemplate capabilities ("OpCapability Float64\n"
7616 "OpCapability ${cap}\n");
7617 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
7618 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7619
7620 extensions.push_back("VK_KHR_16bit_storage");
7621
7622 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
7623
7624 struct RndMode
7625 {
7626 const char* name;
7627 const char* decor;
7628 VerifyIOFunc f;
7629 };
7630
7631 getDefaultColors(defaultColors);
7632
7633 { // scalar cases
7634 fragments["pre_main"] =
7635 " %f16 = OpTypeFloat 16\n"
7636 " %f64 = OpTypeFloat 64\n"
7637 "%c_i32_256 = OpConstant %i32 256\n"
7638 " %up_f64 = OpTypePointer Uniform %f64\n"
7639 " %up_f16 = OpTypePointer Uniform %f16\n"
7640 " %ra_f64 = OpTypeArray %f64 %c_i32_256\n"
7641 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
7642 " %SSBO64 = OpTypeStruct %ra_f64\n"
7643 " %SSBO16 = OpTypeStruct %ra_f16\n"
7644 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7645 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7646 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7647 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7648
7649 const StringTemplate decoration (
7650 "OpDecorate %ra_f64 ArrayStride ${stride64}\n"
7651 "OpDecorate %ra_f16 ArrayStride 2\n"
7652 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7653 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7654 "OpDecorate %SSBO64 ${indecor}\n"
7655 "OpDecorate %SSBO16 BufferBlock\n"
7656 "OpDecorate %ssbo64 DescriptorSet 0\n"
7657 "OpDecorate %ssbo16 DescriptorSet 0\n"
7658 "OpDecorate %ssbo64 Binding 0\n"
7659 "OpDecorate %ssbo16 Binding 1\n"
7660 "${rounddecor}\n");
7661
7662 fragments["testfun"] =
7663 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7664 " %param = OpFunctionParameter %v4f32\n"
7665
7666 "%entry = OpLabel\n"
7667 " %i = OpVariable %fp_i32 Function\n"
7668 " OpStore %i %c_i32_0\n"
7669 " OpBranch %loop\n"
7670
7671 " %loop = OpLabel\n"
7672 " %15 = OpLoad %i32 %i\n"
7673 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
7674 " OpLoopMerge %merge %inc None\n"
7675 " OpBranchConditional %lt %write %merge\n"
7676
7677 "%write = OpLabel\n"
7678 " %30 = OpLoad %i32 %i\n"
7679 " %src = OpAccessChain %up_f64 %ssbo64 %c_i32_0 %30\n"
7680 "%val64 = OpLoad %f64 %src\n"
7681 "%val16 = OpFConvert %f16 %val64\n"
7682 " %dst = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n"
7683 " OpStore %dst %val16\n"
7684 " OpBranch %inc\n"
7685
7686 " %inc = OpLabel\n"
7687 " %37 = OpLoad %i32 %i\n"
7688 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7689 " OpStore %i %39\n"
7690 " OpBranch %loop\n"
7691
7692 "%merge = OpLabel\n"
7693 " OpReturnValue %param\n"
7694
7695 "OpFunctionEnd\n";
7696
7697 const RndMode rndModes[] =
7698 {
7699 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7700 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7701 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7702 };
7703
7704 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7705 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7706 {
7707 map<string, string> specs;
7708 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float_" + rndModes[rndModeIdx].name;
7709 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7710 VulkanFeatures features;
7711
7712 specs["cap"] = CAPABILITIES[capIdx].cap;
7713 specs["indecor"] = CAPABILITIES[capIdx].decor;
7714 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7715 specs["stride64"] = isUBO ? "16" : "8";
7716
7717 fragments["capability"] = capabilities.specialize(specs);
7718 fragments["decoration"] = decoration.specialize(specs);
7719
7720 resources.inputs.clear();
7721 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data, isUBO ? 8 : 0)), CAPABILITIES[capIdx].dtype));
7722
7723 resources.verifyIO = rndModes[rndModeIdx].f;
7724
7725 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7726 features.coreFeatures.shaderFloat64 = DE_TRUE;
7727
7728
7729 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7730 }
7731 }
7732
7733 { // vector cases
7734 fragments["pre_main"] =
7735 " %f16 = OpTypeFloat 16\n"
7736 " %f64 = OpTypeFloat 64\n"
7737 " %c_i32_64 = OpConstant %i32 64\n"
7738 " %v4f16 = OpTypeVector %f16 4\n"
7739 " %v4f64 = OpTypeVector %f64 4\n"
7740 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7741 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
7742 " %ra_v4f64 = OpTypeArray %v4f64 %c_i32_64\n"
7743 " %ra_v4f16 = OpTypeArray %v4f16 %c_i32_64\n"
7744 " %SSBO64 = OpTypeStruct %ra_v4f64\n"
7745 " %SSBO16 = OpTypeStruct %ra_v4f16\n"
7746 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7747 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7748 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7749 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7750
7751 const StringTemplate decoration (
7752 "OpDecorate %ra_v4f64 ArrayStride 32\n"
7753 "OpDecorate %ra_v4f16 ArrayStride 8\n"
7754 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7755 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7756 "OpDecorate %SSBO64 ${indecor}\n"
7757 "OpDecorate %SSBO16 BufferBlock\n"
7758 "OpDecorate %ssbo64 DescriptorSet 0\n"
7759 "OpDecorate %ssbo16 DescriptorSet 0\n"
7760 "OpDecorate %ssbo64 Binding 0\n"
7761 "OpDecorate %ssbo16 Binding 1\n"
7762 "${rounddecor}\n");
7763
7764 // ssbo16[] <- convert ssbo64[] to 16bit float
7765 fragments["testfun"] =
7766 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7767 " %param = OpFunctionParameter %v4f32\n"
7768
7769 "%entry = OpLabel\n"
7770 " %i = OpVariable %fp_i32 Function\n"
7771 " OpStore %i %c_i32_0\n"
7772 " OpBranch %loop\n"
7773
7774 " %loop = OpLabel\n"
7775 " %15 = OpLoad %i32 %i\n"
7776 " %lt = OpSLessThan %bool %15 %c_i32_64\n"
7777 " OpLoopMerge %merge %inc None\n"
7778 " OpBranchConditional %lt %write %merge\n"
7779
7780 "%write = OpLabel\n"
7781 " %30 = OpLoad %i32 %i\n"
7782 " %src = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30\n"
7783 "%val64 = OpLoad %v4f64 %src\n"
7784 "%val16 = OpFConvert %v4f16 %val64\n"
7785 " %dst = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30\n"
7786 " OpStore %dst %val16\n"
7787 " OpBranch %inc\n"
7788
7789 " %inc = OpLabel\n"
7790 " %37 = OpLoad %i32 %i\n"
7791 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7792 " OpStore %i %39\n"
7793 " OpBranch %loop\n"
7794
7795 "%merge = OpLabel\n"
7796 " OpReturnValue %param\n"
7797
7798 "OpFunctionEnd\n";
7799
7800 const RndMode rndModes[] =
7801 {
7802 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7803 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7804 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7805 };
7806
7807 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7808 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7809 {
7810 map<string, string> specs;
7811 VulkanFeatures features;
7812 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float_" + rndModes[rndModeIdx].name;
7813
7814 specs["cap"] = CAPABILITIES[capIdx].cap;
7815 specs["indecor"] = CAPABILITIES[capIdx].decor;
7816 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7817
7818 fragments["capability"] = capabilities.specialize(specs);
7819 fragments["decoration"] = decoration.specialize(specs);
7820
7821 resources.inputs.clear();
7822 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), CAPABILITIES[capIdx].dtype));
7823 resources.verifyIO = rndModes[rndModeIdx].f;
7824
7825 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7826 features.coreFeatures.shaderFloat64 = DE_TRUE;
7827
7828 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7829 }
7830 }
7831
7832 { // matrix cases
7833 fragments["pre_main"] =
7834 " %f16 = OpTypeFloat 16\n"
7835 " %f64 = OpTypeFloat 64\n"
7836 " %c_i32_16 = OpConstant %i32 16\n"
7837 " %v4f16 = OpTypeVector %f16 4\n"
7838 " %v4f64 = OpTypeVector %f64 4\n"
7839 " %m4x4f64 = OpTypeMatrix %v4f64 4\n"
7840 " %m4x4f16 = OpTypeMatrix %v4f16 4\n"
7841 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7842 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
7843 "%a16m4x4f64 = OpTypeArray %m4x4f64 %c_i32_16\n"
7844 "%a16m4x4f16 = OpTypeArray %m4x4f16 %c_i32_16\n"
7845 " %SSBO64 = OpTypeStruct %a16m4x4f64\n"
7846 " %SSBO16 = OpTypeStruct %a16m4x4f16\n"
7847 " %up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7848 " %up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7849 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7850 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7851
7852 const StringTemplate decoration (
7853 "OpDecorate %a16m4x4f64 ArrayStride 128\n"
7854 "OpDecorate %a16m4x4f16 ArrayStride 32\n"
7855 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7856 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7857 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7858 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7859 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7860 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n"
7861 "OpDecorate %SSBO64 ${indecor}\n"
7862 "OpDecorate %SSBO16 BufferBlock\n"
7863 "OpDecorate %ssbo64 DescriptorSet 0\n"
7864 "OpDecorate %ssbo16 DescriptorSet 0\n"
7865 "OpDecorate %ssbo64 Binding 0\n"
7866 "OpDecorate %ssbo16 Binding 1\n"
7867 "${rounddecor}\n");
7868
7869 fragments["testfun"] =
7870 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7871 " %param = OpFunctionParameter %v4f32\n"
7872
7873 "%entry = OpLabel\n"
7874 " %i = OpVariable %fp_i32 Function\n"
7875 " OpStore %i %c_i32_0\n"
7876 " OpBranch %loop\n"
7877
7878 " %loop = OpLabel\n"
7879 " %15 = OpLoad %i32 %i\n"
7880 " %lt = OpSLessThan %bool %15 %c_i32_16\n"
7881 " OpLoopMerge %merge %inc None\n"
7882 " OpBranchConditional %lt %write %merge\n"
7883
7884 " %write = OpLabel\n"
7885 " %30 = OpLoad %i32 %i\n"
7886 " %src_0 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_0\n"
7887 " %src_1 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7888 " %src_2 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_2\n"
7889 " %src_3 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_3\n"
7890 "%val64_0 = OpLoad %v4f64 %src_0\n"
7891 "%val64_1 = OpLoad %v4f64 %src_1\n"
7892 "%val64_2 = OpLoad %v4f64 %src_2\n"
7893 "%val64_3 = OpLoad %v4f64 %src_3\n"
7894 "%val16_0 = OpFConvert %v4f16 %val64_0\n"
7895 "%val16_1 = OpFConvert %v4f16 %val64_1\n"
7896 "%val16_2 = OpFConvert %v4f16 %val64_2\n"
7897 "%val16_3 = OpFConvert %v4f16 %val64_3\n"
7898 " %dst_0 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
7899 " %dst_1 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
7900 " %dst_2 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
7901 " %dst_3 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
7902 " OpStore %dst_0 %val16_0\n"
7903 " OpStore %dst_1 %val16_1\n"
7904 " OpStore %dst_2 %val16_2\n"
7905 " OpStore %dst_3 %val16_3\n"
7906 " OpBranch %inc\n"
7907
7908 " %inc = OpLabel\n"
7909 " %37 = OpLoad %i32 %i\n"
7910 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7911 " OpStore %i %39\n"
7912 " OpBranch %loop\n"
7913
7914 "%merge = OpLabel\n"
7915 " OpReturnValue %param\n"
7916
7917 "OpFunctionEnd\n";
7918
7919 const RndMode rndModes[] =
7920 {
7921 {"rte", "OpDecorate %val16_0 FPRoundingMode RTE\nOpDecorate %val16_1 FPRoundingMode RTE\nOpDecorate %val16_2 FPRoundingMode RTE\nOpDecorate %val16_3 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7922 {"rtz", "OpDecorate %val16_0 FPRoundingMode RTZ\nOpDecorate %val16_1 FPRoundingMode RTZ\nOpDecorate %val16_2 FPRoundingMode RTZ\nOpDecorate %val16_3 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7923 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7924 };
7925
7926 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7927 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7928 {
7929 map<string, string> specs;
7930 VulkanFeatures features;
7931 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float_" + rndModes[rndModeIdx].name;
7932
7933 specs["cap"] = CAPABILITIES[capIdx].cap;
7934 specs["indecor"] = CAPABILITIES[capIdx].decor;
7935 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7936
7937 fragments["capability"] = capabilities.specialize(specs);
7938 fragments["decoration"] = decoration.specialize(specs);
7939
7940 resources.inputs.clear();
7941 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), CAPABILITIES[capIdx].dtype));
7942 resources.verifyIO = rndModes[rndModeIdx].f;
7943
7944 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7945 features.coreFeatures.shaderFloat64 = DE_TRUE;
7946
7947 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7948 }
7949 }
7950 }
7951
addGraphics16BitStorageInputOutputFloat64To16Group(tcu::TestCaseGroup * testGroup)7952 void addGraphics16BitStorageInputOutputFloat64To16Group (tcu::TestCaseGroup* testGroup)
7953 {
7954 de::Random rnd (deStringHash(testGroup->getName()));
7955 RGBA defaultColors[4];
7956 vector<string> extensions;
7957 map<string, string> fragments = passthruFragments();
7958 const deUint32 numDataPoints = 64;
7959 // Special values like inf/nan/denormal may not be preserved when float control features are not provided,
7960 // thus values generating special float16 values must be excluded in input data here.
7961 vector<double> float64Data = getFloat64s(rnd, numDataPoints, DE_FALSE);
7962
7963 extensions.push_back("VK_KHR_16bit_storage");
7964
7965 fragments["capability"] =
7966 "OpCapability StorageInputOutput16\n"
7967 "OpCapability Float64\n";
7968 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
7969
7970 getDefaultColors(defaultColors);
7971
7972 struct RndMode
7973 {
7974 const char* name;
7975 const char* decor;
7976 const char* decor_tessc;
7977 RoundingModeFlags flags;
7978 };
7979
7980 const RndMode rndModes[] =
7981 {
7982 {"rtz",
7983 "OpDecorate %ret0 FPRoundingMode RTZ\n",
7984 "OpDecorate %ret1 FPRoundingMode RTZ\n"
7985 "OpDecorate %ret2 FPRoundingMode RTZ\n",
7986 ROUNDINGMODE_RTZ},
7987 {"rte",
7988 "OpDecorate %ret0 FPRoundingMode RTE\n",
7989 "OpDecorate %ret1 FPRoundingMode RTE\n"
7990 "OpDecorate %ret2 FPRoundingMode RTE\n",
7991 ROUNDINGMODE_RTE},
7992 {"unspecified_rnd_mode", "", "", RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)},
7993 };
7994
7995 struct Case
7996 {
7997 const char* name;
7998 const char* interfaceOpCall;
7999 const char* interfaceOpFunc;
8000 const char* postInterfaceOp;
8001 const char* postInterfaceOpGeom;
8002 const char* postInterfaceOpTessc;
8003 const char* preMain;
8004 const char* inputType;
8005 const char* outputType;
8006 deUint32 numPerCase;
8007 deUint32 numElements;
8008 };
8009
8010 const Case cases[] =
8011 {
8012 { // Scalar cases
8013 "scalar",
8014
8015 "OpFConvert %f16",
8016
8017 "",
8018
8019 " %ret0 = OpFConvert %f16 %IF_input_val\n"
8020 " OpStore %IF_output %ret0\n",
8021
8022 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
8023 " OpStore %IF_output %ret0\n",
8024
8025 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
8026 " OpStore %IF_output_ptr0 %ret0\n"
8027 " %ret1 = OpFConvert %f16 %IF_input_val1\n"
8028 " OpStore %IF_output_ptr1 %ret1\n"
8029 " %ret2 = OpFConvert %f16 %IF_input_val2\n"
8030 " OpStore %IF_output_ptr2 %ret2\n",
8031
8032 " %f16 = OpTypeFloat 16\n"
8033 " %f64 = OpTypeFloat 64\n"
8034 " %op_f16 = OpTypePointer Output %f16\n"
8035 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
8036 " %op_a3f16 = OpTypePointer Output %a3f16\n"
8037 "%f16_f64_function = OpTypeFunction %f16 %f64\n"
8038 " %a3f64 = OpTypeArray %f64 %c_i32_3\n"
8039 " %ip_a3f64 = OpTypePointer Input %a3f64\n"
8040 " %ip_f64 = OpTypePointer Input %f64\n",
8041
8042 "f64",
8043 "f16",
8044 4,
8045 1,
8046 },
8047 { // Vector cases
8048 "vector",
8049
8050 "OpFConvert %v2f16",
8051
8052 "",
8053
8054 " %ret0 = OpFConvert %v2f16 %IF_input_val\n"
8055 " OpStore %IF_output %ret0\n",
8056
8057 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
8058 " OpStore %IF_output %ret0\n",
8059
8060 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
8061 " OpStore %IF_output_ptr0 %ret0\n"
8062 " %ret1 = OpFConvert %v2f16 %IF_input_val1\n"
8063 " OpStore %IF_output_ptr1 %ret1\n"
8064 " %ret2 = OpFConvert %v2f16 %IF_input_val2\n"
8065 " OpStore %IF_output_ptr2 %ret2\n",
8066
8067 " %f16 = OpTypeFloat 16\n"
8068 " %f64 = OpTypeFloat 64\n"
8069 " %v2f16 = OpTypeVector %f16 2\n"
8070 " %v2f64 = OpTypeVector %f64 2\n"
8071 " %op_v2f16 = OpTypePointer Output %v2f16\n"
8072 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
8073 " %op_a3v2f16 = OpTypePointer Output %a3v2f16\n"
8074 "%v2f16_v2f64_function = OpTypeFunction %v2f16 %v2f64\n"
8075 " %a3v2f64 = OpTypeArray %v2f64 %c_i32_3\n"
8076 " %ip_a3v2f64 = OpTypePointer Input %a3v2f64\n"
8077 " %ip_v2f64 = OpTypePointer Input %v2f64\n",
8078
8079 "v2f64",
8080 "v2f16",
8081 2 * 4,
8082 2,
8083 }
8084 };
8085
8086 VulkanFeatures requiredFeatures;
8087
8088 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
8089 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
8090
8091 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
8092 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
8093 {
8094 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
8095 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
8096 fragments["post_interface_op_frag"] = cases[caseIdx].postInterfaceOp;
8097 fragments["post_interface_op_vert"] = cases[caseIdx].postInterfaceOp;
8098 fragments["post_interface_op_geom"] = cases[caseIdx].postInterfaceOpGeom;
8099 fragments["post_interface_op_tesse"] = cases[caseIdx].postInterfaceOpGeom;
8100 fragments["post_interface_op_tessc"] = cases[caseIdx].postInterfaceOpTessc;
8101 fragments["pre_main"] = cases[caseIdx].preMain;
8102 fragments["decoration"] = rndModes[rndModeIdx].decor;
8103 fragments["decoration_tessc"] = rndModes[rndModeIdx].decor_tessc;
8104
8105 fragments["input_type"] = cases[caseIdx].inputType;
8106 fragments["output_type"] = cases[caseIdx].outputType;
8107
8108 GraphicsInterfaces interfaces;
8109 const deUint32 numPerCase = cases[caseIdx].numPerCase;
8110 vector<double> subInputs (numPerCase);
8111 vector<deFloat16> subOutputs (numPerCase);
8112
8113 // The pipeline need this to call compare16BitFloat() when checking the result.
8114 interfaces.setRoundingMode(rndModes[rndModeIdx].flags);
8115
8116 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
8117 {
8118 string testName = string(cases[caseIdx].name) + numberToString(caseNdx) + "_" + rndModes[rndModeIdx].name;
8119
8120 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
8121 {
8122 subInputs[numNdx] = float64Data[caseNdx * numPerCase + numNdx];
8123 // We derive the expected result from inputs directly in the graphics pipeline.
8124 subOutputs[numNdx] = 0;
8125 }
8126 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT64), BufferSp(new Float64Buffer(subInputs))),
8127 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs))));
8128 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
8129 }
8130 }
8131 }
8132
addCompute16bitStorageUniform16To64Group(tcu::TestCaseGroup * group)8133 void addCompute16bitStorageUniform16To64Group (tcu::TestCaseGroup* group)
8134 {
8135 tcu::TestContext& testCtx = group->getTestContext();
8136 de::Random rnd (deStringHash(group->getName()));
8137 const int numElements = 128;
8138
8139 const StringTemplate shaderTemplate (
8140 "OpCapability Shader\n"
8141 "OpCapability Float64\n"
8142 "OpCapability ${capability}\n"
8143 "OpExtension \"SPV_KHR_16bit_storage\"\n"
8144 "OpMemoryModel Logical GLSL450\n"
8145 "OpEntryPoint GLCompute %main \"main\" %id\n"
8146 "OpExecutionMode %main LocalSize 1 1 1\n"
8147 "OpDecorate %id BuiltIn GlobalInvocationId\n"
8148
8149 "${stride}\n"
8150
8151 "OpMemberDecorate %SSBO64 0 Offset 0\n"
8152 "OpMemberDecorate %SSBO16 0 Offset 0\n"
8153 "OpDecorate %SSBO64 BufferBlock\n"
8154 "OpDecorate %SSBO16 ${storage}\n"
8155 "OpDecorate %ssbo64 DescriptorSet 0\n"
8156 "OpDecorate %ssbo16 DescriptorSet 0\n"
8157 "OpDecorate %ssbo64 Binding 1\n"
8158 "OpDecorate %ssbo16 Binding 0\n"
8159
8160 "${matrix_decor:opt}\n"
8161
8162 "%bool = OpTypeBool\n"
8163 "%void = OpTypeVoid\n"
8164 "%voidf = OpTypeFunction %void\n"
8165 "%u32 = OpTypeInt 32 0\n"
8166 "%i32 = OpTypeInt 32 1\n"
8167 "%f64 = OpTypeFloat 64\n"
8168 "%v3u32 = OpTypeVector %u32 3\n"
8169 "%uvec3ptr = OpTypePointer Input %v3u32\n"
8170 "%i32ptr = OpTypePointer Uniform %i32\n"
8171 "%f64ptr = OpTypePointer Uniform %f64\n"
8172
8173 "%zero = OpConstant %i32 0\n"
8174 "%c_i32_1 = OpConstant %i32 1\n"
8175 "%c_i32_2 = OpConstant %i32 2\n"
8176 "%c_i32_3 = OpConstant %i32 3\n"
8177 "%c_i32_16 = OpConstant %i32 16\n"
8178 "%c_i32_32 = OpConstant %i32 32\n"
8179 "%c_i32_64 = OpConstant %i32 64\n"
8180 "%c_i32_128 = OpConstant %i32 128\n"
8181 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
8182
8183 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
8184 "%f64arr = OpTypeArray %f64 %c_i32_128\n"
8185
8186 "${types}\n"
8187 "${matrix_types:opt}\n"
8188
8189 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
8190 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
8191 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
8192 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
8193 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
8194 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
8195
8196 "%id = OpVariable %uvec3ptr Input\n"
8197
8198 "%main = OpFunction %void None %voidf\n"
8199 "%label = OpLabel\n"
8200 "%idval = OpLoad %v3u32 %id\n"
8201 "%x = OpCompositeExtract %u32 %idval 0\n"
8202 "%inloc = OpAccessChain %${base16}ptr %ssbo16 %zero %${arrayindex} ${index0:opt}\n"
8203 "%val16 = OpLoad %${base16} %inloc\n"
8204 "%val64 = ${convert} %${base64} %val16\n"
8205 "%outloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
8206 " OpStore %outloc %val64\n"
8207 "${matrix_store:opt}\n"
8208 " OpReturn\n"
8209 " OpFunctionEnd\n");
8210
8211 { // floats
8212 const char floatTypes[] =
8213 "%f16 = OpTypeFloat 16\n"
8214 "%f16ptr = OpTypePointer Uniform %f16\n"
8215 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
8216 "%v2f16 = OpTypeVector %f16 2\n"
8217 "%v2f64 = OpTypeVector %f64 2\n"
8218 "%v2f16ptr = OpTypePointer Uniform %v2f16\n"
8219 "%v2f64ptr = OpTypePointer Uniform %v2f64\n"
8220 "%v2f16arr = OpTypeArray %v2f16 %c_i32_64\n"
8221 "%v2f64arr = OpTypeArray %v2f64 %c_i32_64\n";
8222
8223 enum DataType
8224 {
8225 SCALAR,
8226 VEC2,
8227 MAT2X2,
8228 };
8229
8230
8231 struct CompositeType
8232 {
8233 const char* name;
8234 const char* base64;
8235 const char* base16;
8236 const char* strideStr;
8237 const char* stride16UBO;
8238 unsigned padding16UBO;
8239 const char* stride16SSBO;
8240 unsigned padding16SSBO;
8241 bool useConstantIndex;
8242 unsigned constantIndex;
8243 unsigned count;
8244 DataType dataType;
8245 };
8246
8247 const CompositeType cTypes[] =
8248 {
8249 {"scalar", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, false, 0, numElements , SCALAR },
8250 {"scalar_const_idx_5", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, true, 5, numElements , SCALAR },
8251 {"scalar_const_idx_8", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, true, 8, numElements , SCALAR },
8252 {"vector", "v2f64", "v2f16", "OpDecorate %v2f64arr ArrayStride 16\nOpDecorate %v2f16arr ArrayStride ", "16", 12, "4", 0, false, 0, numElements / 2 , VEC2 },
8253 {"matrix", "v2f64", "v2f16", "OpDecorate %m4v2f64arr ArrayStride 64\nOpDecorate %m4v2f16arr ArrayStride ", "16", 0, "16", 0, false, 0, numElements / 8 , MAT2X2 }
8254 };
8255
8256 vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
8257 vector<double> float64Data;
8258
8259 float64Data.reserve(numElements);
8260 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8261 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
8262
8263 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
8264 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
8265 {
8266 ComputeShaderSpec spec;
8267 map<string, string> specs;
8268 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float";
8269 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
8270
8271 specs["capability"] = CAPABILITIES[capIdx].cap;
8272 specs["storage"] = CAPABILITIES[capIdx].decor;
8273 specs["stride"] = cTypes[tyIdx].strideStr;
8274 specs["base64"] = cTypes[tyIdx].base64;
8275 specs["base16"] = cTypes[tyIdx].base16;
8276 specs["types"] = floatTypes;
8277 specs["convert"] = "OpFConvert";
8278 specs["constarrayidx"] = de::toString(cTypes[tyIdx].constantIndex);
8279
8280 if (isUBO)
8281 specs["stride"] += cTypes[tyIdx].stride16UBO;
8282 else
8283 specs["stride"] += cTypes[tyIdx].stride16SSBO;
8284
8285 if (cTypes[tyIdx].useConstantIndex)
8286 specs["arrayindex"] = "c_i32_ci";
8287 else
8288 specs["arrayindex"] = "x";
8289
8290 vector<double> float64DataConstIdx;
8291 if (cTypes[tyIdx].useConstantIndex)
8292 {
8293 const deUint32 numFloats = numElements / cTypes[tyIdx].count;
8294 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8295 float64DataConstIdx.push_back(float64Data[cTypes[tyIdx].constantIndex * numFloats + numIdx % numFloats]);
8296 }
8297
8298 if (deStringEqual(cTypes[tyIdx].name, "matrix"))
8299 {
8300 specs["index0"] = "%zero";
8301 specs["matrix_prefix"] = "m4";
8302 specs["matrix_types"] =
8303 "%m4v2f16 = OpTypeMatrix %v2f16 4\n"
8304 "%m4v2f64 = OpTypeMatrix %v2f64 4\n"
8305 "%m4v2f16arr = OpTypeArray %m4v2f16 %c_i32_16\n"
8306 "%m4v2f64arr = OpTypeArray %m4v2f64 %c_i32_16\n";
8307 specs["matrix_decor"] =
8308 "OpMemberDecorate %SSBO64 0 ColMajor\n"
8309 "OpMemberDecorate %SSBO64 0 MatrixStride 16\n"
8310 "OpMemberDecorate %SSBO16 0 ColMajor\n"
8311 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n";
8312 specs["matrix_store"] =
8313 "%inloc_1 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_1\n"
8314 "%val16_1 = OpLoad %v2f16 %inloc_1\n"
8315 "%val64_1 = OpFConvert %v2f64 %val16_1\n"
8316 "%outloc_1 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_1\n"
8317 " OpStore %outloc_1 %val64_1\n"
8318
8319 "%inloc_2 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_2\n"
8320 "%val16_2 = OpLoad %v2f16 %inloc_2\n"
8321 "%val64_2 = OpFConvert %v2f64 %val16_2\n"
8322 "%outloc_2 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_2\n"
8323 " OpStore %outloc_2 %val64_2\n"
8324
8325 "%inloc_3 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_3\n"
8326 "%val16_3 = OpLoad %v2f16 %inloc_3\n"
8327 "%val64_3 = OpFConvert %v2f64 %val16_3\n"
8328 "%outloc_3 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_3\n"
8329 " OpStore %outloc_3 %val64_3\n";
8330 }
8331
8332 spec.assembly = shaderTemplate.specialize(specs);
8333 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
8334 spec.verifyIO = check64BitFloats;
8335 const unsigned padding = isUBO ? cTypes[tyIdx].padding16UBO : cTypes[tyIdx].padding16SSBO;
8336
8337 if (cTypes[tyIdx].dataType == SCALAR || cTypes[tyIdx].dataType == MAT2X2)
8338 {
8339 DE_ASSERT(cTypes[tyIdx].dataType != MAT2X2 || padding == 0);
8340 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data, padding)), CAPABILITIES[capIdx].dtype));
8341 }
8342 else if (cTypes[tyIdx].dataType == VEC2)
8343 {
8344 vector<tcu::Vector<deFloat16, 2> > float16Vec2Data(numElements / 2);
8345 for (size_t elemIdx = 0; elemIdx < numElements; elemIdx++)
8346 {
8347 float16Vec2Data[elemIdx / 2][elemIdx % 2] = float16Data[elemIdx];
8348 }
8349
8350 typedef Buffer<tcu::Vector<deFloat16, 2> > Float16Vec2Buffer;
8351 spec.inputs.push_back(Resource(BufferSp(new Float16Vec2Buffer(float16Vec2Data, padding)), CAPABILITIES[capIdx].dtype));
8352 }
8353
8354 spec.outputs.push_back(Resource(BufferSp(new Float64Buffer(cTypes[tyIdx].useConstantIndex ? float64DataConstIdx : float64Data))));
8355 spec.extensions.push_back("VK_KHR_16bit_storage");
8356
8357 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
8358 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
8359
8360 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
8361 }
8362 }
8363 }
8364
addCompute16bitStoragePushConstant16To64Group(tcu::TestCaseGroup * group)8365 void addCompute16bitStoragePushConstant16To64Group (tcu::TestCaseGroup* group)
8366 {
8367 tcu::TestContext& testCtx = group->getTestContext();
8368 de::Random rnd (deStringHash(group->getName()));
8369 const int numElements = 64;
8370
8371 const StringTemplate shaderTemplate (
8372 "OpCapability Shader\n"
8373 "OpCapability StoragePushConstant16\n"
8374 "OpCapability Float64\n"
8375 "OpExtension \"SPV_KHR_16bit_storage\"\n"
8376 "OpMemoryModel Logical GLSL450\n"
8377 "OpEntryPoint GLCompute %main \"main\" %id\n"
8378 "OpExecutionMode %main LocalSize 1 1 1\n"
8379 "OpDecorate %id BuiltIn GlobalInvocationId\n"
8380
8381 "${stride}"
8382
8383 "OpDecorate %PC16 Block\n"
8384 "OpMemberDecorate %PC16 0 Offset 0\n"
8385 "OpMemberDecorate %SSBO64 0 Offset 0\n"
8386 "OpDecorate %SSBO64 BufferBlock\n"
8387 "OpDecorate %ssbo64 DescriptorSet 0\n"
8388 "OpDecorate %ssbo64 Binding 0\n"
8389
8390 "${matrix_decor:opt}\n"
8391
8392 "%bool = OpTypeBool\n"
8393 "%void = OpTypeVoid\n"
8394 "%voidf = OpTypeFunction %void\n"
8395 "%u32 = OpTypeInt 32 0\n"
8396 "%i32 = OpTypeInt 32 1\n"
8397 "%f32 = OpTypeFloat 32\n"
8398 "%uvec3 = OpTypeVector %u32 3\n"
8399 "%fvec3 = OpTypeVector %f32 3\n"
8400 "%uvec3ptr = OpTypePointer Input %uvec3\n"
8401 "%i32ptr = OpTypePointer Uniform %i32\n"
8402 "%f32ptr = OpTypePointer Uniform %f32\n"
8403
8404 "%zero = OpConstant %i32 0\n"
8405 "%c_i32_1 = OpConstant %i32 1\n"
8406 "%c_i32_8 = OpConstant %i32 8\n"
8407 "%c_i32_16 = OpConstant %i32 16\n"
8408 "%c_i32_32 = OpConstant %i32 32\n"
8409 "%c_i32_64 = OpConstant %i32 64\n"
8410
8411 "%i32arr = OpTypeArray %i32 %c_i32_64\n"
8412 "%f32arr = OpTypeArray %f32 %c_i32_64\n"
8413
8414 "${types}\n"
8415 "${matrix_types:opt}\n"
8416
8417 "%PC16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
8418 "%pp_PC16 = OpTypePointer PushConstant %PC16\n"
8419 "%pc16 = OpVariable %pp_PC16 PushConstant\n"
8420 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
8421 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
8422 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
8423
8424 "%id = OpVariable %uvec3ptr Input\n"
8425
8426 "%main = OpFunction %void None %voidf\n"
8427 "%label = OpLabel\n"
8428 "%idval = OpLoad %uvec3 %id\n"
8429 "%x = OpCompositeExtract %u32 %idval 0\n"
8430 "%inloc = OpAccessChain %${base16}ptr %pc16 %zero %x ${index0:opt}\n"
8431 "%val16 = OpLoad %${base16} %inloc\n"
8432 "%val64 = ${convert} %${base64} %val16\n"
8433 "%outloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
8434 " OpStore %outloc %val64\n"
8435 "${matrix_store:opt}\n"
8436 " OpReturn\n"
8437 " OpFunctionEnd\n");
8438
8439 { // floats
8440 const char floatTypes[] =
8441 "%f16 = OpTypeFloat 16\n"
8442 "%f16ptr = OpTypePointer PushConstant %f16\n"
8443 "%f16arr = OpTypeArray %f16 %c_i32_64\n"
8444 "%f64 = OpTypeFloat 64\n"
8445 "%f64ptr = OpTypePointer Uniform %f64\n"
8446 "%f64arr = OpTypeArray %f64 %c_i32_64\n"
8447 "%v4f16 = OpTypeVector %f16 4\n"
8448 "%v4f32 = OpTypeVector %f32 4\n"
8449 "%v4f64 = OpTypeVector %f64 4\n"
8450 "%v4f16ptr = OpTypePointer PushConstant %v4f16\n"
8451 "%v4f32ptr = OpTypePointer Uniform %v4f32\n"
8452 "%v4f64ptr = OpTypePointer Uniform %v4f64\n"
8453 "%v4f16arr = OpTypeArray %v4f16 %c_i32_16\n"
8454 "%v4f32arr = OpTypeArray %v4f32 %c_i32_16\n"
8455 "%v4f64arr = OpTypeArray %v4f64 %c_i32_16\n";
8456
8457 struct CompositeType
8458 {
8459 const char* name;
8460 const char* base64;
8461 const char* base16;
8462 const char* stride;
8463 unsigned count;
8464 };
8465
8466 const CompositeType cTypes[] =
8467 {
8468 {"scalar", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride 2\n", numElements},
8469 {"vector", "v4f64", "v4f16", "OpDecorate %v4f64arr ArrayStride 32\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4},
8470 {"matrix", "v4f64", "v4f16", "OpDecorate %m2v4f64arr ArrayStride 64\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8},
8471 };
8472
8473 vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
8474 vector<double> float64Data;
8475
8476 float64Data.reserve(numElements);
8477 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8478 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
8479
8480 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
8481 {
8482 ComputeShaderSpec spec;
8483 map<string, string> specs;
8484 string testName = string(cTypes[tyIdx].name) + "_float";
8485
8486 specs["stride"] = cTypes[tyIdx].stride;
8487 specs["base64"] = cTypes[tyIdx].base64;
8488 specs["base16"] = cTypes[tyIdx].base16;
8489 specs["types"] = floatTypes;
8490 specs["convert"] = "OpFConvert";
8491
8492 if (strcmp(cTypes[tyIdx].name, "matrix") == 0)
8493 {
8494 specs["index0"] = "%zero";
8495 specs["matrix_prefix"] = "m2";
8496 specs["matrix_types"] =
8497 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
8498 "%m2v4f64 = OpTypeMatrix %v4f64 2\n"
8499 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_8\n"
8500 "%m2v4f64arr = OpTypeArray %m2v4f64 %c_i32_8\n";
8501 specs["matrix_decor"] =
8502 "OpMemberDecorate %SSBO64 0 ColMajor\n"
8503 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
8504 "OpMemberDecorate %PC16 0 ColMajor\n"
8505 "OpMemberDecorate %PC16 0 MatrixStride 8\n";
8506 specs["matrix_store"] =
8507 "%inloc_1 = OpAccessChain %v4f16ptr %pc16 %zero %x %c_i32_1\n"
8508 "%val16_1 = OpLoad %v4f16 %inloc_1\n"
8509 "%val64_1 = OpFConvert %v4f64 %val16_1\n"
8510 "%outloc_1 = OpAccessChain %v4f64ptr %ssbo64 %zero %x %c_i32_1\n"
8511 " OpStore %outloc_1 %val64_1\n";
8512 }
8513
8514 spec.assembly = shaderTemplate.specialize(specs);
8515 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
8516 spec.verifyIO = check64BitFloats;
8517 spec.pushConstants = BufferSp(new Float16Buffer(float16Data));
8518
8519 spec.outputs.push_back(BufferSp(new Float64Buffer(float64Data)));
8520
8521 spec.extensions.push_back("VK_KHR_16bit_storage");
8522
8523 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
8524 spec.requestedVulkanFeatures.ext16BitStorage.storagePushConstant16 = true;
8525
8526 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
8527 }
8528 }
8529 }
8530
8531 } // anonymous
8532
create16BitStorageComputeGroup(tcu::TestContext & testCtx)8533 tcu::TestCaseGroup* create16BitStorageComputeGroup (tcu::TestContext& testCtx)
8534 {
8535 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Compute tests for VK_KHR_16bit_storage extension"));
8536 addTestGroup(group.get(), "uniform_64_to_16", "64bit floats to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform64To16Group);
8537 addTestGroup(group.get(), "uniform_32_to_16", "32bit floats/ints to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform32To16Group);
8538 addTestGroup(group.get(), "uniform_16_to_32", "16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To32Group);
8539 addTestGroup(group.get(), "uniform_16_to_64", "16bit floats to 64bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To64Group);
8540 addTestGroup(group.get(), "push_constant_16_to_32", "16bit floats/ints to 32bit tests under capability StoragePushConstant16", addCompute16bitStoragePushConstant16To32Group);
8541 addTestGroup(group.get(), "push_constant_16_to_64", "16bit floats to 64bit tests under capability StoragePushConstant16", addCompute16bitStoragePushConstant16To64Group);
8542 addTestGroup(group.get(), "uniform_16struct_to_32struct", "16bit floats struct to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16StructTo32StructGroup);
8543 addTestGroup(group.get(), "uniform_32struct_to_16struct", "32bit floats struct to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform32StructTo16StructGroup);
8544 addTestGroup(group.get(), "struct_mixed_types", "mixed type of 8bit and 32bit struct", addCompute16bitStructMixedTypesGroup);
8545 addTestGroup(group.get(), "uniform_16_to_16", "16bit floats/ints to 16bit tests under capability StorageUniformBufferBlock16", addCompute16bitStorageUniform16To16Group);
8546 addTestGroup(group.get(), "uniform_16_to_32_chainaccess", "chain access 16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To32ChainAccessGroup);
8547
8548 return group.release();
8549 }
8550
create16BitStorageGraphicsGroup(tcu::TestContext & testCtx)8551 tcu::TestCaseGroup* create16BitStorageGraphicsGroup (tcu::TestContext& testCtx)
8552 {
8553 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Graphics tests for VK_KHR_16bit_storage extension"));
8554
8555 addTestGroup(group.get(), "uniform_float_64_to_16", "64-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat64To16Group);
8556 addTestGroup(group.get(), "uniform_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat32To16Group);
8557 addTestGroup(group.get(), "uniform_float_16_to_32", "16-bit floats into 32-bit testsunder capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat16To32Group);
8558 addTestGroup(group.get(), "uniform_float_16_to_64", "16-bit floats into 64-bit testsunder capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat16To64Group);
8559 addTestGroup(group.get(), "uniform_int_32_to_16", "32-bit int into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt32To16Group);
8560 addTestGroup(group.get(), "uniform_int_16_to_32", "16-bit int into 32-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt16To32Group);
8561 addTestGroup(group.get(), "input_output_float_64_to_16", "64-bit floats into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat64To16Group);
8562 addTestGroup(group.get(), "input_output_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat32To16Group);
8563 addTestGroup(group.get(), "input_output_float_16_to_32", "16-bit floats into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To32Group);
8564 addTestGroup(group.get(), "input_output_float_16_to_16", "16-bit floats pass-through tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To16Group);
8565 addTestGroup(group.get(), "input_output_float_16_to_64", "16-bit floats into 64-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To64Group);
8566 addTestGroup(group.get(), "input_output_float_16_to_16x2", "16-bit floats pass-through to two outputs tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To16x2Group);
8567 addTestGroup(group.get(), "input_output_int_16_to_16x2", "16-bit ints pass-through to two outputs tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To16x2Group);
8568 addTestGroup(group.get(), "input_output_int_32_to_16", "32-bit int into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt32To16Group);
8569 addTestGroup(group.get(), "input_output_int_16_to_32", "16-bit int into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To32Group);
8570 addTestGroup(group.get(), "input_output_int_16_to_16", "16-bit int into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To16Group);
8571 addTestGroup(group.get(), "push_constant_float_16_to_32", "16-bit floats into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantFloat16To32Group);
8572 addTestGroup(group.get(), "push_constant_float_16_to_64", "16-bit floats into 64-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantFloat16To64Group);
8573 addTestGroup(group.get(), "push_constant_int_16_to_32", "16-bit int into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantInt16To32Group);
8574 addTestGroup(group.get(), "uniform_16struct_to_32struct", "16-bit float struct into 32-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformStructFloat16To32Group);
8575 addTestGroup(group.get(), "uniform_32struct_to_16struct", "32-bit float struct into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformStructFloat32To16Group);
8576 addTestGroup(group.get(), "struct_mixed_types", "mixed type of 8bit and 32bit struct", addGraphics16bitStructMixedTypesGroup);
8577
8578 return group.release();
8579 }
8580
8581 } // SpirVAssembly
8582 } // vkt
8583