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