• 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,bool useNontemporal=false)576 std::string getImageReadOpStr (ReadOp readOp, bool useNontemporal = false)
577 {
578 	std::string imageOperand = useNontemporal ? " Nontemporal" : "";
579 
580 	switch (readOp)
581 	{
582 		case READOP_IMAGEREAD:
583 			return std::string("OpImageRead %v4f32 %func_img %coord") + imageOperand;
584 
585 		case READOP_IMAGEFETCH:
586 			return std::string("OpImageFetch %v4f32 %func_img %coord") + imageOperand;
587 
588 		case READOP_IMAGESAMPLE:
589 			if (useNontemporal)
590 				return "OpImageSampleExplicitLod %v4f32 %func_smi %normalcoordf Lod|Nontemporal %c_f32_0";
591 			return "OpImageSampleExplicitLod %v4f32 %func_smi %normalcoordf Lod %c_f32_0";
592 
593 		case READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD:
594 			return "OpImageSampleDrefImplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Bias %c_f32_0";
595 
596 		case READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD:
597 			return "OpImageSampleDrefExplicitLod %f32 %func_smi %normalcoordf %c_f32_0_5 Lod %c_f32_0";
598 
599 		default:
600 			DE_FATAL("Unknown readop");
601 			return "";
602 	}
603 }
604 
isImageSampleDrefReadOp(ReadOp readOp)605 bool isImageSampleDrefReadOp (ReadOp readOp)
606 {
607 	return (readOp == READOP_IMAGESAMPLE_DREF_IMPLICIT_LOD) || (readOp == READOP_IMAGESAMPLE_DREF_EXPLICIT_LOD);
608 }
609 
610 static const VkFormat optypeimageFormatMismatchVkFormat[] =
611 {
612 	VK_FORMAT_R8G8B8A8_UNORM,
613 	VK_FORMAT_R8G8B8A8_SNORM,
614 	VK_FORMAT_R8G8B8A8_UINT,
615 	VK_FORMAT_R8G8B8A8_SINT,
616 	VK_FORMAT_R16G16B16A16_UINT,
617 	VK_FORMAT_R16G16B16A16_SINT,
618 	VK_FORMAT_R16G16B16A16_SFLOAT,
619 	VK_FORMAT_R32_UINT,
620 	VK_FORMAT_R32_SINT,
621 	VK_FORMAT_R32G32B32A32_UINT,
622 	VK_FORMAT_R32G32B32A32_SINT,
623 	VK_FORMAT_R32G32B32A32_SFLOAT
624 };
625 
626 static const size_t optypeimageFormatMismatchFormatCount = sizeof(optypeimageFormatMismatchVkFormat) / sizeof(VkFormat);
627 
628 static const char *optypeimageFormatMismatchSpirvFormat[] =
629 {
630 	"Rgba8",
631 	"Rgba8Snorm",
632 	"Rgba8ui",
633 	"Rgba8i",
634 	"Rgba16ui",
635 	"Rgba16i",
636 	"Rgba16f",
637 	"R32ui",
638 	"R32i",
639 	"Rgba32ui",
640 	"Rgba32i",
641 	"Rgba32f"
642 };
643 
644 static const char *optypeimageFormatMismatchCase[] =
645 {
646 	"rgba8",
647 	"rgba8snorm",
648 	"rgba8ui",
649 	"rgba8i",
650 	"rgba16ui",
651 	"rgba16i",
652 	"rgba16f",
653 	"r32ui",
654 	"r32i",
655 	"rgba32ui",
656 	"rgba32i",
657 	"rgba32f"
658 };
659 
660 // Get types and pointers for input images and samplers
getImageSamplerTypeStr(DescriptorType descType,ReadOp readOp,deUint32 depthProperty,TestType testType,int formatIndex)661 std::string getImageSamplerTypeStr (DescriptorType descType, ReadOp readOp, deUint32 depthProperty, TestType testType, int formatIndex)
662 {
663 	const string imageFormat =	(testType == TESTTYPE_OPTYPEIMAGE_MISMATCH) ? optypeimageFormatMismatchSpirvFormat[formatIndex] :
664 								isImageSampleDrefReadOp(readOp) ? "R32f" : "Rgba32f";
665 
666 	switch (descType)
667 	{
668 		case DESCRIPTOR_TYPE_STORAGE_IMAGE:
669 			return	"              %Image = OpTypeImage %f32 2D " + de::toString(depthProperty) + " 0 0 2 " + imageFormat + "\n"
670 					"           %ImagePtr = OpTypePointer UniformConstant %Image\n"
671 					"          %InputData = OpVariable %ImagePtr UniformConstant\n";
672 
673 		case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
674 			return	"              %Image = OpTypeImage %f32 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
675 					"           %ImagePtr = OpTypePointer UniformConstant %Image\n"
676 					"          %InputData = OpVariable %ImagePtr UniformConstant\n"
677 
678 					"            %Sampler = OpTypeSampler\n"
679 					"         %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
680 					"        %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
681 					"       %SampledImage = OpTypeSampledImage %Image\n";
682 
683 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
684 			return	"              %Image = OpTypeImage %f32 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
685 					"       %SampledImage = OpTypeSampledImage %Image\n"
686 					"         %SamplerPtr = OpTypePointer UniformConstant %SampledImage\n"
687 					"          %InputData = OpVariable %SamplerPtr UniformConstant\n";
688 
689 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
690 			return	"              %Image = OpTypeImage %f32 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
691 					"           %ImagePtr = OpTypePointer UniformConstant %Image\n"
692 					"          %InputData = OpVariable %ImagePtr UniformConstant\n"
693 
694 					"            %Sampler = OpTypeSampler\n"
695 					"         %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
696 					"        %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
697 					"       %SampledImage = OpTypeSampledImage %Image\n";
698 
699 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
700 			return	"              %Image = OpTypeImage %f32 2D " + de::toString(depthProperty) + " 0 0 1 " + imageFormat + "\n"
701 					"           %ImagePtr = OpTypePointer UniformConstant %Image\n"
702 					"          %InputData = OpVariable %ImagePtr UniformConstant\n"
703 					"         %InputData2 = OpVariable %ImagePtr UniformConstant\n"
704 
705 					"            %Sampler = OpTypeSampler\n"
706 					"         %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
707 					"        %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
708 					"       %SamplerData2 = OpVariable %SamplerPtr UniformConstant\n"
709 					"       %SampledImage = OpTypeSampledImage %Image\n";
710 
711 		default:
712 			DE_FATAL("Unknown descriptor type");
713 			return "";
714 	}
715 }
716 
getInterfaceList(DescriptorType descType)717 std::string getInterfaceList (DescriptorType descType)
718 {
719 	std::string list = " %InputData %OutputData";
720 	switch (descType)
721 	{
722 		case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
723 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
724 			list += " %SamplerData";
725 			break;
726 
727 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
728 			list += " %SamplerData %InputData2 %SamplerData2";
729 			break;
730 
731 		default:
732 			break;
733 	}
734 
735 	return list;
736 }
737 
getSamplerDecoration(DescriptorType descType)738 std::string getSamplerDecoration (DescriptorType descType)
739 {
740 	switch (descType)
741 	{
742 		// Separate image and sampler
743 		case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
744 			return	"                       OpDecorate %SamplerData DescriptorSet 0\n"
745 					"                       OpDecorate %SamplerData Binding 1\n";
746 
747 		// Combined image sampler with separate variables
748 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_VARIABLES:
749 			return	"                       OpDecorate %SamplerData DescriptorSet 0\n"
750 					"                       OpDecorate %SamplerData Binding 0\n";
751 
752 		// Two combined image samplers with separate variables
753 		case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS:
754 			return	"                       OpDecorate %SamplerData DescriptorSet 0\n"
755 					"                       OpDecorate %SamplerData Binding 0\n"
756 					"                       OpDecorate %InputData2 DescriptorSet 0\n"
757 					"                       OpDecorate %InputData2 Binding 1\n"
758 					"                       OpDecorate %SamplerData2 DescriptorSet 0\n"
759 					"                       OpDecorate %SamplerData2 Binding 1\n";
760 
761 		default:
762 			return "";
763 	}
764 }
765 
766 // 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 &)767 bool nopVerifyFunction (const std::vector<Resource>&,
768 						const std::vector<AllocationSp>&,
769 						const std::vector<Resource>&,
770 						tcu::TestLog&)
771 {
772 	return true;
773 }
774 
addComputeImageSamplerTest(tcu::TestCaseGroup * group)775 void addComputeImageSamplerTest (tcu::TestCaseGroup* group)
776 {
777 	tcu::TestContext& testCtx = group->getTestContext();
778 
779 	de::Random				rnd					(deStringHash(group->getName()));
780 	const deUint32			numDataPoints		= 64;
781 	RGBA					defaultColors[4];
782 	vector<tcu::Vec4>		inputData;
783 
784 	inputData.reserve(numDataPoints);
785 
786 	for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
787 		inputData.push_back(tcu::randomVec4(rnd));
788 
789 	struct SpirvData
790 	{
791 		SpirvVersion	version;
792 		std::string		postfix;
793 	};
794 	const std::vector<SpirvData> spirvDataVect
795 	{
796 		{ SPIRV_VERSION_1_0, "" },
797 		{ SPIRV_VERSION_1_6, "_nontemporal" },
798 	};
799 
800 	for (deUint32 opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++)
801 	{
802 		de::MovePtr<tcu::TestCaseGroup> readOpGroup	(new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), ""));
803 
804 		for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
805 		{
806 			de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), ""));
807 
808 			for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
809 			{
810 				if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
811 					continue;
812 
813 				deUint32 numFormats = 1;
814 				if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
815 					numFormats = optypeimageFormatMismatchFormatCount;
816 
817 				for (deUint32 formatIndex = 0; formatIndex < numFormats; formatIndex++)
818 				{
819 					const std::string	imageSamplerTypes = getImageSamplerTypeStr((DescriptorType)descNdx, (ReadOp)opNdx, DEPTH_PROPERTY_NON_DEPTH, (TestType)testNdx, formatIndex);
820 					const std::string	functionParamTypes = getFunctionParamTypeStr((TestType)testNdx);
821 
822 					const std::string	functionSrcVariables = getFunctionSrcVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
823 					const std::string	functionDstVariables = getFunctionDstVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
824 
825 					const std::string	functionSrcParams = getFunctionSrcParamStr((TestType)testNdx);
826 					const std::string	functionDstParams = getFunctionDstParamStr((ReadOp)opNdx, (TestType)testNdx);
827 
828 					getDefaultColors(defaultColors);
829 
830 					ComputeShaderSpec	spec;
831 
832 					spec.numWorkGroups = IVec3(numDataPoints, 1, 1);
833 
834 					spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
835 
836 					// Separate sampler for sampled images
837 					if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
838 					{
839 						vector<tcu::Vec4> unusedData;
840 						spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData))));
841 						spec.inputs[1].setDescriptorType(VK_DESCRIPTOR_TYPE_SAMPLER);
842 					}
843 
844 					// Second combined image sampler with different image data
845 					if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
846 					{
847 						for (size_t i = 0; i < inputData.size(); i++)
848 							inputData[i] = tcu::Vec4(1.0f) - inputData[i];
849 
850 						spec.inputs.push_back(BufferSp(new Vec4Buffer(inputData)));
851 						spec.inputs[1].setDescriptorType(getVkDescriptorType((DescriptorType)descNdx));
852 					}
853 
854 					// Shader is expected to pass the input image data to the output buffer
855 					spec.outputs.push_back(BufferSp(new Vec4Buffer(inputData)));
856 
857 					const std::string	samplerDecoration	= getSamplerDecoration((DescriptorType)descNdx);
858 
859 					for (auto spirvData : spirvDataVect)
860 					{
861 						spec.spirvVersion = spirvData.version;
862 
863 						bool		useSpirV16			(spirvData.version == SPIRV_VERSION_1_6);
864 						std::string	interfaceList		("");
865 						std::string	outputDecoration	("BufferBlock");
866 						std::string	outputType			("Uniform");
867 						std::string	imageReadOp			(getImageReadOpStr((ReadOp)opNdx, useSpirV16));
868 
869 						// adjust shader code to spv16
870 						if (useSpirV16)
871 						{
872 							interfaceList		= getInterfaceList((DescriptorType)descNdx);
873 							outputDecoration	= "Block";
874 							outputType			= "StorageBuffer";
875 						}
876 
877 						const string shaderSource =
878 							"                       OpCapability Shader\n"
879 							"                  %1 = OpExtInstImport \"GLSL.std.450\"\n"
880 							"                       OpMemoryModel Logical GLSL450\n"
881 							"                       OpEntryPoint GLCompute %main \"main\" %id" + interfaceList + "\n"
882 							"                       OpExecutionMode %main LocalSize 1 1 1\n"
883 							"                       OpSource GLSL 430\n"
884 							"                       OpDecorate %id BuiltIn GlobalInvocationId\n"
885 							"                       OpDecorate %_arr_v4f_u32_64 ArrayStride 16\n"
886 							"                       OpMemberDecorate %Output 0 Offset 0\n"
887 							"                       OpDecorate %Output " + outputDecoration + "\n"
888 							"                       OpDecorate %InputData DescriptorSet 0\n"
889 							"                       OpDecorate %InputData Binding 0\n"
890 
891 							+ samplerDecoration +
892 
893 							"                       OpDecorate %OutputData DescriptorSet 0\n"
894 							"                       OpDecorate %OutputData Binding " + de::toString(spec.inputs.size()) + "\n"
895 
896 							"               %void = OpTypeVoid\n"
897 							"                  %3 = OpTypeFunction %void\n"
898 							"                %u32 = OpTypeInt 32 0\n"
899 							"                %i32 = OpTypeInt 32 1\n"
900 							"                %f32 = OpTypeFloat 32\n"
901 							" %_ptr_Function_uint = OpTypePointer Function %u32\n"
902 							"              %v3u32 = OpTypeVector %u32 3\n"
903 							"   %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
904 							"                 %id = OpVariable %_ptr_Input_v3u32 Input\n"
905 							"            %c_f32_0 = OpConstant %f32 0.0\n"
906 							"            %c_u32_0 = OpConstant %u32 0\n"
907 							"            %c_i32_0 = OpConstant %i32 0\n"
908 							"    %_ptr_Input_uint = OpTypePointer Input %u32\n"
909 							"              %v2u32 = OpTypeVector %u32 2\n"
910 							"              %v2f32 = OpTypeVector %f32 2\n"
911 							"              %v4f32 = OpTypeVector %f32 4\n"
912 							"           %uint_128 = OpConstant %u32 128\n"
913 							"           %c_u32_64 = OpConstant %u32 64\n"
914 							"            %c_u32_8 = OpConstant %u32 8\n"
915 							"            %c_f32_8 = OpConstant %f32 8.0\n"
916 							"        %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
917 							"    %_arr_v4f_u32_64 = OpTypeArray %v4f32 %c_u32_64\n"
918 							"   %_ptr_Uniform_v4f = OpTypePointer " + outputType + " %v4f32\n"
919 							"             %Output = OpTypeStruct %_arr_v4f_u32_64\n"
920 							"%_ptr_Uniform_Output = OpTypePointer " + outputType + " %Output\n"
921 							"         %OutputData = OpVariable %_ptr_Uniform_Output " + outputType + "\n"
922 
923 							+ imageSamplerTypes +
924 
925 							"     %read_func_type = OpTypeFunction %void %u32" + functionParamTypes + "\n"
926 
927 							"          %read_func = OpFunction %void None %read_func_type\n"
928 							"           %func_ndx = OpFunctionParameter %u32\n"
929 
930 							+ functionDstParams +
931 
932 							"          %funcentry = OpLabel\n"
933 							"                %row = OpUMod %u32 %func_ndx %c_u32_8\n"
934 							"                %col = OpUDiv %u32 %func_ndx %c_u32_8\n"
935 							"              %coord = OpCompositeConstruct %v2u32 %row %col\n"
936 							"             %coordf = OpConvertUToF %v2f32 %coord\n"
937 							"       %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
938 
939 							+ functionDstVariables +
940 
941 							"              %color = " + imageReadOp + "\n"
942 							"                 %36 = OpAccessChain %_ptr_Uniform_v4f %OutputData %c_u32_0 %func_ndx\n"
943 							"                       OpStore %36 %color\n"
944 							"                       OpReturn\n"
945 							"                       OpFunctionEnd\n"
946 
947 							"               %main = OpFunction %void None %3\n"
948 							"                  %5 = OpLabel\n"
949 							"                  %i = OpVariable %_ptr_Function_uint Function\n"
950 							"                 %14 = OpAccessChain %_ptr_Input_uint %id %c_u32_0\n"
951 							"                 %15 = OpLoad %u32 %14\n"
952 							"                       OpStore %i %15\n"
953 							"              %index = OpLoad %u32 %14\n"
954 
955 							+ functionSrcVariables +
956 
957 							"                %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
958 							"                       OpReturn\n"
959 							"                       OpFunctionEnd\n";
960 
961 						spec.assembly = shaderSource;
962 
963 						string testname = getTestTypeName((TestType)testNdx);
964 
965 						if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
966 						{
967 							// If testing for mismatched optypeimage, ignore the
968 							// result (we're only interested to see if we crash)
969 							spec.verifyIO = nopVerifyFunction;
970 
971 							testname = testname + string("_") + string(optypeimageFormatMismatchCase[formatIndex]);
972 						}
973 
974 						testname += spirvData.postfix;
975 						descGroup->addChild(new SpvAsmComputeShaderCase(testCtx, testname.c_str(), "", spec));
976 					}
977 				}
978 			}
979 			readOpGroup->addChild(descGroup.release());
980 		}
981 		group->addChild(readOpGroup.release());
982 	}
983 }
984 
generateGraphicsImageSamplerSource(ReadOp readOp,DescriptorType descriptorType,TestType testType,DepthProperty depthProperty,deUint32 outputBinding,deUint32 formatIndex)985 map<string, string> generateGraphicsImageSamplerSource (ReadOp readOp, DescriptorType descriptorType, TestType testType, DepthProperty depthProperty, deUint32 outputBinding, deUint32 formatIndex)
986 {
987 	map<string, string>	source;
988 
989 	const std::string	imageReadOp				= getImageReadOpStr(readOp);
990 	const std::string	imageSamplerTypes		= getImageSamplerTypeStr(descriptorType, readOp, depthProperty, testType, formatIndex);
991 	const std::string	functionParamTypes		= getFunctionParamTypeStr(testType);
992 	const std::string	functionSrcVariables	= getFunctionSrcVariableStr(readOp, descriptorType, testType);
993 	const std::string	functionDstVariables	= getFunctionDstVariableStr(readOp, descriptorType, testType);
994 	const std::string	functionSrcParams		= getFunctionSrcParamStr(testType);
995 	const std::string	functionDstParams		= getFunctionDstParamStr(readOp, testType);
996 	const std::string	samplerDecoration		= getSamplerDecoration(descriptorType);
997 	const std::string	outputUniformPtr		= isImageSampleDrefReadOp(readOp) ? "%_ptr_Uniform_f32" : "%_ptr_Uniform_v4f32";
998 	const std::string	outputArrayStruct		= isImageSampleDrefReadOp(readOp) ? "%_arr_f32_u32_64" : "%_arr_v4f32_u32_64";
999 
1000 	source["pre_main"]	=
1001 		"           %c_u32_64 = OpConstant %u32 64\n"
1002 		"           %c_i32_64 = OpConstant %i32 64\n"
1003 		"            %c_i32_8 = OpConstant %i32 8\n"
1004 		"        %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
1005 
1006 		"    %_arr_f32_u32_64 = OpTypeArray %f32 %c_u32_64\n"
1007 		"  %_arr_v4f32_u32_64 = OpTypeArray %v4f32 %c_u32_64\n"
1008 		"   %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
1009 		" %_ptr_Uniform_v4f32 = OpTypePointer Uniform %v4f32\n"
1010 
1011 		"             %Output = OpTypeStruct " + outputArrayStruct + "\n"
1012 		"%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
1013 		"         %OutputData = OpVariable %_ptr_Uniform_Output Uniform\n"
1014 
1015 		+ imageSamplerTypes +
1016 
1017 		"     %read_func_type = OpTypeFunction %void %i32" + functionParamTypes + "\n";
1018 
1019 	source["decoration"]	=
1020 		"                       OpDecorate %_arr_f32_u32_64 ArrayStride 4\n"
1021 		"                       OpDecorate %_arr_v4f32_u32_64 ArrayStride 16\n"
1022 		"                       OpMemberDecorate %Output 0 Offset 0\n"
1023 		"                       OpDecorate %Output BufferBlock\n"
1024 		"                       OpDecorate %InputData DescriptorSet 0\n"
1025 		"                       OpDecorate %InputData Binding 0\n"
1026 
1027 		+ samplerDecoration +
1028 
1029 		"OpDecorate %OutputData DescriptorSet 0\n"
1030 		"OpDecorate %OutputData Binding " + de::toString(outputBinding) + "\n";
1031 
1032 	source["testfun"]	=
1033 		"          %read_func = OpFunction %void None %read_func_type\n"
1034 		"           %func_ndx = OpFunctionParameter %i32\n"
1035 
1036 		+ functionDstParams +
1037 
1038 		"          %funcentry = OpLabel\n"
1039 
1040 		"                %row = OpSRem %i32 %func_ndx %c_i32_8\n"
1041 		"                %col = OpSDiv %i32 %func_ndx %c_i32_8\n"
1042 		"              %coord = OpCompositeConstruct %v2i32 %row %col\n"
1043 		"             %coordf = OpConvertSToF %v2f32 %coord\n"
1044 		"       %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
1045 
1046 		+ functionDstVariables +
1047 
1048 		"              %color = " + imageReadOp + "\n"
1049 		"                 %36 = OpAccessChain " + outputUniformPtr + " %OutputData %c_i32_0 %func_ndx\n"
1050 		"                       OpStore %36 %color\n"
1051 
1052 		"                       OpReturn\n"
1053 		"                       OpFunctionEnd\n"
1054 
1055 		"          %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1056 		"              %param = OpFunctionParameter %v4f32\n"
1057 
1058 		"              %entry = OpLabel\n"
1059 
1060 		"                  %i = OpVariable %fp_i32 Function\n"
1061 		"                       OpStore %i %c_i32_0\n"
1062 		"                       OpBranch %loop\n"
1063 
1064 		"               %loop = OpLabel\n"
1065 		"                 %15 = OpLoad %i32 %i\n"
1066 		"                 %lt = OpSLessThan %bool %15 %c_i32_64\n"
1067 		"                       OpLoopMerge %merge %inc None\n"
1068 		"                       OpBranchConditional %lt %write %merge\n"
1069 
1070 		"              %write = OpLabel\n"
1071 		"              %index = OpLoad %i32 %i\n"
1072 
1073 		+ functionSrcVariables +
1074 
1075 		"                %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
1076 		"                       OpBranch %inc\n"
1077 
1078 		"                %inc = OpLabel\n"
1079 
1080 		"                 %37 = OpLoad %i32 %i\n"
1081 		"                 %39 = OpIAdd %i32 %37 %c_i32_1\n"
1082 		"                       OpStore %i %39\n"
1083 		"                       OpBranch %loop\n"
1084 
1085 		"              %merge = OpLabel\n"
1086 		"                       OpReturnValue %param\n"
1087 		"                       OpFunctionEnd\n";
1088 
1089 	return source;
1090 }
1091 
addGraphicsImageSamplerTest(tcu::TestCaseGroup * group)1092 void addGraphicsImageSamplerTest (tcu::TestCaseGroup* group)
1093 {
1094 	tcu::TestContext&			testCtx				= group->getTestContext();
1095 
1096 	de::Random					rnd					(deStringHash(group->getName()));
1097 	const deUint32				numDataPoints		= 64;
1098 	RGBA						defaultColors[4];
1099 
1100 	SpecConstants				noSpecConstants;
1101 	PushConstants				noPushConstants;
1102 	GraphicsInterfaces			noInterfaces;
1103 	std::vector<std::string>	noExtensions;
1104 	VulkanFeatures				vulkanFeatures		= VulkanFeatures();
1105 
1106 	vector<tcu::Vec4> inputData(numDataPoints);
1107 	for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
1108 		inputData[numIdx] = tcu::randomVec4(rnd);
1109 
1110 	for (deUint32 opNdx = 0u; opNdx <= READOP_IMAGESAMPLE; opNdx++)
1111 	{
1112 		de::MovePtr<tcu::TestCaseGroup> readOpGroup	(new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), ""));
1113 
1114 		for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
1115 		{
1116 			de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), ""));
1117 
1118 			for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
1119 			{
1120 				if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
1121 					continue;
1122 
1123 				deUint32 formatCount = 1;
1124 				if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1125 					formatCount = optypeimageFormatMismatchFormatCount;
1126 
1127 				// this group is only used for optypeimage_mismatch case
1128 				de::MovePtr<tcu::TestCaseGroup> testtypeGroup(new tcu::TestCaseGroup(testCtx, getTestTypeName((TestType)testNdx), ""));
1129 
1130 				for (deUint32 formatIndex = 0; formatIndex < formatCount; formatIndex++)
1131 				{
1132 					// optypeimage_mismatch uses an additional level of test hierarchy
1133 					const char *groupname = testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH ? optypeimageFormatMismatchCase[formatIndex] : getTestTypeName((TestType)testNdx);
1134 					de::MovePtr<tcu::TestCaseGroup>	typeGroup(new tcu::TestCaseGroup(testCtx, groupname, ""));
1135 
1136 					GraphicsResources				resources;
1137 
1138 					resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1139 
1140 					// Separate sampler for sampled images
1141 					if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1142 					{
1143 						vector<tcu::Vec4> unusedData;
1144 						resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData)), VK_DESCRIPTOR_TYPE_SAMPLER));
1145 					}
1146 
1147 					// Second combined image sampler with different image data
1148 					if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
1149 					{
1150 						for (size_t i = 0; i < inputData.size(); i++)
1151 							inputData[i] = tcu::Vec4(1.0f) - inputData[i];
1152 
1153 						resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1154 					}
1155 
1156 					// Shader is expected to pass the input image data to output buffer
1157 					resources.outputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1158 
1159 					getDefaultColors(defaultColors);
1160 
1161 					const map<string, string>		fragments = generateGraphicsImageSamplerSource((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx, DEPTH_PROPERTY_NON_DEPTH, (deUint32)resources.inputs.size(), (deUint32)((formatIndex + 1) % optypeimageFormatMismatchFormatCount));
1162 
1163 					// If testing for mismatched optypeimage, ignore the rendered
1164 					// result (we're only interested to see if we crash)
1165 					if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1166 					{
1167 						resources.verifyIO = nopVerifyFunction;
1168 						resources.inputFormat = optypeimageFormatMismatchVkFormat[formatIndex];
1169 					}
1170 
1171 					vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
1172 					vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
1173 					createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, "shader_vert", defaultColors, defaultColors, fragments, noSpecConstants,
1174 						noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get());
1175 
1176 					createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "shader_tessc", defaultColors, defaultColors, fragments, noSpecConstants,
1177 						noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get());
1178 
1179 					createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "shader_tesse", defaultColors, defaultColors, fragments, noSpecConstants,
1180 						noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get());
1181 
1182 					createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, "shader_geom", defaultColors, defaultColors, fragments, noSpecConstants,
1183 						noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get());
1184 
1185 					vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
1186 					vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
1187 					createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors, fragments, noSpecConstants,
1188 						noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, typeGroup.get());
1189 
1190 					if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1191 						testtypeGroup->addChild(typeGroup.release());
1192 					else
1193 						descGroup->addChild(typeGroup.release());
1194 				}
1195 				if (testNdx == TESTTYPE_OPTYPEIMAGE_MISMATCH)
1196 					descGroup->addChild(testtypeGroup.release());
1197 			}
1198 			readOpGroup->addChild(descGroup.release());
1199 		}
1200 		group->addChild(readOpGroup.release());
1201 	}
1202 }
1203 
verifyDepthCompareResult(const std::vector<Resource> & originalFloats,const std::vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog &)1204 bool verifyDepthCompareResult (const std::vector<Resource>&		originalFloats,
1205 							   const std::vector<AllocationSp>&	outputAllocs,
1206 							   const std::vector<Resource>&		expectedOutputs,
1207 							   tcu::TestLog&)
1208 {
1209 	DE_UNREF(originalFloats);
1210 
1211 	if (outputAllocs.size() != expectedOutputs.size())
1212 		return false;
1213 
1214 	vector<deUint8>	expectedBytes;
1215 	expectedOutputs[0].getBytes(expectedBytes);
1216 
1217 	const float*	returnedAsFloat	= static_cast<const float*>(outputAllocs[0]->getHostPtr());
1218 	const float*	expectedAsFloat	= reinterpret_cast<const float*>(&expectedBytes.front());
1219 
1220 	for (deUint32 elementNdx = 0; elementNdx < static_cast<deUint32>(expectedBytes.size() / sizeof(float)); ++elementNdx)
1221 	{
1222 		const float input	= expectedAsFloat[elementNdx];
1223 		const float result	= returnedAsFloat[elementNdx];
1224 
1225 		// VK_COMPARE_OP_LESS: D = 1.0 if D < Dref, otherwise D = 0.0
1226 		if ((input < 0.5f && result != 0.0f) || (input >= 0.5f && result != 1.0f))
1227 			return false;
1228 	}
1229 
1230 	return true;
1231 }
1232 
addGraphicsDepthPropertyTest(tcu::TestCaseGroup * group)1233 void addGraphicsDepthPropertyTest (tcu::TestCaseGroup* group)
1234 {
1235 	tcu::TestContext&			testCtx				= group->getTestContext();
1236 
1237 	de::Random					rnd					(deStringHash(group->getName()));
1238 	const deUint32				numDataPoints		= 64;
1239 	RGBA						defaultColors[4];
1240 	vector<Vec4>				inputDataVec4;
1241 
1242 	SpecConstants				noSpecConstants;
1243 	PushConstants				noPushConstants;
1244 	GraphicsInterfaces			noInterfaces;
1245 	std::vector<std::string>	noExtensions;
1246 	VulkanFeatures				vulkanFeatures		= VulkanFeatures();
1247 
1248 	vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
1249 	vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
1250 
1251 	inputDataVec4.reserve(numDataPoints);
1252 
1253 	for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
1254 		inputDataVec4.push_back(tcu::randomVec4(rnd));
1255 
1256 	de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "depth_property", ""));
1257 
1258 	for (deUint32 propertyNdx = 0u; propertyNdx < DEPTH_PROPERTY_LAST; propertyNdx++)
1259 	{
1260 		de::MovePtr<tcu::TestCaseGroup> depthPropertyGroup (new tcu::TestCaseGroup(testCtx, getDepthPropertyName((DepthProperty)propertyNdx), ""));
1261 
1262 		for (deUint32 opNdx = 0u; opNdx < READOP_LAST; opNdx++)
1263 		{
1264 			de::MovePtr<tcu::TestCaseGroup> readOpGroup	(new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), ""));
1265 
1266 			for (deUint32 descNdx = DESCRIPTOR_TYPE_SAMPLED_IMAGE; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
1267 			{
1268 				de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), ""));
1269 
1270 				if (!isValidTestCase(TESTTYPE_LOCAL_VARIABLES, (DescriptorType)descNdx, (ReadOp)opNdx))
1271 					continue;
1272 
1273 				const VkFormat				imageFormat			= getImageFormat((ReadOp)opNdx);
1274 				const bool					hasDpethComponent	= tcu::hasDepthComponent(vk::mapVkFormat(imageFormat).order);
1275 
1276 				GraphicsResources			resources;
1277 				resources.inputFormat = imageFormat;
1278 
1279 				std::vector<Vec4>			inputData			= inputDataVec4;
1280 
1281 				// Depth images have one channel, thus only needing 1/4 of the data
1282 				if (hasDpethComponent)
1283 					inputData.resize(numDataPoints / 4u);
1284 
1285 				resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1286 
1287 				// Separate sampler for sampled images
1288 				if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1289 				{
1290 					vector<Vec4> unusedData;
1291 					resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(unusedData)), VK_DESCRIPTOR_TYPE_SAMPLER));
1292 				}
1293 
1294 				// Second combined image sampler with different image data
1295 				if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_SEPARATE_DESCRIPTORS)
1296 				{
1297 					for (size_t i = 0; i < inputData.size(); i++)
1298 						inputData[i] = Vec4(1.0f) - inputData[i];
1299 
1300 					resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), getVkDescriptorType((DescriptorType)descNdx)));
1301 				}
1302 
1303 				// Read image without depth reference: shader is expected to pass the input image data to output buffer
1304 				resources.outputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1305 
1306 				// Read image with depth reference: shader is expected to pass the depth comparison result to output buffer
1307 				if (hasDpethComponent)
1308 					resources.verifyIO = verifyDepthCompareResult;
1309 
1310 				const map<string, string>	fragments			= generateGraphicsImageSamplerSource((ReadOp)opNdx, (DescriptorType)descNdx, TESTTYPE_LOCAL_VARIABLES, (DepthProperty)propertyNdx, (deUint32)resources.inputs.size(), 0);
1311 
1312 				getDefaultColors(defaultColors);
1313 
1314 				createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "shader_frag", defaultColors, defaultColors, fragments, noSpecConstants,
1315 								   noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, descGroup.get());
1316 
1317 				readOpGroup->addChild(descGroup.release());
1318 			}
1319 			depthPropertyGroup->addChild(readOpGroup.release());
1320 		}
1321 		testGroup->addChild(depthPropertyGroup.release());
1322 	}
1323 	group->addChild(testGroup.release());
1324 }
1325 } // anonymous
1326 
createImageSamplerComputeGroup(tcu::TestContext & testCtx)1327 tcu::TestCaseGroup* createImageSamplerComputeGroup (tcu::TestContext& testCtx)
1328 {
1329 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "image_sampler", "Compute tests for combining images and samplers."));
1330 	addComputeImageSamplerTest(group.get());
1331 
1332 	return group.release();
1333 }
1334 
createImageSamplerGraphicsGroup(tcu::TestContext & testCtx)1335 tcu::TestCaseGroup* createImageSamplerGraphicsGroup (tcu::TestContext& testCtx)
1336 {
1337 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "image_sampler", "Graphics tests for combining images and samplers."));
1338 
1339 	addGraphicsImageSamplerTest(group.get());
1340 	addGraphicsDepthPropertyTest(group.get());
1341 
1342 	return group.release();
1343 }
1344 
1345 } // SpirVAssembly
1346 } // vkt
1347