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