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