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