1/*------------------------------------------------------------------------
2* Vulkan Conformance Tests
3* ------------------------
4*
5* Copyright (c) 2017 The Khronos Group Inc.
6* Copyright (c) 2017 Nvidia Corporation
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 Device Group Tests
23*//*--------------------------------------------------------------------*/
24
25#include "vktDeviceGroupTests.hpp"
26
27#include "vkDefs.hpp"
28#include "vkDeviceUtil.hpp"
29#include "vkImageUtil.hpp"
30#include "vkMemUtil.hpp"
31#include "vkPlatform.hpp"
32#include "vkPrograms.hpp"
33#include "vkQueryUtil.hpp"
34#include "vkRef.hpp"
35#include "vkRefUtil.hpp"
36#include "vkStrUtil.hpp"
37#include "vkTypeUtil.hpp"
38#include "vktTestCase.hpp"
39#include "vktTestCaseUtil.hpp"
40#include "vktTestGroupUtil.hpp"
41
42#include "tcuDefs.hpp"
43#include "tcuFormatUtil.hpp"
44#include "tcuImageCompare.hpp"
45#include "tcuResource.hpp"
46#include "tcuTestCase.hpp"
47#include "tcuTestLog.hpp"
48#include "tcuCommandLine.hpp"
49#include "tcuTextureUtil.hpp"
50#include "tcuImageIO.hpp"
51
52#include "rrRenderer.hpp"
53
54namespace vkt
55{
56namespace DeviceGroup
57{
58namespace
59{
60
61using namespace vk;
62using std::string;
63using std::vector;
64using tcu::TestLog;
65using de::UniquePtr;
66
67//Device group test modes
68enum TestModeType
69{
70	TEST_MODE_SFR			= 1 << 0,			//!< Split frame remdering
71	TEST_MODE_AFR			= 1 << 1,			//!< Alternate frame rendering
72	TEST_MODE_HOSTMEMORY	= 1 << 2,			//!< Use host memory for rendertarget
73	TEST_MODE_DEDICATED		= 1 << 3,			//!< Use dedicated allocations
74	TEST_MODE_PEER_FETCH	= 1 << 4,			//!< Peer vertex attributes from peer memroy
75	TEST_MODE_TESSELLATION	= 1 << 5,			//!< Generate a tessellated sphere instead of triangle
76	TEST_MODE_LINEFILL		= 1 << 6,			//!< Draw polygon edges as line segments
77};
78
79class RefVertexShader : public rr::VertexShader
80{
81public:
82	RefVertexShader (void)
83		: rr::VertexShader(1, 0)
84	{
85		m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
86	}
87	virtual	~RefVertexShader(void) {}
88
89	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
90	{
91		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
92		{
93			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
94				packets[packetNdx]->instanceNdx,
95				packets[packetNdx]->vertexNdx);
96		}
97	}
98};
99
100class RefFragmentShader : public rr::FragmentShader
101{
102public:
103	RefFragmentShader (void)
104		: rr::FragmentShader(0, 1)
105	{
106		m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
107	}
108
109	virtual	~RefFragmentShader(void) {}
110
111	void shadeFragments (rr::FragmentPacket*, const int numPackets, const rr::FragmentShadingContext& context) const
112	{
113		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
114		{
115			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
116			{
117				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
118			}
119		}
120	}
121};
122
123void renderReferenceTriangle (const tcu::PixelBufferAccess& dst, const tcu::Vec4(&vertices)[3])
124{
125	const RefVertexShader					vertShader;
126	const RefFragmentShader					fragShader;
127	const rr::Program						program(&vertShader, &fragShader);
128	const rr::MultisamplePixelBufferAccess	colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst);
129	const rr::RenderTarget					renderTarget(colorBuffer);
130	const rr::RenderState					renderState((rr::ViewportState(colorBuffer)));
131	const rr::Renderer						renderer;
132	const rr::VertexAttrib					vertexAttribs[] =
133	{
134		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, vertices[0].getPtr())
135	};
136	renderer.draw(rr::DrawCommand(renderState,
137		renderTarget,
138		program,
139		DE_LENGTH_OF_ARRAY(vertexAttribs),
140		&vertexAttribs[0],
141		rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, DE_LENGTH_OF_ARRAY(vertices), 0)));
142}
143
144class DeviceGroupTestInstance : public TestInstance
145{
146public:
147	DeviceGroupTestInstance(Context& context, deUint32 mode);
148	~DeviceGroupTestInstance(void) {}
149private:
150			void						init						(void);
151			deUint32					getMemoryIndex				(deUint32 memoryTypeBits, deUint32 memoryPropertyFlag);
152			void						getDeviceLayers				(vector<string>& enabledLayers);
153			bool						isPeerFetchAllowed			(deUint32 memoryTypeIndex, deUint32 firstdeviceID, deUint32 seconddeviceID);
154			void						SubmitBufferAndWaitForIdle	(const DeviceDriver& vk, VkCommandBuffer cmdBuf, VkDeviceGroupSubmitInfo);
155	virtual	tcu::TestStatus				iterate						(void);
156
157			Move<VkDevice>				m_deviceGroup;
158			deUint32					m_physicalDeviceCount;
159			VkQueue						m_deviceGroupQueue;
160			vector<VkPhysicalDevice>	m_physicalDevices;
161
162			deUint32					m_testMode;
163			bool						m_useHostMemory;
164			bool						m_useDedicated;
165			bool						m_usePeerFetch;
166			bool						m_subsetAllocation;
167			bool						m_fillModeNonSolid;
168			bool						m_drawTessellatedSphere;
169};
170
171DeviceGroupTestInstance::DeviceGroupTestInstance (Context& context, const deUint32 mode)
172	: TestInstance				(context)
173	, m_physicalDeviceCount		(0)
174	, m_deviceGroupQueue		(DE_NULL)
175	, m_testMode				(mode)
176	, m_useHostMemory			(m_testMode & TEST_MODE_HOSTMEMORY)
177	, m_useDedicated			(m_testMode & TEST_MODE_DEDICATED)
178	, m_usePeerFetch			(m_testMode & TEST_MODE_PEER_FETCH)
179	, m_subsetAllocation		(true)
180	, m_fillModeNonSolid		(m_testMode & TEST_MODE_LINEFILL)
181	, m_drawTessellatedSphere	(m_testMode & TEST_MODE_TESSELLATION)
182{
183	init();
184}
185
186deUint32 DeviceGroupTestInstance::getMemoryIndex (const deUint32 memoryTypeBits, const deUint32 memoryPropertyFlag)
187{
188	const VkPhysicalDeviceMemoryProperties deviceMemProps = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
189	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
190	{
191		if ((memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
192			(deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & memoryPropertyFlag) == memoryPropertyFlag)
193			return memoryTypeNdx;
194	}
195	TCU_THROW(NotSupportedError, "No compatible memory type found");
196}
197
198bool DeviceGroupTestInstance::isPeerFetchAllowed (deUint32 memoryTypeIndex, deUint32 firstdeviceID, deUint32 seconddeviceID)
199{
200	VkPeerMemoryFeatureFlags				peerMemFeatures1;
201	VkPeerMemoryFeatureFlags				peerMemFeatures2;
202	const DeviceDriver						vk						(m_context.getInstanceInterface(), *m_deviceGroup);
203	const VkPhysicalDeviceMemoryProperties	deviceMemProps1			= getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[firstdeviceID]);
204	const VkPhysicalDeviceMemoryProperties	deviceMemProps2			= getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[seconddeviceID]);
205	vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps2.memoryTypes[memoryTypeIndex].heapIndex, firstdeviceID, seconddeviceID, &peerMemFeatures1);
206	vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps1.memoryTypes[memoryTypeIndex].heapIndex, seconddeviceID, firstdeviceID, &peerMemFeatures2);
207	return (peerMemFeatures1 & VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT) && (peerMemFeatures2 & VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT);
208}
209
210void DeviceGroupTestInstance::getDeviceLayers (vector<string>& enabledLayers)
211{
212	const tcu::CommandLine& cmdLine = m_context.getTestContext().getCommandLine();
213	if (cmdLine.isValidationEnabled())
214	{
215		const vector<VkLayerProperties> layerProperties = enumerateDeviceLayerProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
216
217		static const char*	s_magicLayer = "VK_LAYER_LUNARG_standard_validation";
218		static const char*	s_defaultLayers[] =
219		{
220			"VK_LAYER_GOOGLE_threading",
221			"VK_LAYER_LUNARG_parameter_validation",
222			"VK_LAYER_LUNARG_device_limits",
223			"VK_LAYER_LUNARG_object_tracker",
224			"VK_LAYER_LUNARG_image",
225			"VK_LAYER_LUNARG_core_validation",
226			"VK_LAYER_LUNARG_swapchain",
227			"VK_LAYER_GOOGLE_unique_objects",
228		};
229
230		if (isLayerSupported(layerProperties, RequiredLayer(s_magicLayer)))
231			enabledLayers.push_back(s_magicLayer);
232		else
233		{
234			for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
235			{
236				if (isLayerSupported(layerProperties, RequiredLayer(s_defaultLayers[ndx])))
237					enabledLayers.push_back(s_defaultLayers[ndx]);
238			}
239		}
240		if (enabledLayers.empty())
241			TCU_THROW(NotSupportedError, "No device validation layers found");
242	}
243}
244
245void DeviceGroupTestInstance::init (void)
246{
247	if (!isInstanceExtensionSupported(m_context.getUsedApiVersion(), m_context.getInstanceExtensions(), "VK_KHR_device_group_creation"))
248		TCU_THROW(NotSupportedError, "Device Group tests are not supported, no device group extension present.");
249
250	const InstanceInterface&		instanceInterface	= m_context.getInstanceInterface();
251	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
252	const deUint32					queueIndex			= 0;
253	const float						queuePriority		= 1.0f;
254	vector<const char*>				extensionPtrs;
255	de::MovePtr<vk::DeviceDriver>	deviceDriver;
256	vector<const char*>				layerPtrs;
257	vector<string>					deviceExtensions;
258	vector<string>					enabledLayers;
259
260	if (!isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_KHR_device_group"))
261		TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_device_group");
262
263	if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
264		deviceExtensions.push_back("VK_KHR_device_group");
265
266	if(m_useDedicated)
267	{
268		if (!isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_KHR_dedicated_allocation"))
269			TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_dedicated_allocation");
270
271		if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_dedicated_allocation"))
272			deviceExtensions.push_back("VK_KHR_dedicated_allocation");
273	}
274
275	{
276		const tcu::CommandLine&								cmdLine = m_context.getTestContext().getCommandLine();
277		const vector<VkPhysicalDeviceGroupProperties>		properties = enumeratePhysicalDeviceGroups(instanceInterface, m_context.getInstance());
278		if ((size_t)cmdLine.getVKDeviceGroupId() > properties.size())
279			TCU_THROW(TestError, "Invalid device group index.");
280
281		m_physicalDeviceCount = properties[cmdLine.getVKDeviceGroupId() - 1].physicalDeviceCount;
282		for (deUint32 idx = 0; idx < m_physicalDeviceCount; idx++)
283		{
284			m_physicalDevices.push_back(properties[cmdLine.getVKDeviceGroupId() - 1].physicalDevices[idx]);
285		}
286
287		if (m_usePeerFetch && m_physicalDeviceCount < 2)
288			TCU_THROW(NotSupportedError, "Peer fetching needs more than 1 physical device.");
289
290		if (!(m_testMode & TEST_MODE_AFR) || (m_physicalDeviceCount > 1))
291		{
292			if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), std::string("VK_KHR_bind_memory2")))
293				TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_bind_memory2");
294			deviceExtensions.push_back("VK_KHR_bind_memory2");
295		}
296
297		const VkDeviceQueueCreateInfo						deviceQueueCreateInfo =
298		{
299			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	//type
300			DE_NULL,									//pNext
301			(VkDeviceQueueCreateFlags)0u,				//flags
302			queueFamilyIndex,							//queueFamilyIndex;
303			1u,											//queueCount;
304			&queuePriority,								//pQueuePriorities;
305		};
306		const VkDeviceGroupDeviceCreateInfo		deviceGroupInfo =
307		{
308			VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO,					//stype
309			DE_NULL,															//pNext
310			properties[cmdLine.getVKDeviceGroupId() - 1].physicalDeviceCount,	//physicalDeviceCount
311			properties[cmdLine.getVKDeviceGroupId() - 1].physicalDevices		//physicalDevices
312		};
313
314		VkPhysicalDevice			physicalDevice			= properties[cmdLine.getVKDeviceGroupId() - 1].physicalDevices[(size_t)(cmdLine.getVKDeviceId() - 1)];
315		VkPhysicalDeviceFeatures	enabledDeviceFeatures	= getPhysicalDeviceFeatures(instanceInterface, physicalDevice);
316		m_subsetAllocation									= properties[cmdLine.getVKDeviceGroupId() - 1].subsetAllocation;
317
318		if (m_drawTessellatedSphere & static_cast<bool>(!enabledDeviceFeatures.tessellationShader))
319			TCU_THROW(NotSupportedError, "Tessellation is not supported.");
320
321		if (m_fillModeNonSolid & static_cast<bool>(!enabledDeviceFeatures.fillModeNonSolid))
322			TCU_THROW(NotSupportedError, "Line polygon mode is not supported.");
323
324		extensionPtrs.resize(deviceExtensions.size());
325		for (size_t ndx = 0; ndx < deviceExtensions.size(); ++ndx)
326			extensionPtrs[ndx] = deviceExtensions[ndx].c_str();
327
328		// Get Layers
329		getDeviceLayers(enabledLayers);
330		layerPtrs.resize(enabledLayers.size());
331		for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
332			layerPtrs[ndx] = enabledLayers[ndx].c_str();
333
334		const VkDeviceCreateInfo	deviceCreateInfo =
335		{
336			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,					//sType;
337			&deviceGroupInfo,										//pNext;
338			(VkDeviceCreateFlags)0u,								//flags
339			1,														//queueRecordCount;
340			&deviceQueueCreateInfo,									//pRequestedQueues;
341			(deUint32)layerPtrs.size(),								//layerCount;
342			(layerPtrs.empty() ? DE_NULL : &layerPtrs[0]),			//ppEnabledLayerNames;
343			(deUint32)extensionPtrs.size(),							//extensionCount;
344			(extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]),	//ppEnabledExtensionNames;
345			&enabledDeviceFeatures,									//pEnabledFeatures;
346		};
347		m_deviceGroup = createDevice(instanceInterface, physicalDevice, &deviceCreateInfo);
348	}
349
350	deviceDriver = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(instanceInterface, *m_deviceGroup));
351	m_deviceGroupQueue = getDeviceQueue(*deviceDriver, *m_deviceGroup, queueFamilyIndex, queueIndex);
352}
353
354void DeviceGroupTestInstance::SubmitBufferAndWaitForIdle(const DeviceDriver& vk, VkCommandBuffer cmdBuf, VkDeviceGroupSubmitInfo deviceGroupSubmitInfo)
355{
356	const VkFenceCreateInfo	fenceParams =
357	{
358		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// sType
359		DE_NULL,								// pNext
360		0u,										// flags
361	};
362	const VkSubmitInfo		submitInfo =
363	{
364		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// sType
365		&deviceGroupSubmitInfo,					// pNext
366		0u,										// waitSemaphoreCount
367		DE_NULL,								// pWaitSemaphores
368		(const VkPipelineStageFlags*)DE_NULL,	// pWaitDstStageMask
369		1u,										// commandBufferCount
370		&cmdBuf,								// pCommandBuffers
371		0u,										// signalSemaphoreCount
372		DE_NULL,								// pSignalSemaphores
373	};
374	const Unique<VkFence>	fence(createFence(vk, *m_deviceGroup, &fenceParams));
375
376	VK_CHECK(vk.queueSubmit(m_deviceGroupQueue, 1u, &submitInfo, *fence));
377	VK_CHECK(vk.waitForFences(*m_deviceGroup, 1u, &fence.get(), DE_TRUE, ~0ull));
378	VK_CHECK(vk.deviceWaitIdle(*m_deviceGroup));
379}
380
381tcu::TestStatus DeviceGroupTestInstance::iterate (void)
382{
383	const InstanceInterface&	vki						(m_context.getInstanceInterface());
384	const DeviceDriver			vk						(vki, *m_deviceGroup);
385	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
386	const tcu::UVec2			renderSize				(256, 256);
387	const VkFormat				colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
388	const tcu::Vec4				clearColor				(0.125f, 0.25f, 0.75f, 1.0f);
389	const tcu::Vec4				drawColor				(1.0f, 1.0f, 0.0f, 1.0f);
390	const float					tessLevel				= 16.0f;
391	SimpleAllocator				memAlloc				(vk, *m_deviceGroup, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
392	bool						iterateResultSuccess	= false;
393	const tcu::Vec4				sphereVertices[]		=
394	{
395		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
396		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
397		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
398		tcu::Vec4(0.0f, 0.0f, -1.0f, 1.0f),
399		tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f),
400		tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
401	};
402	const deUint32				sphereIndices[]			= {0, 1, 2, 2, 1, 3, 3, 1, 5, 5, 1, 0, 0, 2, 4, 2, 3, 4, 3, 5, 4, 5, 0, 4};
403	const tcu::Vec4				triVertices[]			=
404	{
405		tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
406		tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
407		tcu::Vec4(0.0f, +0.5f, 0.0f, 1.0f)
408	};
409	const deUint32				triIndices[]			= {0, 1, 2};
410	const tcu::Vec4 *			vertices				= m_drawTessellatedSphere ? &sphereVertices[0] : &triVertices[0];
411	const deUint32 *			indices					= m_drawTessellatedSphere ? &sphereIndices[0] : &triIndices[0];
412	const deUint32				verticesSize			= m_drawTessellatedSphere ? deUint32(sizeof(sphereVertices)) : deUint32(sizeof(triVertices));
413	const deUint32				numIndices				= m_drawTessellatedSphere ? deUint32(sizeof(sphereIndices)/sizeof(sphereIndices[0])) : deUint32(sizeof(triIndices)/sizeof(triIndices[0]));
414	const deUint32				indicesSize				= m_drawTessellatedSphere ? deUint32(sizeof(sphereIndices)) : deUint32(sizeof(triIndices));
415
416	// Loop through all physical devices in the device group
417	for (deUint32 physDevID = 0; physDevID < m_physicalDeviceCount; physDevID++)
418	{
419		const deUint32			firstDeviceID				= physDevID;
420		const deUint32			secondDeviceID				= (firstDeviceID + 1 ) % m_physicalDeviceCount;
421		vector<deUint32>		deviceIndices				(m_physicalDeviceCount);
422		bool					isPeerMemAsCopySrcAllowed	= true;
423		// Set broadcast on memory allocation
424		const deUint32			allocDeviceMask				= m_subsetAllocation ? (1 << firstDeviceID) | (1 << secondDeviceID) : (1 << m_physicalDeviceCount) - 1;
425
426		for (deUint32 i = 0; i < m_physicalDeviceCount; i++)
427			deviceIndices[i] = i;
428		deviceIndices[firstDeviceID] = secondDeviceID;
429		deviceIndices[secondDeviceID] = firstDeviceID;
430
431		VkMemoryRequirements			memReqs				=
432		{
433			0,							// VkDeviceSize		size
434			0,							// VkDeviceSize		alignment
435			0,							// uint32_t			memoryTypeBits
436		};
437		deUint32						memoryTypeNdx		= 0;
438		de::MovePtr<Allocation>			stagingVertexBufferMemory;
439		de::MovePtr<Allocation>			stagingIndexBufferMemory;
440		de::MovePtr<Allocation>			stagingUniformBufferMemory;
441		de::MovePtr<Allocation>			stagingSboBufferMemory;
442
443		vk::Move<vk::VkDeviceMemory>	vertexBufferMemory;
444		vk::Move<vk::VkDeviceMemory>	indexBufferMemory;
445		vk::Move<vk::VkDeviceMemory>	uniformBufferMemory;
446		vk::Move<vk::VkDeviceMemory>	sboBufferMemory;
447		vk::Move<vk::VkDeviceMemory>	imageMemory;
448
449		Move<VkRenderPass>				renderPass;
450		Move<VkImage>					renderImage;
451		Move<VkImage>					readImage;
452
453		Move<VkDescriptorSetLayout>		descriptorSetLayout;
454		Move<VkDescriptorPool>			descriptorPool;
455		Move<VkDescriptorSet>			descriptorSet;
456
457		Move<VkBuffer>					stagingVertexBuffer;
458		Move<VkBuffer>					stagingUniformBuffer;
459		Move<VkBuffer>					stagingIndexBuffer;
460		Move<VkBuffer>					stagingSboBuffer;
461
462		Move<VkBuffer>					vertexBuffer;
463		Move<VkBuffer>					indexBuffer;
464		Move<VkBuffer>					uniformBuffer;
465		Move<VkBuffer>					sboBuffer;
466
467		Move<VkPipeline>				pipeline;
468		Move<VkPipelineLayout>			pipelineLayout;
469
470		Move<VkImageView>				colorAttView;
471		Move<VkFramebuffer>				framebuffer;
472		Move<VkCommandPool>				cmdPool;
473		Move<VkCommandBuffer>			cmdBuffer;
474
475		VkMemoryDedicatedAllocateInfo	dedicatedAllocInfo =
476		{
477				VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,		// sType
478				DE_NULL,												// pNext
479				DE_NULL,												// image
480				DE_NULL													// buffer
481		};
482
483		VkMemoryAllocateFlagsInfo		allocDeviceMaskInfo =
484		{
485			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,		// sType
486			m_useDedicated ? &dedicatedAllocInfo : DE_NULL,		// pNext
487			VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,					// flags
488			allocDeviceMask,									// deviceMask
489		};
490
491		VkMemoryAllocateInfo		allocInfo =
492		{
493			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,			// sType
494			&allocDeviceMaskInfo,							// pNext
495			0u,												// allocationSize
496			0u,												// memoryTypeIndex
497		};
498
499		VkDeviceGroupSubmitInfo		deviceGroupSubmitInfo =
500		{
501			VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,		// sType
502			DE_NULL,										// pNext
503			0u,												// waitSemaphoreCount
504			DE_NULL,										// pWaitSemaphoreDeviceIndices
505			0u,												// commandBufferCount
506			DE_NULL,										// pCommandBufferDeviceMasks
507			0u,												// signalSemaphoreCount
508			DE_NULL,										// pSignalSemaphoreDeviceIndices
509		};
510
511		// create vertex buffers
512		{
513			const VkBufferCreateInfo	stagingVertexBufferParams =
514			{
515				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
516				DE_NULL,																// pNext
517				0u,																		// flags
518				(VkDeviceSize)verticesSize,												// size
519				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,										// usage
520				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
521				1u,																		// queueFamilyIndexCount
522				&queueFamilyIndex,														// pQueueFamilyIndices
523			};
524			stagingVertexBuffer = createBuffer(vk, *m_deviceGroup, &stagingVertexBufferParams);
525			stagingVertexBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingVertexBuffer), MemoryRequirement::HostVisible);
526			VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingVertexBuffer, stagingVertexBufferMemory->getMemory(), stagingVertexBufferMemory->getOffset()));
527
528			const VkMappedMemoryRange	range	=
529			{
530				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
531				DE_NULL,								// pNext
532				stagingVertexBufferMemory->getMemory(),	// memory
533				0u,										// offset
534				(VkDeviceSize)verticesSize,				// size
535			};
536			void*	vertexBufPtr	= stagingVertexBufferMemory->getHostPtr();
537			deMemcpy(vertexBufPtr, &vertices[0], verticesSize);
538			VK_CHECK(vk.flushMappedMemoryRanges(*m_deviceGroup, 1u, &range));
539		}
540
541		{
542			const VkBufferCreateInfo	vertexBufferParams =
543			{
544				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
545				DE_NULL,																// pNext
546				0u,																		// flags
547				(VkDeviceSize)verticesSize,												// size
548				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,	// usage
549				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
550				1u,																		// queueFamilyIndexCount
551				&queueFamilyIndex,														// pQueueFamilyIndices
552			};
553			vertexBuffer = createBuffer(vk, *m_deviceGroup, &vertexBufferParams);
554
555			memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, vertexBuffer.get());
556			memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
557
558			dedicatedAllocInfo.buffer = vertexBuffer.get();
559			allocInfo.allocationSize = memReqs.size;
560			allocInfo.memoryTypeIndex = memoryTypeNdx;
561			vertexBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
562
563			if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
564				TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
565
566			// Bind vertex buffer
567			if (m_usePeerFetch)
568			{
569				VkBindBufferMemoryDeviceGroupInfo	devGroupBindInfo =
570				{
571					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,		// sType
572					DE_NULL,													// pNext
573					m_physicalDeviceCount,										// deviceIndexCount
574					&deviceIndices[0],											// pDeviceIndices
575				};
576
577				VkBindBufferMemoryInfo				bindInfo =
578				{
579					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,					// sType
580					&devGroupBindInfo,											// pNext
581					vertexBuffer.get(),											// buffer
582					vertexBufferMemory.get(),									// memory
583					0u,															// memoryOffset
584				};
585				VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
586			}
587			else
588				VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *vertexBuffer, vertexBufferMemory.get(), 0));
589		}
590
591		// create index buffers
592		{
593			const VkBufferCreateInfo	stagingIndexBufferParams =
594			{
595				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
596				DE_NULL,																// pNext
597				0u,																		// flags
598				(VkDeviceSize)indicesSize,												// size
599				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,										// usage
600				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
601				1u,																		// queueFamilyIndexCount
602				&queueFamilyIndex,														// pQueueFamilyIndices
603			};
604			stagingIndexBuffer = createBuffer(vk, *m_deviceGroup, &stagingIndexBufferParams);
605			stagingIndexBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingIndexBuffer), MemoryRequirement::HostVisible);
606			VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingIndexBuffer, stagingIndexBufferMemory->getMemory(), stagingIndexBufferMemory->getOffset()));
607
608			const VkMappedMemoryRange	range	=
609			{
610				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
611				DE_NULL,								// pNext
612				stagingIndexBufferMemory->getMemory(),	// memory
613				0u,										// offset
614				(VkDeviceSize)indicesSize,				// size
615			};
616			void*	indexBufPtr	= stagingIndexBufferMemory->getHostPtr();
617			deMemcpy(indexBufPtr, &indices[0], indicesSize);
618			VK_CHECK(vk.flushMappedMemoryRanges(*m_deviceGroup, 1u, &range));
619		}
620
621		{
622			const VkBufferCreateInfo	indexBufferParams =
623			{
624				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
625				DE_NULL,																// pNext
626				0u,																		// flags
627				(VkDeviceSize)indicesSize,												// size
628				VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,	// usage
629				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
630				1u,																		// queueFamilyIndexCount
631				&queueFamilyIndex,														// pQueueFamilyIndices
632			};
633			indexBuffer = createBuffer(vk, *m_deviceGroup, &indexBufferParams);
634
635			memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, indexBuffer.get());
636			memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
637
638			dedicatedAllocInfo.buffer = indexBuffer.get();
639			allocInfo.allocationSize = memReqs.size;
640			allocInfo.memoryTypeIndex = memoryTypeNdx;
641			indexBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
642
643			if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
644				TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
645
646			// Bind index buffer
647			if (m_usePeerFetch)
648			{
649				VkBindBufferMemoryDeviceGroupInfo	devGroupBindInfo =
650				{
651					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,		// sType
652					DE_NULL,													// pNext
653					m_physicalDeviceCount,										// deviceIndexCount
654					&deviceIndices[0],											// pDeviceIndices
655				};
656
657				VkBindBufferMemoryInfo				bindInfo =
658				{
659					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,					// sType
660					&devGroupBindInfo,											// pNext
661					indexBuffer.get(),											// buffer
662					indexBufferMemory.get(),									// memory
663					0u,															// memoryOffset
664				};
665				VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
666			}
667			else
668				VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *indexBuffer, indexBufferMemory.get(), 0));
669		}
670
671		// create uniform buffers
672		{
673			const VkBufferCreateInfo	stagingUniformBufferParams =
674			{
675				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
676				DE_NULL,																// pNext
677				0u,																		// flags
678				(VkDeviceSize)sizeof(drawColor),												// size
679				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,										// usage
680				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
681				1u,																		// queueFamilyIndexCount
682				&queueFamilyIndex,														// pQueueFamilyIndices
683			};
684			stagingUniformBuffer = createBuffer(vk, *m_deviceGroup, &stagingUniformBufferParams);
685			stagingUniformBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingUniformBuffer), MemoryRequirement::HostVisible);
686			VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingUniformBuffer, stagingUniformBufferMemory->getMemory(), stagingUniformBufferMemory->getOffset()));
687
688			const VkMappedMemoryRange	range	=
689			{
690				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
691				DE_NULL,								// pNext
692				stagingUniformBufferMemory->getMemory(),// memory
693				0u,										// offset
694				(VkDeviceSize)sizeof(drawColor),		// size
695			};
696			void*	uniformBufPtr	= stagingUniformBufferMemory->getHostPtr();
697			deMemcpy(uniformBufPtr, &drawColor[0], sizeof(drawColor));
698			VK_CHECK(vk.flushMappedMemoryRanges(*m_deviceGroup, 1u, &range));
699		}
700
701		{
702			const VkBufferCreateInfo	uniformBufferParams =
703			{
704				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
705				DE_NULL,																// pNext
706				0u,																		// flags
707				(VkDeviceSize)sizeof(drawColor),										// size
708				VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,	// usage
709				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
710				1u,																		// queueFamilyIndexCount
711				&queueFamilyIndex,														// pQueueFamilyIndices
712			};
713			uniformBuffer = createBuffer(vk, *m_deviceGroup, &uniformBufferParams);
714
715			memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, uniformBuffer.get());
716			memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
717
718			dedicatedAllocInfo.buffer = uniformBuffer.get();
719			allocInfo.allocationSize = memReqs.size;
720			allocInfo.memoryTypeIndex = memoryTypeNdx;
721			uniformBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
722
723			if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
724				TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
725
726			if (m_usePeerFetch)
727			{
728				VkBindBufferMemoryDeviceGroupInfo	devGroupBindInfo =
729				{
730					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,		// sType
731					DE_NULL,													// pNext
732					m_physicalDeviceCount,										// deviceIndexCount
733					&deviceIndices[0],											// pDeviceIndices
734				};
735
736				VkBindBufferMemoryInfo				bindInfo =
737				{
738					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,					// sType
739					&devGroupBindInfo,											// pNext
740					uniformBuffer.get(),										// buffer
741					uniformBufferMemory.get(),									// memory
742					0u,															// memoryOffset
743				};
744				VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
745			}
746			else
747				VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, uniformBuffer.get(), uniformBufferMemory.get(), 0));
748		}
749
750		// create SBO buffers
751		{
752			const VkBufferCreateInfo	stagingSboBufferParams =
753			{
754				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
755				DE_NULL,																// pNext
756				0u,																		// flags
757				(VkDeviceSize)sizeof(tessLevel),										// size
758				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,										// usage
759				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
760				1u,																		// queueFamilyIndexCount
761				&queueFamilyIndex,														// pQueueFamilyIndices
762			};
763			stagingSboBuffer = createBuffer(vk, *m_deviceGroup, &stagingSboBufferParams);
764			stagingSboBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingSboBuffer), MemoryRequirement::HostVisible);
765			VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingSboBuffer, stagingSboBufferMemory->getMemory(), stagingSboBufferMemory->getOffset()));
766
767			const VkMappedMemoryRange	range	=
768			{
769				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
770				DE_NULL,								// pNext
771				stagingSboBufferMemory->getMemory(),	// memory
772				0u,										// offset
773				(VkDeviceSize)sizeof(tessLevel),		// size
774			};
775			void*	sboBufPtr	= stagingSboBufferMemory->getHostPtr();
776			deMemcpy(sboBufPtr, &tessLevel, sizeof(tessLevel));
777			VK_CHECK(vk.flushMappedMemoryRanges(*m_deviceGroup, 1u, &range));
778		}
779
780		{
781			const VkBufferCreateInfo	sboBufferParams =
782			{
783				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// sType
784				DE_NULL,																// pNext
785				0u,																		// flags
786				(VkDeviceSize)sizeof(tessLevel),										// size
787				VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,	// usage
788				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
789				1u,																		// queueFamilyIndexCount
790				&queueFamilyIndex,														// pQueueFamilyIndices
791			};
792			sboBuffer = createBuffer(vk, *m_deviceGroup, &sboBufferParams);
793
794			memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, sboBuffer.get());
795			memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
796
797			dedicatedAllocInfo.buffer = sboBuffer.get();
798			allocInfo.allocationSize = memReqs.size;
799			allocInfo.memoryTypeIndex = memoryTypeNdx;
800			sboBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
801
802			if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
803				TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
804
805			if (m_usePeerFetch)
806			{
807				VkBindBufferMemoryDeviceGroupInfo	devGroupBindInfo =
808				{
809					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,		// sType
810					DE_NULL,													// pNext
811					m_physicalDeviceCount,										// deviceIndexCount
812					&deviceIndices[0],											// pDeviceIndices
813				};
814
815				VkBindBufferMemoryInfo				bindInfo =
816				{
817					VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,					// sType
818					&devGroupBindInfo,											// pNext
819					sboBuffer.get(),											// buffer
820					sboBufferMemory.get(),										// memory
821					0u,															// memoryOffset
822				};
823				VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
824			}
825			else
826				VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, sboBuffer.get(), sboBufferMemory.get(), 0));
827		}
828
829		// Create image resources
830		// Use a consistent usage flag because of memory aliasing
831		VkImageUsageFlags imageUsageFlag = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
832		{
833			// Check for SFR support
834			VkImageFormatProperties properties;
835			if ((m_testMode & TEST_MODE_SFR) && vki.getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
836				colorFormat,															// format
837				VK_IMAGE_TYPE_2D,														// type
838				VK_IMAGE_TILING_OPTIMAL,												// tiling
839				VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// usage
840				VK_IMAGE_CREATE_BIND_SFR_BIT,											// flags
841				&properties) != VK_SUCCESS)												// properties
842			{
843				TCU_THROW(NotSupportedError, "Format not supported for SFR");
844			}
845
846			VkImageCreateFlags	imageCreateFlags = VK_IMAGE_CREATE_ALIAS_BIT;	// The image objects alias same memory
847			if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
848			{
849				imageCreateFlags |= VK_IMAGE_CREATE_BIND_SFR_BIT;
850			}
851
852			const VkImageCreateInfo		imageParams =
853			{
854				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// sType
855				DE_NULL,																// pNext
856				imageCreateFlags,														// flags
857				VK_IMAGE_TYPE_2D,														// imageType
858				colorFormat,															// format
859				{ renderSize.x(), renderSize.y(), 1 },									// extent
860				1u,																		// mipLevels
861				1u,																		// arraySize
862				VK_SAMPLE_COUNT_1_BIT,													// samples
863				VK_IMAGE_TILING_OPTIMAL,												// tiling
864				imageUsageFlag,															// usage
865				VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
866				1u,																		// queueFamilyIndexCount
867				&queueFamilyIndex,														// pQueueFamilyIndices
868				VK_IMAGE_LAYOUT_UNDEFINED,												// initialLayout
869			};
870
871			renderImage = createImage(vk, *m_deviceGroup, &imageParams);
872			readImage = createImage(vk, *m_deviceGroup, &imageParams);
873
874			dedicatedAllocInfo.image = *renderImage;
875			dedicatedAllocInfo.buffer = DE_NULL;
876			memReqs = getImageMemoryRequirements(vk, *m_deviceGroup, renderImage.get());
877			memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, m_useHostMemory ? 0 : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
878			allocInfo.allocationSize = memReqs.size;
879			allocInfo.memoryTypeIndex = memoryTypeNdx;
880			imageMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
881		}
882
883		if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
884		{
885			if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
886				TCU_THROW(NotSupportedError, "Peer texture reads is not supported.");
887
888			// Check if peer memory can be used as source of a copy command in case of SFR bindings, always allowed in case of 1 device
889			VkPeerMemoryFeatureFlags				peerMemFeatures;
890			const VkPhysicalDeviceMemoryProperties	deviceMemProps = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[secondDeviceID]);
891			vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps.memoryTypes[memoryTypeNdx].heapIndex, firstDeviceID, secondDeviceID, &peerMemFeatures);
892			isPeerMemAsCopySrcAllowed = (peerMemFeatures & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT);
893
894			VkRect2D zeroRect = {
895				{
896					0,	//	VkOffset2D.x
897					0,	//	VkOffset2D.x
898				},
899				{
900					0,	//	VkExtent2D.x
901					0,	//	VkExtent2D.x
902				}
903			};
904			vector<VkRect2D> sfrRects;
905			for (deUint32 i = 0; i < m_physicalDeviceCount*m_physicalDeviceCount; i++)
906				sfrRects.push_back(zeroRect);
907
908			if (m_physicalDeviceCount == 1u)
909			{
910				sfrRects[0].extent.width	= (deInt32)renderSize.x();
911				sfrRects[0].extent.height	= (deInt32)renderSize.y();
912			}
913			else
914			{
915				// Split into 2 vertical halves
916				sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.width	= (deInt32)renderSize.x() / 2;
917				sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.height	= (deInt32)renderSize.y();
918				sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID]				= sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
919				sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID].offset.x		= (deInt32)renderSize.x() / 2;
920				sfrRects[secondDeviceID * m_physicalDeviceCount + firstDeviceID]				= sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
921				sfrRects[secondDeviceID * m_physicalDeviceCount + secondDeviceID]				= sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID];
922			}
923
924			VkBindImageMemoryDeviceGroupInfo	devGroupBindInfo =
925			{
926				VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,		// sType
927				DE_NULL,													// pNext
928				0u,															// deviceIndexCount
929				DE_NULL,													// pDeviceIndices
930				m_physicalDeviceCount*m_physicalDeviceCount,				// SFRRectCount
931				&sfrRects[0],												// pSFRRects
932			};
933
934			VkBindImageMemoryInfo				bindInfo =
935			{
936				VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,					// sType
937				&devGroupBindInfo,											// pNext
938				*renderImage,												// image
939				imageMemory.get(),											// memory
940				0u,															// memoryOffset
941			};
942			VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
943		}
944		else
945			VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *renderImage, imageMemory.get(), 0));
946
947		VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *readImage, imageMemory.get(), 0));
948
949		// Create renderpass
950		{
951			const VkAttachmentDescription			colorAttDesc =
952			{
953				0u,												// flags
954				colorFormat,									// format
955				VK_SAMPLE_COUNT_1_BIT,							// samples
956				VK_ATTACHMENT_LOAD_OP_CLEAR,					// loadOp
957				VK_ATTACHMENT_STORE_OP_STORE,					// storeOp
958				VK_ATTACHMENT_LOAD_OP_DONT_CARE,				// stencilLoadOp
959				VK_ATTACHMENT_STORE_OP_DONT_CARE,				// stencilStoreOp
960				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// initialLayout
961				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// finalLayout
962			};
963			const VkAttachmentReference				colorAttRef =
964			{
965				0u,												// attachment
966				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// layout
967			};
968			const VkSubpassDescription				subpassDesc =
969			{
970				(VkSubpassDescriptionFlags)0u,					// flags
971				VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
972				0u,												// inputAttachmentCount
973				DE_NULL,										// pInputAttachments
974				1u,												// colorAttachmentCount
975				&colorAttRef,									// pColorAttachments
976				DE_NULL,										// pResolveAttachments
977				DE_NULL,										// depthStencilAttachment
978				0u,												// preserveAttachmentCount
979				DE_NULL,										// pPreserveAttachments
980			};
981			const VkRenderPassCreateInfo			renderPassParams =
982			{
983				VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		// sType
984				DE_NULL,										// pNext
985				0u,												// flags
986				1u,												// attachmentCount
987				&colorAttDesc,									// pAttachments
988				1u,												// subpassCount
989				&subpassDesc,									// pSubpasses
990				0u,												// dependencyCount
991				DE_NULL,										// pDependencies
992			};
993			renderPass = createRenderPass(vk, *m_deviceGroup, &renderPassParams);
994		}
995
996		// Create descriptors
997		{
998			vector<VkDescriptorSetLayoutBinding>	layoutBindings;
999			vector<VkDescriptorPoolSize>			descriptorTypes;
1000			vector<VkWriteDescriptorSet>			writeDescritporSets;
1001
1002			const VkDescriptorSetLayoutBinding layoutBindingUBO =
1003			{
1004				0u,											// deUint32				binding;
1005				VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			// VkDescriptorType		descriptorType;
1006				1u,											// deUint32				descriptorCount;
1007				VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlags	stageFlags;
1008				DE_NULL										// const VkSampler*		pImmutableSamplers;
1009			};
1010			const VkDescriptorSetLayoutBinding layoutBindingSBO =
1011			{
1012				1u,											// deUint32				binding;
1013				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			// VkDescriptorType		descriptorType;
1014				1u,											// deUint32				descriptorCount;
1015				VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	// VkShaderStageFlags	stageFlags;
1016				DE_NULL										// const VkSampler*		pImmutableSamplers;
1017			};
1018
1019			layoutBindings.push_back(layoutBindingUBO);
1020			if (m_drawTessellatedSphere)
1021				layoutBindings.push_back(layoutBindingSBO);
1022
1023			const VkDescriptorSetLayoutCreateInfo	descriptorLayoutParams =
1024			{
1025				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
1026				DE_NULL,												// cost void*							pNext;
1027				(VkDescriptorSetLayoutCreateFlags)0,					// VkDescriptorSetLayoutCreateFlags		flags
1028				deUint32(layoutBindings.size()),						// deUint32								count;
1029				layoutBindings.data()									// const VkDescriptorSetLayoutBinding	pBinding;
1030			};
1031			descriptorSetLayout = createDescriptorSetLayout(vk, *m_deviceGroup, &descriptorLayoutParams);
1032
1033			const VkDescriptorPoolSize descriptorTypeUBO =
1034			{
1035				VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,		// VkDescriptorType		type;
1036				1										// deUint32				count;
1037			};
1038			const VkDescriptorPoolSize descriptorTypeSBO =
1039			{
1040				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// VkDescriptorType		type;
1041				1										// deUint32				count;
1042			};
1043			descriptorTypes.push_back(descriptorTypeUBO);
1044			if (m_drawTessellatedSphere)
1045				descriptorTypes.push_back(descriptorTypeSBO);
1046
1047			const VkDescriptorPoolCreateInfo descriptorPoolParams =
1048			{
1049				VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,		// VkStructureType					sType;
1050				DE_NULL,											// void*							pNext;
1051				VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	// VkDescriptorPoolCreateFlags		flags;
1052				1u,													// deUint32							maxSets;
1053				deUint32(descriptorTypes.size()),					// deUint32							count;
1054				descriptorTypes.data()								// const VkDescriptorTypeCount*		pTypeCount
1055			};
1056			descriptorPool = createDescriptorPool(vk, *m_deviceGroup, &descriptorPoolParams);
1057
1058			const VkDescriptorSetAllocateInfo descriptorSetParams =
1059			{
1060				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1061				DE_NULL,
1062				*descriptorPool,
1063				1u,
1064				&descriptorSetLayout.get(),
1065			};
1066			descriptorSet = allocateDescriptorSet(vk, *m_deviceGroup, &descriptorSetParams);
1067
1068			const VkDescriptorBufferInfo uboDescriptorInfo =
1069			{
1070				uniformBuffer.get(),
1071				0,
1072				(VkDeviceSize)sizeof(drawColor)
1073			};
1074			const VkDescriptorBufferInfo sboDescriptorInfo =
1075			{
1076				sboBuffer.get(),
1077				0,
1078				(VkDeviceSize)sizeof(tessLevel)
1079			};
1080			const VkWriteDescriptorSet writeDescritporSetUBO =
1081			{
1082				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType			sType;
1083				DE_NULL,									// const void*				pNext;
1084				*descriptorSet,								// VkDescriptorSet			destSet;
1085				0,											// deUint32					destBinding;
1086				0,											// deUint32					destArrayElement;
1087				1u,											// deUint32					count;
1088				VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			// VkDescriptorType			descriptorType;
1089				(const VkDescriptorImageInfo*)DE_NULL,		// VkDescriptorImageInfo*	pImageInfo;
1090				&uboDescriptorInfo,							// VkDescriptorBufferInfo*	pBufferInfo;
1091				(const VkBufferView*)DE_NULL				// VkBufferView*			pTexelBufferView;
1092			};
1093
1094			const VkWriteDescriptorSet writeDescritporSetSBO =
1095			{
1096				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType			sType;
1097				DE_NULL,									// const void*				pNext;
1098				*descriptorSet,								// VkDescriptorSet			destSet;
1099				1,											// deUint32					destBinding;
1100				0,											// deUint32					destArrayElement;
1101				1u,											// deUint32					count;
1102				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			// VkDescriptorType			descriptorType;
1103				(const VkDescriptorImageInfo*)DE_NULL,		// VkDescriptorImageInfo*	pImageInfo;
1104				&sboDescriptorInfo,							// VkDescriptorBufferInfo*	pBufferInfo;
1105				(const VkBufferView*)DE_NULL				// VkBufferView*			pTexelBufferView;
1106			};
1107			writeDescritporSets.push_back(writeDescritporSetUBO);
1108			if (m_drawTessellatedSphere)
1109				writeDescritporSets.push_back(writeDescritporSetSBO);
1110
1111			vk.updateDescriptorSets(*m_deviceGroup, deUint32(writeDescritporSets.size()), writeDescritporSets.data(), 0u, DE_NULL);
1112		}
1113
1114		// Create Pipeline
1115		{
1116			vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
1117			Move<VkShaderModule>					vertShaderModule;
1118			Move<VkShaderModule>					tcssShaderModule;
1119			Move<VkShaderModule>					tessShaderModule;
1120			Move<VkShaderModule>					fragShaderModule;
1121
1122			const VkDescriptorSetLayout descset = descriptorSetLayout.get();
1123			const VkPipelineLayoutCreateInfo	pipelineLayoutParams =
1124			{
1125				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			// sType
1126				DE_NULL,												// pNext
1127				(vk::VkPipelineLayoutCreateFlags)0,						// flags
1128				1u,														// setLayoutCount
1129				&descset,												// pSetLayouts
1130				0u,														// pushConstantRangeCount
1131				DE_NULL,												// pPushConstantRanges
1132			};
1133			pipelineLayout = createPipelineLayout(vk, *m_deviceGroup, &pipelineLayoutParams);
1134
1135			// Shaders
1136			vertShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("vert"), 0);
1137			fragShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("frag"), 0);
1138
1139			const VkSpecializationInfo				emptyShaderSpecParams =
1140			{
1141				0u,															// mapEntryCount
1142				DE_NULL,													// pMap
1143				0,															// dataSize
1144				DE_NULL,													// pData
1145			};
1146			const VkPipelineShaderStageCreateInfo	vertexShaderStageParams =
1147			{
1148				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1149				DE_NULL,												// pNext
1150				0u,														// flags
1151				VK_SHADER_STAGE_VERTEX_BIT,								// stage
1152				*vertShaderModule,										// module
1153				"main",													// pName
1154				&emptyShaderSpecParams,									// pSpecializationInfo
1155			};
1156			shaderStageParams.push_back(vertexShaderStageParams);
1157
1158			if (m_drawTessellatedSphere)
1159			{
1160				tcssShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tesc"), 0);
1161				tessShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tese"), 0);
1162
1163				const VkPipelineShaderStageCreateInfo	tessControlShaderStageParams =
1164				{
1165					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1166					DE_NULL,												// pNext
1167					0u,														// flags
1168					VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,				// stage
1169					*tcssShaderModule,										// module
1170					"main",													// pName
1171					&emptyShaderSpecParams,									// pSpecializationInfo
1172				};
1173				const VkPipelineShaderStageCreateInfo	tessEvalShaderStageParams =
1174				{
1175					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1176					DE_NULL,												// pNext
1177					0u,														// flags
1178					VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,			// stage
1179					*tessShaderModule,										// module
1180					"main",													// pName
1181					&emptyShaderSpecParams,									// pSpecializationInfo
1182				};
1183
1184				shaderStageParams.push_back(tessControlShaderStageParams);
1185				shaderStageParams.push_back(tessEvalShaderStageParams);
1186			}
1187
1188			const VkPipelineShaderStageCreateInfo	fragmentShaderStageParams =
1189			{
1190				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1191				DE_NULL,												// pNext
1192				0u,														// flags
1193				VK_SHADER_STAGE_FRAGMENT_BIT,							// stage
1194				*fragShaderModule,										// module
1195				"main",													// pName
1196				&emptyShaderSpecParams,									// pSpecializationInfo
1197			};
1198			shaderStageParams.push_back(fragmentShaderStageParams);
1199
1200			const VkPipelineDepthStencilStateCreateInfo	depthStencilParams =
1201			{
1202				VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// sType
1203				DE_NULL,													// pNext
1204				0u,															// flags
1205				DE_FALSE,													// depthTestEnable
1206				DE_FALSE,													// depthWriteEnable
1207				VK_COMPARE_OP_ALWAYS,										// depthCompareOp
1208				DE_FALSE,													// depthBoundsTestEnable
1209				DE_FALSE,													// stencilTestEnable
1210				{
1211					VK_STENCIL_OP_KEEP,										// failOp
1212					VK_STENCIL_OP_KEEP,										// passOp
1213					VK_STENCIL_OP_KEEP,										// depthFailOp
1214					VK_COMPARE_OP_ALWAYS,									// compareOp
1215					0u,														// compareMask
1216					0u,														// writeMask
1217					0u,														// reference
1218				},															// front
1219				{
1220					VK_STENCIL_OP_KEEP,										// failOp
1221					VK_STENCIL_OP_KEEP,										// passOp
1222					VK_STENCIL_OP_KEEP,										// depthFailOp
1223					VK_COMPARE_OP_ALWAYS,									// compareOp
1224					0u,														// compareMask
1225					0u,														// writeMask
1226					0u,														// reference
1227				},															// back;
1228				0.0f,														// minDepthBounds;
1229				1.0f,														// maxDepthBounds;
1230			};
1231			const VkViewport	viewport0 =
1232			{
1233				0.0f,														// x
1234				0.0f,														// y
1235				(float)renderSize.x(),										// width
1236				(float)renderSize.y(),										// height
1237				0.0f,														// minDepth
1238				1.0f,														// maxDepth
1239			};
1240			const VkRect2D		scissor0 =
1241			{
1242				{
1243					0u,														// x
1244					0u,														// y
1245				},															// offset
1246				{
1247					renderSize.x(),											// width
1248					renderSize.y(),											// height
1249				},															// extent;
1250			};
1251			const VkPipelineViewportStateCreateInfo		viewportParams =
1252			{
1253				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// sType
1254				DE_NULL,													// pNext
1255				0u,															// flags
1256				1u,															// viewportCount
1257				&viewport0,													// pViewports
1258				1u,															// scissorCount
1259				&scissor0													// pScissors
1260			};
1261			const VkSampleMask							sampleMask = ~0u;
1262			const VkPipelineMultisampleStateCreateInfo	multisampleParams =
1263			{
1264				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// sType
1265				DE_NULL,													// pNext
1266				0u,															// flags
1267				VK_SAMPLE_COUNT_1_BIT,										// rasterizationSamples
1268				VK_FALSE,													// sampleShadingEnable
1269				0.0f,														// minSampleShading
1270				&sampleMask,												// sampleMask
1271				VK_FALSE,													// alphaToCoverageEnable
1272				VK_FALSE,													// alphaToOneEnable
1273			};
1274			const VkPipelineRasterizationStateCreateInfo	rasterParams =
1275			{
1276				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,			// sType
1277				DE_NULL,															// pNext
1278				0u,																	// flags
1279				VK_TRUE,															// depthClampEnable
1280				VK_FALSE,															// rasterizerDiscardEnable
1281				m_fillModeNonSolid ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL,	// polygonMode
1282				VK_CULL_MODE_NONE,													// cullMode
1283				VK_FRONT_FACE_COUNTER_CLOCKWISE,									// frontFace
1284				VK_FALSE,															// depthBiasEnable
1285				0.0f,																// depthBiasConstantFactor
1286				0.0f,																// depthBiasClamp
1287				0.0f,																// depthBiasSlopeFactor
1288				1.0f,																// lineWidth
1289			};
1290			const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams =
1291			{
1292				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// sType
1293				DE_NULL,														// pNext
1294				0u,																// flags
1295				m_drawTessellatedSphere ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// topology
1296				DE_FALSE,														// primitiveRestartEnable
1297			};
1298			const VkVertexInputBindingDescription		vertexBinding0 =
1299			{
1300				0u,														// binding
1301				(deUint32)sizeof(tcu::Vec4),							// stride
1302				VK_VERTEX_INPUT_RATE_VERTEX,							// inputRate
1303			};
1304			const VkVertexInputAttributeDescription		vertexAttrib0 =
1305			{
1306				0u,														// location
1307				0u,														// binding
1308				VK_FORMAT_R32G32B32A32_SFLOAT,							// format
1309				0u,														// offset
1310			};
1311			const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams =
1312			{
1313				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// sType
1314				DE_NULL,													// pNext
1315				0u,															// flags
1316				1u,															// vertexBindingDescriptionCount
1317				&vertexBinding0,											// pVertexBindingDescriptions
1318				1u,															// vertexAttributeDescriptionCount
1319				&vertexAttrib0,												// pVertexAttributeDescriptions
1320			};
1321			const VkPipelineColorBlendAttachmentState	attBlendParams =
1322			{
1323				VK_FALSE,													// blendEnable
1324				VK_BLEND_FACTOR_ONE,										// srcColorBlendFactor
1325				VK_BLEND_FACTOR_ZERO,										// dstColorBlendFactor
1326				VK_BLEND_OP_ADD,											// colorBlendOp
1327				VK_BLEND_FACTOR_ONE,										// srcAlphaBlendFactor
1328				VK_BLEND_FACTOR_ZERO,										// dstAlphaBlendFactor
1329				VK_BLEND_OP_ADD,											// alphaBlendOp
1330				(VK_COLOR_COMPONENT_R_BIT |
1331				 VK_COLOR_COMPONENT_G_BIT |
1332				 VK_COLOR_COMPONENT_B_BIT |
1333				 VK_COLOR_COMPONENT_A_BIT),									// colorWriteMask
1334			};
1335			const VkPipelineColorBlendStateCreateInfo	blendParams =
1336			{
1337				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// sType
1338				DE_NULL,													// pNext
1339				0u,															// flags
1340				DE_FALSE,													// logicOpEnable
1341				VK_LOGIC_OP_COPY,											// logicOp
1342				1u,															// attachmentCount
1343				&attBlendParams,											// pAttachments
1344				{ 0.0f, 0.0f, 0.0f, 0.0f },									// blendConstants[4]
1345			};
1346
1347			const VkPipelineTessellationStateCreateInfo tessState =
1348			{
1349				VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	// sType
1350				DE_NULL,													// pNext
1351				0u,															// flags
1352				3u,															// patchControlPoints
1353			};
1354			const VkGraphicsPipelineCreateInfo		pipelineParams =
1355			{
1356				VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// sType
1357				DE_NULL,												// pNext
1358				0u,														// flags
1359				deUint32(shaderStageParams.size()),						// stageCount
1360				shaderStageParams.data(),								// pStages
1361				&vertexInputStateParams,								// pVertexInputState
1362				&inputAssemblyParams,									// pInputAssemblyState
1363				m_drawTessellatedSphere ? &tessState : DE_NULL,			// pTessellationState
1364				&viewportParams,										// pViewportState
1365				&rasterParams,											// pRasterizationState
1366				&multisampleParams,										// pMultisampleState
1367				&depthStencilParams,									// pDepthStencilState
1368				&blendParams,											// pColorBlendState
1369				(const VkPipelineDynamicStateCreateInfo*)DE_NULL,		// pDynamicState
1370				*pipelineLayout,										// layout
1371				*renderPass,											// renderPass
1372				0u,														// subpass
1373				DE_NULL,												// basePipelineHandle
1374				0u,														// basePipelineIndex
1375			};
1376			pipeline = createGraphicsPipeline(vk, *m_deviceGroup, DE_NULL, &pipelineParams);
1377		}
1378
1379		// Create Framebuffer
1380		{
1381			const VkImageViewCreateInfo				colorAttViewParams =
1382			{
1383				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// sType
1384				DE_NULL,										// pNext
1385				0u,												// flags
1386				*renderImage,									// image
1387				VK_IMAGE_VIEW_TYPE_2D,							// viewType
1388				colorFormat,									// format
1389				{
1390					VK_COMPONENT_SWIZZLE_R,
1391					VK_COMPONENT_SWIZZLE_G,
1392					VK_COMPONENT_SWIZZLE_B,
1393					VK_COMPONENT_SWIZZLE_A
1394				},												// components
1395				{
1396					VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
1397					0u,											// baseMipLevel
1398					1u,											// levelCount
1399					0u,											// baseArrayLayer
1400					1u,											// layerCount
1401				},												// subresourceRange
1402			};
1403			colorAttView = createImageView(vk, *m_deviceGroup, &colorAttViewParams);
1404
1405			const VkFramebufferCreateInfo			framebufferParams =
1406			{
1407				VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				// sType
1408				DE_NULL,												// pNext
1409				0u,														// flags
1410				*renderPass,											// renderPass
1411				1u,														// attachmentCount
1412				&*colorAttView,											// pAttachments
1413				renderSize.x(),											// width
1414				renderSize.y(),											// height
1415				1u,														// layers
1416			};
1417			framebuffer = createFramebuffer(vk, *m_deviceGroup, &framebufferParams);
1418		}
1419
1420		// Create Command buffer
1421		{
1422			const VkCommandPoolCreateInfo			cmdPoolParams =
1423			{
1424				VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType
1425				DE_NULL,													// pNext
1426				VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags
1427				queueFamilyIndex,											// queueFamilyIndex
1428			};
1429			cmdPool = createCommandPool(vk, *m_deviceGroup, &cmdPoolParams);
1430
1431			const VkCommandBufferAllocateInfo		cmdBufParams =
1432			{
1433				VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,			// sType
1434				DE_NULL,												// pNext
1435				*cmdPool,												// pool
1436				VK_COMMAND_BUFFER_LEVEL_PRIMARY,						// level
1437				1u,														// bufferCount
1438			};
1439			cmdBuffer = allocateCommandBuffer(vk, *m_deviceGroup, &cmdBufParams);
1440		}
1441
1442		// Begin recording
1443		VkCommandBufferBeginInfo				cmdBufBeginParams =
1444		{
1445			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// sType
1446			DE_NULL,												// pNext
1447			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// flags
1448			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1449		};
1450		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
1451
1452		// Prepare render target for rendering
1453		{
1454			const VkMemoryBarrier		vertFlushBarrier =
1455			{
1456				VK_STRUCTURE_TYPE_MEMORY_BARRIER,			// sType
1457				DE_NULL,									// pNext
1458				VK_ACCESS_HOST_WRITE_BIT,					// srcAccessMask
1459				VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		// dstAccessMask
1460			};
1461			const VkImageMemoryBarrier	colorAttBarrier =
1462			{
1463				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType
1464				DE_NULL,									// pNext
1465				0u,											// srcAccessMask
1466				(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1467				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),		// dstAccessMask
1468				VK_IMAGE_LAYOUT_UNDEFINED,					// oldLayout
1469				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// newLayout
1470				queueFamilyIndex,							// srcQueueFamilyIndex
1471				queueFamilyIndex,							// dstQueueFamilyIndex
1472				*renderImage,								// image
1473				{
1474					VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask
1475					0u,										// baseMipLevel
1476					1u,										// levelCount
1477					0u,										// baseArrayLayer
1478					1u,										// layerCount
1479				}											// subresourceRange
1480			};
1481			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier);
1482		}
1483
1484		// Update buffers
1485		{
1486			const VkBufferMemoryBarrier		stagingVertexBufferUpdateBarrier =
1487			{
1488				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1489				DE_NULL,									// const void*		pNext;
1490				VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1491				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1492				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1493				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1494				stagingVertexBuffer.get(),					// VkBuffer			buffer;
1495				0u,											// VkDeviceSize		offset;
1496				verticesSize								// VkDeviceSize		size;
1497			};
1498
1499			const VkBufferMemoryBarrier		vertexBufferUpdateBarrier =
1500			{
1501				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1502				DE_NULL,									// const void*		pNext;
1503				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1504				VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		// VkAccessFlags	dstAccessMask;
1505				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1506				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1507				vertexBuffer.get(),							// VkBuffer			buffer;
1508				0u,											// VkDeviceSize		offset;
1509				verticesSize								// VkDeviceSize		size;
1510			};
1511
1512			const VkBufferMemoryBarrier		stagingIndexBufferUpdateBarrier =
1513			{
1514				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1515				DE_NULL,									// const void*		pNext;
1516				VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1517				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1518				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1519				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1520				stagingIndexBuffer.get(),					// VkBuffer			buffer;
1521				0u,											// VkDeviceSize		offset;
1522				indicesSize									// VkDeviceSize		size;
1523			};
1524
1525			const VkBufferMemoryBarrier		indexBufferUpdateBarrier =
1526			{
1527				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1528				DE_NULL,									// const void*		pNext;
1529				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1530				VK_ACCESS_INDEX_READ_BIT,					// VkAccessFlags	dstAccessMask;
1531				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1532				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1533				indexBuffer.get(),							// VkBuffer			buffer;
1534				0u,											// VkDeviceSize		offset;
1535				indicesSize									// VkDeviceSize		size;
1536			};
1537
1538			const VkBufferMemoryBarrier		stagingUboBufferUpdateBarrier =
1539			{
1540				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1541				DE_NULL,									// const void*		pNext;
1542				VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1543				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1544				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1545				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1546				stagingUniformBuffer.get(),					// VkBuffer			buffer;
1547				0u,											// VkDeviceSize		offset;
1548				indicesSize									// VkDeviceSize		size;
1549			};
1550
1551			const VkBufferMemoryBarrier		uboUpdateBarrier =
1552			{
1553				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1554				DE_NULL,									// const void*		pNext;
1555				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1556				VK_ACCESS_UNIFORM_READ_BIT,					// VkAccessFlags	dstAccessMask;
1557				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1558				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1559				uniformBuffer.get(),						// VkBuffer			buffer;
1560				0u,											// VkDeviceSize		offset;
1561				sizeof(drawColor)							// VkDeviceSize		size;
1562			};
1563
1564
1565			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingVertexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1566			VkBufferCopy	vertexBufferCopy	= { 0u, 0u, verticesSize };
1567			vk.cmdCopyBuffer(*cmdBuffer, stagingVertexBuffer.get(), vertexBuffer.get(), 1u, &vertexBufferCopy);
1568			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &vertexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1569
1570			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingIndexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1571			VkBufferCopy	indexBufferCopy	= { 0u, 0u, indicesSize };
1572			vk.cmdCopyBuffer(*cmdBuffer, stagingIndexBuffer.get(), indexBuffer.get(), 1u, &indexBufferCopy);
1573			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &indexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1574
1575			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingUboBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1576			VkBufferCopy	uboBufferCopy	= { 0u, 0u, sizeof(drawColor) };
1577			vk.cmdCopyBuffer(*cmdBuffer, stagingUniformBuffer.get(), uniformBuffer.get(), 1u, &uboBufferCopy);
1578			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &uboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1579
1580			if (m_drawTessellatedSphere)
1581			{
1582				const VkBufferMemoryBarrier		stagingsboUpdateBarrier =
1583				{
1584					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1585					DE_NULL,									// const void*		pNext;
1586					VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1587					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1588					VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1589					VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1590					stagingSboBuffer.get(),						// VkBuffer			buffer;
1591					0u,											// VkDeviceSize		offset;
1592					sizeof(tessLevel)							// VkDeviceSize		size;
1593				};
1594
1595				const VkBufferMemoryBarrier		sboUpdateBarrier =
1596				{
1597					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1598					DE_NULL,									// const void*		pNext;
1599					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1600					VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags	dstAccessMask;
1601					VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1602					VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1603					sboBuffer.get(),							// VkBuffer			buffer;
1604					0u,											// VkDeviceSize		offset;
1605					sizeof(tessLevel)							// VkDeviceSize		size;
1606				};
1607
1608				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingsboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1609				VkBufferCopy	sboBufferCopy	= { 0u, 0u, sizeof(tessLevel) };
1610				vk.cmdCopyBuffer(*cmdBuffer, stagingSboBuffer.get(), sboBuffer.get(), 1u, &sboBufferCopy);
1611				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &sboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1612			}
1613
1614			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1615			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
1616			{
1617				const VkDeviceSize bindingOffset = 0;
1618				vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
1619				vk.cmdBindIndexBuffer(*cmdBuffer, *indexBuffer, 0, VK_INDEX_TYPE_UINT32);
1620			}
1621		}
1622
1623		// Begin renderpass
1624		{
1625			const VkClearValue clearValue = makeClearValueColorF32(
1626				clearColor[0],
1627				clearColor[1],
1628				clearColor[2],
1629				clearColor[3]);
1630
1631			VkRect2D zeroRect = { { 0, 0, },{ 0, 0, } };
1632			vector<VkRect2D> renderAreas;
1633			for (deUint32 i = 0; i < m_physicalDeviceCount; i++)
1634				renderAreas.push_back(zeroRect);
1635
1636			// Render completely if there is only 1 device
1637			if (m_physicalDeviceCount == 1u)
1638			{
1639				renderAreas[0].extent.width = (deInt32)renderSize.x();
1640				renderAreas[0].extent.height = (deInt32)renderSize.y();
1641			}
1642			else
1643			{
1644				// Split into 2 vertical halves
1645				renderAreas[firstDeviceID].extent.width		= (deInt32)renderSize.x() / 2;
1646				renderAreas[firstDeviceID].extent.height	= (deInt32)renderSize.y();
1647				renderAreas[secondDeviceID]					= renderAreas[firstDeviceID];
1648				renderAreas[secondDeviceID].offset.x		= (deInt32)renderSize.x() / 2;
1649			}
1650
1651			const VkDeviceGroupRenderPassBeginInfo deviceGroupRPBeginInfo =
1652			{
1653				VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
1654				DE_NULL,
1655				(deUint32)((1 << m_physicalDeviceCount) - 1),
1656				m_physicalDeviceCount,
1657				&renderAreas[0]
1658			};
1659
1660			const VkRenderPassBeginInfo	passBeginParams =
1661			{
1662				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// sType
1663				(m_testMode & TEST_MODE_SFR) ? &deviceGroupRPBeginInfo : DE_NULL,	// pNext
1664				*renderPass,														// renderPass
1665				*framebuffer,														// framebuffer
1666				{
1667					{ 0, 0 },
1668					{ renderSize.x(), renderSize.y() }
1669				},																// renderArea
1670				1u,																// clearValueCount
1671				&clearValue,													// pClearValues
1672			};
1673			vk.cmdBeginRenderPass(*cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
1674		}
1675
1676		// Draw
1677		if (m_testMode & TEST_MODE_AFR)
1678		{
1679			vk.cmdSetDeviceMask(*cmdBuffer, 1 << secondDeviceID);
1680			vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1u, 0, 0, 0);
1681
1682		}
1683		else
1684		{
1685			vk.cmdSetDeviceMask(*cmdBuffer, ((1 << firstDeviceID) | (1 << secondDeviceID)));
1686			vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1u, 0, 0, 0);
1687		}
1688		vk.cmdEndRenderPass(*cmdBuffer);
1689
1690		// Change image layout for copy
1691		{
1692			const VkImageMemoryBarrier	renderFinishBarrier =
1693			{
1694				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType
1695				DE_NULL,									// pNext
1696				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// outputMask
1697				VK_ACCESS_TRANSFER_READ_BIT,				// inputMask
1698				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// oldLayout
1699				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// newLayout
1700				queueFamilyIndex,							// srcQueueFamilyIndex
1701				queueFamilyIndex,							// dstQueueFamilyIndex
1702				*renderImage,								// image
1703				{
1704					VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask
1705					0u,										// baseMipLevel
1706					1u,										// mipLevels
1707					0u,										// baseArraySlice
1708					1u,										// arraySize
1709				}											// subresourceRange
1710			};
1711			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier);
1712		}
1713
1714		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1715
1716		// Submit & wait for completion
1717		{
1718			const deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
1719			deviceGroupSubmitInfo.commandBufferCount = 1;
1720			deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
1721			SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
1722		}
1723
1724		// Copy image from secondDeviceID in case of AFR and SFR(only if Peer memory as copy source is not allowed)
1725		if ((m_physicalDeviceCount > 1) && ((m_testMode & TEST_MODE_AFR) || (!isPeerMemAsCopySrcAllowed)))
1726		{
1727			Move<VkImage>			peerImage;
1728
1729			// Create and bind peer image
1730			{
1731				const VkImageCreateInfo					peerImageParams =
1732				{
1733					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// sType
1734					DE_NULL,																// pNext
1735					VK_IMAGE_CREATE_ALIAS_BIT,												// flags
1736					VK_IMAGE_TYPE_2D,														// imageType
1737					colorFormat,															// format
1738					{ renderSize.x(), renderSize.y(), 1 },									// extent
1739					1u,																		// mipLevels
1740					1u,																		// arraySize
1741					VK_SAMPLE_COUNT_1_BIT,													// samples
1742					VK_IMAGE_TILING_OPTIMAL,												// tiling
1743					imageUsageFlag,															// usage
1744					VK_SHARING_MODE_EXCLUSIVE,												// sharingMode
1745					1u,																		// queueFamilyIndexCount
1746					&queueFamilyIndex,														// pQueueFamilyIndices
1747					VK_IMAGE_LAYOUT_UNDEFINED,												// initialLayout
1748				};
1749				peerImage = createImage(vk, *m_deviceGroup, &peerImageParams);
1750
1751				VkBindImageMemoryDeviceGroupInfo	devGroupBindInfo =
1752				{
1753					VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,		// sType
1754					DE_NULL,													// pNext
1755					m_physicalDeviceCount,										// deviceIndexCount
1756					&deviceIndices[0],											// pDeviceIndices
1757					0u,															// SFRRectCount
1758					DE_NULL,													// pSFRRects
1759				};
1760
1761				VkBindImageMemoryInfo				bindInfo =
1762				{
1763					VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,					// sType
1764					&devGroupBindInfo,											// pNext
1765					peerImage.get(),											// image
1766					imageMemory.get(),											// memory
1767					0u,															// memoryOffset
1768				};
1769				VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
1770			}
1771
1772			// Copy peer image (only needed in SFR case when peer memory as copy source is not allowed)
1773			{
1774				// Change layout on firstDeviceID
1775				{
1776					const VkImageMemoryBarrier	preCopyBarrier =
1777					{
1778						VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		 sType;
1779						DE_NULL,									// const void*			 pNext;
1780						0,											// VkAccessFlags		 srcAccessMask;
1781						VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags		 dstAccessMask;
1782						VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		 oldLayout;
1783						VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout		 newLayout;
1784						VK_QUEUE_FAMILY_IGNORED,					// deUint32				 srcQueueFamilyIndex;
1785						VK_QUEUE_FAMILY_IGNORED,					// deUint32				 dstQueueFamilyIndex;
1786						*renderImage,								// VkImage				 image;
1787						{											// VkImageSubresourceRange subresourceRange;
1788							VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	 aspectMask;
1789							0u,										// deUint32				 baseMipLevel;
1790							1u,										// deUint32				 mipLevels;
1791							0u,										// deUint32				 baseArraySlice;
1792							1u										// deUint32				 arraySize;
1793						}
1794					};
1795
1796					VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
1797					vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
1798					vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &preCopyBarrier);
1799					VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1800
1801					const deUint32 deviceMask = 1 << firstDeviceID;
1802					deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
1803					SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
1804				}
1805
1806				// Copy Image from secondDeviceID to firstDeviceID
1807				{
1808					// AFR: Copy entire image from secondDeviceID
1809					// SFR: Copy the right half of image from secondDeviceID to firstDeviceID, so that the copy
1810					// to a buffer below (for checking) does not require VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT
1811					deInt32 imageOffsetX = (m_testMode & TEST_MODE_AFR) ? 0 : renderSize.x() / 2;
1812					deUint32 imageExtentX = (m_testMode & TEST_MODE_AFR) ? (deUint32)renderSize.x() : (deUint32)renderSize.x() / 2;
1813
1814					const VkImageCopy	imageCopy =
1815					{
1816						{
1817							VK_IMAGE_ASPECT_COLOR_BIT,
1818							0, // mipLevel
1819							0, // arrayLayer
1820							1  // layerCount
1821						},
1822						{ imageOffsetX, 0, 0 },
1823						{
1824							VK_IMAGE_ASPECT_COLOR_BIT,
1825							0, // mipLevel
1826							0, // arrayLayer
1827							1  // layerCount
1828						},
1829						{ imageOffsetX, 0, 0 },
1830						{
1831							imageExtentX,
1832							(deUint32)renderSize.y(),
1833							1u
1834						}
1835					};
1836
1837					VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
1838					vk.cmdSetDeviceMask(*cmdBuffer, 1 << secondDeviceID);
1839					vk.cmdCopyImage(*cmdBuffer, *renderImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *peerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
1840					VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1841
1842					const deUint32 deviceMask = 1 << secondDeviceID;
1843					deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
1844					SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
1845				}
1846
1847				// Change layout back on firstDeviceID
1848				{
1849					const VkImageMemoryBarrier	postCopyBarrier =
1850					{
1851						VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1852						DE_NULL,									// const void*				pNext;
1853						VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1854						VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1855						VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1856						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
1857						VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1858						VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1859						*renderImage,								// VkImage					image;
1860						{											// VkImageSubresourceRange	subresourceRange;
1861							VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags		aspectMask;
1862							0u,										// deUint32					baseMipLevel;
1863							1u,										// deUint32					mipLevels;
1864							0u,										// deUint32					baseArraySlice;
1865							1u										// deUint32					arraySize;
1866						}
1867					};
1868
1869					VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
1870					vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
1871					vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postCopyBarrier);
1872					VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1873
1874					const deUint32 deviceMask = 1 << firstDeviceID;
1875					deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
1876					SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
1877				}
1878			}
1879		}
1880
1881		// copy image to read buffer for checking
1882		{
1883			const VkDeviceSize			imageSizeBytes = (VkDeviceSize)(sizeof(deUint32) * renderSize.x() * renderSize.y());
1884			const VkBufferCreateInfo	readImageBufferParams =
1885			{
1886				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// sType
1887				DE_NULL,									// pNext
1888				(VkBufferCreateFlags)0u,					// flags
1889				imageSizeBytes,								// size
1890				VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
1891				VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
1892				1u,											// queueFamilyIndexCount
1893				&queueFamilyIndex,							// pQueueFamilyIndices
1894			};
1895			const Unique<VkBuffer>		readImageBuffer(createBuffer(vk, *m_deviceGroup, &readImageBufferParams));
1896			const UniquePtr<Allocation>	readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *readImageBuffer), MemoryRequirement::HostVisible));
1897			VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1898
1899			VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
1900
1901			// Copy image to buffer
1902			{
1903				const VkBufferImageCopy	copyParams =
1904				{
1905					(VkDeviceSize)0u,						// bufferOffset
1906					renderSize.x(),							// bufferRowLength
1907					renderSize.y(),							// bufferImageHeight
1908					{
1909						VK_IMAGE_ASPECT_COLOR_BIT,			// aspectMask
1910						0u,									// mipLevel
1911						0u,									// baseArrayLayer
1912						1u,									// layerCount
1913					},										// imageSubresource
1914					{ 0, 0, 0 },							// imageOffset
1915					{
1916						renderSize.x(),
1917						renderSize.y(),
1918						1u
1919					}										// imageExtent
1920				};
1921
1922				// Use a diffferent binding in SFR when peer memory as copy source is not allowed
1923				vk.cmdCopyImageToBuffer(*cmdBuffer, isPeerMemAsCopySrcAllowed ? *renderImage : *readImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1924
1925				const VkBufferMemoryBarrier	copyFinishBarrier =
1926				{
1927					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// sType
1928					DE_NULL,									// pNext
1929					VK_ACCESS_TRANSFER_WRITE_BIT,				// srcAccessMask
1930					VK_ACCESS_HOST_READ_BIT,					// dstAccessMask
1931					queueFamilyIndex,							// srcQueueFamilyIndex
1932					queueFamilyIndex,							// dstQueueFamilyIndex
1933					*readImageBuffer,							// buffer
1934					0u,											// offset
1935					imageSizeBytes								// size
1936				};
1937				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &copyFinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1938			}
1939			VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1940
1941			// Submit & wait for completion
1942			{
1943				const deUint32 deviceMask = 1 << firstDeviceID;
1944				deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
1945				SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
1946			}
1947
1948			// Read results and check against reference image
1949			if (m_drawTessellatedSphere)
1950			{
1951				const tcu::TextureFormat			tcuFormat = vk::mapVkFormat(colorFormat);
1952				const VkMappedMemoryRange			range =
1953				{
1954					VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
1955					DE_NULL,								// pNext
1956					readImageBufferMemory->getMemory(),		// memory
1957					0,										// offset
1958					imageSizeBytes,							// size
1959				};
1960				const tcu::ConstPixelBufferAccess	resultAccess(tcuFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1961				VK_CHECK(vk.invalidateMappedMemoryRanges(*m_deviceGroup, 1u, &range));
1962
1963				tcu::TextureLevel referenceImage;
1964				string refImage = m_fillModeNonSolid ? "vulkan/data/device_group/sphere.png" : "vulkan/data/device_group/spherefilled.png";
1965				tcu::ImageIO::loadPNG(referenceImage, m_context.getTestContext().getArchive(),  refImage.c_str());
1966				iterateResultSuccess = tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
1967										referenceImage.getAccess(), resultAccess, 0.001f, tcu::COMPARE_LOG_RESULT);
1968			}
1969			else
1970			{
1971				const tcu::TextureFormat			tcuFormat = vk::mapVkFormat(colorFormat);
1972				const VkMappedMemoryRange			range =
1973				{
1974					VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType
1975					DE_NULL,								// pNext
1976					readImageBufferMemory->getMemory(),		// memory
1977					0,										// offset
1978					imageSizeBytes,							// size
1979				};
1980				const tcu::ConstPixelBufferAccess	resultAccess(tcuFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1981				VK_CHECK(vk.invalidateMappedMemoryRanges(*m_deviceGroup, 1u, &range));
1982
1983				// Render reference and compare
1984				{
1985					tcu::TextureLevel	refImage(tcuFormat, (deInt32)renderSize.x(), (deInt32)renderSize.y());
1986					const tcu::UVec4	threshold(0u);
1987					const tcu::IVec3	posDeviation(1, 1, 0);
1988
1989					tcu::clear(refImage.getAccess(), clearColor);
1990					renderReferenceTriangle(refImage.getAccess(), triVertices);
1991
1992					iterateResultSuccess = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1993						"ComparisonResult",
1994						"Image comparison result",
1995						refImage.getAccess(),
1996						resultAccess,
1997						threshold,
1998						posDeviation,
1999						false,
2000						tcu::COMPARE_LOG_RESULT);
2001				}
2002			}
2003		}
2004
2005		if (!iterateResultSuccess)
2006			return tcu::TestStatus::fail("Image comparison failed");
2007	}
2008
2009	return tcu::TestStatus(QP_TEST_RESULT_PASS, "Device group verification passed");
2010}
2011
2012template<class Instance>
2013class DeviceGroupTestCase : public TestCase
2014{
2015public:
2016	DeviceGroupTestCase (tcu::TestContext& context,
2017						const char*	name,
2018						const char*	description,
2019						deUint32 mode)
2020	: TestCase(context, name, description)
2021	, m_testMode		(mode)
2022	{}
2023
2024private:
2025
2026	deUint32			m_testMode;
2027
2028	TestInstance*		createInstance	(Context& context) const
2029	{
2030		return new Instance(context, m_testMode);
2031	}
2032
2033	void				initPrograms	(vk::SourceCollections& programCollection) const
2034	{
2035		programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
2036			"layout(location = 0) in vec4 in_Position;\n"
2037			"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
2038			"void main() {\n"
2039			"	gl_Position	= in_Position;\n"
2040			"	gl_PointSize = 1.0;\n"
2041			"}\n");
2042
2043		if (m_testMode & TEST_MODE_TESSELLATION)
2044		{
2045			programCollection.glslSources.add("tesc") << glu::TessellationControlSource("#version 450\n"
2046				"#extension GL_EXT_tessellation_shader : require\n"
2047				"layout(vertices=3) out;\n"
2048				"layout(set=0, binding=1) buffer tessLevel { \n"
2049				"  float tessLvl;\n"
2050				"};\n"
2051				"void main()\n"
2052				"{\n"
2053				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2054				"  if (gl_InvocationID == 0) {\n"
2055				"    for (int i = 0; i < 4; i++)\n"
2056				"      gl_TessLevelOuter[i] = tessLvl;\n"
2057				"    for (int i = 0; i < 2; i++)\n"
2058				"      gl_TessLevelInner[i] = tessLvl;\n"
2059				"  }\n"
2060				"}\n");
2061
2062			programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource("#version 450\n"
2063				"#extension GL_EXT_tessellation_shader : require\n"
2064				"layout(triangles) in;\n"
2065				"layout(equal_spacing) in;\n"
2066				"layout(ccw) in;\n"
2067				"void main()\n"
2068				"{\n"
2069				"  vec4 pos = vec4(0, 0, 0, 0);\n"
2070				"  vec3 tessCoord = gl_TessCoord.xyz;\n"
2071				"  pos += tessCoord.z * gl_in[0].gl_Position;\n"
2072				"  pos += tessCoord.x * gl_in[1].gl_Position;\n"
2073				"  pos += tessCoord.y * gl_in[2].gl_Position;\n"
2074				"  vec3 sign = sign(pos.xyz);\n"
2075				"  pos.xyz = 0.785398 - abs(pos.xyz) * 1.5707963;\n"
2076				"  pos.xyz = (1 - tan(pos.xyz))/2.0;\n"
2077				"  pos.xyz = (sign * pos.xyz) / length(pos.xyz);\n"
2078				"  gl_Position = pos;\n"
2079				"}\n");
2080		}
2081
2082		programCollection.glslSources.add("frag") << glu::FragmentSource("#version 430\n"
2083			"layout(location = 0) out vec4 out_FragColor;\n"
2084			"layout(std140, set=0, binding=0) uniform bufferData { \n"
2085			"	vec4 color;\n"
2086			"};\n"
2087			"void main()\n"
2088			"{\n"
2089			"	out_FragColor = color;\n"
2090			"}\n");
2091	}
2092};
2093
2094} //anonymous
2095
2096class DeviceGroupTestRendering : public tcu::TestCaseGroup
2097{
2098public:
2099								DeviceGroupTestRendering	(tcu::TestContext& testCtx);
2100								~DeviceGroupTestRendering	(void) {}
2101	void						init(void);
2102
2103private:
2104								DeviceGroupTestRendering	(const DeviceGroupTestRendering& other);
2105	DeviceGroupTestRendering&	operator=					(const DeviceGroupTestRendering& other);
2106};
2107
2108DeviceGroupTestRendering::DeviceGroupTestRendering (tcu::TestContext& testCtx)
2109	: TestCaseGroup (testCtx, "device_group", "Testing device group test cases")
2110{
2111	// Left blank on purpose
2112}
2113
2114void DeviceGroupTestRendering::init (void)
2115{
2116	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr",							"Test split frame rendering",														TEST_MODE_SFR));
2117	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_sys",						"Test split frame rendering with render target in host memory",						TEST_MODE_SFR | TEST_MODE_HOSTMEMORY));
2118	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_dedicated",				"Test split frame rendering with dedicated memory allocations",						TEST_MODE_SFR | TEST_MODE_DEDICATED));
2119	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_dedicated_peer",			"Test split frame rendering with dedicated memory allocations and peer fetching",	TEST_MODE_SFR | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2120
2121	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr",							"Test alternate frame rendering",													TEST_MODE_AFR));
2122	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_sys",						"Test split frame rendering with render target in host memory",						TEST_MODE_AFR | TEST_MODE_HOSTMEMORY));
2123	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_dedicated",				"Test split frame rendering with dedicated memory allocations",						TEST_MODE_AFR | TEST_MODE_DEDICATED));
2124	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_dedicated_peer",			"Test split frame rendering with dedicated memory allocations and peer fetching",	TEST_MODE_AFR | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2125
2126	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_tessellated",				"Test split frame rendering with tessellated sphere",								TEST_MODE_SFR | TEST_MODE_TESSELLATION | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2127	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_tessellated_linefill",	"Test split frame rendering with tessellated sphere with line segments",			TEST_MODE_SFR | TEST_MODE_TESSELLATION | TEST_MODE_LINEFILL  | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2128	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_tessellated",				"Test alternate frame rendering with tesselated sphere",							TEST_MODE_AFR | TEST_MODE_TESSELLATION | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2129	addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_tessellated_linefill",	"Test alternate frame rendering with tesselated sphere with line segments",			TEST_MODE_AFR | TEST_MODE_TESSELLATION | TEST_MODE_LINEFILL  | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
2130}
2131
2132tcu::TestCaseGroup* createTests(tcu::TestContext& testCtx)
2133{
2134	return new DeviceGroupTestRendering(testCtx);
2135}
2136}	// DeviceGroup
2137}	// vkt
2138