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