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 
isValidTestCase(TestType testType,DescriptorType descriptorType,ReadOp readOp)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 
getTestTypeName(TestType testType)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 
getReadOpName(ReadOp readOp)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 
getDescriptorName(DescriptorType descType)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 
getDepthPropertyName(DepthProperty depthProperty)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 
getVkDescriptorType(DescriptorType descType)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 
getImageFormat(ReadOp readOp)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
getFunctionDstVariableStr(ReadOp readOp,DescriptorType descType,TestType testType)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
getFunctionSrcVariableStr(ReadOp readOp,DescriptorType descType,TestType testType)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
getFunctionParamTypeStr(TestType testType)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
getFunctionSrcParamStr(TestType testType)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
getFunctionDstParamStr(ReadOp readOp,TestType testType)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
getImageReadOpStr(ReadOp readOp)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 
isImageSampleDrefReadOp(ReadOp readOp)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
getImageSamplerTypeStr(DescriptorType descType,ReadOp readOp,deUint32 depthProperty,TestType testType,int formatIndex)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 
getSamplerDecoration(DescriptorType descType)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)
nopVerifyFunction(const std::vector<Resource> &,const std::vector<AllocationSp> &,const std::vector<Resource> &,tcu::TestLog &)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 
addComputeImageSamplerTest(tcu::TestCaseGroup * group)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 
generateGraphicsImageSamplerSource(ReadOp readOp,DescriptorType descriptorType,TestType testType,DepthProperty depthProperty,deUint32 outputBinding,deUint32 formatIndex)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 
addGraphicsImageSamplerTest(tcu::TestCaseGroup * group)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(), (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 
verifyDepthCompareResult(const std::vector<Resource> & originalFloats,const std::vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog &)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 
addGraphicsDepthPropertyTest(tcu::TestCaseGroup * group)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 
createImageSamplerComputeGroup(tcu::TestContext & testCtx)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 
createImageSamplerGraphicsGroup(tcu::TestContext & testCtx)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
1292