• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Advanced Micro Devices, Inc.
6  * Copyright (c) 2017 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_EXT_sample_locations
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineMultisampleSampleLocationsExtTests.hpp"
26 #include "vktPipelineSampleLocationsUtil.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vktTestCaseUtil.hpp"
31 
32 #include "vkPlatform.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "deUniquePtr.hpp"
44 #include "deRandom.hpp"
45 #include "deMath.h"
46 
47 #include "tcuTestLog.hpp"
48 #include "tcuImageCompare.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuRGBA.hpp"
51 #include "tcuVectorUtil.hpp"
52 
53 #include <string>
54 #include <vector>
55 #include <set>
56 #include <algorithm>
57 
58 namespace vkt
59 {
60 namespace pipeline
61 {
62 namespace
63 {
64 using namespace vk;
65 using de::UniquePtr;
66 using de::MovePtr;
67 using tcu::Vec4;
68 using tcu::Vec2;
69 using tcu::UVec2;
70 using tcu::UVec4;
71 using tcu::RGBA;
72 
73 static const deUint32		STENCIL_REFERENCE	= 1u;
74 static const float			DEPTH_CLEAR			= 1.0f;
75 static const float			DEPTH_REFERENCE     = 0.5f;
76 static const Vec4			CLEAR_COLOR_0		= Vec4(0.0f, 0.0f,  0.0f,  1.0f);
77 static const Vec4			CLEAR_COLOR_1		= Vec4(0.5f, 0.25f, 0.75f, 1.0f);
78 static const VkDeviceSize	ZERO				= 0u;
79 
80 template<typename T>
dataOrNullPtr(const std::vector<T> & v)81 inline const T* dataOrNullPtr (const std::vector<T>& v)
82 {
83 	return (v.empty() ? DE_NULL : &v[0]);
84 }
85 
86 template<typename T>
dataOrNullPtr(std::vector<T> & v)87 inline T* dataOrNullPtr (std::vector<T>& v)
88 {
89 	return (v.empty() ? DE_NULL : &v[0]);
90 }
91 
92 template<typename T>
append(std::vector<T> & first,const std::vector<T> & second)93 inline void append (std::vector<T>& first, const std::vector<T>& second)
94 {
95 	first.insert(first.end(), second.begin(), second.end());
96 }
97 
98 //! Order a Vector by X, Y, Z, and W
99 template<typename VectorT>
100 struct LessThan
101 {
operator ()vkt::pipeline::__anon990dfa0c0111::LessThan102 	bool operator()(const VectorT& v1, const VectorT& v2) const
103 	{
104 		for (int i = 0; i < VectorT::SIZE; ++i)
105 		{
106 			if (v1[i] == v2[i])
107 				continue;
108 			else
109 				return v1[i] < v2[i];
110 		}
111 
112 		return false;
113 	}
114 };
115 
116 //! Similar to the class in vktTestCaseUtil.hpp, but uses Arg0 directly rather than through a InstanceFunction1
117 template<typename Arg0>
118 class FunctionProgramsSimple1
119 {
120 public:
121 	typedef void	(*Function)				(vk::SourceCollections& dst, Arg0 arg0);
FunctionProgramsSimple1(Function func)122 					FunctionProgramsSimple1	(Function func) : m_func(func)							{}
init(vk::SourceCollections & dst,const Arg0 & arg0) const123 	void			init					(vk::SourceCollections& dst, const Arg0& arg0) const	{ m_func(dst, arg0); }
124 
125 private:
126 	const Function	m_func;
127 };
128 
129 //! Convenience function to create a TestCase based on a freestanding initPrograms and a TestInstance implementation
130 template<typename Instance, typename Arg0>
addInstanceTestCaseWithPrograms(tcu::TestCaseGroup * group,const std::string & name,const std::string & desc,typename FunctionSupport1<Arg0>::Function checkSupport,typename FunctionProgramsSimple1<Arg0>::Function initPrograms,Arg0 arg0)131 void addInstanceTestCaseWithPrograms (tcu::TestCaseGroup*								group,
132 									  const std::string&								name,
133 									  const std::string&								desc,
134 									  typename FunctionSupport1<Arg0>::Function			checkSupport,
135 									  typename FunctionProgramsSimple1<Arg0>::Function	initPrograms,
136 									  Arg0												arg0)
137 {
138 	group->addChild(new InstanceFactory1WithSupport<Instance, Arg0, FunctionSupport1<Arg0>, FunctionProgramsSimple1<Arg0> >(
139 		group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, FunctionProgramsSimple1<Arg0>(initPrograms), arg0, typename FunctionSupport1<Arg0>::Args(checkSupport, arg0)));
140 }
141 
checkSupportSampleLocations(Context & context)142 void checkSupportSampleLocations (Context& context)
143 {
144 	context.requireDeviceFunctionality("VK_EXT_sample_locations");
145 }
146 
getString(const VkSampleCountFlagBits sampleCount)147 std::string getString (const VkSampleCountFlagBits sampleCount)
148 {
149 	std::ostringstream str;
150 	str << "samples_" << static_cast<deUint32>(sampleCount);
151 	return str.str();
152 }
153 
isSupportedDepthStencilFormat(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkFormat format)154 bool isSupportedDepthStencilFormat (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
155 {
156 	VkFormatProperties formatProps;
157 	vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps);
158 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
159 }
160 
findSupportedDepthStencilFormat(Context & context,const bool useDepth,const bool useStencil)161 VkFormat findSupportedDepthStencilFormat (Context& context, const bool useDepth, const bool useStencil)
162 {
163 	const InstanceInterface&	vki			= context.getInstanceInterface();
164 	const VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
165 
166 	if (useDepth && !useStencil)
167 		return VK_FORMAT_D16_UNORM;		// must be supported
168 
169 	// One of these formats must be supported.
170 
171 	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT))
172 		return VK_FORMAT_D24_UNORM_S8_UINT;
173 
174 	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D32_SFLOAT_S8_UINT))
175 		return VK_FORMAT_D32_SFLOAT_S8_UINT;
176 
177 	return VK_FORMAT_UNDEFINED;
178 }
179 
checkFragmentShadingRateRequirements(Context & context,deUint32 sampleCount)180 void checkFragmentShadingRateRequirements(Context& context, deUint32 sampleCount)
181 {
182 	const auto&	vki = context.getInstanceInterface();
183 	const auto	physicalDevice = context.getPhysicalDevice();
184 
185 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
186 
187 	if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
188 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
189 
190 	// Fetch information about supported fragment shading rates
191 	deUint32 supportedFragmentShadingRateCount = 0;
192 	vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
193 
194 	std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(supportedFragmentShadingRateCount,
195 		{
196 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
197 			DE_NULL,
198 			vk::VK_SAMPLE_COUNT_1_BIT,
199 			{1, 1}
200 		});
201 	vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, supportedFragmentShadingRates.data());
202 
203 	bool requiredRateFound = false;
204 	for (const auto& rate : supportedFragmentShadingRates)
205 	{
206 		if ((rate.fragmentSize.width == 2u) &&
207 			(rate.fragmentSize.height == 2u) &&
208 			(rate.sampleCounts & sampleCount))
209 		{
210 			requiredRateFound = true;
211 			break;
212 		}
213 	}
214 
215 	if (!requiredRateFound)
216 		TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
217 }
218 
getImageAspectFlags(const VkFormat format)219 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
220 {
221 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
222 
223 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
224 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
225 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
226 
227 	DE_FATAL("Format not handled");
228 	return 0u;
229 }
230 
getSampleLocationsPropertiesEXT(Context & context)231 VkPhysicalDeviceSampleLocationsPropertiesEXT getSampleLocationsPropertiesEXT (Context& context)
232 {
233 	const InstanceInterface&	vki				= context.getInstanceInterface();
234 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
235 
236 	VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties;
237 	deMemset(&sampleLocationsProperties, 0, sizeof(sampleLocationsProperties));
238 
239 	sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
240 	sampleLocationsProperties.pNext = DE_NULL;
241 
242 	VkPhysicalDeviceProperties2 properties =
243 	{
244 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,			// VkStructureType               sType;
245 		&sampleLocationsProperties,								// void*                         pNext;
246 		VkPhysicalDeviceProperties(),							// VkPhysicalDeviceProperties    properties;
247 	};
248 
249 	vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
250 
251 	return sampleLocationsProperties;
252 }
253 
numSamplesPerPixel(const MultisamplePixelGrid & pixelGrid)254 inline deUint32 numSamplesPerPixel (const MultisamplePixelGrid& pixelGrid)
255 {
256 	return static_cast<deUint32>(pixelGrid.samplesPerPixel());
257 }
258 
makeEmptySampleLocationsInfo()259 inline VkSampleLocationsInfoEXT makeEmptySampleLocationsInfo ()
260 {
261 	const VkSampleLocationsInfoEXT info =
262 	{
263 		VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,				// VkStructureType               sType;
264 		DE_NULL,													// const void*                   pNext;
265 		(VkSampleCountFlagBits)0,									// VkSampleCountFlagBits         sampleLocationsPerPixel;
266 		makeExtent2D(0,0),											// VkExtent2D                    sampleLocationGridSize;
267 		0,															// uint32_t                      sampleLocationsCount;
268 		DE_NULL,													// const VkSampleLocationEXT*    pSampleLocations;
269 	};
270 	return info;
271 }
272 
logPixelGrid(tcu::TestLog & log,const VkPhysicalDeviceSampleLocationsPropertiesEXT & sampleLocationsProperties,const MultisamplePixelGrid & pixelGrid)273 void logPixelGrid (tcu::TestLog& log, const VkPhysicalDeviceSampleLocationsPropertiesEXT& sampleLocationsProperties, const MultisamplePixelGrid& pixelGrid)
274 {
275 	log << tcu::TestLog::Section("pixelGrid", "Multisample pixel grid configuration:")
276 		<< tcu::TestLog::Message << sampleLocationsProperties << tcu::TestLog::EndMessage
277 		<< tcu::TestLog::Message << "Specified grid size = " << pixelGrid.size() << tcu::TestLog::EndMessage;
278 
279 	for (deUint32 gridY = 0; gridY < pixelGrid.size().y(); ++gridY)
280 	for (deUint32 gridX = 0; gridX < pixelGrid.size().x(); ++gridX)
281 	{
282 		log << tcu::TestLog::Message << "Pixel(" << gridX << ", " << gridY <<")" << tcu::TestLog::EndMessage;
283 
284 		for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(pixelGrid); ++sampleNdx)
285 		{
286 			const VkSampleLocationEXT& loc = pixelGrid.getSample(gridX, gridY, sampleNdx);
287 			log << tcu::TestLog::Message << "* Sample(" << sampleNdx <<") = " << Vec2(loc.x, loc.y) << tcu::TestLog::EndMessage;
288 		}
289 	}
290 
291 	log << tcu::TestLog::Message << "Sample locations visualization" << tcu::TestLog::EndMessage;
292 
293 	{
294 		const deUint32		height	= deMinu32(1u << sampleLocationsProperties.sampleLocationSubPixelBits, 16u);	// increase if you want more precision
295 		const deUint32		width	= 2 * height;	// works well with a fixed-size font
296 		std::vector<char>	buffer	(width * height);
297 
298 		for (deUint32 gridY = 0; gridY < pixelGrid.size().y(); ++gridY)
299 		for (deUint32 gridX = 0; gridX < pixelGrid.size().x(); ++gridX)
300 		{
301 			std::fill(buffer.begin(), buffer.end(), '.');
302 
303 			for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(pixelGrid); ++sampleNdx)
304 			{
305 				const VkSampleLocationEXT&	loc		= pixelGrid.getSample(gridX, gridY, sampleNdx);
306 				const deUint32				ndx		= deMinu32(width  - 1, static_cast<deUint32>(static_cast<float>(width)  * loc.x)) +
307 													  deMinu32(height - 1, static_cast<deUint32>(static_cast<float>(height) * loc.y)) * width;
308 				const deUint32				evenNdx = ndx - ndx % 2;
309 
310 				buffer[evenNdx    ] = '[';
311 				buffer[evenNdx + 1] = ']';
312 			}
313 
314 			std::ostringstream str;
315 			str << "Pixel(" << gridX << ", " << gridY <<")\n";
316 
317 			for (deUint32 lineNdx = 0; lineNdx < height; ++lineNdx)
318 			{
319 				str.write(&buffer[width * lineNdx], width);
320 				str << "\n";
321 			}
322 
323 			log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
324 		}
325 	}
326 
327 	log << tcu::TestLog::EndSection;
328 }
329 
330 //! Place samples very close to each other
fillSampleLocationsPacked(MultisamplePixelGrid & grid,const deUint32 subPixelBits)331 void fillSampleLocationsPacked (MultisamplePixelGrid& grid, const deUint32 subPixelBits)
332 {
333 	const deUint32	numLocations	= 1u << subPixelBits;
334 	const int		offset[3]		= { -1, 0, 1 };
335 	de::Random		rng				(214);
336 
337 	for (deUint32 gridY = 0; gridY < grid.size().y(); ++gridY)
338 	for (deUint32 gridX = 0; gridX < grid.size().x(); ++gridX)
339 	{
340 		// Will start placing from this location
341 		const UVec2 baseLocationNdx (rng.getUint32() % numLocations,
342 									 rng.getUint32() % numLocations);
343 		UVec2		locationNdx		= baseLocationNdx;
344 
345 		std::set<UVec2, LessThan<UVec2> >	takenLocationIndices;
346 		for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(grid); /* no increment */)
347 		{
348 			if (takenLocationIndices.find(locationNdx) == takenLocationIndices.end())
349 			{
350 				const VkSampleLocationEXT location =
351 				{
352 					static_cast<float>(locationNdx.x()) / static_cast<float>(numLocations),	// float x;
353 					static_cast<float>(locationNdx.y()) / static_cast<float>(numLocations),	// float y;
354 				};
355 
356 				grid.setSample(gridX, gridY, sampleNdx, location);
357 				takenLocationIndices.insert(locationNdx);
358 
359 				++sampleNdx;	// next sample
360 			}
361 
362 			// Find next location by applying a small offset. Just keep iterating if a redundant location is chosen
363 			locationNdx.x() = static_cast<deUint32>(deClamp32(locationNdx.x() + offset[rng.getUint32() % DE_LENGTH_OF_ARRAY(offset)], 0u, numLocations - 1));
364 			locationNdx.y() = static_cast<deUint32>(deClamp32(locationNdx.y() + offset[rng.getUint32() % DE_LENGTH_OF_ARRAY(offset)], 0u, numLocations - 1));
365 		}
366 	}
367 }
368 
369 //! Unorm/int compare, very low threshold as we are expecting near-exact values
compareGreenImage(tcu::TestLog & log,const char * name,const char * description,const tcu::ConstPixelBufferAccess & image)370 bool compareGreenImage (tcu::TestLog& log, const char* name, const char* description, const tcu::ConstPixelBufferAccess& image)
371 {
372 	tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight());
373 	tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec());
374 	return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u), tcu::COMPARE_LOG_RESULT);
375 }
376 
377 //! Silent compare - no logging
intThresholdCompare(const tcu::ConstPixelBufferAccess & reference,const tcu::ConstPixelBufferAccess & result,const UVec4 & threshold)378 bool intThresholdCompare (const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const UVec4& threshold)
379 {
380 	using namespace tcu;
381 
382 	int						width				= reference.getWidth();
383 	int						height				= reference.getHeight();
384 	int						depth				= reference.getDepth();
385 	UVec4					maxDiff				(0, 0, 0, 0);
386 
387 	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
388 
389 	for (int z = 0; z < depth; z++)
390 	{
391 		for (int y = 0; y < height; y++)
392 		{
393 			for (int x = 0; x < width; x++)
394 			{
395 				IVec4	refPix	= reference.getPixelInt(x, y, z);
396 				IVec4	cmpPix	= result.getPixelInt(x, y, z);
397 				UVec4	diff	= abs(refPix - cmpPix).cast<deUint32>();
398 
399 				maxDiff = max(maxDiff, diff);
400 			}
401 		}
402 	}
403 
404 	return boolAll(lessThanEqual(maxDiff, threshold));
405 }
406 
countUniqueColors(const tcu::ConstPixelBufferAccess & image)407 int countUniqueColors (const tcu::ConstPixelBufferAccess& image)
408 {
409 	std::set<Vec4, LessThan<Vec4> > colors;
410 
411 	for (int y = 0; y < image.getHeight(); ++y)
412 	for (int x = 0; x < image.getWidth();  ++x)
413 	{
414 		colors.insert(image.getPixel(x, y));
415 	}
416 
417 	return static_cast<int>(colors.size());
418 }
419 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkImageCreateFlags flags,const VkFormat format,const UVec2 & size,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)420 Move<VkImage> makeImage (const DeviceInterface&			vk,
421 						 const VkDevice					device,
422 						 const VkImageCreateFlags		flags,
423 						 const VkFormat					format,
424 						 const UVec2&					size,
425 						 const VkSampleCountFlagBits	samples,
426 						 const VkImageUsageFlags		usage)
427 {
428 	const VkImageCreateInfo imageParams =
429 	{
430 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
431 		DE_NULL,										// const void*				pNext;
432 		flags,											// VkImageCreateFlags		flags;
433 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
434 		format,											// VkFormat					format;
435 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
436 		1u,												// deUint32					mipLevels;
437 		1u,												// deUint32					arrayLayers;
438 		samples,										// VkSampleCountFlagBits	samples;
439 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
440 		usage,											// VkImageUsageFlags		usage;
441 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
442 		0u,												// deUint32					queueFamilyIndexCount;
443 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
444 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
445 	};
446 	return createImage(vk, device, &imageParams);
447 }
448 
makeEvent(const DeviceInterface & vk,const VkDevice device)449 Move<VkEvent> makeEvent (const DeviceInterface& vk, const VkDevice device)
450 {
451 	const VkEventCreateInfo createInfo =
452 	{
453 		VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,		// VkStructureType       sType;
454 		DE_NULL,									// const void*           pNext;
455 		(VkEventCreateFlags)0,						// VkEventCreateFlags    flags;
456 	};
457 	return createEvent(vk, device, &createInfo);
458 }
459 
460 //! Generate NDC space sample locations at each framebuffer pixel
461 //! Data is filled starting at pixel (0,0) and for each pixel there are numSamples locations
genFramebufferSampleLocations(const MultisamplePixelGrid & pixelGrid,const UVec2 & gridSize,const UVec2 & framebufferSize)462 std::vector<Vec2> genFramebufferSampleLocations (const MultisamplePixelGrid& pixelGrid, const UVec2& gridSize, const UVec2& framebufferSize)
463 {
464 	std::vector<Vec2>	locations;
465 
466 	for (deUint32 y			= 0; y			< framebufferSize.y();				++y)
467 	for (deUint32 x			= 0; x			< framebufferSize.x();				++x)
468 	for (deUint32 sampleNdx	= 0; sampleNdx	< numSamplesPerPixel(pixelGrid);	++sampleNdx)
469 	{
470 		const VkSampleLocationEXT&	location = pixelGrid.getSample(x % gridSize.x(), y % gridSize.y(), sampleNdx);
471 		const float					globalX  = location.x + static_cast<float>(x);
472 		const float					globalY  = location.y + static_cast<float>(y);
473 
474 		// Transform to [-1, 1] space
475 		locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())),
476 								 -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y()))));
477 	}
478 
479 	return locations;
480 }
481 
482 struct PositionColor
483 {
484 	tcu::Vec4	position;
485 	tcu::Vec4	color;
486 
PositionColorvkt::pipeline::__anon990dfa0c0111::PositionColor487 	PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos), color(col) {}
488 };
489 
genVerticesFullQuad(const Vec4 & color=Vec4 (1.0f),const float z=0.0f)490 std::vector<PositionColor> genVerticesFullQuad (const Vec4& color = Vec4(1.0f), const float z = 0.0f)
491 {
492 	const PositionColor vertices[] =
493 	{
494 		PositionColor(Vec4( 1.0f, -1.0f, z, 1.0f), color),
495 		PositionColor(Vec4(-1.0f, -1.0f, z, 1.0f), color),
496 		PositionColor(Vec4(-1.0f,  1.0f, z, 1.0f), color),
497 
498 		PositionColor(Vec4(-1.0f,  1.0f, z, 1.0f), color),
499 		PositionColor(Vec4( 1.0f,  1.0f, z, 1.0f), color),
500 		PositionColor(Vec4( 1.0f, -1.0f, z, 1.0f), color),
501 	};
502 
503 	return std::vector<PositionColor>(vertices, vertices + DE_LENGTH_OF_ARRAY(vertices));
504 }
505 
506 //! Some abstract geometry with angled edges, to make multisampling visible.
genVerticesShapes(const Vec4 & color=Vec4 (1.0f),const float z=0.0f)507 std::vector<PositionColor> genVerticesShapes (const Vec4& color = Vec4(1.0f), const float z = 0.0f)
508 {
509 	std::vector<PositionColor> vertices;
510 
511 	const float numSteps  = 16.0f;
512 	const float angleStep = (2.0f * DE_PI) / numSteps;
513 
514 	for (float a = 0.0f; a <= 2.0f * DE_PI; a += angleStep)
515 	{
516 		vertices.push_back(PositionColor(Vec4(1.0f * deFloatCos(a),				1.0f * deFloatSin(a),				z, 1.0f), color));
517 		vertices.push_back(PositionColor(Vec4(0.1f * deFloatCos(a - angleStep), 0.1f * deFloatSin(a - angleStep),	z, 1.0f), color));
518 		vertices.push_back(PositionColor(Vec4(0.1f * deFloatCos(a + angleStep), 0.1f * deFloatSin(a + angleStep),	z, 1.0f), color));
519 	}
520 
521 	return vertices;
522 }
523 
524 //! Stencil op that only allows drawing over the cleared area of an attachment.
stencilOpStateDrawOnce(void)525 inline VkStencilOpState stencilOpStateDrawOnce (void)
526 {
527 	return makeStencilOpState(
528 		VK_STENCIL_OP_KEEP,		// stencil fail
529 		VK_STENCIL_OP_ZERO,		// depth & stencil pass
530 		VK_STENCIL_OP_KEEP,		// depth only fail
531 		VK_COMPARE_OP_EQUAL,	// compare op
532 		~0u,					// compare mask
533 		~0u,					// write mask
534 		STENCIL_REFERENCE);		// reference
535 }
536 
537 //! Stencil op that simply increments the buffer with each passing test.
stencilOpStateIncrement(void)538 inline VkStencilOpState stencilOpStateIncrement(void)
539 {
540 	return makeStencilOpState(
541 		VK_STENCIL_OP_KEEP,						// stencil fail
542 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,		// depth & stencil pass
543 		VK_STENCIL_OP_KEEP,						// depth only fail
544 		VK_COMPARE_OP_ALWAYS,					// compare op
545 		~0u,									// compare mask
546 		~0u,									// write mask
547 		STENCIL_REFERENCE);						// reference
548 }
549 
550 //! A few preconfigured vertex attribute configurations
551 enum VertexInputConfig
552 {
553 	VERTEX_INPUT_NONE = 0u,
554 	VERTEX_INPUT_VEC4,
555 	VERTEX_INPUT_VEC4_VEC4,
556 };
557 
558 //! Create a MSAA pipeline, with max per-sample shading
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const std::vector<VkDynamicState> & dynamicState,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const deUint32 subpassIndex,const VkViewport & viewport,const VkRect2D scissor,const VkSampleCountFlagBits numSamples,const bool useSampleLocations,const VkSampleLocationsInfoEXT & sampleLocationsInfo,const bool useDepth,const bool useStencil,const VertexInputConfig vertexInputConfig,const VkPrimitiveTopology topology,const VkStencilOpState & stencilOpState,const bool useFragmentShadingRate)559 void preparePipelineWrapper (GraphicsPipelineWrapper&			gpw,
560 							 const std::vector<VkDynamicState>&	dynamicState,
561 							 const VkPipelineLayout				pipelineLayout,
562 							 const VkRenderPass					renderPass,
563 							 const VkShaderModule				vertexModule,
564 							 const VkShaderModule				fragmentModule,
565 							 const deUint32						subpassIndex,
566 							 const VkViewport&					viewport,
567 							 const VkRect2D						scissor,
568 							 const VkSampleCountFlagBits		numSamples,
569 							 const bool							useSampleLocations,
570 							 const VkSampleLocationsInfoEXT&	sampleLocationsInfo,
571 							 const bool							useDepth,
572 							 const bool							useStencil,
573 							 const VertexInputConfig			vertexInputConfig,
574 							 const VkPrimitiveTopology			topology,
575 							 const VkStencilOpState&			stencilOpState,
576 							 const bool							useFragmentShadingRate)
577 {
578 	std::vector<VkVertexInputBindingDescription>	vertexInputBindingDescriptions;
579 	std::vector<VkVertexInputAttributeDescription>	vertexInputAttributeDescriptions;
580 
581 	const deUint32 sizeofVec4 = static_cast<deUint32>(sizeof(Vec4));
582 
583 	switch (vertexInputConfig)
584 	{
585 	case VERTEX_INPUT_NONE:
586 		break;
587 
588 	case VERTEX_INPUT_VEC4:
589 		vertexInputBindingDescriptions.push_back(makeVertexInputBindingDescription(0u, sizeofVec4, VK_VERTEX_INPUT_RATE_VERTEX));
590 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
591 		break;
592 
593 	case VERTEX_INPUT_VEC4_VEC4:
594 		vertexInputBindingDescriptions.push_back(makeVertexInputBindingDescription(0u, 2u * sizeofVec4, VK_VERTEX_INPUT_RATE_VERTEX));
595 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
596 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeofVec4));
597 		break;
598 
599 	default:
600 		DE_FATAL("Vertex input config not supported");
601 		break;
602 	}
603 
604 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
605 	{
606 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
607 		DE_NULL,														// const void*								pNext;
608 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
609 		static_cast<deUint32>(vertexInputBindingDescriptions.size()),	// uint32_t									vertexBindingDescriptionCount;
610 		dataOrNullPtr(vertexInputBindingDescriptions),					// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
611 		static_cast<deUint32>(vertexInputAttributeDescriptions.size()),	// uint32_t									vertexAttributeDescriptionCount;
612 		dataOrNullPtr(vertexInputAttributeDescriptions),				// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
613 	};
614 
615 	const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo =
616 	{
617 		VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,	// VkStructureType             sType;
618 		DE_NULL,															// const void*                 pNext;
619 		useSampleLocations,													// VkBool32                    sampleLocationsEnable;
620 		sampleLocationsInfo,												// VkSampleLocationsInfoEXT    sampleLocationsInfo;
621 	};
622 
623 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
624 	{
625 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
626 		&pipelineSampleLocationsCreateInfo,							// const void*								pNext;
627 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
628 		numSamples,													// VkSampleCountFlagBits					rasterizationSamples;
629 		VK_TRUE,													// VkBool32									sampleShadingEnable;
630 		1.0f,														// float									minSampleShading;
631 		DE_NULL,													// const VkSampleMask*						pSampleMask;
632 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
633 		VK_FALSE													// VkBool32									alphaToOneEnable;
634 	};
635 
636 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
637 	{
638 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
639 		DE_NULL,													// const void*								pNext;
640 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
641 		useDepth,													// VkBool32									depthTestEnable;
642 		true,														// VkBool32									depthWriteEnable;
643 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
644 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
645 		useStencil,													// VkBool32									stencilTestEnable;
646 		stencilOpState,												// VkStencilOpState							front;
647 		stencilOpState,												// VkStencilOpState							back;
648 		0.0f,														// float									minDepthBounds;
649 		1.0f,														// float									maxDepthBounds;
650 	};
651 
652 	const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
653 	{
654 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType						sType;
655 		DE_NULL,													// const void*							pNext;
656 		(VkPipelineDynamicStateCreateFlags)0,						// VkPipelineDynamicStateCreateFlags	flags;
657 		static_cast<deUint32>(dynamicState.size()),					// uint32_t								dynamicStateCount;
658 		dataOrNullPtr(dynamicState),								// const VkDynamicState*				pDynamicStates;
659 	};
660 
661 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState
662 	{
663 		VK_FALSE,																								// VkBool32                 blendEnable
664 		VK_BLEND_FACTOR_ZERO,																					// VkBlendFactor            srcColorBlendFactor
665 		VK_BLEND_FACTOR_ZERO,																					// VkBlendFactor            dstColorBlendFactor
666 		VK_BLEND_OP_ADD,																						// VkBlendOp                colorBlendOp
667 		VK_BLEND_FACTOR_ZERO,																					// VkBlendFactor            srcAlphaBlendFactor
668 		VK_BLEND_FACTOR_ZERO,																					// VkBlendFactor            dstAlphaBlendFactor
669 		VK_BLEND_OP_ADD,																						// VkBlendOp                alphaBlendOp
670 		VK_COLOR_COMPONENT_R_BIT																				// VkColorComponentFlags    colorWriteMask
671 		| VK_COLOR_COMPONENT_G_BIT
672 		| VK_COLOR_COMPONENT_B_BIT
673 		| VK_COLOR_COMPONENT_A_BIT
674 	};
675 
676 	VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoDefault = initVulkanStructure();
677 	colorBlendStateCreateInfoDefault.attachmentCount	= 1u;
678 	colorBlendStateCreateInfoDefault.pAttachments		= &colorBlendAttachmentState;
679 
680 	const std::vector<VkViewport>	viewports	{ viewport };
681 	const std::vector<VkRect2D>		scissors	{ scissor };
682 
683 	VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo
684 	{
685 		VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,									// VkStructureType						sType;
686 		DE_NULL,																								// const void*							pNext;
687 		{ 2, 2 },																								// VkExtent2D							fragmentSize;
688 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR },		// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
689 	};
690 
691 	gpw.setDefaultTopology(topology)
692 	   .setDynamicState(&dynamicStateCreateInfo)
693 	   .setDefaultRasterizationState()
694 	   .setupVertexInputState(&vertexInputStateInfo)
695 	   .setupPreRasterizationShaderState(viewports,
696 								scissors,
697 								pipelineLayout,
698 								renderPass,
699 								subpassIndex,
700 								vertexModule,
701 								nullptr, DE_NULL, DE_NULL, DE_NULL, DE_NULL,
702 								(useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr))
703 	   .setupFragmentShaderState(pipelineLayout,
704 								renderPass,
705 								subpassIndex,
706 								fragmentModule,
707 								&pipelineDepthStencilStateInfo,
708 								&pipelineMultisampleStateInfo)
709 	   .setupFragmentOutputState(renderPass, subpassIndex, &colorBlendStateCreateInfoDefault, &pipelineMultisampleStateInfo)
710 	   .setMonolithicPipelineLayout(pipelineLayout)
711 	   .buildPipeline();
712 }
713 
preparePipelineWrapperSinglePassColor(GraphicsPipelineWrapper & gpw,const std::vector<VkDynamicState> & dynamicState,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const VkViewport & viewport,const VkRect2D scissor,const VkSampleCountFlagBits numSamples,const bool useSampleLocations,const VkSampleLocationsInfoEXT & sampleLocationsInfo,const VertexInputConfig vertexInputConfig,const VkPrimitiveTopology topology,const bool useFragmentShadingRate)714 void preparePipelineWrapperSinglePassColor (GraphicsPipelineWrapper&			gpw,
715 											const std::vector<VkDynamicState>&	dynamicState,
716 											const VkPipelineLayout				pipelineLayout,
717 											const VkRenderPass					renderPass,
718 											const VkShaderModule				vertexModule,
719 											const VkShaderModule				fragmentModule,
720 											const VkViewport&					viewport,
721 											const VkRect2D						scissor,
722 											const VkSampleCountFlagBits			numSamples,
723 											const bool							useSampleLocations,
724 											const VkSampleLocationsInfoEXT&		sampleLocationsInfo,
725 											const VertexInputConfig				vertexInputConfig,
726 											const VkPrimitiveTopology			topology,
727 											const bool							useFragmentShadingRate)
728 {
729 	preparePipelineWrapper(gpw, dynamicState, pipelineLayout, renderPass, vertexModule, fragmentModule,
730 						   /*subpass*/ 0u, viewport, scissor, numSamples, useSampleLocations, sampleLocationsInfo,
731 						   /*depth test*/ false, /*stencil test*/ false, vertexInputConfig, topology, stencilOpStateIncrement(), useFragmentShadingRate);
732 }
733 
734 //! Utility to build and maintain render pass, framebuffer and related resources.
735 //! Use bake() before using the render pass.
736 class RenderTarget
737 {
738 public:
RenderTarget(void)739 	RenderTarget (void)
740 	{
741 		nextSubpass();
742 	}
743 
744 	//! Returns an attachment index that is used to reference this attachment later
addAttachment(const VkImageView imageView,const VkAttachmentDescriptionFlags flags,const VkFormat format,const VkSampleCountFlagBits numSamples,const VkAttachmentLoadOp loadOp,const VkAttachmentStoreOp storeOp,const VkAttachmentLoadOp stencilLoadOp,const VkAttachmentStoreOp stencilStoreOp,const VkImageLayout initialLayout,const VkImageLayout finalLayout,const VkClearValue clearValue,const VkSampleLocationsInfoEXT * pInitialSampleLocations=DE_NULL)745 	deUint32 addAttachment (const VkImageView					imageView,
746 							const VkAttachmentDescriptionFlags	flags,
747 							const VkFormat						format,
748 							const VkSampleCountFlagBits			numSamples,
749 							const VkAttachmentLoadOp			loadOp,
750 							const VkAttachmentStoreOp			storeOp,
751 							const VkAttachmentLoadOp			stencilLoadOp,
752 							const VkAttachmentStoreOp			stencilStoreOp,
753 							const VkImageLayout					initialLayout,
754 							const VkImageLayout					finalLayout,
755 							const VkClearValue					clearValue,
756 							const VkSampleLocationsInfoEXT*		pInitialSampleLocations = DE_NULL)
757 	{
758 		const deUint32 index = static_cast<deUint32>(m_attachments.size());
759 
760 		m_attachments.push_back(imageView);
761 		m_attachmentDescriptions.push_back(makeAttachmentDescription(
762 			flags,										// VkAttachmentDescriptionFlags		flags;
763 			format,										// VkFormat							format;
764 			numSamples,									// VkSampleCountFlagBits			samples;
765 			loadOp,										// VkAttachmentLoadOp				loadOp;
766 			storeOp,									// VkAttachmentStoreOp				storeOp;
767 			stencilLoadOp,								// VkAttachmentLoadOp				stencilLoadOp;
768 			stencilStoreOp,								// VkAttachmentStoreOp				stencilStoreOp;
769 			initialLayout,								// VkImageLayout					initialLayout;
770 			finalLayout									// VkImageLayout					finalLayout;
771 		));
772 		m_clearValues.push_back(clearValue);			// always add, even if unused
773 
774 		if (pInitialSampleLocations)
775 		{
776 			const VkAttachmentSampleLocationsEXT attachmentSampleLocations =
777 			{
778 				index,						// uint32_t                    attachmentIndex;
779 				*pInitialSampleLocations,	// VkSampleLocationsInfoEXT    sampleLocationsInfo;
780 			};
781 			m_attachmentSampleLocations.push_back(attachmentSampleLocations);
782 		}
783 
784 		return index;
785 	}
786 
addSubpassColorAttachment(const deUint32 attachmentIndex,const VkImageLayout subpassLayout)787 	void addSubpassColorAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout)
788 	{
789 		m_subpasses.back().colorAttachmentReferences.push_back(
790 			makeAttachmentReference(attachmentIndex, subpassLayout));
791 		m_subpasses.back().resolveAttachmentReferences.push_back(
792 			makeAttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_UNDEFINED));
793 	}
794 
addSubpassColorAttachmentWithResolve(const deUint32 colorAttachmentIndex,const VkImageLayout colorSubpassLayout,const deUint32 resolveAttachmentIndex,const VkImageLayout resolveSubpassLayout,const VkSampleLocationsInfoEXT * pSampleLocations=DE_NULL)795 	void addSubpassColorAttachmentWithResolve (const deUint32 colorAttachmentIndex, const VkImageLayout colorSubpassLayout, const deUint32 resolveAttachmentIndex, const VkImageLayout resolveSubpassLayout, const VkSampleLocationsInfoEXT* pSampleLocations = DE_NULL)
796 	{
797 		m_subpasses.back().colorAttachmentReferences.push_back(
798 			makeAttachmentReference(colorAttachmentIndex, colorSubpassLayout));
799 		m_subpasses.back().resolveAttachmentReferences.push_back(
800 			makeAttachmentReference(resolveAttachmentIndex, resolveSubpassLayout));
801 
802 		if (pSampleLocations)
803 		{
804 			const VkSubpassSampleLocationsEXT subpassSampleLocations =
805 			{
806 				static_cast<deUint32>(m_subpasses.size() - 1),		// uint32_t                    subpassIndex;
807 				*pSampleLocations,									// VkSampleLocationsInfoEXT    sampleLocationsInfo;
808 			};
809 			m_subpassSampleLocations.push_back(subpassSampleLocations);
810 		}
811 	}
812 
addSubpassDepthStencilAttachment(const deUint32 attachmentIndex,const VkImageLayout subpassLayout,const VkSampleLocationsInfoEXT * pSampleLocations=DE_NULL)813 	void addSubpassDepthStencilAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout, const VkSampleLocationsInfoEXT* pSampleLocations = DE_NULL)
814 	{
815 		m_subpasses.back().depthStencilAttachmentReferences.push_back(
816 			makeAttachmentReference(attachmentIndex, subpassLayout));
817 
818 		if (pSampleLocations)
819 		{
820 			const VkSubpassSampleLocationsEXT subpassSampleLocations =
821 			{
822 				static_cast<deUint32>(m_subpasses.size() - 1),		// uint32_t                    subpassIndex;
823 				*pSampleLocations,									// VkSampleLocationsInfoEXT    sampleLocationsInfo;
824 			};
825 			m_subpassSampleLocations.push_back(subpassSampleLocations);
826 		}
827 	}
828 
addSubpassInputAttachment(const deUint32 attachmentIndex,const VkImageLayout subpassLayout)829 	void addSubpassInputAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout)
830 	{
831 		m_subpasses.back().inputAttachmentReferences.push_back(
832 			makeAttachmentReference(attachmentIndex, subpassLayout));
833 	}
834 
addSubpassPreserveAttachment(const deUint32 attachmentIndex)835 	void addSubpassPreserveAttachment (const deUint32 attachmentIndex)
836 	{
837 		m_subpasses.back().preserveAttachmentReferences.push_back(attachmentIndex);
838 	}
839 
nextSubpass(void)840 	void nextSubpass (void)
841 	{
842 		m_subpasses.push_back(SubpassDescription());
843 	}
844 
845 	//! Create a RenderPass and Framebuffer based on provided attachments
bake(const DeviceInterface & vk,const VkDevice device,const UVec2 & framebufferSize)846 	void bake (const DeviceInterface&							vk,
847 			   const VkDevice									device,
848 			   const UVec2&										framebufferSize)
849 	{
850 		DE_ASSERT(!m_renderPass);
851 		const deUint32 numSubpasses = static_cast<deUint32>(m_subpasses.size());
852 
853 		std::vector<VkSubpassDescription>	subpassDescriptions;
854 		std::vector<VkSubpassDependency>	subpassDependencies;
855 		for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
856 		{
857 			const SubpassDescription&	sd			= m_subpasses[subpassNdx];
858 			const VkSubpassDescription	description	=
859 			{
860 				(VkSubpassDescriptionFlags)0,									// VkSubpassDescriptionFlags		flags;
861 				VK_PIPELINE_BIND_POINT_GRAPHICS,								// VkPipelineBindPoint				pipelineBindPoint;
862 				static_cast<deUint32>(sd.inputAttachmentReferences.size()),		// deUint32							inputAttachmentCount;
863 				dataOrNullPtr(sd.inputAttachmentReferences),					// const VkAttachmentReference*		pInputAttachments;
864 				static_cast<deUint32>(sd.colorAttachmentReferences.size()),		// deUint32							colorAttachmentCount;
865 				dataOrNullPtr(sd.colorAttachmentReferences),					// const VkAttachmentReference*		pColorAttachments;
866 				dataOrNullPtr(sd.resolveAttachmentReferences),					// const VkAttachmentReference*		pResolveAttachments;
867 				dataOrNullPtr(sd.depthStencilAttachmentReferences),				// const VkAttachmentReference*		pDepthStencilAttachment;
868 				static_cast<deUint32>(sd.preserveAttachmentReferences.size()),	// deUint32							preserveAttachmentCount;
869 				dataOrNullPtr(sd.preserveAttachmentReferences)					// const deUint32*					pPreserveAttachments;
870 			};
871 			subpassDescriptions.push_back(description);
872 
873 			// Add a very coarse dependency enforcing sequential ordering of subpasses
874 			if (subpassNdx > 0)
875 			{
876 				static const VkAccessFlags	accessAny	= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
877 														| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
878 														| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
879 														| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
880 														| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
881 				const VkSubpassDependency	dependency	=
882 				{
883 					subpassNdx - 1,								// uint32_t                srcSubpass;
884 					subpassNdx,									// uint32_t                dstSubpass;
885 					VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,			// VkPipelineStageFlags    srcStageMask;
886 					VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,			// VkPipelineStageFlags    dstStageMask;
887 					accessAny,									// VkAccessFlags           srcAccessMask;
888 					accessAny,									// VkAccessFlags           dstAccessMask;
889 					(VkDependencyFlags)0,						// VkDependencyFlags       dependencyFlags;
890 				};
891 				subpassDependencies.push_back(dependency);
892 			}
893 		}
894 		// add a final dependency to synchronize results for the copy commands that will follow the renderpass
895 		const VkSubpassDependency finalDependency = {
896 			numSubpasses - 1,																			// uint32_t                srcSubpass;
897 			VK_SUBPASS_EXTERNAL,																		// uint32_t                dstSubpass;
898 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,	// VkPipelineStageFlags    srcStageMask;
899 			VK_PIPELINE_STAGE_TRANSFER_BIT,																// VkPipelineStageFlags    dstStageMask;
900 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags           srcAccessMask;
901 			VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags           dstAccessMask;
902 			(VkDependencyFlags)0,																		// VkDependencyFlags       dependencyFlags;
903 		};
904 		subpassDependencies.push_back(finalDependency);
905 
906 		const VkRenderPassCreateInfo renderPassInfo =
907 		{
908 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,						// VkStructureType					sType;
909 			DE_NULL,														// const void*						pNext;
910 			(VkRenderPassCreateFlags)0,										// VkRenderPassCreateFlags			flags;
911 			static_cast<deUint32>(m_attachmentDescriptions.size()),			// deUint32							attachmentCount;
912 			dataOrNullPtr(m_attachmentDescriptions),						// const VkAttachmentDescription*	pAttachments;
913 			static_cast<deUint32>(subpassDescriptions.size()),				// deUint32							subpassCount;
914 			dataOrNullPtr(subpassDescriptions),								// const VkSubpassDescription*		pSubpasses;
915 			static_cast<deUint32>(subpassDependencies.size()),				// deUint32							dependencyCount;
916 			dataOrNullPtr(subpassDependencies)								// const VkSubpassDependency*		pDependencies;
917 		};
918 
919 		m_renderPass  = createRenderPass(vk, device, &renderPassInfo);
920 		m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, static_cast<deUint32>(m_attachments.size()), dataOrNullPtr(m_attachments), framebufferSize.x(), framebufferSize.y());
921 	}
922 
getRenderPass(void) const923 	VkRenderPass getRenderPass (void) const
924 	{
925 		DE_ASSERT(m_renderPass);
926 		return *m_renderPass;
927 	}
928 
getFramebuffer(void) const929 	VkFramebuffer getFramebuffer (void) const
930 	{
931 		DE_ASSERT(m_framebuffer);
932 		return *m_framebuffer;
933 	}
934 
recordBeginRenderPass(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const VkRect2D & renderArea,const VkSubpassContents subpassContents) const935 	void recordBeginRenderPass (const DeviceInterface&	vk,
936 								const VkCommandBuffer	cmdBuffer,
937 								const VkRect2D&			renderArea,
938 								const VkSubpassContents	subpassContents) const
939 	{
940 		DE_ASSERT(m_renderPass);
941 		DE_ASSERT(m_framebuffer);
942 
943 		const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo =
944 		{
945 			VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,	// VkStructureType                          sType;
946 			DE_NULL,														// const void*                              pNext;
947 			static_cast<deUint32>(m_attachmentSampleLocations.size()),		// uint32_t                                 attachmentInitialSampleLocationsCount;
948 			dataOrNullPtr(m_attachmentSampleLocations),						// const VkAttachmentSampleLocationsEXT*    pAttachmentInitialSampleLocations;
949 			static_cast<deUint32>(m_subpassSampleLocations.size()),			// uint32_t                                 postSubpassSampleLocationsCount;
950 			dataOrNullPtr(m_subpassSampleLocations),						// const VkSubpassSampleLocationsEXT*       pPostSubpassSampleLocations;
951 		};
952 
953 		const VkRenderPassBeginInfo renderPassBeginInfo =
954 		{
955 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,						// VkStructureType         sType;
956 			&renderPassSampleLocationsBeginInfo,							// const void*             pNext;
957 			*m_renderPass,													// VkRenderPass            renderPass;
958 			*m_framebuffer,													// VkFramebuffer           framebuffer;
959 			renderArea,														// VkRect2D                renderArea;
960 			static_cast<deUint32>(m_clearValues.size()),					// uint32_t                clearValueCount;
961 			dataOrNullPtr(m_clearValues),									// const VkClearValue*     pClearValues;
962 		};
963 		vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, subpassContents);
964 	}
965 
966 private:
967 	struct SubpassDescription
968 	{
969 		std::vector<VkAttachmentReference>	inputAttachmentReferences;
970 		std::vector<VkAttachmentReference>	colorAttachmentReferences;
971 		std::vector<VkAttachmentReference>	resolveAttachmentReferences;
972 		std::vector<VkAttachmentReference>	depthStencilAttachmentReferences;
973 		std::vector<deUint32>				preserveAttachmentReferences;
974 	};
975 
976 	std::vector<SubpassDescription>				m_subpasses;
977 	std::vector<VkImageView>					m_attachments;
978 	std::vector<VkAttachmentDescription>		m_attachmentDescriptions;
979 	std::vector<VkClearValue>					m_clearValues;
980 	std::vector<VkAttachmentSampleLocationsEXT>	m_attachmentSampleLocations;
981 	std::vector<VkSubpassSampleLocationsEXT>	m_subpassSampleLocations;
982 	Move<VkRenderPass>							m_renderPass;
983 	Move<VkFramebuffer>							m_framebuffer;
984 
985 	// No copying allowed
986 	RenderTarget (const RenderTarget&);
987 	RenderTarget& operator=(const RenderTarget&);
988 };
989 
recordImageBarrier(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageAspectFlags aspect,const VkPipelineStageFlags srcStageMask,const VkPipelineStageFlags dstStageMask,const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)990 void recordImageBarrier (const DeviceInterface&				vk,
991 						 const VkCommandBuffer				cmdBuffer,
992 						 const VkImage						image,
993 						 const VkImageAspectFlags			aspect,
994 						 const VkPipelineStageFlags			srcStageMask,
995 						 const VkPipelineStageFlags			dstStageMask,
996 						 const VkAccessFlags				srcAccessMask,
997 						 const VkAccessFlags				dstAccessMask,
998 						 const VkImageLayout				oldLayout,
999 						 const VkImageLayout				newLayout,
1000 						 const VkSampleLocationsInfoEXT*	pSampleLocationsInfo = DE_NULL)
1001 {
1002 	const VkImageMemoryBarrier barrier =
1003 	{
1004 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType            sType;
1005 		pSampleLocationsInfo,										// const void*                pNext;
1006 		srcAccessMask,												// VkAccessFlags              srcAccessMask;
1007 		dstAccessMask,												// VkAccessFlags              dstAccessMask;
1008 		oldLayout,													// VkImageLayout              oldLayout;
1009 		newLayout,													// VkImageLayout              newLayout;
1010 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t                   srcQueueFamilyIndex;
1011 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t                   dstQueueFamilyIndex;
1012 		image,														// VkImage                    image;
1013 		makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u),			// VkImageSubresourceRange    subresourceRange;
1014 	};
1015 
1016 	vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1017 }
1018 
recordWaitEventWithImage(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const VkEvent event,const VkImage image,const VkImageAspectFlags aspect,const VkPipelineStageFlags srcStageMask,const VkPipelineStageFlags dstStageMask,const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)1019 void recordWaitEventWithImage (const DeviceInterface&			vk,
1020 							   const VkCommandBuffer			cmdBuffer,
1021 							   const VkEvent					event,
1022 							   const VkImage					image,
1023 							   const VkImageAspectFlags			aspect,
1024 							   const VkPipelineStageFlags		srcStageMask,
1025 							   const VkPipelineStageFlags		dstStageMask,
1026 							   const VkAccessFlags				srcAccessMask,
1027 							   const VkAccessFlags				dstAccessMask,
1028 							   const VkImageLayout				oldLayout,
1029 							   const VkImageLayout				newLayout,
1030 							   const VkSampleLocationsInfoEXT*	pSampleLocationsInfo = DE_NULL)
1031 {
1032 	const VkImageMemoryBarrier barrier =
1033 	{
1034 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType            sType;
1035 		pSampleLocationsInfo,										// const void*                pNext;
1036 		srcAccessMask,												// VkAccessFlags              srcAccessMask;
1037 		dstAccessMask,												// VkAccessFlags              dstAccessMask;
1038 		oldLayout,													// VkImageLayout              oldLayout;
1039 		newLayout,													// VkImageLayout              newLayout;
1040 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t                   srcQueueFamilyIndex;
1041 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t                   dstQueueFamilyIndex;
1042 		image,														// VkImage                    image;
1043 		makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u),			// VkImageSubresourceRange    subresourceRange;
1044 	};
1045 
1046 	vk.cmdWaitEvents(
1047 		cmdBuffer,													// VkCommandBuffer                             commandBuffer,
1048 		1u,															// uint32_t                                    eventCount,
1049 		&event,														// const VkEvent*                              pEvents,
1050 		srcStageMask,												// VkPipelineStageFlags                        srcStageMask,
1051 		dstStageMask,												// VkPipelineStageFlags                        dstStageMask,
1052 		0u,															// uint32_t                                    memoryBarrierCount,
1053 		DE_NULL,													// const VkMemoryBarrier*                      pMemoryBarriers,
1054 		0u,															// uint32_t                                    bufferMemoryBarrierCount,
1055 		DE_NULL,													// const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
1056 		1u,															// uint32_t                                    imageMemoryBarrierCount,
1057 		&barrier);													// const VkImageMemoryBarrier*                 pImageMemoryBarriers);
1058 }
1059 
recordCopyImageToBuffer(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const UVec2 & imageSize,const VkImage srcImage,const VkBuffer dstBuffer)1060 void recordCopyImageToBuffer (const DeviceInterface&	vk,
1061 							  const VkCommandBuffer		cmdBuffer,
1062 							  const UVec2&				imageSize,
1063 							  const VkImage				srcImage,
1064 							  const VkBuffer			dstBuffer)
1065 {
1066 	// Resolve image -> host buffer
1067 	{
1068 		const VkBufferImageCopy region =
1069 		{
1070 			0ull,																// VkDeviceSize                bufferOffset;
1071 			0u,																	// uint32_t                    bufferRowLength;
1072 			0u,																	// uint32_t                    bufferImageHeight;
1073 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
1074 			makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1075 			makeExtent3D(imageSize.x(), imageSize.y(), 1u),						// VkExtent3D                  imageExtent;
1076 		};
1077 
1078 		vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, &region);
1079 	}
1080 	// Buffer write barrier
1081 	{
1082 		const VkBufferMemoryBarrier barrier =
1083 		{
1084 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1085 			DE_NULL,										// const void*        pNext;
1086 			VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
1087 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1088 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1089 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1090 			dstBuffer,										// VkBuffer           buffer;
1091 			0ull,											// VkDeviceSize       offset;
1092 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
1093 		};
1094 
1095 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
1096 							  0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
1097 	}
1098 }
1099 
recordClearAttachments(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const deUint32 colorAttachment,const VkClearValue & colorClearValue,const VkImageAspectFlags depthStencilAspect,const VkClearValue & depthStencilClearValue,const VkRect2D & clearRect)1100 void recordClearAttachments (const DeviceInterface&		vk,
1101 							 const VkCommandBuffer		cmdBuffer,
1102 							 const deUint32				colorAttachment,
1103 							 const VkClearValue&		colorClearValue,
1104 							 const VkImageAspectFlags	depthStencilAspect,
1105 							 const VkClearValue&		depthStencilClearValue,
1106 							 const VkRect2D&			clearRect)
1107 {
1108 	std::vector<VkClearAttachment> attachments;
1109 
1110 	const VkClearRect rect =
1111 	{
1112 		clearRect,					// VkRect2D    rect;
1113 		0u,							// uint32_t    baseArrayLayer;
1114 		1u,							// uint32_t    layerCount;
1115 	};
1116 
1117 	// Clear color
1118 	{
1119 		const VkClearAttachment attachment =
1120 		{
1121 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags    aspectMask;
1122 			colorAttachment,			// uint32_t              colorAttachment;
1123 			colorClearValue,			// VkClearValue          clearValue;
1124 		};
1125 		attachments.push_back(attachment);
1126 	}
1127 
1128 	if ((depthStencilAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0u)
1129 	{
1130 		const VkClearAttachment attachment =
1131 		{
1132 			depthStencilAspect,			// VkImageAspectFlags    aspectMask;
1133 			VK_ATTACHMENT_UNUSED,		// uint32_t              colorAttachment;
1134 			depthStencilClearValue,		// VkClearValue          clearValue;
1135 		};
1136 		attachments.push_back(attachment);
1137 	}
1138 
1139 	vk.cmdClearAttachments(cmdBuffer, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), 1u, &rect);
1140 }
1141 
1142 //! Suitable for executing in a render pass, no queries
beginSecondaryCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const deUint32 subpass,const VkFramebuffer framebuffer)1143 void beginSecondaryCommandBuffer (const DeviceInterface&	vk,
1144 								  const VkCommandBuffer		commandBuffer,
1145 								  const VkRenderPass		renderPass,
1146 								  const deUint32			subpass,
1147 								  const VkFramebuffer		framebuffer)
1148 {
1149 	const VkCommandBufferInheritanceInfo inheritanceInfo =
1150 	{
1151 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,		// VkStructureType                  sType;
1152 		DE_NULL,												// const void*                      pNext;
1153 		renderPass,												// VkRenderPass                     renderPass;
1154 		subpass,												// uint32_t                         subpass;
1155 		framebuffer,											// VkFramebuffer                    framebuffer;
1156 		VK_FALSE,												// VkBool32                         occlusionQueryEnable;
1157 		(VkQueryControlFlags)0,									// VkQueryControlFlags              queryFlags;
1158 		(VkQueryPipelineStatisticFlags)0,						// VkQueryPipelineStatisticFlags    pipelineStatistics;
1159 	};
1160 	const VkCommandBufferBeginInfo beginInfo =
1161 	{
1162 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,		// VkStructureType                          sType;
1163 		DE_NULL,											// const void*                              pNext;
1164 		(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1165 		|VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT),	// VkCommandBufferUsageFlags                flags;
1166 		&inheritanceInfo,									// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
1167 	};
1168 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &beginInfo));
1169 }
1170 
1171 //! Verify results of a VkPhysicalDeviceSampleLocationsPropertiesEXT query with VkPhysicalDeviceProperties2KHR
testQuerySampleLocationProperties(Context & context)1172 tcu::TestStatus testQuerySampleLocationProperties (Context& context)
1173 {
1174 	const VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties = getSampleLocationsPropertiesEXT(context);
1175 
1176 	context.getTestContext().getLog()
1177 		<< tcu::TestLog::Section("VkPhysicalDeviceSampleLocationsPropertiesEXT", "Query results")
1178 		<< tcu::TestLog::Message << sampleLocationsProperties << tcu::TestLog::EndMessage
1179 		<< tcu::TestLog::EndSection;
1180 
1181 	const VkSampleCountFlags allowedSampleCounts = (VK_SAMPLE_COUNT_2_BIT  |
1182 													VK_SAMPLE_COUNT_4_BIT  |
1183 													VK_SAMPLE_COUNT_8_BIT  |
1184 													VK_SAMPLE_COUNT_16_BIT |
1185 													VK_SAMPLE_COUNT_32_BIT |
1186 													VK_SAMPLE_COUNT_64_BIT);
1187 
1188 	if ((sampleLocationsProperties.sampleLocationSampleCounts & allowedSampleCounts) == 0)
1189 	{
1190 		return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationSampleCounts should specify at least one MSAA sample count");
1191 	}
1192 
1193 	if (sampleLocationsProperties.maxSampleLocationGridSize.width  == 0u     ||
1194 		sampleLocationsProperties.maxSampleLocationGridSize.height == 0u     ||
1195 		sampleLocationsProperties.maxSampleLocationGridSize.width  >  16384u || // max not specified, but try to catch nonsense values like -1
1196 		sampleLocationsProperties.maxSampleLocationGridSize.height >  16384u)
1197 	{
1198 		return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: maxSampleLocationGridSize must be at least (1,1) size");
1199 	}
1200 
1201 	for (int i = 0; i < 2; ++i)
1202 	{
1203 		if (sampleLocationsProperties.sampleLocationCoordinateRange[i] < 0.0f ||
1204 			sampleLocationsProperties.sampleLocationCoordinateRange[i] > 1.0f)
1205 		{
1206 			return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationCoordinateRange[] values must be in [0, 1] range");
1207 		}
1208 	}
1209 
1210 	if (sampleLocationsProperties.sampleLocationSubPixelBits == 0u  ||
1211 		sampleLocationsProperties.sampleLocationSubPixelBits >  64u)	// max not specified, but try to catch nonsense values
1212 	{
1213 		return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationSubPixelBits should be greater than 0");
1214 	}
1215 
1216 	return tcu::TestStatus::pass("Pass");
1217 }
1218 
1219 //! Verify results of vkGetPhysicalDeviceMultisamplePropertiesEXT queries
testQueryMultisampleProperties(Context & context)1220 tcu::TestStatus testQueryMultisampleProperties (Context& context)
1221 {
1222 	const InstanceInterface&	vki				= context.getInstanceInterface();
1223 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
1224 	tcu::TestLog&				log				= context.getTestContext().getLog();
1225 
1226 	const VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties = getSampleLocationsPropertiesEXT(context);
1227 
1228 	const VkSampleCountFlagBits	sampleCountRange[] =
1229 	{
1230 		VK_SAMPLE_COUNT_1_BIT,
1231 		VK_SAMPLE_COUNT_2_BIT,
1232 		VK_SAMPLE_COUNT_4_BIT,
1233 		VK_SAMPLE_COUNT_8_BIT,
1234 		VK_SAMPLE_COUNT_16_BIT,
1235 		VK_SAMPLE_COUNT_32_BIT,
1236 		VK_SAMPLE_COUNT_64_BIT,
1237 	};
1238 
1239 	bool allOk = true;
1240 
1241 	for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples)
1242 	{
1243 		VkMultisamplePropertiesEXT multisampleProperties =
1244 		{
1245 			VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT,		// VkStructureType    sType;
1246 			DE_NULL,											// void*              pNext;
1247 			VkExtent2D(),										// VkExtent2D         maxSampleLocationGridSize;
1248 		};
1249 
1250 		vki.getPhysicalDeviceMultisamplePropertiesEXT(physicalDevice, *pLoopNumSamples, &multisampleProperties);
1251 
1252 		log << tcu::TestLog::Section("getPhysicalDeviceMultisamplePropertiesEXT", "Query results")
1253 			<< tcu::TestLog::Message << "Sample count: " << *pLoopNumSamples << tcu::TestLog::EndMessage
1254 			<< tcu::TestLog::Message << multisampleProperties << tcu::TestLog::EndMessage;
1255 
1256 		const bool isSupportedSampleCount = (*pLoopNumSamples & sampleLocationsProperties.sampleLocationSampleCounts) != 0;
1257 
1258 		if (isSupportedSampleCount)
1259 		{
1260 			if (!(multisampleProperties.maxSampleLocationGridSize.width  >= sampleLocationsProperties.maxSampleLocationGridSize.width &&
1261 				  multisampleProperties.maxSampleLocationGridSize.height >= sampleLocationsProperties.maxSampleLocationGridSize.height))
1262 			{
1263 				allOk = false;
1264 				log << tcu::TestLog::Message
1265 					<< "FAIL: Grid size should be the same or larger than VkPhysicalDeviceSampleLocationsPropertiesEXT::maxSampleLocationGridSize"
1266 					<< tcu::TestLog::EndMessage;
1267 			}
1268 		}
1269 		else
1270 		{
1271 			if (!(multisampleProperties.maxSampleLocationGridSize.width  == 0u &&
1272 				  multisampleProperties.maxSampleLocationGridSize.height == 0u))
1273 			{
1274 				allOk = false;
1275 				log << tcu::TestLog::Message << "FAIL: Expected (0, 0) grid size" << tcu::TestLog::EndMessage;
1276 			}
1277 		}
1278 
1279 		log << tcu::TestLog::EndSection;
1280 	}
1281 
1282 	return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some values were incorrect");
1283 }
1284 
1285 // These tests only use a color attachment and focus on per-sample data
1286 namespace VerifySamples
1287 {
1288 
1289 //! Data layout used in verify sample locations and interpolation cases
1290 namespace SampleDataSSBO
1291 {
1292 
1293 static VkDeviceSize	STATIC_SIZE		= 6 * sizeof(deUint32);
1294 
renderSize(void * const basePtr)1295 static UVec2&		renderSize		(void* const basePtr) { return *reinterpret_cast<UVec2*>	(static_cast<deUint8*>(basePtr) + 0 * sizeof(deUint32)); }
gridSize(void * const basePtr)1296 static UVec2&		gridSize		(void* const basePtr) { return *reinterpret_cast<UVec2*>	(static_cast<deUint8*>(basePtr) + 2 * sizeof(deUint32)); }
samplesPerPixel(void * const basePtr)1297 static deUint32&	samplesPerPixel	(void* const basePtr) { return *reinterpret_cast<deUint32*>	(static_cast<deUint8*>(basePtr) + 4 * sizeof(deUint32)); }
1298 
1299 template<typename T>
sampleData(void * const basePtr)1300 static T*			sampleData		(void* const basePtr) { DE_STATIC_ASSERT(sizeof(T) == sizeof(Vec2));
1301 															return  reinterpret_cast<T*>		(static_cast<deUint8*>(basePtr) + STATIC_SIZE); }
1302 
1303 } // SampleDataSSBO
1304 
1305 enum TestOptionFlagBits
1306 {
1307 	TEST_OPTION_DYNAMIC_STATE_BIT				= 0x1,	//!< Use dynamic pipeline state to pass in sample locations
1308 	TEST_OPTION_CLOSELY_PACKED_BIT				= 0x2,	//!< Place samples as close as possible to each other
1309 	TEST_OPTION_FRAGMENT_SHADING_RATE_BIT		= 0x4,	//!< Use VK_KHR_fragment_shading_rate
1310 	TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT	= 0x8	//!< Use variable sample locations
1311 };
1312 typedef deUint32 TestOptionFlags;
1313 
1314 struct TestParams
1315 {
1316 	PipelineConstructionType	pipelineConstructionType;
1317 	VkSampleCountFlagBits		numSamples;
1318 	TestOptionFlags				options;
1319 };
1320 
checkSupportVerifyTests(Context & context,const TestParams params)1321 void checkSupportVerifyTests (Context& context, const TestParams params)
1322 {
1323 	checkSupportSampleLocations(context);
1324 
1325 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1326 
1327 	if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & params.numSamples) == 0u)
1328 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
1329 
1330 	if ((getSampleLocationsPropertiesEXT(context).sampleLocationSampleCounts & params.numSamples) == 0u)
1331 		TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: sample count not supported");
1332 
1333 	if (TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & params.options)
1334 		checkFragmentShadingRateRequirements(context, params.numSamples);
1335 
1336 	if (TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT & params.options && !getSampleLocationsPropertiesEXT(context).variableSampleLocations)
1337 		TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: variableSampleLocations not supported");
1338 
1339 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
1340 }
1341 
declareSampleDataSSBO(void)1342 std::string declareSampleDataSSBO (void)
1343 {
1344 	std::ostringstream str;
1345 	str << "layout(set = 0, binding = 0, std430) readonly buffer SampleData {\n"	// make sure this matches SampleDataSSBO definition
1346 		<< "    uvec2 renderSize;\n"
1347 		<< "    uvec2 gridSize;\n"
1348 		<< "    uint  samplesPerPixel;\n"
1349 		<< "          // padding 1-uint size;\n"
1350 		<< "    vec2  data[];\n"
1351 		<< "} sb_data;\n";
1352 	return str.str();
1353 }
1354 
addProgramsVerifyLocationGeometry(SourceCollections & programCollection,const TestParams)1355 void addProgramsVerifyLocationGeometry (SourceCollections& programCollection, const TestParams)
1356 {
1357 	// Vertex shader
1358 	{
1359 		std::ostringstream src;
1360 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1361 			<< "\n"
1362 			<< "layout(location = 0) in vec4 in_position;\n"
1363 			<< "\n"
1364 			<< "out gl_PerVertex {\n"
1365 			<< "    vec4 gl_Position;\n"
1366 			<< "};\n"
1367 			<< "\n"
1368 			<< "void main(void)\n"
1369 			<< "{\n"
1370 			<< "    gl_Position = in_position;\n"
1371 			<< "}\n";
1372 
1373 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1374 	}
1375 
1376 	// Fragment shader
1377 	{
1378 		std::ostringstream src;
1379 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1380 			<< "\n"
1381 			<< "layout(location = 0) out vec4 o_color;\n"
1382 			<< "\n"
1383 			<< declareSampleDataSSBO()
1384 			<< "\n"
1385 			<< "void main(void)\n"
1386 			<< "{\n"
1387 			<< "    uvec2 fragCoord = uvec2(gl_FragCoord.xy);\n"
1388 			<< "    uint  index     = (fragCoord.y * sb_data.renderSize.x + fragCoord.x) * sb_data.samplesPerPixel + gl_SampleID;\n"
1389 			<< "\n"
1390 			<< "    if (gl_PrimitiveID == index)\n"
1391 			<< "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1392 			<< "    else\n"
1393 			<< "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1394 			<< "}\n";
1395 
1396 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1397 	}
1398 }
1399 
addProgramsVerifyInterpolation(SourceCollections & programCollection,const TestParams)1400 void addProgramsVerifyInterpolation (SourceCollections& programCollection, const TestParams)
1401 {
1402 	// Vertex shader
1403 	{
1404 		std::ostringstream src;
1405 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1406 			<< "\n"
1407 			<< "layout(location = 0) in  vec4 in_position;\n"
1408 			<< "layout(location = 0) out vec2 o_position;\n"
1409 			<< "\n"
1410 			<< "out gl_PerVertex {\n"
1411 			<< "    vec4 gl_Position;\n"
1412 			<< "};\n"
1413 			<< "\n"
1414 			<< "void main(void)\n"
1415 			<< "{\n"
1416 			<< "    gl_Position = in_position;\n"
1417 			<< "    o_position  = in_position.xy;\n"	// user-data that will be interpolated
1418 			<< "}\n";
1419 
1420 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1421 	}
1422 
1423 	// Fragment shader
1424 	{
1425 		std::ostringstream src;
1426 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1427 			<< "\n"
1428 			<< "layout(location = 0) sample in  vec2 in_value;\n"
1429 			<< "layout(location = 0)        out vec4 o_color;\n"
1430 			<< "\n"
1431 			<< declareSampleDataSSBO()
1432 			<< "\n"
1433 			<< "void main(void)\n"
1434 			<< "{\n"
1435 			<< "    uvec2 fragCoord         = uvec2(gl_FragCoord.xy);\n"
1436 			<< "    uint  index             = (fragCoord.y * sb_data.renderSize.x + fragCoord.x) * sb_data.samplesPerPixel + gl_SampleID;\n"
1437 			<< "    vec2  diff              = abs(sb_data.data[index] - in_value);\n"
1438 			<< "    vec2  threshold         = vec2(0.002);\n"
1439 			<< "\n"
1440 			<< "    if (all(lessThan(diff, threshold)))\n"
1441 			<< "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1442 			<< "    else\n"
1443 			<< "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1444 			<< "}\n";
1445 
1446 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1447 	}
1448 }
1449 
1450 class TestBase : public TestInstance
1451 {
1452 public:
TestBase(Context & context,const TestParams params)1453 	TestBase (Context& context, const TestParams params)
1454 		: TestInstance					(context)
1455 		, m_params						(params)
1456 		, m_sampleLocationsProperties	(getSampleLocationsPropertiesEXT(context))
1457 		, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
1458 		, m_numVertices					(0)
1459 		, m_currentGridNdx				(0)
1460 	{
1461 		VkMultisamplePropertiesEXT multisampleProperties =
1462 		{
1463 			VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT,		// VkStructureType    sType;
1464 			DE_NULL,											// void*              pNext;
1465 			VkExtent2D(),										// VkExtent2D         maxSampleLocationGridSize;
1466 		};
1467 
1468 		m_context.getInstanceInterface().getPhysicalDeviceMultisamplePropertiesEXT(m_context.getPhysicalDevice(), m_params.numSamples, &multisampleProperties);
1469 
1470 		// Generate grid size combinations
1471 		for (deUint32 y = multisampleProperties.maxSampleLocationGridSize.height; y >= 1u; y >>= 1)
1472 		for (deUint32 x = multisampleProperties.maxSampleLocationGridSize.width;  x >= 1u; x >>= 1)
1473 		{
1474 			DE_ASSERT(multisampleProperties.maxSampleLocationGridSize.width  % x == 0u);
1475 			DE_ASSERT(multisampleProperties.maxSampleLocationGridSize.height % y == 0u);
1476 			m_gridSizes.push_back(UVec2(x, y));
1477 		}
1478 	}
1479 
iterate(void)1480 	tcu::TestStatus iterate (void)
1481 	{
1482 		// Will be executed several times, for all possible pixel grid sizes
1483 		if (!(currentGridSize().x() >= 1 && currentGridSize().y() >= 1))
1484 			return tcu::TestStatus::fail("maxSampleLocationGridSize is invalid");
1485 
1486 		// Prepare the pixel grid
1487 		{
1488 			const deUint32	pixelGridRepetitions = 2;	// just to make sure the pattern is consistently applied across the framebuffer
1489 			m_renderSize = UVec2(pixelGridRepetitions * currentGridSize().x(),
1490 								 pixelGridRepetitions * currentGridSize().y());
1491 			m_pixelGrid = MovePtr<MultisamplePixelGrid>(new MultisamplePixelGrid(currentGridSize(), m_params.numSamples));
1492 
1493 			if ((m_params.options & TEST_OPTION_CLOSELY_PACKED_BIT) != 0u)
1494 				fillSampleLocationsPacked(*m_pixelGrid, m_sampleLocationsProperties.sampleLocationSubPixelBits);
1495 			else
1496 				fillSampleLocationsRandom(*m_pixelGrid, m_sampleLocationsProperties.sampleLocationSubPixelBits);
1497 
1498 			logPixelGrid (m_context.getTestContext().getLog(), m_sampleLocationsProperties, *m_pixelGrid);
1499 		}
1500 
1501 		// Create images
1502 		{
1503 			const DeviceInterface&	vk			= m_context.getDeviceInterface();
1504 			const VkDevice			device		= m_context.getDevice();
1505 			Allocator&				allocator	= m_context.getDefaultAllocator();
1506 
1507 			// Images and staging buffers
1508 
1509 			m_colorImage		= makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, m_params.numSamples, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1510 			m_colorImageAlloc	= bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
1511 			m_colorImageView	= makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1512 
1513 			m_resolveImage		= makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1514 			m_resolveImageAlloc	= bindImage(vk, device, allocator, *m_resolveImage, MemoryRequirement::Any);
1515 			m_resolveImageView	= makeImageView(vk, device, *m_resolveImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1516 
1517 			const VkDeviceSize	colorBufferSize = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(m_colorFormat));
1518 			m_colorBuffer		= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1519 			m_colorBufferAlloc	= bindBuffer(vk, device, allocator, *m_colorBuffer, MemoryRequirement::HostVisible);
1520 		}
1521 
1522 		if (!testPixelGrid())
1523 			return tcu::TestStatus::fail("Fail");
1524 
1525 		if (shrinkCurrentGrid())
1526 			return tcu::TestStatus::incomplete();
1527 		else
1528 			return tcu::TestStatus::pass("Pass");
1529 	}
1530 
1531 protected:
1532 	//! Return true if the test passed the current grid size
1533 	virtual bool testPixelGrid (void) = 0;
1534 
currentGridSize(void)1535 	const UVec2& currentGridSize (void)
1536 	{
1537 		return m_gridSizes[m_currentGridNdx];
1538 	}
1539 
1540 	//! Return false if the grid is already at (1, 1) size
shrinkCurrentGrid(void)1541 	bool shrinkCurrentGrid (void)
1542 	{
1543 		if (m_gridSizes.size() <= m_currentGridNdx + 1)
1544 			return false;
1545 
1546 		++m_currentGridNdx;
1547 		return true;
1548 	}
1549 
drawSinglePass(const VertexInputConfig vertexInputConfig)1550 	void drawSinglePass (const VertexInputConfig vertexInputConfig)
1551 	{
1552 		DE_ASSERT(m_descriptorSetLayout);
1553 
1554 		const DeviceInterface&			vk				= m_context.getDeviceInterface();
1555 		const VkDevice					device			= m_context.getDevice();
1556 		const VkViewport				viewport		= makeViewport(m_renderSize);
1557 		const VkRect2D					renderArea		= makeRect2D(m_renderSize);
1558 		const VkRect2D					scissor			= makeRect2D(m_renderSize);
1559 		const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1560 		const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1561 		const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device, *m_descriptorSetLayout));
1562 
1563 		const bool						useDynamicStateSampleLocations	= ((m_params.options & TEST_OPTION_DYNAMIC_STATE_BIT) != 0u);
1564 		const bool						useFragmentShadingRate			= ((m_params.options & TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) != 0u);
1565 		const VkSampleLocationsInfoEXT	sampleLocationsInfo				= makeSampleLocationsInfo(*m_pixelGrid);
1566 
1567 		RenderTarget rt;
1568 
1569 		rt.addAttachment(
1570 			*m_colorImageView,											// VkImageView					imageView,
1571 			(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
1572 			m_colorFormat,												// VkFormat						format,
1573 			m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
1574 			VK_ATTACHMENT_LOAD_OP_CLEAR,								// VkAttachmentLoadOp			loadOp,
1575 			VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
1576 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
1577 			VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
1578 			VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
1579 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout				finalLayout,
1580 			makeClearValueColor(CLEAR_COLOR_0));						// VkClearValue					clearValue,
1581 
1582 		rt.addAttachment(
1583 			*m_resolveImageView,										// VkImageView					imageView,
1584 			(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
1585 			m_colorFormat,												// VkFormat						format,
1586 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		numSamples,
1587 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			loadOp,
1588 			VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
1589 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
1590 			VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
1591 			VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
1592 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout				finalLayout,
1593 			VkClearValue());											// VkClearValue					clearValue,
1594 
1595 		if (TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT & m_params.options)
1596 		{
1597 			rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1598 				1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &sampleLocationsInfo);
1599 		}
1600 		else
1601 		{
1602 			rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1603 				1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1604 		}
1605 
1606 		rt.bake(vk, device, m_renderSize);
1607 
1608 		GraphicsPipelineWrapper pipeline(vk, device, m_params.pipelineConstructionType);
1609 
1610 		if (useDynamicStateSampleLocations)
1611 		{
1612 			std::vector<VkDynamicState>	dynamicState;
1613 			dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
1614 
1615 			preparePipelineWrapperSinglePassColor(
1616 				pipeline, dynamicState, *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule, viewport, scissor,
1617 				m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(), vertexInputConfig, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, useFragmentShadingRate);
1618 		}
1619 		else
1620 		{
1621 			preparePipelineWrapperSinglePassColor(
1622 				pipeline, std::vector<VkDynamicState>(), *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule, viewport, scissor,
1623 				m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo, vertexInputConfig, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, useFragmentShadingRate);
1624 		}
1625 
1626 		const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()));
1627 		const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1628 
1629 		beginCommandBuffer(vk, *cmdBuffer);
1630 
1631 		rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE);
1632 
1633 		vk.cmdBindVertexBuffers(*cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO);
1634 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
1635 
1636 		if (useDynamicStateSampleLocations)
1637 			vk.cmdSetSampleLocationsEXT(*cmdBuffer, &sampleLocationsInfo);
1638 
1639 		if (m_descriptorSet)
1640 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1641 
1642 		vk.cmdDraw(*cmdBuffer, m_numVertices, 1u, 0u, 0u);
1643 		endRenderPass(vk, *cmdBuffer);
1644 
1645 		recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer);
1646 
1647 		endCommandBuffer(vk, *cmdBuffer);
1648 		submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
1649 
1650 		invalidateAlloc(vk, device, *m_colorBufferAlloc);
1651 	}
1652 
createSampleDataBufferAndDescriptors(const VkDeviceSize bufferSize)1653 	void createSampleDataBufferAndDescriptors (const VkDeviceSize bufferSize)
1654 	{
1655 		// Make sure the old descriptor set is destroyed before we destroy its pool
1656 		m_descriptorSet	= Move<VkDescriptorSet>();
1657 
1658 		const DeviceInterface&	vk			= m_context.getDeviceInterface();
1659 		const VkDevice			device		= m_context.getDevice();
1660 		Allocator&				allocator	= m_context.getDefaultAllocator();
1661 
1662 		m_sampleDataBuffer		= makeBuffer(vk, device, bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1663 		m_sampleDataBufferAlloc	= bindBuffer(vk, device, allocator, *m_sampleDataBuffer, MemoryRequirement::HostVisible);
1664 
1665 		m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1666 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1667 			.build(vk, device);
1668 
1669 		m_descriptorPool = DescriptorPoolBuilder()
1670 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1671 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1672 
1673 		m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1674 
1675 		const VkDescriptorBufferInfo bufferDescriptorInfo = makeDescriptorBufferInfo(*m_sampleDataBuffer, 0ull, bufferSize);
1676 		DescriptorSetUpdateBuilder()
1677 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescriptorInfo)
1678 			.update(vk, device);
1679 
1680 		SampleDataSSBO::renderSize		(m_sampleDataBufferAlloc->getHostPtr()) = m_renderSize;
1681 		SampleDataSSBO::gridSize		(m_sampleDataBufferAlloc->getHostPtr()) = m_pixelGrid->size();
1682 		SampleDataSSBO::samplesPerPixel	(m_sampleDataBufferAlloc->getHostPtr()) = m_pixelGrid->samplesPerPixel();
1683 
1684 		flushAlloc(vk, device, *m_sampleDataBufferAlloc);
1685 	}
1686 
1687 	template<typename Vertex>
createVertexBuffer(const std::vector<Vertex> & vertices)1688 	void createVertexBuffer (const std::vector<Vertex>& vertices)
1689 	{
1690 		const DeviceInterface&	vk					= m_context.getDeviceInterface();
1691 		const VkDevice			device				= m_context.getDevice();
1692 		Allocator&				allocator			= m_context.getDefaultAllocator();
1693 		const VkDeviceSize		vertexBufferSize	= static_cast<VkDeviceSize>(vertices.size() * sizeof(vertices[0]));
1694 
1695 		m_numVertices		= static_cast<deUint32>(vertices.size());
1696 		m_vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1697 		m_vertexBufferAlloc	= bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);
1698 
1699 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1700 		flushAlloc(vk, device, *m_vertexBufferAlloc);
1701 	}
1702 
1703 	const TestParams									m_params;
1704 	const VkPhysicalDeviceSampleLocationsPropertiesEXT	m_sampleLocationsProperties;
1705 	const VkFormat										m_colorFormat;
1706 	UVec2												m_renderSize;
1707 	MovePtr<MultisamplePixelGrid>						m_pixelGrid;
1708 	deUint32											m_numVertices;
1709 	Move<VkBuffer>										m_vertexBuffer;
1710 	MovePtr<Allocation>									m_vertexBufferAlloc;
1711 	Move<VkImage>										m_colorImage;
1712 	Move<VkImageView>									m_colorImageView;
1713 	MovePtr<Allocation>									m_colorImageAlloc;
1714 	Move<VkImage>										m_resolveImage;
1715 	Move<VkImageView>									m_resolveImageView;
1716 	MovePtr<Allocation>									m_resolveImageAlloc;
1717 	Move<VkBuffer>										m_colorBuffer;
1718 	MovePtr<Allocation>									m_colorBufferAlloc;
1719 	Move<VkBuffer>										m_sampleDataBuffer;
1720 	MovePtr<Allocation>									m_sampleDataBufferAlloc;
1721 	Move<VkDescriptorSetLayout>							m_descriptorSetLayout;
1722 	Move<VkDescriptorPool>								m_descriptorPool;
1723 	Move<VkDescriptorSet>								m_descriptorSet;
1724 
1725 private:
1726 	deUint32											m_currentGridNdx;
1727 	std::vector<UVec2>									m_gridSizes;
1728 };
1729 
1730 //! Check that each custom sample has the expected position
1731 class VerifyLocationTest : public TestBase
1732 {
1733 public:
VerifyLocationTest(Context & context,const TestParams params)1734 	VerifyLocationTest (Context& context, const TestParams params) : TestBase(context, params) {}
1735 
testPixelGrid(void)1736 	bool testPixelGrid (void)
1737 	{
1738 		// Create vertices
1739 		{
1740 			// For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it.
1741 			// NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution.
1742 			const Vec2			pixelSize	= Vec2(2.0f) / m_renderSize.cast<float>();
1743 			const Vec2			offset		= pixelSize / UVec2(1u << m_sampleLocationsProperties.sampleLocationSubPixelBits).cast<float>();
1744 			std::vector<Vec4>	vertices;
1745 
1746 			// Surround with a roughly centered triangle
1747 			const float y1 = 0.5f  * offset.y();
1748 			const float y2 = 0.35f * offset.y();
1749 			const float x1 = 0.5f  * offset.x();
1750 
1751 			const std::vector<Vec2>	locations = genFramebufferSampleLocations(*m_pixelGrid, m_pixelGrid->size(), m_renderSize);
1752 			for (std::vector<Vec2>::const_iterator iter = locations.begin(); iter != locations.end(); ++iter)
1753 			{
1754 				vertices.push_back(Vec4(iter->x(),      iter->y() - y1, 0.0f, 1.0f));
1755 				vertices.push_back(Vec4(iter->x() - x1, iter->y() + y2, 0.0f, 1.0f));
1756 				vertices.push_back(Vec4(iter->x() + x1, iter->y() + y2, 0.0f, 1.0f));
1757 			}
1758 
1759 			createVertexBuffer(vertices);
1760 		}
1761 
1762 		createSampleDataBufferAndDescriptors(SampleDataSSBO::STATIC_SIZE);	// no per-sample data used
1763 
1764 		drawSinglePass(VERTEX_INPUT_VEC4);	// sample locations are taken from the pixel grid
1765 
1766 		// Verify
1767 
1768 		const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr()));
1769 
1770 		return compareGreenImage(m_context.getTestContext().getLog(), "resolve0", "Resolved test image", image);
1771 	}
1772 };
1773 
1774 //! Verify that vertex attributes are correctly interpolated at each custom sample location
1775 class VerifyInterpolationTest : public TestBase
1776 {
1777 public:
VerifyInterpolationTest(Context & context,const TestParams params)1778 	VerifyInterpolationTest (Context& context, const TestParams params) : TestBase(context, params)	{}
1779 
testPixelGrid(void)1780 	bool testPixelGrid (void)
1781 	{
1782 		createVertexBuffer(genVerticesFullQuad());
1783 
1784 		// Create sample data SSBO
1785 		{
1786 			const deUint32		numSamples		= m_pixelGrid->samplesPerPixel();
1787 			const deUint32		numDataEntries	= numSamples * m_renderSize.x() * m_renderSize.y();
1788 			const VkDeviceSize  bufferSize		= SampleDataSSBO::STATIC_SIZE + sizeof(Vec2) * numDataEntries;
1789 
1790 			createSampleDataBufferAndDescriptors(bufferSize);
1791 
1792 			Vec2* const				pSampleData	= SampleDataSSBO::sampleData<Vec2>(m_sampleDataBufferAlloc->getHostPtr());
1793 			const std::vector<Vec2>	locations	= genFramebufferSampleLocations(*m_pixelGrid, m_pixelGrid->size(), m_renderSize);
1794 
1795 			// Fill SSBO with interpolated values (here: from -1.0 to 1.0 across the render area in both x and y)
1796 			DE_ASSERT(locations.size() == numDataEntries);
1797 			std::copy(locations.begin(), locations.end(), pSampleData);
1798 
1799 			flushAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_sampleDataBufferAlloc);
1800 		}
1801 
1802 		drawSinglePass(VERTEX_INPUT_VEC4_VEC4);	// sample locations are taken from the pixel grid
1803 
1804 		// Verify
1805 
1806 		const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr()));
1807 
1808 		return compareGreenImage(m_context.getTestContext().getLog(), "resolve0", "Resolved test image", image);
1809 	}
1810 };
1811 
1812 template<typename Test, typename ProgramsFunc>
addCases(tcu::TestCaseGroup * group,const VkSampleCountFlagBits numSamples,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate,const ProgramsFunc initPrograms)1813 void addCases (tcu::TestCaseGroup* group, const VkSampleCountFlagBits numSamples, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate, const ProgramsFunc initPrograms)
1814 {
1815 	TestParams params;
1816 	deMemset(&params, 0, sizeof(params));
1817 
1818 	params.pipelineConstructionType	= pipelineConstructionType;
1819 	params.numSamples				= numSamples;
1820 
1821 	struct TestOptions
1822 	{
1823 		std::string		testSuffix;
1824 		TestOptionFlags	testFlags;
1825 
1826 	};
1827 
1828 	TestOptions testOpts[]	=
1829 	{
1830 		{ "",				useFragmentShadingRate ? (TestOptionFlags)TEST_OPTION_FRAGMENT_SHADING_RATE_BIT : (TestOptionFlags)0 | (TestOptionFlags)TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT },
1831 		{ "_invariable",	useFragmentShadingRate ? (TestOptionFlags)TEST_OPTION_FRAGMENT_SHADING_RATE_BIT : (TestOptionFlags)0 }
1832 	};
1833 
1834 	for (const auto &options : testOpts)
1835 	{
1836 		params.options	= options.testFlags;
1837 
1838 		addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + options.testSuffix).c_str(), "", checkSupportVerifyTests, initPrograms, params);
1839 
1840 		params.options	|= (TestOptionFlags)TEST_OPTION_DYNAMIC_STATE_BIT;
1841 		addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + "_dynamic" + options.testSuffix).c_str(), "", checkSupportVerifyTests, initPrograms, params);
1842 
1843 		params.options	|= (TestOptionFlags)TEST_OPTION_CLOSELY_PACKED_BIT;
1844 		addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + "_packed" + options.testSuffix).c_str(), "", checkSupportVerifyTests, initPrograms, params);
1845 	}
1846 }
1847 
1848 } // VerifySamples
1849 
1850 // Draw tests with at least two "passes" where sample locations may change.
1851 // Test case is based on a combination of parameters defined below. Not all combinations are compatible.
1852 namespace Draw
1853 {
1854 
1855 //! Options common to all test cases
1856 enum TestOptionFlagBits
1857 {
1858 	TEST_OPTION_SAME_PATTERN_BIT				= 1u << 0,	//!< Use the same sample pattern for all operations
1859 	TEST_OPTION_DYNAMIC_STATE_BIT				= 1u << 1,	//!< Use dynamic pipeline state to pass in sample locations
1860 	TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT	= 1u << 2,	//!< Put drawing commands in a secondary buffer, including sample locations change (if dynamic)
1861 	TEST_OPTION_GENERAL_LAYOUT_BIT				= 1u << 3,	//!< Transition the image to general layout at some point in rendering
1862 	TEST_OPTION_WAIT_EVENTS_BIT					= 1u << 4,	//!< Use image memory barriers with vkCmdWaitEvents rather than vkCmdPipelineBarrier
1863 	TEST_OPTION_FRAGMENT_SHADING_RATE_BIT		= 1u << 5,	//!< Use VK_KHR_fragment_shading_rate
1864 };
1865 typedef deUint32 TestOptionFlags;
1866 
1867 //! Determines where draws/clears with custom samples occur in the test
1868 enum TestDrawIn
1869 {
1870 	TEST_DRAW_IN_RENDER_PASSES = 0u,	//!< Each operation in a separate render pass
1871 	TEST_DRAW_IN_SUBPASSES,				//!< Each operation in a separate subpass of the same render pass
1872 	TEST_DRAW_IN_SAME_SUBPASS,			//!< Each operation in the same subpass
1873 };
1874 
1875 //! How a clear before the second pass will be done
1876 enum TestClears
1877 {
1878 	TEST_CLEARS_NO_CLEAR = 0u,				//!< Don't clear
1879 	TEST_CLEARS_LOAD_OP_CLEAR,				//!< Render pass attachment load clear
1880 	TEST_CLEARS_CMD_CLEAR_ATTACHMENTS,		//!< vkCmdClearAttachments within a subpass
1881 	TEST_CLEARS_CMD_CLEAR_IMAGE,			//!< vkCmdClear{Color|DepthStencil}Image outside a render pass
1882 };
1883 
1884 //! What type of image will be verified with custom samples
1885 enum TestImageAspect
1886 {
1887 	TEST_IMAGE_ASPECT_COLOR = 0u,			//!< Color image
1888 	TEST_IMAGE_ASPECT_DEPTH,				//!< Depth aspect of an image (can be mixed format)
1889 	TEST_IMAGE_ASPECT_STENCIL,				//!< Stencil aspect of an image (can be mixed format)
1890 };
1891 
1892 struct TestParams
1893 {
1894 	PipelineConstructionType	pipelineConstructionType;
1895 	VkSampleCountFlagBits		numSamples;
1896 	TestOptionFlags				options;
1897 	TestDrawIn					drawIn;
1898 	TestClears					clears;
1899 	TestImageAspect				imageAspect;
1900 };
1901 
checkSupportDrawTests(Context & context,const TestParams params)1902 void checkSupportDrawTests (Context& context, const TestParams params)
1903 {
1904 	checkSupportSampleLocations(context);
1905 
1906 	if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & params.numSamples) == 0u)
1907 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
1908 
1909 	if ((getSampleLocationsPropertiesEXT(context).sampleLocationSampleCounts & params.numSamples) == 0u)
1910 		TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: sample count not supported");
1911 
1912 	// Are we allowed to modify the sample pattern within the same subpass?
1913 	if (params.drawIn == TEST_DRAW_IN_SAME_SUBPASS && ((params.options & TEST_OPTION_SAME_PATTERN_BIT) == 0) && !getSampleLocationsPropertiesEXT(context).variableSampleLocations)
1914 		TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: variableSampleLocations not supported");
1915 
1916 	if (TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & params.options)
1917 		checkFragmentShadingRateRequirements(context, params.numSamples);
1918 
1919 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
1920 
1921 #ifndef CTS_USES_VULKANSC
1922 	if (TEST_OPTION_WAIT_EVENTS_BIT & params.options &&
1923 		context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
1924 	{
1925 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
1926 	}
1927 #endif // CTS_USES_VULKANSC
1928 }
1929 
getString(const TestImageAspect aspect)1930 const char* getString (const TestImageAspect aspect)
1931 {
1932 	switch (aspect)
1933 	{
1934 		case TEST_IMAGE_ASPECT_COLOR:	return "color";
1935 		case TEST_IMAGE_ASPECT_DEPTH:	return "depth";
1936 		case TEST_IMAGE_ASPECT_STENCIL:	return "stencil";
1937 	}
1938 	DE_ASSERT(0);
1939 	return DE_NULL;
1940 }
1941 
getString(const TestDrawIn drawIn)1942 const char* getString (const TestDrawIn drawIn)
1943 {
1944 	switch (drawIn)
1945 	{
1946 		case TEST_DRAW_IN_RENDER_PASSES:	return "separate_renderpass";
1947 		case TEST_DRAW_IN_SUBPASSES:		return "separate_subpass";
1948 		case TEST_DRAW_IN_SAME_SUBPASS:		return "same_subpass";
1949 	}
1950 	DE_ASSERT(0);
1951 	return DE_NULL;
1952 }
1953 
getString(const TestClears clears)1954 const char* getString (const TestClears clears)
1955 {
1956 	switch (clears)
1957 	{
1958 		case TEST_CLEARS_NO_CLEAR:				return "no_clear";
1959 		case TEST_CLEARS_LOAD_OP_CLEAR:			return "load_op_clear";
1960 		case TEST_CLEARS_CMD_CLEAR_ATTACHMENTS:	return "clear_attachments";
1961 		case TEST_CLEARS_CMD_CLEAR_IMAGE:		return "clear_image";
1962 	}
1963 	DE_ASSERT(0);
1964 	return DE_NULL;
1965 }
1966 
getTestOptionFlagsString(const deUint32 flags)1967 std::string getTestOptionFlagsString (const deUint32 flags)
1968 {
1969 	std::ostringstream str;
1970 
1971 	if ((flags & TEST_OPTION_SAME_PATTERN_BIT) != 0)				str << (str.tellp() > 0 ? "_" : "") << "same_pattern";
1972 	if ((flags & TEST_OPTION_DYNAMIC_STATE_BIT) != 0)				str << (str.tellp() > 0 ? "_" : "") << "dynamic";
1973 	if ((flags & TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT) != 0)	str << (str.tellp() > 0 ? "_" : "") << "secondary_cmd_buf";
1974 	if ((flags & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0)				str << (str.tellp() > 0 ? "_" : "") << "general_layout";
1975 	if ((flags & TEST_OPTION_WAIT_EVENTS_BIT) != 0)					str << (str.tellp() > 0 ? "_" : "") << "event";
1976 
1977 	return str.str();
1978 }
1979 
initPrograms(SourceCollections & programCollection,const TestParams)1980 void initPrograms (SourceCollections& programCollection, const TestParams)
1981 {
1982 	// Vertex shader
1983 	{
1984 		std::ostringstream src;
1985 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1986 			<< "\n"
1987 			<< "layout(location = 0) in  vec4 in_position;\n"
1988 			<< "layout(location = 1) in  vec4 in_color;\n"
1989 			<< "layout(location = 0) out vec4 o_color;\n"
1990 			<< "\n"
1991 			<< "out gl_PerVertex {\n"
1992 			<< "    vec4 gl_Position;\n"
1993 			<< "};\n"
1994 			<< "\n"
1995 			<< "void main(void)\n"
1996 			<< "{\n"
1997 			<< "    gl_Position = in_position;\n"
1998 			<< "    o_color     = in_color;\n"
1999 			<< "\n"
2000 			// We use instance index to draw the left shape (index = 0) or the right shape (index = 1).
2001 			// Vertices are squished and moved to either half of the viewport.
2002 			<< "    if (gl_InstanceIndex == 0)\n"
2003 			<< "        gl_Position.x = 0.5 * (gl_Position.x - 1.0);\n"
2004 			<< "    else if (gl_InstanceIndex == 1)\n"
2005 			<< "        gl_Position.x = 0.5 * (gl_Position.x + 1.0);\n"
2006 			<< "}\n";
2007 
2008 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2009 	}
2010 
2011 	// Fragment shader
2012 	{
2013 		std::ostringstream src;
2014 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2015 			<< "\n"
2016 			<< "layout(location = 0) in  vec4 in_color;\n"
2017 			<< "layout(location = 0) out vec4 o_color;\n"
2018 			<< "\n"
2019 			<< "void main(void)\n"
2020 			<< "{\n"
2021 			<< "    o_color = in_color;\n"
2022 			<< "}\n";
2023 
2024 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2025 	}
2026 }
2027 
2028 //! Draw shapes using changing sample patterns. Add clears and other operations as necessary
2029 class DrawTest : public TestInstance
2030 {
2031 	static const deUint32 NUM_PASSES = 2u;
2032 
2033 public:
DrawTest(Context & context,const TestParams params)2034 	DrawTest (Context& context, const TestParams params)
2035 		: TestInstance					(context)
2036 		, m_params						(params)
2037 		, m_sampleLocationsProperties	(getSampleLocationsPropertiesEXT(context))
2038 		, m_renderSize					(64, 32)
2039 		, m_numVertices					(0)
2040 		, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
2041 		, m_depthStencilFormat			(VK_FORMAT_UNDEFINED)
2042 		, m_depthStencilAspect			(0)
2043 	{
2044 		VkMultisamplePropertiesEXT multisampleProperties =
2045 		{
2046 			VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT,		// VkStructureType    sType;
2047 			DE_NULL,											// void*              pNext;
2048 			VkExtent2D(),										// VkExtent2D         maxSampleLocationGridSize;
2049 		};
2050 
2051 		// For this test always use the full pixel grid
2052 
2053 		m_context.getInstanceInterface().getPhysicalDeviceMultisamplePropertiesEXT(m_context.getPhysicalDevice(), m_params.numSamples, &multisampleProperties);
2054 		m_gridSize.x() = multisampleProperties.maxSampleLocationGridSize.width;
2055 		m_gridSize.y() = multisampleProperties.maxSampleLocationGridSize.height;
2056 	}
2057 
iterate(void)2058 	tcu::TestStatus iterate (void)
2059 	{
2060 		// Requirements
2061 		if (!(m_gridSize.x() >= 1 && m_gridSize.y() >= 1))
2062 			return tcu::TestStatus::fail("maxSampleLocationGridSize is invalid");
2063 
2064 		// Images
2065 		{
2066 			const DeviceInterface&	vk					 = m_context.getDeviceInterface();
2067 			const VkDevice			device				 = m_context.getDevice();
2068 			Allocator&				allocator			 = m_context.getDefaultAllocator();
2069 			const VkImageUsageFlags	colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2070 
2071 			m_colorImage		= makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, m_params.numSamples, colorImageUsageFlags);
2072 			m_colorImageAlloc	= bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
2073 			m_colorImageView	= makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat,
2074 												makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
2075 
2076 			m_resolveImage		= makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
2077 			m_resolveImageAlloc	= bindImage(vk, device, allocator, *m_resolveImage, MemoryRequirement::Any);
2078 			m_resolveImageView	= makeImageView(vk, device, *m_resolveImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat,
2079 												makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
2080 
2081 			const VkDeviceSize	colorBufferSize = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(m_colorFormat));
2082 			m_colorBuffer		= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2083 			m_colorBufferAlloc	= bindBuffer(vk, device, allocator, *m_colorBuffer, MemoryRequirement::HostVisible);
2084 
2085 			if (m_params.imageAspect != TEST_IMAGE_ASPECT_COLOR)
2086 			{
2087 				const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2088 
2089 				m_depthStencilFormat	 = findSupportedDepthStencilFormat(m_context, useDepth(), useStencil());
2090 				m_depthStencilAspect	 = (useDepth()   ? VK_IMAGE_ASPECT_DEPTH_BIT   : (VkImageAspectFlagBits)0) |
2091 										   (useStencil() ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0);
2092 				m_depthStencilImage		 = makeImage(vk, device, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT,
2093 													 m_depthStencilFormat, m_renderSize, m_params.numSamples, depthStencilImageUsageFlags);
2094 				m_depthStencilImageAlloc = bindImage(vk, device, allocator, *m_depthStencilImage, MemoryRequirement::Any);
2095 				m_depthStencilImageView	 = makeImageView(vk, device, *m_depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, m_depthStencilFormat,
2096 														 makeImageSubresourceRange(m_depthStencilAspect, 0u, 1u, 0u, 1u));
2097 			}
2098 		}
2099 
2100 		// Vertices
2101 		{
2102 			const DeviceInterface&	vk			= m_context.getDeviceInterface();
2103 			const VkDevice			device		= m_context.getDevice();
2104 			Allocator&				allocator	= m_context.getDefaultAllocator();
2105 
2106 			std::vector<PositionColor> vertices;
2107 
2108 			if (useDepth())
2109 			{
2110 				append(vertices, genVerticesShapes  (RGBA::black().toVec(), DEPTH_REFERENCE / 2.0f));	// mask above (z = 0.0 is nearest)
2111 				append(vertices, genVerticesFullQuad(RGBA::white().toVec(), DEPTH_REFERENCE));			// fill below the mask, using the depth test
2112 			}
2113 			else if (useStencil())
2114 			{
2115 				append(vertices, genVerticesShapes  (RGBA::black().toVec(), DEPTH_REFERENCE));			// first mask
2116 				append(vertices, genVerticesFullQuad(RGBA::white().toVec(), DEPTH_REFERENCE / 2.0f));	// then fill the whole area, using the stencil test
2117 			}
2118 			else
2119 				vertices = genVerticesShapes();
2120 
2121 			const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(vertices.size() * sizeof(vertices[0]));
2122 
2123 			m_numVertices       = static_cast<deUint32>(vertices.size());
2124 			m_vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2125 			m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);
2126 
2127 			deMemcpy(m_vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
2128 			flushAlloc(vk, device, *m_vertexBufferAlloc);
2129 		}
2130 
2131 		// Multisample pixel grids - set up two sample patterns for two draw passes
2132 		{
2133 			const deUint32 numGrids = (useSameSamplePattern() ? 1u : NUM_PASSES);
2134 			m_pixelGrids.reserve(numGrids);
2135 
2136 			for (deUint32 passNdx = 0u; passNdx < numGrids; ++passNdx)
2137 			{
2138 				const deUint32 seed = 142u + 75u * passNdx;
2139 				m_pixelGrids.push_back(MultisamplePixelGrid(m_gridSize, m_params.numSamples));
2140 				fillSampleLocationsRandom(m_pixelGrids.back(), m_sampleLocationsProperties.sampleLocationSubPixelBits, seed);
2141 				logPixelGrid (m_context.getTestContext().getLog(), m_sampleLocationsProperties, m_pixelGrids.back());
2142 			}
2143 		}
2144 
2145 		// Some test cases will not clear the left hand image, so we can use it directly
2146 		const bool isClearCase		= (m_params.clears != TEST_CLEARS_NO_CLEAR);
2147 		const bool hasLeftSideImage = (!isClearCase ||
2148 										(m_params.drawIn != TEST_DRAW_IN_RENDER_PASSES && m_params.clears != TEST_CLEARS_CMD_CLEAR_ATTACHMENTS));
2149 
2150 		// Render second pass reference image with the first pattern
2151 		tcu::TextureLevel refImagePattern0;
2152 		if (!useSameSamplePattern() && !hasLeftSideImage)
2153 		{
2154 			const tcu::TextureFormat colorFormat = mapVkFormat(m_colorFormat);
2155 
2156 			drawPatternChangeReference();
2157 
2158 			refImagePattern0.setStorage(colorFormat, m_renderSize.x(), m_renderSize.y());
2159 			tcu::copy(refImagePattern0.getAccess(), tcu::ConstPixelBufferAccess(colorFormat, tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr()));
2160 		}
2161 
2162 		// Two-pass rendering
2163 
2164 		switch (m_params.drawIn)
2165 		{
2166 			case TEST_DRAW_IN_RENDER_PASSES:	drawRenderPasses();	break;
2167 			case TEST_DRAW_IN_SUBPASSES:		drawSubpasses();	break;
2168 			case TEST_DRAW_IN_SAME_SUBPASS:		drawSameSubpass();	break;
2169 
2170 			default:
2171 				DE_ASSERT(0);
2172 				break;
2173 		}
2174 
2175 		// Log the result
2176 
2177 		const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr()));
2178 
2179 		m_context.getTestContext().getLog()
2180 			<< tcu::TestLog::ImageSet("Result", "Final result")
2181 			<< tcu::TestLog::Image("resolve0", "resolve0", image)
2182 			<< tcu::TestLog::EndImageSet;
2183 
2184 		// Verify result
2185 		{
2186 			DE_ASSERT((m_renderSize.x() % 2) == 0);
2187 			DE_ASSERT((m_renderSize.y() % 2) == 0);
2188 
2189 			// Count colors in each image half separately, each half may have its own background color
2190 			const int  numBackgroundColors		= 1;
2191 			const int  numExpectedColorsRight	= numBackgroundColors + static_cast<int>(m_params.numSamples);
2192 			const int  numExpectedColorsLeft	= (isClearCase ? numBackgroundColors : numExpectedColorsRight);
2193 			const int  numActualColorsLeft		= countUniqueColors(tcu::getSubregion(image, 0,					 0, m_renderSize.x()/2, m_renderSize.y()));
2194 			const int  numActualColorsRight		= countUniqueColors(tcu::getSubregion(image, m_renderSize.x()/2, 0, m_renderSize.x()/2, m_renderSize.y()));
2195 
2196 			if (numActualColorsLeft != numExpectedColorsLeft || numActualColorsRight != numExpectedColorsRight)
2197 			{
2198 				std::ostringstream msg;
2199 				msg << "Expected " << numExpectedColorsLeft << " unique colors, but got " << numActualColorsLeft;
2200 
2201 				if (numActualColorsLeft != numActualColorsRight)
2202 					msg << " and " << numActualColorsRight;
2203 
2204 				m_context.getTestContext().getLog()
2205 					<< tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2206 
2207 				return tcu::TestStatus::fail("Resolved image has incorrect pixels");
2208 			}
2209 
2210 			if (hasLeftSideImage)
2211 			{
2212 				// Compare the left and the right half
2213 				const bool match = intThresholdCompare(tcu::getSubregion(image,	0,					0, m_renderSize.x()/2,	m_renderSize.y()),
2214 													   tcu::getSubregion(image,	m_renderSize.x()/2, 0, m_renderSize.x()/2,	m_renderSize.y()),
2215 													   UVec4(2u));
2216 				if (useSameSamplePattern() && !match)
2217 					return tcu::TestStatus::fail("Multisample pattern should be identical in both image halves");
2218 				else if (!useSameSamplePattern() && match)
2219 					return tcu::TestStatus::fail("Multisample pattern doesn't seem to change between left and right image halves");
2220 			}
2221 			else if (!useSameSamplePattern())
2222 			{
2223 				// Compare the right half with the previously rendered reference image -- patterns should be different
2224 				bool match = intThresholdCompare(tcu::getSubregion(refImagePattern0.getAccess(),	m_renderSize.x()/2, 0, m_renderSize.x()/2,	m_renderSize.y()),
2225 												 tcu::getSubregion(image,							m_renderSize.x()/2, 0, m_renderSize.x()/2,	m_renderSize.y()),
2226 												 UVec4(2u));
2227 
2228 				if (match)
2229 					return tcu::TestStatus::fail("Multisample pattern doesn't seem to change between passes");
2230 			}
2231 		}
2232 
2233 		return tcu::TestStatus::pass("Pass");
2234 	}
2235 
2236 protected:
useDepth(void) const2237 	bool useDepth				(void) const { return m_params.imageAspect == TEST_IMAGE_ASPECT_DEPTH; }
useStencil(void) const2238 	bool useStencil				(void) const { return m_params.imageAspect == TEST_IMAGE_ASPECT_STENCIL; }
useSameSamplePattern(void) const2239 	bool useSameSamplePattern	(void) const { return (m_params.options & TEST_OPTION_SAME_PATTERN_BIT) != 0u; }
useDynamicState(void) const2240 	bool useDynamicState		(void) const { return (m_params.options & TEST_OPTION_DYNAMIC_STATE_BIT) != 0u; }
useSecondaryCmdBuffer(void) const2241 	bool useSecondaryCmdBuffer	(void) const { return (m_params.options & TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT) != 0u; }
useGeneralLayout(void) const2242 	bool useGeneralLayout		(void) const { return (m_params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0u; }
useWaitEvents(void) const2243 	bool useWaitEvents			(void) const { return (m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) != 0u; }
useFragmentShadingRate(void) const2244 	bool useFragmentShadingRate	(void) const { return (m_params.options & TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) != 0u; }
2245 
2246 	//! Draw the second pass image, but with sample pattern from the first pass -- used to verify that the pattern is different
drawPatternChangeReference(void)2247 	void drawPatternChangeReference (void)
2248 	{
2249 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
2250 		const VkDevice					device				= m_context.getDevice();
2251 		const VkViewport				viewport			= makeViewport(m_renderSize);
2252 		const VkRect2D					renderArea			= makeRect2D(m_renderSize);
2253 		const VkRect2D					scissor				= makeRect2D(m_renderSize);
2254 		const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2255 		const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2256 		const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
2257 		const VkSampleLocationsInfoEXT	sampleLocationsInfo	= makeSampleLocationsInfo(m_pixelGrids[0]);
2258 		const VkClearValue				clearColor0			= (m_params.clears == TEST_CLEARS_NO_CLEAR ? makeClearValueColor(CLEAR_COLOR_0) : makeClearValueColor(CLEAR_COLOR_1));
2259 
2260 		RenderTarget rt;
2261 
2262 		rt.addAttachment(
2263 			*m_colorImageView,											// VkImageView					imageView,
2264 			(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2265 			m_colorFormat,												// VkFormat						format,
2266 			m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
2267 			VK_ATTACHMENT_LOAD_OP_CLEAR,								// VkAttachmentLoadOp			loadOp,
2268 			VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2269 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2270 			VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2271 			VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2272 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout				finalLayout,
2273 			clearColor0);												// VkClearValue					clearValue,
2274 
2275 		rt.addAttachment(
2276 			*m_resolveImageView,										// VkImageView					imageView,
2277 			(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2278 			m_colorFormat,												// VkFormat						format,
2279 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		numSamples,
2280 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			loadOp,
2281 			VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2282 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2283 			VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2284 			VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2285 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout				finalLayout,
2286 			VkClearValue());											// VkClearValue					clearValue,
2287 
2288 		rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2289 												1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2290 
2291 		if (useDepth() || useStencil())
2292 		{
2293 			rt.addAttachment(
2294 				*m_depthStencilImageView,										// VkImageView					imageView,
2295 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags	flags,
2296 				m_depthStencilFormat,											// VkFormat						format,
2297 				m_params.numSamples,											// VkSampleCountFlagBits		numSamples,
2298 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			loadOp,
2299 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp,
2300 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			stencilLoadOp,
2301 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			stencilStoreOp,
2302 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout				initialLayout,
2303 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout,
2304 				makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE),		// VkClearValue					clearValue,
2305 				&sampleLocationsInfo);											// VkSampleLocationsInfoEXT*	pInitialSampleLocations
2306 
2307 			rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo);
2308 		}
2309 
2310 		rt.bake(vk, device, m_renderSize);
2311 
2312 		GraphicsPipelineWrapper pipeline(vk, device, m_params.pipelineConstructionType);
2313 		preparePipelineWrapper(pipeline, std::vector<VkDynamicState>(), *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule,
2314 				/*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo,
2315 				useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate());
2316 
2317 		const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()));
2318 		const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
2319 		Move<VkCommandBuffer>			secondaryCmdBuffer;
2320 		VkCommandBuffer					currentCmdBuffer	= *cmdBuffer;
2321 
2322 		beginCommandBuffer(vk, currentCmdBuffer);
2323 		rt.recordBeginRenderPass(vk, currentCmdBuffer, renderArea, (useSecondaryCmdBuffer() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE));
2324 
2325 		// For maximum consistency also use a secondary command buffer, if the two-pass path uses it
2326 		if (useSecondaryCmdBuffer())
2327 		{
2328 			secondaryCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2329 			currentCmdBuffer = *secondaryCmdBuffer;
2330 
2331 			beginSecondaryCommandBuffer(vk, currentCmdBuffer, rt.getRenderPass(), /*subpass*/ 0u, rt.getFramebuffer());
2332 		}
2333 
2334 		vk.cmdBindVertexBuffers(currentCmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO);
2335 		vk.cmdBindPipeline(currentCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
2336 
2337 		// Draw the right shape only
2338 		vk.cmdDraw(currentCmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 1u);
2339 
2340 		if (useSecondaryCmdBuffer())
2341 		{
2342 			endCommandBuffer(vk, currentCmdBuffer);
2343 			currentCmdBuffer = *cmdBuffer;
2344 
2345 			vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer.get());
2346 		}
2347 
2348 		endRenderPass(vk, *cmdBuffer);
2349 
2350 		recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer);
2351 
2352 		endCommandBuffer(vk, *cmdBuffer);
2353 		submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
2354 
2355 		invalidateAlloc(vk, device, *m_colorBufferAlloc);
2356 	}
2357 
2358 	//! Draw two shapes with distinct sample patterns, each in its own render pass
drawRenderPasses(void)2359 	void drawRenderPasses (void)
2360 	{
2361 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
2362 		const VkDevice					device				= m_context.getDevice();
2363 		const VkViewport				viewport			= makeViewport(m_renderSize);
2364 		const VkRect2D					renderArea			= makeRect2D(m_renderSize);
2365 		const VkRect2D					scissor				= makeRect2D(m_renderSize);
2366 		const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2367 		const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2368 		const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
2369 		const VkClearValue				clearColor0			= makeClearValueColor(CLEAR_COLOR_0);
2370 		const VkClearValue				clearColor1			= makeClearValueColor(CLEAR_COLOR_1);
2371 		const VkClearValue				clearDepthStencil0	= makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE);
2372 		const VkSampleLocationsInfoEXT	sampleLocationsInfo	[NUM_PASSES] =
2373 		{
2374 			makeSampleLocationsInfo(m_pixelGrids[0]),
2375 			makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]),
2376 		};
2377 		const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()));
2378 		Move<VkCommandBuffer>			cmdBuffer			[NUM_PASSES] =
2379 		{
2380 			makeCommandBuffer(vk, device, *cmdPool),
2381 			makeCommandBuffer(vk, device, *cmdPool),
2382 		};
2383 		Move<VkCommandBuffer>					secondaryCmdBuffer	[NUM_PASSES];
2384 		RenderTarget							rt					[NUM_PASSES];
2385 		std::vector<GraphicsPipelineWrapper>	pipelines;
2386 		Move<VkEvent>							event				[2];	/*color and depth/stencil*/
2387 
2388 		// Layouts expected by the second render pass
2389 		const VkImageLayout	colorLayout1		= useGeneralLayout() && !(useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2390 		const VkImageLayout	depthStencilLayout1	= useGeneralLayout() && (useDepth() || useStencil())  ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2391 
2392 		// First render pass - no resolves
2393 		{
2394 			rt[0].addAttachment(
2395 				*m_colorImageView,											// VkImageView					imageView,
2396 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2397 				m_colorFormat,												// VkFormat						format,
2398 				m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
2399 				VK_ATTACHMENT_LOAD_OP_CLEAR,								// VkAttachmentLoadOp			loadOp,
2400 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2401 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2402 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2403 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2404 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout				finalLayout,
2405 				clearColor0);												// VkClearValue					clearValue,
2406 
2407 			rt[0].addSubpassColorAttachment(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2408 
2409 			if (useDepth() || useStencil())
2410 			{
2411 				rt[0].addAttachment(
2412 					*m_depthStencilImageView,										// VkImageView					imageView,
2413 					(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags	flags,
2414 					m_depthStencilFormat,											// VkFormat						format,
2415 					m_params.numSamples,											// VkSampleCountFlagBits		numSamples,
2416 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			loadOp,
2417 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp,
2418 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			stencilLoadOp,
2419 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			stencilStoreOp,
2420 					VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout				initialLayout,
2421 					VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout,
2422 					clearDepthStencil0,												// VkClearValue					clearValue,
2423 					&sampleLocationsInfo[0]);										// VkSampleLocationsInfoEXT*	pInitialSampleLocations
2424 
2425 				rt[0].addSubpassDepthStencilAttachment(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]);
2426 			}
2427 
2428 			rt[0].bake(vk, device, m_renderSize);
2429 		}
2430 
2431 		// Second render pass
2432 		{
2433 			const VkAttachmentLoadOp loadOp	= (m_params.clears == TEST_CLEARS_LOAD_OP_CLEAR ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
2434 
2435 			rt[1].addAttachment(
2436 				*m_colorImageView,											// VkImageView					imageView,
2437 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2438 				m_colorFormat,												// VkFormat						format,
2439 				m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
2440 				loadOp,														// VkAttachmentLoadOp			loadOp,
2441 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2442 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2443 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2444 				colorLayout1,												// VkImageLayout				initialLayout,
2445 				colorLayout1,												// VkImageLayout				finalLayout,
2446 				clearColor1);												// VkClearValue					clearValue,
2447 
2448 			rt[1].addAttachment(
2449 				*m_resolveImageView,										// VkImageView					imageView,
2450 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2451 				m_colorFormat,												// VkFormat						format,
2452 				VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		numSamples,
2453 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			loadOp,
2454 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2455 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2456 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2457 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2458 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout				finalLayout,
2459 				VkClearValue());											// VkClearValue					clearValue,
2460 
2461 			rt[1].addSubpassColorAttachmentWithResolve(0u, colorLayout1,
2462 													   1u, colorLayout1);
2463 
2464 			if (useDepth() || useStencil())
2465 			{
2466 				rt[1].addAttachment(
2467 					*m_depthStencilImageView,										// VkImageView					imageView,
2468 					(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags	flags,
2469 					m_depthStencilFormat,											// VkFormat						format,
2470 					m_params.numSamples,											// VkSampleCountFlagBits		numSamples,
2471 					loadOp,															// VkAttachmentLoadOp			loadOp,
2472 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp,
2473 					loadOp,															// VkAttachmentLoadOp			stencilLoadOp,
2474 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			stencilStoreOp,
2475 					depthStencilLayout1,											// VkImageLayout				initialLayout,
2476 					depthStencilLayout1,											// VkImageLayout				finalLayout,
2477 					clearDepthStencil0,												// VkClearValue					clearValue,
2478 					&sampleLocationsInfo[1]);										// VkSampleLocationsInfoEXT*	pInitialSampleLocations
2479 
2480 				rt[1].addSubpassDepthStencilAttachment(2u, depthStencilLayout1, &sampleLocationsInfo[1]);
2481 			}
2482 
2483 			rt[1].bake(vk, device, m_renderSize);
2484 		}
2485 
2486 		// Pipelines
2487 		pipelines.reserve(NUM_PASSES);
2488 		if (useDynamicState())
2489 		{
2490 			std::vector<VkDynamicState>	dynamicState;
2491 			dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
2492 
2493 			for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
2494 			{
2495 				pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
2496 				preparePipelineWrapper(pipelines.back(), dynamicState, *pipelineLayout, rt[passNdx].getRenderPass(), *vertexModule, *fragmentModule,
2497 					/*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(),
2498 					useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate());
2499 			}
2500 		}
2501 		else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
2502 		{
2503 			pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
2504 			preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), *pipelineLayout, rt[passNdx].getRenderPass(), *vertexModule, *fragmentModule,
2505 				/*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx],
2506 				useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate());
2507 		}
2508 
2509 		// Record secondary command buffers
2510 
2511 		if (useSecondaryCmdBuffer())
2512 		{
2513 			secondaryCmdBuffer[0] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2514 			secondaryCmdBuffer[1] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2515 
2516 			// First render pass contents
2517 			beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[0], rt[0].getRenderPass(), /*subpass*/ 0u, rt[0].getFramebuffer());
2518 			recordFirstPassContents(*secondaryCmdBuffer[0], pipelines[0].getPipeline(), sampleLocationsInfo[0]);
2519 			endCommandBuffer(vk, *secondaryCmdBuffer[0]);
2520 
2521 			// Second render pass contents
2522 			beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[1], rt[1].getRenderPass(), /*subpass*/ 0u, rt[1].getFramebuffer());
2523 			recordSecondPassContents(*secondaryCmdBuffer[1], pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
2524 			endCommandBuffer(vk, *secondaryCmdBuffer[1]);
2525 		}
2526 
2527 		// Record primary command buffers
2528 
2529 		VkCommandBuffer currentCmdBuffer = *cmdBuffer[0];
2530 		beginCommandBuffer(vk, currentCmdBuffer);
2531 
2532 		// First render pass
2533 		if (useSecondaryCmdBuffer())
2534 		{
2535 			rt[0].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
2536 			vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer[0].get());
2537 			endRenderPass(vk, currentCmdBuffer);
2538 		}
2539 		else
2540 		{
2541 			rt[0].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE);
2542 			recordFirstPassContents(currentCmdBuffer, pipelines[0].getPipeline(), sampleLocationsInfo[0]);
2543 			endRenderPass(vk, currentCmdBuffer);
2544 		}
2545 
2546 		endCommandBuffer(vk, currentCmdBuffer);
2547 
2548 		// Record the second primary command buffer
2549 		currentCmdBuffer = *cmdBuffer[1];
2550 		beginCommandBuffer(vk, currentCmdBuffer);
2551 
2552 		if (m_params.clears == TEST_CLEARS_CMD_CLEAR_IMAGE)
2553 		{
2554 			{
2555 				const VkImageLayout finalLayout = (useWaitEvents() ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : colorLayout1);
2556 
2557 				recordImageBarrier(vk, currentCmdBuffer, *m_colorImage,
2558 									VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags	aspect,
2559 									VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags srcStageMask,
2560 									VK_PIPELINE_STAGE_TRANSFER_BIT,							// VkPipelineStageFlags dstStageMask,
2561 									VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags		srcAccessMask,
2562 									VK_ACCESS_TRANSFER_WRITE_BIT,							// VkAccessFlags		dstAccessMask,
2563 									VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout		oldLayout,
2564 									VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);					// VkImageLayout		newLayout)
2565 
2566 				const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2567 				vk.cmdClearColorImage(currentCmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor1.color, 1u, &subresourceRange);
2568 
2569 				recordImageBarrier(vk, currentCmdBuffer, *m_colorImage,
2570 						VK_IMAGE_ASPECT_COLOR_BIT,											// VkImageAspectFlags	aspect,
2571 						VK_PIPELINE_STAGE_TRANSFER_BIT,										// VkPipelineStageFlags srcStageMask,
2572 						VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,						// VkPipelineStageFlags dstStageMask,
2573 						VK_ACCESS_TRANSFER_WRITE_BIT,										// VkAccessFlags		srcAccessMask,
2574 						(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2575 						 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT),								// VkAccessFlags		dstAccessMask,
2576 						VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,								// VkImageLayout		oldLayout,
2577 						finalLayout);														// VkImageLayout		newLayout)
2578 			}
2579 
2580 			if (useDepth() || useStencil())
2581 			{
2582 				const VkImageLayout finalLayout = (useWaitEvents() ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : depthStencilLayout1);
2583 
2584 				recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage,
2585 								   getImageAspectFlags(m_depthStencilFormat),			// VkImageAspectFlags	aspect,
2586 								   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,			// VkPipelineStageFlags srcStageMask,
2587 								   VK_PIPELINE_STAGE_TRANSFER_BIT,						// VkPipelineStageFlags dstStageMask,
2588 								   VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags		srcAccessMask,
2589 								   VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask,
2590 								   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout		oldLayout,
2591 								   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout		newLayout)
2592 								   &sampleLocationsInfo[0]);							// VkSampleLocationsInfoEXT
2593 
2594 				const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(m_depthStencilAspect, 0u, 1u, 0u, 1u);
2595 				vk.cmdClearDepthStencilImage(currentCmdBuffer, *m_depthStencilImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDepthStencil0.depthStencil, 1u, &subresourceRange);
2596 
2597 				recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage,
2598 								   getImageAspectFlags(m_depthStencilFormat),			// VkImageAspectFlags	aspect,
2599 								   VK_PIPELINE_STAGE_TRANSFER_BIT,						// VkPipelineStageFlags srcStageMask,
2600 								   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,			// VkPipelineStageFlags dstStageMask,
2601 								   VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask,
2602 								   (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2603 									VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT),		// VkAccessFlags		dstAccessMask,
2604 								   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout		oldLayout,
2605 								   finalLayout,											// VkImageLayout		newLayout)
2606 								   &sampleLocationsInfo[0]);							// VkSampleLocationsInfoEXT
2607 			}
2608 		}
2609 		else if (!useWaitEvents())
2610 		{
2611 			// Barrier between the render passes
2612 
2613 			recordImageBarrier(vk, currentCmdBuffer, *m_colorImage,
2614 							   VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags	aspect,
2615 							   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags srcStageMask,
2616 							   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags dstStageMask,
2617 							   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags		srcAccessMask,
2618 							   (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2619 								VK_ACCESS_COLOR_ATTACHMENT_READ_BIT),					// VkAccessFlags		dstAccessMask,
2620 							   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout		oldLayout,
2621 							   colorLayout1);											// VkImageLayout		newLayout)
2622 
2623 			if (useDepth() || useStencil())
2624 			{
2625 				recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage,
2626 								   getImageAspectFlags(m_depthStencilFormat),			// VkImageAspectFlags	aspect,
2627 								   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,			// VkPipelineStageFlags srcStageMask,
2628 								   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,			// VkPipelineStageFlags dstStageMask,
2629 								   VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags		srcAccessMask,
2630 								   (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2631 									VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT),		// VkAccessFlags		dstAccessMask,
2632 								   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout		oldLayout,
2633 								   depthStencilLayout1);								// VkImageLayout		newLayout)
2634 			}
2635 		}
2636 
2637 		if (useWaitEvents())
2638 		{
2639 			// Use events to sync both render passes
2640 			event[0] = makeEvent(vk, device);
2641 			vk.cmdSetEvent(currentCmdBuffer, *event[0], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2642 
2643 			recordWaitEventWithImage(vk, currentCmdBuffer, *event[0], *m_colorImage,
2644 									 VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags		aspect,
2645 									 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags		srcStageMask,
2646 									 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags		dstStageMask,
2647 									 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags			srcAccessMask,
2648 									 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2649 									  VK_ACCESS_COLOR_ATTACHMENT_READ_BIT),					// VkAccessFlags			dstAccessMask,
2650 									 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			oldLayout,
2651 									 colorLayout1);											// VkImageLayout			newLayout,
2652 
2653 			if (useDepth() || useStencil())
2654 			{
2655 				event[1] = makeEvent(vk, device);
2656 				vk.cmdSetEvent(currentCmdBuffer, *event[1], VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
2657 
2658 				recordWaitEventWithImage(vk, currentCmdBuffer, *event[1], *m_depthStencilImage,
2659 										 getImageAspectFlags(m_depthStencilFormat),			// VkImageAspectFlags		aspect,
2660 										 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,			// VkPipelineStageFlags		srcStageMask,
2661 										 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags		dstStageMask,
2662 										 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask,
2663 										 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2664 										  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT),		// VkAccessFlags			dstAccessMask,
2665 										 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout,
2666 										 depthStencilLayout1);								// VkImageLayout			newLayout,
2667 			}
2668 		}
2669 
2670 		// Second render pass
2671 		if (useSecondaryCmdBuffer())
2672 		{
2673 			rt[1].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
2674 			vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer[1].get());
2675 			endRenderPass(vk, currentCmdBuffer);
2676 		}
2677 		else
2678 		{
2679 			rt[1].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE);
2680 			recordSecondPassContents(currentCmdBuffer, pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
2681 			endRenderPass(vk, currentCmdBuffer);
2682 		}
2683 
2684 		// Resolve image -> host buffer
2685 		recordCopyImageToBuffer(vk, currentCmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer);
2686 
2687 		endCommandBuffer(vk, currentCmdBuffer);
2688 
2689 		// Submit work
2690 		{
2691 			const Unique<VkFence>	fence	(createFence(vk, device));
2692 			const VkCommandBuffer	buffers	[NUM_PASSES] =
2693 			{
2694 				*cmdBuffer[0],
2695 				*cmdBuffer[1],
2696 			};
2697 
2698 			const VkSubmitInfo submitInfo =
2699 			{
2700 				VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType                sType;
2701 				DE_NULL,							// const void*                    pNext;
2702 				0u,									// uint32_t                       waitSemaphoreCount;
2703 				DE_NULL,							// const VkSemaphore*             pWaitSemaphores;
2704 				DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
2705 				DE_LENGTH_OF_ARRAY(buffers),		// uint32_t                       commandBufferCount;
2706 				buffers,							// const VkCommandBuffer*         pCommandBuffers;
2707 				0u,									// uint32_t                       signalSemaphoreCount;
2708 				DE_NULL,							// const VkSemaphore*             pSignalSemaphores;
2709 			};
2710 			VK_CHECK(vk.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, *fence));
2711 			VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
2712 		}
2713 
2714 		invalidateAlloc(vk, device, *m_colorBufferAlloc);
2715 	}
2716 
recordFirstPassContents(const VkCommandBuffer cmdBuffer,const VkPipeline pipeline,const VkSampleLocationsInfoEXT & sampleLocationsInfo)2717 	void recordFirstPassContents (const VkCommandBuffer				cmdBuffer,
2718 								  const VkPipeline					pipeline,
2719 								  const VkSampleLocationsInfoEXT&	sampleLocationsInfo)
2720 	{
2721 		const DeviceInterface& vk = m_context.getDeviceInterface();
2722 
2723 		vk.cmdBindVertexBuffers(cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO);
2724 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
2725 
2726 		if (useDynamicState())
2727 			vk.cmdSetSampleLocationsEXT(cmdBuffer, &sampleLocationsInfo);
2728 
2729 		if (m_params.clears == TEST_CLEARS_NO_CLEAR)
2730 			vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 0u);			// left shape only
2731 		else
2732 			vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ NUM_PASSES, /*first vertex*/ 0u, /*first instance*/ 0u);	// both shapes
2733 	}
2734 
recordSecondPassContents(const VkCommandBuffer cmdBuffer,const VkPipeline pipeline,const VkSampleLocationsInfoEXT & sampleLocationsInfo,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil,const VkRect2D & clearRect)2735 	void recordSecondPassContents (const VkCommandBuffer			cmdBuffer,
2736 								   const VkPipeline					pipeline,
2737 								   const VkSampleLocationsInfoEXT&	sampleLocationsInfo,
2738 								   const VkClearValue&				clearColor,
2739 								   const VkClearValue&				clearDepthStencil,
2740 								   const VkRect2D&					clearRect)
2741 	{
2742 		const DeviceInterface& vk = m_context.getDeviceInterface();
2743 
2744 		vk.cmdBindVertexBuffers(cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO);
2745 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
2746 
2747 		if (m_params.clears == TEST_CLEARS_CMD_CLEAR_ATTACHMENTS)
2748 			recordClearAttachments(vk, cmdBuffer, 0u, clearColor, m_depthStencilAspect, clearDepthStencil, clearRect);
2749 
2750 		if (useDynamicState())
2751 			vk.cmdSetSampleLocationsEXT(cmdBuffer, &sampleLocationsInfo);
2752 
2753 		// Draw the right shape only
2754 		vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 1u);
2755 	}
2756 
2757 	//! Draw two shapes in two subpasses of the same render pass
drawSubpasses(void)2758 	void drawSubpasses (void)
2759 	{
2760 		DE_ASSERT(m_params.clears != TEST_CLEARS_CMD_CLEAR_IMAGE);			// not possible in a render pass
2761 		DE_ASSERT(m_params.clears != TEST_CLEARS_LOAD_OP_CLEAR);			// can't specify a load op for a subpass
2762 		DE_ASSERT((m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) == 0);	// can't change layouts inside a subpass
2763 
2764 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
2765 		const VkDevice					device				= m_context.getDevice();
2766 		const VkViewport				viewport			= makeViewport(m_renderSize);
2767 		const VkRect2D					renderArea			= makeRect2D(m_renderSize);
2768 		const VkRect2D					scissor				= makeRect2D(m_renderSize);
2769 		const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2770 		const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2771 		const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
2772 		const VkClearValue				clearColor0			= makeClearValueColor(CLEAR_COLOR_0);
2773 		const VkClearValue				clearColor1			= makeClearValueColor(CLEAR_COLOR_1);
2774 		const VkClearValue				clearDepthStencil0	= makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE);
2775 		const VkSampleLocationsInfoEXT	sampleLocationsInfo	[NUM_PASSES] =
2776 		{
2777 			makeSampleLocationsInfo(m_pixelGrids[0]),
2778 			makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]),
2779 		};
2780 		const Unique<VkCommandPool>				cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()));
2781 		const Unique<VkCommandBuffer>			cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
2782 		Move<VkCommandBuffer>					secondaryCmdBuffer	[NUM_PASSES];
2783 		RenderTarget							rt;
2784 		std::vector<GraphicsPipelineWrapper>	pipelines;
2785 		Move<VkEvent>							event;
2786 
2787 		// Layouts used in the second subpass
2788 		const VkImageLayout	colorLayout1		= useGeneralLayout() && !(useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2789 		const VkImageLayout	depthStencilLayout1	= useGeneralLayout() && (useDepth() || useStencil())  ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2790 
2791 		// Prepare the render pass
2792 		{
2793 			rt.addAttachment(
2794 				*m_colorImageView,											// VkImageView					imageView,
2795 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2796 				m_colorFormat,												// VkFormat						format,
2797 				m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
2798 				VK_ATTACHMENT_LOAD_OP_CLEAR,								// VkAttachmentLoadOp			loadOp,
2799 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2800 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2801 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2802 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2803 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout				finalLayout,
2804 				clearColor0);												// VkClearValue					clearValue,
2805 
2806 			rt.addAttachment(
2807 				*m_resolveImageView,										// VkImageView					imageView,
2808 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2809 				m_colorFormat,												// VkFormat						format,
2810 				VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		numSamples,
2811 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			loadOp,
2812 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2813 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2814 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2815 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2816 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout				finalLayout,
2817 				VkClearValue());											// VkClearValue					clearValue,
2818 
2819 			// First subpass
2820 			rt.addSubpassColorAttachment(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2821 
2822 			if (useDepth() || useStencil())
2823 			{
2824 				rt.addAttachment(
2825 					*m_depthStencilImageView,										// VkImageView					imageView,
2826 					(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags	flags,
2827 					m_depthStencilFormat,											// VkFormat						format,
2828 					m_params.numSamples,											// VkSampleCountFlagBits		numSamples,
2829 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			loadOp,
2830 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp,
2831 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			stencilLoadOp,
2832 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			stencilStoreOp,
2833 					VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout				initialLayout,
2834 					VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout,
2835 					clearDepthStencil0,												// VkClearValue					clearValue,
2836 					&sampleLocationsInfo[0]);										// VkSampleLocationsInfoEXT*	pInitialSampleLocations
2837 
2838 				rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]);
2839 			}
2840 
2841 			// Second subpass
2842 			rt.nextSubpass();
2843 			rt.addSubpassColorAttachmentWithResolve(0u, colorLayout1,
2844 													1u, colorLayout1);
2845 
2846 			if (useDepth() || useStencil())
2847 				rt.addSubpassDepthStencilAttachment(2u, depthStencilLayout1, &sampleLocationsInfo[1]);
2848 
2849 			rt.bake(vk, device, m_renderSize);
2850 		}
2851 
2852 		// Pipelines
2853 		pipelines.reserve(NUM_PASSES);
2854 		if (useDynamicState())
2855 		{
2856 			std::vector<VkDynamicState>	dynamicState;
2857 			dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
2858 
2859 			for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
2860 			{
2861 				pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
2862 				preparePipelineWrapper(pipelines.back(), dynamicState, *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule,
2863 					/*subpass*/ passNdx, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(),
2864 					useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate());
2865 			}
2866 		}
2867 		else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
2868 		{
2869 			pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
2870 			preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule,
2871 				/*subpass*/ passNdx, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx],
2872 				useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate());
2873 		}
2874 
2875 		// Record secondary command buffers
2876 
2877 		if (useSecondaryCmdBuffer())
2878 		{
2879 			secondaryCmdBuffer[0] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2880 			secondaryCmdBuffer[1] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2881 
2882 			// First subpass contents
2883 			beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[0], rt.getRenderPass(), /*subpass*/ 0u, rt.getFramebuffer());
2884 			recordFirstPassContents(*secondaryCmdBuffer[0], pipelines[0].getPipeline(), sampleLocationsInfo[0]);
2885 			endCommandBuffer(vk, *secondaryCmdBuffer[0]);
2886 
2887 			// Second subpass contents
2888 			beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[1], rt.getRenderPass(), /*subpass*/ 1u, rt.getFramebuffer());
2889 			recordSecondPassContents(*secondaryCmdBuffer[1], pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
2890 			endCommandBuffer(vk, *secondaryCmdBuffer[1]);
2891 		}
2892 
2893 		// Record primary command buffer
2894 
2895 		beginCommandBuffer(vk, *cmdBuffer);
2896 
2897 		if (useSecondaryCmdBuffer())
2898 		{
2899 			rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
2900 			vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer[0].get());
2901 
2902 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
2903 			vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer[1].get());
2904 		}
2905 		else
2906 		{
2907 			rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE);
2908 			recordFirstPassContents(*cmdBuffer, pipelines[0].getPipeline(), sampleLocationsInfo[0]);
2909 
2910 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
2911 			recordSecondPassContents(*cmdBuffer, pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
2912 		}
2913 
2914 		endRenderPass(vk, *cmdBuffer);
2915 
2916 		// Resolve image -> host buffer
2917 		recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer);
2918 
2919 		endCommandBuffer(vk, *cmdBuffer);
2920 
2921 		submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
2922 		invalidateAlloc(vk, device, *m_colorBufferAlloc);
2923 	}
2924 
2925 	//! Draw two shapes within the same subpass of a renderpass
drawSameSubpass(void)2926 	void drawSameSubpass (void)
2927 	{
2928 		DE_ASSERT(m_params.clears != TEST_CLEARS_CMD_CLEAR_IMAGE);				// not possible in a render pass
2929 		DE_ASSERT(m_params.clears != TEST_CLEARS_LOAD_OP_CLEAR);				// can't specify a load op for a subpass
2930 		DE_ASSERT((m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) == 0);		// can't change layouts inside a subpass
2931 		DE_ASSERT((m_params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) == 0);	// can't change layouts inside a subpass
2932 
2933 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
2934 		const VkDevice					device				= m_context.getDevice();
2935 		const VkViewport				viewport			= makeViewport(m_renderSize);
2936 		const VkRect2D					renderArea			= makeRect2D(m_renderSize);
2937 		const VkRect2D					scissor				= makeRect2D(m_renderSize);
2938 		const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2939 		const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2940 		const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
2941 		const VkClearValue				clearColor0			= makeClearValueColor(CLEAR_COLOR_0);
2942 		const VkClearValue				clearColor1			= makeClearValueColor(CLEAR_COLOR_1);
2943 		const VkClearValue				clearDepthStencil0	= makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE);
2944 		const VkSampleLocationsInfoEXT	sampleLocationsInfo	[NUM_PASSES] =
2945 		{
2946 			makeSampleLocationsInfo(m_pixelGrids[0]),
2947 			makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]),
2948 		};
2949 		const bool								useFragmentShadingRate	(TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & m_params.options);
2950 		const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()));
2951 		const Unique<VkCommandBuffer>			cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
2952 		Move<VkCommandBuffer>					secondaryCmdBuffer;
2953 		RenderTarget							rt;
2954 		std::vector<GraphicsPipelineWrapper>	pipelines;
2955 		Move<VkEvent>							event;
2956 
2957 		// Prepare the render pass
2958 		{
2959 			rt.addAttachment(
2960 				*m_colorImageView,											// VkImageView					imageView,
2961 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2962 				m_colorFormat,												// VkFormat						format,
2963 				m_params.numSamples,										// VkSampleCountFlagBits		numSamples,
2964 				VK_ATTACHMENT_LOAD_OP_CLEAR,								// VkAttachmentLoadOp			loadOp,
2965 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2966 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2967 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2968 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2969 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout				finalLayout,
2970 				clearColor0);												// VkClearValue					clearValue,
2971 
2972 			rt.addAttachment(
2973 				*m_resolveImageView,										// VkImageView					imageView,
2974 				(VkAttachmentDescriptionFlags)0,							// VkAttachmentDescriptionFlags	flags,
2975 				m_colorFormat,												// VkFormat						format,
2976 				VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		numSamples,
2977 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			loadOp,
2978 				VK_ATTACHMENT_STORE_OP_STORE,								// VkAttachmentStoreOp			storeOp,
2979 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,							// VkAttachmentLoadOp			stencilLoadOp,
2980 				VK_ATTACHMENT_STORE_OP_DONT_CARE,							// VkAttachmentStoreOp			stencilStoreOp,
2981 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout				initialLayout,
2982 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout				finalLayout,
2983 				VkClearValue());											// VkClearValue					clearValue,
2984 
2985 			rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2986 													1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2987 
2988 			if (useDepth() || useStencil())
2989 			{
2990 				rt.addAttachment(
2991 					*m_depthStencilImageView,										// VkImageView					imageView,
2992 					(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags	flags,
2993 					m_depthStencilFormat,											// VkFormat						format,
2994 					m_params.numSamples,											// VkSampleCountFlagBits		numSamples,
2995 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			loadOp,
2996 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp,
2997 					VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp			stencilLoadOp,
2998 					VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			stencilStoreOp,
2999 					VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout				initialLayout,
3000 					VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout,
3001 					clearDepthStencil0,												// VkClearValue					clearValue,
3002 					&sampleLocationsInfo[0]);										// VkSampleLocationsInfoEXT*	pInitialSampleLocations
3003 
3004 				rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]);
3005 			}
3006 
3007 			rt.bake(vk, device, m_renderSize);
3008 		}
3009 
3010 		// Pipelines
3011 		pipelines.reserve(NUM_PASSES);
3012 		if (useDynamicState())
3013 		{
3014 			std::vector<VkDynamicState>	dynamicState;
3015 			dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
3016 
3017 			for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
3018 			{
3019 				pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
3020 				preparePipelineWrapper(pipelines.back(), dynamicState, *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule,
3021 					/*subpass*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(),
3022 					useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate);
3023 			}
3024 		}
3025 		else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx)
3026 		{
3027 			pipelines.emplace_back(vk, device, m_params.pipelineConstructionType);
3028 			preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), *pipelineLayout, rt.getRenderPass(), *vertexModule, *fragmentModule,
3029 				/*subpass*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx],
3030 				useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate);
3031 		}
3032 
3033 		// Record secondary command buffers
3034 
3035 		if (useSecondaryCmdBuffer())
3036 		{
3037 			secondaryCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
3038 
3039 			beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, rt.getRenderPass(), /*subpass*/ 0u, rt.getFramebuffer());
3040 			recordFirstPassContents(*secondaryCmdBuffer, pipelines[0].getPipeline(), sampleLocationsInfo[0]);
3041 			recordSecondPassContents(*secondaryCmdBuffer, pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
3042 			endCommandBuffer(vk, *secondaryCmdBuffer);
3043 		}
3044 
3045 		// Record primary command buffer
3046 
3047 		beginCommandBuffer(vk, *cmdBuffer);
3048 
3049 		if (useSecondaryCmdBuffer())
3050 		{
3051 			rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
3052 			vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
3053 		}
3054 		else
3055 		{
3056 			rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE);
3057 			recordFirstPassContents(*cmdBuffer, pipelines[0].getPipeline(), sampleLocationsInfo[0]);
3058 			recordSecondPassContents(*cmdBuffer, pipelines[1].getPipeline(), sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor);
3059 		}
3060 
3061 		endRenderPass(vk, *cmdBuffer);
3062 
3063 		// Resolve image -> host buffer
3064 		recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer);
3065 
3066 		endCommandBuffer(vk, *cmdBuffer);
3067 
3068 		submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
3069 		invalidateAlloc(vk, device, *m_colorBufferAlloc);
3070 	}
3071 
3072 	const TestParams									m_params;
3073 	const VkPhysicalDeviceSampleLocationsPropertiesEXT	m_sampleLocationsProperties;
3074 	const UVec2											m_renderSize;
3075 	UVec2												m_gridSize;
3076 	std::vector<MultisamplePixelGrid>					m_pixelGrids;
3077 	deUint32											m_numVertices;
3078 	Move<VkBuffer>										m_vertexBuffer;
3079 	MovePtr<Allocation>									m_vertexBufferAlloc;
3080 	const VkFormat										m_colorFormat;
3081 	Move<VkImage>										m_colorImage;
3082 	Move<VkImageView>									m_colorImageView;
3083 	MovePtr<Allocation>									m_colorImageAlloc;
3084 	VkFormat											m_depthStencilFormat;
3085 	VkImageAspectFlags									m_depthStencilAspect;
3086 	Move<VkImage>										m_depthStencilImage;
3087 	Move<VkImageView>									m_depthStencilImageView;
3088 	MovePtr<Allocation>									m_depthStencilImageAlloc;
3089 	Move<VkImage>										m_resolveImage;
3090 	Move<VkImageView>									m_resolveImageView;
3091 	MovePtr<Allocation>									m_resolveImageAlloc;
3092 	Move<VkBuffer>										m_colorBuffer;
3093 	MovePtr<Allocation>									m_colorBufferAlloc;
3094 };
3095 
3096 } // Draw
3097 
createTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)3098 void createTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate)
3099 {
3100 	// Queries
3101 	if (!useFragmentShadingRate && (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC))
3102 	{
3103 		MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "query", ""));
3104 
3105 		addFunctionCase(group.get(), "sample_locations_properties", "", checkSupportSampleLocations, testQuerySampleLocationProperties);
3106 		addFunctionCase(group.get(), "multisample_properties",		"", checkSupportSampleLocations, testQueryMultisampleProperties);
3107 
3108 		rootGroup->addChild(group.release());
3109 	}
3110 
3111 	const VkSampleCountFlagBits	sampleCountRange[] =
3112 	{
3113 		VK_SAMPLE_COUNT_2_BIT,
3114 		VK_SAMPLE_COUNT_4_BIT,
3115 		VK_SAMPLE_COUNT_8_BIT,
3116 		VK_SAMPLE_COUNT_16_BIT,
3117 		// There are no implementations that support 32 or 64 programmable samples currently
3118 	};
3119 
3120 	// Verify custom sample locations and interpolation
3121 	{
3122 		using namespace VerifySamples;
3123 
3124 		MovePtr<tcu::TestCaseGroup> groupLocation		(new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_location", ""));
3125 		MovePtr<tcu::TestCaseGroup> groupInterpolation	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_interpolation", ""));
3126 
3127 		for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples)
3128 		{
3129 			addCases<VerifyLocationTest>	 (groupLocation.get(),		*pLoopNumSamples, pipelineConstructionType, useFragmentShadingRate, addProgramsVerifyLocationGeometry);
3130 			addCases<VerifyInterpolationTest>(groupInterpolation.get(),	*pLoopNumSamples, pipelineConstructionType, useFragmentShadingRate, addProgramsVerifyInterpolation);
3131 		}
3132 
3133 		rootGroup->addChild(groupLocation.release());
3134 		rootGroup->addChild(groupInterpolation.release());
3135 	}
3136 
3137 	// Draw with custom samples and various options
3138 	{
3139 		using namespace Draw;
3140 
3141 		const deUint32 globalOption = useFragmentShadingRate ? static_cast<deUint32>(TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) : 0u;
3142 		const deUint32 optionSets[] =
3143 		{
3144 			globalOption | TEST_OPTION_SAME_PATTERN_BIT,
3145 			globalOption | 0u,
3146 			globalOption | TEST_OPTION_DYNAMIC_STATE_BIT,
3147 			globalOption | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT,
3148 			globalOption | TEST_OPTION_DYNAMIC_STATE_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT,
3149 			globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT,
3150 			globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_DYNAMIC_STATE_BIT,
3151 			globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT,
3152 			globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_DYNAMIC_STATE_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT,
3153 			globalOption | TEST_OPTION_WAIT_EVENTS_BIT,
3154 			globalOption | TEST_OPTION_WAIT_EVENTS_BIT | TEST_OPTION_GENERAL_LAYOUT_BIT,
3155 			globalOption | TEST_OPTION_WAIT_EVENTS_BIT | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT,
3156 		};
3157 
3158 		const struct
3159 		{
3160 			TestDrawIn	drawIn;
3161 			TestClears	clears;
3162 		} drawClearSets[] =
3163 		{
3164 			{ TEST_DRAW_IN_RENDER_PASSES,	TEST_CLEARS_NO_CLEAR				},
3165 			{ TEST_DRAW_IN_RENDER_PASSES,	TEST_CLEARS_LOAD_OP_CLEAR			},
3166 			{ TEST_DRAW_IN_RENDER_PASSES,	TEST_CLEARS_CMD_CLEAR_ATTACHMENTS	},
3167 			{ TEST_DRAW_IN_RENDER_PASSES,	TEST_CLEARS_CMD_CLEAR_IMAGE			},
3168 			{ TEST_DRAW_IN_SUBPASSES,		TEST_CLEARS_NO_CLEAR				},
3169 			{ TEST_DRAW_IN_SUBPASSES,		TEST_CLEARS_CMD_CLEAR_ATTACHMENTS	},
3170 			{ TEST_DRAW_IN_SAME_SUBPASS,	TEST_CLEARS_NO_CLEAR				},
3171 			{ TEST_DRAW_IN_SAME_SUBPASS,	TEST_CLEARS_CMD_CLEAR_ATTACHMENTS	},
3172 		};
3173 
3174 		const TestImageAspect aspectRange[] =
3175 		{
3176 			TEST_IMAGE_ASPECT_COLOR,
3177 			TEST_IMAGE_ASPECT_DEPTH,
3178 			TEST_IMAGE_ASPECT_STENCIL,
3179 		};
3180 
3181 		MovePtr<tcu::TestCaseGroup> drawGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "draw", ""));
3182 		for (const TestImageAspect* pLoopImageAspect = aspectRange; pLoopImageAspect != DE_ARRAY_END(aspectRange); ++pLoopImageAspect)
3183 		{
3184 			MovePtr<tcu::TestCaseGroup> aspectGroup (new tcu::TestCaseGroup(drawGroup->getTestContext(), getString(*pLoopImageAspect), ""));
3185 			for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples)
3186 			{
3187 				MovePtr<tcu::TestCaseGroup> samplesGroup (new tcu::TestCaseGroup(aspectGroup->getTestContext(), getString(*pLoopNumSamples).c_str(), ""));
3188 
3189 				for (deUint32		 loopDrawSetNdx = 0u;		  loopDrawSetNdx <  DE_LENGTH_OF_ARRAY(drawClearSets); ++loopDrawSetNdx)
3190 				for (const deUint32* pLoopOptions	= optionSets; pLoopOptions	 != DE_ARRAY_END(optionSets);		   ++pLoopOptions)
3191 				{
3192 					const TestParams params
3193 					{
3194 						pipelineConstructionType,					// PipelineConstructionType	pipelineConstructionType;
3195 						*pLoopNumSamples,							// VkSampleCountFlagBits	numSamples;
3196 						*pLoopOptions,								// TestOptionFlags			options;
3197 						drawClearSets[loopDrawSetNdx].drawIn,		// TestDrawIn				drawIn;
3198 						drawClearSets[loopDrawSetNdx].clears,		// TestClears				clears;
3199 						*pLoopImageAspect,							// TestImageAspect			imageAspect;
3200 					};
3201 
3202 					// Filter out incompatible parameter combinations
3203 					if (params.imageAspect != TEST_IMAGE_ASPECT_COLOR)
3204 					{
3205 						// If the sample pattern is changed, the D/S image must be cleared or the result is undefined
3206 						if (((params.options & TEST_OPTION_SAME_PATTERN_BIT) == 0u) && (params.clears == TEST_CLEARS_NO_CLEAR))
3207 							continue;
3208 					}
3209 
3210 					// We are using events to change image layout and this is only allowed outside a render pass
3211 					if (((params.options & TEST_OPTION_WAIT_EVENTS_BIT) != 0u) && (params.drawIn != TEST_DRAW_IN_RENDER_PASSES))
3212 						continue;
3213 
3214 					// Can't change image layout inside a subpass
3215 					if (((params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0u) && (params.drawIn == TEST_DRAW_IN_SAME_SUBPASS))
3216 						continue;
3217 
3218 					std::ostringstream caseName;
3219 					caseName << getString(params.drawIn) << "_"
3220 							 << getString(params.clears) << (params.options != 0 ? "_" : "")
3221 							 << getTestOptionFlagsString(params.options);
3222 
3223 					addInstanceTestCaseWithPrograms<DrawTest>(samplesGroup.get(), caseName.str().c_str(), "", checkSupportDrawTests, initPrograms, params);
3224 				}
3225 				aspectGroup->addChild(samplesGroup.release());
3226 			}
3227 			drawGroup->addChild(aspectGroup.release());
3228 		}
3229 		rootGroup->addChild(drawGroup.release());
3230 	}
3231 }
3232 
3233 } // anonymous ns
3234 
createMultisampleSampleLocationsExtTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)3235 tcu::TestCaseGroup* createMultisampleSampleLocationsExtTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate)
3236 {
3237 	return createTestGroup(testCtx, "sample_locations_ext", "Test a graphics pipeline with user-defined sample locations", createTestsInGroup, pipelineConstructionType, useFragmentShadingRate);
3238 }
3239 
3240 } // pipeline
3241 } // vkt
3242