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