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