Home | History | Annotate | Download | only in device_group
      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 
     54 namespace vkt
     55 {
     56 namespace DeviceGroup
     57 {
     58 namespace
     59 {
     60 
     61 using namespace vk;
     62 using std::string;
     63 using std::vector;
     64 using tcu::TestLog;
     65 using de::UniquePtr;
     66 
     67 //Device group test modes
     68 enum 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 
     79 class RefVertexShader : public rr::VertexShader
     80 {
     81 public:
     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 
    100 class RefFragmentShader : public rr::FragmentShader
    101 {
    102 public:
    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 
    123 void 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 
    144 class DeviceGroupTestInstance : public TestInstance
    145 {
    146 public:
    147 	DeviceGroupTestInstance(Context& context, deUint32 mode);
    148 	~DeviceGroupTestInstance(void) {}
    149 private:
    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 
    171 DeviceGroupTestInstance::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 
    186 deUint32 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 
    198 bool 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 
    210 void 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 
    245 void 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 
    354 void 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 
    381 tcu::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 
   2012 template<class Instance>
   2013 class DeviceGroupTestCase : public TestCase
   2014 {
   2015 public:
   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 
   2024 private:
   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 
   2096 class DeviceGroupTestRendering : public tcu::TestCaseGroup
   2097 {
   2098 public:
   2099 								DeviceGroupTestRendering	(tcu::TestContext& testCtx);
   2100 								~DeviceGroupTestRendering	(void) {}
   2101 	void						init(void);
   2102 
   2103 private:
   2104 								DeviceGroupTestRendering	(const DeviceGroupTestRendering& other);
   2105 	DeviceGroupTestRendering&	operator=					(const DeviceGroupTestRendering& other);
   2106 };
   2107 
   2108 DeviceGroupTestRendering::DeviceGroupTestRendering (tcu::TestContext& testCtx)
   2109 	: TestCaseGroup (testCtx, "device_group", "Testing device group test cases")
   2110 {
   2111 	// Left blank on purpose
   2112 }
   2113 
   2114 void 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 
   2132 tcu::TestCaseGroup* createTests(tcu::TestContext& testCtx)
   2133 {
   2134 	return new DeviceGroupTestRendering(testCtx);
   2135 }
   2136 }	// DeviceGroup
   2137 }	// vkt
   2138