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