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(), 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(), 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(), 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(), 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, 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", 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(), 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(), 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(), 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(), 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(), 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 addShaderCode16BitStorageInputOutput16To16x2,
4247 runAndVerifyDefaultPipeline,
4248 testDef);
4249 }
4250 }
4251
addGraphics16BitStorageInputOutputInt16To16x2Group(tcu::TestCaseGroup * testGroup)4252 void addGraphics16BitStorageInputOutputInt16To16x2Group (tcu::TestCaseGroup* testGroup)
4253 {
4254 map<string, string> fragments;
4255 RGBA defaultColors[4];
4256 SpecConstants noSpecConstants;
4257 PushConstants noPushConstants;
4258 vector<string> extensions;
4259 GraphicsResources noResources;
4260 StageToSpecConstantMap specConstantMap;
4261 VulkanFeatures requiredFeatures;
4262
4263 const ShaderElement pipelineStages[] =
4264 {
4265 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
4266 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
4267 };
4268
4269 specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = noSpecConstants;
4270 specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = noSpecConstants;
4271
4272 getDefaultColors(defaultColors);
4273
4274 extensions.push_back("VK_KHR_16bit_storage");
4275 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4276 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4277
4278 const struct
4279 {
4280 string name;
4281 deUint32 numElements;
4282 TestDefDataType dataType;
4283 NumberType numberType;
4284 bool isVector;
4285 } cases[] =
4286 {
4287 { "scalar_int", 1, DATATYPE_INT, NUMBERTYPE_INT16, false },
4288 { "scalar_uint", 1, DATATYPE_UINT, NUMBERTYPE_UINT16, false },
4289 { "ivec2", 2, DATATYPE_IVEC2, NUMBERTYPE_INT16, true },
4290 { "uvec2", 2, DATATYPE_UVEC2, NUMBERTYPE_UINT16, true }
4291 };
4292
4293 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4294 {
4295 const RGBA outColor (128u, 128u, cases[caseIdx].isVector ? 128u : 255u, cases[caseIdx].isVector ? 128u : 255u);
4296 RGBA outputColors[4] = {outColor, outColor, outColor, outColor};
4297 vector<deInt16> int16Data (4 * cases[caseIdx].numElements, 32767);
4298 GraphicsInterfaces interfaces;
4299
4300 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Int16Buffer(int16Data))),
4301 std::make_pair(IFDataType(cases[caseIdx].numElements, cases[caseIdx].numberType), BufferSp(new Int16Buffer(int16Data))));
4302
4303 const InstanceContext& instanceContext = createInstanceContext(pipelineStages,
4304 defaultColors,
4305 outputColors,
4306 fragments,
4307 specConstantMap,
4308 noPushConstants,
4309 noResources,
4310 interfaces,
4311 extensions,
4312 requiredFeatures,
4313 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
4314 QP_TEST_RESULT_FAIL,
4315 string());
4316
4317 TestDefinition testDef = {instanceContext, cases[caseIdx].dataType};
4318
4319 addFunctionCaseWithPrograms<TestDefinition>(testGroup,
4320 cases[caseIdx].name,
4321 addShaderCode16BitStorageInputOutput16To16x2,
4322 runAndVerifyDefaultPipeline,
4323 testDef);
4324 }
4325 }
4326
addGraphics16BitStorageInputOutputInt32To16Group(tcu::TestCaseGroup * testGroup)4327 void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testGroup)
4328 {
4329 de::Random rnd (deStringHash(testGroup->getName()));
4330 RGBA defaultColors[4];
4331 vector<string> extensions;
4332 map<string, string> fragments = passthruFragments();
4333 const deUint32 numDataPoints = 64;
4334 // inputs and outputs are declared to be vectors of signed integers.
4335 // However, depending on the test, they may be interpreted as unsiged
4336 // integers. That won't be a problem as long as we passed the bits
4337 // in faithfully to the pipeline.
4338 vector<deInt32> inputs = getInt32s(rnd, numDataPoints);
4339 vector<deInt16> outputs;
4340
4341 outputs.reserve(inputs.size());
4342 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4343 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx]));
4344
4345 extensions.push_back("VK_KHR_16bit_storage");
4346
4347 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4348 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4349
4350 getDefaultColors(defaultColors);
4351
4352 const StringTemplate scalarInterfaceOpCall(
4353 "${convert} %${type16}");
4354
4355 const StringTemplate scalarInterfaceOpFunc("");
4356
4357 const StringTemplate scalarPreMain(
4358 " %${type16} = OpTypeInt 16 ${signed}\n"
4359 " %op_${type16} = OpTypePointer Output %${type16}\n"
4360 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4361 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4362 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4363 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4364 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4365
4366 const StringTemplate vecInterfaceOpCall(
4367 "${convert} %${type16}");
4368
4369 const StringTemplate vecInterfaceOpFunc("");
4370
4371 const StringTemplate vecPreMain(
4372 " %i16 = OpTypeInt 16 1\n"
4373 " %u16 = OpTypeInt 16 0\n"
4374 " %v4i16 = OpTypeVector %i16 4\n"
4375 " %v4u16 = OpTypeVector %u16 4\n"
4376 " %op_${type16} = OpTypePointer Output %${type16}\n"
4377 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4378 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n"
4379 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n"
4380 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4381 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n");
4382
4383 struct Case
4384 {
4385 const char* name;
4386 const StringTemplate& interfaceOpCall;
4387 const StringTemplate& interfaceOpFunc;
4388 const StringTemplate& preMain;
4389 const char* type32;
4390 const char* type16;
4391 const char* sign;
4392 const char* opcode;
4393 deUint32 numPerCase;
4394 deUint32 numElements;
4395 };
4396
4397 Case cases[] =
4398 {
4399 {"scalar_sint", scalarInterfaceOpCall, scalarInterfaceOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1},
4400 {"scalar_uint", scalarInterfaceOpCall, scalarInterfaceOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1},
4401 {"vector_sint", vecInterfaceOpCall, vecInterfaceOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4},
4402 {"vector_uint", vecInterfaceOpCall, vecInterfaceOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4},
4403 };
4404
4405 VulkanFeatures requiredFeatures;
4406 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4407 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4408
4409 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4410 {
4411 map<string, string> specs;
4412
4413 specs["type32"] = cases[caseIdx].type32;
4414 specs["type16"] = cases[caseIdx].type16;
4415 specs["signed"] = cases[caseIdx].sign;
4416 specs["convert"] = cases[caseIdx].opcode;
4417
4418 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4419 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4420 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4421 fragments["input_type"] = cases[caseIdx].type32;
4422 fragments["output_type"] = cases[caseIdx].type16;
4423
4424 GraphicsInterfaces interfaces;
4425 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4426 vector<deInt32> subInputs (numPerCase);
4427 vector<deInt16> subOutputs (numPerCase);
4428
4429 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4430 {
4431 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4432
4433 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4434 {
4435 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4436 subOutputs[numNdx] = outputs[caseNdx * numPerCase + numNdx];
4437 }
4438 if (strcmp(cases[caseIdx].sign, "1") == 0)
4439 {
4440 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subInputs))),
4441 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subOutputs))));
4442 }
4443 else
4444 {
4445 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subInputs))),
4446 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subOutputs))));
4447 }
4448 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4449 }
4450 }
4451 }
4452
addGraphics16BitStorageInputOutputInt16To32Group(tcu::TestCaseGroup * testGroup)4453 void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testGroup)
4454 {
4455 de::Random rnd (deStringHash(testGroup->getName()));
4456 RGBA defaultColors[4];
4457 vector<string> extensions;
4458 map<string, string> fragments = passthruFragments();
4459 const deUint32 numDataPoints = 64;
4460 // inputs and outputs are declared to be vectors of signed integers.
4461 // However, depending on the test, they may be interpreted as unsiged
4462 // integers. That won't be a problem as long as we passed the bits
4463 // in faithfully to the pipeline.
4464 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
4465 vector<deInt32> sOutputs;
4466 vector<deInt32> uOutputs;
4467 const deUint16 signBitMask = 0x8000;
4468 const deUint32 signExtendMask = 0xffff0000;
4469
4470 sOutputs.reserve(inputs.size());
4471 uOutputs.reserve(inputs.size());
4472
4473 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
4474 {
4475 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
4476 if (inputs[numNdx] & signBitMask)
4477 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
4478 else
4479 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
4480 }
4481
4482 extensions.push_back("VK_KHR_16bit_storage");
4483
4484 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4485 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4486
4487 getDefaultColors(defaultColors);
4488
4489 const StringTemplate scalarIfOpCall (
4490 "${convert} %${type32}");
4491
4492 const StringTemplate scalarIfOpFunc ("");
4493
4494 const StringTemplate scalarPreMain (
4495 " %${type16} = OpTypeInt 16 ${signed}\n"
4496 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4497 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4498 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4499 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4500 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4501 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4502
4503 const StringTemplate vecIfOpCall (
4504 "${convert} %${type32}");
4505
4506 const StringTemplate vecIfOpFunc ("");
4507
4508 const StringTemplate vecPreMain (
4509 " %i16 = OpTypeInt 16 1\n"
4510 " %u16 = OpTypeInt 16 0\n"
4511 " %v4i16 = OpTypeVector %i16 4\n"
4512 " %v4u16 = OpTypeVector %u16 4\n"
4513 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4514 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4515 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4516 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n"
4517 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n"
4518 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n");
4519
4520 struct Case
4521 {
4522 const char* name;
4523 const StringTemplate& interfaceOpCall;
4524 const StringTemplate& interfaceOpFunc;
4525 const StringTemplate& preMain;
4526 const char* type32;
4527 const char* type16;
4528 const char* sign;
4529 const char* opcode;
4530 deUint32 numPerCase;
4531 deUint32 numElements;
4532 };
4533
4534 Case cases[] =
4535 {
4536 {"scalar_sint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1},
4537 {"scalar_uint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1},
4538 {"vector_sint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4},
4539 {"vector_uint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4},
4540 };
4541
4542 VulkanFeatures requiredFeatures;
4543 requiredFeatures.coreFeatures.shaderInt16 = DE_TRUE;
4544 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4545
4546 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4547 {
4548 map<string, string> specs;
4549
4550 specs["type32"] = cases[caseIdx].type32;
4551 specs["type16"] = cases[caseIdx].type16;
4552 specs["signed"] = cases[caseIdx].sign;
4553 specs["convert"] = cases[caseIdx].opcode;
4554
4555 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4556 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4557 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4558 fragments["input_type"] = cases[caseIdx].type16;
4559 fragments["output_type"] = cases[caseIdx].type32;
4560
4561 GraphicsInterfaces interfaces;
4562 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4563 vector<deInt16> subInputs (numPerCase);
4564 vector<deInt32> subOutputs (numPerCase);
4565
4566 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4567 {
4568 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4569
4570 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4571 {
4572 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4573 if (cases[caseIdx].sign[0] == '1')
4574 subOutputs[numNdx] = sOutputs[caseNdx * numPerCase + numNdx];
4575 else
4576 subOutputs[numNdx] = uOutputs[caseNdx * numPerCase + numNdx];
4577 }
4578 if (strcmp(cases[caseIdx].sign, "1") == 0)
4579 {
4580 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subInputs))),
4581 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subOutputs))));
4582 }
4583 else
4584 {
4585 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subInputs))),
4586 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subOutputs))));
4587 }
4588 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4589 }
4590 }
4591 }
4592
addGraphics16BitStorageInputOutputInt16To16Group(tcu::TestCaseGroup * testGroup)4593 void addGraphics16BitStorageInputOutputInt16To16Group (tcu::TestCaseGroup* testGroup)
4594 {
4595 de::Random rnd (deStringHash(testGroup->getName()));
4596 RGBA defaultColors[4];
4597 vector<string> extensions;
4598 map<string, string> fragments = passthruFragments();
4599 const deUint32 numDataPoints = 64;
4600 // inputs and outputs are declared to be vectors of signed integers.
4601 // However, depending on the test, they may be interpreted as unsiged
4602 // integers. That won't be a problem as long as we passed the bits
4603 // in faithfully to the pipeline.
4604 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
4605 VulkanFeatures requiredFeatures;
4606
4607 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
4608 extensions.push_back("VK_KHR_16bit_storage");
4609
4610 fragments["capability"] = "OpCapability StorageInputOutput16\n";
4611 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4612
4613 getDefaultColors(defaultColors);
4614
4615 const StringTemplate scalarIfOpCall (
4616 "OpCopyObject %${type16}");
4617
4618 const StringTemplate scalarIfOpFunc ("");
4619
4620 const StringTemplate scalarPreMain (
4621 " %${type16} = OpTypeInt 16 ${signed}\n"
4622 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4623 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4624 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4625 "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4626 " %op_${type16} = OpTypePointer Output %${type16}\n"
4627 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4628
4629 const StringTemplate vecIfOpCall (
4630 "OpCopyObject %${type16}");
4631
4632 const StringTemplate vecIfOpFunc ("");
4633
4634 const StringTemplate vecPreMain (
4635 " %i16 = OpTypeInt 16 1\n"
4636 " %u16 = OpTypeInt 16 0\n"
4637 " %v4i16 = OpTypeVector %i16 4\n"
4638 " %v4u16 = OpTypeVector %u16 4\n"
4639 " %ip_${type16} = OpTypePointer Input %${type16}\n"
4640 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n"
4641 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n"
4642 "%${type16}_${type16}_function = OpTypeFunction %${type16} %${type16}\n"
4643 " %op_${type16} = OpTypePointer Output %${type16}\n"
4644 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n");
4645
4646 struct Case
4647 {
4648 const char* name;
4649 const StringTemplate& interfaceOpCall;
4650 const StringTemplate& interfaceOpFunc;
4651 const StringTemplate& preMain;
4652 const char* type16;
4653 const char* sign;
4654 deUint32 numPerCase;
4655 deUint32 numElements;
4656 };
4657
4658 Case cases[] =
4659 {
4660 {"scalar_sint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "i16", "1", 4, 1},
4661 {"scalar_uint", scalarIfOpCall, scalarIfOpFunc, scalarPreMain, "u16", "0", 4, 1},
4662 {"vector_sint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4i16", "1", 4 * 4, 4},
4663 {"vector_uint", vecIfOpCall, vecIfOpFunc, vecPreMain, "v4u16", "0", 4 * 4, 4},
4664 };
4665
4666 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
4667 {
4668 map<string, string> specs;
4669
4670 specs["type16"] = cases[caseIdx].type16;
4671 specs["signed"] = cases[caseIdx].sign;
4672
4673 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs);
4674 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall.specialize(specs);
4675 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs);
4676 fragments["input_type"] = cases[caseIdx].type16;
4677 fragments["output_type"] = cases[caseIdx].type16;
4678
4679 GraphicsInterfaces interfaces;
4680 const deUint32 numPerCase = cases[caseIdx].numPerCase;
4681 vector<deInt16> subInputsOutputs (numPerCase);
4682 const NumberType numberType = strcmp(cases[caseIdx].sign, "1") == 0 ? NUMBERTYPE_INT16 : NUMBERTYPE_UINT16;
4683
4684 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
4685 {
4686 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
4687
4688 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
4689 subInputsOutputs[numNdx] = inputs[caseNdx * numPerCase + numNdx];
4690
4691 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))),
4692 std::make_pair(IFDataType(cases[caseIdx].numElements, numberType), BufferSp(new Int16Buffer(subInputsOutputs))));
4693
4694 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
4695 }
4696 }
4697 }
4698
addGraphics16BitStoragePushConstantFloat16To32Group(tcu::TestCaseGroup * testGroup)4699 void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* testGroup)
4700 {
4701 de::Random rnd (deStringHash(testGroup->getName()));
4702 map<string, string> fragments;
4703 RGBA defaultColors[4];
4704 vector<string> extensions;
4705 GraphicsResources resources;
4706 PushConstants pcs;
4707 const deUint32 numDataPoints = 64;
4708 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
4709 vector<float> float32Data;
4710 VulkanFeatures requiredFeatures;
4711
4712 struct ConstantIndex
4713 {
4714 bool useConstantIndex;
4715 deUint32 constantIndex;
4716 };
4717
4718 ConstantIndex constantIndices[] =
4719 {
4720 { false, 0 },
4721 { true, 4 },
4722 { true, 5 },
4723 { true, 6 }
4724 };
4725
4726 float32Data.reserve(numDataPoints);
4727 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4728 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
4729
4730 extensions.push_back("VK_KHR_16bit_storage");
4731
4732 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
4733 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
4734 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
4735
4736 fragments["capability"] = "OpCapability StoragePushConstant16\n";
4737 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
4738
4739 pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data)));
4740 resources.verifyIO = check32BitFloats;
4741
4742 getDefaultColors(defaultColors);
4743
4744 const StringTemplate testFun (
4745 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
4746 " %param = OpFunctionParameter %v4f32\n"
4747
4748 "%entry = OpLabel\n"
4749 " %i = OpVariable %fp_i32 Function\n"
4750 " OpStore %i %c_i32_0\n"
4751 " OpBranch %loop\n"
4752
4753 " %loop = OpLabel\n"
4754 " %15 = OpLoad %i32 %i\n"
4755 " %lt = OpSLessThan %bool %15 ${count}\n"
4756 " OpLoopMerge %merge %inc None\n"
4757 " OpBranchConditional %lt %write %merge\n"
4758
4759 "%write = OpLabel\n"
4760 " %30 = OpLoad %i32 %i\n"
4761 " %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %${arrayindex} ${index0:opt}\n"
4762 "%val16 = OpLoad ${f_type16} %src\n"
4763 "%val32 = OpFConvert ${f_type32} %val16\n"
4764 " %dst = OpAccessChain ${up_type32} %ssbo32 %c_i32_0 %30 ${index0:opt}\n"
4765 " OpStore %dst %val32\n"
4766
4767 "${store:opt}\n"
4768
4769 " OpBranch %inc\n"
4770
4771 " %inc = OpLabel\n"
4772 " %37 = OpLoad %i32 %i\n"
4773 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
4774 " OpStore %i %39\n"
4775 " OpBranch %loop\n"
4776
4777 "%merge = OpLabel\n"
4778 " OpReturnValue %param\n"
4779
4780 "OpFunctionEnd\n");
4781
4782 { // Scalar cases
4783 const StringTemplate preMain (
4784 " %f16 = OpTypeFloat 16\n"
4785 " %c_i32_64 = OpConstant %i32 64\n"
4786 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4787 " %a64f16 = OpTypeArray %f16 %c_i32_64\n"
4788 " %a64f32 = OpTypeArray %f32 %c_i32_64\n"
4789 " %pp_f16 = OpTypePointer PushConstant %f16\n"
4790 " %up_f32 = OpTypePointer Uniform %f32\n"
4791 " %SSBO32 = OpTypeStruct %a64f32\n"
4792 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4793 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4794 " %PC16 = OpTypeStruct %a64f16\n"
4795 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4796 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4797
4798 fragments["decoration"] =
4799 "OpDecorate %a64f16 ArrayStride 2\n"
4800 "OpDecorate %a64f32 ArrayStride 4\n"
4801 "OpDecorate %SSBO32 BufferBlock\n"
4802 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4803 "OpDecorate %PC16 Block\n"
4804 "OpMemberDecorate %PC16 0 Offset 0\n"
4805 "OpDecorate %ssbo32 DescriptorSet 0\n"
4806 "OpDecorate %ssbo32 Binding 0\n";
4807
4808 map<string, string> specs;
4809
4810 specs["count"] = "%c_i32_64";
4811 specs["pp_type16"] = "%pp_f16";
4812 specs["f_type16"] = "%f16";
4813 specs["f_type32"] = "%f32";
4814 specs["up_type32"] = "%up_f32";
4815
4816 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4817 {
4818 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4819 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4820 string testName = "scalar";
4821 vector<float> float32ConstIdxData;
4822
4823 if (useConstIdx)
4824 {
4825 float32ConstIdxData.reserve(numDataPoints);
4826
4827 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4828 float32ConstIdxData.push_back(float32Data[constIdx]);
4829 }
4830
4831 specs["constarrayidx"] = de::toString(constIdx);
4832 if (useConstIdx)
4833 specs["arrayindex"] = "c_i32_ci";
4834 else
4835 specs["arrayindex"] = "30";
4836
4837 resources.outputs.clear();
4838 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4839
4840 fragments["pre_main"] = preMain.specialize(specs);
4841 fragments["testfun"] = testFun.specialize(specs);
4842
4843 if (useConstIdx)
4844 testName += string("_const_idx_") + de::toString(constIdx);
4845
4846 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4847 }
4848 }
4849
4850 { // Vector cases
4851 const StringTemplate preMain (
4852 " %f16 = OpTypeFloat 16\n"
4853 " %v4f16 = OpTypeVector %f16 4\n"
4854 " %c_i32_16 = OpConstant %i32 16\n"
4855 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4856 " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n"
4857 " %a16v4f32 = OpTypeArray %v4f32 %c_i32_16\n"
4858 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
4859 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
4860 " %SSBO32 = OpTypeStruct %a16v4f32\n"
4861 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4862 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4863 " %PC16 = OpTypeStruct %a16v4f16\n"
4864 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4865 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4866
4867 fragments["decoration"] =
4868 "OpDecorate %a16v4f16 ArrayStride 8\n"
4869 "OpDecorate %a16v4f32 ArrayStride 16\n"
4870 "OpDecorate %SSBO32 BufferBlock\n"
4871 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4872 "OpDecorate %PC16 Block\n"
4873 "OpMemberDecorate %PC16 0 Offset 0\n"
4874 "OpDecorate %ssbo32 DescriptorSet 0\n"
4875 "OpDecorate %ssbo32 Binding 0\n";
4876
4877 map<string, string> specs;
4878
4879 specs["count"] = "%c_i32_16";
4880 specs["pp_type16"] = "%pp_v4f16";
4881 specs["f_type16"] = "%v4f16";
4882 specs["f_type32"] = "%v4f32";
4883 specs["up_type32"] = "%up_v4f32";
4884
4885 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4886 {
4887 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4888 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4889 string testName = "vector";
4890 vector<float> float32ConstIdxData;
4891
4892 if (useConstIdx)
4893 {
4894 float32ConstIdxData.reserve(numDataPoints);
4895
4896 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4897 float32ConstIdxData.push_back(float32Data[constIdx * 4 + numIdx % 4]);
4898 }
4899
4900 specs["constarrayidx"] = de::toString(constIdx);
4901 if (useConstIdx)
4902 specs["arrayindex"] = "c_i32_ci";
4903 else
4904 specs["arrayindex"] = "30";
4905
4906 resources.outputs.clear();
4907 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4908
4909 fragments["pre_main"] = preMain.specialize(specs);
4910 fragments["testfun"] = testFun.specialize(specs);
4911
4912 if (useConstIdx)
4913 testName += string("_const_idx_") + de::toString(constIdx);
4914
4915 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
4916 }
4917 }
4918
4919 { // Matrix cases
4920 const StringTemplate preMain (
4921 " %c_i32_8 = OpConstant %i32 8\n"
4922 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
4923 " %f16 = OpTypeFloat 16\n"
4924 " %v4f16 = OpTypeVector %f16 4\n"
4925 " %m2v4f16 = OpTypeMatrix %v4f16 2\n"
4926 " %m2v4f32 = OpTypeMatrix %v4f32 2\n"
4927 " %a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n"
4928 " %a8m2v4f32 = OpTypeArray %m2v4f32 %c_i32_8\n"
4929 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
4930 " %up_v4f32 = OpTypePointer Uniform %v4f32\n"
4931 " %SSBO32 = OpTypeStruct %a8m2v4f32\n"
4932 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
4933 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
4934 " %PC16 = OpTypeStruct %a8m2v4f16\n"
4935 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
4936 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
4937
4938 fragments["decoration"] =
4939 "OpDecorate %a8m2v4f16 ArrayStride 16\n"
4940 "OpDecorate %a8m2v4f32 ArrayStride 32\n"
4941 "OpDecorate %SSBO32 BufferBlock\n"
4942 "OpMemberDecorate %SSBO32 0 Offset 0\n"
4943 "OpMemberDecorate %SSBO32 0 ColMajor\n"
4944 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n"
4945 "OpDecorate %PC16 Block\n"
4946 "OpMemberDecorate %PC16 0 Offset 0\n"
4947 "OpMemberDecorate %PC16 0 ColMajor\n"
4948 "OpMemberDecorate %PC16 0 MatrixStride 8\n"
4949 "OpDecorate %ssbo32 DescriptorSet 0\n"
4950 "OpDecorate %ssbo32 Binding 0\n";
4951
4952 map<string, string> specs;
4953
4954 specs["count"] = "%c_i32_8";
4955 specs["pp_type16"] = "%pp_v4f16";
4956 specs["up_type32"] = "%up_v4f32";
4957 specs["f_type16"] = "%v4f16";
4958 specs["f_type32"] = "%v4f32";
4959 specs["index0"] = "%c_i32_0";
4960
4961 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
4962 {
4963 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
4964 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
4965 string testName = "matrix";
4966 vector<float> float32ConstIdxData;
4967 const StringTemplate store (
4968 " %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %${arrayindex} %c_i32_1\n"
4969 "%val16_1 = OpLoad %v4f16 %src_1\n"
4970 "%val32_1 = OpFConvert %v4f32 %val16_1\n"
4971 " %dst_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
4972 " OpStore %dst_1 %val32_1\n");
4973
4974 if (useConstIdx)
4975 {
4976 float32ConstIdxData.reserve(numDataPoints);
4977
4978 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
4979 float32ConstIdxData.push_back(float32Data[constIdx * 8 + numIdx % 8]);
4980 }
4981
4982 specs["constarrayidx"] = de::toString(constIdx);
4983 if (useConstIdx)
4984 specs["arrayindex"] = "c_i32_ci";
4985 else
4986 specs["arrayindex"] = "30";
4987
4988 specs["store"] = store.specialize(specs);
4989
4990 resources.outputs.clear();
4991 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(useConstIdx ? float32ConstIdxData : float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
4992
4993 fragments["pre_main"] = preMain.specialize(specs);
4994 fragments["testfun"] = testFun.specialize(specs);
4995
4996 if (useConstIdx)
4997 testName += string("_const_idx_") + de::toString(constIdx);
4998
4999 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5000 }
5001 }
5002 }
5003
addGraphics16BitStoragePushConstantInt16To32Group(tcu::TestCaseGroup * testGroup)5004 void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* testGroup)
5005 {
5006 de::Random rnd (deStringHash(testGroup->getName()));
5007 map<string, string> fragments;
5008 RGBA defaultColors[4];
5009 const deUint32 numDataPoints = 64;
5010 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
5011 vector<deInt32> sOutputs;
5012 vector<deInt32> uOutputs;
5013 PushConstants pcs;
5014 GraphicsResources resources;
5015 vector<string> extensions;
5016 const deUint16 signBitMask = 0x8000;
5017 const deUint32 signExtendMask = 0xffff0000;
5018 VulkanFeatures requiredFeatures;
5019
5020 struct ConstantIndex
5021 {
5022 bool useConstantIndex;
5023 deUint32 constantIndex;
5024 };
5025
5026 ConstantIndex constantIndices[] =
5027 {
5028 { false, 0 },
5029 { true, 4 },
5030 { true, 5 },
5031 { true, 6 }
5032 };
5033
5034 sOutputs.reserve(inputs.size());
5035 uOutputs.reserve(inputs.size());
5036
5037 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
5038 {
5039 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
5040 if (inputs[numNdx] & signBitMask)
5041 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
5042 else
5043 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
5044 }
5045
5046 extensions.push_back("VK_KHR_16bit_storage");
5047
5048 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
5049 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
5050 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
5051
5052 fragments["capability"] = "OpCapability StoragePushConstant16\n";
5053 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5054
5055 pcs.setPushConstant(BufferSp(new Int16Buffer(inputs)));
5056
5057 getDefaultColors(defaultColors);
5058
5059 const StringTemplate testFun (
5060 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5061 " %param = OpFunctionParameter %v4f32\n"
5062
5063 "%entry = OpLabel\n"
5064 " %i = OpVariable %fp_i32 Function\n"
5065 " OpStore %i %c_i32_0\n"
5066 " OpBranch %loop\n"
5067
5068 " %loop = OpLabel\n"
5069 " %15 = OpLoad %i32 %i\n"
5070 " %lt = OpSLessThan %bool %15 %c_i32_${count}\n"
5071 " OpLoopMerge %merge %inc None\n"
5072 " OpBranchConditional %lt %write %merge\n"
5073
5074 "%write = OpLabel\n"
5075 " %30 = OpLoad %i32 %i\n"
5076 " %src = OpAccessChain %pp_${type16} %pc16 %c_i32_0 %${arrayindex}\n"
5077 "%val16 = OpLoad %${type16} %src\n"
5078 "%val32 = ${convert} %${type32} %val16\n"
5079 " %dst = OpAccessChain %up_${type32} %ssbo32 %c_i32_0 %30\n"
5080 " OpStore %dst %val32\n"
5081 " OpBranch %inc\n"
5082
5083 " %inc = OpLabel\n"
5084 " %37 = OpLoad %i32 %i\n"
5085 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5086 " OpStore %i %39\n"
5087 " OpBranch %loop\n"
5088
5089 "%merge = OpLabel\n"
5090 " OpReturnValue %param\n"
5091
5092 "OpFunctionEnd\n");
5093
5094 { // Scalar cases
5095 const StringTemplate preMain (
5096 " %${type16} = OpTypeInt 16 ${signed}\n"
5097 " %c_i32_${count} = OpConstant %i32 ${count}\n" // Should be the same as numDataPoints
5098 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5099 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
5100 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
5101 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
5102 " %up_${type32} = OpTypePointer Uniform %${type32}\n"
5103 " %SSBO32 = OpTypeStruct %a${count}${type32}\n"
5104 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5105 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5106 " %PC16 = OpTypeStruct %a${count}${type16}\n"
5107 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
5108 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
5109
5110 const StringTemplate decoration (
5111 "OpDecorate %a${count}${type16} ArrayStride 2\n"
5112 "OpDecorate %a${count}${type32} ArrayStride 4\n"
5113 "OpDecorate %SSBO32 BufferBlock\n"
5114 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5115 "OpDecorate %PC16 Block\n"
5116 "OpMemberDecorate %PC16 0 Offset 0\n"
5117 "OpDecorate %ssbo32 DescriptorSet 0\n"
5118 "OpDecorate %ssbo32 Binding 0\n");
5119
5120 { // signed int
5121 map<string, string> specs;
5122
5123 specs["type16"] = "i16";
5124 specs["type32"] = "i32";
5125 specs["signed"] = "1";
5126 specs["count"] = "64";
5127 specs["convert"] = "OpSConvert";
5128
5129 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5130 {
5131 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5132 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5133 string testName = "sint_scalar";
5134 vector<deInt32> constIdxData;
5135
5136 if (useConstIdx)
5137 {
5138 constIdxData.reserve(numDataPoints);
5139
5140 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5141 constIdxData.push_back(sOutputs[constIdx]);
5142 }
5143
5144 specs["constarrayidx"] = de::toString(constIdx);
5145 if (useConstIdx)
5146 specs["arrayindex"] = "c_i32_ci";
5147 else
5148 specs["arrayindex"] = "30";
5149
5150 if (useConstIdx)
5151 testName += string("_const_idx_") + de::toString(constIdx);
5152
5153 resources.outputs.clear();
5154 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5155
5156 fragments["testfun"] = testFun.specialize(specs);
5157 fragments["pre_main"] = preMain.specialize(specs);
5158 fragments["decoration"] = decoration.specialize(specs);
5159
5160 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5161 }
5162 }
5163 { // unsigned int
5164 map<string, string> specs;
5165
5166 specs["type16"] = "u16";
5167 specs["type32"] = "u32";
5168 specs["signed"] = "0";
5169 specs["count"] = "64";
5170 specs["convert"] = "OpUConvert";
5171
5172 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5173 {
5174 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5175 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5176 string testName = "uint_scalar";
5177 vector<deInt32> constIdxData;
5178
5179 if (useConstIdx)
5180 {
5181 constIdxData.reserve(numDataPoints);
5182
5183 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5184 constIdxData.push_back(uOutputs[constIdx]);
5185 }
5186
5187 specs["constarrayidx"] = de::toString(constIdx);
5188 if (useConstIdx)
5189 specs["arrayindex"] = "c_i32_ci";
5190 else
5191 specs["arrayindex"] = "30";
5192
5193 if (useConstIdx)
5194 testName += string("_const_idx_") + de::toString(constIdx);
5195
5196 resources.outputs.clear();
5197 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5198
5199 fragments["testfun"] = testFun.specialize(specs);
5200 fragments["pre_main"] = preMain.specialize(specs);
5201 fragments["decoration"] = decoration.specialize(specs);
5202
5203 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5204 }
5205 }
5206 }
5207
5208 { // Vector cases
5209 const StringTemplate preMain (
5210 " %${base_type16} = OpTypeInt 16 ${signed}\n"
5211 " %${type16} = OpTypeVector %${base_type16} 2\n"
5212 " %c_i32_${count} = OpConstant %i32 ${count}\n"
5213 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5214 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n"
5215 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n"
5216 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n"
5217 " %up_${type32} = OpTypePointer Uniform %${type32}\n"
5218 " %SSBO32 = OpTypeStruct %a${count}${type32}\n"
5219 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5220 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5221 " %PC16 = OpTypeStruct %a${count}${type16}\n"
5222 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
5223 " %pc16 = OpVariable %pp_PC16 PushConstant\n");
5224
5225 const StringTemplate decoration (
5226 "OpDecorate %a${count}${type16} ArrayStride 4\n"
5227 "OpDecorate %a${count}${type32} ArrayStride 8\n"
5228 "OpDecorate %SSBO32 BufferBlock\n"
5229 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5230 "OpDecorate %PC16 Block\n"
5231 "OpMemberDecorate %PC16 0 Offset 0\n"
5232 "OpDecorate %ssbo32 DescriptorSet 0\n"
5233 "OpDecorate %ssbo32 Binding 0\n");
5234
5235 { // signed int
5236 map<string, string> specs;
5237
5238 specs["base_type16"] = "i16";
5239 specs["type16"] = "v2i16";
5240 specs["type32"] = "v2i32";
5241 specs["signed"] = "1";
5242 specs["count"] = "32";
5243 specs["convert"] = "OpSConvert";
5244
5245 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5246 {
5247 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5248 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5249 string testName = "sint_vector";
5250 vector<deInt32> constIdxData;
5251
5252 if (useConstIdx)
5253 {
5254 constIdxData.reserve(numDataPoints);
5255
5256 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5257 constIdxData.push_back(sOutputs[constIdx * 2 + numIdx % 2]);
5258 }
5259
5260 specs["constarrayidx"] = de::toString(constIdx);
5261 if (useConstIdx)
5262 specs["arrayindex"] = "c_i32_ci";
5263 else
5264 specs["arrayindex"] = "30";
5265
5266 if (useConstIdx)
5267 testName += string("_const_idx_") + de::toString(constIdx);
5268
5269 resources.outputs.clear();
5270 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5271
5272 fragments["testfun"] = testFun.specialize(specs);
5273 fragments["pre_main"] = preMain.specialize(specs);
5274 fragments["decoration"] = decoration.specialize(specs);
5275
5276 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5277 }
5278 }
5279 { // unsigned int
5280 map<string, string> specs;
5281
5282 specs["base_type16"] = "u16";
5283 specs["type16"] = "v2u16";
5284 specs["type32"] = "v2u32";
5285 specs["signed"] = "0";
5286 specs["count"] = "32";
5287 specs["convert"] = "OpUConvert";
5288
5289 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5290 {
5291 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5292 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5293 string testName = "uint_vector";
5294 vector<deInt32> constIdxData;
5295
5296 if (useConstIdx)
5297 {
5298 constIdxData.reserve(numDataPoints);
5299
5300 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5301 constIdxData.push_back(uOutputs[constIdx * 2 + numIdx % 2]);
5302 }
5303
5304 specs["constarrayidx"] = de::toString(constIdx);
5305 if (useConstIdx)
5306 specs["arrayindex"] = "c_i32_ci";
5307 else
5308 specs["arrayindex"] = "30";
5309
5310 if (useConstIdx)
5311 testName += string("_const_idx_") + de::toString(constIdx);
5312
5313 resources.outputs.clear();
5314 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(useConstIdx ? constIdxData : uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5315
5316 fragments["testfun"] = testFun.specialize(specs);
5317 fragments["pre_main"] = preMain.specialize(specs);
5318 fragments["decoration"] = decoration.specialize(specs);
5319
5320 createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
5321 }
5322 }
5323 }
5324 }
5325
addGraphics16BitStorageUniformInt16To32Group(tcu::TestCaseGroup * testGroup)5326 void addGraphics16BitStorageUniformInt16To32Group (tcu::TestCaseGroup* testGroup)
5327 {
5328 de::Random rnd (deStringHash(testGroup->getName()));
5329 map<string, string> fragments;
5330 const deUint32 numDataPoints = 256;
5331 RGBA defaultColors[4];
5332 vector<deInt16> inputs = getInt16s(rnd, numDataPoints);
5333 vector<deInt32> sOutputs;
5334 vector<deInt32> uOutputs;
5335 vector<string> extensions;
5336 const deUint16 signBitMask = 0x8000;
5337 const deUint32 signExtendMask = 0xffff0000;
5338 const StringTemplate capabilities ("OpCapability ${cap}\n");
5339
5340 sOutputs.reserve(inputs.size());
5341 uOutputs.reserve(inputs.size());
5342
5343 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx)
5344 {
5345 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx]));
5346 if (inputs[numNdx] & signBitMask)
5347 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask));
5348 else
5349 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx]));
5350 }
5351
5352 extensions.push_back("VK_KHR_16bit_storage");
5353 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5354
5355 getDefaultColors(defaultColors);
5356
5357 struct IntegerFacts
5358 {
5359 const char* name;
5360 const char* type32;
5361 const char* type16;
5362 const char* opcode;
5363 bool isSigned;
5364 };
5365
5366 const IntegerFacts intFacts[] =
5367 {
5368 {"sint", "%i32", "%i16", "OpSConvert", true},
5369 {"uint", "%u32", "%u16", "OpUConvert", false},
5370 };
5371
5372 struct ConstantIndex
5373 {
5374 bool useConstantIndex;
5375 deUint32 constantIndex;
5376 };
5377
5378 ConstantIndex constantIndices[] =
5379 {
5380 { false, 0 },
5381 { true, 4 },
5382 { true, 5 },
5383 { true, 6 }
5384 };
5385
5386 const StringTemplate scalarPreMain (
5387 "${itype16} = OpTypeInt 16 ${signed}\n"
5388 "%c_i32_256 = OpConstant %i32 256\n"
5389 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5390 " %up_i32 = OpTypePointer Uniform ${itype32}\n"
5391 " %up_i16 = OpTypePointer Uniform ${itype16}\n"
5392 " %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n"
5393 " %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n"
5394 " %SSBO32 = OpTypeStruct %ra_i32\n"
5395 " %SSBO16 = OpTypeStruct %ra_i16\n"
5396 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5397 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5398 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5399 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5400
5401 const StringTemplate scalarDecoration (
5402 "OpDecorate %ra_i32 ArrayStride 4\n"
5403 "OpDecorate %ra_i16 ArrayStride ${arraystride}\n"
5404 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5405 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5406 "OpDecorate %SSBO32 BufferBlock\n"
5407 "OpDecorate %SSBO16 ${indecor}\n"
5408 "OpDecorate %ssbo32 DescriptorSet 0\n"
5409 "OpDecorate %ssbo16 DescriptorSet 0\n"
5410 "OpDecorate %ssbo32 Binding 1\n"
5411 "OpDecorate %ssbo16 Binding 0\n");
5412
5413 const StringTemplate scalarTestFunc (
5414 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5415 " %param = OpFunctionParameter %v4f32\n"
5416
5417 "%entry = OpLabel\n"
5418 " %i = OpVariable %fp_i32 Function\n"
5419 " OpStore %i %c_i32_0\n"
5420 " OpBranch %loop\n"
5421
5422 " %loop = OpLabel\n"
5423 " %15 = OpLoad %i32 %i\n"
5424 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
5425 " OpLoopMerge %merge %inc None\n"
5426 " OpBranchConditional %lt %write %merge\n"
5427
5428 "%write = OpLabel\n"
5429 " %30 = OpLoad %i32 %i\n"
5430 " %src = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5431 "%val16 = OpLoad ${itype16} %src\n"
5432 "%val32 = ${convert} ${itype32} %val16\n"
5433 " %dst = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n"
5434 " OpStore %dst %val32\n"
5435 " OpBranch %inc\n"
5436
5437 " %inc = OpLabel\n"
5438 " %37 = OpLoad %i32 %i\n"
5439 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5440 " OpStore %i %39\n"
5441 " OpBranch %loop\n"
5442 "%merge = OpLabel\n"
5443 " OpReturnValue %param\n"
5444
5445 "OpFunctionEnd\n");
5446
5447 const StringTemplate vecPreMain (
5448 "${itype16} = OpTypeInt 16 ${signed}\n"
5449 "%c_i32_128 = OpConstant %i32 128\n"
5450 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5451 "%v2itype16 = OpTypeVector ${itype16} 2\n"
5452 " %up_v2i32 = OpTypePointer Uniform ${v2itype32}\n"
5453 " %up_v2i16 = OpTypePointer Uniform %v2itype16\n"
5454 " %ra_v2i32 = OpTypeArray ${v2itype32} %c_i32_128\n"
5455 " %ra_v2i16 = OpTypeArray %v2itype16 %c_i32_128\n"
5456 " %SSBO32 = OpTypeStruct %ra_v2i32\n"
5457 " %SSBO16 = OpTypeStruct %ra_v2i16\n"
5458 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5459 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5460 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5461 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5462
5463 const StringTemplate vecDecoration (
5464 "OpDecorate %ra_v2i32 ArrayStride 8\n"
5465 "OpDecorate %ra_v2i16 ArrayStride ${arraystride}\n"
5466 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5467 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5468 "OpDecorate %SSBO32 BufferBlock\n"
5469 "OpDecorate %SSBO16 ${indecor}\n"
5470 "OpDecorate %ssbo32 DescriptorSet 0\n"
5471 "OpDecorate %ssbo16 DescriptorSet 0\n"
5472 "OpDecorate %ssbo32 Binding 1\n"
5473 "OpDecorate %ssbo16 Binding 0\n");
5474
5475 const StringTemplate vecTestFunc (
5476 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5477 " %param = OpFunctionParameter %v4f32\n"
5478
5479 "%entry = OpLabel\n"
5480 " %i = OpVariable %fp_i32 Function\n"
5481 " OpStore %i %c_i32_0\n"
5482 " OpBranch %loop\n"
5483
5484 " %loop = OpLabel\n"
5485 " %15 = OpLoad %i32 %i\n"
5486 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
5487 " OpLoopMerge %merge %inc None\n"
5488 " OpBranchConditional %lt %write %merge\n"
5489
5490 "%write = OpLabel\n"
5491 " %30 = OpLoad %i32 %i\n"
5492 " %src = OpAccessChain %up_v2i16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5493 "%val16 = OpLoad %v2itype16 %src\n"
5494 "%val32 = ${convert} ${v2itype32} %val16\n"
5495 " %dst = OpAccessChain %up_v2i32 %ssbo32 %c_i32_0 %30\n"
5496 " OpStore %dst %val32\n"
5497 " OpBranch %inc\n"
5498
5499 " %inc = OpLabel\n"
5500 " %37 = OpLoad %i32 %i\n"
5501 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5502 " OpStore %i %39\n"
5503 " OpBranch %loop\n"
5504 "%merge = OpLabel\n"
5505 " OpReturnValue %param\n"
5506
5507 "OpFunctionEnd\n");
5508
5509 struct Category
5510 {
5511 const char* name;
5512 const StringTemplate& preMain;
5513 const StringTemplate& decoration;
5514 const StringTemplate& testFunction;
5515 const deUint32 numElements;
5516 };
5517
5518 const Category categories[] =
5519 {
5520 {"scalar", scalarPreMain, scalarDecoration, scalarTestFunc, 1},
5521 {"vector", vecPreMain, vecDecoration, vecTestFunc, 2},
5522 };
5523
5524 const deUint32 minArrayStride[] = {2, 16};
5525
5526 for (deUint32 catIdx = 0; catIdx < DE_LENGTH_OF_ARRAY(categories); ++catIdx)
5527 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5528 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx)
5529 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5530 {
5531 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5532 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5533 map<string, string> specs;
5534 string name = string(CAPABILITIES[capIdx].name) + "_" + categories[catIdx].name + "_" + intFacts[factIdx].name;
5535 const deUint32 numElements = categories[catIdx].numElements;
5536 const deUint32 arrayStride = de::max(numElements * 2, minArrayStride[capIdx]);
5537
5538 specs["cap"] = CAPABILITIES[capIdx].cap;
5539 specs["indecor"] = CAPABILITIES[capIdx].decor;
5540 specs["arraystride"] = de::toString(arrayStride);
5541 specs["itype32"] = intFacts[factIdx].type32;
5542 specs["v2itype32"] = "%v2" + string(intFacts[factIdx].type32).substr(1);
5543 specs["v3itype32"] = "%v3" + string(intFacts[factIdx].type32).substr(1);
5544 specs["itype16"] = intFacts[factIdx].type16;
5545 if (intFacts[factIdx].isSigned)
5546 specs["signed"] = "1";
5547 else
5548 specs["signed"] = "0";
5549 specs["convert"] = intFacts[factIdx].opcode;
5550 specs["constarrayidx"] = de::toString(constIdx);
5551 if (useConstIdx)
5552 specs["arrayindex"] = "c_i32_ci";
5553 else
5554 specs["arrayindex"] = "30";
5555
5556 fragments["pre_main"] = categories[catIdx].preMain.specialize(specs);
5557 fragments["testfun"] = categories[catIdx].testFunction.specialize(specs);
5558 fragments["capability"] = capabilities.specialize(specs);
5559 fragments["decoration"] = categories[catIdx].decoration.specialize(specs);
5560
5561 GraphicsResources resources;
5562 vector<deInt16> inputsPadded;
5563 VulkanFeatures features;
5564
5565 for (size_t dataIdx = 0; dataIdx < inputs.size() / numElements; ++dataIdx)
5566 {
5567 for (deUint32 elementIdx = 0; elementIdx < numElements; ++elementIdx)
5568 inputsPadded.push_back(inputs[dataIdx * numElements + elementIdx]);
5569 for (deUint32 padIdx = 0; padIdx < arrayStride / 2 - numElements; ++padIdx)
5570 inputsPadded.push_back(0);
5571 }
5572
5573 resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inputsPadded)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5574
5575 vector<deInt32> constIdxOutputs;
5576 if (useConstIdx)
5577 {
5578 name += string("_const_idx_") + de::toString(constIdx);
5579 for (deUint32 i = 0; i < numDataPoints; i++)
5580 {
5581 deUint32 idx = constIdx * numElements + i % numElements;
5582 constIdxOutputs.push_back(intFacts[factIdx].isSigned ? sOutputs[idx] : uOutputs[idx]);
5583 }
5584 }
5585
5586 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5587 resources.outputs.clear();
5588 if (useConstIdx)
5589 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(constIdxOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5590 else if (intFacts[factIdx].isSigned)
5591 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(sOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5592 else
5593 resources.outputs.push_back(Resource(BufferSp(new Int32Buffer(uOutputs)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5594
5595 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5596 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5597 features.coreFeatures.fragmentStoresAndAtomics = true;
5598
5599 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5600 }
5601 }
5602
addGraphics16BitStorageUniformFloat16To32Group(tcu::TestCaseGroup * testGroup)5603 void addGraphics16BitStorageUniformFloat16To32Group (tcu::TestCaseGroup* testGroup)
5604 {
5605 de::Random rnd (deStringHash(testGroup->getName()));
5606 map<string, string> fragments;
5607 vector<string> extensions;
5608 const deUint32 numDataPoints = 256;
5609 RGBA defaultColors[4];
5610 const StringTemplate capabilities ("OpCapability ${cap}\n");
5611 vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints);
5612
5613 struct ConstantIndex
5614 {
5615 bool useConstantIndex;
5616 deUint32 constantIndex;
5617 };
5618
5619 ConstantIndex constantIndices[] =
5620 {
5621 { false, 0 },
5622 { true, 4 },
5623 { true, 5 },
5624 { true, 6 }
5625 };
5626
5627 extensions.push_back("VK_KHR_16bit_storage");
5628 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
5629
5630 getDefaultColors(defaultColors);
5631
5632 { // scalar cases
5633 const StringTemplate preMain (
5634 " %f16 = OpTypeFloat 16\n"
5635 "%c_i32_256 = OpConstant %i32 256\n"
5636 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5637 " %up_f32 = OpTypePointer Uniform %f32\n"
5638 " %up_f16 = OpTypePointer Uniform %f16\n"
5639 " %ra_f32 = OpTypeArray %f32 %c_i32_256\n"
5640 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
5641 " %SSBO32 = OpTypeStruct %ra_f32\n"
5642 " %SSBO16 = OpTypeStruct %ra_f16\n"
5643 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5644 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5645 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5646 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5647
5648 const StringTemplate decoration (
5649 "OpDecorate %ra_f32 ArrayStride 4\n"
5650 "OpDecorate %ra_f16 ArrayStride ${arraystride}\n"
5651 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5652 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5653 "OpDecorate %SSBO32 BufferBlock\n"
5654 "OpDecorate %SSBO16 ${indecor}\n"
5655 "OpDecorate %ssbo32 DescriptorSet 0\n"
5656 "OpDecorate %ssbo16 DescriptorSet 0\n"
5657 "OpDecorate %ssbo32 Binding 1\n"
5658 "OpDecorate %ssbo16 Binding 0\n");
5659
5660 // ssbo32[] <- convert ssbo16[] to 32bit float
5661 const StringTemplate testFun (
5662 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5663 " %param = OpFunctionParameter %v4f32\n"
5664
5665 "%entry = OpLabel\n"
5666 " %i = OpVariable %fp_i32 Function\n"
5667 " OpStore %i %c_i32_0\n"
5668 " OpBranch %loop\n"
5669
5670 " %loop = OpLabel\n"
5671 " %15 = OpLoad %i32 %i\n"
5672 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
5673 " OpLoopMerge %merge %inc None\n"
5674 " OpBranchConditional %lt %write %merge\n"
5675
5676 "%write = OpLabel\n"
5677 " %30 = OpLoad %i32 %i\n"
5678 " %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5679 "%val16 = OpLoad %f16 %src\n"
5680 "%val32 = OpFConvert %f32 %val16\n"
5681 " %dst = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n"
5682 " OpStore %dst %val32\n"
5683 " OpBranch %inc\n"
5684
5685 " %inc = OpLabel\n"
5686 " %37 = OpLoad %i32 %i\n"
5687 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5688 " OpStore %i %39\n"
5689 " OpBranch %loop\n"
5690
5691 "%merge = OpLabel\n"
5692 " OpReturnValue %param\n"
5693
5694 "OpFunctionEnd\n");
5695
5696 const deUint32 arrayStrides[] = {2, 16};
5697
5698 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5699 {
5700 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5701 {
5702 GraphicsResources resources;
5703 map<string, string> specs;
5704 VulkanFeatures features;
5705 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float";
5706 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5707 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5708
5709 specs["cap"] = CAPABILITIES[capIdx].cap;
5710 specs["indecor"] = CAPABILITIES[capIdx].decor;
5711 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
5712 specs["constarrayidx"] = de::toString(constIdx);
5713 if (useConstIdx)
5714 specs["arrayindex"] = "c_i32_ci";
5715 else
5716 specs["arrayindex"] = "30";
5717
5718 fragments["capability"] = capabilities.specialize(specs);
5719 fragments["decoration"] = decoration.specialize(specs);
5720 fragments["pre_main"] = preMain.specialize(specs);
5721 fragments["testfun"] = testFun.specialize(specs);
5722
5723 vector<deFloat16> inputData;
5724 for (size_t dataIdx = 0; dataIdx < float16Data.size(); ++dataIdx)
5725 {
5726 inputData.push_back(float16Data[dataIdx]);
5727 for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 1; ++padIdx)
5728 inputData.push_back(deFloat16(0.0f));
5729 }
5730
5731 vector<float> float32Data;
5732 float32Data.reserve(numDataPoints);
5733 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5734 float32Data.push_back(deFloat16To32(float16Data[useConstIdx ? constIdx : numIdx]));
5735
5736 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5737 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5738 resources.verifyIO = check32BitFloats;
5739 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5740
5741 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5742 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5743 features.coreFeatures.fragmentStoresAndAtomics = true;
5744
5745 if (useConstIdx)
5746 testName += string("_const_idx_") + de::toString(constIdx);
5747
5748 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5749 }
5750 }
5751 }
5752
5753 { // vector cases
5754 const StringTemplate preMain (
5755 " %f16 = OpTypeFloat 16\n"
5756 "%c_i32_128 = OpConstant %i32 128\n"
5757 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
5758 " %v2f16 = OpTypeVector %f16 2\n"
5759 " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5760 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5761 " %ra_v2f32 = OpTypeArray %v2f32 %c_i32_128\n"
5762 " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n"
5763 " %SSBO32 = OpTypeStruct %ra_v2f32\n"
5764 " %SSBO16 = OpTypeStruct %ra_v2f16\n"
5765 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5766 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5767 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5768 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
5769
5770 const StringTemplate decoration (
5771 "OpDecorate %ra_v2f32 ArrayStride 8\n"
5772 "OpDecorate %ra_v2f16 ArrayStride ${arraystride}\n"
5773 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5774 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5775 "OpDecorate %SSBO32 BufferBlock\n"
5776 "OpDecorate %SSBO16 ${indecor}\n"
5777 "OpDecorate %ssbo32 DescriptorSet 0\n"
5778 "OpDecorate %ssbo16 DescriptorSet 0\n"
5779 "OpDecorate %ssbo32 Binding 1\n"
5780 "OpDecorate %ssbo16 Binding 0\n");
5781
5782 // ssbo32[] <- convert ssbo16[] to 32bit float
5783 const StringTemplate testFun (
5784 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5785 " %param = OpFunctionParameter %v4f32\n"
5786
5787 "%entry = OpLabel\n"
5788 " %i = OpVariable %fp_i32 Function\n"
5789 " OpStore %i %c_i32_0\n"
5790 " OpBranch %loop\n"
5791
5792 " %loop = OpLabel\n"
5793 " %15 = OpLoad %i32 %i\n"
5794 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
5795 " OpLoopMerge %merge %inc None\n"
5796 " OpBranchConditional %lt %write %merge\n"
5797
5798 "%write = OpLabel\n"
5799 " %30 = OpLoad %i32 %i\n"
5800 " %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
5801 "%val16 = OpLoad %v2f16 %src\n"
5802 "%val32 = OpFConvert %v2f32 %val16\n"
5803 " %dst = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30\n"
5804 " OpStore %dst %val32\n"
5805 " OpBranch %inc\n"
5806
5807 " %inc = OpLabel\n"
5808 " %37 = OpLoad %i32 %i\n"
5809 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5810 " OpStore %i %39\n"
5811 " OpBranch %loop\n"
5812
5813 "%merge = OpLabel\n"
5814 " OpReturnValue %param\n"
5815
5816 "OpFunctionEnd\n");
5817
5818 const deUint32 arrayStrides[] = {4, 16};
5819
5820 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
5821 {
5822 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5823 {
5824 GraphicsResources resources;
5825 map<string, string> specs;
5826 VulkanFeatures features;
5827 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float";
5828 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
5829 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
5830
5831 specs["cap"] = CAPABILITIES[capIdx].cap;
5832 specs["indecor"] = CAPABILITIES[capIdx].decor;
5833 specs["arraystride"] = de::toString(arrayStrides[capIdx]);
5834 specs["constarrayidx"] = de::toString(constIdx);
5835 if (useConstIdx)
5836 specs["arrayindex"] = "c_i32_ci";
5837 else
5838 specs["arrayindex"] = "30";
5839
5840 fragments["capability"] = capabilities.specialize(specs);
5841 fragments["decoration"] = decoration.specialize(specs);
5842 fragments["pre_main"] = preMain.specialize(specs);
5843 fragments["testfun"] = testFun.specialize(specs);
5844
5845 vector<deFloat16> inputData;
5846 for (size_t dataIdx = 0; dataIdx < float16Data.size() / 2; ++dataIdx)
5847 {
5848 inputData.push_back(float16Data[dataIdx * 2]);
5849 inputData.push_back(float16Data[dataIdx * 2 + 1]);
5850 for (deUint32 padIdx = 0; padIdx < arrayStrides[capIdx] / 2 - 2; ++padIdx)
5851 inputData.push_back(deFloat16(0.0f));
5852 }
5853
5854 vector<float> float32Data;
5855 float32Data.reserve(numDataPoints);
5856 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5857 float32Data.push_back(deFloat16To32(float16Data[constantIndices[constIndexIdx].useConstantIndex ? (constantIndices[constIndexIdx].constantIndex * 2 + numIdx % 2) : numIdx]));
5858
5859 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5860 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5861 resources.verifyIO = check32BitFloats;
5862 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5863
5864 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5865 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5866 features.coreFeatures.fragmentStoresAndAtomics = true;
5867
5868 if (constantIndices[constIndexIdx].useConstantIndex)
5869 testName += string("_const_idx_") + de::toString(constantIndices[constIndexIdx].constantIndex);
5870
5871 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5872 }
5873 }
5874 }
5875
5876 { // matrix cases
5877 fragments["pre_main"] =
5878 " %c_i32_32 = OpConstant %i32 32\n"
5879 " %f16 = OpTypeFloat 16\n"
5880 " %v2f16 = OpTypeVector %f16 2\n"
5881 " %m4x2f32 = OpTypeMatrix %v2f32 4\n"
5882 " %m4x2f16 = OpTypeMatrix %v2f16 4\n"
5883 " %up_v2f32 = OpTypePointer Uniform %v2f32\n"
5884 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
5885 "%a8m4x2f32 = OpTypeArray %m4x2f32 %c_i32_32\n"
5886 "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n"
5887 " %SSBO32 = OpTypeStruct %a8m4x2f32\n"
5888 " %SSBO16 = OpTypeStruct %a8m4x2f16\n"
5889 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
5890 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
5891 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n"
5892 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
5893
5894 const StringTemplate decoration (
5895 "OpDecorate %a8m4x2f32 ArrayStride 32\n"
5896 "OpDecorate %a8m4x2f16 ArrayStride 16\n"
5897 "OpMemberDecorate %SSBO32 0 Offset 0\n"
5898 "OpMemberDecorate %SSBO32 0 ColMajor\n"
5899 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n"
5900 "OpMemberDecorate %SSBO16 0 Offset 0\n"
5901 "OpMemberDecorate %SSBO16 0 ColMajor\n"
5902 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"
5903 "OpDecorate %SSBO32 BufferBlock\n"
5904 "OpDecorate %SSBO16 ${indecor}\n"
5905 "OpDecorate %ssbo32 DescriptorSet 0\n"
5906 "OpDecorate %ssbo16 DescriptorSet 0\n"
5907 "OpDecorate %ssbo32 Binding 1\n"
5908 "OpDecorate %ssbo16 Binding 0\n");
5909
5910 fragments["testfun"] =
5911 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
5912 " %param = OpFunctionParameter %v4f32\n"
5913
5914 "%entry = OpLabel\n"
5915 " %i = OpVariable %fp_i32 Function\n"
5916 " OpStore %i %c_i32_0\n"
5917 " OpBranch %loop\n"
5918
5919 " %loop = OpLabel\n"
5920 " %15 = OpLoad %i32 %i\n"
5921 " %lt = OpSLessThan %bool %15 %c_i32_32\n"
5922 " OpLoopMerge %merge %inc None\n"
5923 " OpBranchConditional %lt %write %merge\n"
5924
5925 " %write = OpLabel\n"
5926 " %30 = OpLoad %i32 %i\n"
5927 " %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
5928 " %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
5929 " %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
5930 " %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
5931 "%val16_0 = OpLoad %v2f16 %src_0\n"
5932 "%val16_1 = OpLoad %v2f16 %src_1\n"
5933 "%val16_2 = OpLoad %v2f16 %src_2\n"
5934 "%val16_3 = OpLoad %v2f16 %src_3\n"
5935 "%val32_0 = OpFConvert %v2f32 %val16_0\n"
5936 "%val32_1 = OpFConvert %v2f32 %val16_1\n"
5937 "%val32_2 = OpFConvert %v2f32 %val16_2\n"
5938 "%val32_3 = OpFConvert %v2f32 %val16_3\n"
5939 " %dst_0 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n"
5940 " %dst_1 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n"
5941 " %dst_2 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n"
5942 " %dst_3 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n"
5943 " OpStore %dst_0 %val32_0\n"
5944 " OpStore %dst_1 %val32_1\n"
5945 " OpStore %dst_2 %val32_2\n"
5946 " OpStore %dst_3 %val32_3\n"
5947 " OpBranch %inc\n"
5948
5949 " %inc = OpLabel\n"
5950 " %37 = OpLoad %i32 %i\n"
5951 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
5952 " OpStore %i %39\n"
5953 " OpBranch %loop\n"
5954
5955 "%merge = OpLabel\n"
5956 " OpReturnValue %param\n"
5957
5958 "OpFunctionEnd\n";
5959
5960 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
5961 {
5962 GraphicsResources resources;
5963 map<string, string> specs;
5964 VulkanFeatures features;
5965 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float";
5966
5967 specs["cap"] = CAPABILITIES[capIdx].cap;
5968 specs["indecor"] = CAPABILITIES[capIdx].decor;
5969
5970 fragments["capability"] = capabilities.specialize(specs);
5971 fragments["decoration"] = decoration.specialize(specs);
5972
5973 vector<float> float32Data;
5974 float32Data.reserve(numDataPoints);
5975 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
5976 float32Data.push_back(deFloat16To32(float16Data[numIdx]));
5977
5978 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5979 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
5980 resources.verifyIO = check32BitFloats;
5981 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
5982
5983 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
5984 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
5985 features.coreFeatures.fragmentStoresAndAtomics = true;
5986
5987 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
5988 }
5989 }
5990 }
5991
addGraphics16BitStorageUniformStructFloat16To32Group(tcu::TestCaseGroup * testGroup)5992 void addGraphics16BitStorageUniformStructFloat16To32Group (tcu::TestCaseGroup* testGroup)
5993 {
5994 de::Random rnd (deStringHash(testGroup->getName()));
5995 map<string, string> fragments;
5996 vector<string> extensions;
5997 RGBA defaultColors[4];
5998 const StringTemplate capabilities ("OpCapability ${cap}\n");
5999 vector<float> float32Data (getStructSize(SHADERTEMPLATE_STRIDE32BIT_STD430), 0.0f);
6000
6001 extensions.push_back("VK_KHR_16bit_storage");
6002 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6003
6004 getDefaultColors(defaultColors);
6005
6006 const StringTemplate preMain (
6007 "\n"
6008 "${types}\n"
6009 "\n"
6010 "%zero = OpConstant %i32 0\n"
6011 "%c_i32_5 = OpConstant %i32 5\n"
6012 "%c_i32_6 = OpConstant %i32 6\n"
6013 "%c_i32_7 = OpConstant %i32 7\n"
6014 "%c_i32_8 = OpConstant %i32 8\n"
6015 "%c_i32_9 = OpConstant %i32 9\n"
6016 "%c_i32_11 = OpConstant %i32 11\n"
6017 "\n"
6018 "%c_u32_7 = OpConstant %u32 7\n"
6019 "%c_u32_11 = OpConstant %u32 11\n"
6020 "\n"
6021 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
6022 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
6023 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
6024 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
6025 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
6026 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
6027 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
6028 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
6029 "\n"
6030 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
6031 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
6032 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
6033 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
6034 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
6035 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
6036 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
6037 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
6038 "\n"
6039 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
6040 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
6041 "%SSBO_IN = OpTypeStruct %f16StructArr7\n"
6042 "%SSBO_OUT = OpTypeStruct %f32StructArr7\n"
6043 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6044 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6045 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6046 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
6047 "\n");
6048
6049 const StringTemplate decoration (
6050 "${strideF16}"
6051 "\n"
6052 "${strideF32}"
6053 "\n"
6054 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6055 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6056 "OpDecorate %SSBO_IN ${indecor}\n"
6057 "OpDecorate %SSBO_OUT BufferBlock\n"
6058 "OpDecorate %ssboIN DescriptorSet 0\n"
6059 "OpDecorate %ssboOUT DescriptorSet 0\n"
6060 "OpDecorate %ssboIN Binding 0\n"
6061 "OpDecorate %ssboOUT Binding 1\n"
6062 "\n");
6063
6064 fragments["testfun"] =
6065 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6066 " %param = OpFunctionParameter %v4f32\n"
6067 "%label = OpLabel\n"
6068 "%loopNdx = OpVariable %fp_i32 Function\n"
6069 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
6070
6071 "OpStore %loopNdx %zero\n"
6072 "OpBranch %loop\n"
6073 "%loop = OpLabel\n"
6074 "OpLoopMerge %merge %13 None\n"
6075 "OpBranch %14\n"
6076 "%14 = OpLabel\n"
6077 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
6078 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
6079 "OpBranchConditional %18 %11 %merge\n"
6080 "%11 = OpLabel\n"
6081 "\n"
6082 "%f16src = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %zero\n"
6083 "%val_f16 = OpLoad %f16 %f16src\n"
6084 "%val_f32 = OpFConvert %f32 %val_f16\n"
6085 "%f32dst = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %zero\n"
6086 "OpStore %f32dst %val_f32\n"
6087 "\n"
6088 "%v2f16src = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
6089 "%val_v2f16 = OpLoad %v2f16 %v2f16src\n"
6090 "%val_v2f32 = OpFConvert %v2f32 %val_v2f16\n"
6091 "%v2f32dst = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
6092 "OpStore %v2f32dst %val_v2f32\n"
6093 "\n"
6094 "%v3f16src = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
6095 "%val_v3f16 = OpLoad %v3f16 %v3f16src\n"
6096 "%val_v3f32 = OpFConvert %v3f32 %val_v3f16\n"
6097 "%v3f32dst = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
6098 "OpStore %v3f32dst %val_v3f32\n"
6099 "\n"
6100 "%v4f16src = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
6101 "%val_v4f16 = OpLoad %v4f16 %v4f16src\n"
6102 "%val_v4f32 = OpFConvert %v4f32 %val_v4f16\n"
6103 "%v4f32dst = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
6104 "OpStore %v4f32dst %val_v4f32\n"
6105 "\n"
6106 "%f16src2 = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
6107 "%val2_f16 = OpLoad %f16 %f16src2\n"
6108 "%val2_f32 = OpFConvert %f32 %val2_f16\n"
6109 "%f32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
6110 "OpStore %f32dst2 %val2_f32\n"
6111 "\n"
6112 "OpStore %insideLoopNdx %zero\n"
6113 "OpBranch %loopInside\n"
6114 "%loopInside = OpLabel\n"
6115 "OpLoopMerge %92 %93 None\n"
6116 "OpBranch %94\n"
6117 "%94 = OpLabel\n"
6118 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
6119 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
6120 "OpBranchConditional %96 %91 %92\n"
6121 "\n"
6122 "%91 = OpLabel\n"
6123 "\n"
6124 "%v2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6125 "%val2_v2f16 = OpLoad %v2f16 %v2f16src2\n"
6126 "%val2_v2f32 = OpFConvert %v2f32 %val2_v2f16\n"
6127 "%v2f32dst2 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6128 "OpStore %v2f32dst2 %val2_v2f32\n"
6129 "\n"
6130 "%v3f16src2 = OpAccessChain %v3f16ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6131 "%val2_v3f16 = OpLoad %v3f16 %v3f16src2\n"
6132 "%val2_v3f32 = OpFConvert %v3f32 %val2_v3f16\n"
6133 "%v3f32dst2 = OpAccessChain %v3f32ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6134 "OpStore %v3f32dst2 %val2_v3f32\n"
6135 "\n"
6136 //struct {f16, v2f16[3]}
6137 "%Sf16src = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6138 "%Sval_f16 = OpLoad %f16 %Sf16src\n"
6139 "%Sval_f32 = OpFConvert %f32 %Sval_f16\n"
6140 "%Sf32dst2 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6141 "OpStore %Sf32dst2 %Sval_f32\n"
6142 "\n"
6143 "%Sv2f16src0 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6144 "%Sv2f16_0 = OpLoad %v2f16 %Sv2f16src0\n"
6145 "%Sv2f32_0 = OpFConvert %v2f32 %Sv2f16_0\n"
6146 "%Sv2f32dst_0 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6147 "OpStore %Sv2f32dst_0 %Sv2f32_0\n"
6148 "\n"
6149 "%Sv2f16src1 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6150 "%Sv2f16_1 = OpLoad %v2f16 %Sv2f16src1\n"
6151 "%Sv2f32_1 = OpFConvert %v2f32 %Sv2f16_1\n"
6152 "%Sv2f32dst_1 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6153 "OpStore %Sv2f32dst_1 %Sv2f32_1\n"
6154 "\n"
6155 "%Sv2f16src2 = OpAccessChain %v2f16ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6156 "%Sv2f16_2 = OpLoad %v2f16 %Sv2f16src2\n"
6157 "%Sv2f32_2 = OpFConvert %v2f32 %Sv2f16_2\n"
6158 "%Sv2f32dst_2 = OpAccessChain %v2f32ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6159 "OpStore %Sv2f32dst_2 %Sv2f32_2\n"
6160 "\n"
6161 //Array with 3 elements
6162 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
6163 "OpSelectionMerge %BlockIf None\n"
6164 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
6165 "%LabelIf = OpLabel\n"
6166 " %f16src3 = OpAccessChain %f16ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6167 " %val3_f16 = OpLoad %f16 %f16src3\n"
6168 " %val3_f32 = OpFConvert %f32 %val3_f16\n"
6169 " %f32dst3 = OpAccessChain %f32ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6170 " OpStore %f32dst3 %val3_f32\n"
6171 "\n"
6172 " %v4f16src2 = OpAccessChain %v4f16ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6173 " %val2_v4f16 = OpLoad %v4f16 %v4f16src2\n"
6174 " %val2_v4f32 = OpFConvert %v4f32 %val2_v4f16\n"
6175 " %v4f32dst2 = OpAccessChain %v4f32ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6176 " OpStore %v4f32dst2 %val2_v4f32\n"
6177 "OpBranch %BlockIf\n"
6178 "%BlockIf = OpLabel\n"
6179 "\n"
6180 "OpBranch %93\n"
6181 "%93 = OpLabel\n"
6182 "%132 = OpLoad %i32 %insideLoopNdx\n"
6183 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
6184 "OpStore %insideLoopNdx %133\n"
6185 "OpBranch %loopInside\n"
6186 "\n"
6187 "%92 = OpLabel\n"
6188 "OpBranch %13\n"
6189 "%13 = OpLabel\n"
6190 "%134 = OpLoad %i32 %loopNdx\n"
6191 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
6192 "OpStore %loopNdx %135\n"
6193 "OpBranch %loop\n"
6194
6195 "%merge = OpLabel\n"
6196 " OpReturnValue %param\n"
6197 " OpFunctionEnd\n";
6198
6199 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6200 {
6201 vector<deFloat16> float16Data = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data16bitStd430(rnd) : data16bitStd140(rnd);
6202 GraphicsResources resources;
6203 map<string, string> specs;
6204 VulkanFeatures features;
6205 string testName = string(CAPABILITIES[capIdx].name);
6206
6207 specs["cap"] = CAPABILITIES[capIdx].cap;
6208 specs["indecor"] = CAPABILITIES[capIdx].decor;
6209 specs["strideF16"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE16BIT_STD430 : SHADERTEMPLATE_STRIDE16BIT_STD140);
6210 specs["strideF32"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE32BIT_STD430);
6211 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
6212
6213 fragments["capability"] = capabilities.specialize(specs);
6214 fragments["decoration"] = decoration.specialize(specs);
6215 fragments["pre_main"] = preMain.specialize(specs);
6216
6217 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), CAPABILITIES[capIdx].dtype));
6218 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6219 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>;
6220
6221 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6222 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6223 features.coreFeatures.fragmentStoresAndAtomics = true;
6224
6225 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6226 }
6227 }
6228
addGraphics16BitStorageUniformStructFloat32To16Group(tcu::TestCaseGroup * testGroup)6229 void addGraphics16BitStorageUniformStructFloat32To16Group (tcu::TestCaseGroup* testGroup)
6230 {
6231 de::Random rnd (deStringHash(testGroup->getName()));
6232 map<string, string> fragments;
6233 vector<string> extensions;
6234 RGBA defaultColors[4];
6235 const StringTemplate capabilities ("OpCapability ${cap}\n");
6236 vector<deUint16> float16Data (getStructSize(SHADERTEMPLATE_STRIDE16BIT_STD430), 0u);
6237
6238 extensions.push_back("VK_KHR_16bit_storage");
6239 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6240
6241 getDefaultColors(defaultColors);
6242
6243 const StringTemplate preMain (
6244 "\n"
6245 "${types}\n"
6246 "\n"
6247 "%zero = OpConstant %i32 0\n"
6248 "%c_i32_5 = OpConstant %i32 5\n"
6249 "%c_i32_6 = OpConstant %i32 6\n"
6250 "%c_i32_7 = OpConstant %i32 7\n"
6251 "%c_i32_8 = OpConstant %i32 8\n"
6252 "%c_i32_9 = OpConstant %i32 9\n"
6253 "%c_i32_11 = OpConstant %i32 11\n"
6254 "\n"
6255 "%c_u32_7 = OpConstant %u32 7\n"
6256 "%c_u32_11 = OpConstant %u32 11\n"
6257 "\n"
6258 "%f16arr3 = OpTypeArray %f16 %c_u32_3\n"
6259 "%v2f16arr3 = OpTypeArray %v2f16 %c_u32_3\n"
6260 "%v2f16arr11 = OpTypeArray %v2f16 %c_u32_11\n"
6261 "%v3f16arr11 = OpTypeArray %v3f16 %c_u32_11\n"
6262 "%v4f16arr3 = OpTypeArray %v4f16 %c_u32_3\n"
6263 "%struct16 = OpTypeStruct %f16 %v2f16arr3\n"
6264 "%struct16arr11 = OpTypeArray %struct16 %c_u32_11\n"
6265 "%f16Struct = OpTypeStruct %f16 %v2f16 %v3f16 %v4f16 %f16arr3 %struct16arr11 %v2f16arr11 %f16 %v3f16arr11 %v4f16arr3\n"
6266 "\n"
6267 "%f32arr3 = OpTypeArray %f32 %c_u32_3\n"
6268 "%v2f32arr3 = OpTypeArray %v2f32 %c_u32_3\n"
6269 "%v2f32arr11 = OpTypeArray %v2f32 %c_u32_11\n"
6270 "%v3f32arr11 = OpTypeArray %v3f32 %c_u32_11\n"
6271 "%v4f32arr3 = OpTypeArray %v4f32 %c_u32_3\n"
6272 "%struct32 = OpTypeStruct %f32 %v2f32arr3\n"
6273 "%struct32arr11 = OpTypeArray %struct32 %c_u32_11\n"
6274 "%f32Struct = OpTypeStruct %f32 %v2f32 %v3f32 %v4f32 %f32arr3 %struct32arr11 %v2f32arr11 %f32 %v3f32arr11 %v4f32arr3\n"
6275 "\n"
6276 "%f16StructArr7 = OpTypeArray %f16Struct %c_u32_7\n"
6277 "%f32StructArr7 = OpTypeArray %f32Struct %c_u32_7\n"
6278 "%SSBO_IN = OpTypeStruct %f32StructArr7\n"
6279 "%SSBO_OUT = OpTypeStruct %f16StructArr7\n"
6280 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6281 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6282 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6283 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n"
6284 "\n");
6285
6286 const StringTemplate decoration (
6287 "${strideF16}"
6288 "\n"
6289 "${strideF32}"
6290 "\n"
6291 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6292 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6293 "OpDecorate %SSBO_IN ${indecor}\n"
6294 "OpDecorate %SSBO_OUT BufferBlock\n"
6295 "OpDecorate %ssboIN DescriptorSet 0\n"
6296 "OpDecorate %ssboOUT DescriptorSet 0\n"
6297 "OpDecorate %ssboIN Binding 0\n"
6298 "OpDecorate %ssboOUT Binding 1\n"
6299 "\n");
6300
6301 fragments["testfun"] =
6302 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6303 "%param = OpFunctionParameter %v4f32\n"
6304 "%label = OpLabel\n"
6305 "%loopNdx = OpVariable %fp_i32 Function\n"
6306 "%insideLoopNdx = OpVariable %fp_i32 Function\n"
6307
6308 "OpStore %loopNdx %zero\n"
6309 "OpBranch %loop\n"
6310 "%loop = OpLabel\n"
6311 "OpLoopMerge %merge %13 None\n"
6312 "OpBranch %14\n"
6313 "%14 = OpLabel\n"
6314 "%valLoopNdx = OpLoad %i32 %loopNdx\n"
6315 "%18 = OpSLessThan %bool %valLoopNdx %c_i32_7\n"
6316 "OpBranchConditional %18 %11 %merge\n"
6317 "%11 = OpLabel\n"
6318 "\n"
6319 "%f32src = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %zero\n"
6320 "%val_f32 = OpLoad %f32 %f32src\n"
6321 "%val_f16 = OpFConvert %f16 %val_f32\n"
6322 "%f16dst = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %zero\n"
6323 "OpStore %f16dst %val_f16\n"
6324 "\n"
6325 "%v2f32src = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_1\n"
6326 "%val_v2f32 = OpLoad %v2f32 %v2f32src\n"
6327 "%val_v2f16 = OpFConvert %v2f16 %val_v2f32\n"
6328 "%v2f16dst = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_1\n"
6329 "OpStore %v2f16dst %val_v2f16\n"
6330 "\n"
6331 "%v3f32src = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_2\n"
6332 "%val_v3f32 = OpLoad %v3f32 %v3f32src\n"
6333 "%val_v3f16 = OpFConvert %v3f16 %val_v3f32\n"
6334 "%v3f16dst = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_2\n"
6335 "OpStore %v3f16dst %val_v3f16\n"
6336 "\n"
6337 "%v4f32src = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_3\n"
6338 "%val_v4f32 = OpLoad %v4f32 %v4f32src\n"
6339 "%val_v4f16 = OpFConvert %v4f16 %val_v4f32\n"
6340 "%v4f16dst = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_3\n"
6341 "OpStore %v4f16dst %val_v4f16\n"
6342 "\n"
6343 "%f32src2 = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_7\n"
6344 "%val2_f32 = OpLoad %f32 %f32src2\n"
6345 "%val2_f16 = OpFConvert %f16 %val2_f32\n"
6346 "%f16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_7\n"
6347 "OpStore %f16dst2 %val2_f16\n"
6348 "\n"
6349 "OpStore %insideLoopNdx %zero\n"
6350 "OpBranch %loopInside\n"
6351 "%loopInside = OpLabel\n"
6352 "OpLoopMerge %92 %93 None\n"
6353 "OpBranch %94\n"
6354 "%94 = OpLabel\n"
6355 "%valInsideLoopNdx = OpLoad %i32 %insideLoopNdx\n"
6356 "%96 = OpSLessThan %bool %valInsideLoopNdx %c_i32_11\n"
6357 "OpBranchConditional %96 %91 %92\n"
6358 "\n"
6359 "%91 = OpLabel\n"
6360 "\n"
6361 //struct {f16, v2f16[3]}
6362 "%Sf32src = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6363 "%Sval_f32 = OpLoad %f32 %Sf32src\n"
6364 "%Sval_f16 = OpFConvert %f16 %Sval_f32\n"
6365 "%Sf16dst2 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %zero\n"
6366 "OpStore %Sf16dst2 %Sval_f16\n"
6367 "\n"
6368 "%Sv2f32src0 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6369 "%Sv2f32_0 = OpLoad %v2f32 %Sv2f32src0\n"
6370 "%Sv2f16_0 = OpFConvert %v2f16 %Sv2f32_0\n"
6371 "%Sv2f16dst_0 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %zero\n"
6372 "OpStore %Sv2f16dst_0 %Sv2f16_0\n"
6373 "\n"
6374 "%Sv2f32src1 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6375 "%Sv2f32_1 = OpLoad %v2f32 %Sv2f32src1\n"
6376 "%Sv2f16_1 = OpFConvert %v2f16 %Sv2f32_1\n"
6377 "%Sv2f16dst_1 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_1\n"
6378 "OpStore %Sv2f16dst_1 %Sv2f16_1\n"
6379 "\n"
6380 "%Sv2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6381 "%Sv2f32_2 = OpLoad %v2f32 %Sv2f32src2\n"
6382 "%Sv2f16_2 = OpFConvert %v2f16 %Sv2f32_2\n"
6383 "%Sv2f16dst_2 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_5 %valInsideLoopNdx %c_i32_1 %c_i32_2\n"
6384 "OpStore %Sv2f16dst_2 %Sv2f16_2\n"
6385 "\n"
6386
6387 "%v2f32src2 = OpAccessChain %v2f32ptr %ssboIN %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6388 "%val2_v2f32 = OpLoad %v2f32 %v2f32src2\n"
6389 "%val2_v2f16 = OpFConvert %v2f16 %val2_v2f32\n"
6390 "%v2f16dst2 = OpAccessChain %v2f16ptr %ssboOUT %zero %valLoopNdx %c_i32_6 %valInsideLoopNdx\n"
6391 "OpStore %v2f16dst2 %val2_v2f16\n"
6392 "\n"
6393 "%v3f32src2 = OpAccessChain %v3f32ptr %ssboIN %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6394 "%val2_v3f32 = OpLoad %v3f32 %v3f32src2\n"
6395 "%val2_v3f16 = OpFConvert %v3f16 %val2_v3f32\n"
6396 "%v3f16dst2 = OpAccessChain %v3f16ptr %ssboOUT %zero %valLoopNdx %c_i32_8 %valInsideLoopNdx\n"
6397 "OpStore %v3f16dst2 %val2_v3f16\n"
6398 "\n"
6399
6400 //Array with 3 elements
6401 "%LessThan3 = OpSLessThan %bool %valInsideLoopNdx %c_i32_3\n"
6402 "OpSelectionMerge %BlockIf None\n"
6403 "OpBranchConditional %LessThan3 %LabelIf %BlockIf\n"
6404 " %LabelIf = OpLabel\n"
6405 " %f32src3 = OpAccessChain %f32ptr %ssboIN %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6406 " %val3_f32 = OpLoad %f32 %f32src3\n"
6407 " %val3_f16 = OpFConvert %f16 %val3_f32\n"
6408 " %f16dst3 = OpAccessChain %f16ptr %ssboOUT %zero %valLoopNdx %c_i32_4 %valInsideLoopNdx\n"
6409 " OpStore %f16dst3 %val3_f16\n"
6410 "\n"
6411 " %v4f32src2 = OpAccessChain %v4f32ptr %ssboIN %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6412 " %val2_v4f32 = OpLoad %v4f32 %v4f32src2\n"
6413 " %val2_v4f16 = OpFConvert %v4f16 %val2_v4f32\n"
6414 " %v4f16dst2 = OpAccessChain %v4f16ptr %ssboOUT %zero %valLoopNdx %c_i32_9 %valInsideLoopNdx\n"
6415 " OpStore %v4f16dst2 %val2_v4f16\n"
6416 "OpBranch %BlockIf\n"
6417 "%BlockIf = OpLabel\n"
6418
6419 "OpBranch %93\n"
6420 "%93 = OpLabel\n"
6421 "%132 = OpLoad %i32 %insideLoopNdx\n"
6422 "%133 = OpIAdd %i32 %132 %c_i32_1\n"
6423 "OpStore %insideLoopNdx %133\n"
6424 "OpBranch %loopInside\n"
6425 "\n"
6426 "%92 = OpLabel\n"
6427 "OpBranch %13\n"
6428 "%13 = OpLabel\n"
6429 "%134 = OpLoad %i32 %loopNdx\n"
6430 "%135 = OpIAdd %i32 %134 %c_i32_1\n"
6431 "OpStore %loopNdx %135\n"
6432 "OpBranch %loop\n"
6433
6434 "%merge = OpLabel\n"
6435 " OpReturnValue %param\n"
6436 " OpFunctionEnd\n";
6437
6438 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6439 {
6440 map<string, string> specs;
6441 string testName = string(CAPABILITIES[capIdx].name);
6442 vector<float> float32Data = (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? data32bitStd430(rnd) : data32bitStd140(rnd);
6443 GraphicsResources resources;
6444
6445 specs["cap"] = "StorageUniformBufferBlock16";
6446 specs["indecor"] = CAPABILITIES[capIdx].decor;
6447 specs["strideF16"] = getStructShaderComponet(SHADERTEMPLATE_STRIDE16BIT_STD430);
6448 specs["strideF32"] = getStructShaderComponet((VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == CAPABILITIES[capIdx].dtype) ? SHADERTEMPLATE_STRIDE32BIT_STD430 : SHADERTEMPLATE_STRIDE32BIT_STD140);
6449 specs["types"] = getStructShaderComponet(SHADERTEMPLATE_TYPES);
6450
6451 fragments["capability"] = capabilities.specialize(specs);
6452 fragments["decoration"] = decoration.specialize(specs);
6453 fragments["pre_main"] = preMain.specialize(specs);
6454
6455 resources.inputs.push_back(Resource(BufferSp(new Float32Buffer(float32Data)), CAPABILITIES[capIdx].dtype));
6456 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6457 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>;
6458
6459 VulkanFeatures features;
6460
6461 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6462 features.coreFeatures.fragmentStoresAndAtomics = true;
6463 features.ext16BitStorage.storageBuffer16BitAccess = true;
6464
6465 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6466 }
6467 }
6468
addGraphics16bitStructMixedTypesGroup(tcu::TestCaseGroup * group)6469 void addGraphics16bitStructMixedTypesGroup (tcu::TestCaseGroup* group)
6470 {
6471 de::Random rnd (deStringHash(group->getName()));
6472 map<string, string> fragments;
6473 vector<string> extensions;
6474 RGBA defaultColors[4];
6475 const StringTemplate capabilities ("OpCapability StorageUniformBufferBlock16\n"
6476 "${cap}\n");
6477 vector<deInt16> outData (getStructSize(SHADERTEMPLATE_STRIDEMIX_STD430), 0u);
6478
6479 extensions.push_back("VK_KHR_16bit_storage");
6480 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
6481
6482 getDefaultColors(defaultColors);
6483
6484 const StringTemplate preMain (
6485 "\n"//Types
6486 "%i16 = OpTypeInt 16 1\n"
6487 "%v2i16 = OpTypeVector %i16 2\n"
6488 "%v3i16 = OpTypeVector %i16 3\n"
6489 "%v4i16 = OpTypeVector %i16 4\n"
6490 "\n"//Consta value
6491 "%zero = OpConstant %i32 0\n"
6492 "%c_i32_5 = OpConstant %i32 5\n"
6493 "%c_i32_6 = OpConstant %i32 6\n"
6494 "%c_i32_7 = OpConstant %i32 7\n"
6495 "%c_i32_8 = OpConstant %i32 8\n"
6496 "%c_i32_9 = OpConstant %i32 9\n"
6497 "%c_i32_10 = OpConstant %i32 10\n"
6498 "%c_i32_11 = OpConstant %i32 11\n"
6499 "%c_u32_7 = OpConstant %u32 7\n"
6500 "%c_u32_11 = OpConstant %u32 11\n"
6501 "\n"//Arrays & Structs
6502 "%v2b16NestedArr11In = OpTypeArray %v2i16 %c_u32_11\n"
6503 "%b32NestedArr11In = OpTypeArray %i32 %c_u32_11\n"
6504 "%sb16Arr11In = OpTypeArray %i16 %c_u32_11\n"
6505 "%sb32Arr11In = OpTypeArray %i32 %c_u32_11\n"
6506 "%sNestedIn = OpTypeStruct %i16 %i32 %v2b16NestedArr11In %b32NestedArr11In\n"
6507 "%sNestedArr11In = OpTypeArray %sNestedIn %c_u32_11\n"
6508 "%structIn = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11In %sb16Arr11In %sb32Arr11In\n"
6509 "%structArr7In = OpTypeArray %structIn %c_u32_7\n"
6510 "%v2b16NestedArr11Out = OpTypeArray %v2i16 %c_u32_11\n"
6511 "%b32NestedArr11Out = OpTypeArray %i32 %c_u32_11\n"
6512 "%sb16Arr11Out = OpTypeArray %i16 %c_u32_11\n"
6513 "%sb32Arr11Out = OpTypeArray %i32 %c_u32_11\n"
6514 "%sNestedOut = OpTypeStruct %i16 %i32 %v2b16NestedArr11Out %b32NestedArr11Out\n"
6515 "%sNestedArr11Out = OpTypeArray %sNestedOut %c_u32_11\n"
6516 "%structOut = OpTypeStruct %i16 %i32 %v2i16 %v2i32 %v3i16 %v3i32 %v4i16 %v4i32 %sNestedArr11Out %sb16Arr11Out %sb32Arr11Out\n"
6517 "%structArr7Out = OpTypeArray %structOut %c_u32_7\n"
6518 "\n"//Pointers
6519 "%i16outPtr = OpTypePointer Uniform %i16\n"
6520 "%v2i16outPtr = OpTypePointer Uniform %v2i16\n"
6521 "%v3i16outPtr = OpTypePointer Uniform %v3i16\n"
6522 "%v4i16outPtr = OpTypePointer Uniform %v4i16\n"
6523 "%i32outPtr = OpTypePointer Uniform %i32\n"
6524 "%v2i32outPtr = OpTypePointer Uniform %v2i32\n"
6525 "%v3i32outPtr = OpTypePointer Uniform %v3i32\n"
6526 "%v4i32outPtr = OpTypePointer Uniform %v4i32\n"
6527 "%uvec3ptr = OpTypePointer Input %v3u32\n"
6528 "\n"//SSBO IN
6529 "%SSBO_IN = OpTypeStruct %structArr7In\n"
6530 "%up_SSBOIN = OpTypePointer Uniform %SSBO_IN\n"
6531 "%ssboIN = OpVariable %up_SSBOIN Uniform\n"
6532 "\n"//SSBO OUT
6533 "%SSBO_OUT = OpTypeStruct %structArr7Out\n"
6534 "%up_SSBOOUT = OpTypePointer Uniform %SSBO_OUT\n"
6535 "%ssboOUT = OpVariable %up_SSBOOUT Uniform\n");
6536
6537 const StringTemplate decoration (
6538 "${OutOffsets}"
6539 "${InOffsets}"
6540 "\n"//SSBO IN
6541 "OpMemberDecorate %SSBO_IN 0 Offset 0\n"
6542 "OpDecorate %ssboIN DescriptorSet 0\n"
6543 "OpDecorate %SSBO_IN ${storage}\n"
6544 "OpDecorate %SSBO_OUT BufferBlock\n"
6545 "OpDecorate %ssboIN Binding 0\n"
6546 "\n"//SSBO OUT
6547 "OpMemberDecorate %SSBO_OUT 0 Offset 0\n"
6548 "OpDecorate %ssboOUT DescriptorSet 0\n"
6549 "OpDecorate %ssboOUT Binding 1\n");
6550
6551 const StringTemplate testFun (
6552 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6553 "%param = OpFunctionParameter %v4f32\n"
6554 "%label = OpLabel\n"
6555 "%ndxArrx = OpVariable %fp_i32 Function\n"
6556 "%ndxArry = OpVariable %fp_i32 Function\n"
6557 "%ndxArrz = OpVariable %fp_i32 Function\n"
6558 "${xBeginLoop}"
6559 "\n"//strutOut.b16 = strutIn.b16
6560 "%inP1 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %zero\n"
6561 "%inV1 = OpLoad %i16 %inP1\n"
6562 "%outP1 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %zero\n"
6563 "OpStore %outP1 %inV1\n"
6564 "\n"//strutOut.b32 = strutIn.b32
6565 "%inP2 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_1\n"
6566 "%inV2 = OpLoad %i32 %inP2\n"
6567 "%outP2 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_1\n"
6568 "OpStore %outP2 %inV2\n"
6569 "\n"//strutOut.v2b16 = strutIn.v2b16
6570 "%inP3 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_2\n"
6571 "%inV3 = OpLoad %v2i16 %inP3\n"
6572 "%outP3 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_2\n"
6573 "OpStore %outP3 %inV3\n"
6574 "\n"//strutOut.v2b32 = strutIn.v2b32
6575 "%inP4 = OpAccessChain %v2i32${inPtr} %ssboIN %zero %Valx %c_i32_3\n"
6576 "%inV4 = OpLoad %v2i32 %inP4\n"
6577 "%outP4 = OpAccessChain %v2i32outPtr %ssboOUT %zero %Valx %c_i32_3\n"
6578 "OpStore %outP4 %inV4\n"
6579 "\n"//strutOut.v3b16 = strutIn.v3b16
6580 "%inP5 = OpAccessChain %v3i16${inPtr} %ssboIN %zero %Valx %c_i32_4\n"
6581 "%inV5 = OpLoad %v3i16 %inP5\n"
6582 "%outP5 = OpAccessChain %v3i16outPtr %ssboOUT %zero %Valx %c_i32_4\n"
6583 "OpStore %outP5 %inV5\n"
6584 "\n"//strutOut.v3b32 = strutIn.v3b32
6585 "%inP6 = OpAccessChain %v3i32${inPtr} %ssboIN %zero %Valx %c_i32_5\n"
6586 "%inV6 = OpLoad %v3i32 %inP6\n"
6587 "%outP6 = OpAccessChain %v3i32outPtr %ssboOUT %zero %Valx %c_i32_5\n"
6588 "OpStore %outP6 %inV6\n"
6589 "\n"//strutOut.v4b16 = strutIn.v4b16
6590 "%inP7 = OpAccessChain %v4i16${inPtr} %ssboIN %zero %Valx %c_i32_6\n"
6591 "%inV7 = OpLoad %v4i16 %inP7\n"
6592 "%outP7 = OpAccessChain %v4i16outPtr %ssboOUT %zero %Valx %c_i32_6\n"
6593 "OpStore %outP7 %inV7\n"
6594 "\n"//strutOut.v4b32 = strutIn.v4b32
6595 "%inP8 = OpAccessChain %v4i32${inPtr} %ssboIN %zero %Valx %c_i32_7\n"
6596 "%inV8 = OpLoad %v4i32 %inP8\n"
6597 "%outP8 = OpAccessChain %v4i32outPtr %ssboOUT %zero %Valx %c_i32_7\n"
6598 "OpStore %outP8 %inV8\n"
6599 "${yBeginLoop}"
6600 "\n"//strutOut.b16[y] = strutIn.b16[y]
6601 "%inP9 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_9 %Valy\n"
6602 "%inV9 = OpLoad %i16 %inP9\n"
6603 "%outP9 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_9 %Valy\n"
6604 "OpStore %outP9 %inV9\n"
6605 "\n"//strutOut.b32[y] = strutIn.b32[y]
6606 "%inP10 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_10 %Valy\n"
6607 "%inV10 = OpLoad %i32 %inP10\n"
6608 "%outP10 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_10 %Valy\n"
6609 "OpStore %outP10 %inV10\n"
6610 "\n"//strutOut.strutNestedOut[y].b16 = strutIn.strutNestedIn[y].b16
6611 "%inP11 = OpAccessChain %i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %zero\n"
6612 "%inV11 = OpLoad %i16 %inP11\n"
6613 "%outP11 = OpAccessChain %i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %zero\n"
6614 "OpStore %outP11 %inV11\n"
6615 "\n"//strutOut.strutNestedOut[y].b32 = strutIn.strutNestedIn[y].b32
6616 "%inP12 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6617 "%inV12 = OpLoad %i32 %inP12\n"
6618 "%outP12 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_1\n"
6619 "OpStore %outP12 %inV12\n"
6620 "${zBeginLoop}"
6621 "\n"//strutOut.strutNestedOut[y].v2b16[valNdx] = strutIn.strutNestedIn[y].v2b16[valNdx]
6622 "%inP13 = OpAccessChain %v2i16${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6623 "%inV13 = OpLoad %v2i16 %inP13\n"
6624 "%outP13 = OpAccessChain %v2i16outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_2 %Valz\n"
6625 "OpStore %outP13 %inV13\n"
6626 "\n"//strutOut.strutNestedOut[y].b32[valNdx] = strutIn.strutNestedIn[y].b32[valNdx]
6627 "%inP14 = OpAccessChain %i32${inPtr} %ssboIN %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6628 "%inV14 = OpLoad %i32 %inP14\n"
6629 "%outP14 = OpAccessChain %i32outPtr %ssboOUT %zero %Valx %c_i32_8 %Valy %c_i32_3 %Valz\n"
6630 "OpStore %outP14 %inV14\n"
6631 "${zEndLoop}"
6632 "${yEndLoop}"
6633 "${xEndLoop}"
6634 "\n"
6635 "OpBranch %ExitLabel\n"
6636 "%ExitLabel = OpLabel\n"
6637 "OpReturnValue %param\n"
6638 "OpFunctionEnd\n");
6639
6640 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6641 { // int
6642 const bool isUniform = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == CAPABILITIES[capIdx].dtype;
6643 vector<deInt16> inData = isUniform ? dataMixStd140(rnd) : dataMixStd430(rnd);
6644 GraphicsResources resources;
6645 map<string, string> specsLoop;
6646 map<string, string> specsOffset;
6647 map<string, string> specs;
6648 VulkanFeatures features;
6649 string testName = string(CAPABILITIES[capIdx].name);
6650
6651 specsLoop["exeCount"] = "c_i32_7";
6652 specsLoop["loopName"] = "x";
6653 specs["xBeginLoop"] = beginLoop(specsLoop);
6654 specs["xEndLoop"] = endLoop(specsLoop);
6655
6656 specsLoop["exeCount"] = "c_i32_11";
6657 specsLoop["loopName"] = "y";
6658 specs["yBeginLoop"] = beginLoop(specsLoop);
6659 specs["yEndLoop"] = endLoop(specsLoop);
6660
6661 specsLoop["exeCount"] = "c_i32_11";
6662 specsLoop["loopName"] = "z";
6663 specs["zBeginLoop"] = beginLoop(specsLoop);
6664 specs["zEndLoop"] = endLoop(specsLoop);
6665
6666 specs["storage"] = isUniform ? "Block" : "BufferBlock";
6667 specs["cap"] = isUniform ?"OpCapability " + string( CAPABILITIES[capIdx].cap) : "";
6668 specs["inPtr"] = "outPtr";
6669 specsOffset["InOut"] = "In";
6670 specs["InOffsets"] = StringTemplate(isUniform ? getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD140) : getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6671 specsOffset["InOut"] = "Out";
6672 specs["OutOffsets"] = StringTemplate(getStructShaderComponet(SHADERTEMPLATE_STRIDEMIX_STD430)).specialize(specsOffset);
6673
6674 fragments["capability"] = capabilities.specialize(specs);
6675 fragments["decoration"] = decoration.specialize(specs);
6676 fragments["pre_main"] = preMain.specialize(specs);
6677 fragments["testfun"] = testFun.specialize(specs);
6678
6679 resources.verifyIO = isUniform ? graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD140, SHADERTEMPLATE_STRIDEMIX_STD430> : graphicsCheckStruct<deInt16, deInt16, SHADERTEMPLATE_STRIDEMIX_STD430, SHADERTEMPLATE_STRIDEMIX_STD430>;
6680 resources.inputs.push_back(Resource(BufferSp(new Int16Buffer(inData)), CAPABILITIES[capIdx].dtype));
6681 resources.outputs.push_back(Resource(BufferSp(new Int16Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6682
6683 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6684 features.coreFeatures.vertexPipelineStoresAndAtomics = true;
6685 features.coreFeatures.fragmentStoresAndAtomics = true;
6686
6687 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, group, features);
6688 }
6689 }
6690
addGraphics16BitStorageInputOutputFloat16To64Group(tcu::TestCaseGroup * testGroup)6691 void addGraphics16BitStorageInputOutputFloat16To64Group (tcu::TestCaseGroup* testGroup)
6692 {
6693 de::Random rnd (deStringHash(testGroup->getName()));
6694 RGBA defaultColors[4];
6695 vector<string> extensions;
6696 map<string, string> fragments = passthruFragments();
6697 const deUint32 numDataPoints = 64;
6698 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
6699 vector<double> float64Data;
6700
6701 float64Data.reserve(numDataPoints);
6702 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
6703 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
6704
6705 extensions.push_back("VK_KHR_16bit_storage");
6706
6707 fragments["capability"] =
6708 "OpCapability StorageInputOutput16\n"
6709 "OpCapability Float64\n";
6710 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
6711
6712 getDefaultColors(defaultColors);
6713
6714 struct Case
6715 {
6716 const char* name;
6717 const char* interfaceOpCall;
6718 const char* interfaceOpFunc;
6719 const char* preMain;
6720 const char* inputType;
6721 const char* outputType;
6722 deUint32 numPerCase;
6723 deUint32 numElements;
6724 };
6725
6726 Case cases[] =
6727 {
6728 { // Scalar cases
6729 "scalar",
6730
6731 "OpFConvert %f64",
6732 "",
6733
6734 " %f16 = OpTypeFloat 16\n"
6735 " %f64 = OpTypeFloat 64\n"
6736 " %v4f64 = OpTypeVector %f64 4\n"
6737 " %ip_f16 = OpTypePointer Input %f16\n"
6738 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
6739 " %ip_a3f16 = OpTypePointer Input %a3f16\n"
6740 "%f64_f16_function = OpTypeFunction %f64 %f16\n"
6741 " %a3f64 = OpTypeArray %f64 %c_i32_3\n"
6742 " %op_f64 = OpTypePointer Output %f64\n"
6743 " %op_a3f64 = OpTypePointer Output %a3f64\n",
6744
6745 "f16",
6746 "f64",
6747 4,
6748 1,
6749 },
6750 { // Vector cases
6751 "vector",
6752
6753 "OpFConvert %v2f64",
6754 "",
6755
6756 " %f16 = OpTypeFloat 16\n"
6757 " %v2f16 = OpTypeVector %f16 2\n"
6758 " %f64 = OpTypeFloat 64\n"
6759 " %v2f64 = OpTypeVector %f64 2\n"
6760 " %v4f64 = OpTypeVector %f64 4\n"
6761 " %ip_v2f16 = OpTypePointer Input %v2f16\n"
6762 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
6763 " %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n"
6764 "%v2f64_v2f16_function = OpTypeFunction %v2f64 %v2f16\n"
6765 " %a3v2f64 = OpTypeArray %v2f64 %c_i32_3\n"
6766 " %op_f64 = OpTypePointer Output %f64\n"
6767 " %op_v2f64 = OpTypePointer Output %v2f64\n"
6768 " %op_v4f64 = OpTypePointer Output %v4f64\n"
6769 " %op_a3v2f64 = OpTypePointer Output %a3v2f64\n",
6770
6771 "v2f16",
6772 "v2f64",
6773 2 * 4,
6774 2,
6775 }
6776 };
6777
6778 VulkanFeatures requiredFeatures;
6779
6780 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
6781 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
6782
6783 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
6784 {
6785 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
6786 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
6787 fragments["pre_main"] = cases[caseIdx].preMain;
6788
6789 fragments["input_type"] = cases[caseIdx].inputType;
6790 fragments["output_type"] = cases[caseIdx].outputType;
6791
6792 GraphicsInterfaces interfaces;
6793 const deUint32 numPerCase = cases[caseIdx].numPerCase;
6794 vector<deFloat16> subInputs (numPerCase);
6795 vector<double> subOutputs (numPerCase);
6796
6797 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
6798 {
6799 string testName = string(cases[caseIdx].name) + numberToString(caseNdx);
6800
6801 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
6802 {
6803 subInputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx];
6804 subOutputs[numNdx] = float64Data[caseNdx * numPerCase + numNdx];
6805 }
6806 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))),
6807 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT64), BufferSp(new Float64Buffer(subOutputs))));
6808 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
6809 }
6810 }
6811 }
6812
addGraphics16BitStorageUniformFloat16To64Group(tcu::TestCaseGroup * testGroup)6813 void addGraphics16BitStorageUniformFloat16To64Group (tcu::TestCaseGroup* testGroup)
6814 {
6815 de::Random rnd (deStringHash(testGroup->getName()));
6816 map<string, string> fragments;
6817 vector<string> extensions;
6818 const deUint32 numDataPoints = 256;
6819 RGBA defaultColors[4];
6820 const StringTemplate capabilities ("OpCapability ${cap}\n"
6821 "OpCapability Float64\n");
6822 vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints);
6823
6824 struct ConstantIndex
6825 {
6826 bool useConstantIndex;
6827 deUint32 constantIndex;
6828 };
6829
6830 ConstantIndex constantIndices[] =
6831 {
6832 { false, 0 },
6833 { true, 4 },
6834 { true, 5 },
6835 { true, 6 }
6836 };
6837
6838 extensions.push_back("VK_KHR_16bit_storage");
6839
6840 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
6841
6842 getDefaultColors(defaultColors);
6843
6844 { // scalar cases
6845 const StringTemplate preMain (
6846 " %f16 = OpTypeFloat 16\n"
6847 " %f64 = OpTypeFloat 64\n"
6848 "%c_i32_256 = OpConstant %i32 256\n"
6849 " %c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
6850 " %up_f64 = OpTypePointer Uniform %f64\n"
6851 " %up_f16 = OpTypePointer Uniform %f16\n"
6852 " %ra_f64 = OpTypeArray %f64 %c_i32_256\n"
6853 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
6854 " %SSBO64 = OpTypeStruct %ra_f64\n"
6855 " %SSBO16 = OpTypeStruct %ra_f16\n"
6856 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
6857 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
6858 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
6859 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
6860
6861 const StringTemplate decoration (
6862 "OpDecorate %ra_f64 ArrayStride 8\n"
6863 "OpDecorate %ra_f16 ArrayStride ${stride16}\n"
6864 "OpMemberDecorate %SSBO64 0 Offset 0\n"
6865 "OpMemberDecorate %SSBO16 0 Offset 0\n"
6866 "OpDecorate %SSBO64 BufferBlock\n"
6867 "OpDecorate %SSBO16 ${indecor}\n"
6868 "OpDecorate %ssbo64 DescriptorSet 0\n"
6869 "OpDecorate %ssbo16 DescriptorSet 0\n"
6870 "OpDecorate %ssbo64 Binding 1\n"
6871 "OpDecorate %ssbo16 Binding 0\n");
6872
6873 // ssbo64[] <- convert ssbo16[] to 64bit float
6874 const StringTemplate testFun (
6875 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6876 " %param = OpFunctionParameter %v4f32\n"
6877
6878 "%entry = OpLabel\n"
6879 " %i = OpVariable %fp_i32 Function\n"
6880 " OpStore %i %c_i32_0\n"
6881 " OpBranch %loop\n"
6882
6883 " %loop = OpLabel\n"
6884 " %15 = OpLoad %i32 %i\n"
6885 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
6886 " OpLoopMerge %merge %inc None\n"
6887 " OpBranchConditional %lt %write %merge\n"
6888
6889 "%write = OpLabel\n"
6890 " %30 = OpLoad %i32 %i\n"
6891 " %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
6892 "%val16 = OpLoad %f16 %src\n"
6893 "%val64 = OpFConvert %f64 %val16\n"
6894 " %dst = OpAccessChain %up_f64 %ssbo64 %c_i32_0 %30\n"
6895 " OpStore %dst %val64\n"
6896 " OpBranch %inc\n"
6897
6898 " %inc = OpLabel\n"
6899 " %37 = OpLoad %i32 %i\n"
6900 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
6901 " OpStore %i %39\n"
6902 " OpBranch %loop\n"
6903
6904 "%merge = OpLabel\n"
6905 " OpReturnValue %param\n"
6906
6907 "OpFunctionEnd\n");
6908
6909 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
6910 {
6911 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
6912 {
6913 GraphicsResources resources;
6914 map<string, string> specs;
6915 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float";
6916 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
6917 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
6918 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6919
6920 specs["cap"] = CAPABILITIES[capIdx].cap;
6921 specs["indecor"] = CAPABILITIES[capIdx].decor;
6922 specs["constarrayidx"] = de::toString(constIdx);
6923 specs["stride16"] = isUBO ? "16" : "2";
6924
6925 if (useConstIdx)
6926 specs["arrayindex"] = "c_i32_ci";
6927 else
6928 specs["arrayindex"] = "30";
6929
6930 fragments["capability"] = capabilities.specialize(specs);
6931 fragments["decoration"] = decoration.specialize(specs);
6932 fragments["pre_main"] = preMain.specialize(specs);
6933 fragments["testfun"] = testFun.specialize(specs);
6934
6935 vector<double> float64Data;
6936 float64Data.reserve(numDataPoints);
6937 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
6938 float64Data.push_back(deFloat16To64(float16Data[useConstIdx ? constIdx : numIdx]));
6939
6940 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data, isUBO ? 14 : 0)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6941 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
6942 resources.verifyIO = check64BitFloats;
6943 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
6944
6945 if (useConstIdx)
6946 testName += string("_const_idx_") + de::toString(constIdx);
6947
6948 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
6949
6950 features.coreFeatures.shaderFloat64 = DE_TRUE;
6951
6952 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
6953 }
6954 }
6955 }
6956
6957 { // vector cases
6958 const StringTemplate preMain (
6959 " %f16 = OpTypeFloat 16\n"
6960 " %f64 = OpTypeFloat 64\n"
6961 "%c_i32_128 = OpConstant %i32 128\n"
6962 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
6963 " %v2f16 = OpTypeVector %f16 2\n"
6964 " %v2f64 = OpTypeVector %f64 2\n"
6965 " %up_v2f64 = OpTypePointer Uniform %v2f64\n"
6966 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
6967 " %ra_v2f64 = OpTypeArray %v2f64 %c_i32_128\n"
6968 " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n"
6969 " %SSBO64 = OpTypeStruct %ra_v2f64\n"
6970 " %SSBO16 = OpTypeStruct %ra_v2f16\n"
6971 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
6972 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
6973 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
6974 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n");
6975
6976 const StringTemplate decoration (
6977 "OpDecorate %ra_v2f64 ArrayStride 16\n"
6978 "OpDecorate %ra_v2f16 ArrayStride ${stride16}\n"
6979 "OpMemberDecorate %SSBO64 0 Offset 0\n"
6980 "OpMemberDecorate %SSBO16 0 Offset 0\n"
6981 "OpDecorate %SSBO64 BufferBlock\n"
6982 "OpDecorate %SSBO16 ${indecor}\n"
6983 "OpDecorate %ssbo64 DescriptorSet 0\n"
6984 "OpDecorate %ssbo16 DescriptorSet 0\n"
6985 "OpDecorate %ssbo64 Binding 1\n"
6986 "OpDecorate %ssbo16 Binding 0\n");
6987
6988 // ssbo64[] <- convert ssbo16[] to 64bit float
6989 const StringTemplate testFun (
6990 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
6991 " %param = OpFunctionParameter %v4f32\n"
6992
6993 "%entry = OpLabel\n"
6994 " %i = OpVariable %fp_i32 Function\n"
6995 " OpStore %i %c_i32_0\n"
6996 " OpBranch %loop\n"
6997
6998 " %loop = OpLabel\n"
6999 " %15 = OpLoad %i32 %i\n"
7000 " %lt = OpSLessThan %bool %15 %c_i32_128\n"
7001 " OpLoopMerge %merge %inc None\n"
7002 " OpBranchConditional %lt %write %merge\n"
7003
7004 "%write = OpLabel\n"
7005 " %30 = OpLoad %i32 %i\n"
7006 " %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %${arrayindex}\n"
7007 "%val16 = OpLoad %v2f16 %src\n"
7008 "%val64 = OpFConvert %v2f64 %val16\n"
7009 " %dst = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30\n"
7010 " OpStore %dst %val64\n"
7011 " OpBranch %inc\n"
7012
7013 " %inc = OpLabel\n"
7014 " %37 = OpLoad %i32 %i\n"
7015 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7016 " OpStore %i %39\n"
7017 " OpBranch %loop\n"
7018
7019 "%merge = OpLabel\n"
7020 " OpReturnValue %param\n"
7021
7022 "OpFunctionEnd\n");
7023
7024 for (deUint32 constIndexIdx = 0; constIndexIdx < DE_LENGTH_OF_ARRAY(constantIndices); ++constIndexIdx)
7025 {
7026 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7027 {
7028 GraphicsResources resources;
7029 map<string, string> specs;
7030 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float";
7031 bool useConstIdx = constantIndices[constIndexIdx].useConstantIndex;
7032 deUint32 constIdx = constantIndices[constIndexIdx].constantIndex;
7033 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7034
7035 specs["cap"] = CAPABILITIES[capIdx].cap;
7036 specs["indecor"] = CAPABILITIES[capIdx].decor;
7037 specs["constarrayidx"] = de::toString(constIdx);
7038 specs["stride16"] = isUBO ? "16" : "4";
7039
7040 if (useConstIdx)
7041 specs["arrayindex"] = "c_i32_ci";
7042 else
7043 specs["arrayindex"] = "30";
7044
7045 fragments["capability"] = capabilities.specialize(specs);
7046 fragments["decoration"] = decoration.specialize(specs);
7047 fragments["pre_main"] = preMain.specialize(specs);
7048 fragments["testfun"] = testFun.specialize(specs);
7049
7050 vector<double> float64Data;
7051 float64Data.reserve(numDataPoints);
7052 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7053 float64Data.push_back(deFloat16To64(float16Data[constantIndices[constIndexIdx].useConstantIndex ? (constantIndices[constIndexIdx].constantIndex * 2 + numIdx % 2) : numIdx]));
7054
7055 vector<tcu::Vector<deFloat16, 2> > float16Vec2Data(float16Data.size() / 2);
7056 for (size_t elemIdx = 0; elemIdx < float16Data.size(); elemIdx++)
7057 {
7058 float16Vec2Data[elemIdx / 2][elemIdx % 2] = float16Data[elemIdx];
7059 }
7060 typedef Buffer<tcu::Vector<deFloat16, 2> > Float16Vec2Buffer;
7061 resources.inputs.push_back(Resource(BufferSp(new Float16Vec2Buffer(float16Vec2Data, isUBO ? 12 : 0)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7062 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7063 resources.verifyIO = check64BitFloats;
7064 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
7065
7066 if (constantIndices[constIndexIdx].useConstantIndex)
7067 testName += string("_const_idx_") + de::toString(constantIndices[constIndexIdx].constantIndex);
7068
7069 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7070
7071 features.coreFeatures.shaderFloat64 = DE_TRUE;
7072
7073 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7074 }
7075 }
7076 }
7077
7078 { // matrix cases
7079 fragments["pre_main"] =
7080 " %c_i32_32 = OpConstant %i32 32\n"
7081 " %f16 = OpTypeFloat 16\n"
7082 " %f64 = OpTypeFloat 64\n"
7083 " %v2f16 = OpTypeVector %f16 2\n"
7084 " %v2f64 = OpTypeVector %f64 2\n"
7085 " %m4x2f64 = OpTypeMatrix %v2f64 4\n"
7086 " %m4x2f16 = OpTypeMatrix %v2f16 4\n"
7087 " %up_v2f64 = OpTypePointer Uniform %v2f64\n"
7088 " %up_v2f16 = OpTypePointer Uniform %v2f16\n"
7089 "%a8m4x2f64 = OpTypeArray %m4x2f64 %c_i32_32\n"
7090 "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n"
7091 " %SSBO64 = OpTypeStruct %a8m4x2f64\n"
7092 " %SSBO16 = OpTypeStruct %a8m4x2f16\n"
7093 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7094 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7095 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7096 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7097
7098 const StringTemplate decoration (
7099 "OpDecorate %a8m4x2f64 ArrayStride 64\n"
7100 "OpDecorate %a8m4x2f16 ArrayStride 16\n"
7101 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7102 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7103 "OpMemberDecorate %SSBO64 0 MatrixStride 16\n"
7104 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7105 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7106 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"
7107 "OpDecorate %SSBO64 BufferBlock\n"
7108 "OpDecorate %SSBO16 ${indecor}\n"
7109 "OpDecorate %ssbo64 DescriptorSet 0\n"
7110 "OpDecorate %ssbo16 DescriptorSet 0\n"
7111 "OpDecorate %ssbo64 Binding 1\n"
7112 "OpDecorate %ssbo16 Binding 0\n");
7113
7114 fragments["testfun"] =
7115 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7116 " %param = OpFunctionParameter %v4f32\n"
7117
7118 "%entry = OpLabel\n"
7119 " %i = OpVariable %fp_i32 Function\n"
7120 " OpStore %i %c_i32_0\n"
7121 " OpBranch %loop\n"
7122
7123 " %loop = OpLabel\n"
7124 " %15 = OpLoad %i32 %i\n"
7125 " %lt = OpSLessThan %bool %15 %c_i32_32\n"
7126 " OpLoopMerge %merge %inc None\n"
7127 " OpBranchConditional %lt %write %merge\n"
7128
7129 " %write = OpLabel\n"
7130 " %30 = OpLoad %i32 %i\n"
7131 " %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
7132 " %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
7133 " %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
7134 " %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
7135 "%val16_0 = OpLoad %v2f16 %src_0\n"
7136 "%val16_1 = OpLoad %v2f16 %src_1\n"
7137 "%val16_2 = OpLoad %v2f16 %src_2\n"
7138 "%val16_3 = OpLoad %v2f16 %src_3\n"
7139 "%val64_0 = OpFConvert %v2f64 %val16_0\n"
7140 "%val64_1 = OpFConvert %v2f64 %val16_1\n"
7141 "%val64_2 = OpFConvert %v2f64 %val16_2\n"
7142 "%val64_3 = OpFConvert %v2f64 %val16_3\n"
7143 " %dst_0 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_0\n"
7144 " %dst_1 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7145 " %dst_2 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_2\n"
7146 " %dst_3 = OpAccessChain %up_v2f64 %ssbo64 %c_i32_0 %30 %c_i32_3\n"
7147 " OpStore %dst_0 %val64_0\n"
7148 " OpStore %dst_1 %val64_1\n"
7149 " OpStore %dst_2 %val64_2\n"
7150 " OpStore %dst_3 %val64_3\n"
7151 " OpBranch %inc\n"
7152
7153 " %inc = OpLabel\n"
7154 " %37 = OpLoad %i32 %i\n"
7155 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7156 " OpStore %i %39\n"
7157 " OpBranch %loop\n"
7158
7159 "%merge = OpLabel\n"
7160 " OpReturnValue %param\n"
7161
7162 "OpFunctionEnd\n";
7163
7164 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7165 {
7166 GraphicsResources resources;
7167 map<string, string> specs;
7168 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float";
7169
7170 specs["cap"] = CAPABILITIES[capIdx].cap;
7171 specs["indecor"] = CAPABILITIES[capIdx].decor;
7172
7173 fragments["capability"] = capabilities.specialize(specs);
7174 fragments["decoration"] = decoration.specialize(specs);
7175
7176 vector<double> float64Data;
7177 float64Data.reserve(numDataPoints);
7178 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7179 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
7180
7181 resources.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7182 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7183 resources.verifyIO = check64BitFloats;
7184 resources.inputs.back().setDescriptorType(CAPABILITIES[capIdx].dtype);
7185
7186 VulkanFeatures features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7187
7188 features.coreFeatures.shaderFloat64 = DE_TRUE;
7189
7190 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7191 }
7192 }
7193 }
7194
addGraphics16BitStoragePushConstantFloat16To64Group(tcu::TestCaseGroup * testGroup)7195 void addGraphics16BitStoragePushConstantFloat16To64Group (tcu::TestCaseGroup* testGroup)
7196 {
7197 de::Random rnd (deStringHash(testGroup->getName()));
7198 map<string, string> fragments;
7199 RGBA defaultColors[4];
7200 vector<string> extensions;
7201 GraphicsResources resources;
7202 PushConstants pcs;
7203 const deUint32 numDataPoints = 64;
7204 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints));
7205 vector<double> float64Data;
7206 VulkanFeatures requiredFeatures;
7207
7208 float64Data.reserve(numDataPoints);
7209 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
7210 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
7211
7212 extensions.push_back("VK_KHR_16bit_storage");
7213
7214 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
7215 requiredFeatures.ext16BitStorage.storagePushConstant16 = true;
7216
7217 fragments["capability"] =
7218 "OpCapability StoragePushConstant16\n"
7219 "OpCapability Float64\n";
7220
7221 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
7222
7223 pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data)));
7224 resources.outputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7225 resources.verifyIO = check64BitFloats;
7226
7227 getDefaultColors(defaultColors);
7228
7229 const StringTemplate testFun (
7230 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7231 " %param = OpFunctionParameter %v4f32\n"
7232
7233 "%entry = OpLabel\n"
7234 " %i = OpVariable %fp_i32 Function\n"
7235 " OpStore %i %c_i32_0\n"
7236 " OpBranch %loop\n"
7237
7238 " %loop = OpLabel\n"
7239 " %15 = OpLoad %i32 %i\n"
7240 " %lt = OpSLessThan %bool %15 ${count}\n"
7241 " OpLoopMerge %merge %inc None\n"
7242 " OpBranchConditional %lt %write %merge\n"
7243
7244 "%write = OpLabel\n"
7245 " %30 = OpLoad %i32 %i\n"
7246 " %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %30 ${index0:opt}\n"
7247 "%val16 = OpLoad ${f_type16} %src\n"
7248 "%val64 = OpFConvert ${f_type64} %val16\n"
7249 " %dst = OpAccessChain ${up_type64} %ssbo64 %c_i32_0 %30 ${index0:opt}\n"
7250 " OpStore %dst %val64\n"
7251
7252 "${store:opt}\n"
7253
7254 " OpBranch %inc\n"
7255
7256 " %inc = OpLabel\n"
7257 " %37 = OpLoad %i32 %i\n"
7258 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7259 " OpStore %i %39\n"
7260 " OpBranch %loop\n"
7261
7262 "%merge = OpLabel\n"
7263 " OpReturnValue %param\n"
7264
7265 "OpFunctionEnd\n");
7266
7267 { // Scalar cases
7268 fragments["pre_main"] =
7269 " %f16 = OpTypeFloat 16\n"
7270 " %f64 = OpTypeFloat 64\n"
7271 " %c_i32_64 = OpConstant %i32 64\n" // Should be the same as numDataPoints
7272 " %v4f64 = OpTypeVector %f64 4\n"
7273 " %a64f16 = OpTypeArray %f16 %c_i32_64\n"
7274 " %a64f64 = OpTypeArray %f64 %c_i32_64\n"
7275 " %pp_f16 = OpTypePointer PushConstant %f16\n"
7276 " %up_f64 = OpTypePointer Uniform %f64\n"
7277 " %SSBO64 = OpTypeStruct %a64f64\n"
7278 " %up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7279 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7280 " %PC16 = OpTypeStruct %a64f16\n"
7281 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7282 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7283
7284 fragments["decoration"] =
7285 "OpDecorate %a64f16 ArrayStride 2\n"
7286 "OpDecorate %a64f64 ArrayStride 8\n"
7287 "OpDecorate %SSBO64 BufferBlock\n"
7288 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7289 "OpDecorate %PC16 Block\n"
7290 "OpMemberDecorate %PC16 0 Offset 0\n"
7291 "OpDecorate %ssbo64 DescriptorSet 0\n"
7292 "OpDecorate %ssbo64 Binding 0\n";
7293
7294 map<string, string> specs;
7295
7296 specs["count"] = "%c_i32_64";
7297 specs["pp_type16"] = "%pp_f16";
7298 specs["f_type16"] = "%f16";
7299 specs["f_type64"] = "%f64";
7300 specs["up_type64"] = "%up_f64";
7301
7302 fragments["testfun"] = testFun.specialize(specs);
7303
7304 createTestsForAllStages("scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7305 }
7306
7307 { // Vector cases
7308 fragments["pre_main"] =
7309 " %f16 = OpTypeFloat 16\n"
7310 " %f64 = OpTypeFloat 64\n"
7311 " %v4f16 = OpTypeVector %f16 4\n"
7312 " %v4f64 = OpTypeVector %f64 4\n"
7313 " %v2f64 = OpTypeVector %f64 2\n"
7314 " %c_i32_16 = OpConstant %i32 16\n"
7315 " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n"
7316 " %a16v4f64 = OpTypeArray %v4f64 %c_i32_16\n"
7317 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
7318 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7319 " %SSBO64 = OpTypeStruct %a16v4f64\n"
7320 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7321 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7322 " %PC16 = OpTypeStruct %a16v4f16\n"
7323 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7324 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7325
7326 fragments["decoration"] =
7327 "OpDecorate %a16v4f16 ArrayStride 8\n"
7328 "OpDecorate %a16v4f64 ArrayStride 32\n"
7329 "OpDecorate %SSBO64 BufferBlock\n"
7330 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7331 "OpDecorate %PC16 Block\n"
7332 "OpMemberDecorate %PC16 0 Offset 0\n"
7333 "OpDecorate %ssbo64 DescriptorSet 0\n"
7334 "OpDecorate %ssbo64 Binding 0\n";
7335
7336 map<string, string> specs;
7337
7338 specs["count"] = "%c_i32_16";
7339 specs["pp_type16"] = "%pp_v4f16";
7340 specs["f_type16"] = "%v4f16";
7341 specs["f_type64"] = "%v4f64";
7342 specs["up_type64"] = "%up_v4f64";
7343
7344 fragments["testfun"] = testFun.specialize(specs);
7345
7346 createTestsForAllStages("vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7347 }
7348
7349 { // Matrix cases
7350 fragments["pre_main"] =
7351 " %c_i32_8 = OpConstant %i32 8\n"
7352 " %f16 = OpTypeFloat 16\n"
7353 " %v4f16 = OpTypeVector %f16 4\n"
7354 " %f64 = OpTypeFloat 64\n"
7355 " %v4f64 = OpTypeVector %f64 4\n"
7356 " %m2v4f16 = OpTypeMatrix %v4f16 2\n"
7357 " %m2v4f64 = OpTypeMatrix %v4f64 2\n"
7358 "%a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n"
7359 "%a8m2v4f64 = OpTypeArray %m2v4f64 %c_i32_8\n"
7360 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n"
7361 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7362 " %SSBO64 = OpTypeStruct %a8m2v4f64\n"
7363 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7364 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7365 " %PC16 = OpTypeStruct %a8m2v4f16\n"
7366 " %pp_PC16 = OpTypePointer PushConstant %PC16\n"
7367 " %pc16 = OpVariable %pp_PC16 PushConstant\n";
7368
7369 fragments["decoration"] =
7370 "OpDecorate %a8m2v4f16 ArrayStride 16\n"
7371 "OpDecorate %a8m2v4f64 ArrayStride 64\n"
7372 "OpDecorate %SSBO64 BufferBlock\n"
7373 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7374 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7375 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7376 "OpDecorate %PC16 Block\n"
7377 "OpMemberDecorate %PC16 0 Offset 0\n"
7378 "OpMemberDecorate %PC16 0 ColMajor\n"
7379 "OpMemberDecorate %PC16 0 MatrixStride 8\n"
7380 "OpDecorate %ssbo64 DescriptorSet 0\n"
7381 "OpDecorate %ssbo64 Binding 0\n";
7382
7383 map<string, string> specs;
7384
7385 specs["count"] = "%c_i32_8";
7386 specs["pp_type16"] = "%pp_v4f16";
7387 specs["up_type64"] = "%up_v4f64";
7388 specs["f_type16"] = "%v4f16";
7389 specs["f_type64"] = "%v4f64";
7390 specs["index0"] = "%c_i32_0";
7391 specs["store"] =
7392 " %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %30 %c_i32_1\n"
7393 "%val16_1 = OpLoad %v4f16 %src_1\n"
7394 "%val64_1 = OpFConvert %v4f64 %val16_1\n"
7395 " %dst_1 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7396 " OpStore %dst_1 %val64_1\n";
7397
7398 fragments["testfun"] = testFun.specialize(specs);
7399
7400 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
7401 }
7402 }
7403
addCompute16bitStorageUniform64To16Group(tcu::TestCaseGroup * group)7404 void addCompute16bitStorageUniform64To16Group (tcu::TestCaseGroup* group)
7405 {
7406 tcu::TestContext& testCtx = group->getTestContext();
7407 de::Random rnd (deStringHash(group->getName()));
7408 const int numElements = 128;
7409
7410 const StringTemplate shaderTemplate (
7411 "OpCapability Shader\n"
7412 "OpCapability ${capability}\n"
7413 "OpCapability Float64\n"
7414 "OpExtension \"SPV_KHR_16bit_storage\"\n"
7415 "OpMemoryModel Logical GLSL450\n"
7416 "OpEntryPoint GLCompute %main \"main\" %id\n"
7417 "OpExecutionMode %main LocalSize 1 1 1\n"
7418 "OpDecorate %id BuiltIn GlobalInvocationId\n"
7419
7420 "${stride}\n"
7421
7422 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7423 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7424 "OpDecorate %SSBO64 ${storage}\n"
7425 "OpDecorate %SSBO16 BufferBlock\n"
7426 "OpDecorate %ssbo64 DescriptorSet 0\n"
7427 "OpDecorate %ssbo16 DescriptorSet 0\n"
7428 "OpDecorate %ssbo64 Binding 0\n"
7429 "OpDecorate %ssbo16 Binding 1\n"
7430
7431 "${matrix_decor:opt}\n"
7432
7433 "${rounding:opt}\n"
7434
7435 "%bool = OpTypeBool\n"
7436 "%void = OpTypeVoid\n"
7437 "%voidf = OpTypeFunction %void\n"
7438 "%u32 = OpTypeInt 32 0\n"
7439 "%i32 = OpTypeInt 32 1\n"
7440 "%f32 = OpTypeFloat 32\n"
7441 "%f64 = OpTypeFloat 64\n"
7442 "%uvec3 = OpTypeVector %u32 3\n"
7443 "%fvec3 = OpTypeVector %f32 3\n"
7444 "%uvec3ptr = OpTypePointer Input %uvec3\n"
7445 "%i32ptr = OpTypePointer Uniform %i32\n"
7446 "%f64ptr = OpTypePointer Uniform %f64\n"
7447
7448 "%zero = OpConstant %i32 0\n"
7449 "%c_i32_1 = OpConstant %i32 1\n"
7450 "%c_i32_16 = OpConstant %i32 16\n"
7451 "%c_i32_32 = OpConstant %i32 32\n"
7452 "%c_i32_64 = OpConstant %i32 64\n"
7453 "%c_i32_128 = OpConstant %i32 128\n"
7454
7455 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
7456 "%f64arr = OpTypeArray %f64 %c_i32_128\n"
7457
7458 "${types}\n"
7459 "${matrix_types:opt}\n"
7460
7461 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
7462 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
7463 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7464 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7465 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7466 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
7467
7468 "%id = OpVariable %uvec3ptr Input\n"
7469
7470 "%main = OpFunction %void None %voidf\n"
7471 "%label = OpLabel\n"
7472 "%idval = OpLoad %uvec3 %id\n"
7473 "%x = OpCompositeExtract %u32 %idval 0\n"
7474 "%inloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
7475 "%val64 = OpLoad %${base64} %inloc\n"
7476 "%val16 = ${convert} %${base16} %val64\n"
7477 "%outloc = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n"
7478 " OpStore %outloc %val16\n"
7479 "${matrix_store:opt}\n"
7480 " OpReturn\n"
7481 " OpFunctionEnd\n");
7482
7483 { // Floats
7484 const char floatTypes[] =
7485 "%f16 = OpTypeFloat 16\n"
7486 "%f16ptr = OpTypePointer Uniform %f16\n"
7487 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
7488 "%v4f16 = OpTypeVector %f16 4\n"
7489 "%v4f64 = OpTypeVector %f64 4\n"
7490 "%v4f16ptr = OpTypePointer Uniform %v4f16\n"
7491 "%v4f64ptr = OpTypePointer Uniform %v4f64\n"
7492 "%v4f16arr = OpTypeArray %v4f16 %c_i32_32\n"
7493 "%v4f64arr = OpTypeArray %v4f64 %c_i32_32\n";
7494
7495 struct RndMode
7496 {
7497 const char* name;
7498 const char* decor;
7499 VerifyIOFunc func;
7500 };
7501
7502 const RndMode rndModes[] =
7503 {
7504 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", computeCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7505 {"rte", "OpDecorate %val16 FPRoundingMode RTE", computeCheck16BitFloats64<ROUNDINGMODE_RTE>},
7506 {"unspecified_rnd_mode", "", computeCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7507 };
7508
7509 struct CompositeType
7510 {
7511 const char* name;
7512 const char* base64;
7513 const char* base16;
7514 const char* strideStr;
7515 const char* stride64UBO;
7516 unsigned padding64UBO;
7517 const char* stride64SSBO;
7518 unsigned padding64SSBO;
7519 unsigned count;
7520 };
7521
7522 const CompositeType cTypes[] =
7523 {
7524 {"scalar", "f64", "f16", "OpDecorate %f16arr ArrayStride 2\nOpDecorate %f64arr ArrayStride ", "16", 8, "8", 0, numElements},
7525 {"vector", "v4f64", "v4f16", "OpDecorate %v4f16arr ArrayStride 8\nOpDecorate %v4f64arr ArrayStride ", "32", 0, "32", 0, numElements / 4},
7526 {"matrix", "v4f64", "v4f16", "OpDecorate %m2v4f16arr ArrayStride 16\nOpDecorate %m2v4f64arr ArrayStride ", "64", 0, "64", 0, numElements / 8},
7527 };
7528
7529 vector<double> float64Data = getFloat64s(rnd, numElements);
7530 vector<deFloat16> float16UnusedData (numElements, 0);
7531
7532 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7533 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
7534 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7535 {
7536 ComputeShaderSpec spec;
7537 map<string, string> specs;
7538 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float_" + rndModes[rndModeIdx].name;
7539 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7540
7541 specs["capability"] = CAPABILITIES[capIdx].cap;
7542 specs["storage"] = CAPABILITIES[capIdx].decor;
7543 specs["stride"] = cTypes[tyIdx].strideStr;
7544 specs["base64"] = cTypes[tyIdx].base64;
7545 specs["base16"] = cTypes[tyIdx].base16;
7546 specs["rounding"] = rndModes[rndModeIdx].decor;
7547 specs["types"] = floatTypes;
7548 specs["convert"] = "OpFConvert";
7549
7550 if (isUBO)
7551 specs["stride"] += cTypes[tyIdx].stride64UBO;
7552 else
7553 specs["stride"] += cTypes[tyIdx].stride64SSBO;
7554
7555 if (deStringEqual(cTypes[tyIdx].name, "matrix"))
7556 {
7557 if (strcmp(rndModes[rndModeIdx].name, "rtz") == 0)
7558 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTZ\n";
7559 else if (strcmp(rndModes[rndModeIdx].name, "rte") == 0)
7560 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTE\n";
7561
7562 specs["index0"] = "%zero";
7563 specs["matrix_prefix"] = "m2";
7564 specs["matrix_types"] =
7565 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
7566 "%m2v4f64 = OpTypeMatrix %v4f64 2\n"
7567 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_16\n"
7568 "%m2v4f64arr = OpTypeArray %m2v4f64 %c_i32_16\n";
7569 specs["matrix_decor"] =
7570 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7571 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7572 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7573 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n";
7574 specs["matrix_store"] =
7575 "%inloc_1 = OpAccessChain %v4f64ptr %ssbo64 %zero %x %c_i32_1\n"
7576 "%val64_1 = OpLoad %v4f64 %inloc_1\n"
7577 "%val16_1 = OpFConvert %v4f16 %val64_1\n"
7578 "%outloc_1 = OpAccessChain %v4f16ptr %ssbo16 %zero %x %c_i32_1\n"
7579 " OpStore %outloc_1 %val16_1\n";
7580 }
7581
7582 spec.assembly = shaderTemplate.specialize(specs);
7583 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
7584 spec.verifyIO = rndModes[rndModeIdx].func;
7585 const unsigned padding = isUBO ? cTypes[tyIdx].padding64UBO : cTypes[tyIdx].padding64SSBO;
7586
7587 spec.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data, padding)), CAPABILITIES[capIdx].dtype));
7588
7589 // We provided a custom verifyIO in the above in which inputs will be used for checking.
7590 // So put unused data in the expected values.
7591 spec.outputs.push_back(BufferSp(new Float16Buffer(float16UnusedData)));
7592
7593 spec.extensions.push_back("VK_KHR_16bit_storage");
7594
7595 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7596 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
7597
7598 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
7599 }
7600 }
7601 }
7602
addGraphics16BitStorageUniformFloat64To16Group(tcu::TestCaseGroup * testGroup)7603 void addGraphics16BitStorageUniformFloat64To16Group (tcu::TestCaseGroup* testGroup)
7604 {
7605 de::Random rnd (deStringHash(testGroup->getName()));
7606 map<string, string> fragments;
7607 GraphicsResources resources;
7608 vector<string> extensions;
7609 const deUint32 numDataPoints = 256;
7610 RGBA defaultColors[4];
7611 vector<double> float64Data = getFloat64s(rnd, numDataPoints);
7612 vector<deFloat16> float16UnusedData (numDataPoints, 0);
7613 const StringTemplate capabilities ("OpCapability Float64\n"
7614 "OpCapability ${cap}\n");
7615 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter.
7616 resources.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16UnusedData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
7617
7618 extensions.push_back("VK_KHR_16bit_storage");
7619
7620 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
7621
7622 struct RndMode
7623 {
7624 const char* name;
7625 const char* decor;
7626 VerifyIOFunc f;
7627 };
7628
7629 getDefaultColors(defaultColors);
7630
7631 { // scalar cases
7632 fragments["pre_main"] =
7633 " %f16 = OpTypeFloat 16\n"
7634 " %f64 = OpTypeFloat 64\n"
7635 "%c_i32_256 = OpConstant %i32 256\n"
7636 " %up_f64 = OpTypePointer Uniform %f64\n"
7637 " %up_f16 = OpTypePointer Uniform %f16\n"
7638 " %ra_f64 = OpTypeArray %f64 %c_i32_256\n"
7639 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n"
7640 " %SSBO64 = OpTypeStruct %ra_f64\n"
7641 " %SSBO16 = OpTypeStruct %ra_f16\n"
7642 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7643 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7644 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7645 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7646
7647 const StringTemplate decoration (
7648 "OpDecorate %ra_f64 ArrayStride ${stride64}\n"
7649 "OpDecorate %ra_f16 ArrayStride 2\n"
7650 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7651 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7652 "OpDecorate %SSBO64 ${indecor}\n"
7653 "OpDecorate %SSBO16 BufferBlock\n"
7654 "OpDecorate %ssbo64 DescriptorSet 0\n"
7655 "OpDecorate %ssbo16 DescriptorSet 0\n"
7656 "OpDecorate %ssbo64 Binding 0\n"
7657 "OpDecorate %ssbo16 Binding 1\n"
7658 "${rounddecor}\n");
7659
7660 fragments["testfun"] =
7661 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7662 " %param = OpFunctionParameter %v4f32\n"
7663
7664 "%entry = OpLabel\n"
7665 " %i = OpVariable %fp_i32 Function\n"
7666 " OpStore %i %c_i32_0\n"
7667 " OpBranch %loop\n"
7668
7669 " %loop = OpLabel\n"
7670 " %15 = OpLoad %i32 %i\n"
7671 " %lt = OpSLessThan %bool %15 %c_i32_256\n"
7672 " OpLoopMerge %merge %inc None\n"
7673 " OpBranchConditional %lt %write %merge\n"
7674
7675 "%write = OpLabel\n"
7676 " %30 = OpLoad %i32 %i\n"
7677 " %src = OpAccessChain %up_f64 %ssbo64 %c_i32_0 %30\n"
7678 "%val64 = OpLoad %f64 %src\n"
7679 "%val16 = OpFConvert %f16 %val64\n"
7680 " %dst = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n"
7681 " OpStore %dst %val16\n"
7682 " OpBranch %inc\n"
7683
7684 " %inc = OpLabel\n"
7685 " %37 = OpLoad %i32 %i\n"
7686 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7687 " OpStore %i %39\n"
7688 " OpBranch %loop\n"
7689
7690 "%merge = OpLabel\n"
7691 " OpReturnValue %param\n"
7692
7693 "OpFunctionEnd\n";
7694
7695 const RndMode rndModes[] =
7696 {
7697 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7698 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7699 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7700 };
7701
7702 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7703 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7704 {
7705 map<string, string> specs;
7706 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float_" + rndModes[rndModeIdx].name;
7707 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
7708 VulkanFeatures features;
7709
7710 specs["cap"] = CAPABILITIES[capIdx].cap;
7711 specs["indecor"] = CAPABILITIES[capIdx].decor;
7712 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7713 specs["stride64"] = isUBO ? "16" : "8";
7714
7715 fragments["capability"] = capabilities.specialize(specs);
7716 fragments["decoration"] = decoration.specialize(specs);
7717
7718 resources.inputs.clear();
7719 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data, isUBO ? 8 : 0)), CAPABILITIES[capIdx].dtype));
7720
7721 resources.verifyIO = rndModes[rndModeIdx].f;
7722
7723 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7724 features.coreFeatures.shaderFloat64 = DE_TRUE;
7725
7726
7727 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7728 }
7729 }
7730
7731 { // vector cases
7732 fragments["pre_main"] =
7733 " %f16 = OpTypeFloat 16\n"
7734 " %f64 = OpTypeFloat 64\n"
7735 " %c_i32_64 = OpConstant %i32 64\n"
7736 " %v4f16 = OpTypeVector %f16 4\n"
7737 " %v4f64 = OpTypeVector %f64 4\n"
7738 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7739 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
7740 " %ra_v4f64 = OpTypeArray %v4f64 %c_i32_64\n"
7741 " %ra_v4f16 = OpTypeArray %v4f16 %c_i32_64\n"
7742 " %SSBO64 = OpTypeStruct %ra_v4f64\n"
7743 " %SSBO16 = OpTypeStruct %ra_v4f16\n"
7744 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7745 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7746 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7747 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7748
7749 const StringTemplate decoration (
7750 "OpDecorate %ra_v4f64 ArrayStride 32\n"
7751 "OpDecorate %ra_v4f16 ArrayStride 8\n"
7752 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7753 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7754 "OpDecorate %SSBO64 ${indecor}\n"
7755 "OpDecorate %SSBO16 BufferBlock\n"
7756 "OpDecorate %ssbo64 DescriptorSet 0\n"
7757 "OpDecorate %ssbo16 DescriptorSet 0\n"
7758 "OpDecorate %ssbo64 Binding 0\n"
7759 "OpDecorate %ssbo16 Binding 1\n"
7760 "${rounddecor}\n");
7761
7762 // ssbo16[] <- convert ssbo64[] to 16bit float
7763 fragments["testfun"] =
7764 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7765 " %param = OpFunctionParameter %v4f32\n"
7766
7767 "%entry = OpLabel\n"
7768 " %i = OpVariable %fp_i32 Function\n"
7769 " OpStore %i %c_i32_0\n"
7770 " OpBranch %loop\n"
7771
7772 " %loop = OpLabel\n"
7773 " %15 = OpLoad %i32 %i\n"
7774 " %lt = OpSLessThan %bool %15 %c_i32_64\n"
7775 " OpLoopMerge %merge %inc None\n"
7776 " OpBranchConditional %lt %write %merge\n"
7777
7778 "%write = OpLabel\n"
7779 " %30 = OpLoad %i32 %i\n"
7780 " %src = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30\n"
7781 "%val64 = OpLoad %v4f64 %src\n"
7782 "%val16 = OpFConvert %v4f16 %val64\n"
7783 " %dst = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30\n"
7784 " OpStore %dst %val16\n"
7785 " OpBranch %inc\n"
7786
7787 " %inc = OpLabel\n"
7788 " %37 = OpLoad %i32 %i\n"
7789 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7790 " OpStore %i %39\n"
7791 " OpBranch %loop\n"
7792
7793 "%merge = OpLabel\n"
7794 " OpReturnValue %param\n"
7795
7796 "OpFunctionEnd\n";
7797
7798 const RndMode rndModes[] =
7799 {
7800 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7801 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7802 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7803 };
7804
7805 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7806 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7807 {
7808 map<string, string> specs;
7809 VulkanFeatures features;
7810 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float_" + rndModes[rndModeIdx].name;
7811
7812 specs["cap"] = CAPABILITIES[capIdx].cap;
7813 specs["indecor"] = CAPABILITIES[capIdx].decor;
7814 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7815
7816 fragments["capability"] = capabilities.specialize(specs);
7817 fragments["decoration"] = decoration.specialize(specs);
7818
7819 resources.inputs.clear();
7820 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), CAPABILITIES[capIdx].dtype));
7821 resources.verifyIO = rndModes[rndModeIdx].f;
7822
7823 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7824 features.coreFeatures.shaderFloat64 = DE_TRUE;
7825
7826 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7827 }
7828 }
7829
7830 { // matrix cases
7831 fragments["pre_main"] =
7832 " %f16 = OpTypeFloat 16\n"
7833 " %f64 = OpTypeFloat 64\n"
7834 " %c_i32_16 = OpConstant %i32 16\n"
7835 " %v4f16 = OpTypeVector %f16 4\n"
7836 " %v4f64 = OpTypeVector %f64 4\n"
7837 " %m4x4f64 = OpTypeMatrix %v4f64 4\n"
7838 " %m4x4f16 = OpTypeMatrix %v4f16 4\n"
7839 " %up_v4f64 = OpTypePointer Uniform %v4f64\n"
7840 " %up_v4f16 = OpTypePointer Uniform %v4f16\n"
7841 "%a16m4x4f64 = OpTypeArray %m4x4f64 %c_i32_16\n"
7842 "%a16m4x4f16 = OpTypeArray %m4x4f16 %c_i32_16\n"
7843 " %SSBO64 = OpTypeStruct %a16m4x4f64\n"
7844 " %SSBO16 = OpTypeStruct %a16m4x4f16\n"
7845 " %up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
7846 " %up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
7847 " %ssbo64 = OpVariable %up_SSBO64 Uniform\n"
7848 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n";
7849
7850 const StringTemplate decoration (
7851 "OpDecorate %a16m4x4f64 ArrayStride 128\n"
7852 "OpDecorate %a16m4x4f16 ArrayStride 32\n"
7853 "OpMemberDecorate %SSBO64 0 Offset 0\n"
7854 "OpMemberDecorate %SSBO64 0 ColMajor\n"
7855 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
7856 "OpMemberDecorate %SSBO16 0 Offset 0\n"
7857 "OpMemberDecorate %SSBO16 0 ColMajor\n"
7858 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n"
7859 "OpDecorate %SSBO64 ${indecor}\n"
7860 "OpDecorate %SSBO16 BufferBlock\n"
7861 "OpDecorate %ssbo64 DescriptorSet 0\n"
7862 "OpDecorate %ssbo16 DescriptorSet 0\n"
7863 "OpDecorate %ssbo64 Binding 0\n"
7864 "OpDecorate %ssbo16 Binding 1\n"
7865 "${rounddecor}\n");
7866
7867 fragments["testfun"] =
7868 "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
7869 " %param = OpFunctionParameter %v4f32\n"
7870
7871 "%entry = OpLabel\n"
7872 " %i = OpVariable %fp_i32 Function\n"
7873 " OpStore %i %c_i32_0\n"
7874 " OpBranch %loop\n"
7875
7876 " %loop = OpLabel\n"
7877 " %15 = OpLoad %i32 %i\n"
7878 " %lt = OpSLessThan %bool %15 %c_i32_16\n"
7879 " OpLoopMerge %merge %inc None\n"
7880 " OpBranchConditional %lt %write %merge\n"
7881
7882 " %write = OpLabel\n"
7883 " %30 = OpLoad %i32 %i\n"
7884 " %src_0 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_0\n"
7885 " %src_1 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_1\n"
7886 " %src_2 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_2\n"
7887 " %src_3 = OpAccessChain %up_v4f64 %ssbo64 %c_i32_0 %30 %c_i32_3\n"
7888 "%val64_0 = OpLoad %v4f64 %src_0\n"
7889 "%val64_1 = OpLoad %v4f64 %src_1\n"
7890 "%val64_2 = OpLoad %v4f64 %src_2\n"
7891 "%val64_3 = OpLoad %v4f64 %src_3\n"
7892 "%val16_0 = OpFConvert %v4f16 %val64_0\n"
7893 "%val16_1 = OpFConvert %v4f16 %val64_1\n"
7894 "%val16_2 = OpFConvert %v4f16 %val64_2\n"
7895 "%val16_3 = OpFConvert %v4f16 %val64_3\n"
7896 " %dst_0 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n"
7897 " %dst_1 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n"
7898 " %dst_2 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n"
7899 " %dst_3 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n"
7900 " OpStore %dst_0 %val16_0\n"
7901 " OpStore %dst_1 %val16_1\n"
7902 " OpStore %dst_2 %val16_2\n"
7903 " OpStore %dst_3 %val16_3\n"
7904 " OpBranch %inc\n"
7905
7906 " %inc = OpLabel\n"
7907 " %37 = OpLoad %i32 %i\n"
7908 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
7909 " OpStore %i %39\n"
7910 " OpBranch %loop\n"
7911
7912 "%merge = OpLabel\n"
7913 " OpReturnValue %param\n"
7914
7915 "OpFunctionEnd\n";
7916
7917 const RndMode rndModes[] =
7918 {
7919 {"rte", "OpDecorate %val16_0 FPRoundingMode RTE\nOpDecorate %val16_1 FPRoundingMode RTE\nOpDecorate %val16_2 FPRoundingMode RTE\nOpDecorate %val16_3 FPRoundingMode RTE", graphicsCheck16BitFloats64<ROUNDINGMODE_RTE>},
7920 {"rtz", "OpDecorate %val16_0 FPRoundingMode RTZ\nOpDecorate %val16_1 FPRoundingMode RTZ\nOpDecorate %val16_2 FPRoundingMode RTZ\nOpDecorate %val16_3 FPRoundingMode RTZ", graphicsCheck16BitFloats64<ROUNDINGMODE_RTZ>},
7921 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats64<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>},
7922 };
7923
7924 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
7925 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
7926 {
7927 map<string, string> specs;
7928 VulkanFeatures features;
7929 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float_" + rndModes[rndModeIdx].name;
7930
7931 specs["cap"] = CAPABILITIES[capIdx].cap;
7932 specs["indecor"] = CAPABILITIES[capIdx].decor;
7933 specs["rounddecor"] = rndModes[rndModeIdx].decor;
7934
7935 fragments["capability"] = capabilities.specialize(specs);
7936 fragments["decoration"] = decoration.specialize(specs);
7937
7938 resources.inputs.clear();
7939 resources.inputs.push_back(Resource(BufferSp(new Float64Buffer(float64Data)), CAPABILITIES[capIdx].dtype));
7940 resources.verifyIO = rndModes[rndModeIdx].f;
7941
7942 features = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
7943 features.coreFeatures.shaderFloat64 = DE_TRUE;
7944
7945 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, features);
7946 }
7947 }
7948 }
7949
addGraphics16BitStorageInputOutputFloat64To16Group(tcu::TestCaseGroup * testGroup)7950 void addGraphics16BitStorageInputOutputFloat64To16Group (tcu::TestCaseGroup* testGroup)
7951 {
7952 de::Random rnd (deStringHash(testGroup->getName()));
7953 RGBA defaultColors[4];
7954 vector<string> extensions;
7955 map<string, string> fragments = passthruFragments();
7956 const deUint32 numDataPoints = 64;
7957 // Special values like inf/nan/denormal may not be preserved when float control features are not provided,
7958 // thus values generating special float16 values must be excluded in input data here.
7959 vector<double> float64Data = getFloat64s(rnd, numDataPoints, DE_FALSE);
7960
7961 extensions.push_back("VK_KHR_16bit_storage");
7962
7963 fragments["capability"] =
7964 "OpCapability StorageInputOutput16\n"
7965 "OpCapability Float64\n";
7966 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n";
7967
7968 getDefaultColors(defaultColors);
7969
7970 struct RndMode
7971 {
7972 const char* name;
7973 const char* decor;
7974 const char* decor_tessc;
7975 RoundingModeFlags flags;
7976 };
7977
7978 const RndMode rndModes[] =
7979 {
7980 {"rtz",
7981 "OpDecorate %ret0 FPRoundingMode RTZ\n",
7982 "OpDecorate %ret1 FPRoundingMode RTZ\n"
7983 "OpDecorate %ret2 FPRoundingMode RTZ\n",
7984 ROUNDINGMODE_RTZ},
7985 {"rte",
7986 "OpDecorate %ret0 FPRoundingMode RTE\n",
7987 "OpDecorate %ret1 FPRoundingMode RTE\n"
7988 "OpDecorate %ret2 FPRoundingMode RTE\n",
7989 ROUNDINGMODE_RTE},
7990 {"unspecified_rnd_mode", "", "", RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)},
7991 };
7992
7993 struct Case
7994 {
7995 const char* name;
7996 const char* interfaceOpCall;
7997 const char* interfaceOpFunc;
7998 const char* postInterfaceOp;
7999 const char* postInterfaceOpGeom;
8000 const char* postInterfaceOpTessc;
8001 const char* preMain;
8002 const char* inputType;
8003 const char* outputType;
8004 deUint32 numPerCase;
8005 deUint32 numElements;
8006 };
8007
8008 const Case cases[] =
8009 {
8010 { // Scalar cases
8011 "scalar",
8012
8013 "OpFConvert %f16",
8014
8015 "",
8016
8017 " %ret0 = OpFConvert %f16 %IF_input_val\n"
8018 " OpStore %IF_output %ret0\n",
8019
8020 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
8021 " OpStore %IF_output %ret0\n",
8022
8023 " %ret0 = OpFConvert %f16 %IF_input_val0\n"
8024 " OpStore %IF_output_ptr0 %ret0\n"
8025 " %ret1 = OpFConvert %f16 %IF_input_val1\n"
8026 " OpStore %IF_output_ptr1 %ret1\n"
8027 " %ret2 = OpFConvert %f16 %IF_input_val2\n"
8028 " OpStore %IF_output_ptr2 %ret2\n",
8029
8030 " %f16 = OpTypeFloat 16\n"
8031 " %f64 = OpTypeFloat 64\n"
8032 " %op_f16 = OpTypePointer Output %f16\n"
8033 " %a3f16 = OpTypeArray %f16 %c_i32_3\n"
8034 " %op_a3f16 = OpTypePointer Output %a3f16\n"
8035 "%f16_f64_function = OpTypeFunction %f16 %f64\n"
8036 " %a3f64 = OpTypeArray %f64 %c_i32_3\n"
8037 " %ip_a3f64 = OpTypePointer Input %a3f64\n"
8038 " %ip_f64 = OpTypePointer Input %f64\n",
8039
8040 "f64",
8041 "f16",
8042 4,
8043 1,
8044 },
8045 { // Vector cases
8046 "vector",
8047
8048 "OpFConvert %v2f16",
8049
8050 "",
8051
8052 " %ret0 = OpFConvert %v2f16 %IF_input_val\n"
8053 " OpStore %IF_output %ret0\n",
8054
8055 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
8056 " OpStore %IF_output %ret0\n",
8057
8058 " %ret0 = OpFConvert %v2f16 %IF_input_val0\n"
8059 " OpStore %IF_output_ptr0 %ret0\n"
8060 " %ret1 = OpFConvert %v2f16 %IF_input_val1\n"
8061 " OpStore %IF_output_ptr1 %ret1\n"
8062 " %ret2 = OpFConvert %v2f16 %IF_input_val2\n"
8063 " OpStore %IF_output_ptr2 %ret2\n",
8064
8065 " %f16 = OpTypeFloat 16\n"
8066 " %f64 = OpTypeFloat 64\n"
8067 " %v2f16 = OpTypeVector %f16 2\n"
8068 " %v2f64 = OpTypeVector %f64 2\n"
8069 " %op_v2f16 = OpTypePointer Output %v2f16\n"
8070 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n"
8071 " %op_a3v2f16 = OpTypePointer Output %a3v2f16\n"
8072 "%v2f16_v2f64_function = OpTypeFunction %v2f16 %v2f64\n"
8073 " %a3v2f64 = OpTypeArray %v2f64 %c_i32_3\n"
8074 " %ip_a3v2f64 = OpTypePointer Input %a3v2f64\n"
8075 " %ip_v2f64 = OpTypePointer Input %v2f64\n",
8076
8077 "v2f64",
8078 "v2f16",
8079 2 * 4,
8080 2,
8081 }
8082 };
8083
8084 VulkanFeatures requiredFeatures;
8085
8086 requiredFeatures.coreFeatures.shaderFloat64 = DE_TRUE;
8087 requiredFeatures.ext16BitStorage.storageInputOutput16 = true;
8088
8089 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
8090 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
8091 {
8092 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc;
8093 fragments["interface_op_call"] = cases[caseIdx].interfaceOpCall;
8094 fragments["post_interface_op_frag"] = cases[caseIdx].postInterfaceOp;
8095 fragments["post_interface_op_vert"] = cases[caseIdx].postInterfaceOp;
8096 fragments["post_interface_op_geom"] = cases[caseIdx].postInterfaceOpGeom;
8097 fragments["post_interface_op_tesse"] = cases[caseIdx].postInterfaceOpGeom;
8098 fragments["post_interface_op_tessc"] = cases[caseIdx].postInterfaceOpTessc;
8099 fragments["pre_main"] = cases[caseIdx].preMain;
8100 fragments["decoration"] = rndModes[rndModeIdx].decor;
8101 fragments["decoration_tessc"] = rndModes[rndModeIdx].decor_tessc;
8102
8103 fragments["input_type"] = cases[caseIdx].inputType;
8104 fragments["output_type"] = cases[caseIdx].outputType;
8105
8106 GraphicsInterfaces interfaces;
8107 const deUint32 numPerCase = cases[caseIdx].numPerCase;
8108 vector<double> subInputs (numPerCase);
8109 vector<deFloat16> subOutputs (numPerCase);
8110
8111 // The pipeline need this to call compare16BitFloat() when checking the result.
8112 interfaces.setRoundingMode(rndModes[rndModeIdx].flags);
8113
8114 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx)
8115 {
8116 string testName = string(cases[caseIdx].name) + numberToString(caseNdx) + "_" + rndModes[rndModeIdx].name;
8117
8118 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx)
8119 {
8120 subInputs[numNdx] = float64Data[caseNdx * numPerCase + numNdx];
8121 // We derive the expected result from inputs directly in the graphics pipeline.
8122 subOutputs[numNdx] = 0;
8123 }
8124 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT64), BufferSp(new Float64Buffer(subInputs))),
8125 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs))));
8126 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
8127 }
8128 }
8129 }
8130
addCompute16bitStorageUniform16To64Group(tcu::TestCaseGroup * group)8131 void addCompute16bitStorageUniform16To64Group (tcu::TestCaseGroup* group)
8132 {
8133 tcu::TestContext& testCtx = group->getTestContext();
8134 de::Random rnd (deStringHash(group->getName()));
8135 const int numElements = 128;
8136
8137 const StringTemplate shaderTemplate (
8138 "OpCapability Shader\n"
8139 "OpCapability Float64\n"
8140 "OpCapability ${capability}\n"
8141 "OpExtension \"SPV_KHR_16bit_storage\"\n"
8142 "OpMemoryModel Logical GLSL450\n"
8143 "OpEntryPoint GLCompute %main \"main\" %id\n"
8144 "OpExecutionMode %main LocalSize 1 1 1\n"
8145 "OpDecorate %id BuiltIn GlobalInvocationId\n"
8146
8147 "${stride}\n"
8148
8149 "OpMemberDecorate %SSBO64 0 Offset 0\n"
8150 "OpMemberDecorate %SSBO16 0 Offset 0\n"
8151 "OpDecorate %SSBO64 BufferBlock\n"
8152 "OpDecorate %SSBO16 ${storage}\n"
8153 "OpDecorate %ssbo64 DescriptorSet 0\n"
8154 "OpDecorate %ssbo16 DescriptorSet 0\n"
8155 "OpDecorate %ssbo64 Binding 1\n"
8156 "OpDecorate %ssbo16 Binding 0\n"
8157
8158 "${matrix_decor:opt}\n"
8159
8160 "%bool = OpTypeBool\n"
8161 "%void = OpTypeVoid\n"
8162 "%voidf = OpTypeFunction %void\n"
8163 "%u32 = OpTypeInt 32 0\n"
8164 "%i32 = OpTypeInt 32 1\n"
8165 "%f64 = OpTypeFloat 64\n"
8166 "%v3u32 = OpTypeVector %u32 3\n"
8167 "%uvec3ptr = OpTypePointer Input %v3u32\n"
8168 "%i32ptr = OpTypePointer Uniform %i32\n"
8169 "%f64ptr = OpTypePointer Uniform %f64\n"
8170
8171 "%zero = OpConstant %i32 0\n"
8172 "%c_i32_1 = OpConstant %i32 1\n"
8173 "%c_i32_2 = OpConstant %i32 2\n"
8174 "%c_i32_3 = OpConstant %i32 3\n"
8175 "%c_i32_16 = OpConstant %i32 16\n"
8176 "%c_i32_32 = OpConstant %i32 32\n"
8177 "%c_i32_64 = OpConstant %i32 64\n"
8178 "%c_i32_128 = OpConstant %i32 128\n"
8179 "%c_i32_ci = OpConstant %i32 ${constarrayidx}\n"
8180
8181 "%i32arr = OpTypeArray %i32 %c_i32_128\n"
8182 "%f64arr = OpTypeArray %f64 %c_i32_128\n"
8183
8184 "${types}\n"
8185 "${matrix_types:opt}\n"
8186
8187 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
8188 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
8189 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
8190 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
8191 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
8192 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n"
8193
8194 "%id = OpVariable %uvec3ptr Input\n"
8195
8196 "%main = OpFunction %void None %voidf\n"
8197 "%label = OpLabel\n"
8198 "%idval = OpLoad %v3u32 %id\n"
8199 "%x = OpCompositeExtract %u32 %idval 0\n"
8200 "%inloc = OpAccessChain %${base16}ptr %ssbo16 %zero %${arrayindex} ${index0:opt}\n"
8201 "%val16 = OpLoad %${base16} %inloc\n"
8202 "%val64 = ${convert} %${base64} %val16\n"
8203 "%outloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
8204 " OpStore %outloc %val64\n"
8205 "${matrix_store:opt}\n"
8206 " OpReturn\n"
8207 " OpFunctionEnd\n");
8208
8209 { // floats
8210 const char floatTypes[] =
8211 "%f16 = OpTypeFloat 16\n"
8212 "%f16ptr = OpTypePointer Uniform %f16\n"
8213 "%f16arr = OpTypeArray %f16 %c_i32_128\n"
8214 "%v2f16 = OpTypeVector %f16 2\n"
8215 "%v2f64 = OpTypeVector %f64 2\n"
8216 "%v2f16ptr = OpTypePointer Uniform %v2f16\n"
8217 "%v2f64ptr = OpTypePointer Uniform %v2f64\n"
8218 "%v2f16arr = OpTypeArray %v2f16 %c_i32_64\n"
8219 "%v2f64arr = OpTypeArray %v2f64 %c_i32_64\n";
8220
8221 enum DataType
8222 {
8223 SCALAR,
8224 VEC2,
8225 MAT2X2,
8226 };
8227
8228
8229 struct CompositeType
8230 {
8231 const char* name;
8232 const char* base64;
8233 const char* base16;
8234 const char* strideStr;
8235 const char* stride16UBO;
8236 unsigned padding16UBO;
8237 const char* stride16SSBO;
8238 unsigned padding16SSBO;
8239 bool useConstantIndex;
8240 unsigned constantIndex;
8241 unsigned count;
8242 DataType dataType;
8243 };
8244
8245 const CompositeType cTypes[] =
8246 {
8247 {"scalar", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, false, 0, numElements , SCALAR },
8248 {"scalar_const_idx_5", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, true, 5, numElements , SCALAR },
8249 {"scalar_const_idx_8", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride ", "16", 14, "2", 0, true, 8, numElements , SCALAR },
8250 {"vector", "v2f64", "v2f16", "OpDecorate %v2f64arr ArrayStride 16\nOpDecorate %v2f16arr ArrayStride ", "16", 12, "4", 0, false, 0, numElements / 2 , VEC2 },
8251 {"matrix", "v2f64", "v2f16", "OpDecorate %m4v2f64arr ArrayStride 64\nOpDecorate %m4v2f16arr ArrayStride ", "16", 0, "16", 0, false, 0, numElements / 8 , MAT2X2 }
8252 };
8253
8254 vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
8255 vector<double> float64Data;
8256
8257 float64Data.reserve(numElements);
8258 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8259 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
8260
8261 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx)
8262 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
8263 {
8264 ComputeShaderSpec spec;
8265 map<string, string> specs;
8266 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float";
8267 const bool isUBO = CAPABILITIES[capIdx].dtype == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
8268
8269 specs["capability"] = CAPABILITIES[capIdx].cap;
8270 specs["storage"] = CAPABILITIES[capIdx].decor;
8271 specs["stride"] = cTypes[tyIdx].strideStr;
8272 specs["base64"] = cTypes[tyIdx].base64;
8273 specs["base16"] = cTypes[tyIdx].base16;
8274 specs["types"] = floatTypes;
8275 specs["convert"] = "OpFConvert";
8276 specs["constarrayidx"] = de::toString(cTypes[tyIdx].constantIndex);
8277
8278 if (isUBO)
8279 specs["stride"] += cTypes[tyIdx].stride16UBO;
8280 else
8281 specs["stride"] += cTypes[tyIdx].stride16SSBO;
8282
8283 if (cTypes[tyIdx].useConstantIndex)
8284 specs["arrayindex"] = "c_i32_ci";
8285 else
8286 specs["arrayindex"] = "x";
8287
8288 vector<double> float64DataConstIdx;
8289 if (cTypes[tyIdx].useConstantIndex)
8290 {
8291 const deUint32 numFloats = numElements / cTypes[tyIdx].count;
8292 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8293 float64DataConstIdx.push_back(float64Data[cTypes[tyIdx].constantIndex * numFloats + numIdx % numFloats]);
8294 }
8295
8296 if (deStringEqual(cTypes[tyIdx].name, "matrix"))
8297 {
8298 specs["index0"] = "%zero";
8299 specs["matrix_prefix"] = "m4";
8300 specs["matrix_types"] =
8301 "%m4v2f16 = OpTypeMatrix %v2f16 4\n"
8302 "%m4v2f64 = OpTypeMatrix %v2f64 4\n"
8303 "%m4v2f16arr = OpTypeArray %m4v2f16 %c_i32_16\n"
8304 "%m4v2f64arr = OpTypeArray %m4v2f64 %c_i32_16\n";
8305 specs["matrix_decor"] =
8306 "OpMemberDecorate %SSBO64 0 ColMajor\n"
8307 "OpMemberDecorate %SSBO64 0 MatrixStride 16\n"
8308 "OpMemberDecorate %SSBO16 0 ColMajor\n"
8309 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n";
8310 specs["matrix_store"] =
8311 "%inloc_1 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_1\n"
8312 "%val16_1 = OpLoad %v2f16 %inloc_1\n"
8313 "%val64_1 = OpFConvert %v2f64 %val16_1\n"
8314 "%outloc_1 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_1\n"
8315 " OpStore %outloc_1 %val64_1\n"
8316
8317 "%inloc_2 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_2\n"
8318 "%val16_2 = OpLoad %v2f16 %inloc_2\n"
8319 "%val64_2 = OpFConvert %v2f64 %val16_2\n"
8320 "%outloc_2 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_2\n"
8321 " OpStore %outloc_2 %val64_2\n"
8322
8323 "%inloc_3 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_3\n"
8324 "%val16_3 = OpLoad %v2f16 %inloc_3\n"
8325 "%val64_3 = OpFConvert %v2f64 %val16_3\n"
8326 "%outloc_3 = OpAccessChain %v2f64ptr %ssbo64 %zero %x %c_i32_3\n"
8327 " OpStore %outloc_3 %val64_3\n";
8328 }
8329
8330 spec.assembly = shaderTemplate.specialize(specs);
8331 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
8332 spec.verifyIO = check64BitFloats;
8333 const unsigned padding = isUBO ? cTypes[tyIdx].padding16UBO : cTypes[tyIdx].padding16SSBO;
8334
8335 if (cTypes[tyIdx].dataType == SCALAR || cTypes[tyIdx].dataType == MAT2X2)
8336 {
8337 DE_ASSERT(cTypes[tyIdx].dataType != MAT2X2 || padding == 0);
8338 spec.inputs.push_back(Resource(BufferSp(new Float16Buffer(float16Data, padding)), CAPABILITIES[capIdx].dtype));
8339 }
8340 else if (cTypes[tyIdx].dataType == VEC2)
8341 {
8342 vector<tcu::Vector<deFloat16, 2> > float16Vec2Data(numElements / 2);
8343 for (size_t elemIdx = 0; elemIdx < numElements; elemIdx++)
8344 {
8345 float16Vec2Data[elemIdx / 2][elemIdx % 2] = float16Data[elemIdx];
8346 }
8347
8348 typedef Buffer<tcu::Vector<deFloat16, 2> > Float16Vec2Buffer;
8349 spec.inputs.push_back(Resource(BufferSp(new Float16Vec2Buffer(float16Vec2Data, padding)), CAPABILITIES[capIdx].dtype));
8350 }
8351
8352 spec.outputs.push_back(Resource(BufferSp(new Float64Buffer(cTypes[tyIdx].useConstantIndex ? float64DataConstIdx : float64Data))));
8353 spec.extensions.push_back("VK_KHR_16bit_storage");
8354
8355 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
8356 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
8357
8358 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
8359 }
8360 }
8361 }
8362
addCompute16bitStoragePushConstant16To64Group(tcu::TestCaseGroup * group)8363 void addCompute16bitStoragePushConstant16To64Group (tcu::TestCaseGroup* group)
8364 {
8365 tcu::TestContext& testCtx = group->getTestContext();
8366 de::Random rnd (deStringHash(group->getName()));
8367 const int numElements = 64;
8368
8369 const StringTemplate shaderTemplate (
8370 "OpCapability Shader\n"
8371 "OpCapability StoragePushConstant16\n"
8372 "OpCapability Float64\n"
8373 "OpExtension \"SPV_KHR_16bit_storage\"\n"
8374 "OpMemoryModel Logical GLSL450\n"
8375 "OpEntryPoint GLCompute %main \"main\" %id\n"
8376 "OpExecutionMode %main LocalSize 1 1 1\n"
8377 "OpDecorate %id BuiltIn GlobalInvocationId\n"
8378
8379 "${stride}"
8380
8381 "OpDecorate %PC16 Block\n"
8382 "OpMemberDecorate %PC16 0 Offset 0\n"
8383 "OpMemberDecorate %SSBO64 0 Offset 0\n"
8384 "OpDecorate %SSBO64 BufferBlock\n"
8385 "OpDecorate %ssbo64 DescriptorSet 0\n"
8386 "OpDecorate %ssbo64 Binding 0\n"
8387
8388 "${matrix_decor:opt}\n"
8389
8390 "%bool = OpTypeBool\n"
8391 "%void = OpTypeVoid\n"
8392 "%voidf = OpTypeFunction %void\n"
8393 "%u32 = OpTypeInt 32 0\n"
8394 "%i32 = OpTypeInt 32 1\n"
8395 "%f32 = OpTypeFloat 32\n"
8396 "%uvec3 = OpTypeVector %u32 3\n"
8397 "%fvec3 = OpTypeVector %f32 3\n"
8398 "%uvec3ptr = OpTypePointer Input %uvec3\n"
8399 "%i32ptr = OpTypePointer Uniform %i32\n"
8400 "%f32ptr = OpTypePointer Uniform %f32\n"
8401
8402 "%zero = OpConstant %i32 0\n"
8403 "%c_i32_1 = OpConstant %i32 1\n"
8404 "%c_i32_8 = OpConstant %i32 8\n"
8405 "%c_i32_16 = OpConstant %i32 16\n"
8406 "%c_i32_32 = OpConstant %i32 32\n"
8407 "%c_i32_64 = OpConstant %i32 64\n"
8408
8409 "%i32arr = OpTypeArray %i32 %c_i32_64\n"
8410 "%f32arr = OpTypeArray %f32 %c_i32_64\n"
8411
8412 "${types}\n"
8413 "${matrix_types:opt}\n"
8414
8415 "%PC16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n"
8416 "%pp_PC16 = OpTypePointer PushConstant %PC16\n"
8417 "%pc16 = OpVariable %pp_PC16 PushConstant\n"
8418 "%SSBO64 = OpTypeStruct %${matrix_prefix:opt}${base64}arr\n"
8419 "%up_SSBO64 = OpTypePointer Uniform %SSBO64\n"
8420 "%ssbo64 = OpVariable %up_SSBO64 Uniform\n"
8421
8422 "%id = OpVariable %uvec3ptr Input\n"
8423
8424 "%main = OpFunction %void None %voidf\n"
8425 "%label = OpLabel\n"
8426 "%idval = OpLoad %uvec3 %id\n"
8427 "%x = OpCompositeExtract %u32 %idval 0\n"
8428 "%inloc = OpAccessChain %${base16}ptr %pc16 %zero %x ${index0:opt}\n"
8429 "%val16 = OpLoad %${base16} %inloc\n"
8430 "%val64 = ${convert} %${base64} %val16\n"
8431 "%outloc = OpAccessChain %${base64}ptr %ssbo64 %zero %x ${index0:opt}\n"
8432 " OpStore %outloc %val64\n"
8433 "${matrix_store:opt}\n"
8434 " OpReturn\n"
8435 " OpFunctionEnd\n");
8436
8437 { // floats
8438 const char floatTypes[] =
8439 "%f16 = OpTypeFloat 16\n"
8440 "%f16ptr = OpTypePointer PushConstant %f16\n"
8441 "%f16arr = OpTypeArray %f16 %c_i32_64\n"
8442 "%f64 = OpTypeFloat 64\n"
8443 "%f64ptr = OpTypePointer Uniform %f64\n"
8444 "%f64arr = OpTypeArray %f64 %c_i32_64\n"
8445 "%v4f16 = OpTypeVector %f16 4\n"
8446 "%v4f32 = OpTypeVector %f32 4\n"
8447 "%v4f64 = OpTypeVector %f64 4\n"
8448 "%v4f16ptr = OpTypePointer PushConstant %v4f16\n"
8449 "%v4f32ptr = OpTypePointer Uniform %v4f32\n"
8450 "%v4f64ptr = OpTypePointer Uniform %v4f64\n"
8451 "%v4f16arr = OpTypeArray %v4f16 %c_i32_16\n"
8452 "%v4f32arr = OpTypeArray %v4f32 %c_i32_16\n"
8453 "%v4f64arr = OpTypeArray %v4f64 %c_i32_16\n";
8454
8455 struct CompositeType
8456 {
8457 const char* name;
8458 const char* base64;
8459 const char* base16;
8460 const char* stride;
8461 unsigned count;
8462 };
8463
8464 const CompositeType cTypes[] =
8465 {
8466 {"scalar", "f64", "f16", "OpDecorate %f64arr ArrayStride 8\nOpDecorate %f16arr ArrayStride 2\n", numElements},
8467 {"vector", "v4f64", "v4f16", "OpDecorate %v4f64arr ArrayStride 32\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4},
8468 {"matrix", "v4f64", "v4f16", "OpDecorate %m2v4f64arr ArrayStride 64\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8},
8469 };
8470
8471 vector<deFloat16> float16Data = getFloat16s(rnd, numElements);
8472 vector<double> float64Data;
8473
8474 float64Data.reserve(numElements);
8475 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
8476 float64Data.push_back(deFloat16To64(float16Data[numIdx]));
8477
8478 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx)
8479 {
8480 ComputeShaderSpec spec;
8481 map<string, string> specs;
8482 string testName = string(cTypes[tyIdx].name) + "_float";
8483
8484 specs["stride"] = cTypes[tyIdx].stride;
8485 specs["base64"] = cTypes[tyIdx].base64;
8486 specs["base16"] = cTypes[tyIdx].base16;
8487 specs["types"] = floatTypes;
8488 specs["convert"] = "OpFConvert";
8489
8490 if (strcmp(cTypes[tyIdx].name, "matrix") == 0)
8491 {
8492 specs["index0"] = "%zero";
8493 specs["matrix_prefix"] = "m2";
8494 specs["matrix_types"] =
8495 "%m2v4f16 = OpTypeMatrix %v4f16 2\n"
8496 "%m2v4f64 = OpTypeMatrix %v4f64 2\n"
8497 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_8\n"
8498 "%m2v4f64arr = OpTypeArray %m2v4f64 %c_i32_8\n";
8499 specs["matrix_decor"] =
8500 "OpMemberDecorate %SSBO64 0 ColMajor\n"
8501 "OpMemberDecorate %SSBO64 0 MatrixStride 32\n"
8502 "OpMemberDecorate %PC16 0 ColMajor\n"
8503 "OpMemberDecorate %PC16 0 MatrixStride 8\n";
8504 specs["matrix_store"] =
8505 "%inloc_1 = OpAccessChain %v4f16ptr %pc16 %zero %x %c_i32_1\n"
8506 "%val16_1 = OpLoad %v4f16 %inloc_1\n"
8507 "%val64_1 = OpFConvert %v4f64 %val16_1\n"
8508 "%outloc_1 = OpAccessChain %v4f64ptr %ssbo64 %zero %x %c_i32_1\n"
8509 " OpStore %outloc_1 %val64_1\n";
8510 }
8511
8512 spec.assembly = shaderTemplate.specialize(specs);
8513 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1);
8514 spec.verifyIO = check64BitFloats;
8515 spec.pushConstants = BufferSp(new Float16Buffer(float16Data));
8516
8517 spec.outputs.push_back(BufferSp(new Float64Buffer(float64Data)));
8518
8519 spec.extensions.push_back("VK_KHR_16bit_storage");
8520
8521 spec.requestedVulkanFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
8522 spec.requestedVulkanFeatures.ext16BitStorage.storagePushConstant16 = true;
8523
8524 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
8525 }
8526 }
8527 }
8528
8529 } // anonymous
8530
create16BitStorageComputeGroup(tcu::TestContext & testCtx)8531 tcu::TestCaseGroup* create16BitStorageComputeGroup (tcu::TestContext& testCtx)
8532 {
8533 // Compute tests for VK_KHR_16bit_storage extension
8534 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage"));
8535 // 64bit floats to 16bit tests under capability StorageUniform{|BufferBlock}
8536 addTestGroup(group.get(), "uniform_64_to_16", addCompute16bitStorageUniform64To16Group);
8537 // 32bit floats/ints to 16bit tests under capability StorageUniform{|BufferBlock}
8538 addTestGroup(group.get(), "uniform_32_to_16", addCompute16bitStorageUniform32To16Group);
8539 // 16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}
8540 addTestGroup(group.get(), "uniform_16_to_32", addCompute16bitStorageUniform16To32Group);
8541 // 16bit floats to 64bit tests under capability StorageUniform{|BufferBlock}
8542 addTestGroup(group.get(), "uniform_16_to_64", addCompute16bitStorageUniform16To64Group);
8543 // 16bit floats/ints to 32bit tests under capability StoragePushConstant16
8544 addTestGroup(group.get(), "push_constant_16_to_32", addCompute16bitStoragePushConstant16To32Group);
8545 // 16bit floats to 64bit tests under capability StoragePushConstant16
8546 addTestGroup(group.get(), "push_constant_16_to_64", addCompute16bitStoragePushConstant16To64Group);
8547 // 16bit floats struct to 32bit tests under capability StorageUniform{|BufferBlock}
8548 addTestGroup(group.get(), "uniform_16struct_to_32struct", addCompute16bitStorageUniform16StructTo32StructGroup);
8549 // 32bit floats struct to 16bit tests under capability StorageUniform{|BufferBlock}
8550 addTestGroup(group.get(), "uniform_32struct_to_16struct", addCompute16bitStorageUniform32StructTo16StructGroup);
8551 // mixed type of 8bit and 32bit struct
8552 addTestGroup(group.get(), "struct_mixed_types", addCompute16bitStructMixedTypesGroup);
8553 // 16bit floats/ints to 16bit tests under capability StorageUniformBufferBlock16
8554 addTestGroup(group.get(), "uniform_16_to_16", addCompute16bitStorageUniform16To16Group);
8555 // chain access 16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}
8556 addTestGroup(group.get(), "uniform_16_to_32_chainaccess", addCompute16bitStorageUniform16To32ChainAccessGroup);
8557
8558 return group.release();
8559 }
8560
create16BitStorageGraphicsGroup(tcu::TestContext & testCtx)8561 tcu::TestCaseGroup* create16BitStorageGraphicsGroup (tcu::TestContext& testCtx)
8562 {
8563 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Graphics tests for VK_KHR_16bit_storage extension"));
8564
8565 // 64-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16
8566 addTestGroup(group.get(), "uniform_float_64_to_16", addGraphics16BitStorageUniformFloat64To16Group);
8567 // 32-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16
8568 addTestGroup(group.get(), "uniform_float_32_to_16", addGraphics16BitStorageUniformFloat32To16Group);
8569 // 16-bit floats into 32-bit testsunder capability StorageUniform{|BufferBlock}16
8570 addTestGroup(group.get(), "uniform_float_16_to_32", addGraphics16BitStorageUniformFloat16To32Group);
8571 // 16-bit floats into 64-bit testsunder capability StorageUniform{|BufferBlock}16
8572 addTestGroup(group.get(), "uniform_float_16_to_64", addGraphics16BitStorageUniformFloat16To64Group);
8573 // 32-bit int into 16-bit tests under capability StorageUniform{|BufferBlock}16
8574 addTestGroup(group.get(), "uniform_int_32_to_16", addGraphics16BitStorageUniformInt32To16Group);
8575 // 16-bit int into 32-bit tests under capability StorageUniform{|BufferBlock}16
8576 addTestGroup(group.get(), "uniform_int_16_to_32", addGraphics16BitStorageUniformInt16To32Group);
8577 // 64-bit floats into 16-bit tests under capability StorageInputOutput16
8578 addTestGroup(group.get(), "input_output_float_64_to_16", addGraphics16BitStorageInputOutputFloat64To16Group);
8579 // 32-bit floats into 16-bit tests under capability StorageInputOutput16
8580 addTestGroup(group.get(), "input_output_float_32_to_16", addGraphics16BitStorageInputOutputFloat32To16Group);
8581 // 16-bit floats into 32-bit tests under capability StorageInputOutput16
8582 addTestGroup(group.get(), "input_output_float_16_to_32", addGraphics16BitStorageInputOutputFloat16To32Group);
8583 // 16-bit floats pass-through tests under capability StorageInputOutput16
8584 addTestGroup(group.get(), "input_output_float_16_to_16", addGraphics16BitStorageInputOutputFloat16To16Group);
8585 // 16-bit floats into 64-bit tests under capability StorageInputOutput16
8586 addTestGroup(group.get(), "input_output_float_16_to_64", addGraphics16BitStorageInputOutputFloat16To64Group);
8587 // 16-bit floats pass-through to two outputs tests under capability StorageInputOutput16
8588 addTestGroup(group.get(), "input_output_float_16_to_16x2", addGraphics16BitStorageInputOutputFloat16To16x2Group);
8589 // 16-bit ints pass-through to two outputs tests under capability StorageInputOutput16
8590 addTestGroup(group.get(), "input_output_int_16_to_16x2", addGraphics16BitStorageInputOutputInt16To16x2Group);
8591 // 32-bit int into 16-bit tests under capability StorageInputOutput16
8592 addTestGroup(group.get(), "input_output_int_32_to_16", addGraphics16BitStorageInputOutputInt32To16Group);
8593 // 16-bit int into 32-bit tests under capability StorageInputOutput16
8594 addTestGroup(group.get(), "input_output_int_16_to_32", addGraphics16BitStorageInputOutputInt16To32Group);
8595 // 16-bit int into 16-bit tests under capability StorageInputOutput16
8596 addTestGroup(group.get(), "input_output_int_16_to_16", addGraphics16BitStorageInputOutputInt16To16Group);
8597 // 16-bit floats into 32-bit tests under capability StoragePushConstant16
8598 addTestGroup(group.get(), "push_constant_float_16_to_32", addGraphics16BitStoragePushConstantFloat16To32Group);
8599 // 16-bit floats into 64-bit tests under capability StoragePushConstant16
8600 addTestGroup(group.get(), "push_constant_float_16_to_64", addGraphics16BitStoragePushConstantFloat16To64Group);
8601 // 16-bit int into 32-bit tests under capability StoragePushConstant16
8602 addTestGroup(group.get(), "push_constant_int_16_to_32", addGraphics16BitStoragePushConstantInt16To32Group);
8603 // 16-bit float struct into 32-bit tests under capability StorageUniform{|BufferBlock}16
8604 addTestGroup(group.get(), "uniform_16struct_to_32struct", addGraphics16BitStorageUniformStructFloat16To32Group);
8605 // 32-bit float struct into 16-bit tests under capability StorageUniform{|BufferBlock}16
8606 addTestGroup(group.get(), "uniform_32struct_to_16struct", addGraphics16BitStorageUniformStructFloat32To16Group);
8607 // mixed type of 8bit and 32bit struct
8608 addTestGroup(group.get(), "struct_mixed_types", addGraphics16bitStructMixedTypesGroup);
8609
8610 return group.release();
8611 }
8612
8613 } // SpirVAssembly
8614 } // vkt
8615