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 images and samplers.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmImageSamplerTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28
29 #include "vkImageUtil.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuVectorUtil.hpp"
32
33 namespace vkt
34 {
35 namespace SpirVAssembly
36 {
37
38 using namespace vk;
39 using std::map;
40 using std::string;
41 using std::vector;
42 using tcu::IVec3;
43 using tcu::RGBA;
44 using tcu::Vec4;
45
46 namespace
47 {
48 enum TestType
49 {
50 TESTTYPE_LOCAL_VARIABLES = 0,
51 TESTTYPE_PASS_IMAGE_TO_FUNCTION,
52 TESTTYPE_PASS_SAMPLER_TO_FUNCTION,
53 TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION,
54 TESTTYPE_OPTYPEIMAGE_MISMATCH,
55
56 TESTTYPE_LAST
57 };
58
59 enum ReadOp
60 {
61 READOP_IMAGEREAD = 0,
62 READOP_IMAGEFETCH,
63 READOP_IMAGESAMPLE,
64 READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD,
65 READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD,
66
67 READOP_LAST
68 };
69
70 enum DescriptorType
71 {
72 DESCRIPTOR_TYPE_STORAGE_IMAGE = 0, // Storage image
73 DESCRIPTOR_TYPE_SAMPLED_IMAGE, // Sampled image
74 DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // Combined image sampler
75 DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES, // Combined image sampler with separate shader variables
76 DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS, // Combined image sampler where image and sampler variables are taken from two different desciptors
77
78 DESCRIPTOR_TYPE_LAST
79 };
80
81 enum DepthProperty
82 {
83 DEPTH_PROPERTY_NON_DEPTH = 0,
84 DEPTH_PROPERTY_DEPTH,
85 DEPTH_PROPERTY_UNKNOWN,
86
87 DEPTH_PROPERTY_LAST
88 };
89
isValidTestCase(TestType testType,DescriptorType descriptorType,ReadOp readOp)90 bool isValidTestCase (TestType testType, DescriptorType descriptorType, ReadOp readOp)
91 {
92 // Check valid descriptor type and test type combinations
93 switch (testType)
94 {
95 case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
96 if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE &&
97 descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
98 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
99 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
100 return false;
101 break;
102
103 case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
104 if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
105 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
106 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
107 return false;
108 break;
109
110 case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
111 if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
112 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
113 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
114 return false;
115 break;
116
117 default:
118 break;
119 }
120
121 // Check valid descriptor type and read operation combinations
122 switch (readOp)
123 {
124 case READOP_IMAGEREAD:
125 if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE)
126 return false;
127 break;
128
129 case READOP_IMAGEFETCH:
130 if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
131 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
132 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
133 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
134 return false;
135 break;
136
137 case READOP_IMAGESAMPLE:
138 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
139 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
140 if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE &&
141 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
142 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES &&
143 descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
144 return false;
145 break;
146
147 default:
148 break;
149 }
150
151 // Check valid test type and readOp combination
152 switch (testType)
153 {
154 case TESTTYPE_OPTYPEIMAGE_MISMATCH:
155 // OPTYPEIMAGE_MISTMATCH does not test DEPTH formats
156 if (readOp == READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD ||
157 readOp == READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD)
158 return false;
159 break;
160
161 default:
162 break;
163 }
164
165 return true;
166 }
167
getTestTypeName(TestType testType)168 const char* getTestTypeName (TestType testType)
169 {
170 switch (testType)
171 {
172 case TESTTYPE_LOCAL_VARIABLES:
173 return "all_local_variables";
174
175 case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
176 return "pass_image_to_function";
177
178 case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
179 return "pass_sampler_to_function";
180
181 case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
182 return "pass_image_and_sampler_to_function";
183
184 case TESTTYPE_OPTYPEIMAGE_MISMATCH:
185 return "optypeimage_mismatch";
186
187 default:
188 DE_FATAL("Unknown test type");
189 return "";
190 }
191 }
192
getReadOpName(ReadOp readOp)193 const char* getReadOpName (ReadOp readOp)
194 {
195 switch (readOp)
196 {
197 case READOP_IMAGEREAD:
198 return "imageread";
199
200 case READOP_IMAGEFETCH:
201 return "imagefetch";
202
203 case READOP_IMAGESAMPLE:
204 return "imagesample";
205
206 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
207 return "imagesample_dref_implicit_lod";
208
209 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
210 return "imagesample_dref_explicit_lod";
211
212 default:
213 DE_FATAL("Unknown readop");
214 return "";
215 }
216 }
217
getDescriptorName(DescriptorType descType)218 const char* getDescriptorName (DescriptorType descType)
219 {
220 switch (descType)
221 {
222 case DESCRIPTOR_TYPE_STORAGE_IMAGE:
223 return "storage_image";
224
225 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
226 return "sampled_image";
227
228 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
229 return "combined_image_sampler";
230
231 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
232 return "combined_image_sampler_separate_variables";
233
234 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
235 return "combined_image_sampler_separate_descriptors";
236
237 default:
238 DE_FATAL("Unknown descriptor type");
239 return "";
240 }
241 }
242
getDepthPropertyName(DepthProperty depthProperty)243 const char* getDepthPropertyName (DepthProperty depthProperty)
244 {
245 switch (depthProperty)
246 {
247 case DEPTH_PROPERTY_NON_DEPTH:
248 return "non_depth";
249
250 case DEPTH_PROPERTY_DEPTH:
251 return "depth";
252
253 case DEPTH_PROPERTY_UNKNOWN:
254 return "unknown";
255
256 default:
257 DE_FATAL("Unknown depth property");
258 return "";
259 }
260 }
261
getVkDescriptorType(DescriptorType descType)262 VkDescriptorType getVkDescriptorType (DescriptorType descType)
263 {
264 switch (descType)
265 {
266 case DESCRIPTOR_TYPE_STORAGE_IMAGE:
267 return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
268
269 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
270 return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
271
272 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
273 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
274 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
275 return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
276
277 default:
278 DE_FATAL("Unknown descriptor type");
279 return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
280 }
281 }
282
getImageFormat(ReadOp readOp)283 VkFormat getImageFormat (ReadOp readOp)
284 {
285 switch (readOp)
286 {
287 case READOP_IMAGEREAD:
288 case READOP_IMAGEFETCH:
289 case READOP_IMAGESAMPLE:
290 return VK_FORMAT_R32G32B32A32_SFLOAT;
291
292 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
293 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
294 return VK_FORMAT_D32_SFLOAT;
295
296 default:
297 DE_FATAL("Unknown readop");
298 return VK_FORMAT_UNDEFINED;
299 }
300 }
301
302 // Get variables that are declared in the read function, ie. not passed as parameters
getFunctionDstVariableStr(ReadOp readOp,DescriptorType descType,TestType testType)303 std::string getFunctionDstVariableStr (ReadOp readOp, DescriptorType descType, TestType testType)
304 {
305 const bool passNdx = (testType == TESTTYPE_LOCAL_VARIABLES) || (testType == TESTTYPE_OPTYPEIMAGE_MISMATCH);
306 const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
307 const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
308
309 std::string result = "";
310
311 switch (descType)
312 {
313 case DESCRIPTOR_TYPE_STORAGE_IMAGE:
314 {
315 switch (readOp)
316 {
317 case READOP_IMAGEREAD:
318 if (passNdx)
319 return " %func_img = OpLoad %Image %InputData\n";
320 break;
321
322 default:
323 DE_FATAL("Not possible");
324 break;
325 }
326 break;
327 }
328 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
329 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
330 {
331 switch (readOp)
332 {
333 case READOP_IMAGEFETCH:
334 if (passNdx)
335 return " %func_img = OpLoad %Image %InputData\n";
336
337 if (passSmp && !passImg)
338 return " %func_tmp = OpLoad %Image %InputData\n"
339 " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
340 " %func_img = OpImage %Image %func_smi\n";
341
342 if (passSmp && passImg)
343 return " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
344 " %func_img = OpImage %Image %func_smi\n";
345 break;
346
347 case READOP_IMAGESAMPLE:
348 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
349 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
350 if (passNdx)
351 return " %func_img = OpLoad %Image %InputData\n"
352 " %func_smp = OpLoad %Sampler %SamplerData\n"
353 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
354
355 if (passImg && !passSmp)
356 return " %func_smp = OpLoad %Sampler %SamplerData\n"
357 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
358
359 if (passSmp && !passImg)
360 return " %func_img = OpLoad %Image %InputData\n"
361 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
362
363 if (passSmp && passImg)
364 return " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
365 break;
366
367 default:
368 DE_FATAL("Not possible");
369 }
370 break;
371 }
372
373 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
374 {
375 switch (readOp)
376 {
377 case READOP_IMAGEFETCH:
378 if (passNdx)
379 return " %func_smi = OpLoad %SampledImage %InputData\n"
380 " %func_img = OpImage %Image %func_smi\n";
381 break;
382
383 case READOP_IMAGESAMPLE:
384 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
385 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
386 if (passNdx)
387 return " %func_smi = OpLoad %SampledImage %InputData\n";
388 break;
389
390 default:
391 DE_FATAL("Not possible");
392 }
393 break;
394 }
395
396 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
397 {
398 switch (readOp)
399 {
400 case READOP_IMAGEFETCH:
401 if (passNdx)
402 return " %func_img = OpLoad %Image %InputData2\n";
403
404 if (passSmp && !passImg)
405 return " %func_tmp = OpLoad %Image %InputData2\n"
406 " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
407 " %func_img = OpImage %Image %func_smi\n";
408
409 if (passSmp && passImg)
410 return " %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
411 " %func_img = OpImage %Image %func_smi\n";
412 break;
413
414 case READOP_IMAGESAMPLE:
415 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
416 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
417 if (passNdx)
418 return " %func_img = OpLoad %Image %InputData2\n"
419 " %func_smp = OpLoad %Sampler %SamplerData\n"
420 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
421
422 if (passImg && !passSmp)
423 return " %func_smp = OpLoad %Sampler %SamplerData\n"
424 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
425
426 if (passSmp && !passImg)
427 return " %func_img = OpLoad %Image %InputData2\n"
428 " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
429
430 if (passSmp && passImg)
431 return " %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
432 break;
433
434 default:
435 DE_FATAL("Not possible");
436 }
437 break;
438 }
439
440 default:
441 DE_FATAL("Unknown descriptor type");
442 }
443
444 return result;
445 }
446
447 // Get variables that are passed to the read function
getFunctionSrcVariableStr(ReadOp readOp,DescriptorType descType,TestType testType)448 std::string getFunctionSrcVariableStr (ReadOp readOp, DescriptorType descType, TestType testType)
449 {
450 const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
451 const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
452
453 string result = "";
454
455 switch (descType)
456 {
457 case DESCRIPTOR_TYPE_STORAGE_IMAGE:
458 {
459 switch (readOp)
460 {
461 case READOP_IMAGEREAD:
462 if (passImg)
463 result += " %call_img = OpLoad %Image %InputData\n";
464 break;
465
466 default:
467 DE_FATAL("Not possible");
468 }
469 break;
470 }
471 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
472 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
473 {
474 switch (readOp)
475 {
476 case READOP_IMAGEFETCH:
477 case READOP_IMAGESAMPLE:
478 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
479 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
480 if (passImg)
481 result += " %call_img = OpLoad %Image %InputData\n";
482
483 if (passSmp)
484 result += " %call_smp = OpLoad %Sampler %SamplerData\n";
485 break;
486
487 default:
488 DE_FATAL("Not possible");
489 }
490 break;
491 }
492 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
493 {
494 break;
495 }
496 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
497 {
498 switch (readOp)
499 {
500 case READOP_IMAGEFETCH:
501 case READOP_IMAGESAMPLE:
502 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
503 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
504 if (passImg)
505 result += " %call_img = OpLoad %Image %InputData2\n";
506
507 if (passSmp)
508 result += " %call_smp = OpLoad %Sampler %SamplerData\n";
509 break;
510
511 default:
512 DE_FATAL("Not possible");
513 }
514 break;
515 }
516 default:
517 DE_FATAL("Unknown descriptor type");
518 }
519
520 return result;
521 }
522
523 // Get parameter types for OpTypeFunction
getFunctionParamTypeStr(TestType testType)524 std::string getFunctionParamTypeStr (TestType testType)
525 {
526 const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
527 const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
528
529 string result = "";
530
531 if (passImg)
532 result += " %Image";
533
534 if (passSmp)
535 result += " %Sampler";
536
537 return result;
538 }
539
540 // Get argument names for OpFunctionCall
getFunctionSrcParamStr(TestType testType)541 std::string getFunctionSrcParamStr (TestType testType)
542 {
543 const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
544 const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
545
546 string result = "";
547
548 if (passImg)
549 result += " %call_img";
550
551 if (passSmp)
552 result += " %call_smp";
553
554 return result;
555 }
556
557 // Get OpFunctionParameters
getFunctionDstParamStr(ReadOp readOp,TestType testType)558 std::string getFunctionDstParamStr (ReadOp readOp, TestType testType)
559 {
560 const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
561 const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION) || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
562
563 string result = "";
564
565 switch (readOp)
566 {
567 case READOP_IMAGESAMPLE:
568 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
569 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
570 if (passImg)
571 result += " %func_img = OpFunctionParameter %Image\n";
572
573 if (passSmp)
574 result += " %func_smp = OpFunctionParameter %Sampler\n";
575 break;
576
577 default:
578 if (passImg && !passSmp)
579 result += " %func_img = OpFunctionParameter %Image\n";
580
581 if (passSmp && !passImg)
582 result += " %func_smp = OpFunctionParameter %Sampler\n";
583
584 if (passImg && passSmp)
585 result += " %func_tmp = OpFunctionParameter %Image\n"
586 " %func_smp = OpFunctionParameter %Sampler\n";
587 break;
588 }
589
590 return result;
591 }
592
593 struct FormatDataForShaders
594 {
595 vk::VkFormat m_format;
596 std::string m_name;
597 std::string m_spirvMismatchFormat;
598 std::string m_spirvType;
599 std::string m_spirvVectorType;
600 };
601
602 static const FormatDataForShaders optypeimageFormatMismatchSpirvData[] =
603 {
604 { vk::VK_FORMAT_R8G8B8A8_UNORM, "rgba8", "Rgba16f", "%f32", "%v4f32" },
605 { vk::VK_FORMAT_R8G8B8A8_SNORM, "rgba8snorm", "Rgba16f", "%f32", "%v4f32" },
606 { vk::VK_FORMAT_R8G8B8A8_UINT, "rgba8ui", "Rgba16ui", "%u32", "%v4u32" },
607 { vk::VK_FORMAT_R8G8B8A8_SINT, "rgba8i", "Rgba16i", "%i32", "%v4i32" },
608 { vk::VK_FORMAT_R16G16B16A16_UINT, "rgba16ui", "Rgba32ui", "%u32", "%v4u32" },
609 { vk::VK_FORMAT_R16G16B16A16_SINT, "rgba16i", "Rgba32i", "%i32", "%v4i32" },
610 { vk::VK_FORMAT_R16G16B16A16_SFLOAT, "rgba16f", "Rgba32f", "%f32", "%v4f32" },
611 { vk::VK_FORMAT_R32_UINT, "r32ui", "Rgba32ui", "%u32", "%v4u32" },
612 { vk::VK_FORMAT_R32_SINT, "r32i", "Rgba32i", "%i32", "%v4i32" },
613 { vk::VK_FORMAT_R32G32B32A32_UINT, "rgba32ui", "Rgba8ui", "%u32", "%v4u32" },
614 { vk::VK_FORMAT_R32G32B32A32_SINT, "rgba32i", "Rgba8i", "%i32", "%v4i32" },
615 { vk::VK_FORMAT_R32G32B32A32_SFLOAT, "rgba32f", "Rgba8", "%f32", "%v4f32" },
616 };
617
618 static const uint32_t optypeimageFormatMismatchFormatCount = DE_LENGTH_OF_ARRAY(optypeimageFormatMismatchSpirvData);
619
620 // Get read operation
getImageReadOpStr(ReadOp readOp,const FormatDataForShaders & formatData,bool useNontemporal=false)621 std::string getImageReadOpStr (ReadOp readOp, const FormatDataForShaders& formatData, bool useNontemporal = false)
622 {
623 std::string imageOperand = useNontemporal ? " Nontemporal" : "";
624
625 switch (readOp)
626 {
627 case READOP_IMAGEREAD:
628 return "OpImageRead " + formatData.m_spirvVectorType + " %func_img %coord" + imageOperand;
629
630 case READOP_IMAGEFETCH:
631 return "OpImageFetch " + formatData.m_spirvVectorType + " %func_img %coord" + imageOperand;
632
633 case READOP_IMAGESAMPLE:
634 if (useNontemporal)
635 return "OpImageSampleExplicitLod " + formatData.m_spirvVectorType + " %func_smi %normalcoordf Lod|Nontemporal %c_f32_0";
636 return "OpImageSampleExplicitLod " + formatData.m_spirvVectorType + " %func_smi %normalcoordf Lod %c_f32_0";
637
638 case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
639 return "OpImageSampleDrefImplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Bias %c_f32_0";
640
641 case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
642 return "OpImageSampleDrefExplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Lod %c_f32_0";
643
644 default:
645 DE_FATAL("Unknown readop");
646 return "";
647 }
648 }
649
isImageSampleDrefReadOp(ReadOp readOp)650 bool isImageSampleDrefReadOp (ReadOp readOp)
651 {
652 return (readOp == READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD) || (readOp == READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD);
653 }
654
655 // Get types and pointers for input images and samplers
getImageSamplerTypeStr(DescriptorType descType,ReadOp readOp,deUint32 depthProperty,TestType testType,const FormatDataForShaders & formatData)656 std::string getImageSamplerTypeStr (DescriptorType descType, ReadOp readOp, deUint32 depthProperty, TestType testType, const FormatDataForShaders& formatData)
657 {
658 const string imageFormat = (testType == TESTTYPE_OPTYPEIMAGE_MISMATCH) ? formatData.m_spirvMismatchFormat :
659 isImageSampleDrefReadOp(readOp) ? "R32f" : "Rgba32f";
660
661 switch (descType)
662 {
663 case DESCRIPTOR_TYPE_STORAGE_IMAGE:
664 return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) + " 0 0 2 " + imageFormat + "\n"
665 " %ImagePtr = OpTypePointer UniformConstant %Image\n"
666 " %InputData = OpVariable %ImagePtr UniformConstant\n";
667
668 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
669 return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
670 " %ImagePtr = OpTypePointer UniformConstant %Image\n"
671 " %InputData = OpVariable %ImagePtr UniformConstant\n"
672
673 " %Sampler = OpTypeSampler\n"
674 " %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
675 " %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
676 " %SampledImage = OpTypeSampledImage %Image\n";
677
678 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
679 return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
680 " %SampledImage = OpTypeSampledImage %Image\n"
681 " %SamplerPtr = OpTypePointer UniformConstant %SampledImage\n"
682 " %InputData = OpVariable %SamplerPtr UniformConstant\n";
683
684 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
685 return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
686 " %ImagePtr = OpTypePointer UniformConstant %Image\n"
687 " %InputData = OpVariable %ImagePtr UniformConstant\n"
688
689 " %Sampler = OpTypeSampler\n"
690 " %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
691 " %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
692 " %SampledImage = OpTypeSampledImage %Image\n";
693
694 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
695 return " %Image = OpTypeImage " + formatData.m_spirvType + " 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
696 " %ImagePtr = OpTypePointer UniformConstant %Image\n"
697 " %InputData = OpVariable %ImagePtr UniformConstant\n"
698 " %InputData2 = OpVariable %ImagePtr UniformConstant\n"
699
700 " %Sampler = OpTypeSampler\n"
701 " %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
702 " %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
703 " %SamplerData2 = OpVariable %SamplerPtr UniformConstant\n"
704 " %SampledImage = OpTypeSampledImage %Image\n";
705
706 default:
707 DE_FATAL("Unknown descriptor type");
708 return "";
709 }
710 }
711
getInterfaceList(DescriptorType descType)712 std::string getInterfaceList (DescriptorType descType)
713 {
714 std::string list = " %InputData %OutputData";
715 switch (descType)
716 {
717 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
718 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
719 list += " %SamplerData";
720 break;
721
722 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
723 list += " %SamplerData %InputData2 %SamplerData2";
724 break;
725
726 default:
727 break;
728 }
729
730 return list;
731 }
732
getSamplerDecoration(DescriptorType descType)733 std::string getSamplerDecoration (DescriptorType descType)
734 {
735 switch (descType)
736 {
737 // Separate image and sampler
738 case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
739 return " OpDecorate %SamplerData DescriptorSet 0\n"
740 " OpDecorate %SamplerData Binding 1\n";
741
742 // Combined image sampler with separate variables
743 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
744 return " OpDecorate %SamplerData DescriptorSet 0\n"
745 " OpDecorate %SamplerData Binding 0\n";
746
747 // Two combined image samplers with separate variables
748 case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
749 return " OpDecorate %SamplerData DescriptorSet 0\n"
750 " OpDecorate %SamplerData Binding 0\n"
751 " OpDecorate %InputData2 DescriptorSet 0\n"
752 " OpDecorate %InputData2 Binding 1\n"
753 " OpDecorate %SamplerData2 DescriptorSet 0\n"
754 " OpDecorate %SamplerData2 Binding 1\n";
755
756 default:
757 return "";
758 }
759 }
760
761 // no-operation verify functon to ignore test results (optypeimage_mismatch)
nopVerifyFunction(const std::vector<Resource> &,const std::vector<AllocationSp> &,const std::vector<Resource> &,tcu::TestLog &)762 bool nopVerifyFunction (const std::vector<Resource>&,
763 const std::vector<AllocationSp>&,
764 const std::vector<Resource>&,
765 tcu::TestLog&)
766 {
767 return true;
768 }
769
addComputeImageSamplerTest(tcu::TestCaseGroup * group)770 void addComputeImageSamplerTest (tcu::TestCaseGroup* group)
771 {
772 tcu::TestContext& testCtx = group->getTestContext();
773
774 de::Random rnd (deStringHash(group->getName()));
775 const deUint32 numDataPoints = 64;
776 RGBA defaultColors[4];
777 vector<tcu::Vec4> inputData;
778
779 inputData.reserve(numDataPoints);
780
781 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
782 inputData.push_back(tcu::randomVec4(rnd));
783
784 struct SpirvData
785 {
786 SpirvVersion version;
787 std::string postfix;
788 };
789 const std::vector<SpirvData> spirvDataVect
790 {
791 { SPIRV_VERSION_1_0, "" },
792 { SPIRV_VERSION_1_6, "_nontemporal" },
793 };
794
795 for (deUint32 opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++)
796 {
797 de::MovePtr<tcu::TestCaseGroup> readOpGroup (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx)));
798
799 for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
800 {
801 de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx)));
802
803 for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
804 {
805 if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
806 continue;
807
808 deUint32 numFormats = 1;
809 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
810 numFormats = optypeimageFormatMismatchFormatCount;
811
812 for (deUint32 formatIndex = 0; formatIndex < numFormats; formatIndex++)
813 {
814 const FormatDataForShaders& formatData = optypeimageFormatMismatchSpirvData[formatIndex];
815
816 const std::string functionParamTypes = getFunctionParamTypeStr((TestType)testNdx);
817
818 const std::string functionSrcVariables = getFunctionSrcVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
819 const std::string functionDstVariables = getFunctionDstVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
820
821 const std::string functionSrcParams = getFunctionSrcParamStr((TestType)testNdx);
822 const std::string functionDstParams = getFunctionDstParamStr((ReadOp)opNdx, (TestType)testNdx);
823
824 getDefaultColors(defaultColors);
825
826 ComputeShaderSpec spec;
827
828 spec.numWorkGroups = IVec3(numDataPoints, 1, 1);
829
830 spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
831
832 // Separate sampler for sampled images
833 if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
834 {
835 vector<tcu::Vec4> unusedData;
836 spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData))));
837 spec.inputs[1].setDescriptorType(VK_DESCRIPTOR_TYPE_SAMPLER);
838 }
839
840 // Second combined image sampler with different image data
841 if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
842 {
843 for (size_t i = 0; i < inputData.size(); i++)
844 inputData[i] = tcu::Vec4(1.0f) - inputData[i];
845
846 spec.inputs.push_back(BufferSp(new Vec4Buffer(inputData)));
847 spec.inputs[1].setDescriptorType(getVkDescriptorType((DescriptorType)descNdx));
848 }
849
850 // Shader is expected to pass the input image data to the output buffer
851 spec.outputs.push_back(BufferSp(new Vec4Buffer(inputData)));
852
853 const std::string samplerDecoration = getSamplerDecoration((DescriptorType)descNdx);
854
855 for (auto spirvData : spirvDataVect)
856 {
857 spec.spirvVersion = spirvData.version;
858
859 bool useSpirV16 (spirvData.version == SPIRV_VERSION_1_6);
860 std::string interfaceList ("");
861 std::string outputDecoration ("BufferBlock");
862 std::string outputType ("Uniform");
863 std::string imageReadOp (getImageReadOpStr((ReadOp)opNdx, formatData, useSpirV16));
864
865 // adjust shader code to spv16
866 if (useSpirV16)
867 {
868 interfaceList = getInterfaceList((DescriptorType)descNdx);
869 outputDecoration = "Block";
870 outputType = "StorageBuffer";
871 }
872
873 string testname = getTestTypeName((TestType)testNdx);
874
875 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
876 {
877 // If testing for mismatched optypeimage, ignore the
878 // result (we're only interested to see if we crash)
879 spec.verifyIO = nopVerifyFunction;
880 spec.inputFormat = formatData.m_format;
881
882 testname = testname + string("_") + formatData.m_name;
883 }
884 testname += spirvData.postfix;
885 de::MovePtr<tcu::TestCaseGroup> typeGroup (new tcu::TestCaseGroup(testCtx, testname.c_str()));
886
887 de::MovePtr<tcu::TestCaseGroup> depthGroup (new tcu::TestCaseGroup(testCtx, "depth_property"));
888 for (deUint32 propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++)
889 {
890 const std::string imageSamplerTypes = getImageSamplerTypeStr((DescriptorType)descNdx, (ReadOp)opNdx, (DepthProperty)propertyNdx, (TestType)testNdx, formatData);
891 const string shaderSource =
892 " OpCapability Shader\n"
893 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
894 " OpMemoryModel Logical GLSL450\n"
895 " OpEntryPoint GLCompute %main \"main\" %id" + interfaceList + "\n"
896 " OpExecutionMode %main LocalSize 1 1 1\n"
897 " OpSource GLSL 430\n"
898 " OpDecorate %id BuiltIn GlobalInvocationId\n"
899 " OpDecorate %_arr_v4type_u32_64 ArrayStride 16\n"
900 " OpMemberDecorate %Output 0 Offset 0\n"
901 " OpDecorate %Output " + outputDecoration + "\n"
902 " OpDecorate %InputData DescriptorSet 0\n"
903 " OpDecorate %InputData Binding 0\n"
904
905 + samplerDecoration +
906
907 " OpDecorate %OutputData DescriptorSet 0\n"
908 " OpDecorate %OutputData Binding " + de::toString(spec.inputs.size()) + "\n"
909
910 " %void = OpTypeVoid\n"
911 " %3 = OpTypeFunction %void\n"
912 " %u32 = OpTypeInt 32 0\n"
913 " %i32 = OpTypeInt 32 1\n"
914 " %f32 = OpTypeFloat 32\n"
915 " %_ptr_Function_uint = OpTypePointer Function %u32\n"
916 " %v3u32 = OpTypeVector %u32 3\n"
917 " %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
918 " %id = OpVariable %_ptr_Input_v3u32 Input\n"
919 " %c_f32_0 = OpConstant %f32 0.0\n"
920 " %c_u32_0 = OpConstant %u32 0\n"
921 " %c_i32_0 = OpConstant %i32 0\n"
922 " %_ptr_Input_uint = OpTypePointer Input %u32\n"
923 " %v2u32 = OpTypeVector %u32 2\n"
924 " %v2f32 = OpTypeVector %f32 2\n"
925 " %v4f32 = OpTypeVector %f32 4\n"
926 " %v4u32 = OpTypeVector %u32 4\n"
927 " %v4i32 = OpTypeVector %i32 4\n"
928 " %uint_128 = OpConstant %u32 128\n"
929 " %c_u32_64 = OpConstant %u32 64\n"
930 " %c_u32_8 = OpConstant %u32 8\n"
931 " %c_f32_8 = OpConstant %f32 8.0\n"
932 " %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
933 " %_arr_v4type_u32_64 = OpTypeArray " + formatData.m_spirvVectorType + " %c_u32_64\n"
934 "%_ptr_Uniform_v4type = OpTypePointer " + outputType + " " + formatData.m_spirvVectorType + "\n"
935 " %Output = OpTypeStruct %_arr_v4type_u32_64\n"
936 "%_ptr_Uniform_Output = OpTypePointer " + outputType + " %Output\n"
937 " %OutputData = OpVariable %_ptr_Uniform_Output " + outputType + "\n"
938
939 + imageSamplerTypes +
940
941 " %read_func_type = OpTypeFunction %void %u32" + functionParamTypes + "\n"
942
943 " %read_func = OpFunction %void None %read_func_type\n"
944 " %func_ndx = OpFunctionParameter %u32\n"
945
946 + functionDstParams +
947
948 " %funcentry = OpLabel\n"
949 " %row = OpUMod %u32 %func_ndx %c_u32_8\n"
950 " %col = OpUDiv %u32 %func_ndx %c_u32_8\n"
951 " %coord = OpCompositeConstruct %v2u32 %row %col\n"
952 " %coordf = OpConvertUToF %v2f32 %coord\n"
953 " %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
954
955 + functionDstVariables +
956
957 " %color = " + imageReadOp + "\n"
958 " %36 = OpAccessChain %_ptr_Uniform_v4type %OutputData %c_u32_0 %func_ndx\n"
959 " OpStore %36 %color\n"
960 " OpReturn\n"
961 " OpFunctionEnd\n"
962
963 " %main = OpFunction %void None %3\n"
964 " %5 = OpLabel\n"
965 " %i = OpVariable %_ptr_Function_uint Function\n"
966 " %14 = OpAccessChain %_ptr_Input_uint %id %c_u32_0\n"
967 " %15 = OpLoad %u32 %14\n"
968 " OpStore %i %15\n"
969 " %index = OpLoad %u32 %14\n"
970
971 + functionSrcVariables +
972
973 " %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
974 " OpReturn\n"
975 " OpFunctionEnd\n";
976
977 spec.assembly = shaderSource;
978
979 depthGroup->addChild(new SpvAsmComputeShaderCase(testCtx, getDepthPropertyName((DepthProperty)propertyNdx), spec));
980 }
981 typeGroup->addChild(depthGroup.release());
982 descGroup->addChild(typeGroup.release());
983 }
984 }
985 }
986 readOpGroup->addChild(descGroup.release());
987 }
988 group->addChild(readOpGroup.release());
989 }
990 }
991
generateGraphicsImageSamplerSource(ReadOp readOp,DescriptorType descriptorType,TestType testType,DepthProperty depthProperty,deUint32 outputBinding,deUint32 formatIndex)992 map<string, string> generateGraphicsImageSamplerSource (ReadOp readOp, DescriptorType descriptorType, TestType testType, DepthProperty depthProperty, deUint32 outputBinding, deUint32 formatIndex)
993 {
994 map<string, string> source;
995
996 const FormatDataForShaders& formatData = optypeimageFormatMismatchSpirvData[formatIndex];
997 const std::string imageReadOp = getImageReadOpStr(readOp, formatData);
998 const std::string imageSamplerTypes = getImageSamplerTypeStr(descriptorType, readOp, depthProperty, testType, formatData);
999 const std::string functionParamTypes = getFunctionParamTypeStr(testType);
1000 const std::string functionSrcVariables = getFunctionSrcVariableStr(readOp, descriptorType, testType);
1001 const std::string functionDstVariables = getFunctionDstVariableStr(readOp, descriptorType, testType);
1002 const std::string functionSrcParams = getFunctionSrcParamStr(testType);
1003 const std::string functionDstParams = getFunctionDstParamStr(readOp, testType);
1004 const std::string samplerDecoration = getSamplerDecoration(descriptorType);
1005 const std::string outputUniformPtr = isImageSampleDrefReadOp(readOp) ? "%_ptr_Uniform_type" : "%_ptr_Uniform_v4type";
1006 const std::string outputArrayStruct = isImageSampleDrefReadOp(readOp) ? "%_arr_type_u32_64" : "%_arr_v4type_u32_64";
1007
1008 source["pre_main"] =
1009 " %c_u32_64 = OpConstant %u32 64\n"
1010 " %c_i32_64 = OpConstant %i32 64\n"
1011 " %c_i32_8 = OpConstant %i32 8\n"
1012 " %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
1013
1014 " %_arr_type_u32_64 = OpTypeArray " + formatData.m_spirvType + " %c_u32_64\n"
1015 " %_arr_v4type_u32_64 = OpTypeArray " + formatData.m_spirvVectorType + " %c_u32_64\n"
1016 " %_ptr_Uniform_type = OpTypePointer Uniform " + formatData.m_spirvType + "\n"
1017 "%_ptr_Uniform_v4type = OpTypePointer Uniform " + formatData.m_spirvVectorType + "\n"
1018
1019 " %Output = OpTypeStruct " + outputArrayStruct + "\n"
1020 "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
1021 " %OutputData = OpVariable %_ptr_Uniform_Output Uniform\n"
1022
1023 + imageSamplerTypes +
1024
1025 " %read_func_type = OpTypeFunction %void %i32" + functionParamTypes + "\n";
1026
1027 source["decoration"] =
1028 " OpDecorate %_arr_type_u32_64 ArrayStride 4\n"
1029 " OpDecorate %_arr_v4type_u32_64 ArrayStride 16\n"
1030 " OpMemberDecorate %Output 0 Offset 0\n"
1031 " OpDecorate %Output BufferBlock\n"
1032 " OpDecorate %InputData DescriptorSet 0\n"
1033 " OpDecorate %InputData Binding 0\n"
1034
1035 + samplerDecoration +
1036
1037 "OpDecorate %OutputData DescriptorSet 0\n"
1038 "OpDecorate %OutputData Binding " + de::toString(outputBinding) + "\n";
1039
1040 source["testfun"] =
1041 " %read_func = OpFunction %void None %read_func_type\n"
1042 " %func_ndx = OpFunctionParameter %i32\n"
1043
1044 + functionDstParams +
1045
1046 " %funcentry = OpLabel\n"
1047
1048 " %row = OpSRem %i32 %func_ndx %c_i32_8\n"
1049 " %col = OpSDiv %i32 %func_ndx %c_i32_8\n"
1050 " %coord = OpCompositeConstruct %v2i32 %row %col\n"
1051 " %coordf = OpConvertSToF %v2f32 %coord\n"
1052 " %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
1053
1054 + functionDstVariables +
1055
1056 " %color = " + imageReadOp + "\n"
1057 " %36 = OpAccessChain " + outputUniformPtr + " %OutputData %c_i32_0 %func_ndx\n"
1058 " OpStore %36 %color\n"
1059
1060 " OpReturn\n"
1061 " OpFunctionEnd\n"
1062
1063 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1064 " %param = OpFunctionParameter %v4f32\n"
1065
1066 " %entry = OpLabel\n"
1067
1068 " %i = OpVariable %fp_i32 Function\n"
1069 " OpStore %i %c_i32_0\n"
1070 " OpBranch %loop\n"
1071
1072 " %loop = OpLabel\n"
1073 " %15 = OpLoad %i32 %i\n"
1074 " %lt = OpSLessThan %bool %15 %c_i32_64\n"
1075 " OpLoopMerge %merge %inc None\n"
1076 " OpBranchConditional %lt %write %merge\n"
1077
1078 " %write = OpLabel\n"
1079 " %index = OpLoad %i32 %i\n"
1080
1081 + functionSrcVariables +
1082
1083 " %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
1084 " OpBranch %inc\n"
1085
1086 " %inc = OpLabel\n"
1087
1088 " %37 = OpLoad %i32 %i\n"
1089 " %39 = OpIAdd %i32 %37 %c_i32_1\n"
1090 " OpStore %i %39\n"
1091 " OpBranch %loop\n"
1092
1093 " %merge = OpLabel\n"
1094 " OpReturnValue %param\n"
1095 " OpFunctionEnd\n";
1096
1097 return source;
1098 }
1099
verifyDepthCompareResult(const std::vector<Resource> & originalFloats,const std::vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog &)1100 bool verifyDepthCompareResult (const std::vector<Resource>& originalFloats,
1101 const std::vector<AllocationSp>& outputAllocs,
1102 const std::vector<Resource>& expectedOutputs,
1103 tcu::TestLog&)
1104 {
1105 DE_UNREF(originalFloats);
1106
1107 if (outputAllocs.size() != expectedOutputs.size())
1108 return false;
1109
1110 vector<deUint8> expectedBytes;
1111 expectedOutputs[0].getBytes(expectedBytes);
1112
1113 const float* returnedAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());
1114 const float* expectedAsFloat = reinterpret_cast<const float*>(&expectedBytes.front());
1115
1116 for (deUint32 elementNdx = 0; elementNdx < static_cast<deUint32>(expectedBytes.size() / sizeof(float)); ++elementNdx)
1117 {
1118 const float input = expectedAsFloat[elementNdx];
1119 const float result = returnedAsFloat[elementNdx];
1120
1121 // VK_COMPARE_OP_LESS: D = 1.0 if D < Dref, otherwise D = 0.0
1122 if ((input < 0.5f && result != 0.0f) || (input >= 0.5f && result != 1.0f))
1123 return false;
1124 }
1125
1126 return true;
1127 }
1128
addGraphicsImageSamplerTest(tcu::TestCaseGroup * group)1129 void addGraphicsImageSamplerTest (tcu::TestCaseGroup* group)
1130 {
1131 tcu::TestContext& testCtx = group->getTestContext();
1132
1133 de::Random rnd (deStringHash(group->getName()));
1134 const deUint32 numDataPoints = 64;
1135 RGBA defaultColors[4];
1136
1137 SpecConstants noSpecConstants;
1138 PushConstants noPushConstants;
1139 GraphicsInterfaces noInterfaces;
1140 std::vector<std::string> noExtensions;
1141 VulkanFeatures vulkanFeatures = VulkanFeatures();
1142
1143 vector<tcu::Vec4> inputDataBase (numDataPoints);
1144 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
1145 inputDataBase[numIdx] = tcu::randomVec4(rnd);
1146 // Depth only has 1 component
1147 vector<tcu::Vec4> inputDataBaseDepth = inputDataBase;
1148 inputDataBaseDepth.resize(numDataPoints / 4);
1149
1150 for (deUint32 opNdx = 0u; opNdx < READOP_LAST; opNdx++)
1151 {
1152 de::MovePtr<tcu::TestCaseGroup> readOpGroup (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx)));
1153
1154 const VkFormat imageFormat = getImageFormat((ReadOp)opNdx);
1155 const bool hasDepthComponent = tcu::hasDepthComponent(vk::mapVkFormat(imageFormat).order);
1156
1157 for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
1158 {
1159 de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx)));
1160
1161 for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
1162 {
1163 if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
1164 continue;
1165
1166 deUint32 formatCount = 1;
1167 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1168 formatCount = optypeimageFormatMismatchFormatCount;
1169
1170 // this group is only used for optypeimage_mismatch case
1171 de::MovePtr<tcu::TestCaseGroup> testtypeGroup(new tcu::TestCaseGroup(testCtx, getTestTypeName((TestType)testNdx)));
1172
1173 for (deUint32 formatIndex = 0; formatIndex < formatCount; formatIndex++)
1174 {
1175 const FormatDataForShaders& formatData = optypeimageFormatMismatchSpirvData[formatIndex];
1176
1177 // optypeimage_mismatch uses an additional level of test hierarchy
1178 const char* groupname = (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH) ? formatData.m_name.c_str() : getTestTypeName((TestType)testNdx);
1179 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, groupname));
1180 vector<Vec4>& inputData = hasDepthComponent && testNdx != TESTTYPE_OPTYPEIMAGE_MISMATCH ? inputDataBaseDepth : inputDataBase;
1181 GraphicsResources resources;
1182
1183 resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1184
1185 // Separate sampler for sampled images
1186 if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1187 {
1188 vector<tcu::Vec4> unusedData;
1189 resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData)), VK_DESCRIPTOR_TYPE_SAMPLER));
1190 }
1191
1192 // Second combined image sampler with different image data
1193 if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
1194 {
1195 for (size_t i = 0; i < inputData.size(); i++)
1196 inputData[i] = tcu::Vec4(1.0f) - inputData[i];
1197
1198 resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1199 }
1200
1201 // Shader is expected to pass the input image data to output buffer
1202 resources.outputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1203
1204 getDefaultColors(defaultColors);
1205
1206 // If testing for mismatched optypeimage, ignore the rendered
1207 // result (we're only interested to see if we crash)
1208 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1209 {
1210 resources.verifyIO = nopVerifyFunction;
1211 resources.inputFormat = formatData.m_format;
1212 }
1213 else if (hasDepthComponent)
1214 {
1215 resources.verifyIO = verifyDepthCompareResult;
1216 resources.inputFormat = getImageFormat((ReadOp)opNdx);
1217 }
1218
1219 de::MovePtr<tcu::TestCaseGroup> depthGroup (new tcu::TestCaseGroup(testCtx, "depth_property"));
1220 for (deUint32 propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++)
1221 {
1222 de::MovePtr<tcu::TestCaseGroup> depthPropertyGroup (new tcu::TestCaseGroup(testCtx, getDepthPropertyName((DepthProperty)propertyNdx)));
1223 const map<string, string> fragments = generateGraphicsImageSamplerSource((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx, (DepthProperty)propertyNdx, (deUint32)resources.inputs.size(), formatIndex);
1224
1225 // READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD and READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD can only be present in fragment/compute
1226 if (opNdx <= READOP_IMAGESAMPLE)
1227 {
1228 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
1229 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
1230 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, "shader_vert", defaultColors, defaultColors, fragments, noSpecConstants,
1231 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
1232
1233 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "shader_tessc", defaultColors, defaultColors, fragments, noSpecConstants,
1234 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
1235
1236 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "shader_tesse", defaultColors, defaultColors, fragments, noSpecConstants,
1237 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
1238
1239 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, "shader_geom", defaultColors, defaultColors, fragments, noSpecConstants,
1240 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
1241 }
1242
1243 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
1244 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
1245 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors, fragments, noSpecConstants,
1246 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, depthPropertyGroup.get());
1247
1248 depthGroup->addChild(depthPropertyGroup.release());
1249 }
1250 typeGroup->addChild(depthGroup.release());
1251
1252 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1253 testtypeGroup->addChild(typeGroup.release());
1254 else
1255 descGroup->addChild(typeGroup.release());
1256 }
1257 if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1258 descGroup->addChild(testtypeGroup.release());
1259 }
1260 readOpGroup->addChild(descGroup.release());
1261 }
1262 group->addChild(readOpGroup.release());
1263 }
1264 }
1265 } // anonymous
1266
createImageSamplerComputeGroup(tcu::TestContext & testCtx)1267 tcu::TestCaseGroup* createImageSamplerComputeGroup (tcu::TestContext& testCtx)
1268 {
1269 // Compute tests for combining images and samplers.
1270 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "image_sampler"));
1271 addComputeImageSamplerTest(group.get());
1272
1273 return group.release();
1274 }
1275
createImageSamplerGraphicsGroup(tcu::TestContext & testCtx)1276 tcu::TestCaseGroup* createImageSamplerGraphicsGroup (tcu::TestContext& testCtx)
1277 {
1278 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "image_sampler", "Graphics tests for combining images and samplers."));
1279
1280 addGraphicsImageSamplerTest(group.get());
1281
1282 return group.release();
1283 }
1284
1285 } // SpirVAssembly
1286 } // vkt
1287