• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Advanced Micro Devices, Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for VK_AMD_mixed_attachment_samples
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp"
26 #include "vktPipelineSampleLocationsUtil.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktTestGroupUtil.hpp"
31 
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkImageUtil.hpp"
42 
43 #include "deUniquePtr.hpp"
44 #include "deSharedPtr.hpp"
45 #include "deRandom.hpp"
46 #include "deMath.h"
47 
48 #include "tcuVector.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuImageCompare.hpp"
51 #include "tcuTextureUtil.hpp"
52 #include "tcuRGBA.hpp"
53 
54 #include <string>
55 #include <vector>
56 
57 namespace vkt
58 {
59 namespace pipeline
60 {
61 namespace
62 {
63 using namespace vk;
64 using de::UniquePtr;
65 using de::MovePtr;
66 using de::SharedPtr;
67 using tcu::UVec2;
68 using tcu::Vec2;
69 using tcu::Vec4;
70 
compareGreenImage(tcu::TestLog & log,const char * name,const char * description,const tcu::ConstPixelBufferAccess & image)71 bool compareGreenImage (tcu::TestLog& log, const char* name, const char* description, const tcu::ConstPixelBufferAccess& image)
72 {
73 	tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight());
74 	tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec());
75 	return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u), tcu::COMPARE_LOG_RESULT);
76 }
77 
getImageAspectFlags(const VkFormat format)78 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
79 {
80 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
81 
82 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
83 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
84 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
85 
86 	DE_ASSERT(false);
87 	return 0u;
88 }
89 
90 struct CompareData
91 {
92 	Vec4		color;
93 	float		depth;
94 	deUint32	stencil;
95 
96 	// Pad to 2*16 bytes, in the shader the base alignment of this structure is 16 due to vec4
97 	deUint32	padding[2];
98 
CompareDatavkt::pipeline::__anonc89cd22b0111::CompareData99 	CompareData() : color(Vec4(0.0f)), depth(0.0f), stencil(0u)
100 	{
101 		padding[0] = 0u;
102 		padding[1] = 0u;
103 
104 		static_assert(sizeof(CompareData) == (2 * 16), "Wrong structure size, expected 16 bytes");
105 	}
106 };
107 
108 //! Make a dummy sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)109 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
110 {
111 	const VkSamplerCreateInfo samplerParams =
112 	{
113 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType         sType;
114 		DE_NULL,										// const void*             pNext;
115 		(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags    flags;
116 		VK_FILTER_NEAREST,								// VkFilter                magFilter;
117 		VK_FILTER_NEAREST,								// VkFilter                minFilter;
118 		VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipmapMode     mipmapMode;
119 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeU;
120 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeV;
121 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeW;
122 		0.0f,											// float                   mipLodBias;
123 		VK_FALSE,										// VkBool32                anisotropyEnable;
124 		1.0f,											// float                   maxAnisotropy;
125 		VK_FALSE,										// VkBool32                compareEnable;
126 		VK_COMPARE_OP_ALWAYS,							// VkCompareOp             compareOp;
127 		0.0f,											// float                   minLod;
128 		0.0f,											// float                   maxLod;
129 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor           borderColor;
130 		VK_FALSE,										// VkBool32                unnormalizedCoordinates;
131 	};
132 	return createSampler(vk, device, &samplerParams);
133 }
134 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)135 Move<VkImage> makeImage (const DeviceInterface&			vk,
136 						 const VkDevice					device,
137 						 const VkFormat					format,
138 						 const UVec2&					size,
139 						 const VkSampleCountFlagBits	samples,
140 						 const VkImageUsageFlags		usage)
141 {
142 	const VkImageCreateInfo imageParams =
143 	{
144 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
145 		DE_NULL,										// const void*				pNext;
146 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
147 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
148 		format,											// VkFormat					format;
149 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
150 		1u,												// deUint32					mipLevels;
151 		1u,												// deUint32					arrayLayers;
152 		samples,										// VkSampleCountFlagBits	samples;
153 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
154 		usage,											// VkImageUsageFlags		usage;
155 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
156 		0u,												// deUint32					queueFamilyIndexCount;
157 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
158 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
159 	};
160 	return createImage(vk, device, &imageParams);
161 }
162 
isDepthFormat(const VkFormat format)163 inline bool isDepthFormat (const VkFormat format)
164 {
165 	return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
166 }
167 
isStencilFormat(const VkFormat format)168 inline bool isStencilFormat (const VkFormat format)
169 {
170 	return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
171 }
172 
173 //! Create a test-specific MSAA pipeline
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const bool useVertexInput,const deUint32 subpassNdx,const UVec2 & renderSize,const VkImageAspectFlags depthStencilAspect,const VkSampleCountFlagBits numSamples,const bool sampleShadingEnable,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)174 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&					vk,
175 									   const VkDevice							device,
176 									   const VkPipelineLayout					pipelineLayout,
177 									   const VkRenderPass						renderPass,
178 									   const VkShaderModule						vertexModule,
179 									   const VkShaderModule						fragmentModule,
180 									   const bool								useVertexInput,
181 									   const deUint32							subpassNdx,
182 									   const UVec2&								renderSize,
183 									   const VkImageAspectFlags					depthStencilAspect,	//!< Used to determine which D/S tests to turn on
184 									   const VkSampleCountFlagBits				numSamples,
185 									   const bool								sampleShadingEnable,
186 									   const VkSampleLocationsInfoEXT*			pSampleLocationsInfo = DE_NULL)
187 {
188 	std::vector<VkVertexInputBindingDescription>	vertexInputBindingDescriptions;
189 	std::vector<VkVertexInputAttributeDescription>	vertexInputAttributeDescriptions;
190 
191 	// Vertex attributes: position and color
192 	if (useVertexInput)
193 	{
194 		vertexInputBindingDescriptions.push_back  (makeVertexInputBindingDescription  (0u, 2 * sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX));
195 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
196 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(Vec4)));
197 	}
198 
199 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
200 	{
201 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
202 		DE_NULL,														// const void*								pNext;
203 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
204 		static_cast<deUint32>(vertexInputBindingDescriptions.size()),	// uint32_t									vertexBindingDescriptionCount;
205 		dataOrNullPtr(vertexInputBindingDescriptions),					// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
206 		static_cast<deUint32>(vertexInputAttributeDescriptions.size()),	// uint32_t									vertexAttributeDescriptionCount;
207 		dataOrNullPtr(vertexInputAttributeDescriptions),				// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
208 	};
209 
210 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
211 	{
212 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
213 		DE_NULL,														// const void*								pNext;
214 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
215 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
216 		VK_FALSE,														// VkBool32									primitiveRestartEnable;
217 	};
218 
219 	const VkViewport viewport =
220 	{
221 		0.0f, 0.0f,																	// x, y
222 		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),		// widht, height
223 		0.0f, 1.0f																	// minDepth, maxDepth
224 	};
225 
226 	const VkRect2D scissor =
227 	{
228 		makeOffset2D(0, 0),
229 		makeExtent2D(renderSize.x(), renderSize.y()),
230 	};
231 
232 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
233 	{
234 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
235 		DE_NULL,														// const void*							pNext;
236 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags	flags;
237 		1u,																// uint32_t								viewportCount;
238 		&viewport,														// const VkViewport*					pViewports;
239 		1u,																// uint32_t								scissorCount;
240 		&scissor,														// const VkRect2D*						pScissors;
241 	};
242 
243 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
244 	{
245 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
246 		DE_NULL,													// const void*								pNext;
247 		(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
248 		VK_FALSE,													// VkBool32									depthClampEnable;
249 		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
250 		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
251 		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
252 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
253 		VK_FALSE,													// VkBool32									depthBiasEnable;
254 		0.0f,														// float									depthBiasConstantFactor;
255 		0.0f,														// float									depthBiasClamp;
256 		0.0f,														// float									depthBiasSlopeFactor;
257 		1.0f,														// float									lineWidth;
258 	};
259 
260 	VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo =
261 	{
262 		VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,	// VkStructureType             sType;
263 		DE_NULL,															// const void*                 pNext;
264 		VK_TRUE,															// VkBool32                    sampleLocationsEnable;
265 		VkSampleLocationsInfoEXT(),											// VkSampleLocationsInfoEXT    sampleLocationsInfo;
266 	};
267 
268 	VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
269 	{
270 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
271 		DE_NULL,													// const void*								pNext;
272 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
273 		numSamples,													// VkSampleCountFlagBits					rasterizationSamples;
274 		sampleShadingEnable,										// VkBool32									sampleShadingEnable;
275 		1.0f,														// float									minSampleShading;
276 		DE_NULL,													// const VkSampleMask*						pSampleMask;
277 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
278 		VK_FALSE													// VkBool32									alphaToOneEnable;
279 	};
280 
281 	if (pSampleLocationsInfo)
282 	{
283 		pipelineSampleLocationsCreateInfo.sampleLocationsInfo	= *pSampleLocationsInfo;
284 		pipelineMultisampleStateInfo.pNext						= &pipelineSampleLocationsCreateInfo;
285 	}
286 
287 	// Simply increment the buffer
288 	const VkStencilOpState stencilOpState = makeStencilOpState(
289 		VK_STENCIL_OP_KEEP,						// stencil fail
290 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,		// depth & stencil pass
291 		VK_STENCIL_OP_KEEP,						// depth only fail
292 		VK_COMPARE_OP_ALWAYS,					// compare op
293 		~0u,									// compare mask
294 		~0u,									// write mask
295 		0u);									// reference
296 
297 	// Always pass the depth test
298 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
299 	{
300 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
301 		DE_NULL,													// const void*								pNext;
302 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
303 		(depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0u,		// VkBool32									depthTestEnable;
304 		VK_TRUE,													// VkBool32									depthWriteEnable;
305 		VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
306 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
307 		(depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u,	// VkBool32									stencilTestEnable;
308 		stencilOpState,												// VkStencilOpState							front;
309 		stencilOpState,												// VkStencilOpState							back;
310 		0.0f,														// float									minDepthBounds;
311 		1.0f,														// float									maxDepthBounds;
312 	};
313 
314 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
315 	const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState =
316 	{
317 		VK_FALSE,				// VkBool32					blendEnable;
318 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcColorBlendFactor;
319 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
320 		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
321 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcAlphaBlendFactor;
322 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
323 		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
324 		colorComponentsAll,		// VkColorComponentFlags	colorWriteMask;
325 	};
326 
327 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
328 	{
329 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
330 		DE_NULL,													// const void*									pNext;
331 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
332 		VK_FALSE,													// VkBool32										logicOpEnable;
333 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
334 		1u,															// deUint32										attachmentCount;
335 		&defaultBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
336 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
337 	};
338 
339 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
340 	{
341 		{
342 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
343 			DE_NULL,												// const void*							pNext;
344 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
345 			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
346 			vertexModule,											// VkShaderModule						module;
347 			"main",													// const char*							pName;
348 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
349 		},
350 		{
351 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
352 			DE_NULL,												// const void*							pNext;
353 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
354 			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
355 			fragmentModule,											// VkShaderModule						module;
356 			"main",													// const char*							pName;
357 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
358 		}
359 	};
360 
361 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
362 	{
363 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
364 		DE_NULL,											// const void*										pNext;
365 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
366 		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
367 		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
368 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
369 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
370 		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
371 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
372 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
373 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
374 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
375 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
376 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
377 		pipelineLayout,										// VkPipelineLayout									layout;
378 		renderPass,											// VkRenderPass										renderPass;
379 		subpassNdx,											// deUint32											subpass;
380 		DE_NULL,											// VkPipeline										basePipelineHandle;
381 		-1,													// deInt32											basePipelineIndex;
382 	};
383 
384 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
385 }
386 
387 //! Wrap float after an increment
wrapIncFloat(float a,float min,float max)388 inline float wrapIncFloat (float a, float min, float max)
389 {
390 	return deFloatMax(min, deFloatMod(a, max));
391 }
392 
393 //! Generate expected data for color, depth, and stencil samples of a given image.
394 //! Samples are ordered starting at pixel (0, 0) - see compute shader source for reference.
generateCompareData(const deUint32 seed,const UVec2 & imageSize,const deUint32 numCoverageSamples,const deUint32 numColorSamples,const deUint32 numDepthStencilSamples)395 std::vector<CompareData> generateCompareData (const deUint32	seed,
396 											  const UVec2&		imageSize,
397 											  const deUint32	numCoverageSamples,
398 											  const deUint32	numColorSamples,
399 											  const deUint32	numDepthStencilSamples)
400 {
401 	std::vector<CompareData>	allData;
402 	de::Random					rng (seed);
403 
404 	for (deUint32 y		 = 0u; y	  < imageSize.y();		++y)
405 	for (deUint32 x		 = 0u; x	  < imageSize.x();		++x)
406 	for (deUint32 sample = 0u; sample < numCoverageSamples; ++sample)
407 	{
408 		CompareData cd;
409 
410 		if (sample < numColorSamples)
411 		{
412 			for (int i = 0; i < 3; ++i)
413 				cd.color[i]	= 0.1f * static_cast<float>(rng.getInt(1, 10));
414 
415 			cd.color.w() = 1.0f;
416 		}
417 
418 		if (sample < numDepthStencilSamples)
419 		{
420 			const deUint32 globalSample = sample + numColorSamples * (x + imageSize.x() * y);
421 			cd.depth	= wrapIncFloat(0.05f * static_cast<float>(1 + globalSample), 0.05f, 1.0f);
422 			cd.stencil	= 1 + globalSample % numCoverageSamples;
423 		}
424 
425 		allData.push_back(cd);
426 	}
427 
428 	return allData;
429 }
430 
431 //! NDC transformation algorithm for sample locations
432 template<typename SampleAccessor>
ndcTransformEachSampleInPixel(const UVec2 & framebufferSize,const deUint32 numSamplesPerPixel,const SampleAccessor & access)433 std::vector<Vec2> ndcTransformEachSampleInPixel (const UVec2& framebufferSize, const deUint32 numSamplesPerPixel, const SampleAccessor& access)
434 {
435 	std::vector<Vec2> locations;
436 
437 	for (deUint32 y			= 0; y			< framebufferSize.y();	++y)
438 	for (deUint32 x			= 0; x			< framebufferSize.x();	++x)
439 	for (deUint32 sampleNdx	= 0; sampleNdx	< numSamplesPerPixel;	++sampleNdx)
440 	{
441 		const Vec2& sp = access(x, y, sampleNdx);
442 		const float	globalX  = sp.x() + static_cast<float>(x);
443 		const float	globalY  = sp.y() + static_cast<float>(y);
444 
445 		// Transform to [-1, 1] space
446 		locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())),
447 								 -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y()))));
448 	}
449 
450 	return locations;
451 }
452 
453 class AccessStandardSampleLocationsArray
454 {
455 public:
AccessStandardSampleLocationsArray(const Vec2 * ptr)456 	AccessStandardSampleLocationsArray (const Vec2* ptr) : m_pData (ptr) {}
457 
operator ()(const deUint32 x,const deUint32 y,const deUint32 sampleNdx) const458 	const Vec2& operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const
459 	{
460 		DE_UNREF(x);
461 		DE_UNREF(y);
462 		return m_pData[sampleNdx];
463 	}
464 
465 private:
466 	const Vec2*	m_pData;
467 };
468 
469 class AccessMultisamplePixelGrid
470 {
471 public:
AccessMultisamplePixelGrid(const MultisamplePixelGrid * ptr)472 	AccessMultisamplePixelGrid (const MultisamplePixelGrid* ptr) : m_pGrid (ptr) {}
473 
operator ()(const deUint32 x,const deUint32 y,const deUint32 sampleNdx) const474 	Vec2 operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const
475 	{
476 		const VkSampleLocationEXT& sp = m_pGrid->getSample(x, y, sampleNdx);
477 		return Vec2(sp.x, sp.y);
478 	}
479 
480 private:
481 	const MultisamplePixelGrid*	m_pGrid;
482 };
483 
484 //! Generate NDC space standard sample locations at each framebuffer pixel
485 //! Data is filled starting at pixel (0,0) and for each pixel there are numSamples samples
genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples,const UVec2 & framebufferSize)486 std::vector<Vec2> genFramebufferStandardSampleLocations (const VkSampleCountFlagBits numSamples, const UVec2& framebufferSize)
487 {
488 	static const Vec2 s_location_samples_1[] =
489 	{
490 		Vec2(0.5f, 0.5f),
491 	};
492 	static const Vec2 s_location_samples_2[] =
493 	{
494 		Vec2(0.75f, 0.75f),
495 		Vec2(0.25f, 0.25f),
496 	};
497 	static const Vec2 s_location_samples_4[] =
498 	{
499 		Vec2(0.375f, 0.125f),
500 		Vec2(0.875f, 0.375f),
501 		Vec2(0.125f, 0.625f),
502 		Vec2(0.625f, 0.875f),
503 	};
504 	static const Vec2 s_location_samples_8[] =
505 	{
506 		Vec2(0.5625f, 0.3125f),
507 		Vec2(0.4375f, 0.6875f),
508 		Vec2(0.8125f, 0.5625f),
509 		Vec2(0.3125f, 0.1875f),
510 		Vec2(0.1875f, 0.8125f),
511 		Vec2(0.0625f, 0.4375f),
512 		Vec2(0.6875f, 0.9375f),
513 		Vec2(0.9375f, 0.0625f),
514 	};
515 	static const Vec2 s_location_samples_16[] =
516 	{
517 		Vec2(0.5625f, 0.5625f),
518 		Vec2(0.4375f, 0.3125f),
519 		Vec2(0.3125f, 0.6250f),
520 		Vec2(0.7500f, 0.4375f),
521 		Vec2(0.1875f, 0.3750f),
522 		Vec2(0.6250f, 0.8125f),
523 		Vec2(0.8125f, 0.6875f),
524 		Vec2(0.6875f, 0.1875f),
525 		Vec2(0.3750f, 0.8750f),
526 		Vec2(0.5000f, 0.0625f),
527 		Vec2(0.2500f, 0.1250f),
528 		Vec2(0.1250f, 0.7500f),
529 		Vec2(0.0000f, 0.5000f),
530 		Vec2(0.9375f, 0.2500f),
531 		Vec2(0.8750f, 0.9375f),
532 		Vec2(0.0625f, 0.0000f),
533 	};
534 
535 	const Vec2*	pSampleLocation = DE_NULL;
536 
537 	switch (numSamples)
538 	{
539 		case VK_SAMPLE_COUNT_1_BIT:		pSampleLocation = s_location_samples_1;		break;
540 		case VK_SAMPLE_COUNT_2_BIT:		pSampleLocation = s_location_samples_2;		break;
541 		case VK_SAMPLE_COUNT_4_BIT:		pSampleLocation = s_location_samples_4;		break;
542 		case VK_SAMPLE_COUNT_8_BIT:		pSampleLocation = s_location_samples_8;		break;
543 		case VK_SAMPLE_COUNT_16_BIT:	pSampleLocation = s_location_samples_16;	break;
544 
545 		default:
546 			DE_ASSERT(0);
547 			return std::vector<Vec2>();
548 	}
549 
550 	return ndcTransformEachSampleInPixel(framebufferSize, static_cast<deUint32>(numSamples), AccessStandardSampleLocationsArray(pSampleLocation));
551 }
552 
553 //! Generate NDC space custom sample locations at each framebuffer pixel, based on the given pixel grid
getSampleLocations(const MultisamplePixelGrid & pixelGrid,const UVec2 & framebufferSize)554 std::vector<Vec2> getSampleLocations (const MultisamplePixelGrid& pixelGrid, const UVec2& framebufferSize)
555 {
556 	return ndcTransformEachSampleInPixel(framebufferSize, pixelGrid.samplesPerPixel(), AccessMultisamplePixelGrid(&pixelGrid));
557 }
558 
559 struct PositionColor
560 {
561 	tcu::Vec4	position;
562 	tcu::Vec4	color;
563 
PositionColorvkt::pipeline::__anonc89cd22b0111::PositionColor564 	PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos), color(col) {}
565 };
566 
567 //! Generate subpixel triangles containing the sample position, based on compare data.
568 //! Stencil values are created by overlapping triangles, so the stencil pipeline state must be set up accordingly.
generateSubpixelTriangles(const UVec2 & renderSize,const std::vector<CompareData> & compareData,const std::vector<Vec2> & sampleLocations)569 std::vector<PositionColor> generateSubpixelTriangles (const UVec2&						renderSize,
570 													  const std::vector<CompareData>&	compareData,
571 													  const std::vector<Vec2>&			sampleLocations)
572 {
573 	std::vector<PositionColor>	vertices;
574 
575 	// For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it.
576 	// NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution.
577 	const Vec2			pixelSize	= Vec2(2.0f) / renderSize.cast<float>();
578 	const Vec2			offset		= pixelSize / 16.0f;	// 4 bits precision
579 
580 	// Surround with a roughly centered triangle
581 	const float y1 = 0.5f  * offset.y();
582 	const float y2 = 0.35f * offset.y();
583 	const float x1 = 0.5f  * offset.x();
584 
585 	DE_ASSERT(compareData.size() == sampleLocations.size());
586 
587 	for (std::size_t globalSampleNdx = 0; globalSampleNdx < sampleLocations.size(); ++globalSampleNdx)
588 	{
589 		const Vec2&			loc	= sampleLocations[globalSampleNdx];
590 		const CompareData&	cd	= compareData	 [globalSampleNdx];
591 
592 		// Overdraw at the same position to get the desired stencil
593 		// Draw at least once, if stencil is 0
594 		for (deUint32 i = 0; i < deMaxu32(1u, cd.stencil); ++i)
595 		{
596 			vertices.push_back(PositionColor(Vec4(loc.x(),      loc.y() - y1, cd.depth, 1.0f), cd.color));
597 			vertices.push_back(PositionColor(Vec4(loc.x() - x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
598 			vertices.push_back(PositionColor(Vec4(loc.x() + x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
599 		}
600 	}
601 
602 	return vertices;
603 }
604 
reportSampleError(tcu::TestLog & log,const std::string & sampleDesc,UVec2 & renderSize,const deUint32 numCoverageSamples,const deUint32 globalSampleNdx)605 void reportSampleError (tcu::TestLog& log, const std::string& sampleDesc, UVec2& renderSize, const deUint32 numCoverageSamples, const deUint32 globalSampleNdx)
606 {
607 	const deUint32 pixelNdx	= globalSampleNdx / numCoverageSamples;
608 	const deUint32 x		= pixelNdx % renderSize.x();
609 	const deUint32 y		= pixelNdx / renderSize.x();
610 	const deUint32 sample	= globalSampleNdx % numCoverageSamples;
611 
612 	log << tcu::TestLog::Message << "Incorrect " << sampleDesc << " sample (" << sample << ") at pixel (" << x << ", " << y << ")" << tcu::TestLog::EndMessage;
613 }
614 
checkSampleRequirements(Context & context,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const bool requireStandardSampleLocations)615 void checkSampleRequirements (Context&						context,
616 							  const VkSampleCountFlagBits	numColorSamples,
617 							  const VkSampleCountFlagBits	numDepthStencilSamples,
618 							  const bool					requireStandardSampleLocations)
619 {
620 	const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
621 
622 	if ((limits.framebufferColorSampleCounts & numColorSamples) == 0u)
623 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
624 
625 	if ((limits.framebufferDepthSampleCounts & numDepthStencilSamples) == 0u)
626 		TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported");
627 
628 	if ((limits.framebufferStencilSampleCounts & numDepthStencilSamples) == 0u)
629 		TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported");
630 
631 	if ((limits.sampledImageColorSampleCounts & numColorSamples) == 0u)
632 		TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
633 
634 	if ((limits.sampledImageDepthSampleCounts & numDepthStencilSamples) == 0u)
635 		TCU_THROW(NotSupportedError, "sampledImageDepthSampleCounts: sample count not supported");
636 
637 	if ((limits.sampledImageStencilSampleCounts & numDepthStencilSamples) == 0u)
638 		TCU_THROW(NotSupportedError, "sampledImageStencilSampleCounts: sample count not supported");
639 
640 	// This is required to output geometry that is covering a specific sample
641 	if (requireStandardSampleLocations && !limits.standardSampleLocations)
642 		TCU_THROW(NotSupportedError, "standardSampleLocations: not supported");
643 }
644 
checkImageRequirements(Context & context,const VkFormat format,const VkFormatFeatureFlags requiredFeatureFlags,const VkImageUsageFlags requiredUsageFlags,const VkSampleCountFlagBits requiredSampleCount=VK_SAMPLE_COUNT_1_BIT)645 void checkImageRequirements (Context&						context,
646 							 const VkFormat					format,
647 							 const VkFormatFeatureFlags		requiredFeatureFlags,
648 							 const VkImageUsageFlags		requiredUsageFlags,
649 							 const VkSampleCountFlagBits	requiredSampleCount = VK_SAMPLE_COUNT_1_BIT)
650 {
651 	const InstanceInterface&	vki				= context.getInstanceInterface();
652 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
653 	VkImageFormatProperties		imageProperties;
654 
655 	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
656 
657 	if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags)
658 		TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str());
659 
660 	const VkResult result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, requiredUsageFlags, (VkImageCreateFlags)0, &imageProperties);
661 
662 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
663 		TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str());
664 
665 	if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount)
666 		TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str());
667 }
668 
669 //! Used after a render pass color output (draw or resolve)
recordCopyOutputImageToBuffer(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const UVec2 & imageSize,const VkImage srcImage,const VkBuffer dstBuffer)670 void recordCopyOutputImageToBuffer (const DeviceInterface&	vk,
671 									const VkCommandBuffer	cmdBuffer,
672 									const UVec2&			imageSize,
673 									const VkImage			srcImage,
674 									const VkBuffer			dstBuffer)
675 {
676 	// Image read barrier after color output
677 	{
678 		const VkImageMemoryBarrier barrier =
679 		{
680 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
681 			DE_NULL,																// const void*                pNext;
682 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              srcAccessMask;
683 			VK_ACCESS_TRANSFER_READ_BIT,											// VkAccessFlags              dstAccessMask;
684 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,									// VkImageLayout              oldLayout;
685 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,									// VkImageLayout              newLayout;
686 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
687 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
688 			srcImage,																// VkImage                    image;
689 			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u),	// VkImageSubresourceRange    subresourceRange;
690 		};
691 
692 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
693 	}
694 	// Resolve image -> host buffer
695 	{
696 		const VkBufferImageCopy region =
697 		{
698 			0ull,																// VkDeviceSize                bufferOffset;
699 			0u,																	// uint32_t                    bufferRowLength;
700 			0u,																	// uint32_t                    bufferImageHeight;
701 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
702 			makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
703 			makeExtent3D(imageSize.x(), imageSize.y(), 1u),						// VkExtent3D                  imageExtent;
704 		};
705 
706 		vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, &region);
707 	}
708 	// Buffer write barrier
709 	{
710 		const VkBufferMemoryBarrier barrier =
711 		{
712 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
713 			DE_NULL,										// const void*        pNext;
714 			VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
715 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
716 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
717 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
718 			dstBuffer,										// VkBuffer           buffer;
719 			0ull,											// VkDeviceSize       offset;
720 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
721 		};
722 
723 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
724 							  0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
725 	}
726 }
727 
728 namespace VerifySamples
729 {
730 
731 //! The parameters that define a test case
732 struct TestParams
733 {
734 	struct SampleCount
735 	{
736 		VkSampleCountFlagBits	numCoverageSamples;				//!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
737 		VkSampleCountFlagBits	numColorSamples;				//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
738 		VkSampleCountFlagBits	numDepthStencilSamples;			//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
739 	};
740 
741 	VkFormat					colorFormat;					//!< Color attachment format
742 	VkFormat					depthStencilFormat;				//!< D/S attachment format. Will test both aspects if it's a mixed format
743 	bool						useProgrammableSampleLocations;	//!< Try to use VK_EXT_sample_locations if available
744 	std::vector<SampleCount>	perSubpassSamples;				//!< Will use multiple subpasses if more than one element
745 
TestParamsvkt::pipeline::__anonc89cd22b0111::VerifySamples::TestParams746 	TestParams (void)
747 		: colorFormat						()
748 		, depthStencilFormat				()
749 		, useProgrammableSampleLocations	()
750 	{
751 	}
752 };
753 
754 //! Common data used by the test
755 struct WorkingData
756 {
757 	struct PerSubpass
758 	{
759 		deUint32						numVertices;				//!< Number of vertices defined in the vertex buffer
760 		Move<VkBuffer>					vertexBuffer;
761 		MovePtr<Allocation>				vertexBufferAlloc;
762 		Move<VkImage>					colorImage;					//!< Color image
763 		Move<VkImageView>				colorImageView;				//!< Color attachment
764 		MovePtr<Allocation>				colorImageAlloc;
765 		Move<VkImage>					depthStencilImage;			//!< Depth stencil image
766 		Move<VkImageView>				depthStencilImageView;		//!< Depth stencil attachment
767 		Move<VkImageView>				depthOnlyImageView;			//!< Depth aspect for shader read
768 		Move<VkImageView>				stencilOnlyImageView;		//!< Stencil aspect for shader read
769 		MovePtr<Allocation>				depthStencilImageAlloc;
770 		Move<VkBuffer>					compareBuffer;				//!< Buffer used to verify the images - comparison data
771 		MovePtr<Allocation>				compareBufferAlloc;
772 		VkDeviceSize					compareBufferSize;
773 		Move<VkBuffer>					resultBuffer;				//!< Buffer used to verify the images - results
774 		MovePtr<Allocation>				resultBufferAlloc;
775 		VkDeviceSize					resultBufferSize;
776 		deUint32						numResultElements;			//!< Number of checksums in the result buffer
777 		MovePtr<MultisamplePixelGrid>	pixelGrid;					//!< Programmable locations
778 
PerSubpassvkt::pipeline::__anonc89cd22b0111::VerifySamples::WorkingData::PerSubpass779 		PerSubpass (void)
780 			: numVertices		()
781 			, compareBufferSize	()
782 			, resultBufferSize	()
783 			, numResultElements	()
784 		{
785 		}
786 	};
787 
788 	UVec2											renderSize;					//!< Size of the framebuffer
789 	VkPhysicalDeviceSampleLocationsPropertiesEXT	sampleLocationsProperties;	//!< Used with VK_EXT_sample_locations
790 
791 	std::vector<de::SharedPtr<PerSubpass> >			perSubpass;					//!< Test may use more than one set of data
792 
WorkingDatavkt::pipeline::__anonc89cd22b0111::VerifySamples::WorkingData793 	WorkingData (void)
794 		: sampleLocationsProperties ()
795 	{
796 	}
797 };
798 
addVerificationComputeShader(SourceCollections & programCollection,const VkSampleCountFlagBits numCoverageSamples,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const VkFormat depthStencilFormat,const std::string & nameSuffix)799 void addVerificationComputeShader (SourceCollections&			programCollection,
800 								   const VkSampleCountFlagBits	numCoverageSamples,
801 								   const VkSampleCountFlagBits	numColorSamples,
802 								   const VkSampleCountFlagBits	numDepthStencilSamples,
803 								   const VkFormat				depthStencilFormat,
804 								   const std::string&			nameSuffix)
805 {
806 		const bool			isColorMS			= (numColorSamples		  != VK_SAMPLE_COUNT_1_BIT);
807 		const bool			isDepthStencilMS	= (numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT);
808 		const std::string	colorBit			= de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_COLOR_BIT)) + "u";
809 		const std::string	depthBit			= de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_DEPTH_BIT)) + "u";
810 		const std::string	stencilBit			= de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_STENCIL_BIT)) + "u";
811 
812 		std::ostringstream src;
813 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
814 			<< "\n"
815 			<< "struct CompareData {\n"
816 			<< "    vec4  color;\n"
817 			<< "    float depth;\n"
818 			<< "    uint  stencil;\n"
819 			<< "};\n"
820 			<< "\n"
821 			<< "layout(local_size_x = " << static_cast<deUint32>(numCoverageSamples) << ") in;\n"
822 			// Always use this descriptor layout and ignore unused bindings
823 			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
824 			<< "    uint values[];\n"
825 			<< "} sb_out;\n"
826 			<< "layout(set = 0, binding = 1, std430) readonly buffer InputCompare {\n"
827 			<< "    CompareData	data[];\n"
828 			<< "} sb_cmp;\n"
829 			<< "layout(set = 0, binding = 2) uniform sampler2D" << (isColorMS ? "MS" : "") << "  colorImage;\n"
830 			<< "layout(set = 0, binding = 3) uniform sampler2D" << (isDepthStencilMS ? "MS" : "") <<"  depthImage;\n"
831 			<< "layout(set = 0, binding = 4) uniform usampler2D" << (isDepthStencilMS ? "MS" : "") <<" stencilImage;\n"
832 			<< "\n"
833 			<< "void main (void)\n"
834 			<< "{\n"
835 
836 		// Data for each sample in each pixel is laid out linearly (e.g 2 samples):
837 		// [pixel(0, 0) sample(0)][pixel(0, 0) sample(1)][pixel(1, 0) sample(0)][pixel(1, 0) sample(1)]...
838 
839 			<< "    uint  globalIndex = gl_LocalInvocationID.x + gl_WorkGroupSize.x * (gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.x);\n"
840 			<< "    ivec2 position    = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
841 			<< "    int   sampleNdx   = int(gl_LocalInvocationID.x);\n"
842 			<< "    uint  result      = 0u;\n"
843 			<< "\n"
844 			<< "    // Verify color samples\n"
845 			<< "    if (sampleNdx < " << static_cast<deUint32>(numColorSamples) << ")\n"
846 			<< "    {\n"
847 			<< "        vec4 color     = texelFetch(colorImage, position, sampleNdx);\n"	// for non-MS (1 sample) case, sampleNdx = 0 and will instead be LOD = 0
848 			<< "        vec4 diff      = abs(color - sb_cmp.data[globalIndex].color);\n"
849 			<< "        vec4 threshold = vec4(0.02);\n"
850 			<< "\n"
851 			<< "        if (all(lessThan(diff, threshold)))\n"
852 			<< "            result |= " << colorBit << ";\n"
853 			<< "    }\n"
854 			<< "    else\n"
855 			<< "        result |= " << colorBit << ";\n"	// Pass, if sample doesn't exist
856 			<< "\n";
857 
858 		if (isDepthFormat(depthStencilFormat))
859 		{
860 			src << "    // Verify depth samples\n"
861 				<< "    if (sampleNdx < " << static_cast<deUint32>(numDepthStencilSamples) << ")\n"
862 				<< "    {\n"
863 				<< "        float depth     = texelFetch(depthImage, position, sampleNdx).r;\n"
864 				<< "        float diff      = abs(depth - sb_cmp.data[globalIndex].depth);\n"
865 				<< "        float threshold = 0.002;\n"
866 				<< "\n"
867 				<< "        if (diff < threshold)\n"
868 				<< "            result |= " << depthBit << ";\n"
869 				<< "    }\n"
870 				<< "    else\n"
871 				<< "        result |= " << depthBit << ";\n"
872 				<< "\n";
873 		}
874 
875 		if (isStencilFormat(depthStencilFormat))
876 		{
877 			src << "    // Verify stencil samples\n"
878 				<< "    if (sampleNdx < " << static_cast<deUint32>(numDepthStencilSamples) << ")\n"
879 				<< "    {\n"
880 				<< "        uint stencil   = texelFetch(stencilImage, position, sampleNdx).r;\n"
881 				<< "        uint diff      = stencil - sb_cmp.data[globalIndex].stencil;\n"
882 				<< "\n"
883 				<< "        if (diff == 0u)\n"
884 				<< "            result |= " << stencilBit << ";\n"
885 				<< "    }\n"
886 				<< "    else\n"
887 				<< "        result |= " << stencilBit << ";\n"
888 				<< "\n";
889 		}
890 
891 		src << "    sb_out.values[globalIndex] = result;\n"
892 			<< "}\n";
893 		programCollection.glslSources.add("comp" + nameSuffix) << glu::ComputeSource(src.str());
894 }
895 
896 //! Get a compact sample count string in format X_Y_Z
getSampleCountString(const TestParams::SampleCount & samples)897 std::string getSampleCountString (const TestParams::SampleCount& samples)
898 {
899 	std::ostringstream str;
900 
901 	str << static_cast<deUint32>(samples.numCoverageSamples) << "_"
902 		<< static_cast<deUint32>(samples.numColorSamples)	 << "_"
903 		<< static_cast<deUint32>(samples.numDepthStencilSamples);
904 
905 	return str.str();
906 }
907 
initPrograms(SourceCollections & programCollection,const TestParams params)908 void initPrograms (SourceCollections& programCollection, const TestParams params)
909 {
910 	// Vertex shader - position and color
911 	{
912 		std::ostringstream src;
913 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
914 			<< "\n"
915 			<< "layout(location = 0) in  vec4 in_position;\n"
916 			<< "layout(location = 1) in  vec4 in_color;\n"
917 			<< "layout(location = 0) out vec4 o_color;\n"
918 			<< "\n"
919 			<< "out gl_PerVertex {\n"
920 			<< "    vec4 gl_Position;\n"
921 			<< "};\n"
922 			<< "\n"
923 			<< "void main(void)\n"
924 			<< "{\n"
925 			<< "    gl_Position = in_position;\n"
926 			<< "    o_color     = in_color;\n"
927 			<< "}\n";
928 
929 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
930 	}
931 
932 	// Fragment shader - output color from VS
933 	{
934 		std::ostringstream src;
935 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
936 			<< "\n"
937 			<< "layout(location = 0) in  vec4 in_color;\n"
938 			<< "layout(location = 0) out vec4 o_color;\n"
939 			<< "\n"
940 			<< "void main(void)\n"
941 			<< "{\n"
942 			<< "    o_color = in_color;\n"
943 			<< "}\n";
944 
945 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
946 	}
947 
948 	// Compute shader - image verification
949 	for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
950 	{
951 		const TestParams::SampleCount&	samples	= params.perSubpassSamples[subpassNdx];
952 		addVerificationComputeShader(programCollection,
953 									 samples.numCoverageSamples,
954 									 samples.numColorSamples,
955 									 samples.numDepthStencilSamples,
956 									 params.depthStencilFormat,
957 									 "_" + getSampleCountString(samples));
958 	}
959 }
960 
961 //! A simple color, depth/stencil draw. Subpasses (if more than one) are independent
draw(Context & context,const TestParams & params,WorkingData & wd)962 void draw (Context& context, const TestParams& params, WorkingData& wd)
963 {
964 	const DeviceInterface&	vk				= context.getDeviceInterface();
965 	const VkDevice			device			= context.getDevice();
966 	const deUint32			numSubpasses	= static_cast<deUint32>(wd.perSubpass.size());
967 
968 	Move<VkRenderPass>							renderPass;
969 	Move<VkFramebuffer>							framebuffer;
970 	std::vector<VkSampleLocationsInfoEXT>		perSubpassSampleLocationsInfo;
971 	std::vector<VkAttachmentSampleLocationsEXT>	attachmentSampleLocations;
972 	std::vector<VkSubpassSampleLocationsEXT>	subpassSampleLocations;
973 
974 	if (params.useProgrammableSampleLocations)
975 	for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
976 	{
977 		perSubpassSampleLocationsInfo.push_back(makeSampleLocationsInfo(*wd.perSubpass[subpassNdx]->pixelGrid));
978 	}
979 
980 	// Create a render pass and a framebuffer
981 	{
982 		std::vector<VkSubpassDescription>		subpasses;
983 		std::vector<VkImageView>				attachments;
984 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
985 		std::vector<VkAttachmentReference>		attachmentReferences;
986 
987 		// Reserve capacity to avoid invalidating pointers to elements
988 		attachmentReferences.reserve(numSubpasses * 2);
989 
990 		for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
991 		{
992 			attachments.push_back(wd.perSubpass[subpassNdx]->colorImageView.get());
993 			attachments.push_back(wd.perSubpass[subpassNdx]->depthStencilImageView.get());
994 
995 			attachmentDescriptions.push_back(makeAttachmentDescription(
996 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
997 				params.colorFormat,												// VkFormat							format;
998 				params.perSubpassSamples[subpassNdx].numColorSamples,			// VkSampleCountFlagBits			samples;
999 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
1000 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1001 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
1002 				VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
1003 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1004 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
1005 			));
1006 
1007 			attachmentDescriptions.push_back(makeAttachmentDescription(
1008 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1009 				params.depthStencilFormat,										// VkFormat							format;
1010 				params.perSubpassSamples[subpassNdx].numDepthStencilSamples,	// VkSampleCountFlagBits			samples;
1011 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
1012 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1013 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				stencilLoadOp;
1014 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				stencilStoreOp;
1015 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1016 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL					// VkImageLayout					finalLayout;
1017 			));
1018 
1019 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
1020 			const VkAttachmentReference* colorRef = &attachmentReferences.back();
1021 
1022 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
1023 			const VkAttachmentReference* depthStencilRef = &attachmentReferences.back();
1024 
1025 			if (params.useProgrammableSampleLocations)
1026 			{
1027 				const VkAttachmentSampleLocationsEXT newAttachmentSampleLocations =
1028 				{
1029 					attachmentReferences.back().attachment,			// uint32_t                    attachmentIndex;
1030 					perSubpassSampleLocationsInfo[subpassNdx],		// VkSampleLocationsInfoEXT    sampleLocationsInfo;
1031 				};
1032 				attachmentSampleLocations.push_back(newAttachmentSampleLocations);
1033 
1034 				const VkSubpassSampleLocationsEXT newSubpassSampleLocations =
1035 				{
1036 					subpassNdx,										// uint32_t                    subpassIndex;
1037 					perSubpassSampleLocationsInfo[subpassNdx],		// VkSampleLocationsInfoEXT    sampleLocationsInfo;
1038 				};
1039 				subpassSampleLocations.push_back(newSubpassSampleLocations);
1040 			}
1041 
1042 			const VkSubpassDescription subpassDescription =
1043 			{
1044 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
1045 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
1046 				0u,													// uint32_t                        inputAttachmentCount;
1047 				DE_NULL,											// const VkAttachmentReference*    pInputAttachments;
1048 				1u,													// uint32_t                        colorAttachmentCount;
1049 				colorRef,											// const VkAttachmentReference*    pColorAttachments;
1050 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
1051 				depthStencilRef,									// const VkAttachmentReference*    pDepthStencilAttachment;
1052 				0u,													// uint32_t                        preserveAttachmentCount;
1053 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
1054 			};
1055 
1056 			subpasses.push_back(subpassDescription);
1057 		}
1058 
1059 		// Assume there are no dependencies between subpasses
1060 		const VkRenderPassCreateInfo renderPassInfo =
1061 		{
1062 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
1063 			DE_NULL,												// const void*						pNext;
1064 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
1065 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
1066 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
1067 			static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
1068 			dataOrNullPtr(subpasses),								// const VkSubpassDescription*		pSubpasses;
1069 			0u,														// deUint32							dependencyCount;
1070 			DE_NULL,												// const VkSubpassDependency*		pDependencies;
1071 		};
1072 
1073 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
1074 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1075 	}
1076 
1077 	const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1078 	const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1079 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device));
1080 
1081 	typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
1082 	std::vector<PipelineSp> pipelines;
1083 
1084 	for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1085 	{
1086 		const VkSampleLocationsInfoEXT* pSampleLocationsInfo = (params.useProgrammableSampleLocations ? &perSubpassSampleLocationsInfo[subpassNdx] : DE_NULL);
1087 
1088 		pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1089 			makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, /*use vertex input*/ true, subpassNdx,
1090 								 wd.renderSize, getImageAspectFlags(params.depthStencilFormat), params.perSubpassSamples[subpassNdx].numCoverageSamples,
1091 								 /*use sample shading*/ true, pSampleLocationsInfo))));
1092 	}
1093 
1094 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1095 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1096 
1097 	beginCommandBuffer(vk, *cmdBuffer);
1098 
1099 	{
1100 		std::vector<VkClearValue> clearValues;
1101 
1102 		for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1103 		{
1104 			clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1105 			clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1106 		}
1107 
1108 		const VkRect2D renderArea =
1109 		{
1110 			{ 0u, 0u },
1111 			{ wd.renderSize.x(), wd.renderSize.y() }
1112 		};
1113 
1114 		VkRenderPassBeginInfo renderPassBeginInfo =
1115 		{
1116 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
1117 			DE_NULL,											// const void*             pNext;
1118 			*renderPass,										// VkRenderPass            renderPass;
1119 			*framebuffer,										// VkFramebuffer           framebuffer;
1120 			renderArea,											// VkRect2D                renderArea;
1121 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
1122 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
1123 		};
1124 
1125 		if (params.useProgrammableSampleLocations)
1126 		{
1127 			const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo =
1128 			{
1129 				VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,	// VkStructureType                          sType;
1130 				DE_NULL,														// const void*                              pNext;
1131 				static_cast<deUint32>(attachmentSampleLocations.size()),		// uint32_t                                 attachmentInitialSampleLocationsCount;
1132 				dataOrNullPtr(attachmentSampleLocations),						// const VkAttachmentSampleLocationsEXT*    pAttachmentInitialSampleLocations;
1133 				static_cast<deUint32>(subpassSampleLocations.size()),			// uint32_t                                 postSubpassSampleLocationsCount;
1134 				dataOrNullPtr(subpassSampleLocations),							// const VkSubpassSampleLocationsEXT*       pPostSubpassSampleLocations;
1135 			};
1136 
1137 			renderPassBeginInfo.pNext = &renderPassSampleLocationsBeginInfo;
1138 
1139 			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1140 		}
1141 		else
1142 			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1143 	}
1144 
1145 	for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1146 	{
1147 		if (subpassNdx != 0)
1148 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1149 
1150 		const VkDeviceSize vertexBufferOffset = 0ull;
1151 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.perSubpass[subpassNdx]->vertexBuffer.get(), &vertexBufferOffset);
1152 
1153 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1154 
1155 		vk.cmdDraw(*cmdBuffer, wd.perSubpass[subpassNdx]->numVertices, 1u, 0u, 0u);
1156 	}
1157 
1158 	vk.cmdEndRenderPass(*cmdBuffer);
1159 
1160 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1161 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1162 }
1163 
dispatchImageCheck(Context & context,const TestParams & params,WorkingData & wd,const deUint32 subpassNdx)1164 void dispatchImageCheck (Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx)
1165 {
1166 	const DeviceInterface&		vk			= context.getDeviceInterface();
1167 	const VkDevice				device		= context.getDevice();
1168 	WorkingData::PerSubpass&	subpassData	= *wd.perSubpass[subpassNdx];
1169 
1170 	const Unique<VkSampler>	defaultSampler	(makeSampler(vk, device));
1171 
1172 	// Create descriptor set
1173 
1174 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1175 		DescriptorSetLayoutBuilder()
1176 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_COMPUTE_BIT)
1177 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_COMPUTE_BIT)
1178 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get())
1179 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get())
1180 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get())
1181 		.build(vk, device));
1182 
1183 	const Unique<VkDescriptorPool> descriptorPool(
1184 		DescriptorPoolBuilder()
1185 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
1186 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3u)
1187 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1188 
1189 	const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1190 
1191 	{
1192 		const VkDescriptorBufferInfo	compareBufferInfo	= makeDescriptorBufferInfo(*subpassData.compareBuffer, 0ull, subpassData.compareBufferSize);
1193 		const VkDescriptorBufferInfo	resultBufferInfo	= makeDescriptorBufferInfo(*subpassData.resultBuffer, 0ull, subpassData.resultBufferSize);
1194 		const VkDescriptorImageInfo		colorImageInfo		= makeDescriptorImageInfo(DE_NULL, *subpassData.colorImageView,			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1195 		const VkDescriptorImageInfo		depthImageInfo		= makeDescriptorImageInfo(DE_NULL, *subpassData.depthOnlyImageView,		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1196 		const VkDescriptorImageInfo		stencilImageInfo	= makeDescriptorImageInfo(DE_NULL, *subpassData.stencilOnlyImageView,	VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1197 
1198 		DescriptorSetUpdateBuilder	builder;
1199 
1200 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
1201 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &compareBufferInfo);
1202 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1203 
1204 		if (subpassData.depthOnlyImageView)
1205 			builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo);
1206 
1207 		if (subpassData.stencilOnlyImageView)
1208 			builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(4u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &stencilImageInfo);
1209 
1210 		builder.update(vk, device);
1211 	}
1212 
1213 	// Pipeline
1214 
1215 	const std::string				shaderName		("comp_" + getSampleCountString(params.perSubpassSamples[subpassNdx]));
1216 	const Unique<VkShaderModule>	shaderModule	(createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1217 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device, *descriptorSetLayout));
1218 	const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1219 
1220 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1221 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1222 
1223 	beginCommandBuffer(vk, *cmdBuffer);
1224 
1225 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1226 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1227 
1228 	vk.cmdDispatch(*cmdBuffer, wd.renderSize.x(), wd.renderSize.y(), 1u);
1229 
1230 	{
1231 		const VkBufferMemoryBarrier barrier =
1232 		{
1233 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1234 			DE_NULL,										// const void*        pNext;
1235 			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
1236 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1237 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1238 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1239 			*subpassData.resultBuffer,						// VkBuffer           buffer;
1240 			0ull,											// VkDeviceSize       offset;
1241 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
1242 		};
1243 
1244 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1245 			(const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1246 	}
1247 
1248 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1249 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1250 
1251 	invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(), subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1252 }
1253 
createPerSubpassData(Context & context,const TestParams & params,WorkingData & wd,const deUint32 subpassNdx)1254 void createPerSubpassData (Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx)
1255 {
1256 	const DeviceInterface&			vk			= context.getDeviceInterface();
1257 	const VkDevice					device		= context.getDevice();
1258 	MovePtr<Allocator>				allocator   = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1259 	const TestParams::SampleCount&	samples		= params.perSubpassSamples[subpassNdx];
1260 	WorkingData::PerSubpass&		subpassData	= *wd.perSubpass[subpassNdx];
1261 
1262 	// Create images
1263 	{
1264 
1265 		const VkImageUsageFlags	colorImageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT		  | VK_IMAGE_USAGE_SAMPLED_BIT;
1266 		const VkImageUsageFlags depthStencilImageUsageFlags	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1267 
1268 		checkImageRequirements (context,
1269 								params.colorFormat,
1270 								VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1271 								colorImageUsageFlags,
1272 								samples.numColorSamples);
1273 
1274 		subpassData.colorImage		= makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags);
1275 		subpassData.colorImageAlloc	= bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any);
1276 		subpassData.colorImageView	= makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1277 
1278 		checkImageRequirements (context,
1279 								params.depthStencilFormat,
1280 								VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1281 								depthStencilImageUsageFlags,
1282 								samples.numDepthStencilSamples);
1283 
1284 		subpassData.depthStencilImage		= makeImage(vk, device, params.depthStencilFormat, wd.renderSize, samples.numDepthStencilSamples, depthStencilImageUsageFlags);
1285 		subpassData.depthStencilImageAlloc	= bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any);
1286 		subpassData.depthStencilImageView	= makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1287 
1288 		if (isDepthFormat(params.depthStencilFormat))
1289 			subpassData.depthOnlyImageView	= makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1290 
1291 		if (isStencilFormat(params.depthStencilFormat))
1292 			subpassData.stencilOnlyImageView	= makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1293 	}
1294 
1295 	// Create vertex and comparison buffers
1296 	{
1297 		const deUint32					seed		= 123 + 19 * subpassNdx;
1298 		const std::vector<CompareData>	compareData	= generateCompareData(seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples);
1299 
1300 		subpassData.compareBufferSize	= static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size());
1301 		subpassData.compareBuffer		= makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1302 		subpassData.compareBufferAlloc	= bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible);
1303 
1304 		deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData), static_cast<std::size_t>(subpassData.compareBufferSize));
1305 		flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(), subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1306 
1307 		subpassData.numResultElements	= static_cast<deUint32>(compareData.size());
1308 		subpassData.resultBufferSize	= static_cast<VkDeviceSize>(sizeof(deUint32) * compareData.size());
1309 		subpassData.resultBuffer		= makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1310 		subpassData.resultBufferAlloc	= bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible);
1311 
1312 		deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(subpassData.resultBufferSize));
1313 		flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(), subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1314 
1315 		std::vector<PositionColor> vertices;
1316 
1317 		if (params.useProgrammableSampleLocations)
1318 		{
1319 			subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width,
1320 																								 wd.sampleLocationsProperties.maxSampleLocationGridSize.height),
1321 																						   samples.numCoverageSamples));
1322 
1323 			const deUint32 locationsSeed = 211 + 4 * subpassNdx;
1324 			fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits, locationsSeed);
1325 			vertices = generateSubpixelTriangles(wd.renderSize, compareData, getSampleLocations(*subpassData.pixelGrid, wd.renderSize));
1326 		}
1327 		else
1328 		{
1329 			const std::vector<Vec2>	locations = genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize);
1330 			vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations);
1331 		}
1332 
1333 		const VkDeviceSize	vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1334 		subpassData.numVertices			= static_cast<deUint32>(vertices.size());
1335 		subpassData.vertexBuffer			= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1336 		subpassData.vertexBufferAlloc	= bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible);
1337 
1338 		deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1339 		flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(), subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1340 	}
1341 }
1342 
checkRequirements(Context & context,TestParams params)1343 void checkRequirements (Context& context, TestParams params)
1344 {
1345 	context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1346 
1347 	if (params.useProgrammableSampleLocations)
1348 		context.requireDeviceFunctionality("VK_EXT_sample_locations");
1349 
1350 	for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
1351 	{
1352 		const TestParams::SampleCount& samples = params.perSubpassSamples[subpassNdx];
1353 		checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples, !params.useProgrammableSampleLocations);
1354 	}
1355 }
1356 
1357 //! Verify the values of all samples in all attachments.
test(Context & context,const TestParams params)1358 tcu::TestStatus test (Context& context, const TestParams params)
1359 {
1360 	WorkingData wd;
1361 	wd.renderSize	= UVec2(2, 2);	// Use a very small image, as we will verify all samples for all pixels
1362 
1363 	// Query state related to programmable sample locations
1364 	if (params.useProgrammableSampleLocations)
1365 	{
1366 		const InstanceInterface&	vki				= context.getInstanceInterface();
1367 		const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
1368 
1369 		wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
1370 		wd.sampleLocationsProperties.pNext = DE_NULL;
1371 
1372 		VkPhysicalDeviceProperties2 properties =
1373 		{
1374 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,	    // VkStructureType               sType;
1375 			&wd.sampleLocationsProperties,							// void*                         pNext;
1376 			VkPhysicalDeviceProperties(),							// VkPhysicalDeviceProperties    properties;
1377 		};
1378 
1379 		vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1380 
1381 		for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
1382 		{
1383 			if ((wd.sampleLocationsProperties.sampleLocationSampleCounts & params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u)
1384 				TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported");
1385 		}
1386 	}
1387 
1388 	// Create subpass data
1389 	for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
1390 	{
1391 		wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass()));
1392 		createPerSubpassData(context, params, wd, subpassNdx);
1393 	}
1394 
1395 	// Draw test geometry
1396 	draw (context, params, wd);
1397 
1398 	// Verify images with a compute shader
1399 	for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
1400 		dispatchImageCheck (context, params, wd, subpassNdx);
1401 
1402 	// Test checksums
1403 	for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx)
1404 	{
1405 		const deUint32*	const	pSampleChecksumBase	= static_cast<deUint32*>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr());
1406 		const bool				hasDepth			= isDepthFormat(params.depthStencilFormat);
1407 		const bool				hasStencil			= isStencilFormat(params.depthStencilFormat);
1408 		bool					allOk				= true;
1409 
1410 		context.getTestContext().getLog() << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage;
1411 
1412 		for (deUint32 globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements; ++globalSampleNdx)
1413 		{
1414 			const TestParams::SampleCount&	samples	 = params.perSubpassSamples[subpassNdx];
1415 			const deUint32					checksum = pSampleChecksumBase[globalSampleNdx];
1416 
1417 			if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u)
1418 			{
1419 				reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples, globalSampleNdx);
1420 				allOk = false;
1421 			}
1422 
1423 			if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u))
1424 			{
1425 				reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples, globalSampleNdx);
1426 				allOk = false;
1427 			}
1428 
1429 			if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u))
1430 			{
1431 				reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize, samples.numCoverageSamples, globalSampleNdx);
1432 				allOk = false;
1433 			}
1434 		}
1435 
1436 		if (!allOk)
1437 			return tcu::TestStatus::fail("Multisampled image has incorrect samples");
1438 	}
1439 
1440 	return tcu::TestStatus::pass("Pass");
1441 }
1442 
1443 } // VerifySamples
1444 
1445 namespace ShaderBuiltins
1446 {
1447 
1448 struct TestParams
1449 {
1450 	VkSampleCountFlagBits		numCoverageSamples;			//!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
1451 	VkSampleCountFlagBits		numColorSamples;			//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1452 	VkSampleCountFlagBits		numDepthStencilSamples;		//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1453 	VkFormat					colorFormat;				//!< Color attachment format
1454 	VkFormat					depthStencilFormat;			//!< D/S attachment format. Will test both aspects if it's a mixed format
1455 };
1456 
1457 struct WorkingData
1458 {
1459 	UVec2						renderSize;					//!< Size of the framebuffer
1460 	deUint32					numVertices;				//!< Number of vertices defined in the vertex buffer
1461 	Move<VkBuffer>				vertexBuffer;
1462 	MovePtr<Allocation>			vertexBufferAlloc;
1463 	Move<VkImage>				colorImage;					//!< Color image
1464 	Move<VkImageView>			colorImageView;				//!< Color attachment
1465 	MovePtr<Allocation>			colorImageAlloc;
1466 	Move<VkImage>				depthStencilImage;			//!< Depth stencil image
1467 	Move<VkImageView>			depthStencilImageView;		//!< Depth stencil attachment
1468 	Move<VkImageView>			depthOnlyImageView;			//!< Depth aspect for shader read
1469 	Move<VkImageView>			stencilOnlyImageView;		//!< Stencil aspect for shader read
1470 	MovePtr<Allocation>			depthStencilImageAlloc;
1471 	Move<VkImage>				resolveImage;				//!< Resolve image
1472 	Move<VkImageView>			resolveImageView;			//!< Resolve attachment
1473 	MovePtr<Allocation>			resolveImageAlloc;
1474 	Move<VkBuffer>				colorBuffer;				//!< Buffer used to copy resolve output
1475 	MovePtr<Allocation>			colorBufferAlloc;
1476 	VkDeviceSize				colorBufferSize;
1477 
WorkingDatavkt::pipeline::__anonc89cd22b0111::ShaderBuiltins::WorkingData1478 	WorkingData (void)
1479 		: numVertices		()
1480 	{
1481 	}
1482 };
1483 
initPrograms(SourceCollections & programCollection,const TestParams params)1484 void initPrograms (SourceCollections& programCollection, const TestParams params)
1485 {
1486 	// Vertex shader - no vertex data
1487 	{
1488 		std::ostringstream src;
1489 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1490 			<< "\n"
1491 			<< "out gl_PerVertex {\n"
1492 			<< "    vec4 gl_Position;\n"
1493 			<< "};\n"
1494 			<< "\n"
1495 			<< "void main(void)\n"
1496 			<< "{\n"
1497 			// Specify an oversized triangle covering the whole viewport.
1498 			<< "    switch (gl_VertexIndex)\n"
1499 			<< "    {\n"
1500 			<< "        case 0:\n"
1501 			<< "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1502 			<< "            break;\n"
1503 			<< "        case 1:\n"
1504 			<< "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
1505 			<< "            break;\n"
1506 			<< "        case 2:\n"
1507 			<< "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1508 			<< "            break;\n"
1509 			<< "    }\n"
1510 			<< "}\n";
1511 
1512 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1513 	}
1514 
1515 	// Fragment shader
1516 	{
1517 		std::ostringstream src;
1518 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1519 			<< "\n"
1520 			<< "layout(location = 0) out vec4 o_color;\n"
1521 			<< "\n"
1522 			<< "void main(void)\n"
1523 			<< "{\n"
1524 			<< "    vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n"
1525 			<< "\n";
1526 
1527 		if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT)
1528 		{
1529 			const deUint32 expectedMask = ((1u << static_cast<deUint32>(params.numCoverageSamples)) - 1u);
1530 
1531 			// Expect all covered samples to be lit, the rest is zero
1532 			src << "    if (gl_SampleMaskIn[0] == " << expectedMask << ")\n"
1533 				<< "        col.g = 1.0;\n"
1534 				<< "    else\n"
1535 				<< "        col.r = 1.0;\n";
1536 		}
1537 		else
1538 		{
1539 			// Expect only a matching sample to be lit
1540 			src << "    if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n"
1541 				<< "        col.g = 1.0;\n"
1542 				<< "    else\n"
1543 				<< "        col.r = 1.0;\n"
1544 				<< "\n"
1545 				<< "    if (gl_SampleID >= " << static_cast<deUint32>(params.numColorSamples) << ")  // number of color samples, should not happen\n"
1546 				<< "        col.b = 1.0;\n";
1547 		}
1548 
1549 		src << "\n"
1550 			<< "    o_color = col;\n"
1551 			<< "}\n";
1552 
1553 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1554 	}
1555 }
1556 
1557 //! A simple color, depth/stencil draw. Single subpass, no vertex input
drawResolve(Context & context,const TestParams & params,WorkingData & wd)1558 void drawResolve (Context& context, const TestParams& params, WorkingData& wd)
1559 {
1560 	const DeviceInterface&	vk			= context.getDeviceInterface();
1561 	const VkDevice			device		= context.getDevice();
1562 	const bool				needResolve	= (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1563 
1564 	Move<VkRenderPass>		renderPass;
1565 	Move<VkFramebuffer>		framebuffer;
1566 
1567 	// Create a render pass and a framebuffer
1568 	{
1569 		std::vector<VkImageView>				attachments;
1570 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
1571 
1572 		attachments.push_back(*wd.colorImageView);
1573 		attachments.push_back(*wd.depthStencilImageView);
1574 
1575 		attachmentDescriptions.push_back(makeAttachmentDescription(
1576 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags		flags;
1577 			params.colorFormat,										// VkFormat							format;
1578 			params.numColorSamples,									// VkSampleCountFlagBits			samples;
1579 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp				loadOp;
1580 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp				storeOp;
1581 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp				stencilLoadOp;
1582 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp				stencilStoreOp;
1583 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					initialLayout;
1584 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL					// VkImageLayout					finalLayout;
1585 		));
1586 
1587 		attachmentDescriptions.push_back(makeAttachmentDescription(
1588 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags		flags;
1589 			params.depthStencilFormat,								// VkFormat							format;
1590 			params.numDepthStencilSamples,							// VkSampleCountFlagBits			samples;
1591 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp				loadOp;
1592 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp				storeOp;
1593 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp				stencilLoadOp;
1594 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp				stencilStoreOp;
1595 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					initialLayout;
1596 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL		// VkImageLayout					finalLayout;
1597 		));
1598 
1599 		if (needResolve)
1600 		{
1601 			attachments.push_back(*wd.resolveImageView);
1602 
1603 			attachmentDescriptions.push_back(makeAttachmentDescription(
1604 				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
1605 				params.colorFormat,									// VkFormat							format;
1606 				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1607 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				loadOp;
1608 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1609 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1610 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1611 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
1612 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL				// VkImageLayout					finalLayout;
1613 			));
1614 		}
1615 
1616 		const VkAttachmentReference	colorRef		= makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1617 		const VkAttachmentReference	depthStencilRef	= makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1618 		const VkAttachmentReference	resolveRef		= makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1619 
1620 		const VkSubpassDescription subpassDescription =
1621 		{
1622 			(VkSubpassDescriptionFlags)0,							// VkSubpassDescriptionFlags       flags;
1623 			VK_PIPELINE_BIND_POINT_GRAPHICS,						// VkPipelineBindPoint             pipelineBindPoint;
1624 			0u,														// uint32_t                        inputAttachmentCount;
1625 			DE_NULL,												// const VkAttachmentReference*    pInputAttachments;
1626 			1u,														// uint32_t                        colorAttachmentCount;
1627 			&colorRef,												// const VkAttachmentReference*    pColorAttachments;
1628 			(needResolve ? &resolveRef : DE_NULL),					// const VkAttachmentReference*    pResolveAttachments;
1629 			&depthStencilRef,										// const VkAttachmentReference*    pDepthStencilAttachment;
1630 			0u,														// uint32_t                        preserveAttachmentCount;
1631 			DE_NULL,												// const uint32_t*                 pPreserveAttachments;
1632 		};
1633 
1634 		// Assume there are no dependencies between subpasses
1635 		VkRenderPassCreateInfo renderPassInfo =
1636 		{
1637 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
1638 			DE_NULL,												// const void*						pNext;
1639 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
1640 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
1641 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
1642 			1u,														// deUint32							subpassCount;
1643 			&subpassDescription,									// const VkSubpassDescription*		pSubpasses;
1644 			0u,														// deUint32							dependencyCount;
1645 			DE_NULL,												// const VkSubpassDependency*		pDependencies;
1646 		};
1647 
1648 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
1649 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1650 	}
1651 
1652 	const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1653 	const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1654 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device));
1655 	const bool						useVertexInput	= false;
1656 	const bool						sampleShading	= (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1657 	const deUint32					subpassNdx		= 0u;
1658 	const Unique<VkPipeline>		pipeline		(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, useVertexInput, subpassNdx,
1659 																		  wd.renderSize, getImageAspectFlags(params.depthStencilFormat), params.numCoverageSamples, sampleShading));
1660 
1661 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1662 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1663 
1664 	beginCommandBuffer(vk, *cmdBuffer);
1665 
1666 	{
1667 		std::vector<VkClearValue> clearValues;
1668 		clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1669 		clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1670 
1671 		const VkRect2D renderArea =
1672 		{
1673 			{ 0u, 0u },
1674 			{ wd.renderSize.x(), wd.renderSize.y() }
1675 		};
1676 
1677 		const VkRenderPassBeginInfo renderPassBeginInfo =
1678 		{
1679 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
1680 			DE_NULL,											// const void*             pNext;
1681 			*renderPass,										// VkRenderPass            renderPass;
1682 			*framebuffer,										// VkFramebuffer           framebuffer;
1683 			renderArea,											// VkRect2D                renderArea;
1684 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
1685 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
1686 		};
1687 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1688 	}
1689 
1690 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1691 	vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
1692 
1693 	vk.cmdEndRenderPass(*cmdBuffer);
1694 
1695 	if (needResolve)
1696 		recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer);
1697 	else
1698 		recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer);
1699 
1700 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1701 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1702 }
1703 
checkRequirements(Context & context,TestParams params)1704 void checkRequirements (Context& context, TestParams params)
1705 {
1706 	context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1707 
1708 	checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples, false /* require standard sample locations */);
1709 }
1710 
1711 //! Verify the values of shader builtins
test(Context & context,const TestParams params)1712 tcu::TestStatus test (Context& context, const TestParams params)
1713 {
1714 	WorkingData				wd;
1715 	const DeviceInterface&	vk			= context.getDeviceInterface();
1716 	const VkDevice			device		= context.getDevice();
1717 	MovePtr<Allocator>		allocator	= MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1718 
1719 	wd.renderSize	= UVec2(16, 16);
1720 
1721 	// Create images and a color buffer
1722 	{
1723 
1724 		const VkImageUsageFlags	colorImageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1725 		const VkImageUsageFlags depthStencilImageUsageFlags	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1726 
1727 		checkImageRequirements (context,
1728 								params.colorFormat,
1729 								VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1730 								colorImageUsageFlags,
1731 								params.numColorSamples);
1732 
1733 		wd.colorImage		= makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags);
1734 		wd.colorImageAlloc	= bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1735 		wd.colorImageView	= makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1736 
1737 		if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1738 		{
1739 			wd.resolveImage			= makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
1740 			wd.resolveImageAlloc	= bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any);
1741 			wd.resolveImageView		= makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1742 		}
1743 
1744 		// Resolve result
1745 		wd.colorBufferSize	= static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) * wd.renderSize.x() * wd.renderSize.y());
1746 		wd.colorBuffer		= makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1747 		wd.colorBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1748 
1749 		deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1750 		flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1751 
1752 		checkImageRequirements (context,
1753 								params.depthStencilFormat,
1754 								VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
1755 								depthStencilImageUsageFlags,
1756 								params.numDepthStencilSamples);
1757 
1758 		wd.depthStencilImage		= makeImage(vk, device, params.depthStencilFormat, wd.renderSize, params.numDepthStencilSamples, depthStencilImageUsageFlags);
1759 		wd.depthStencilImageAlloc	= bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any);
1760 		wd.depthStencilImageView	= makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1761 
1762 		if (isDepthFormat(params.depthStencilFormat))
1763 			wd.depthOnlyImageView	= makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1764 
1765 		if (isStencilFormat(params.depthStencilFormat))
1766 			wd.stencilOnlyImageView	= makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1767 	}
1768 
1769 	// Draw, resolve, and copy to color buffer (see the fragment shader for details)
1770 	drawResolve(context, params, wd);
1771 
1772 	// Verify resolved image
1773 	{
1774 		const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),wd.colorBufferAlloc->getHostPtr()));
1775 
1776 		if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image))
1777 			return tcu::TestStatus::pass("Pass");
1778 		else
1779 			return tcu::TestStatus::fail("Some samples were incorrect");
1780 	}
1781 }
1782 
1783 } // ShaderBuiltins
1784 
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,const VkSampleCountFlagBits colorCount,const VkSampleCountFlagBits depthStencilCount)1785 std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,
1786 									const VkSampleCountFlagBits colorCount,
1787 									const VkSampleCountFlagBits depthStencilCount)
1788 {
1789 	std::ostringstream str;
1790 	str << "coverage_"		 << static_cast<deUint32>(coverageCount)
1791 		<< "_color_"		 << static_cast<deUint32>(colorCount)
1792 		<< "_depth_stencil_" << static_cast<deUint32>(depthStencilCount);
1793 	return str.str();
1794 }
1795 
getFormatShortString(const VkFormat format)1796 std::string getFormatShortString (const VkFormat format)
1797 {
1798 	std::string s(de::toLower(getFormatName(format)));
1799 	return s.substr(10);
1800 }
1801 
getFormatCaseName(const VkFormat colorFormat,const VkFormat depthStencilFormat)1802 std::string getFormatCaseName (const VkFormat colorFormat,
1803 							   const VkFormat depthStencilFormat)
1804 {
1805 	std::ostringstream str;
1806 	str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat);
1807 	return str.str();
1808 }
1809 
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup * rootGroup)1810 void createMixedAttachmentSamplesTestsInGroup (tcu::TestCaseGroup* rootGroup)
1811 {
1812 	const VkFormat colorFormatRange[] =
1813 	{
1814 		VK_FORMAT_R8G8B8A8_UNORM,
1815 		// If you add more, make sure it is handled in the test/shader
1816 	};
1817 
1818 	const VkFormat depthStencilFormatRange[] =
1819 	{
1820 		VK_FORMAT_D16_UNORM,
1821 		VK_FORMAT_X8_D24_UNORM_PACK32,
1822 		VK_FORMAT_D32_SFLOAT,
1823 		VK_FORMAT_S8_UINT,
1824 		VK_FORMAT_D16_UNORM_S8_UINT,
1825 		VK_FORMAT_D24_UNORM_S8_UINT,
1826 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1827 	};
1828 
1829 	// Minimal set of formats to cover depth and stencil
1830 	const VkFormat depthStencilReducedFormatRange[] =
1831 	{
1832 		VK_FORMAT_D16_UNORM,				//!< Must be supported
1833 		VK_FORMAT_D24_UNORM_S8_UINT,		//!< Either this, or the next one must be supported
1834 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1835 	};
1836 
1837 	struct SampleCase
1838 	{
1839 		VkSampleCountFlagBits	colorSamples;
1840 		VkSampleCountFlagBits	depthStencilSamples;
1841 	};
1842 
1843 	// Currently supported EQAA cases
1844 	static const SampleCase	singlePassCases[] =
1845 	{
1846 		// Less color than depth/stencil
1847 		{ VK_SAMPLE_COUNT_1_BIT,	VK_SAMPLE_COUNT_2_BIT  },
1848 		{ VK_SAMPLE_COUNT_1_BIT,	VK_SAMPLE_COUNT_4_BIT  },
1849 		{ VK_SAMPLE_COUNT_1_BIT,	VK_SAMPLE_COUNT_8_BIT  },
1850 		{ VK_SAMPLE_COUNT_1_BIT,	VK_SAMPLE_COUNT_16_BIT },
1851 		{ VK_SAMPLE_COUNT_2_BIT,	VK_SAMPLE_COUNT_4_BIT  },
1852 		{ VK_SAMPLE_COUNT_2_BIT,	VK_SAMPLE_COUNT_8_BIT  },
1853 		{ VK_SAMPLE_COUNT_2_BIT,	VK_SAMPLE_COUNT_16_BIT },
1854 		{ VK_SAMPLE_COUNT_4_BIT,	VK_SAMPLE_COUNT_8_BIT  },
1855 		{ VK_SAMPLE_COUNT_4_BIT,	VK_SAMPLE_COUNT_16_BIT },
1856 		{ VK_SAMPLE_COUNT_8_BIT,	VK_SAMPLE_COUNT_16_BIT },
1857 	};
1858 
1859 	// Multi-subpass cases
1860 
1861 	static const SampleCase caseSubpassIncreaseColor_1[] =
1862 	{
1863 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT },
1864 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1865 	};
1866 	static const SampleCase caseSubpassIncreaseColor_2[] =
1867 	{
1868 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT },
1869 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT },
1870 		{ VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT },
1871 	};
1872 	static const SampleCase caseSubpassDecreaseColor_1[] =
1873 	{
1874 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1875 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT },
1876 	};
1877 	static const SampleCase caseSubpassDecreaseColor_2[] =
1878 	{
1879 		{ VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT },
1880 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT },
1881 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT },
1882 	};
1883 	static const SampleCase caseSubpassIncreaseCoverage_1[] =
1884 	{
1885 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT },
1886 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1887 	};
1888 	static const SampleCase caseSubpassIncreaseCoverage_2[] =
1889 	{
1890 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT },
1891 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1892 		{ VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT },
1893 	};
1894 	static const SampleCase caseSubpassDecreaseCoverage_1[] =
1895 	{
1896 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1897 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT },
1898 	};
1899 	static const SampleCase caseSubpassDecreaseCoverage_2[] =
1900 	{
1901 		{ VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT },
1902 		{ VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT },
1903 		{ VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT },
1904 	};
1905 
1906 	static const struct
1907 	{
1908 		const char* const	caseName;
1909 		const deUint32		numSampleCases;
1910 		const SampleCase*	pSampleCase;
1911 	} subpassCases[] =
1912 	{
1913 		{ "multi_subpass_decrease_color_4",		DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1),		caseSubpassDecreaseColor_1 },
1914 		{ "multi_subpass_decrease_color_8",		DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2),		caseSubpassDecreaseColor_2 },
1915 		{ "multi_subpass_decrease_coverage_4",	DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1),	caseSubpassDecreaseCoverage_1 },
1916 		{ "multi_subpass_decrease_coverage_8",	DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2),	caseSubpassDecreaseCoverage_2 },
1917 		{ "multi_subpass_increase_color_4",		DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1),		caseSubpassIncreaseColor_1 },
1918 		{ "multi_subpass_increase_color_8",		DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2),		caseSubpassIncreaseColor_2 },
1919 		{ "multi_subpass_increase_coverage_4",	DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1),	caseSubpassIncreaseCoverage_1 },
1920 		{ "multi_subpass_increase_coverage_8",	DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2),	caseSubpassIncreaseCoverage_2 },
1921 	};
1922 
1923 	// Test 1: Per-sample expected value check
1924 	{
1925 		MovePtr<tcu::TestCaseGroup> standardLocationsGroup		(new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations", ""));
1926 		MovePtr<tcu::TestCaseGroup> programmableLocationsGroup	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations", ""));
1927 
1928 		tcu::TestCaseGroup* locationsGroups[2] =
1929 		{
1930 			standardLocationsGroup.get(),
1931 			programmableLocationsGroup.get()
1932 		};
1933 
1934 		for (deUint32 groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx)
1935 		{
1936 			// Single subpass cases
1937 			for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
1938 			{
1939 				VerifySamples::TestParams::SampleCount	samples;
1940 				samples.numColorSamples					= singlePassCases[caseNdx].colorSamples;
1941 				samples.numDepthStencilSamples			= singlePassCases[caseNdx].depthStencilSamples;
1942 				samples.numCoverageSamples				= de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1943 
1944 				VerifySamples::TestParams params;
1945 				params.perSubpassSamples.push_back(samples);
1946 				params.useProgrammableSampleLocations	= (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1947 
1948 				MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
1949 					rootGroup->getTestContext(), getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples).c_str(), ""));
1950 
1951 				for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange; pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat)
1952 				for (const VkFormat *pColorFormat		 = colorFormatRange;		pColorFormat		!= DE_ARRAY_END(colorFormatRange);		  ++pColorFormat)
1953 				{
1954 					params.colorFormat			= *pColorFormat;
1955 					params.depthStencilFormat	= *pDepthStencilFormat;
1956 
1957 					addFunctionCaseWithPrograms(
1958 						sampleCaseGroup.get(),
1959 						getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1960 						"",
1961 						VerifySamples::checkRequirements,
1962 						VerifySamples::initPrograms,
1963 						VerifySamples::test, params);
1964 				}
1965 
1966 				locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1967 			}
1968 
1969 			// Multi subpass cases
1970 			for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx)
1971 			{
1972 				VerifySamples::TestParams params;
1973 				params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1974 
1975 				for (deUint32 subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx)
1976 				{
1977 					VerifySamples::TestParams::SampleCount	samples;
1978 					samples.numColorSamples					= subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples;
1979 					samples.numDepthStencilSamples			= subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples;
1980 					samples.numCoverageSamples				= de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1981 					params.perSubpassSamples.push_back(samples);
1982 				}
1983 
1984 				MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName, ""));
1985 
1986 				for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;	pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
1987 				for (const VkFormat *pColorFormat		 = colorFormatRange;				pColorFormat		!= DE_ARRAY_END(colorFormatRange);				 ++pColorFormat)
1988 				{
1989 					params.colorFormat			= *pColorFormat;
1990 					params.depthStencilFormat	= *pDepthStencilFormat;
1991 
1992 					addFunctionCaseWithPrograms(
1993 						sampleCaseGroup.get(),
1994 						getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1995 						"",
1996 						VerifySamples::checkRequirements,
1997 						VerifySamples::initPrograms,
1998 						VerifySamples::test, params);
1999 				}
2000 
2001 				locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
2002 			}
2003 		}
2004 
2005 		rootGroup->addChild(standardLocationsGroup.release());
2006 		rootGroup->addChild(programmableLocationsGroup.release());
2007 	}
2008 
2009 	// Test 2: Shader built-ins check
2010 	{
2011 		MovePtr<tcu::TestCaseGroup> builtinsGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins", ""));
2012 
2013 		for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
2014 		{
2015 			ShaderBuiltins::TestParams params;
2016 			params.numColorSamples			= singlePassCases[caseNdx].colorSamples;
2017 			params.numDepthStencilSamples	= singlePassCases[caseNdx].depthStencilSamples;
2018 			params.numCoverageSamples		= de::max(params.numColorSamples, params.numDepthStencilSamples);
2019 
2020 			MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
2021 				rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples, params.numDepthStencilSamples).c_str(), ""));
2022 
2023 			for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;  pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
2024 			for (const VkFormat *pColorFormat		 = colorFormatRange;				pColorFormat		!= DE_ARRAY_END(colorFormatRange);				 ++pColorFormat)
2025 			{
2026 				params.colorFormat			= *pColorFormat;
2027 				params.depthStencilFormat	= *pDepthStencilFormat;
2028 
2029 				addFunctionCaseWithPrograms(
2030 					sampleCaseGroup.get(),
2031 					getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
2032 					"",
2033 					ShaderBuiltins::checkRequirements,
2034 					ShaderBuiltins::initPrograms,
2035 					ShaderBuiltins::test,
2036 					params);
2037 			}
2038 
2039 			builtinsGroup->addChild(sampleCaseGroup.release());
2040 		}
2041 
2042 		rootGroup->addChild(builtinsGroup.release());
2043 	}
2044 }
2045 
2046 } // anonymous ns
2047 
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext & testCtx)2048 tcu::TestCaseGroup* createMultisampleMixedAttachmentSamplesTests (tcu::TestContext& testCtx)
2049 {
2050 	return createTestGroup(testCtx, "mixed_attachment_samples", "Test a graphics pipeline with varying sample count per color and depth/stencil attachments", createMixedAttachmentSamplesTestsInGroup);
2051 }
2052 
2053 } // pipeline
2054 } // vkt
2055