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