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