• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2020 The Khronos Group Inc.
6  * Copyright (c) 2020 AMD
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_KHR_fragment_shading_rate
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentShadingRatePixelConsistency.hpp"
26 
27 #include "vkBufferWithMemory.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkPlatform.hpp"
37 
38 #include "vktTestGroupUtil.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktCustomInstancesDevices.hpp"
41 
42 #include "deDefs.h"
43 #include "deMath.h"
44 #include "deRandom.h"
45 #include "deSharedPtr.hpp"
46 #include "deString.h"
47 
48 #include "tcuTestCase.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuCommandLine.hpp"
51 
52 #include <limits>
53 #include <string>
54 #include <sstream>
55 
56 namespace vkt
57 {
58 namespace FragmentShadingRate
59 {
60 namespace
61 {
62 using namespace vk;
63 using namespace std;
64 
65 struct CaseDef
66 {
67 	VkExtent2D				shadingRate;
68 	VkSampleCountFlagBits	samples;
69 	VkExtent2D				framebufferExtent;
70 	bool					zwCoord;
71 };
72 
73 struct Vertex
74 {
75 	float x;
76 	float y;
77 };
78 
79 Vertex basicTriangles[6] =
80 {
81 	{-1.0f, -1.0f},
82 	{ 1.0f, -1.0f},
83 	{ 1.0f,  1.0f},
84 
85 	{-1.0f,  1.0f},
86 	{ 1.0f, -1.0f},
87 	{ 1.0f,  1.0f},
88 };
89 
createImageRobustnessDevice(Context & context)90 Move<VkDevice> createImageRobustnessDevice(Context& context)
91 {
92 	const InstanceInterface&	instance		= context.getInstanceInterface();
93 	const vk::VkPhysicalDevice	physicalDevice	= context.getPhysicalDevice();
94 	const float					queuePriority	= 1.0f;
95 
96 	// Create a universal queue
97 	const VkDeviceQueueCreateInfo queueParams =
98 	{
99 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
100 		DE_NULL,									// const void*					pNext;
101 		0u,											// VkDeviceQueueCreateFlags		flags;
102 		context.getUniversalQueueFamilyIndex(),		// deUint32						queueFamilyIndex;
103 		1u,											// deUint32						queueCount;
104 		&queuePriority								// const float*					pQueuePriorities;
105 	};
106 
107 	// Add image robustness extension if supported
108 	std::vector<const char*> deviceExtensions;
109 
110 	deviceExtensions.push_back("VK_KHR_fragment_shading_rate");
111 
112 	if (context.isDeviceFunctionalitySupported("VK_EXT_image_robustness"))
113 	{
114 		deviceExtensions.push_back("VK_EXT_image_robustness");
115 	}
116 
117 	VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsrFeatures =
118 	{
119 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR,	// VkStructureType	sType;
120 		DE_NULL,																// void*			pNext;
121 		DE_FALSE,																// VkBool32			pipelineFragmentShadingRate;
122 		DE_FALSE,																// VkBool32			primitiveFragmentShadingRate;
123 		DE_FALSE,																// VkBool32			attachmentFragmentShadingRate;
124 	};
125 
126 	VkPhysicalDeviceFeatures2 enabledFeatures;
127 	enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
128 	enabledFeatures.pNext = &fsrFeatures;
129 
130 	instance.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures);
131 
132 	const VkDeviceCreateInfo deviceParams =
133 	{
134 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,						// VkStructureType					sType;
135 		&enabledFeatures,											// const void*						pNext;
136 		0u,															// VkDeviceCreateFlags				flags;
137 		1u,															// deUint32							queueCreateInfoCount;
138 		&queueParams,												// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
139 		0u,															// deUint32							enabledLayerCount;
140 		DE_NULL,													// const char* const*				ppEnabledLayerNames;
141 		static_cast<deUint32>(deviceExtensions.size()),				// deUint32							enabledExtensionCount;
142 		deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],	// const char* const*				ppEnabledExtensionNames;
143 		DE_NULL,													// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
144 	};
145 
146 	return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
147 							  context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceParams);
148 }
149 
150 class FSRPixelConsistencyInstance : public TestInstance
151 {
152 public:
153 						FSRPixelConsistencyInstance	(Context& context, const CaseDef& data);
154 						~FSRPixelConsistencyInstance(void);
155 	tcu::TestStatus		iterate						(void);
156 
157 private:
158 	void				clampShadingRate();
159 	tcu::TestStatus		verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index);
160 
161 	CaseDef											m_data;
162 	vector<VkExtent2D>								m_shadingRateClamped;
163 
164 	deUint32										m_supportedFragmentShadingRateCount;
165 	vector<VkPhysicalDeviceFragmentShadingRateKHR>	m_supportedFragmentShadingRates;
166 };
167 
FSRPixelConsistencyInstance(Context & context,const CaseDef & data)168 FSRPixelConsistencyInstance::FSRPixelConsistencyInstance(Context& context, const CaseDef& data)
169 	: vkt::TestInstance		(context)
170 	, m_data(data)
171 	, m_supportedFragmentShadingRateCount(0)
172 {
173 	// Fetch information about supported fragment shading rates
174 	context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL);
175 
176 	m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
177 	for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
178 	{
179 		m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
180 		m_supportedFragmentShadingRates[i].pNext = nullptr;
181 	}
182 	context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
183 
184 	clampShadingRate();
185 }
186 
~FSRPixelConsistencyInstance(void)187 FSRPixelConsistencyInstance::~FSRPixelConsistencyInstance(void)
188 {
189 }
190 
191 class FSRPixelConsistencyTestCase : public TestCase
192 {
193 	public:
194 								FSRPixelConsistencyTestCase		(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
195 								~FSRPixelConsistencyTestCase	(void);
196 	virtual	void				initPrograms					(SourceCollections& programCollection) const;
197 	virtual TestInstance*		createInstance					(Context& context) const;
198 	virtual void				checkSupport					(Context& context) const;
199 
200 private:
201 
202 	CaseDef											m_data;
203 };
204 
FSRPixelConsistencyTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)205 FSRPixelConsistencyTestCase::FSRPixelConsistencyTestCase(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
206 	: vkt::TestCase	(context, name, desc)
207 	, m_data		(data)
208 {
209 }
210 
~FSRPixelConsistencyTestCase(void)211 FSRPixelConsistencyTestCase::~FSRPixelConsistencyTestCase(void)
212 {
213 }
214 
checkSupport(Context & context) const215 void FSRPixelConsistencyTestCase::checkSupport(Context& context) const
216 {
217 	const VkImageUsageFlags cbUsage =	VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
218 										VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
219 										VK_IMAGE_USAGE_TRANSFER_SRC_BIT		|
220 										VK_IMAGE_USAGE_TRANSFER_DST_BIT;
221 
222 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
223 
224 	if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
225 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
226 
227 	VkImageFormatProperties imageProperties;
228 	VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), VK_FORMAT_R32G32_UINT, VK_IMAGE_TYPE_2D,
229 																							VK_IMAGE_TILING_OPTIMAL, cbUsage , 0, &imageProperties);
230 
231 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
232 		TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32_UINT not supported");
233 
234 	if (!(imageProperties.sampleCounts & m_data.samples))
235 		TCU_THROW(NotSupportedError, "Image sample count not supported");
236 
237 	if ((imageProperties.maxExtent.width < m_data.framebufferExtent.width) || (imageProperties.maxExtent.height < m_data.framebufferExtent.height))
238 		TCU_THROW(NotSupportedError, "Image max extents are smaller than required");
239 }
240 
initPrograms(SourceCollections & programCollection) const241 void FSRPixelConsistencyTestCase::initPrograms (SourceCollections& programCollection) const
242 {
243 	std::stringstream vss;
244 
245 	vss <<
246 		"#version 450 core\n"
247 		"layout(location = 0) in vec2 position;\n"
248 		"out gl_PerVertex\n"
249 		"{\n"
250 		"   vec4 gl_Position;\n"
251 		"};\n"
252 		"void main()\n"
253 		"{\n";
254 	if (!m_data.zwCoord)
255 	{
256 		vss <<
257 			"  gl_Position = vec4(position, 0, 1);\n";
258 	}
259 	else
260 	{
261 		vss <<
262 			"  gl_Position = vec4(position, position);\n";
263 	}
264 	vss <<
265 		"}\n";
266 
267 	programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
268 
269 	std::stringstream fssPass0;
270 
271 	fssPass0 <<
272 		"#version 450 core\n"
273 		"layout(push_constant) uniform PC {\n"
274 		"	uvec2 shadingRate[2];\n"
275 		"} pc;\n"
276 		"layout(location = 0) out uvec2 col0;\n"
277 		"void main()\n"
278 		"{\n";
279 	if (!m_data.zwCoord)
280 	{
281 		fssPass0 <<
282 			"  col0.x = (uint(gl_FragCoord.x) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n"
283 			"  col0.y = (uint(gl_FragCoord.x) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n";
284 	}
285 	else
286 	{
287 		fssPass0 <<
288 			"  col0.x = (uint(gl_FragCoord.z) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n"
289 			"  col0.y = (uint(gl_FragCoord.z) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n";
290 	}
291 	fssPass0 <<
292 		"}\n";
293 
294 	programCollection.glslSources.add("frag_pass0") << glu::FragmentSource(fssPass0.str());
295 
296 	std::stringstream fssPass1;
297 
298 	fssPass1 <<
299 		"#version 450 core\n";
300 
301 	if (m_data.samples == VK_SAMPLE_COUNT_1_BIT)
302 	{
303 		fssPass1 <<
304 			"layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInput inputAttachment;\n";
305 	}
306 	else
307 	{
308 		fssPass1 <<
309 			"layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInputMS inputAttachment;\n";
310 	}
311 
312 	fssPass1 <<
313 		"layout(location = 0) out uvec2 col0;\n"
314 		"void main()\n"
315 		"{\n";
316 
317 	if (m_data.samples == VK_SAMPLE_COUNT_1_BIT)
318 	{
319 		fssPass1 <<
320 			"  col0 = subpassLoad(inputAttachment).xy;\n";
321 	}
322 	else
323 	{
324 		fssPass1 <<
325 			"  col0 = subpassLoad(inputAttachment, 0).xy;\n";
326 	}
327 
328 	fssPass1 <<
329 		"}\n";
330 
331 	programCollection.glslSources.add("frag_pass1") << glu::FragmentSource(fssPass1.str());
332 }
333 
createInstance(Context & context) const334 TestInstance* FSRPixelConsistencyTestCase::createInstance (Context& context) const
335 {
336 	return new FSRPixelConsistencyInstance(context, m_data);
337 }
338 
compareShadingRate(VkExtent2D ext1,VkExtent2D ext2)339 bool compareShadingRate(VkExtent2D ext1, VkExtent2D ext2)
340 {
341 	deUint32 ratio1 = std::max(ext1.width, ext1.height) / std::min(ext1.width, ext1.height);
342 	deUint32 ratio2 = std::max(ext2.width, ext2.height) / std::min(ext2.width, ext2.height);
343 
344 	return ratio1 < ratio2;
345 }
346 
clampShadingRate()347 void FSRPixelConsistencyInstance::clampShadingRate()
348 {
349 	deUint32 desiredSize = m_data.shadingRate.width * m_data.shadingRate.height;
350 
351 	while (desiredSize > 0)
352 	{
353 		// Find modes that maximize the area
354 		for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
355 		{
356 			const VkPhysicalDeviceFragmentShadingRateKHR& supportedRate = m_supportedFragmentShadingRates[i];
357 
358 			if (supportedRate.sampleCounts & VK_SAMPLE_COUNT_1_BIT)
359 			{
360 				// We found exact match
361 				if (supportedRate.fragmentSize.width  == m_data.shadingRate.width	&&
362 					supportedRate.fragmentSize.height == m_data.shadingRate.height)
363 				{
364 					m_shadingRateClamped.push_back(supportedRate.fragmentSize);
365 
366 					return;
367 				}
368 				else
369 				{
370 					if (supportedRate.fragmentSize.width  <= m_data.shadingRate.width  &&
371 						supportedRate.fragmentSize.height <= m_data.shadingRate.height &&
372 						supportedRate.fragmentSize.width  *  supportedRate.fragmentSize.height == desiredSize)
373 					{
374 						m_shadingRateClamped.push_back(supportedRate.fragmentSize);
375 					}
376 				}
377 			}
378 		}
379 		if (!m_shadingRateClamped.empty())
380 		{
381 			// Sort the modes so that the ones with the smallest aspect ratio are in front
382 			std::sort(m_shadingRateClamped.begin(), m_shadingRateClamped.end(), compareShadingRate);
383 
384 			deUint32 desiredRatio = std::max(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height) /
385 									std::min(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height);
386 
387 			// Leave only entries with the smallest aspect ratio
388 			auto it = m_shadingRateClamped.begin();
389 			while (it != m_shadingRateClamped.end())
390 			{
391 				deUint32 ratio = std::max(it->width, it->height) / std::min(it->width, it->height);
392 
393 				if (ratio < desiredRatio)
394 				{
395 					it = m_shadingRateClamped.erase(it, m_shadingRateClamped.end());
396 				}
397 				else
398 				{
399 					++it;
400 				}
401 			}
402 
403 			return;
404 		}
405 		else
406 		{
407 			desiredSize /= 2;
408 		}
409 	}
410 	DE_ASSERT(0);
411 
412 	return;
413 }
414 
verifyResult(tcu::ConstPixelBufferAccess & resultBuffer,const deUint32 index)415 tcu::TestStatus	FSRPixelConsistencyInstance::verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index)
416 {
417 	deUint32 pixelIndex			= std::numeric_limits<unsigned int>::max();
418 	deUint32 pixelOutsideIndex	= std::numeric_limits<unsigned int>::max();
419 
420 	for (int y = 0; y < resultBuffer.getHeight(); y++)
421 	{
422 		for (int x = 0; x < resultBuffer.getWidth(); x++)
423 		{
424 			deUint32 pixel = resultBuffer.getPixelUint(x, y)[index];
425 
426 			// If pixel was not covered by any triangle, we skip it
427 			if (pixel == std::numeric_limits<unsigned int>::max())
428 			{
429 				continue;
430 			}
431 
432 			// We check if pixel is part of fragment area that is partially outside of framebuffer area
433 			deBool outsideW = (x / m_shadingRateClamped[index].width  + 1) * m_shadingRateClamped[index].width  > static_cast<deUint32>(resultBuffer.getWidth());
434 			deBool outsideH = (y / m_shadingRateClamped[index].height + 1) * m_shadingRateClamped[index].height > static_cast<deUint32>(resultBuffer.getHeight());
435 
436 			if (outsideW || outsideH)
437 			{
438 				// If image robustness is enabled such pixel can have either a value of 0 or one of the values from the area inside framebuffer
439 				if (m_context.isDeviceFunctionalitySupported("VK_EXT_image_robustness"))
440 				{
441 					if (pixelOutsideIndex == std::numeric_limits<unsigned int>::max() || pixelOutsideIndex == 0)
442 					{
443 						pixelOutsideIndex = pixel;
444 					}
445 					// If value is non-zero we make sure that all 'corner' pixels have the same value
446 					else if ((pixel != 0) && (pixelOutsideIndex != pixel))
447 					{
448 						return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
449 					}
450 				}
451 				// If image robustness is not enabled such pixel can have an undefined value, so we skip it
452 				else
453 				{
454 					continue;
455 				}
456 			}
457 			else
458 			{
459 				if (pixelIndex == std::numeric_limits<unsigned int>::max())
460 				{
461 					if (pixel >= m_shadingRateClamped[index].width * m_shadingRateClamped[index].height)
462 					{
463 						return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
464 					}
465 
466 					pixelIndex = pixel;
467 				}
468 				// If pixel is not part of 'corner' pixels we make sure that is has the same value as other non-'corner' pixels
469 				else if (pixelIndex != pixel)
470 				{
471 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
472 				}
473 			}
474 		}
475 	}
476 
477 	return tcu::TestStatus(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
478 }
479 
iterate(void)480 tcu::TestStatus FSRPixelConsistencyInstance::iterate (void)
481 {
482 	const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
483 
484 	Move<VkDevice>				vkd			 = createImageRobustnessDevice(m_context);
485 	const VkDevice				device		 = *vkd;
486 	de::MovePtr<DeviceDriver>	deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), device));
487 	const DeviceInterface&		vk			 = *deviceDriver.get();
488 	const VkQueue				queue		 = getDeviceQueue(vk, device, m_context.getUniversalQueueFamilyIndex(), 0);
489 	de::MovePtr<Allocator>		allocator	 = de::MovePtr<Allocator>(new SimpleAllocator(vk, device, memoryProperties));
490 
491 	// Create vertex buffer
492 	const VkDeviceSize vertexBufferSize = sizeof(basicTriangles);
493 
494 	const VkFormat imageFormat = VK_FORMAT_R32G32_UINT;
495 
496 	de::MovePtr<BufferWithMemory> vertexBuffer;
497 	vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
498 		vk, device, *allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
499 
500 	float* vbuf = (float*)vertexBuffer->getAllocation().getHostPtr();
501 
502 	deMemcpy(vbuf, basicTriangles, vertexBufferSize);
503 
504 	flushAlloc(vk, device, vertexBuffer->getAllocation());
505 
506 	// Create color output buffer
507 	const VkDeviceSize colorOutputBufferSize = m_data.framebufferExtent.width * m_data.framebufferExtent.height * tcu::getPixelSize(mapVkFormat(imageFormat));
508 
509 	de::MovePtr<BufferWithMemory> colorOutputBuffer;
510 	colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
511 		vk, device, *allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
512 
513 
514 	// Create color attachment for subpass 0
515 	de::MovePtr<ImageWithMemory> cbImagePass0;
516 	Move<VkImageView>			 cbImagePass0View;
517 	{
518 		const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
519 										  VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
520 										  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
521 
522 		const VkImageCreateInfo			imageCreateInfo =
523 		{
524 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
525 			DE_NULL,								// const void*				pNext;
526 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
527 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
528 			imageFormat,							// VkFormat					format;
529 			{
530 				m_data.framebufferExtent.width,		// deUint32	width;
531 				m_data.framebufferExtent.height,	// deUint32	height;
532 				1u									// deUint32	depth;
533 			},										// VkExtent3D				extent;
534 			1u,										// deUint32					mipLevels;
535 			1u,										// deUint32					arrayLayers;
536 			m_data.samples,							// VkSampleCountFlagBits	samples;
537 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
538 			cbUsage,								// VkImageUsageFlags		usage;
539 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
540 			0u,										// deUint32					queueFamilyIndexCount;
541 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
542 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
543 		};
544 		cbImagePass0 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
545 			vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
546 
547 		VkImageViewCreateInfo		imageViewCreateInfo =
548 		{
549 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
550 			DE_NULL,									// const void*				pNext;
551 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
552 			**cbImagePass0,								// VkImage					image;
553 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
554 			imageFormat,								// VkFormat					format;
555 			{
556 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
557 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
558 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
559 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
560 			},											// VkComponentMapping		 components;
561 			{
562 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
563 				0u,										// deUint32				baseMipLevel;
564 				1u,										// deUint32				levelCount;
565 				0u,										// deUint32				baseArrayLayer;
566 				1u										// deUint32				layerCount;
567 			}											// VkImageSubresourceRange	subresourceRange;
568 		};
569 		cbImagePass0View = createImageView(vk, device, &imageViewCreateInfo, NULL);
570 	}
571 
572 	// Create color attachment for subpass 1
573 	de::MovePtr<ImageWithMemory> cbImagePass1;
574 	Move<VkImageView>			 cbImagePass1View;
575 	{
576 		const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
577 										  VK_IMAGE_USAGE_TRANSFER_SRC_BIT	  |
578 										  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
579 
580 		const VkImageCreateInfo			imageCreateInfo =
581 		{
582 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
583 			DE_NULL,								// const void*				pNext;
584 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
585 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
586 			imageFormat,							// VkFormat					format;
587 			{
588 				m_data.framebufferExtent.width,		// deUint32	width;
589 				m_data.framebufferExtent.height,	// deUint32	height;
590 				1u									// deUint32	depth;
591 			},										// VkExtent3D				extent;
592 			1u,										// deUint32					mipLevels;
593 			1u,										// deUint32					arrayLayers;
594 			VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
595 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
596 			cbUsage,								// VkImageUsageFlags		usage;
597 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
598 			0u,										// deUint32					queueFamilyIndexCount;
599 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
600 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
601 		};
602 		cbImagePass1 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
603 			vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
604 
605 		VkImageViewCreateInfo		imageViewCreateInfo =
606 		{
607 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
608 			DE_NULL,									// const void*				pNext;
609 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
610 			**cbImagePass1,								// VkImage					image;
611 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
612 			imageFormat,								// VkFormat					format;
613 			{
614 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
615 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
616 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
617 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
618 			},											// VkComponentMapping		 components;
619 			{
620 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
621 				0u,										// deUint32				baseMipLevel;
622 				1u,										// deUint32				levelCount;
623 				0u,										// deUint32				baseArrayLayer;
624 				1u										// deUint32				layerCount;
625 			}											// VkImageSubresourceRange	subresourceRange;
626 		};
627 		cbImagePass1View = createImageView(vk, device, &imageViewCreateInfo, NULL);
628 	}
629 
630 	// Create render pass
631 	Move<VkRenderPass>	renderPass;
632 	{
633 		const vk::VkAttachmentReference colorAttachment0Reference =
634 		{
635 			0,															// attachment
636 			vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
637 		};
638 
639 		const vk::VkAttachmentReference colorAttachment1Reference =
640 		{
641 			1,															// attachment
642 			vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
643 		};
644 
645 		std::vector<VkAttachmentDescription> attachmentDescriptions;
646 
647 		attachmentDescriptions.push_back(
648 			{
649 				(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
650 				imageFormat,								// VkFormat							format;
651 				m_data.samples,								// VkSampleCountFlagBits			samples;
652 				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
653 				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
654 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
655 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
656 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
657 				VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
658 			}
659 		);
660 
661 		attachmentDescriptions.push_back(
662 			{
663 				(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
664 				imageFormat,								// VkFormat							format;
665 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
666 				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
667 				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
668 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
669 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
670 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
671 				VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
672 			}
673 		);
674 
675 		const VkSubpassDescription subpassDescs[] =
676 		{
677 			{
678 				(vk::VkSubpassDescriptionFlags)0,						// flags
679 				vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
680 				0u,														// inputCount
681 				DE_NULL,												// pInputAttachments
682 				1u,														// colorCount
683 				&colorAttachment0Reference,								// pColorAttachments
684 				DE_NULL,												// pResolveAttachments
685 				DE_NULL,												// depthStencilAttachment
686 				0u,														// preserveCount
687 				DE_NULL,												// pPreserveAttachments
688 			},
689 			{
690 				(vk::VkSubpassDescriptionFlags)0,						// flags
691 				vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
692 				1u,														// inputCount
693 				&colorAttachment0Reference,								// pInputAttachments
694 				1u,														// colorCount
695 				&colorAttachment1Reference,								// pColorAttachments
696 				DE_NULL,												// pResolveAttachments
697 				DE_NULL,												// depthStencilAttachment
698 				0u,														// preserveCount
699 				DE_NULL,												// pPreserveAttachments
700 			},
701 		};
702 
703 		const VkSubpassDependency subpassDependency =
704 		{
705 			0u,												// srcSubpass;
706 			1u,												// dstSubpass;
707 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// srcStageMask;
708 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// dstStageMask;
709 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask;
710 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// dstAccessMask;
711 			0												// dependencyFlags;
712 		};
713 
714 		const VkRenderPassCreateInfo renderPassParams =
715 		{
716 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// sType
717 			DE_NULL,												// pNext
718 			(vk::VkRenderPassCreateFlags)0,
719 			(deUint32)attachmentDescriptions.size(),				// attachmentCount
720 			&attachmentDescriptions[0],								// pAttachments
721 			sizeof(subpassDescs) / sizeof(subpassDescs[0]),			// subpassCount
722 			subpassDescs,											// pSubpasses
723 			1u,														// dependencyCount
724 			&subpassDependency,										// pDependencies
725 		};
726 
727 		renderPass = createRenderPass(vk, device, &renderPassParams);
728 	}
729 
730 	// Create framebuffer
731 	Move<VkFramebuffer> framebuffer;
732 	{
733 		std::vector<VkImageView> attachments;
734 		attachments.push_back(*cbImagePass0View);
735 		attachments.push_back(*cbImagePass1View);
736 
737 		const vk::VkFramebufferCreateInfo framebufferParams =
738 		{
739 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
740 			DE_NULL,										// pNext
741 			(vk::VkFramebufferCreateFlags)(0),				// createFlags
742 			*renderPass,									// renderPass
743 			(deUint32)attachments.size(),					// attachmentCount
744 			&attachments[0],								// pAttachments
745 			m_data.framebufferExtent.width,					// width
746 			m_data.framebufferExtent.height,				// height
747 			1u,												// layers
748 		};
749 
750 		framebuffer = createFramebuffer(vk, device, &framebufferParams);
751 	}
752 
753 
754 	// Create vertex attribute
755 	const VkVertexInputBindingDescription vertexBinding =
756 	{
757 		0u,							// deUint32				binding;
758 		sizeof(Vertex),				// deUint32				stride;
759 		VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
760 	};
761 
762 	const VkVertexInputAttributeDescription	vertexInputAttributeDescription =
763 	{
764 		0u,							// deUint32	location;
765 		0u,							// deUint32	binding;
766 		VK_FORMAT_R32G32_SFLOAT,	// VkFormat	format;
767 		0u							// deUint32	offset;
768 	};
769 
770 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo =
771 	{
772 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
773 		DE_NULL,													// const void*								pNext;
774 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
775 		1u,															// deUint32									vertexBindingDescriptionCount;
776 		&vertexBinding,												// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
777 		1u,															// deUint32									vertexAttributeDescriptionCount;
778 		&vertexInputAttributeDescription							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
779 	};
780 
781 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
782 	{
783 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
784 		DE_NULL,														// const void*								pNext;
785 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
786 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
787 		VK_FALSE														// VkBool32									primitiveRestartEnable;
788 	};
789 
790 	// Create rasterization state
791 	const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
792 	{
793 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
794 		DE_NULL,														// const void*								pNext;
795 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
796 		VK_FALSE,														// VkBool32									depthClampEnable;
797 		VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
798 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
799 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
800 		VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
801 		VK_FALSE,														// VkBool32									depthBiasEnable;
802 		0.0f,															// float									depthBiasConstantFactor;
803 		0.0f,															// float									depthBiasClamp;
804 		0.0f,															// float									depthBiasSlopeFactor;
805 		1.0f															// float									lineWidth;
806 	};
807 
808 	// Create scissor and viewport
809 	VkViewport	viewport	= makeViewport(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
810 	VkRect2D	scissor		= makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
811 
812 	const VkPipelineViewportStateCreateInfo	viewportStateCreateInfo =
813 	{
814 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType							sType
815 		DE_NULL,													// const void*								pNext
816 		(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags		flags
817 		1u,															// deUint32									viewportCount
818 		&viewport,													// const VkViewport*						pViewports
819 		1u,															// deUint32									scissorCount
820 		&scissor													// const VkRect2D*							pScissors
821 	};
822 
823 	const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
824 	{
825 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType					  sType;
826 		DE_NULL,													// const void*						  pNext;
827 		(VkPipelineDynamicStateCreateFlags)0,						// VkPipelineDynamicStateCreateFlags	flags;
828 		0u,															// uint32_t							 dynamicStateCount;
829 		DE_NULL,													// const VkDynamicState*				pDynamicStates;
830 	};
831 
832 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState[] =
833 	{
834 		{
835 			VK_FALSE,				// VkBool32					blendEnable;
836 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcColorBlendFactor;
837 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
838 			VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
839 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcAlphaBlendFactor;
840 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
841 			VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
842 			0xf						// VkColorComponentFlags	colorWriteMask;
843 		}
844 	};
845 
846 	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo =
847 	{
848 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,					// VkStructureType								sType;
849 		DE_NULL,																	// const void*									pNext;
850 		0u,																			// VkPipelineColorBlendStateCreateFlags			flags;
851 		VK_FALSE,																	// VkBool32										logicOpEnable;
852 		VK_LOGIC_OP_COPY,															// VkLogicOp									logicOp;
853 		sizeof(colorBlendAttachmentState) / sizeof(colorBlendAttachmentState[0]),	// deUint32										attachmentCount;
854 		colorBlendAttachmentState,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
855 		{ 1.0f, 1.0f, 1.0f, 1.0f }													// float										blendConstants[4];
856 	};
857 
858 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateParams =
859 	{
860 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
861 		DE_NULL,													// const void*								pNext;
862 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
863 		VK_FALSE,													// VkBool32									depthTestEnable;
864 		VK_FALSE,													// VkBool32									depthWriteEnable;
865 		VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
866 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
867 		VK_FALSE,													// VkBool32									stencilTestEnable;
868 		// VkStencilOpState	front;
869 		{
870 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
871 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
872 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
873 			VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
874 			0u,						// deUint32		compareMask;
875 			0xFFu,					// deUint32		writeMask;
876 			0xFFu,					// deUint32		reference;
877 		},
878 		// VkStencilOpState	back;
879 		{
880 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
881 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
882 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
883 			VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
884 			0u,						// deUint32		compareMask;
885 			0xFFu,					// deUint32		writeMask;
886 			0xFFu,					// deUint32		reference;
887 		},
888 		0.0f,						// float			minDepthBounds;
889 		0.0f,						// float			maxDepthBounds;
890 	};
891 
892 	// Create pipeline for pass 0
893 	Move<VkPipeline> pipelinePass0;
894 	Move<VkPipelineLayout> pipelineLayoutPass0;
895 	{
896 		const VkPushConstantRange		pushConstantRange =
897 		{
898 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
899 			0u,															// deUint32								offset;
900 			2 * sizeof(VkExtent2D)										// deUint32								size;
901 		};
902 
903 		const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
904 		{
905 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
906 			DE_NULL,													// pNext
907 			(VkPipelineLayoutCreateFlags)0,
908 			0u,															// setLayoutCount
909 			DE_NULL,													// pSetLayouts
910 			1u,															// pushConstantRangeCount
911 			&pushConstantRange,											// pPushConstantRanges
912 		};
913 
914 		pipelineLayoutPass0 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
915 
916 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo =
917 		{
918 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
919 			DE_NULL,													// const void*					pNext
920 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
921 			(VkSampleCountFlagBits)m_data.samples,						// VkSampleCountFlagBits					rasterizationSamples
922 			VK_FALSE,													// VkBool32									sampleShadingEnable
923 			1.0f,														// float									minSampleShading
924 			DE_NULL,													// const VkSampleMask*						pSampleMask
925 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
926 			VK_FALSE													// VkBool32									alphaToOneEnable
927 		};
928 
929 		Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
930 		Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass0"), 0);
931 
932 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo[] =
933 		{
934 			{
935 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
936 				DE_NULL,
937 				(VkPipelineShaderStageCreateFlags)0,
938 				VK_SHADER_STAGE_VERTEX_BIT,									// stage
939 				*vertShader,												// shader
940 				"main",
941 				DE_NULL,													// pSpecializationInfo
942 			},
943 			{
944 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
945 				DE_NULL,
946 				(VkPipelineShaderStageCreateFlags)0,
947 				VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
948 				*fragShader,												// shader
949 				"main",
950 				DE_NULL,													// pSpecializationInfo
951 			}
952 		};
953 
954 		const VkGraphicsPipelineCreateInfo	graphicsPipelineCreateInfo =
955 		{
956 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// VkStructureType									sType;
957 			DE_NULL,												// const void*										pNext;
958 			(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags							flags;
959 			sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]),	// deUint32											stageCount;
960 			&shaderCreateInfo[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
961 			&vertexInputStateCreateInfo,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
962 			&inputAssemblyStateCreateInfo,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
963 			DE_NULL,												// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
964 			&viewportStateCreateInfo,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
965 			&rasterizationStateCreateInfo,							// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
966 			&multisampleStateCreateInfo,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
967 			&depthStencilStateParams,								// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
968 			&colorBlendStateCreateInfo,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
969 			&dynamicStateCreateInfo,								// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
970 			pipelineLayoutPass0.get(),								// VkPipelineLayout									layout;
971 			renderPass.get(),										// VkRenderPass										renderPass;
972 			0u,														// deUint32											subpass;
973 			DE_NULL,												// VkPipeline										basePipelineHandle;
974 			0														// int												basePipelineIndex;
975 		};
976 
977 		pipelinePass0 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
978 	}
979 
980 
981 	// Create pipeline for pass 1
982 	Move<VkPipeline>				pipelinePass1;
983 	Move<VkPipelineLayout>			pipelineLayoutPass1;
984 	Move<vk::VkDescriptorPool>		descriptorPool;
985 	Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
986 	Move<vk::VkDescriptorSet>		descriptorSet;
987 	{
988 		const VkDescriptorSetLayoutBinding bindings[] =
989 		{
990 			{
991 				0u,										// binding
992 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// descriptorType
993 				1u,										// descriptorCount
994 				VK_SHADER_STAGE_FRAGMENT_BIT,			// stageFlags
995 				DE_NULL,								// pImmutableSamplers
996 			}
997 		};
998 
999 		// Create a layout and allocate a descriptor set for it.
1000 		const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1001 		{
1002 			vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
1003 			DE_NULL,													// pNext
1004 			(VkDescriptorSetLayoutCreateFlags)(0),						// flags
1005 			sizeof(bindings) / sizeof(bindings[0]),						// bindingCount
1006 			&bindings[0]												// pBindings
1007 		};
1008 
1009 		descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1010 
1011 		vk::DescriptorPoolBuilder poolBuilder;
1012 
1013 		for (deInt32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1014 		{
1015 			poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1016 		}
1017 
1018 		descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1019 		descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1020 
1021 		VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImagePass0View, VK_IMAGE_LAYOUT_GENERAL);
1022 
1023 		VkWriteDescriptorSet writeDescriptorSet =
1024 		{
1025 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1026 			DE_NULL,														// pNext
1027 			*descriptorSet,													// dstSet
1028 			0u,																// dstBinding
1029 			0u,																// dstArrayElement
1030 			1u,																// descriptorCount
1031 			bindings[0].descriptorType,										// descriptorType
1032 			&imageInfo,														// pImageInfo
1033 			DE_NULL,														// pBufferInfo
1034 			DE_NULL,														// pTexelBufferView
1035 		};
1036 
1037 		vk.updateDescriptorSets(device, 1, &writeDescriptorSet, 0, NULL);
1038 
1039 		const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1040 		{
1041 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
1042 			DE_NULL,													// pNext
1043 			(VkPipelineLayoutCreateFlags)0,
1044 			1u,															// setLayoutCount
1045 			&descriptorSetLayout.get(),									// pSetLayouts
1046 			0u,															// pushConstantRangeCount
1047 			DE_NULL,													// pPushConstantRanges
1048 		};
1049 
1050 		pipelineLayoutPass1 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1051 
1052 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo =
1053 		{
1054 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1055 			DE_NULL,													// const void*								pNext
1056 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
1057 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
1058 			VK_FALSE,													// VkBool32									sampleShadingEnable
1059 			1.0f,														// float									minSampleShading
1060 			DE_NULL,													// const VkSampleMask*						pSampleMask
1061 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
1062 			VK_FALSE													// VkBool32									alphaToOneEnable
1063 		};
1064 
1065 		VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo =
1066 		{
1067 			VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,								// VkStructureType						sType;
1068 			DE_NULL,																							// const void*							pNext;
1069 			m_data.shadingRate,																					// VkExtent2D							fragmentSize;
1070 			{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR },	// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
1071 		};
1072 
1073 		Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1074 		Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass1"), 0);
1075 
1076 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo[] =
1077 		{
1078 			{
1079 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1080 				DE_NULL,
1081 				(VkPipelineShaderStageCreateFlags)0,
1082 				VK_SHADER_STAGE_VERTEX_BIT,									// stage
1083 				*vertShader,												// shader
1084 				"main",
1085 				DE_NULL,													// pSpecializationInfo
1086 			},
1087 			{
1088 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1089 				DE_NULL,
1090 				(VkPipelineShaderStageCreateFlags)0,
1091 				VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
1092 				*fragShader,												// shader
1093 				"main",
1094 				DE_NULL,													// pSpecializationInfo
1095 			}
1096 		};
1097 
1098 		const VkGraphicsPipelineCreateInfo	graphicsPipelineCreateInfo =
1099 		{
1100 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// VkStructureType									sType;
1101 			&shadingRateStateCreateInfo,							// const void*										pNext;
1102 			(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags							flags;
1103 			sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]),	// deUint32											stageCount;
1104 			&shaderCreateInfo[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
1105 			&vertexInputStateCreateInfo,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1106 			&inputAssemblyStateCreateInfo,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1107 			DE_NULL,												// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1108 			&viewportStateCreateInfo,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1109 			&rasterizationStateCreateInfo,							// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
1110 			&multisampleStateCreateInfo,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1111 			&depthStencilStateParams,								// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1112 			&colorBlendStateCreateInfo,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1113 			&dynamicStateCreateInfo,								// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1114 			pipelineLayoutPass1.get(),								// VkPipelineLayout									layout;
1115 			renderPass.get(),										// VkRenderPass										renderPass;
1116 			1u,														// deUint32											subpass;
1117 			DE_NULL,												// VkPipeline										basePipelineHandle;
1118 			0														// int												basePipelineIndex;
1119 		};
1120 
1121 		pipelinePass1 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
1122 	}
1123 
1124 	// Create command buffer
1125 	Move<VkCommandPool>		cmdPool		= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
1126 	Move<VkCommandBuffer>	cmdBuffer	= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1127 
1128 	VkImageMemoryBarrier preImageBarriers[] =
1129 	{
1130 		{
1131 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1132 			DE_NULL,											// const void*			pNext
1133 			0u,													// VkAccessFlags		srcAccessMask
1134 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1135 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1136 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1137 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1138 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1139 			**cbImagePass0,										// VkImage				image
1140 			{
1141 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1142 				0u,										// uint32_t				baseMipLevel
1143 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1144 				0u,										// uint32_t				baseArray
1145 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1146 			}
1147 		},
1148 		{
1149 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1150 			DE_NULL,											// const void*			pNext
1151 			0u,													// VkAccessFlags		srcAccessMask
1152 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1153 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1154 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1155 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1156 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1157 			**cbImagePass1,										// VkImage				image
1158 			{
1159 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1160 				0u,										// uint32_t				baseMipLevel
1161 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1162 				0u,										// uint32_t				baseArray
1163 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1164 			}
1165 		}
1166 	};
1167 
1168 	// Record commands
1169 	beginCommandBuffer(vk, *cmdBuffer, 0u);
1170 
1171 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1172 							(VkDependencyFlags)0,
1173 							0, (const VkMemoryBarrier*)DE_NULL,
1174 							0, (const VkBufferMemoryBarrier*)DE_NULL,
1175 							sizeof(preImageBarriers) / sizeof(preImageBarriers[0]), preImageBarriers);
1176 
1177 	// Clear both images to UINT_MAX
1178 	VkImageSubresourceRange range		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1179 	VkClearValue			clearColor	= makeClearValueColorU32(std::numeric_limits<unsigned int>::max(),0,0,0);
1180 
1181 	vk.cmdClearColorImage(*cmdBuffer, **cbImagePass0, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1182 	vk.cmdClearColorImage(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1183 
1184 	// Barrier between the clear and the rendering
1185 	VkImageMemoryBarrier clearColorBarriers[] =
1186 	{
1187 		{
1188 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1189 			DE_NULL,											// const void*			pNext
1190 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
1191 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		dstAccessMask
1192 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1193 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1194 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1195 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1196 			**cbImagePass0,										// VkImage				image
1197 			{
1198 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1199 				0u,										// uint32_t				baseMipLevel
1200 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1201 				0u,										// uint32_t				baseArray
1202 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1203 			}
1204 		},
1205 		{
1206 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1207 			DE_NULL,											// const void*			pNext
1208 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
1209 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		dstAccessMask
1210 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1211 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1212 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1213 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1214 			**cbImagePass1,										// VkImage				image
1215 			{
1216 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1217 				0u,										// uint32_t				baseMipLevel
1218 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1219 				0u,										// uint32_t				baseArray
1220 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1221 			}
1222 		}
1223 	};
1224 
1225 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1226 							(VkDependencyFlags)0,
1227 							0, (const VkMemoryBarrier*)DE_NULL,
1228 							0, (const VkBufferMemoryBarrier*)DE_NULL,
1229 							sizeof(clearColorBarriers) / sizeof(clearColorBarriers[0]), clearColorBarriers);
1230 
1231 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer,
1232 					makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height),
1233 					0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, DE_NULL);
1234 
1235 	// Put primitive shading rate in a push constant
1236 	if (m_shadingRateClamped.size() == 1)
1237 	{
1238 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT,	0, sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1239 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(m_shadingRateClamped[0]), sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1240 	}
1241 	else
1242 	{
1243 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, static_cast<deUint32>(m_shadingRateClamped.size() * sizeof(m_shadingRateClamped[0])), &m_shadingRateClamped[0]);
1244 	}
1245 
1246 	// Bind vertex buffer
1247 	const VkDeviceSize vertexBufferOffset = 0;
1248 	VkBuffer vb = **vertexBuffer;
1249 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1250 
1251 	// Bind pipeline
1252 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass0);
1253 
1254 	// Draw triangles
1255 	vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1256 
1257 	// Start next subpass
1258 	vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1259 
1260 	// Bind descriptors
1261 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPass1, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1262 
1263 	// Bind vertex buffer
1264 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1265 
1266 	// Bind pipeline
1267 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass1);
1268 
1269 	// Draw triangles
1270 	vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1271 
1272 	endRenderPass(vk, *cmdBuffer);
1273 
1274 	VkImageMemoryBarrier postImageBarrier =
1275 	{
1276 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1277 		DE_NULL,											// const void*			pNext
1278 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		srcAccessMask
1279 		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags		dstAccessMask
1280 		VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1281 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				// VkImageLayout		newLayout
1282 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1283 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1284 		**cbImagePass1,										// VkImage				image
1285 		{
1286 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1287 			0u,										// uint32_t				baseMipLevel
1288 			VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1289 			0u,										// uint32_t				baseArray
1290 			VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1291 		}
1292 	};
1293 
1294 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
1295 
1296 	const VkBufferImageCopy	copyRegion =
1297 	{
1298 		0u,																		// VkDeviceSize				bufferOffset;
1299 		0u,																		// deUint32					bufferRowLength;
1300 		0u,																		// deUint32					bufferImageHeight;
1301 		{
1302 			VK_IMAGE_ASPECT_COLOR_BIT,											// VkImageAspectFlags		aspect;
1303 			0u,																	// deUint32					mipLevel;
1304 			0u,																	// deUint32					baseArrayLayer;
1305 			1u,																	// deUint32					layerCount;
1306 		},																		// VkImageSubresourceLayers	imageSubresource;
1307 		{ 0, 0, 0 },															// VkOffset3D				imageOffset;
1308 		{m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1}	// VkExtent3D				imageExtent;
1309 	};
1310 
1311 	vk.cmdCopyImageToBuffer(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **colorOutputBuffer, 1u, &copyRegion);
1312 
1313 	const VkBufferMemoryBarrier	bufferBarrier =
1314 	{
1315 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1316 		DE_NULL,									// const void*		pNext;
1317 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1318 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
1319 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1320 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1321 		**colorOutputBuffer,						// VkBuffer			buffer;
1322 		0ull,										// VkDeviceSize		offset;
1323 		VK_WHOLE_SIZE								// VkDeviceSize		size;
1324 	};
1325 
1326 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1327 
1328 	endCommandBuffer(vk, *cmdBuffer);
1329 
1330 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1331 
1332 	// Read buffer data
1333 	invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
1334 
1335 	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
1336 		tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNSIGNED_INT32),
1337 		m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1, (const void *)colorOutputBuffer->getAllocation().getHostPtr());
1338 
1339 	for (deUint32 i = 0; i < m_shadingRateClamped.size(); i++)
1340 	{
1341 		tcu::TestStatus result = verifyResult(resultBuffer, i);
1342 		if (result.getCode() == QP_TEST_RESULT_PASS)
1343 		{
1344 			return result;
1345 		}
1346 	}
1347 
1348 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
1349 }
1350 
1351 }	// anonymous
1352 
createPixelConsistencyTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1353 void createPixelConsistencyTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1354 {
1355 	typedef struct
1356 	{
1357 		deUint32				count;
1358 		const char*				name;
1359 		const char*				description;
1360 	} TestGroupCase;
1361 
1362 	typedef struct
1363 	{
1364 		VkExtent2D				count;
1365 		const char*				name;
1366 		const char*				description;
1367 	} TestGroupCase2D;
1368 
1369 	TestGroupCase2D shadingRateCases[] =
1370 	{
1371 		{ {1, 1},	"rate_1x1",	"1x1 shading rate"	},
1372 		{ {1, 2},	"rate_1x2",	"1x2 shading rate"	},
1373 		{ {1, 4},	"rate_1x4",	"1x4 shading rate"	},
1374 		{ {2, 1},	"rate_2x1",	"2x1 shading rate"	},
1375 		{ {2, 2},	"rate_2x2",	"2x2 shading rate"	},
1376 		{ {2, 4},	"rate_2x4",	"2x4 shading rate"	},
1377 		{ {4, 1},	"rate_4x1",	"4x1 shading rate"	},
1378 		{ {4, 2},	"rate_4x2",	"4x2 shading rate"	},
1379 		{ {4, 4},	"rate_4x4",	"4x4 shading rate"	},
1380 	};
1381 
1382 	TestGroupCase sampCases[] =
1383 	{
1384 		{ VK_SAMPLE_COUNT_1_BIT,	"samples_1",	"1 raster sample"	},
1385 		{ VK_SAMPLE_COUNT_2_BIT,	"samples_2",	"2 raster samples"	},
1386 		{ VK_SAMPLE_COUNT_4_BIT,	"samples_4",	"4 raster samples"	},
1387 		{ VK_SAMPLE_COUNT_8_BIT,	"samples_8",	"8 raster samples"	},
1388 		{ VK_SAMPLE_COUNT_16_BIT,	"samples_16",	"16 raster samples"	},
1389 	};
1390 
1391 	TestGroupCase2D extentCases[] =
1392 	{
1393 		{ {1,   1},		"extent_1x1",		"framebuffer size 1x1"		},
1394 		{ {4,   4},		"extent_4x4",		"framebuffer size 4x4"		},
1395 		{ {33,  35},	"extent_33x35",		"framebuffer size 33x35"	},
1396 		{ {151, 431},	"extent_151x431",	"framebuffer size 151x431"	},
1397 		{ {256, 256},	"extent_256x256",	"framebuffer size 256x256"	},
1398 	};
1399 
1400 	de::MovePtr<tcu::TestCaseGroup> pixelGroup(new tcu::TestCaseGroup(testCtx, "pixel_consistency", "Pixel selection consistency"));
1401 
1402 	for (int rateNdx = 0; rateNdx < DE_LENGTH_OF_ARRAY(shadingRateCases); rateNdx++)
1403 	{
1404 		de::MovePtr<tcu::TestCaseGroup> rateGroup(new tcu::TestCaseGroup(testCtx, shadingRateCases[rateNdx].name, shadingRateCases[rateNdx].description));
1405 
1406 		for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
1407 		{
1408 			de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name, sampCases[sampNdx].description));
1409 			for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
1410 			{
1411 				VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(sampCases[sampNdx].count);
1412 				VkExtent2D framebufferExtent = extentCases[extNdx].count;
1413 
1414 				CaseDef caseParams{
1415 					shadingRateCases[rateNdx].count,
1416 					samples,
1417 					framebufferExtent,
1418 					false};
1419 				sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, extentCases[extNdx].name, extentCases[extNdx].description, caseParams));
1420 
1421 				// test FragCoord.zw but to avoid duplication limit tests to extent_151x431/256x256 and 1 or 4 samples
1422 				if ((framebufferExtent.width > 150) && (samples & (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)))
1423 				{
1424 					std::string caseName = std::string(extentCases[extNdx].name) + "_zw_coord";
1425 					caseParams.zwCoord = true;
1426 					sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, caseName.c_str(), extentCases[extNdx].description, caseParams));
1427 				}
1428 			}
1429 			rateGroup->addChild(sampleGroup.release());
1430 		}
1431 
1432 		pixelGroup->addChild(rateGroup.release());
1433 	}
1434 
1435 	parentGroup->addChild(pixelGroup.release());
1436 }
1437 
1438 }	// FragmentShadingRage
1439 }	// vkt
1440