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