• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group 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 vktPipelineMultisampleInterpolationTests.cpp
21 * \brief Multisample Interpolation Tests
22 *//*--------------------------------------------------------------------*/
23 
24 #include "vktPipelineMultisampleInterpolationTests.hpp"
25 #include "vktPipelineMultisampleTestsUtil.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 
29 #include <set>
30 
31 namespace vkt
32 {
33 namespace pipeline
34 {
35 namespace multisample
36 {
37 
38 using namespace vk;
39 
40 struct ImageMSParams
41 {
ImageMSParamsvkt::pipeline::multisample::ImageMSParams42 	ImageMSParams(const VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {}
43 
44 	VkSampleCountFlagBits	numSamples;
45 	tcu::UVec3				imageSize;
46 };
47 
48 class MSInterpolationCaseBase : public TestCase
49 {
50 public:
MSInterpolationCaseBase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)51 	MSInterpolationCaseBase	(tcu::TestContext&		testCtx,
52 							 const std::string&		name,
53 							 const ImageMSParams&	imageMSParams)
54 		: TestCase(testCtx, name, "")
55 		, m_imageMSParams(imageMSParams)
56 	{}
57 
58 protected:
59 	const ImageMSParams m_imageMSParams;
60 };
61 
62 typedef MSInterpolationCaseBase* (*MSInterpolationCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams);
63 
64 class MSInterpolationInstanceBase : public TestInstance
65 {
66 public:
MSInterpolationInstanceBase(Context & context,const ImageMSParams & imageMSParams)67 								MSInterpolationInstanceBase	(Context&							context,
68 															 const ImageMSParams&				imageMSParams)
69 		: TestInstance		(context)
70 		, m_imageMSParams	(imageMSParams)
71 		, m_imageType		(IMAGE_TYPE_2D)
72 		, m_imageFormat		(tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNORM_INT8))
73 	{}
74 
75 	tcu::TestStatus				iterate						(void);
76 
77 protected:
78 
79 	typedef std::vector<VkVertexInputAttributeDescription> VertexAttribDescVec;
80 
81 	struct VertexDataDesc
82 	{
83 		VkPrimitiveTopology	primitiveTopology;
84 		deUint32			verticesCount;
85 		deUint32			dataStride;
86 		VkDeviceSize		dataSize;
87 		VertexAttribDescVec	vertexAttribDescVec;
88 	};
89 
90 	void						validateImageSize			(const InstanceInterface&			instance,
91 															 const VkPhysicalDevice				physicalDevice,
92 															 const ImageType					imageType,
93 															 const tcu::UVec3&					imageSize) const;
94 
95 	void						validateImageFeatureFlags	(const InstanceInterface&			instance,
96 															 const VkPhysicalDevice				physicalDevice,
97 															 const VkFormat						format,
98 															 const VkFormatFeatureFlags			featureFlags) const;
99 
100 	void						validateImageInfo			(const InstanceInterface&			instance,
101 															 const VkPhysicalDevice				physicalDevice,
102 															 const VkImageCreateInfo&			imageInfo) const;
103 
104 	virtual VertexDataDesc		getVertexDataDescripton		(void) const = 0;
105 
106 	virtual void				uploadVertexData			(const Allocation&					vertexBufferAllocation,
107 															 const VertexDataDesc&				vertexDataDescripton) const = 0;
108 
109 	virtual tcu::TestStatus		verifyResolvedImage			(const tcu::ConstPixelBufferAccess&	imageData) const = 0;
110 protected:
111 	const ImageMSParams			m_imageMSParams;
112 	const ImageType				m_imageType;
113 	const tcu::TextureFormat	m_imageFormat;
114 };
115 
validateImageSize(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const ImageType imageType,const tcu::UVec3 & imageSize) const116 void MSInterpolationInstanceBase::validateImageSize (const InstanceInterface&	instance,
117 													 const VkPhysicalDevice		physicalDevice,
118 													 const ImageType			imageType,
119 													 const tcu::UVec3&			imageSize) const
120 {
121 	const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
122 
123 	bool isImageSizeValid = true;
124 
125 	switch (imageType)
126 	{
127 		case IMAGE_TYPE_1D:
128 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
129 			break;
130 		case IMAGE_TYPE_1D_ARRAY:
131 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
132 								imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
133 			break;
134 		case IMAGE_TYPE_2D:
135 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
136 								imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
137 			break;
138 		case IMAGE_TYPE_2D_ARRAY:
139 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
140 								imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
141 								imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
142 			break;
143 		case IMAGE_TYPE_CUBE:
144 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
145 								imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
146 			break;
147 		case IMAGE_TYPE_CUBE_ARRAY:
148 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
149 								imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
150 								imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
151 			break;
152 		case IMAGE_TYPE_3D:
153 			isImageSizeValid =	imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
154 								imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
155 								imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
156 			break;
157 		default:
158 			DE_FATAL("Unknown image type");
159 	}
160 
161 	if (!isImageSizeValid)
162 	{
163 		std::ostringstream	notSupportedStream;
164 
165 		notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl;
166 
167 		const std::string notSupportedString = notSupportedStream.str();
168 
169 		TCU_THROW(NotSupportedError, notSupportedString.c_str());
170 	}
171 }
172 
validateImageFeatureFlags(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkFormat format,const VkFormatFeatureFlags featureFlags) const173 void MSInterpolationInstanceBase::validateImageFeatureFlags	(const InstanceInterface&	instance,
174 															 const VkPhysicalDevice		physicalDevice,
175 															 const VkFormat				format,
176 															 const VkFormatFeatureFlags	featureFlags) const
177 {
178 	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
179 
180 	if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags)
181 	{
182 		std::ostringstream	notSupportedStream;
183 
184 		notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl;
185 
186 		const std::string notSupportedString = notSupportedStream.str();
187 
188 		TCU_THROW(NotSupportedError, notSupportedString.c_str());
189 	}
190 }
191 
validateImageInfo(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkImageCreateInfo & imageInfo) const192 void MSInterpolationInstanceBase::validateImageInfo	(const InstanceInterface&	instance,
193 													 const VkPhysicalDevice		physicalDevice,
194 													 const VkImageCreateInfo&	imageInfo) const
195 {
196 	VkImageFormatProperties imageFormatProps;
197 	instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps);
198 
199 	if (imageFormatProps.maxExtent.width  < imageInfo.extent.width  ||
200 		imageFormatProps.maxExtent.height < imageInfo.extent.height ||
201 		imageFormatProps.maxExtent.depth  < imageInfo.extent.depth)
202 	{
203 		std::ostringstream	notSupportedStream;
204 
205 		notSupportedStream	<< "Image extent ("
206 							<< imageInfo.extent.width  << ", "
207 							<< imageInfo.extent.height << ", "
208 							<< imageInfo.extent.depth
209 							<< ") exceeds allowed maximum ("
210 							<< imageFormatProps.maxExtent.width <<  ", "
211 							<< imageFormatProps.maxExtent.height << ", "
212 							<< imageFormatProps.maxExtent.depth
213 							<< ")"
214 							<< std::endl;
215 
216 		const std::string notSupportedString = notSupportedStream.str();
217 
218 		TCU_THROW(NotSupportedError, notSupportedString.c_str());
219 	}
220 
221 	if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers)
222 	{
223 		std::ostringstream	notSupportedStream;
224 
225 		notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl;
226 
227 		const std::string notSupportedString = notSupportedStream.str();
228 
229 		TCU_THROW(NotSupportedError, notSupportedString.c_str());
230 	}
231 
232 	if (!(imageFormatProps.sampleCounts & imageInfo.samples))
233 	{
234 		std::ostringstream	notSupportedStream;
235 
236 		notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl;
237 
238 		const std::string notSupportedString = notSupportedStream.str();
239 
240 		TCU_THROW(NotSupportedError, notSupportedString.c_str());
241 	}
242 }
243 
iterate(void)244 tcu::TestStatus MSInterpolationInstanceBase::iterate (void)
245 {
246 	const InstanceInterface&	instance			= m_context.getInstanceInterface();
247 	const DeviceInterface&		deviceInterface		= m_context.getDeviceInterface();
248 	const VkDevice				device				= m_context.getDevice();
249 	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
250 	Allocator&					allocator			= m_context.getDefaultAllocator();
251 	const VkQueue				queue				= m_context.getUniversalQueue();
252 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
253 
254 	VkImageCreateInfo			imageMSInfo;
255 	VkImageCreateInfo			imageRSInfo;
256 
257 	// Check if image size does not exceed device limits
258 	validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
259 
260 	// Check if device supports image format as color attachment
261 	validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
262 
263 	imageMSInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
264 	imageMSInfo.pNext					= DE_NULL;
265 	imageMSInfo.flags					= 0u;
266 	imageMSInfo.imageType				= mapImageType(m_imageType);
267 	imageMSInfo.format					= mapTextureFormat(m_imageFormat);
268 	imageMSInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
269 	imageMSInfo.arrayLayers				= getNumLayers(m_imageType, m_imageMSParams.imageSize);
270 	imageMSInfo.mipLevels				= 1u;
271 	imageMSInfo.samples					= m_imageMSParams.numSamples;
272 	imageMSInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;
273 	imageMSInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
274 	imageMSInfo.usage					= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
275 	imageMSInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
276 	imageMSInfo.queueFamilyIndexCount	= 0u;
277 	imageMSInfo.pQueueFamilyIndices		= DE_NULL;
278 
279 	if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
280 	{
281 		imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
282 	}
283 
284 	validateImageInfo(instance, physicalDevice, imageMSInfo);
285 
286 	const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
287 
288 	imageRSInfo			= imageMSInfo;
289 	imageRSInfo.samples	= VK_SAMPLE_COUNT_1_BIT;
290 
291 	validateImageInfo(instance, physicalDevice, imageRSInfo);
292 
293 	const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
294 
295 	// Create render pass
296 	const VkAttachmentDescription attachmentMSDesc =
297 	{
298 		(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
299 		imageMSInfo.format,							// VkFormat							format;
300 		imageMSInfo.samples,						// VkSampleCountFlagBits			samples;
301 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
302 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
303 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
304 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
305 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
306 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout;
307 	};
308 
309 	const VkAttachmentDescription attachmentRSDesc =
310 	{
311 		(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
312 		imageRSInfo.format,							// VkFormat							format;
313 		imageRSInfo.samples,						// VkSampleCountFlagBits			samples;
314 		VK_ATTACHMENT_LOAD_OP_CLEAR,			// VkAttachmentLoadOp				loadOp;
315 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
316 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
317 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
318 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
319 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout;
320 	};
321 
322 	const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc };
323 
324 	const VkAttachmentReference attachmentMSRef =
325 	{
326 		0u,											// deUint32			attachment;
327 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
328 	};
329 
330 	const VkAttachmentReference attachmentRSRef =
331 	{
332 		1u,											// deUint32			attachment;
333 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
334 	};
335 
336 	const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
337 
338 	const VkSubpassDescription subpassDescription =
339 	{
340 		(VkSubpassDescriptionFlags)0u,						// VkSubpassDescriptionFlags		flags;
341 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
342 		0u,													// deUint32							inputAttachmentCount;
343 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
344 		1u,													// deUint32							colorAttachmentCount;
345 		&attachmentMSRef,									// const VkAttachmentReference*		pColorAttachments;
346 		resolveAttachment,								// const VkAttachmentReference*		pResolveAttachments;
347 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
348 		0u,													// deUint32							preserveAttachmentCount;
349 		DE_NULL												// const deUint32*					pPreserveAttachments;
350 	};
351 
352 	const VkRenderPassCreateInfo renderPassInfo =
353 	{
354 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
355 		DE_NULL,											// const void*						pNext;
356 		(VkRenderPassCreateFlags)0u,						// VkRenderPassCreateFlags			flags;
357 		2u,													// deUint32							attachmentCount;
358 		attachments,										// const VkAttachmentDescription*	pAttachments;
359 		1u,													// deUint32							subpassCount;
360 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
361 		0u,													// deUint32							dependencyCount;
362 		DE_NULL												// const VkSubpassDependency*		pDependencies;
363 	};
364 
365 	const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
366 
367 	const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
368 
369 	// Create color attachments image views
370 	const Unique<VkImageView> imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
371 	const Unique<VkImageView> imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
372 
373 	const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView };
374 
375 	// Create framebuffer
376 	const VkFramebufferCreateInfo framebufferInfo =
377 	{
378 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType                             sType;
379 		DE_NULL,									// const void*                                 pNext;
380 		(VkFramebufferCreateFlags)0u,				// VkFramebufferCreateFlags                    flags;
381 		*renderPass,								// VkRenderPass                                renderPass;
382 		2u,											// uint32_t                                    attachmentCount;
383 		attachmentsViews,							// const VkImageView*                          pAttachments;
384 		imageMSInfo.extent.width,					// uint32_t                                    width;
385 		imageMSInfo.extent.height,					// uint32_t                                    height;
386 		imageMSInfo.arrayLayers,					// uint32_t                                    layers;
387 	};
388 
389 	const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
390 
391 	// Create pipeline layout
392 	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
393 	{
394 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
395 		DE_NULL,											// const void*						pNext;
396 		(VkPipelineLayoutCreateFlags)0u,					// VkPipelineLayoutCreateFlags		flags;
397 		0u,													// deUint32							setLayoutCount;
398 		DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
399 		0u,													// deUint32							pushConstantRangeCount;
400 		DE_NULL,											// const VkPushConstantRange*		pPushConstantRanges;
401 	};
402 
403 	const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams));
404 
405 	// Create vertex attributes data
406 	const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
407 
408 	de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
409 	const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
410 
411 	uploadVertexData(vertexBufferAllocation, vertexDataDesc);
412 
413 	flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataDesc.dataSize);
414 
415 	const VkVertexInputBindingDescription vertexBinding =
416 	{
417 		0u,							// deUint32				binding;
418 		vertexDataDesc.dataStride,	// deUint32				stride;
419 		VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
420 	};
421 
422 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
423 	{
424 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,			// VkStructureType                             sType;
425 		DE_NULL,															// const void*                                 pNext;
426 		(VkPipelineVertexInputStateCreateFlags)0u,							// VkPipelineVertexInputStateCreateFlags       flags;
427 		1u,																	// uint32_t                                    vertexBindingDescriptionCount;
428 		&vertexBinding,														// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
429 		static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()),	// uint32_t                                    vertexAttributeDescriptionCount;
430 		dataPointer(vertexDataDesc.vertexAttribDescVec),					// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
431 	};
432 
433 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
434 	{
435 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
436 		DE_NULL,														// const void*                                 pNext;
437 		(VkPipelineInputAssemblyStateCreateFlags)0u,					// VkPipelineInputAssemblyStateCreateFlags     flags;
438 		vertexDataDesc.primitiveTopology,								// VkPrimitiveTopology                         topology;
439 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
440 	};
441 
442 	const VkViewport viewport =
443 	{
444 		0.0f, 0.0f,
445 		static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
446 		0.0f, 1.0f
447 	};
448 
449 	const VkRect2D scissor =
450 	{
451 		makeOffset2D(0, 0),
452 		makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
453 	};
454 
455 	const VkPipelineViewportStateCreateInfo viewportStateInfo =
456 	{
457 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
458 		DE_NULL,														// const void*                                 pNext;
459 		(VkPipelineViewportStateCreateFlags)0u,							// VkPipelineViewportStateCreateFlags          flags;
460 		1u,																// uint32_t                                    viewportCount;
461 		&viewport,														// const VkViewport*                           pViewports;
462 		1u,																// uint32_t                                    scissorCount;
463 		&scissor,														// const VkRect2D*                             pScissors;
464 	};
465 
466 	const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
467 	{
468 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
469 		DE_NULL,														// const void*                              pNext;
470 		(VkPipelineRasterizationStateCreateFlags)0u,					// VkPipelineRasterizationStateCreateFlags  flags;
471 		VK_FALSE,														// VkBool32                                 depthClampEnable;
472 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
473 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
474 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
475 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
476 		VK_FALSE,														// VkBool32									depthBiasEnable;
477 		0.0f,															// float									depthBiasConstantFactor;
478 		0.0f,															// float									depthBiasClamp;
479 		0.0f,															// float									depthBiasSlopeFactor;
480 		1.0f,															// float									lineWidth;
481 	};
482 
483 	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
484 	{
485 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
486 		DE_NULL,														// const void*								pNext;
487 		(VkPipelineMultisampleStateCreateFlags)0u,						// VkPipelineMultisampleStateCreateFlags	flags;
488 		imageMSInfo.samples,											// VkSampleCountFlagBits					rasterizationSamples;
489 		VK_TRUE,														// VkBool32									sampleShadingEnable;
490 		1.0f,															// float									minSampleShading;
491 		DE_NULL,														// const VkSampleMask*						pSampleMask;
492 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
493 		VK_FALSE,														// VkBool32									alphaToOneEnable;
494 	};
495 
496 	const VkStencilOpState stencilOpState = makeStencilOpState
497 	(
498 		VK_STENCIL_OP_KEEP,		// stencil fail
499 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
500 		VK_STENCIL_OP_KEEP,		// depth only fail
501 		VK_COMPARE_OP_ALWAYS,	// compare op
502 		0u,						// compare mask
503 		0u,						// write mask
504 		0u						// reference
505 	);
506 
507 	const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
508 	{
509 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
510 		DE_NULL,														// const void*								pNext;
511 		(VkPipelineDepthStencilStateCreateFlags)0u,						// VkPipelineDepthStencilStateCreateFlags	flags;
512 		VK_FALSE,														// VkBool32									depthTestEnable;
513 		VK_FALSE,														// VkBool32									depthWriteEnable;
514 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
515 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
516 		VK_FALSE,														// VkBool32									stencilTestEnable;
517 		stencilOpState,													// VkStencilOpState							front;
518 		stencilOpState,													// VkStencilOpState							back;
519 		0.0f,															// float									minDepthBounds;
520 		1.0f,															// float									maxDepthBounds;
521 	};
522 
523 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
524 
525 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
526 	{
527 		VK_FALSE,														// VkBool32					blendEnable;
528 		VK_BLEND_FACTOR_SRC_ALPHA,										// VkBlendFactor			srcColorBlendFactor;
529 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,							// VkBlendFactor			dstColorBlendFactor;
530 		VK_BLEND_OP_ADD,												// VkBlendOp				colorBlendOp;
531 		VK_BLEND_FACTOR_SRC_ALPHA,										// VkBlendFactor			srcAlphaBlendFactor;
532 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,							// VkBlendFactor			dstAlphaBlendFactor;
533 		VK_BLEND_OP_ADD,												// VkBlendOp				alphaBlendOp;
534 		colorComponentsAll,												// VkColorComponentFlags	colorWriteMask;
535 	};
536 
537 	const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
538 	{
539 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
540 		DE_NULL,														// const void*									pNext;
541 		(VkPipelineColorBlendStateCreateFlags)0u,						// VkPipelineColorBlendStateCreateFlags			flags;
542 		VK_FALSE,														// VkBool32										logicOpEnable;
543 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
544 		1u,																// deUint32										attachmentCount;
545 		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments;
546 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
547 	};
548 
549 	const Unique<VkShaderModule> vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
550 
551 	const VkPipelineShaderStageCreateInfo vsShaderStageInfo =
552 	{
553 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,			// VkStructureType						sType;
554 		DE_NULL,														// const void*							pNext;
555 		(VkPipelineShaderStageCreateFlags)0u,							// VkPipelineShaderStageCreateFlags		flags;
556 		VK_SHADER_STAGE_VERTEX_BIT,										// VkShaderStageFlagBits				stage;
557 		*vsModule,														// VkShaderModule						module;
558 		"main",															// const char*							pName;
559 		DE_NULL,														// const VkSpecializationInfo*			pSpecializationInfo;
560 	};
561 
562 	const Unique<VkShaderModule> fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
563 
564 	const VkPipelineShaderStageCreateInfo fsShaderStageInfo =
565 	{
566 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,			// VkStructureType						sType;
567 		DE_NULL,														// const void*							pNext;
568 		(VkPipelineShaderStageCreateFlags)0u,							// VkPipelineShaderStageCreateFlags		flags;
569 		VK_SHADER_STAGE_FRAGMENT_BIT,									// VkShaderStageFlagBits				stage;
570 		*fsModule,														// VkShaderModule						module;
571 		"main",															// const char*							pName;
572 		DE_NULL,														// const VkSpecializationInfo*			pSpecializationInfo;
573 	};
574 
575 	const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo };
576 
577 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
578 	{
579 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,				// VkStructureType									sType;
580 		DE_NULL,														// const void*										pNext;
581 		(VkPipelineCreateFlags)0,										// VkPipelineCreateFlags							flags;
582 		2u,																// deUint32											stageCount;
583 		shaderStageInfos,												// const VkPipelineShaderStageCreateInfo*			pStages;
584 		&vertexInputStateInfo,											// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
585 		&inputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
586 		DE_NULL,														// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
587 		&viewportStateInfo,												// const VkPipelineViewportStateCreateInfo*			pViewportState;
588 		&rasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
589 		&multisampleStateInfo,											// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
590 		&depthStencilStateInfo,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
591 		&colorBlendStateInfo,											// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
592 		DE_NULL,														// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
593 		*pipelineLayout,												// VkPipelineLayout									layout;
594 		*renderPass,													// VkRenderPass										renderPass;
595 		0u,																// deUint32											subpass;
596 		DE_NULL,														// VkPipeline										basePipelineHandle;
597 		0u,																// deInt32											basePipelineIndex;
598 	};
599 
600 	// Create graphics pipeline
601 	const Unique<VkPipeline> graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
602 
603 	// Create command buffer for compute and transfer oparations
604 	const Unique<VkCommandPool>	  commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
605 	const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
606 
607 	// Start recording commands
608 	beginCommandBuffer(deviceInterface, *commandBuffer);
609 
610 	{
611 		VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
612 
613 		imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
614 		(
615 			0u,
616 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
617 			VK_IMAGE_LAYOUT_UNDEFINED,
618 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
619 			**imageMS,
620 			fullImageRange
621 		);
622 
623 		imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
624 		(
625 			0u,
626 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
627 			VK_IMAGE_LAYOUT_UNDEFINED,
628 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
629 			**imageRS,
630 			fullImageRange
631 		);
632 
633 		deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers);
634 	}
635 
636 	{
637 		const VkDeviceSize vertexStartOffset = 0u;
638 
639 		std::vector<VkClearValue> clearValues;
640 		clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
641 		clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
642 
643 		const vk::VkRect2D renderArea =
644 		{
645 			makeOffset2D(0u, 0u),
646 			makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
647 		};
648 
649 		// Begin render pass
650 		const VkRenderPassBeginInfo renderPassBeginInfo =
651 		{
652 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
653 			DE_NULL,										// const void*             pNext;
654 			*renderPass,										// VkRenderPass            renderPass;
655 			*framebuffer,									// VkFramebuffer           framebuffer;
656 			renderArea,										// VkRect2D                renderArea;
657 			static_cast<deUint32>(clearValues.size()),		// deUint32                clearValueCount;
658 			&clearValues[0],								// const VkClearValue*     pClearValues;
659 		};
660 
661 		deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
662 
663 		// Bind graphics pipeline
664 		deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
665 
666 		// Bind vertex buffer
667 		deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
668 
669 		// Draw full screen quad
670 		deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
671 
672 		// End render pass
673 		deviceInterface.cmdEndRenderPass(*commandBuffer);
674 	}
675 
676 	const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
677 
678 	{
679 		const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier
680 		(
681 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
682 			VK_ACCESS_TRANSFER_READ_BIT,
683 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
684 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
685 			sourceImage,
686 			fullImageRange
687 		);
688 
689 		deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier);
690 	}
691 
692 	// Copy data from resolve image to buffer
693 	const deUint32				imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
694 
695 	const VkBufferCreateInfo	bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
696 	const de::UniquePtr<Buffer>	bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
697 
698 	{
699 		const VkBufferImageCopy bufferImageCopy =
700 		{
701 			0u,																						//	VkDeviceSize				bufferOffset;
702 			0u,																						//	deUint32					bufferRowLength;
703 			0u,																						//	deUint32					bufferImageHeight;
704 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers),	//	VkImageSubresourceLayers	imageSubresource;
705 			makeOffset3D(0, 0, 0),																	//	VkOffset3D					imageOffset;
706 			imageRSInfo.extent,																		//	VkExtent3D					imageExtent;
707 		};
708 
709 		deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
710 	}
711 
712 	{
713 		const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
714 		(
715 			VK_ACCESS_TRANSFER_WRITE_BIT,
716 			VK_ACCESS_HOST_READ_BIT,
717 			bufferRS->get(),
718 			0u,
719 			imageRSSizeInBytes
720 		);
721 
722 		deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
723 	}
724 
725 	// End recording commands
726 	VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
727 
728 	// Submit commands for execution and wait for completion
729 	submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
730 
731 	// Retrieve data from buffer to host memory
732 	const Allocation& bufferRSAllocation = bufferRS->getAllocation();
733 
734 	invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), imageRSSizeInBytes);
735 
736 	const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
737 													imageRSInfo.extent.width,
738 													imageRSInfo.extent.height,
739 													imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
740 													bufferRSAllocation.getHostPtr());
741 
742 	std::stringstream imageName;
743 	imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
744 
745 	m_context.getTestContext().getLog()
746 		<< tcu::TestLog::Section(imageName.str(), imageName.str())
747 		<< tcu::LogImage("image", "", bufferRSData)
748 		<< tcu::TestLog::EndSection;
749 
750 	return verifyResolvedImage(bufferRSData);
751 }
752 
753 class MSInstanceDistinctValues : public MSInterpolationInstanceBase
754 {
755 public:
MSInstanceDistinctValues(Context & context,const ImageMSParams & imageMSParams)756 					MSInstanceDistinctValues(Context&				context,
757 											 const ImageMSParams&	imageMSParams)
758 	: MSInterpolationInstanceBase(context, imageMSParams) {}
759 
760 	VertexDataDesc	getVertexDataDescripton	(void) const;
761 	void			uploadVertexData		(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
762 	tcu::TestStatus	verifyResolvedImage		(const tcu::ConstPixelBufferAccess&	imageData) const;
763 
764 protected:
765 	struct VertexData
766 	{
VertexDatavkt::pipeline::multisample::MSInstanceDistinctValues::VertexData767 		VertexData(const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
768 
769 		tcu::Vec4 positionNdc;
770 	};
771 };
772 
getVertexDataDescripton(void) const773 MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexDataDescripton (void) const
774 {
775 	VertexDataDesc vertexDataDesc;
776 
777 	vertexDataDesc.verticesCount		= 3u;
778 	vertexDataDesc.dataStride			= sizeof(VertexData);
779 	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
780 	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
781 
782 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
783 	{
784 		0u,										// deUint32	location;
785 		0u,										// deUint32	binding;
786 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
787 		DE_OFFSET_OF(VertexData, positionNdc),	// deUint32	offset;
788 	};
789 
790 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
791 
792 	return vertexDataDesc;
793 }
794 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const795 void MSInstanceDistinctValues::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
796 {
797 	std::vector<VertexData> vertices;
798 
799 	vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f)));
800 	vertices.push_back(VertexData(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
801 	vertices.push_back(VertexData(tcu::Vec4( 4.0f,-1.0f, 0.0f, 1.0f)));
802 
803 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
804 }
805 
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const806 tcu::TestStatus	MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
807 {
808 	const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
809 
810 	std::vector<tcu::IVec4> distinctValues;
811 
812 	for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
813 	for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
814 	for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
815 	{
816 		const tcu::IVec4 pixel = imageData.getPixelInt(x, y, z);
817 
818 		if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
819 			distinctValues.push_back(pixel);
820 	}
821 
822 	if (distinctValues.size() >= distinctValuesExpected)
823 		return tcu::TestStatus::pass("Passed");
824 	else
825 		return tcu::TestStatus::fail("Failed");
826 }
827 
828 class MSCaseSampleQualifierDistinctValues : public MSInterpolationCaseBase
829 {
830 public:
MSCaseSampleQualifierDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)831 					MSCaseSampleQualifierDistinctValues	(tcu::TestContext&		testCtx,
832 														 const std::string&		name,
833 														 const ImageMSParams&	imageMSParams)
834 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
835 
836 	void			init								(void);
837 	void			initPrograms						(vk::SourceCollections& programCollection) const;
838 	TestInstance*	createInstance						(Context&				context) const;
839 };
840 
createMSCaseSampleQualifierDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)841 MSInterpolationCaseBase* createMSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
842 {
843 	return new MSCaseSampleQualifierDistinctValues(testCtx, name, imageMSParams);
844 }
845 
init(void)846 void MSCaseSampleQualifierDistinctValues::init (void)
847 {
848 	m_testCtx.getLog()
849 		<< tcu::TestLog::Message
850 		<< "Verifying that a sample qualified varying is given different values for different samples.\n"
851 		<< "	Render full screen traingle with quadratic function defining red/green color pattern division.\n"
852 		<< "	=> Resulting image should contain n+1 different colors, where n = sample count.\n"
853 		<< tcu::TestLog::EndMessage;
854 
855 	MSInterpolationCaseBase::init();
856 }
857 
initPrograms(vk::SourceCollections & programCollection) const858 void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
859 {
860 	// Create vertex shader
861 	std::ostringstream vs;
862 
863 	vs << "#version 440\n"
864 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
865 		<< "\n"
866 		<< "layout(location = 0) out vec4 vs_out_position_ndc;\n"
867 		<< "\n"
868 		<< "out gl_PerVertex {\n"
869 		<< "	vec4  gl_Position;\n"
870 		<< "};\n"
871 		<< "void main (void)\n"
872 		<< "{\n"
873 		<< "	gl_Position			= vs_in_position_ndc;\n"
874 		<< "	vs_out_position_ndc = vs_in_position_ndc;\n"
875 		<< "}\n";
876 
877 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
878 
879 	// Create fragment shader
880 	std::ostringstream fs;
881 
882 	fs << "#version 440\n"
883 		<< "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
884 		<< "\n"
885 		<< "layout(location = 0) out vec2 fs_out_color;\n"
886 		<< "\n"
887 		<< "void main (void)\n"
888 		<< "{\n"
889 		<< "	if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
890 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
891 		<< "	else\n"
892 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
893 		<< "}\n";
894 
895 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
896 }
897 
createInstance(Context & context) const898 TestInstance* MSCaseSampleQualifierDistinctValues::createInstance (Context& context) const
899 {
900 	return new MSInstanceDistinctValues(context, m_imageMSParams);
901 }
902 
903 class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase
904 {
905 public:
MSCaseInterpolateAtSampleDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)906 					MSCaseInterpolateAtSampleDistinctValues	(tcu::TestContext&		testCtx,
907 															 const std::string&		name,
908 															 const ImageMSParams&	imageMSParams)
909 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
910 
911 	void			init									(void);
912 	void			initPrograms							(vk::SourceCollections& programCollection) const;
913 	TestInstance*	createInstance							(Context&				context) const;
914 };
915 
createMSCaseInterpolateAtSampleDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)916 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
917 {
918 	return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams);
919 }
920 
init(void)921 void MSCaseInterpolateAtSampleDistinctValues::init (void)
922 {
923 	m_testCtx.getLog()
924 		<< tcu::TestLog::Message
925 		<< "Verifying that a interpolateAtSample returns different values for different samples.\n"
926 		<< "	Render full screen traingle with quadratic function defining red/green color pattern division.\n"
927 		<< "	=> Resulting image should contain n+1 different colors, where n = sample count.\n"
928 		<< tcu::TestLog::EndMessage;
929 
930 	MSInterpolationCaseBase::init();
931 }
932 
initPrograms(vk::SourceCollections & programCollection) const933 void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
934 {
935 	// Create vertex shader
936 	std::ostringstream vs;
937 
938 	vs << "#version 440\n"
939 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
940 		<< "\n"
941 		<< "layout(location = 0) out vec4 vs_out_position_ndc;\n"
942 		<< "\n"
943 		<< "out gl_PerVertex {\n"
944 		<< "	vec4  gl_Position;\n"
945 		<< "};\n"
946 		<< "void main (void)\n"
947 		<< "{\n"
948 		<< "	gl_Position			= vs_in_position_ndc;\n"
949 		<< "	vs_out_position_ndc = vs_in_position_ndc;\n"
950 		<< "}\n";
951 
952 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
953 
954 	// Create fragment shader
955 	std::ostringstream fs;
956 
957 	fs << "#version 440\n"
958 		<< "layout(location = 0) in vec4 fs_in_position_ndc;\n"
959 		<< "\n"
960 		<< "layout(location = 0) out vec2 fs_out_color;\n"
961 		<< "\n"
962 		<< "void main (void)\n"
963 		<< "{\n"
964 		<< "	const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
965 		<< "	if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
966 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
967 		<< "	else\n"
968 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
969 		<< "}\n";
970 
971 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
972 }
973 
createInstance(Context & context) const974 TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const
975 {
976 	return new MSInstanceDistinctValues(context, m_imageMSParams);
977 }
978 
979 class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase
980 {
981 public:
MSInstanceInterpolateScreenPosition(Context & context,const ImageMSParams & imageMSParams)982 					MSInstanceInterpolateScreenPosition	(Context&				context,
983 														 const ImageMSParams&	imageMSParams)
984 	: MSInterpolationInstanceBase(context, imageMSParams) {}
985 
986 	VertexDataDesc	getVertexDataDescripton				(void) const;
987 	void			uploadVertexData					(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
988 	tcu::TestStatus	verifyResolvedImage					(const tcu::ConstPixelBufferAccess&	imageData) const;
989 
990 protected:
991 	struct VertexData
992 	{
VertexDatavkt::pipeline::multisample::MSInstanceInterpolateScreenPosition::VertexData993 		VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
994 
995 		tcu::Vec4 positionNdc;
996 		tcu::Vec2 positionScreen;
997 	};
998 };
999 
getVertexDataDescripton(void) const1000 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const
1001 {
1002 	VertexDataDesc vertexDataDesc;
1003 
1004 	vertexDataDesc.verticesCount		= 4u;
1005 	vertexDataDesc.dataStride			= sizeof(VertexData);
1006 	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1007 	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1008 
1009 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1010 	{
1011 		0u,											// deUint32	location;
1012 		0u,											// deUint32	binding;
1013 		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
1014 		DE_OFFSET_OF(VertexData, positionNdc),		// deUint32	offset;
1015 	};
1016 
1017 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1018 
1019 	const VkVertexInputAttributeDescription vertexAttribPositionScreen =
1020 	{
1021 		1u,											// deUint32	location;
1022 		0u,											// deUint32	binding;
1023 		VK_FORMAT_R32G32_SFLOAT,					// VkFormat	format;
1024 		DE_OFFSET_OF(VertexData, positionScreen),	// deUint32	offset;
1025 	};
1026 
1027 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
1028 
1029 	return vertexDataDesc;
1030 }
1031 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const1032 void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1033 {
1034 	const tcu::UVec3 layerSize		= getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
1035 	const float		 screenSizeX	= static_cast<float>(layerSize.x());
1036 	const float		 screenSizeY	= static_cast<float>(layerSize.y());
1037 
1038 	std::vector<VertexData> vertices;
1039 
1040 	vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,		 0.0f)));
1041 	vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
1042 	vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,		 screenSizeY)));
1043 	vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
1044 
1045 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1046 }
1047 
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const1048 tcu::TestStatus	MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1049 {
1050 	for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1051 	for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1052 	for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1053 	{
1054 		const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1055 
1056 		if (firstComponent > 0)
1057 			return tcu::TestStatus::fail("Failed");
1058 	}
1059 	return tcu::TestStatus::pass("Passed");
1060 }
1061 
1062 class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase
1063 {
1064 public:
MSCaseInterpolateAtSampleSingleSample(tcu::TestContext & testCtx,const std::string & name,tcu::UVec3 imageSize)1065 					MSCaseInterpolateAtSampleSingleSample	(tcu::TestContext&		testCtx,
1066 															 const std::string&		name,
1067 															 tcu::UVec3				imageSize)
1068 	: MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {}
1069 
1070 	void			init									(void);
1071 	void			initPrograms							(vk::SourceCollections& programCollection) const;
1072 	TestInstance*	createInstance							(Context&				context) const;
1073 };
1074 
init(void)1075 void MSCaseInterpolateAtSampleSingleSample::init (void)
1076 {
1077 	m_testCtx.getLog()
1078 		<< tcu::TestLog::Message
1079 		<< "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
1080 		<< "	Interpolate varying containing screen space location.\n"
1081 		<< "	=> fract(screen space location) should be (about) (0.5, 0.5)\n"
1082 		<< tcu::TestLog::EndMessage;
1083 
1084 	MSInterpolationCaseBase::init();
1085 }
1086 
initPrograms(vk::SourceCollections & programCollection) const1087 void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const
1088 {
1089 	// Create vertex shader
1090 	std::ostringstream vs;
1091 
1092 	vs << "#version 440\n"
1093 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1094 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1095 		<< "\n"
1096 		<< "layout(location = 0) out vec2 vs_out_position_screen;\n"
1097 		<< "\n"
1098 		<< "out gl_PerVertex {\n"
1099 		<< "	vec4  gl_Position;\n"
1100 		<< "};\n"
1101 		<< "void main (void)\n"
1102 		<< "{\n"
1103 		<< "	gl_Position				= vs_in_position_ndc;\n"
1104 		<< "	vs_out_position_screen	= vs_in_position_screen;\n"
1105 		<< "}\n";
1106 
1107 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1108 
1109 	// Create fragment shader
1110 	std::ostringstream fs;
1111 
1112 	fs << "#version 440\n"
1113 		<< "layout(location = 0) in vec2 fs_in_position_screen;\n"
1114 		<< "\n"
1115 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1116 		<< "\n"
1117 		<< "void main (void)\n"
1118 		<< "{\n"
1119 		<< "	const float threshold					= 0.15625;\n"
1120 		<< "	const vec2  position_screen_at_sample	= interpolateAtSample(fs_in_position_screen, 0);\n"
1121 		<< "	const vec2  position_inside_pixel		= fract(position_screen_at_sample);\n"
1122 		<< "\n"
1123 		<< "	if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
1124 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
1125 		<< "	else\n"
1126 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
1127 		<< "}\n";
1128 
1129 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1130 }
1131 
createInstance(Context & context) const1132 TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const
1133 {
1134 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1135 }
1136 
1137 class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase
1138 {
1139 public:
MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1140 					MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext&		testCtx,
1141 															 const std::string&		name,
1142 															 const ImageMSParams&	imageMSParams)
1143 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1144 
1145 	void			init									(void);
1146 	void			initPrograms							(vk::SourceCollections& programCollection) const;
1147 	TestInstance*	createInstance							(Context&				context) const;
1148 };
1149 
createMSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1150 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1151 {
1152 	return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams);
1153 }
1154 
init(void)1155 void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
1156 {
1157 	m_testCtx.getLog()
1158 		<< tcu::TestLog::Message
1159 		<< "Verifying that interpolateAtSample ignores centroid qualifier.\n"
1160 		<< "	Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1161 		<< "	=> interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
1162 		<< tcu::TestLog::EndMessage;
1163 
1164 	MSInterpolationCaseBase::init();
1165 }
1166 
initPrograms(vk::SourceCollections & programCollection) const1167 void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const
1168 {
1169 	// Create vertex shader
1170 	std::ostringstream vs;
1171 
1172 	vs << "#version 440\n"
1173 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1174 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1175 		<< "\n"
1176 		<< "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1177 		<< "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
1178 		<< "\n"
1179 		<< "out gl_PerVertex {\n"
1180 		<< "	vec4  gl_Position;\n"
1181 		<< "};\n"
1182 		<< "void main (void)\n"
1183 		<< "{\n"
1184 		<< "	gl_Position					= vs_in_position_ndc;\n"
1185 		<< "	vs_out_pos_screen_centroid	= vs_in_position_screen;\n"
1186 		<< "	vs_out_pos_screen_fragment	= vs_in_position_screen;\n"
1187 		<< "}\n";
1188 
1189 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1190 
1191 	// Create fragment shader
1192 	std::ostringstream fs;
1193 
1194 	fs << "#version 440\n"
1195 		<< "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1196 		<< "layout(location = 1)		  in vec2 fs_in_pos_screen_fragment;\n"
1197 		<< "\n"
1198 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1199 		<< "\n"
1200 		<< "void main (void)\n"
1201 		<< "{\n"
1202 		<< "	const float threshold = 0.0005;\n"
1203 		<< "\n"
1204 		<< "	const vec2 position_a  = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1205 		<< "	const vec2 position_b  = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
1206 		<< "	const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
1207 		<< "\n"
1208 		<< "	if (valuesEqual)\n"
1209 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
1210 		<< "	else\n"
1211 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
1212 		<< "}\n";
1213 
1214 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1215 }
1216 
createInstance(Context & context) const1217 TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const
1218 {
1219 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1220 }
1221 
1222 class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase
1223 {
1224 public:
MSCaseInterpolateAtSampleConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1225 					MSCaseInterpolateAtSampleConsistency	(tcu::TestContext&		testCtx,
1226 															 const std::string&		name,
1227 															 const ImageMSParams&	imageMSParams)
1228 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1229 
1230 	void			init									(void);
1231 	void			initPrograms							(vk::SourceCollections&	programCollection) const;
1232 	TestInstance*	createInstance							(Context&				context) const;
1233 };
1234 
createMSCaseInterpolateAtSampleConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1235 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1236 {
1237 	return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams);
1238 }
1239 
init(void)1240 void MSCaseInterpolateAtSampleConsistency::init (void)
1241 {
1242 	m_testCtx.getLog()
1243 		<< tcu::TestLog::Message
1244 		<< "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
1245 		<< "	Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1246 		<< "	=> interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
1247 		<< tcu::TestLog::EndMessage;
1248 
1249 	MSInterpolationCaseBase::init();
1250 }
1251 
initPrograms(vk::SourceCollections & programCollection) const1252 void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const
1253 {
1254 	// Create vertex shader
1255 	std::ostringstream vs;
1256 
1257 	vs << "#version 440\n"
1258 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1259 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1260 		<< "\n"
1261 		<< "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1262 		<< "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1263 		<< "\n"
1264 		<< "out gl_PerVertex {\n"
1265 		<< "	vec4  gl_Position;\n"
1266 		<< "};\n"
1267 		<< "void main (void)\n"
1268 		<< "{\n"
1269 		<< "	gl_Position					= vs_in_position_ndc;\n"
1270 		<< "	vs_out_pos_screen_centroid	= vs_in_position_screen;\n"
1271 		<< "	vs_out_pos_screen_sample	= vs_in_position_screen;\n"
1272 		<< "}\n";
1273 
1274 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1275 
1276 	// Create fragment shader
1277 	std::ostringstream fs;
1278 
1279 	fs << "#version 440\n"
1280 		<< "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1281 		<< "layout(location = 1) sample   in vec2 fs_in_pos_screen_sample;\n"
1282 		<< "\n"
1283 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1284 		<< "\n"
1285 		<< "void main (void)\n"
1286 		<< "{\n"
1287 		<< "	const float threshold = 0.15625;\n"
1288 		<< "\n"
1289 		<< "	const vec2  pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1290 		<< "	const bool  valuesEqual				   = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
1291 		<< "\n"
1292 		<< "	if (valuesEqual)\n"
1293 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
1294 		<< "	else\n"
1295 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
1296 		<< "}\n";
1297 
1298 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1299 }
1300 
createInstance(Context & context) const1301 TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const
1302 {
1303 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1304 }
1305 
1306 class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase
1307 {
1308 public:
MSCaseInterpolateAtCentroidConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1309 					MSCaseInterpolateAtCentroidConsistency	(tcu::TestContext&		testCtx,
1310 															 const std::string&		name,
1311 															 const ImageMSParams&	imageMSParams)
1312 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1313 
1314 	void			init									(void);
1315 	void			initPrograms							(vk::SourceCollections&	programCollection) const;
1316 	TestInstance*	createInstance							(Context&				context) const;
1317 };
1318 
createMSCaseInterpolateAtCentroidConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1319 MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1320 {
1321 	return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams);
1322 }
1323 
init(void)1324 void MSCaseInterpolateAtCentroidConsistency::init (void)
1325 {
1326 	m_testCtx.getLog()
1327 		<< tcu::TestLog::Message
1328 		<< "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
1329 		<< "	Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
1330 		<< "	=> interpolateAtCentroid(screenSample) = screenCentroid\n"
1331 		<< tcu::TestLog::EndMessage;
1332 
1333 	MSInterpolationCaseBase::init();
1334 }
1335 
initPrograms(vk::SourceCollections & programCollection) const1336 void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const
1337 {
1338 	// Create vertex shader
1339 	std::ostringstream vs;
1340 
1341 	vs << "#version 440\n"
1342 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1343 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1344 		<< "\n"
1345 		<< "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n"
1346 		<< "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n"
1347 		<< "\n"
1348 		<< "out gl_PerVertex {\n"
1349 		<< "	vec4  gl_Position;\n"
1350 		<< "};\n"
1351 		<< "void main (void)\n"
1352 		<< "{\n"
1353 		<< "	gl_Position					= vs_in_position_ndc;\n"
1354 		<< "	vs_out_pos_screen_sample	= vs_in_position_screen;\n"
1355 		<< "	vs_out_pos_screen_centroid	= vs_in_position_screen;\n"
1356 		<< "}\n";
1357 
1358 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1359 
1360 	// Create fragment shader
1361 	std::ostringstream fs;
1362 
1363 	fs << "#version 440\n"
1364 		<< "layout(location = 0) sample   in vec2 fs_in_pos_screen_sample;\n"
1365 		<< "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
1366 		<< "\n"
1367 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1368 		<< "\n"
1369 		<< "void main (void)\n"
1370 		<< "{\n"
1371 		<< "	const float threshold = 0.0005;\n"
1372 		<< "\n"
1373 		<< "	const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n"
1374 		<< "	const bool valuesEqual					= all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
1375 		<< "\n"
1376 		<< "	if (valuesEqual)\n"
1377 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
1378 		<< "	else\n"
1379 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
1380 		<< "}\n";
1381 
1382 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1383 }
1384 
createInstance(Context & context) const1385 TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const
1386 {
1387 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1388 }
1389 
1390 class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase
1391 {
1392 public:
MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1393 					MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext&		testCtx,
1394 														 const std::string&		name,
1395 														 const ImageMSParams&	imageMSParams)
1396 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1397 
1398 	void			init								(void);
1399 	void			initPrograms						(vk::SourceCollections&	programCollection) const;
1400 	TestInstance*	createInstance						(Context&				context) const;
1401 };
1402 
createMSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1403 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1404 {
1405 	return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams);
1406 }
1407 
init(void)1408 void MSCaseInterpolateAtOffsetPixelCenter::init (void)
1409 {
1410 	m_testCtx.getLog()
1411 		<< tcu::TestLog::Message
1412 		<< "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
1413 		<< "	Interpolate varying containing screen space location.\n"
1414 		<< "	=> interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
1415 		<< tcu::TestLog::EndMessage;
1416 
1417 	MSInterpolationCaseBase::init();
1418 }
1419 
initPrograms(vk::SourceCollections & programCollection) const1420 void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const
1421 {
1422 	// Create vertex shader
1423 	std::ostringstream vs;
1424 
1425 	vs << "#version 440\n"
1426 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1427 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1428 		<< "\n"
1429 		<< "layout(location = 0) out vec2 vs_out_pos_screen;\n"
1430 		<< "layout(location = 1) out vec2 vs_out_offset;\n"
1431 		<< "\n"
1432 		<< "out gl_PerVertex {\n"
1433 		<< "	vec4  gl_Position;\n"
1434 		<< "};\n"
1435 		<< "void main (void)\n"
1436 		<< "{\n"
1437 		<< "	gl_Position			= vs_in_position_ndc;\n"
1438 		<< "	vs_out_pos_screen	= vs_in_position_screen;\n"
1439 		<< "	vs_out_offset		= vs_in_position_ndc.xy * 0.5;\n"
1440 		<< "}\n";
1441 
1442 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1443 
1444 	// Create fragment shader
1445 	std::ostringstream fs;
1446 
1447 	fs << "#version 440\n"
1448 		<< "layout(location = 0) in  vec2 fs_in_pos_screen;\n"
1449 		<< "layout(location = 1) in  vec2 fs_in_offset;\n"
1450 		<< "\n"
1451 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1452 		<< "\n"
1453 		<< "void main (void)\n"
1454 		<< "{\n"
1455 		<< "    const vec2  frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
1456 		<< "    const vec2  center_diff = abs(frag_center - fs_in_pos_screen);\n"
1457 		<< "    const float threshold   = 0.125;\n"
1458 		<< "    bool        valuesEqual = false;\n"
1459 		<< "\n"
1460 		<< "    if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
1461 		<< "        const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
1462 		<< "        const vec2 reference_value            = frag_center + fs_in_offset;\n"
1463 		<< "\n"
1464 		<< "        valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
1465 		<< "    }\n"
1466 		<< "\n"
1467 		<< "    if (valuesEqual)\n"
1468 		<< "        fs_out_color = vec2(0.0, 1.0);\n"
1469 		<< "    else\n"
1470 		<< "        fs_out_color = vec2(1.0, 0.0);\n"
1471 		<< "}\n";
1472 
1473 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1474 }
1475 
createInstance(Context & context) const1476 TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const
1477 {
1478 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1479 }
1480 
1481 class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase
1482 {
1483 public:
MSCaseInterpolateAtOffsetSamplePosition(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1484 					MSCaseInterpolateAtOffsetSamplePosition	(tcu::TestContext&		testCtx,
1485 															 const std::string&		name,
1486 															 const ImageMSParams&	imageMSParams)
1487 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1488 
1489 	void			init									(void);
1490 	void			initPrograms							(vk::SourceCollections&	programCollection) const;
1491 	TestInstance*	createInstance							(Context&				context) const;
1492 };
1493 
createMSCaseInterpolateAtOffsetSamplePosition(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1494 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1495 {
1496 	return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams);
1497 }
1498 
init(void)1499 void MSCaseInterpolateAtOffsetSamplePosition::init (void)
1500 {
1501 	m_testCtx.getLog()
1502 		<< tcu::TestLog::Message
1503 		<< "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
1504 		<< "similar to screen position interpolated at sample.\n"
1505 		<< "	Interpolate varying containing screen space location with and without sample qualifier.\n"
1506 		<< "	=> interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
1507 		<< tcu::TestLog::EndMessage;
1508 
1509 	MSInterpolationCaseBase::init();
1510 }
1511 
initPrograms(vk::SourceCollections & programCollection) const1512 void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const
1513 {
1514 	// Create vertex shader
1515 	std::ostringstream vs;
1516 
1517 	vs << "#version 440\n"
1518 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1519 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
1520 		<< "\n"
1521 		<< "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
1522 		<< "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1523 		<< "\n"
1524 		<< "out gl_PerVertex {\n"
1525 		<< "	vec4  gl_Position;\n"
1526 		<< "};\n"
1527 		<< "void main (void)\n"
1528 		<< "{\n"
1529 		<< "	gl_Position					= vs_in_position_ndc;\n"
1530 		<< "	vs_out_pos_screen_fragment	= vs_in_position_screen;\n"
1531 		<< "	vs_out_pos_screen_sample	= vs_in_position_screen;\n"
1532 		<< "}\n";
1533 
1534 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1535 
1536 	// Create fragment shader
1537 	std::ostringstream fs;
1538 
1539 	fs << "#version 440\n"
1540 		<< "layout(location = 0)		in vec2 fs_in_pos_screen_fragment;\n"
1541 		<< "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
1542 		<< "\n"
1543 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1544 		<< "\n"
1545 		<< "void main (void)\n"
1546 		<< "{\n"
1547 		<< "	const float threshold = 0.15625;\n"
1548 		<< "\n"
1549 		<< "	const vec2 offset					  = gl_SamplePosition - vec2(0.5, 0.5);\n"
1550 		<< "	const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
1551 		<< "	const bool valuesEqual				  = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
1552 		<< "\n"
1553 		<< "	if (valuesEqual)\n"
1554 		<< "		fs_out_color = vec2(0.0, 1.0);\n"
1555 		<< "	else\n"
1556 		<< "		fs_out_color = vec2(1.0, 0.0);\n"
1557 		<< "}\n";
1558 
1559 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1560 }
1561 
createInstance(Context & context) const1562 TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const
1563 {
1564 	return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1565 }
1566 
1567 class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase
1568 {
1569 public:
MSInstanceInterpolateBarycentricCoordinates(Context & context,const ImageMSParams & imageMSParams)1570 					MSInstanceInterpolateBarycentricCoordinates	(Context&				context,
1571 																 const ImageMSParams&	imageMSParams)
1572 	: MSInterpolationInstanceBase(context, imageMSParams) {}
1573 
1574 	VertexDataDesc	getVertexDataDescripton						(void) const;
1575 	void			uploadVertexData							(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
1576 	tcu::TestStatus	verifyResolvedImage							(const tcu::ConstPixelBufferAccess&	imageData) const;
1577 
1578 protected:
1579 	struct VertexData
1580 	{
VertexDatavkt::pipeline::multisample::MSInstanceInterpolateBarycentricCoordinates::VertexData1581 		VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
1582 
1583 		tcu::Vec4 positionNdc;
1584 		tcu::Vec3 barycentricCoord;
1585 	};
1586 };
1587 
getVertexDataDescripton(void) const1588 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const
1589 {
1590 	VertexDataDesc vertexDataDesc;
1591 
1592 	vertexDataDesc.verticesCount		= 3u;
1593 	vertexDataDesc.dataStride			= sizeof(VertexData);
1594 	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1595 	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1596 
1597 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1598 	{
1599 		0u,											// deUint32	location;
1600 		0u,											// deUint32	binding;
1601 		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
1602 		DE_OFFSET_OF(VertexData, positionNdc),		// deUint32	offset;
1603 	};
1604 
1605 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1606 
1607 	const VkVertexInputAttributeDescription vertexAttrBarCoord =
1608 	{
1609 		1u,											// deUint32	location;
1610 		0u,											// deUint32	binding;
1611 		VK_FORMAT_R32G32B32_SFLOAT,					// VkFormat	format;
1612 		DE_OFFSET_OF(VertexData, barycentricCoord),	// deUint32	offset;
1613 	};
1614 
1615 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
1616 
1617 	return vertexDataDesc;
1618 }
1619 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const1620 void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1621 {
1622 	// Create buffer storing vertex data
1623 	std::vector<VertexData> vertices;
1624 
1625 	vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
1626 	vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
1627 	vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
1628 
1629 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1630 }
1631 
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const1632 tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1633 {
1634 	for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1635 	for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1636 	for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1637 	{
1638 		const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1639 
1640 		if (firstComponent > 0)
1641 			return tcu::TestStatus::fail("Failed");
1642 	}
1643 
1644 	return tcu::TestStatus::pass("Passed");
1645 }
1646 
1647 class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase
1648 {
1649 public:
MSCaseCentroidQualifierInsidePrimitive(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1650 					MSCaseCentroidQualifierInsidePrimitive	(tcu::TestContext&		testCtx,
1651 															 const std::string&		name,
1652 															 const ImageMSParams&	imageMSParams)
1653 	: MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1654 
1655 	void			init									(void);
1656 	void			initPrograms							(vk::SourceCollections&	programCollection) const;
1657 	TestInstance*	createInstance							(Context&				context) const;
1658 };
1659 
createMSCaseCentroidQualifierInsidePrimitive(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1660 MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1661 {
1662 	return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams);
1663 }
1664 
init(void)1665 void MSCaseCentroidQualifierInsidePrimitive::init (void)
1666 {
1667 	m_testCtx.getLog()
1668 		<< tcu::TestLog::Message
1669 		<< "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
1670 		<< "	Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
1671 		<< "	=> After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
1672 		<< tcu::TestLog::EndMessage;
1673 
1674 	MSInterpolationCaseBase::init();
1675 }
1676 
initPrograms(vk::SourceCollections & programCollection) const1677 void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const
1678 {
1679 	// Create vertex shader
1680 	std::ostringstream vs;
1681 
1682 	vs << "#version 440\n"
1683 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1684 		<< "layout(location = 1) in vec3 vs_in_barCoord;\n"
1685 		<< "\n"
1686 		<< "layout(location = 0) out vec3 vs_out_barCoord;\n"
1687 		<< "\n"
1688 		<< "out gl_PerVertex {\n"
1689 		<< "	vec4  gl_Position;\n"
1690 		<< "};\n"
1691 		<< "void main (void)\n"
1692 		<< "{\n"
1693 		<< "	gl_Position		= vs_in_position_ndc;\n"
1694 		<< "	vs_out_barCoord = vs_in_barCoord;\n"
1695 		<< "}\n";
1696 
1697 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1698 
1699 	// Create fragment shader
1700 	std::ostringstream fs;
1701 
1702 	fs << "#version 440\n"
1703 		<< "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
1704 		<< "\n"
1705 		<< "layout(location = 0) out vec2 fs_out_color;\n"
1706 		<< "\n"
1707 		<< "void main (void)\n"
1708 		<< "{\n"
1709 		<< "	if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1710 		<< "			fs_out_color = vec2(0.0, 1.0);\n"
1711 		<< "	else\n"
1712 		<< "			fs_out_color = vec2(1.0, 0.0);\n"
1713 		<< "}\n";
1714 
1715 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1716 }
1717 
createInstance(Context & context) const1718 TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const
1719 {
1720 	return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams);
1721 }
1722 
1723 } // multisample
1724 
makeGroup(multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,tcu::TestContext & testCtx,const std::string groupName,const tcu::UVec3 imageSizes[],const deUint32 imageSizesElemCount,const vk::VkSampleCountFlagBits imageSamples[],const deUint32 imageSamplesElemCount)1725 tcu::TestCaseGroup* makeGroup(	multisample::MSInterpolationCaseFuncPtr	createCaseFuncPtr,
1726 								tcu::TestContext&						testCtx,
1727 								const std::string						groupName,
1728 								const tcu::UVec3						imageSizes[],
1729 								const deUint32							imageSizesElemCount,
1730 								const vk::VkSampleCountFlagBits			imageSamples[],
1731 								const deUint32							imageSamplesElemCount)
1732 {
1733 	de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
1734 
1735 	for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
1736 	{
1737 		const tcu::UVec3	imageSize = imageSizes[imageSizeNdx];
1738 		std::ostringstream	imageSizeStream;
1739 
1740 		imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1741 
1742 		de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1743 
1744 		for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
1745 		{
1746 			const vk::VkSampleCountFlagBits		samples			= imageSamples[imageSamplesNdx];
1747 			const multisample::ImageMSParams	imageMSParams	= multisample::ImageMSParams(samples, imageSize);
1748 
1749 			sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams));
1750 		}
1751 
1752 		caseGroup->addChild(sizeGroup.release());
1753 	}
1754 	return caseGroup.release();
1755 }
1756 
createMultisampleInterpolationTests(tcu::TestContext & testCtx)1757 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
1758 {
1759 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
1760 
1761 	const tcu::UVec3 imageSizes[] =
1762 	{
1763 		tcu::UVec3(128u, 128u, 1u),
1764 		tcu::UVec3(137u, 191u, 1u),
1765 	};
1766 
1767 	const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1768 
1769 	const vk::VkSampleCountFlagBits imageSamples[] =
1770 	{
1771 		vk::VK_SAMPLE_COUNT_2_BIT,
1772 		vk::VK_SAMPLE_COUNT_4_BIT,
1773 		vk::VK_SAMPLE_COUNT_8_BIT,
1774 		vk::VK_SAMPLE_COUNT_16_BIT,
1775 		vk::VK_SAMPLE_COUNT_32_BIT,
1776 		vk::VK_SAMPLE_COUNT_64_BIT,
1777 	};
1778 
1779 	const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1780 
1781 	de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", ""));
1782 
1783 	for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1784 	{
1785 		const tcu::UVec3	imageSize = imageSizes[imageSizeNdx];
1786 		std::ostringstream	imageSizeStream;
1787 
1788 		imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1789 
1790 		de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1791 
1792 		sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize));
1793 
1794 		caseGroup->addChild(sizeGroup.release());
1795 	}
1796 
1797 	testGroup->addChild(caseGroup.release());
1798 
1799 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues,	testCtx, "sample_interpolate_at_distinct_values",	imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1800 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid,	testCtx, "sample_interpolate_at_ignores_centroid",	imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1801 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency,		testCtx, "sample_interpolate_at_consistency",		imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1802 	testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues,		testCtx, "sample_qualifier_distinct_values",		imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1803 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency,	testCtx, "centroid_interpolate_at_consistency",		imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1804 	testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive,	testCtx, "centroid_qualifier_inside_primitive",		imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1805 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter,		testCtx, "offset_interpolate_at_pixel_center",		imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1806 	testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition,	testCtx, "offset_interpolate_at_sample_position",	imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1807 
1808 	return testGroup.release();
1809 }
1810 
1811 } // pipeline
1812 } // vkt
1813