• 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 "vkDeviceUtil.hpp"
37 #include "vkPlatform.hpp"
38 
39 #include "vktTestGroupUtil.hpp"
40 #include "vktTestCase.hpp"
41 #include "vktCustomInstancesDevices.hpp"
42 
43 #include "deDefs.h"
44 #include "deMath.h"
45 #include "deRandom.h"
46 #include "deSharedPtr.hpp"
47 #include "deString.h"
48 
49 #include "tcuTestCase.hpp"
50 #include "tcuTestLog.hpp"
51 #include "tcuCommandLine.hpp"
52 
53 #include <limits>
54 #include <string>
55 #include <sstream>
56 
57 namespace vkt
58 {
59 namespace FragmentShadingRate
60 {
61 namespace
62 {
63 using namespace vk;
64 using namespace std;
65 
66 struct CaseDef
67 {
68 	VkExtent2D				shadingRate;
69 	VkSampleCountFlagBits	samples;
70 	VkExtent2D				framebufferExtent;
71 	bool					zwCoord;
72 };
73 
74 struct Vertex
75 {
76 	float x;
77 	float y;
78 };
79 
80 Vertex basicTriangles[6] =
81 {
82 	{-1.0f, -1.0f},
83 	{ 1.0f, -1.0f},
84 	{ 1.0f,  1.0f},
85 
86 	{-1.0f,  1.0f},
87 	{ 1.0f, -1.0f},
88 	{ 1.0f,  1.0f},
89 };
90 
createImageRobustnessDevice(Context & context,const vk::VkInstance & instance,const InstanceInterface & vki)91 Move<VkDevice> createImageRobustnessDevice(Context& context, const vk::VkInstance& instance, const InstanceInterface& vki)
92 {
93 	const VkPhysicalDevice		physicalDevice	= chooseDevice(vki, instance, context.getTestContext().getCommandLine());
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 	vki.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 							  instance, vki, 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 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 CaseDef data)205 FSRPixelConsistencyTestCase::FSRPixelConsistencyTestCase(tcu::TestContext& context, const char* name, const CaseDef data)
206 	: vkt::TestCase	(context, name)
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 	const VkInstance			instance			= m_context.getInstance();
485 	const auto&					instanceDriver		= m_context.getInstanceInterface();
486 
487 	Move<VkDevice>				vkd					= createImageRobustnessDevice(m_context, instance, instanceDriver);
488 	const VkDevice				device				= *vkd;
489 #ifndef CTS_USES_VULKANSC
490 	de::MovePtr<vk::DeviceDriver>	deviceDriver	= de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), device, m_context.getUsedApiVersion()));
491 #else
492 	de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>	deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(m_context.getPlatformInterface(), m_context.getInstance(), device, m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(), m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties(), m_context.getUsedApiVersion()), vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), device));
493 #endif // CTS_USES_VULKANSC
494 	const DeviceInterface&		vk					= *deviceDriver;
495 	const VkQueue				queue				= getDeviceQueue(vk, device, m_context.getUniversalQueueFamilyIndex(), 0);
496 	de::MovePtr<Allocator>		allocator			= de::MovePtr<Allocator>(new SimpleAllocator(vk, device, memoryProperties));
497 
498 	// Create vertex buffer
499 	const VkDeviceSize vertexBufferSize = sizeof(basicTriangles);
500 
501 	const VkFormat imageFormat = VK_FORMAT_R32G32_UINT;
502 
503 	de::MovePtr<BufferWithMemory> vertexBuffer;
504 	vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
505 		vk, device, *allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
506 
507 	float* vbuf = (float*)vertexBuffer->getAllocation().getHostPtr();
508 
509 	deMemcpy(vbuf, basicTriangles, vertexBufferSize);
510 
511 	flushAlloc(vk, device, vertexBuffer->getAllocation());
512 
513 	// Create color output buffer
514 	const VkDeviceSize colorOutputBufferSize = m_data.framebufferExtent.width * m_data.framebufferExtent.height * tcu::getPixelSize(mapVkFormat(imageFormat));
515 
516 	de::MovePtr<BufferWithMemory> colorOutputBuffer;
517 	colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
518 		vk, device, *allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
519 
520 
521 	// Create color attachment for subpass 0
522 	de::MovePtr<ImageWithMemory> cbImagePass0;
523 	Move<VkImageView>			 cbImagePass0View;
524 	{
525 		const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
526 										  VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
527 										  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
528 
529 		const VkImageCreateInfo			imageCreateInfo =
530 		{
531 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
532 			DE_NULL,								// const void*				pNext;
533 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
534 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
535 			imageFormat,							// VkFormat					format;
536 			{
537 				m_data.framebufferExtent.width,		// deUint32	width;
538 				m_data.framebufferExtent.height,	// deUint32	height;
539 				1u									// deUint32	depth;
540 			},										// VkExtent3D				extent;
541 			1u,										// deUint32					mipLevels;
542 			1u,										// deUint32					arrayLayers;
543 			m_data.samples,							// VkSampleCountFlagBits	samples;
544 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
545 			cbUsage,								// VkImageUsageFlags		usage;
546 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
547 			0u,										// deUint32					queueFamilyIndexCount;
548 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
549 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
550 		};
551 		cbImagePass0 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
552 			vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
553 
554 		VkImageViewCreateInfo		imageViewCreateInfo =
555 		{
556 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
557 			DE_NULL,									// const void*				pNext;
558 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
559 			**cbImagePass0,								// VkImage					image;
560 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
561 			imageFormat,								// VkFormat					format;
562 			{
563 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
564 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
565 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
566 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
567 			},											// VkComponentMapping		 components;
568 			{
569 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
570 				0u,										// deUint32				baseMipLevel;
571 				1u,										// deUint32				levelCount;
572 				0u,										// deUint32				baseArrayLayer;
573 				1u										// deUint32				layerCount;
574 			}											// VkImageSubresourceRange	subresourceRange;
575 		};
576 		cbImagePass0View = createImageView(vk, device, &imageViewCreateInfo, NULL);
577 	}
578 
579 	// Create color attachment for subpass 1
580 	de::MovePtr<ImageWithMemory> cbImagePass1;
581 	Move<VkImageView>			 cbImagePass1View;
582 	{
583 		const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
584 										  VK_IMAGE_USAGE_TRANSFER_SRC_BIT	  |
585 										  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
586 
587 		const VkImageCreateInfo			imageCreateInfo =
588 		{
589 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
590 			DE_NULL,								// const void*				pNext;
591 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
592 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
593 			imageFormat,							// VkFormat					format;
594 			{
595 				m_data.framebufferExtent.width,		// deUint32	width;
596 				m_data.framebufferExtent.height,	// deUint32	height;
597 				1u									// deUint32	depth;
598 			},										// VkExtent3D				extent;
599 			1u,										// deUint32					mipLevels;
600 			1u,										// deUint32					arrayLayers;
601 			VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
602 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
603 			cbUsage,								// VkImageUsageFlags		usage;
604 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
605 			0u,										// deUint32					queueFamilyIndexCount;
606 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
607 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
608 		};
609 		cbImagePass1 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
610 			vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
611 
612 		VkImageViewCreateInfo		imageViewCreateInfo =
613 		{
614 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
615 			DE_NULL,									// const void*				pNext;
616 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
617 			**cbImagePass1,								// VkImage					image;
618 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
619 			imageFormat,								// VkFormat					format;
620 			{
621 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
622 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
623 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
624 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
625 			},											// VkComponentMapping		 components;
626 			{
627 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
628 				0u,										// deUint32				baseMipLevel;
629 				1u,										// deUint32				levelCount;
630 				0u,										// deUint32				baseArrayLayer;
631 				1u										// deUint32				layerCount;
632 			}											// VkImageSubresourceRange	subresourceRange;
633 		};
634 		cbImagePass1View = createImageView(vk, device, &imageViewCreateInfo, NULL);
635 	}
636 
637 	// Create render pass
638 	Move<VkRenderPass>	renderPass;
639 	{
640 		const vk::VkAttachmentReference colorAttachment0Reference =
641 		{
642 			0,															// attachment
643 			vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
644 		};
645 
646 		const vk::VkAttachmentReference colorAttachment1Reference =
647 		{
648 			1,															// attachment
649 			vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
650 		};
651 
652 		std::vector<VkAttachmentDescription> attachmentDescriptions;
653 
654 		attachmentDescriptions.push_back(
655 			{
656 				(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
657 				imageFormat,								// VkFormat							format;
658 				m_data.samples,								// VkSampleCountFlagBits			samples;
659 				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
660 				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
661 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
662 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
663 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
664 				VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
665 			}
666 		);
667 
668 		attachmentDescriptions.push_back(
669 			{
670 				(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
671 				imageFormat,								// VkFormat							format;
672 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
673 				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
674 				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
675 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
676 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
677 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
678 				VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
679 			}
680 		);
681 
682 		const VkSubpassDescription subpassDescs[] =
683 		{
684 			{
685 				(vk::VkSubpassDescriptionFlags)0,						// flags
686 				vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
687 				0u,														// inputCount
688 				DE_NULL,												// pInputAttachments
689 				1u,														// colorCount
690 				&colorAttachment0Reference,								// pColorAttachments
691 				DE_NULL,												// pResolveAttachments
692 				DE_NULL,												// depthStencilAttachment
693 				0u,														// preserveCount
694 				DE_NULL,												// pPreserveAttachments
695 			},
696 			{
697 				(vk::VkSubpassDescriptionFlags)0,						// flags
698 				vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
699 				1u,														// inputCount
700 				&colorAttachment0Reference,								// pInputAttachments
701 				1u,														// colorCount
702 				&colorAttachment1Reference,								// pColorAttachments
703 				DE_NULL,												// pResolveAttachments
704 				DE_NULL,												// depthStencilAttachment
705 				0u,														// preserveCount
706 				DE_NULL,												// pPreserveAttachments
707 			},
708 		};
709 
710 		const VkSubpassDependency subpassDependency =
711 		{
712 			0u,												// srcSubpass;
713 			1u,												// dstSubpass;
714 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// srcStageMask;
715 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// dstStageMask;
716 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask;
717 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// dstAccessMask;
718 			0												// dependencyFlags;
719 		};
720 
721 		const VkRenderPassCreateInfo renderPassParams =
722 		{
723 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// sType
724 			DE_NULL,												// pNext
725 			(vk::VkRenderPassCreateFlags)0,
726 			(deUint32)attachmentDescriptions.size(),				// attachmentCount
727 			&attachmentDescriptions[0],								// pAttachments
728 			sizeof(subpassDescs) / sizeof(subpassDescs[0]),			// subpassCount
729 			subpassDescs,											// pSubpasses
730 			1u,														// dependencyCount
731 			&subpassDependency,										// pDependencies
732 		};
733 
734 		renderPass = createRenderPass(vk, device, &renderPassParams);
735 	}
736 
737 	// Create framebuffer
738 	Move<VkFramebuffer> framebuffer;
739 	{
740 		std::vector<VkImageView> attachments;
741 		attachments.push_back(*cbImagePass0View);
742 		attachments.push_back(*cbImagePass1View);
743 
744 		const vk::VkFramebufferCreateInfo framebufferParams =
745 		{
746 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
747 			DE_NULL,										// pNext
748 			(vk::VkFramebufferCreateFlags)(0),				// createFlags
749 			*renderPass,									// renderPass
750 			(deUint32)attachments.size(),					// attachmentCount
751 			&attachments[0],								// pAttachments
752 			m_data.framebufferExtent.width,					// width
753 			m_data.framebufferExtent.height,				// height
754 			1u,												// layers
755 		};
756 
757 		framebuffer = createFramebuffer(vk, device, &framebufferParams);
758 	}
759 
760 
761 	// Create vertex attribute
762 	const VkVertexInputBindingDescription vertexBinding =
763 	{
764 		0u,							// deUint32				binding;
765 		sizeof(Vertex),				// deUint32				stride;
766 		VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
767 	};
768 
769 	const VkVertexInputAttributeDescription	vertexInputAttributeDescription =
770 	{
771 		0u,							// deUint32	location;
772 		0u,							// deUint32	binding;
773 		VK_FORMAT_R32G32_SFLOAT,	// VkFormat	format;
774 		0u							// deUint32	offset;
775 	};
776 
777 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo =
778 	{
779 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
780 		DE_NULL,													// const void*								pNext;
781 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
782 		1u,															// deUint32									vertexBindingDescriptionCount;
783 		&vertexBinding,												// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
784 		1u,															// deUint32									vertexAttributeDescriptionCount;
785 		&vertexInputAttributeDescription							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
786 	};
787 
788 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
789 	{
790 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
791 		DE_NULL,														// const void*								pNext;
792 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
793 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
794 		VK_FALSE														// VkBool32									primitiveRestartEnable;
795 	};
796 
797 	// Create rasterization state
798 	const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
799 	{
800 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
801 		DE_NULL,														// const void*								pNext;
802 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
803 		VK_FALSE,														// VkBool32									depthClampEnable;
804 		VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
805 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
806 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
807 		VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
808 		VK_FALSE,														// VkBool32									depthBiasEnable;
809 		0.0f,															// float									depthBiasConstantFactor;
810 		0.0f,															// float									depthBiasClamp;
811 		0.0f,															// float									depthBiasSlopeFactor;
812 		1.0f															// float									lineWidth;
813 	};
814 
815 	// Create scissor and viewport
816 	VkViewport	viewport	= makeViewport(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
817 	VkRect2D	scissor		= makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
818 
819 	const VkPipelineViewportStateCreateInfo	viewportStateCreateInfo =
820 	{
821 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType							sType
822 		DE_NULL,													// const void*								pNext
823 		(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags		flags
824 		1u,															// deUint32									viewportCount
825 		&viewport,													// const VkViewport*						pViewports
826 		1u,															// deUint32									scissorCount
827 		&scissor													// const VkRect2D*							pScissors
828 	};
829 
830 	const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
831 	{
832 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType					  sType;
833 		DE_NULL,													// const void*						  pNext;
834 		(VkPipelineDynamicStateCreateFlags)0,						// VkPipelineDynamicStateCreateFlags	flags;
835 		0u,															// uint32_t							 dynamicStateCount;
836 		DE_NULL,													// const VkDynamicState*				pDynamicStates;
837 	};
838 
839 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState[] =
840 	{
841 		{
842 			VK_FALSE,				// VkBool32					blendEnable;
843 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcColorBlendFactor;
844 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
845 			VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
846 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcAlphaBlendFactor;
847 			VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
848 			VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
849 			0xf						// VkColorComponentFlags	colorWriteMask;
850 		}
851 	};
852 
853 	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo =
854 	{
855 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,					// VkStructureType								sType;
856 		DE_NULL,																	// const void*									pNext;
857 		0u,																			// VkPipelineColorBlendStateCreateFlags			flags;
858 		VK_FALSE,																	// VkBool32										logicOpEnable;
859 		VK_LOGIC_OP_COPY,															// VkLogicOp									logicOp;
860 		sizeof(colorBlendAttachmentState) / sizeof(colorBlendAttachmentState[0]),	// deUint32										attachmentCount;
861 		colorBlendAttachmentState,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
862 		{ 1.0f, 1.0f, 1.0f, 1.0f }													// float										blendConstants[4];
863 	};
864 
865 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateParams =
866 	{
867 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
868 		DE_NULL,													// const void*								pNext;
869 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
870 		VK_FALSE,													// VkBool32									depthTestEnable;
871 		VK_FALSE,													// VkBool32									depthWriteEnable;
872 		VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
873 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
874 		VK_FALSE,													// VkBool32									stencilTestEnable;
875 		// VkStencilOpState	front;
876 		{
877 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
878 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
879 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
880 			VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
881 			0u,						// deUint32		compareMask;
882 			0xFFu,					// deUint32		writeMask;
883 			0xFFu,					// deUint32		reference;
884 		},
885 		// VkStencilOpState	back;
886 		{
887 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
888 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
889 			VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
890 			VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
891 			0u,						// deUint32		compareMask;
892 			0xFFu,					// deUint32		writeMask;
893 			0xFFu,					// deUint32		reference;
894 		},
895 		0.0f,						// float			minDepthBounds;
896 		0.0f,						// float			maxDepthBounds;
897 	};
898 
899 	// Create pipeline for pass 0
900 	Move<VkPipeline> pipelinePass0;
901 	Move<VkPipelineLayout> pipelineLayoutPass0;
902 	{
903 		const VkPushConstantRange		pushConstantRange =
904 		{
905 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
906 			0u,															// deUint32								offset;
907 			2 * sizeof(VkExtent2D)										// deUint32								size;
908 		};
909 
910 		const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
911 		{
912 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
913 			DE_NULL,													// pNext
914 			(VkPipelineLayoutCreateFlags)0,
915 			0u,															// setLayoutCount
916 			DE_NULL,													// pSetLayouts
917 			1u,															// pushConstantRangeCount
918 			&pushConstantRange,											// pPushConstantRanges
919 		};
920 
921 		pipelineLayoutPass0 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
922 
923 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo =
924 		{
925 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
926 			DE_NULL,													// const void*					pNext
927 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
928 			(VkSampleCountFlagBits)m_data.samples,						// VkSampleCountFlagBits					rasterizationSamples
929 			VK_FALSE,													// VkBool32									sampleShadingEnable
930 			1.0f,														// float									minSampleShading
931 			DE_NULL,													// const VkSampleMask*						pSampleMask
932 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
933 			VK_FALSE													// VkBool32									alphaToOneEnable
934 		};
935 
936 		Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
937 		Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass0"), 0);
938 
939 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo[] =
940 		{
941 			{
942 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
943 				DE_NULL,
944 				(VkPipelineShaderStageCreateFlags)0,
945 				VK_SHADER_STAGE_VERTEX_BIT,									// stage
946 				*vertShader,												// shader
947 				"main",
948 				DE_NULL,													// pSpecializationInfo
949 			},
950 			{
951 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
952 				DE_NULL,
953 				(VkPipelineShaderStageCreateFlags)0,
954 				VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
955 				*fragShader,												// shader
956 				"main",
957 				DE_NULL,													// pSpecializationInfo
958 			}
959 		};
960 
961 		const VkGraphicsPipelineCreateInfo	graphicsPipelineCreateInfo =
962 		{
963 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// VkStructureType									sType;
964 			DE_NULL,												// const void*										pNext;
965 			(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags							flags;
966 			sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]),	// deUint32											stageCount;
967 			&shaderCreateInfo[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
968 			&vertexInputStateCreateInfo,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
969 			&inputAssemblyStateCreateInfo,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
970 			DE_NULL,												// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
971 			&viewportStateCreateInfo,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
972 			&rasterizationStateCreateInfo,							// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
973 			&multisampleStateCreateInfo,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
974 			&depthStencilStateParams,								// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
975 			&colorBlendStateCreateInfo,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
976 			&dynamicStateCreateInfo,								// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
977 			pipelineLayoutPass0.get(),								// VkPipelineLayout									layout;
978 			renderPass.get(),										// VkRenderPass										renderPass;
979 			0u,														// deUint32											subpass;
980 			DE_NULL,												// VkPipeline										basePipelineHandle;
981 			0														// int												basePipelineIndex;
982 		};
983 
984 		pipelinePass0 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
985 	}
986 
987 
988 	// Create pipeline for pass 1
989 	Move<VkPipeline>				pipelinePass1;
990 	Move<VkPipelineLayout>			pipelineLayoutPass1;
991 	Move<vk::VkDescriptorPool>		descriptorPool;
992 	Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
993 	Move<vk::VkDescriptorSet>		descriptorSet;
994 	{
995 		const VkDescriptorSetLayoutBinding bindings[] =
996 		{
997 			{
998 				0u,										// binding
999 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// descriptorType
1000 				1u,										// descriptorCount
1001 				VK_SHADER_STAGE_FRAGMENT_BIT,			// stageFlags
1002 				DE_NULL,								// pImmutableSamplers
1003 			}
1004 		};
1005 
1006 		// Create a layout and allocate a descriptor set for it.
1007 		const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1008 		{
1009 			vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
1010 			DE_NULL,													// pNext
1011 			(VkDescriptorSetLayoutCreateFlags)(0),						// flags
1012 			sizeof(bindings) / sizeof(bindings[0]),						// bindingCount
1013 			&bindings[0]												// pBindings
1014 		};
1015 
1016 		descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1017 
1018 		vk::DescriptorPoolBuilder poolBuilder;
1019 
1020 		for (deInt32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1021 		{
1022 			poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1023 		}
1024 
1025 		descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1026 		descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1027 
1028 		VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImagePass0View, VK_IMAGE_LAYOUT_GENERAL);
1029 
1030 		VkWriteDescriptorSet writeDescriptorSet =
1031 		{
1032 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1033 			DE_NULL,														// pNext
1034 			*descriptorSet,													// dstSet
1035 			0u,																// dstBinding
1036 			0u,																// dstArrayElement
1037 			1u,																// descriptorCount
1038 			bindings[0].descriptorType,										// descriptorType
1039 			&imageInfo,														// pImageInfo
1040 			DE_NULL,														// pBufferInfo
1041 			DE_NULL,														// pTexelBufferView
1042 		};
1043 
1044 		vk.updateDescriptorSets(device, 1, &writeDescriptorSet, 0, NULL);
1045 
1046 		const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1047 		{
1048 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
1049 			DE_NULL,													// pNext
1050 			(VkPipelineLayoutCreateFlags)0,
1051 			1u,															// setLayoutCount
1052 			&descriptorSetLayout.get(),									// pSetLayouts
1053 			0u,															// pushConstantRangeCount
1054 			DE_NULL,													// pPushConstantRanges
1055 		};
1056 
1057 		pipelineLayoutPass1 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1058 
1059 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo =
1060 		{
1061 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1062 			DE_NULL,													// const void*								pNext
1063 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
1064 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
1065 			VK_FALSE,													// VkBool32									sampleShadingEnable
1066 			1.0f,														// float									minSampleShading
1067 			DE_NULL,													// const VkSampleMask*						pSampleMask
1068 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
1069 			VK_FALSE													// VkBool32									alphaToOneEnable
1070 		};
1071 
1072 		VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo =
1073 		{
1074 			VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,								// VkStructureType						sType;
1075 			DE_NULL,																							// const void*							pNext;
1076 			m_data.shadingRate,																					// VkExtent2D							fragmentSize;
1077 			{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR },	// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
1078 		};
1079 
1080 		Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1081 		Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass1"), 0);
1082 
1083 		const VkPipelineShaderStageCreateInfo	shaderCreateInfo[] =
1084 		{
1085 			{
1086 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1087 				DE_NULL,
1088 				(VkPipelineShaderStageCreateFlags)0,
1089 				VK_SHADER_STAGE_VERTEX_BIT,									// stage
1090 				*vertShader,												// shader
1091 				"main",
1092 				DE_NULL,													// pSpecializationInfo
1093 			},
1094 			{
1095 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1096 				DE_NULL,
1097 				(VkPipelineShaderStageCreateFlags)0,
1098 				VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
1099 				*fragShader,												// shader
1100 				"main",
1101 				DE_NULL,													// pSpecializationInfo
1102 			}
1103 		};
1104 
1105 		const VkGraphicsPipelineCreateInfo	graphicsPipelineCreateInfo =
1106 		{
1107 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// VkStructureType									sType;
1108 			&shadingRateStateCreateInfo,							// const void*										pNext;
1109 			(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags							flags;
1110 			sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]),	// deUint32											stageCount;
1111 			&shaderCreateInfo[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
1112 			&vertexInputStateCreateInfo,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1113 			&inputAssemblyStateCreateInfo,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1114 			DE_NULL,												// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1115 			&viewportStateCreateInfo,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1116 			&rasterizationStateCreateInfo,							// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
1117 			&multisampleStateCreateInfo,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1118 			&depthStencilStateParams,								// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1119 			&colorBlendStateCreateInfo,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1120 			&dynamicStateCreateInfo,								// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1121 			pipelineLayoutPass1.get(),								// VkPipelineLayout									layout;
1122 			renderPass.get(),										// VkRenderPass										renderPass;
1123 			1u,														// deUint32											subpass;
1124 			DE_NULL,												// VkPipeline										basePipelineHandle;
1125 			0														// int												basePipelineIndex;
1126 		};
1127 
1128 		pipelinePass1 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
1129 	}
1130 
1131 	// Create command buffer
1132 	Move<VkCommandPool>		cmdPool		= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
1133 	Move<VkCommandBuffer>	cmdBuffer	= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1134 
1135 	VkImageMemoryBarrier preImageBarriers[] =
1136 	{
1137 		{
1138 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1139 			DE_NULL,											// const void*			pNext
1140 			0u,													// VkAccessFlags		srcAccessMask
1141 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1142 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1143 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1144 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1145 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1146 			**cbImagePass0,										// VkImage				image
1147 			{
1148 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1149 				0u,										// uint32_t				baseMipLevel
1150 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1151 				0u,										// uint32_t				baseArray
1152 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1153 			}
1154 		},
1155 		{
1156 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1157 			DE_NULL,											// const void*			pNext
1158 			0u,													// VkAccessFlags		srcAccessMask
1159 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1160 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1161 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1162 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1163 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1164 			**cbImagePass1,										// VkImage				image
1165 			{
1166 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1167 				0u,										// uint32_t				baseMipLevel
1168 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1169 				0u,										// uint32_t				baseArray
1170 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1171 			}
1172 		}
1173 	};
1174 
1175 	// Record commands
1176 	beginCommandBuffer(vk, *cmdBuffer, 0u);
1177 
1178 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1179 							(VkDependencyFlags)0,
1180 							0, (const VkMemoryBarrier*)DE_NULL,
1181 							0, (const VkBufferMemoryBarrier*)DE_NULL,
1182 							sizeof(preImageBarriers) / sizeof(preImageBarriers[0]), preImageBarriers);
1183 
1184 	// Clear both images to UINT_MAX
1185 	VkImageSubresourceRange range		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1186 	VkClearValue			clearColor	= makeClearValueColorU32(std::numeric_limits<unsigned int>::max(),0,0,0);
1187 
1188 	vk.cmdClearColorImage(*cmdBuffer, **cbImagePass0, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1189 	vk.cmdClearColorImage(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1190 
1191 	// Barrier between the clear and the rendering
1192 	VkImageMemoryBarrier clearColorBarriers[] =
1193 	{
1194 		{
1195 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1196 			DE_NULL,											// const void*			pNext
1197 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
1198 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		dstAccessMask
1199 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1200 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1201 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1202 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1203 			**cbImagePass0,										// VkImage				image
1204 			{
1205 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1206 				0u,										// uint32_t				baseMipLevel
1207 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1208 				0u,										// uint32_t				baseArray
1209 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1210 			}
1211 		},
1212 		{
1213 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1214 			DE_NULL,											// const void*			pNext
1215 			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
1216 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		dstAccessMask
1217 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1218 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1219 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1220 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1221 			**cbImagePass1,										// VkImage				image
1222 			{
1223 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1224 				0u,										// uint32_t				baseMipLevel
1225 				VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1226 				0u,										// uint32_t				baseArray
1227 				VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1228 			}
1229 		}
1230 	};
1231 
1232 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1233 							(VkDependencyFlags)0,
1234 							0, (const VkMemoryBarrier*)DE_NULL,
1235 							0, (const VkBufferMemoryBarrier*)DE_NULL,
1236 							sizeof(clearColorBarriers) / sizeof(clearColorBarriers[0]), clearColorBarriers);
1237 
1238 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer,
1239 					makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height),
1240 					0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, DE_NULL);
1241 
1242 	// Put primitive shading rate in a push constant
1243 	if (m_shadingRateClamped.size() == 1)
1244 	{
1245 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT,	0, sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1246 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(m_shadingRateClamped[0]), sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1247 	}
1248 	else
1249 	{
1250 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, static_cast<deUint32>(m_shadingRateClamped.size() * sizeof(m_shadingRateClamped[0])), &m_shadingRateClamped[0]);
1251 	}
1252 
1253 	// Bind vertex buffer
1254 	const VkDeviceSize vertexBufferOffset = 0;
1255 	VkBuffer vb = **vertexBuffer;
1256 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1257 
1258 	// Bind pipeline
1259 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass0);
1260 
1261 	// Draw triangles
1262 	vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1263 
1264 	// Start next subpass
1265 	vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1266 
1267 	// Bind descriptors
1268 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPass1, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1269 
1270 	// Bind vertex buffer
1271 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1272 
1273 	// Bind pipeline
1274 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass1);
1275 
1276 	// Draw triangles
1277 	vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1278 
1279 	endRenderPass(vk, *cmdBuffer);
1280 
1281 	VkImageMemoryBarrier postImageBarrier =
1282 	{
1283 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1284 		DE_NULL,											// const void*			pNext
1285 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		srcAccessMask
1286 		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags		dstAccessMask
1287 		VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
1288 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				// VkImageLayout		newLayout
1289 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1290 		VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1291 		**cbImagePass1,										// VkImage				image
1292 		{
1293 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1294 			0u,										// uint32_t				baseMipLevel
1295 			VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1296 			0u,										// uint32_t				baseArray
1297 			VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1298 		}
1299 	};
1300 
1301 	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);
1302 
1303 	const VkBufferImageCopy	copyRegion =
1304 	{
1305 		0u,																		// VkDeviceSize				bufferOffset;
1306 		0u,																		// deUint32					bufferRowLength;
1307 		0u,																		// deUint32					bufferImageHeight;
1308 		{
1309 			VK_IMAGE_ASPECT_COLOR_BIT,											// VkImageAspectFlags		aspect;
1310 			0u,																	// deUint32					mipLevel;
1311 			0u,																	// deUint32					baseArrayLayer;
1312 			1u,																	// deUint32					layerCount;
1313 		},																		// VkImageSubresourceLayers	imageSubresource;
1314 		{ 0, 0, 0 },															// VkOffset3D				imageOffset;
1315 		{m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1}	// VkExtent3D				imageExtent;
1316 	};
1317 
1318 	vk.cmdCopyImageToBuffer(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **colorOutputBuffer, 1u, &copyRegion);
1319 
1320 	const VkBufferMemoryBarrier	bufferBarrier =
1321 	{
1322 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1323 		DE_NULL,									// const void*		pNext;
1324 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1325 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
1326 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1327 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1328 		**colorOutputBuffer,						// VkBuffer			buffer;
1329 		0ull,										// VkDeviceSize		offset;
1330 		VK_WHOLE_SIZE								// VkDeviceSize		size;
1331 	};
1332 
1333 	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);
1334 
1335 	endCommandBuffer(vk, *cmdBuffer);
1336 
1337 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1338 
1339 	// Read buffer data
1340 	invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
1341 
1342 	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
1343 		tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNSIGNED_INT32),
1344 		m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1, (const void *)colorOutputBuffer->getAllocation().getHostPtr());
1345 
1346 	for (deUint32 i = 0; i < m_shadingRateClamped.size(); i++)
1347 	{
1348 		tcu::TestStatus result = verifyResult(resultBuffer, i);
1349 		if (result.getCode() == QP_TEST_RESULT_PASS)
1350 		{
1351 			return result;
1352 		}
1353 	}
1354 
1355 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
1356 }
1357 
1358 }	// anonymous
1359 
createPixelConsistencyTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1360 void createPixelConsistencyTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1361 {
1362 	typedef struct
1363 	{
1364 		deUint32				count;
1365 		const char*				name;
1366 	} TestGroupCase;
1367 
1368 	typedef struct
1369 	{
1370 		VkExtent2D				count;
1371 		const char*				name;
1372 	} TestGroupCase2D;
1373 
1374 	TestGroupCase2D shadingRateCases[] =
1375 	{
1376 		{ {1, 1},	"rate_1x1"},
1377 		{ {1, 2},	"rate_1x2"},
1378 		{ {1, 4},	"rate_1x4"},
1379 		{ {2, 1},	"rate_2x1"},
1380 		{ {2, 2},	"rate_2x2"},
1381 		{ {2, 4},	"rate_2x4",},
1382 		{ {4, 1},	"rate_4x1",},
1383 		{ {4, 2},	"rate_4x2",},
1384 		{ {4, 4},	"rate_4x4",},
1385 	};
1386 
1387 	TestGroupCase sampCases[] =
1388 	{
1389 		{ VK_SAMPLE_COUNT_1_BIT,	"samples_1"},
1390 		{ VK_SAMPLE_COUNT_2_BIT,	"samples_2"},
1391 		{ VK_SAMPLE_COUNT_4_BIT,	"samples_4"},
1392 		{ VK_SAMPLE_COUNT_8_BIT,	"samples_8"},
1393 		{ VK_SAMPLE_COUNT_16_BIT,	"samples_16"},
1394 	};
1395 
1396 	TestGroupCase2D extentCases[] =
1397 	{
1398 		{ {1,   1},		"extent_1x1"},
1399 		{ {4,   4},		"extent_4x4"},
1400 		{ {33,  35},	"extent_33x35"},
1401 		{ {151, 431},	"extent_151x431"},
1402 		{ {256, 256},	"extent_256x256"},
1403 	};
1404 
1405 	de::MovePtr<tcu::TestCaseGroup> pixelGroup(new tcu::TestCaseGroup(testCtx, "pixel_consistency"));
1406 
1407 	for (int rateNdx = 0; rateNdx < DE_LENGTH_OF_ARRAY(shadingRateCases); rateNdx++)
1408 	{
1409 		de::MovePtr<tcu::TestCaseGroup> rateGroup(new tcu::TestCaseGroup(testCtx, shadingRateCases[rateNdx].name));
1410 
1411 		for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
1412 		{
1413 			de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name));
1414 			for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
1415 			{
1416 				VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(sampCases[sampNdx].count);
1417 				VkExtent2D framebufferExtent = extentCases[extNdx].count;
1418 
1419 				CaseDef caseParams{
1420 					shadingRateCases[rateNdx].count,
1421 					samples,
1422 					framebufferExtent,
1423 					false};
1424 				sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, extentCases[extNdx].name, caseParams));
1425 
1426 				// test FragCoord.zw but to avoid duplication limit tests to extent_151x431/256x256 and 1 or 4 samples
1427 				if ((framebufferExtent.width > 150) && (samples & (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)))
1428 				{
1429 					std::string caseName = std::string(extentCases[extNdx].name) + "_zw_coord";
1430 					caseParams.zwCoord = true;
1431 					sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, caseName.c_str(), caseParams));
1432 				}
1433 			}
1434 			rateGroup->addChild(sampleGroup.release());
1435 		}
1436 
1437 		pixelGroup->addChild(rateGroup.release());
1438 	}
1439 
1440 	parentGroup->addChild(pixelGroup.release());
1441 }
1442 
1443 }	// FragmentShadingRage
1444 }	// vkt
1445