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 
59 namespace vkt
60 {
61 namespace pipeline
62 {
63 namespace
64 {
65 using namespace vk;
66 using de::UniquePtr;
67 using de::MovePtr;
68 using de::SharedPtr;
69 using tcu::UVec2;
70 using tcu::Vec2;
71 using tcu::Vec4;
72 
compareGreenImage(tcu::TestLog& log, const char* name, const char* description, const tcu::ConstPixelBufferAccess& image)73 bool 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 
getImageAspectFlags(const VkFormat format)80 VkImageAspectFlags 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 
92 struct 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 
CompareDatavkt::pipeline::__anon28233::CompareData101 	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.
makeSampler(const DeviceInterface& vk, const VkDevice device)111 Move<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 
makeImage(const DeviceInterface& vk, const VkDevice device, const VkFormat format, const UVec2& size, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)137 Move<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 
isDepthFormat(const VkFormat format)165 inline bool isDepthFormat (const VkFormat format)
166 {
167 	return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
168 }
169 
isStencilFormat(const VkFormat format)170 inline 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
preparePipelineWrapper(GraphicsPipelineWrapper& gpw, const PipelineLayoutWrapper& pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const bool useVertexInput, const deUint32 subpassNdx, const UVec2& renderSize, const VkImageAspectFlags depthStencilAspect, const VkSampleCountFlagBits numSamples, const bool sampleShadingEnable, const bool useFragmentShadingRate, const VkSampleLocationsInfoEXT* pSampleLocationsInfo = DE_NULL)176 void 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
wrapIncFloat(float a, float min, float max)324 inline 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.
generateCompareData(const deUint32 seed, const UVec2& imageSize, const deUint32 numCoverageSamples, const deUint32 numColorSamples, const deUint32 numDepthStencilSamples)331 std::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
368 template<typename SampleAccessor>
ndcTransformEachSampleInPixel(const UVec2& framebufferSize, const deUint32 numSamplesPerPixel, const SampleAccessor& access)369 std::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 
389 class AccessStandardSampleLocationsArray
390 {
391 public:
AccessStandardSampleLocationsArray(const Vec2* ptr)392 	AccessStandardSampleLocationsArray (const Vec2* ptr) : m_pData (ptr) {}
393 
operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const394 	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 
401 private:
402 	const Vec2*	m_pData;
403 };
404 
405 class AccessMultisamplePixelGrid
406 {
407 public:
AccessMultisamplePixelGrid(const MultisamplePixelGrid* ptr)408 	AccessMultisamplePixelGrid (const MultisamplePixelGrid* ptr) : m_pGrid (ptr) {}
409 
operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const410 	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 
416 private:
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
genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples, const UVec2& framebufferSize)422 std::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
getSampleLocations(const MultisamplePixelGrid& pixelGrid, const UVec2& framebufferSize)490 std::vector<Vec2> getSampleLocations (const MultisamplePixelGrid& pixelGrid, const UVec2& framebufferSize)
491 {
492 	return ndcTransformEachSampleInPixel(framebufferSize, pixelGrid.samplesPerPixel(), AccessMultisamplePixelGrid(&pixelGrid));
493 }
494 
495 struct PositionColor
496 {
497 	tcu::Vec4	position;
498 	tcu::Vec4	color;
499 
PositionColorvkt::pipeline::__anon28233::PositionColor500 	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.
generateSubpixelTriangles(const UVec2& renderSize, const std::vector<CompareData>& compareData, const std::vector<Vec2>& sampleLocations)505 std::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 
reportSampleError(tcu::TestLog& log, const std::string& sampleDesc, UVec2& renderSize, const deUint32 numCoverageSamples, const deUint32 globalSampleNdx)541 void 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 
checkSampleRequirements(Context& context, const VkSampleCountFlagBits numColorSamples, const VkSampleCountFlagBits numDepthStencilSamples, const bool requireStandardSampleLocations)551 void 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 
checkImageRequirements(Context& context, const VkFormat format, const VkFormatFeatureFlags requiredFeatureFlags, const VkImageUsageFlags requiredUsageFlags, const VkSampleCountFlagBits requiredSampleCount = VK_SAMPLE_COUNT_1_BIT)581 void 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)
recordCopyOutputImageToBuffer(const DeviceInterface& vk, const VkCommandBuffer cmdBuffer, const UVec2& imageSize, const VkImage srcImage, const VkBuffer dstBuffer)606 void 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 
664 namespace VerifySamples
665 {
666 
667 //! The parameters that define a test case
668 struct 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 
TestParamsvkt::pipeline::__anon28233::VerifySamples::TestParams684 	TestParams (void)
685 		: colorFormat						()
686 		, depthStencilFormat				()
687 		, useProgrammableSampleLocations	()
688 		, useFragmentShadingRate			()
689 	{
690 	}
691 };
692 
693 //! Common data used by the test
694 struct 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 
PerSubpassvkt::pipeline::__anon28233::VerifySamples::WorkingData::PerSubpass718 		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 
WorkingDatavkt::pipeline::__anon28233::VerifySamples::WorkingData732 	WorkingData (void)
733 		: sampleLocationsProperties ()
734 	{
735 	}
736 };
737 
addVerificationComputeShader(SourceCollections& programCollection, const VkSampleCountFlagBits numCoverageSamples, const VkSampleCountFlagBits numColorSamples, const VkSampleCountFlagBits numDepthStencilSamples, const VkFormat depthStencilFormat, const std::string& nameSuffix)738 void 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
getSampleCountString(const TestParams::SampleCount& samples)836 std::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 
initPrograms(SourceCollections& programCollection, const TestParams params)847 void 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
draw(Context& context, const TestParams& params, WorkingData& wd)901 void 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 
dispatchImageCheck(Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx)1092 void 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 
createPerSubpassData(Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx)1182 void 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 
checkRequirements(Context& context, TestParams params)1271 void 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.
test(Context& context, const TestParams params)1331 tcu::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 
1418 namespace ShaderBuiltins
1419 {
1420 
1421 struct 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 
1431 struct 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 
WorkingDatavkt::pipeline::__anon28233::ShaderBuiltins::WorkingData1452 	WorkingData (void)
1453 		: numVertices		()
1454 		, colorBufferSize	(0)
1455 	{
1456 	}
1457 };
1458 
initPrograms(SourceCollections& programCollection, const TestParams params)1459 void 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
drawResolve(Context& context, const TestParams& params, WorkingData& wd)1533 void 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 
checkRequirements(Context& context, TestParams params)1676 void 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
test(Context& context, const TestParams params)1685 tcu::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 
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, const VkSampleCountFlagBits colorCount, const VkSampleCountFlagBits depthStencilCount)1758 std::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 
getFormatShortString(const VkFormat format)1769 std::string getFormatShortString (const VkFormat format)
1770 {
1771 	std::string s(de::toLower(getFormatName(format)));
1772 	return s.substr(10);
1773 }
1774 
getFormatCaseName(const VkFormat colorFormat, const VkFormat depthStencilFormat)1775 std::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 
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate)1783 void 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 
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate)2024 tcu::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