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