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