Home | History | Annotate | Download | only in vulkan
      1 /*-------------------------------------------------------------------------
      2  * Vulkan CTS Framework
      3  * --------------------
      4  *
      5  * Copyright (c) 2016 The Khronos Group Inc.
      6  * Copyright (c) 2016 Google Inc.
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Utility for generating simple work
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktDrawUtil.hpp"
     26 #include "rrMultisamplePixelBufferAccess.hpp"
     27 #include "vkBufferWithMemory.hpp"
     28 #include "vkImageWithMemory.hpp"
     29 #include "vkTypeUtil.hpp"
     30 #include "rrRenderer.hpp"
     31 #include "rrRenderState.hpp"
     32 #include "rrPrimitiveTypes.hpp"
     33 #include "tcuTextureUtil.hpp"
     34 #include "deArrayUtil.hpp"
     35 #include "vkBuilderUtil.hpp"
     36 #include "tcuTestLog.hpp"
     37 
     38 namespace vkt
     39 {
     40 namespace drawutil
     41 {
     42 
     43 using namespace de;
     44 using namespace tcu;
     45 using namespace vk;
     46 
     47 static VkCompareOp mapCompareOp (rr::TestFunc compareFunc)
     48 {
     49 	switch (compareFunc)
     50 	{
     51 		case rr::TESTFUNC_NEVER:				return VK_COMPARE_OP_NEVER;
     52 		case rr::TESTFUNC_LESS:					return VK_COMPARE_OP_LESS;
     53 		case rr::TESTFUNC_EQUAL:				return VK_COMPARE_OP_EQUAL;
     54 		case rr::TESTFUNC_LEQUAL:				return VK_COMPARE_OP_LESS_OR_EQUAL;
     55 		case rr::TESTFUNC_GREATER:				return VK_COMPARE_OP_GREATER;
     56 		case rr::TESTFUNC_NOTEQUAL:				return VK_COMPARE_OP_NOT_EQUAL;
     57 		case rr::TESTFUNC_GEQUAL:				return VK_COMPARE_OP_GREATER_OR_EQUAL;
     58 		case rr::TESTFUNC_ALWAYS:				return VK_COMPARE_OP_ALWAYS;
     59 		default:
     60 			DE_ASSERT(false);
     61 	}
     62 	return VK_COMPARE_OP_LAST;
     63 }
     64 
     65 rr::PrimitiveType mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology& primitiveTopology)
     66 {
     67 	static const rr::PrimitiveType primitiveTypeTable[] =
     68 	{
     69 		rr::PRIMITIVETYPE_POINTS,
     70 		rr::PRIMITIVETYPE_LINES,
     71 		rr::PRIMITIVETYPE_LINE_STRIP,
     72 		rr::PRIMITIVETYPE_TRIANGLES,
     73 		rr::PRIMITIVETYPE_TRIANGLE_STRIP,
     74 		rr::PRIMITIVETYPE_TRIANGLE_FAN,
     75 		rr::PRIMITIVETYPE_LINES_ADJACENCY,
     76 		rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY,
     77 		rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY,
     78 		rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY
     79 	};
     80 
     81 	return de::getSizedArrayElement<vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST>(primitiveTypeTable, primitiveTopology);
     82 }
     83 
     84 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
     85 										 const VkBufferUsageFlags	usage)
     86 {
     87 	const VkBufferCreateInfo bufferCreateInfo =
     88 	{
     89 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
     90 		DE_NULL,								// const void*			pNext;
     91 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
     92 		bufferSize,								// VkDeviceSize			size;
     93 		usage,									// VkBufferUsageFlags	usage;
     94 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
     95 		0u,										// deUint32				queueFamilyIndexCount;
     96 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
     97 	};
     98 	return bufferCreateInfo;
     99 }
    100 
    101 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
    102 											   const VkAccessFlags	dstAccessMask,
    103 											   const VkBuffer		buffer,
    104 											   const VkDeviceSize	offset,
    105 											   const VkDeviceSize	bufferSizeBytes)
    106 {
    107 	const VkBufferMemoryBarrier barrier =
    108 	{
    109 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
    110 		DE_NULL,									// const void*		pNext;
    111 		srcAccessMask,								// VkAccessFlags	srcAccessMask;
    112 		dstAccessMask,								// VkAccessFlags	dstAccessMask;
    113 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
    114 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
    115 		buffer,										// VkBuffer			buffer;
    116 		offset,										// VkDeviceSize		offset;
    117 		bufferSizeBytes,							// VkDeviceSize		size;
    118 	};
    119 	return barrier;
    120 }
    121 
    122 VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
    123 											 const VkAccessFlags			dstAccessMask,
    124 											 const VkImageLayout			oldLayout,
    125 											 const VkImageLayout			newLayout,
    126 											 const VkImage					image,
    127 											 const VkImageSubresourceRange	subresourceRange)
    128 {
    129 	const VkImageMemoryBarrier barrier =
    130 	{
    131 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
    132 		DE_NULL,										// const void*				pNext;
    133 		srcAccessMask,									// VkAccessFlags			outputMask;
    134 		dstAccessMask,									// VkAccessFlags			inputMask;
    135 		oldLayout,										// VkImageLayout			oldLayout;
    136 		newLayout,										// VkImageLayout			newLayout;
    137 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
    138 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
    139 		image,											// VkImage					image;
    140 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    141 	};
    142 	return barrier;
    143 }
    144 
    145 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
    146 {
    147 	const VkCommandPoolCreateInfo info =
    148 	{
    149 		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
    150 		DE_NULL,											// const void*				pNext;
    151 		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
    152 		queueFamilyIndex,									// deUint32					queueFamilyIndex;
    153 	};
    154 	return createCommandPool(vk, device, &info);
    155 }
    156 
    157 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
    158 {
    159 	const VkCommandBufferAllocateInfo info =
    160 	{
    161 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
    162 		DE_NULL,											// const void*			pNext;
    163 		commandPool,										// VkCommandPool		commandPool;
    164 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
    165 		1u,													// deUint32				commandBufferCount;
    166 	};
    167 	return allocateCommandBuffer(vk, device, &info);
    168 }
    169 
    170 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
    171 										 const VkDevice					device,
    172 										 const VkDescriptorPool			descriptorPool,
    173 										 const VkDescriptorSetLayout	setLayout)
    174 {
    175 	const VkDescriptorSetAllocateInfo info =
    176 	{
    177 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    178 		DE_NULL,											// const void*					pNext;
    179 		descriptorPool,										// VkDescriptorPool				descriptorPool;
    180 		1u,													// deUint32						descriptorSetCount;
    181 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
    182 	};
    183 	return allocateDescriptorSet(vk, device, &info);
    184 }
    185 
    186 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
    187 										   const VkDevice				device,
    188 										   const VkDescriptorSetLayout	descriptorSetLayout)
    189 {
    190 	const VkPipelineLayoutCreateInfo info =
    191 	{
    192 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    193 		DE_NULL,											// const void*					pNext;
    194 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
    195 		1u,													// deUint32						setLayoutCount;
    196 		&descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
    197 		0u,													// deUint32						pushConstantRangeCount;
    198 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
    199 	};
    200 	return createPipelineLayout(vk, device, &info);
    201 }
    202 
    203 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&		vk,
    204 															 const VkDevice				device)
    205 {
    206 	const VkPipelineLayoutCreateInfo info =
    207 	{
    208 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    209 		DE_NULL,											// const void*					pNext;
    210 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
    211 		0u,													// deUint32						setLayoutCount;
    212 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
    213 		0u,													// deUint32						pushConstantRangeCount;
    214 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
    215 	};
    216 	return createPipelineLayout(vk, device, &info);
    217 }
    218 
    219 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
    220 								 const VkDevice					device,
    221 								 const VkImage					image,
    222 								 const VkImageViewType			viewType,
    223 								 const VkFormat					format,
    224 								 const VkImageSubresourceRange	subresourceRange)
    225 {
    226 	const VkImageViewCreateInfo imageViewParams =
    227 	{
    228 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    229 		DE_NULL,										// const void*				pNext;
    230 		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
    231 		image,											// VkImage					image;
    232 		viewType,										// VkImageViewType			viewType;
    233 		format,											// VkFormat					format;
    234 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
    235 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    236 	};
    237 	return createImageView(vk, device, &imageViewParams);
    238 }
    239 
    240 VkBufferImageCopy makeBufferImageCopy (const VkImageSubresourceLayers	subresourceLayers,
    241 									   const VkExtent3D					extent)
    242 {
    243 	const VkBufferImageCopy copyParams =
    244 	{
    245 		0ull,										//	VkDeviceSize				bufferOffset;
    246 		0u,											//	deUint32					bufferRowLength;
    247 		0u,											//	deUint32					bufferImageHeight;
    248 		subresourceLayers,							//	VkImageSubresourceLayers	imageSubresource;
    249 		makeOffset3D(0, 0, 0),						//	VkOffset3D					imageOffset;
    250 		extent,										//	VkExtent3D					imageExtent;
    251 	};
    252 	return copyParams;
    253 }
    254 
    255 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    256 {
    257 	const VkCommandBufferBeginInfo info =
    258 	{
    259 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType							sType;
    260 		DE_NULL,										// const void*								pNext;
    261 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags				flags;
    262 		DE_NULL,										// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
    263 	};
    264 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
    265 }
    266 
    267 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    268 {
    269 	VK_CHECK(vk.endCommandBuffer(commandBuffer));
    270 }
    271 
    272 void submitCommandsAndWait (const DeviceInterface&	vk,
    273 							const VkDevice			device,
    274 							const VkQueue			queue,
    275 							const VkCommandBuffer	commandBuffer)
    276 {
    277 	const VkFenceCreateInfo fenceInfo =
    278 	{
    279 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    280 		DE_NULL,								// const void*			pNext;
    281 		(VkFenceCreateFlags)0,					// VkFenceCreateFlags	flags;
    282 	};
    283 	const Unique<VkFence> fence(createFence(vk, device, &fenceInfo));
    284 
    285 	const VkSubmitInfo submitInfo =
    286 	{
    287 		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType					sType;
    288 		DE_NULL,							// const void*						pNext;
    289 		0u,									// uint32_t							waitSemaphoreCount;
    290 		DE_NULL,							// const VkSemaphore*				pWaitSemaphores;
    291 		DE_NULL,							// const VkPipelineStageFlags*		pWaitDstStageMask;
    292 		1u,									// uint32_t							commandBufferCount;
    293 		&commandBuffer,						// const VkCommandBuffer*			pCommandBuffers;
    294 		0u,									// uint32_t							signalSemaphoreCount;
    295 		DE_NULL,							// const VkSemaphore*				pSignalSemaphores;
    296 	};
    297 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
    298 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
    299 }
    300 
    301 std::string getPrimitiveTopologyShortName (const VkPrimitiveTopology topology)
    302 {
    303 	std::string name(getPrimitiveTopologyName(topology));
    304 	return de::toLower(name.substr(22));
    305 }
    306 
    307 DrawState::DrawState(const vk::VkPrimitiveTopology topology_, deUint32 renderWidth_, deUint32 renderHeight_)
    308 	: topology				(topology_)
    309 	, colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
    310 	, renderSize			(tcu::UVec2(renderWidth_, renderHeight_))
    311 	, depthClampEnable		(false)
    312 	, depthTestEnable		(false)
    313 	, depthWriteEnable		(false)
    314 	, compareOp				(rr::TESTFUNC_LESS)
    315 	, depthBoundsTestEnable	(false)
    316 	, blendEnable			(false)
    317 	, lineWidth				(1.0)
    318 	, numPatchControlPoints	(0)
    319 	, numSamples			(VK_SAMPLE_COUNT_1_BIT)
    320 	, sampleShadingEnable	(false)
    321 {
    322 	DE_ASSERT(renderSize.x() != 0 && renderSize.y() != 0);
    323 }
    324 
    325 ReferenceDrawContext::~ReferenceDrawContext (void)
    326 {
    327 }
    328 
    329 void ReferenceDrawContext::draw (void)
    330 {
    331 	m_refImage.setStorage(vk::mapVkFormat(m_drawState.colorFormat), m_drawState.renderSize.x(), m_drawState.renderSize.y());
    332 	tcu::clear(m_refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    333 
    334 	{
    335 		const rr::Program						program(&m_vertexShader, &m_fragmentShader);
    336 		const rr::MultisamplePixelBufferAccess	referenceColorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(m_refImage.getAccess());
    337 		const rr::RenderTarget					renderTarget(referenceColorBuffer);
    338 		const rr::RenderState					renderState((rr::ViewportState(referenceColorBuffer)), rr::VIEWPORTORIENTATION_UPPER_LEFT);
    339 		const rr::Renderer						renderer;
    340 		const rr::VertexAttrib					vertexAttrib[] =
    341 		{
    342 			rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &m_drawCallData.vertices[0])
    343 		};
    344 
    345 		renderer.draw(rr::DrawCommand(	renderState,
    346 										renderTarget,
    347 										program,
    348 										DE_LENGTH_OF_ARRAY(vertexAttrib),
    349 										&vertexAttrib[0],
    350 										rr::PrimitiveList(mapVkPrimitiveToRRPrimitive(m_drawState.topology), (int)m_drawCallData.vertices.size(), 0)));
    351 
    352 	}
    353 
    354 }
    355 
    356 tcu::ConstPixelBufferAccess ReferenceDrawContext::getColorPixels (void) const
    357 {
    358 	return tcu::ConstPixelBufferAccess( m_refImage.getAccess().getFormat(),
    359 										m_refImage.getAccess().getWidth(),
    360 										m_refImage.getAccess().getHeight(),
    361 										m_refImage.getAccess().getDepth(),
    362 										m_refImage.getAccess().getDataPtr());
    363 }
    364 
    365 VulkanDrawContext::VulkanDrawContext ( Context&				context,
    366 									  const DrawState&		drawState,
    367 									  const DrawCallData&	drawCallData,
    368 									  const VulkanProgram&	vulkanProgram)
    369 	: DrawContext	(drawState, drawCallData)
    370 	, m_context		(context)
    371 	, m_program		(vulkanProgram)
    372 {
    373 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
    374 	const VkDevice			device					= m_context.getDevice();
    375 	Allocator&				allocator				= m_context.getDefaultAllocator();
    376 	VkImageSubresourceRange	colorSubresourceRange;
    377 	Move<VkSampler>			sampler;
    378 
    379 	// Command buffer
    380 	{
    381 		m_cmdPool			= makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
    382 		m_cmdBuffer			= makeCommandBuffer(vk, device, *m_cmdPool);
    383 	}
    384 
    385 	// Color attachment image
    386 	{
    387 		const VkImageUsageFlags usage			= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    388 		colorSubresourceRange					= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
    389 		const VkImageCreateInfo	imageCreateInfo	=
    390 		{
    391 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    392 			DE_NULL,																	// const void*				pNext;
    393 			(VkImageCreateFlags)0,														// VkImageCreateFlags		flags;
    394 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    395 			m_drawState.colorFormat,													// VkFormat					format;
    396 			makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u),	// VkExtent3D				extent;
    397 			1u,																			// uint32_t					mipLevels;
    398 			1u,																			// uint32_t					arrayLayers;
    399 			(VkSampleCountFlagBits)m_drawState.numSamples,								// VkSampleCountFlagBits	samples;
    400 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    401 			usage,																		// VkImageUsageFlags		usage;
    402 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    403 			0u,																			// uint32_t					queueFamilyIndexCount;
    404 			DE_NULL,																	// const uint32_t*			pQueueFamilyIndices;
    405 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
    406 		};
    407 
    408 		m_colorImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
    409 		m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_drawState.colorFormat, colorSubresourceRange);
    410 
    411 		// Buffer to copy attachment data after rendering
    412 
    413 		const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_drawState.colorFormat)) * m_drawState.renderSize.x() * m_drawState.renderSize.y();
    414 		m_colorAttachmentBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
    415 			vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
    416 
    417 		{
    418 			const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
    419 			deMemset(alloc.getHostPtr(), 0, (size_t)bitmapSize);
    420 			flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bitmapSize);
    421 		}
    422 	}
    423 
    424 	// Vertex buffer
    425 	{
    426 		const VkDeviceSize bufferSize = m_drawCallData.vertices.size() * sizeof(m_drawCallData.vertices[0]);
    427 		m_vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
    428 			vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
    429 
    430 		const Allocation& alloc = m_vertexBuffer->getAllocation();
    431 		deMemcpy(alloc.getHostPtr(), &m_drawCallData.vertices[0], (size_t)bufferSize);
    432 		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
    433 	}
    434 
    435 	// bind descriptor sets
    436 	{
    437 		if (!vulkanProgram.descriptorSetLayout)
    438 			m_pipelineLayout = makePipelineLayoutWithoutDescriptors(vk, device);
    439 		else
    440 			m_pipelineLayout = makePipelineLayout(vk, device, vulkanProgram.descriptorSetLayout);
    441 	}
    442 
    443 	// Renderpass
    444 	{
    445 		std::vector<VkAttachmentDescription> attachmentDescriptions;
    446 		const VkAttachmentDescription attachDescriptors[] =
    447 		{
    448 			{
    449 				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
    450 				m_drawState.colorFormat,							// VkFormat							format;
    451 				(VkSampleCountFlagBits)m_drawState.numSamples,		// VkSampleCountFlagBits			samples;
    452 				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
    453 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
    454 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
    455 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
    456 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
    457 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
    458 			},
    459 			{
    460 				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags
    461 				m_drawState.depthFormat,							// VkFormat							format
    462 				(VkSampleCountFlagBits)m_drawState.numSamples,		// VkSampleCountFlagBits			samples
    463 				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp
    464 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp
    465 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp
    466 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp
    467 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout
    468 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout
    469 
    470 			}
    471 		};
    472 
    473 		const VkAttachmentReference attachmentReferences[] =
    474 		{
    475 			{
    476 				0u,													// uint32_t			attachment
    477 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout
    478 			},
    479 			{
    480 				1u,													// uint32_t			attachment
    481 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
    482 			},
    483 			{
    484 				VK_ATTACHMENT_UNUSED,								// deUint32         attachment;
    485 				VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout    layout;
    486 			}
    487 		};
    488 
    489 		attachmentDescriptions.push_back(attachDescriptors[0]);
    490 		if (!!vulkanProgram.depthImageView)
    491 			attachmentDescriptions.push_back(attachDescriptors[1]);
    492 
    493 		deUint32 depthReferenceNdx = !!vulkanProgram.depthImageView ? 1 : 2;
    494 		const VkSubpassDescription subpassDescription =
    495 		{
    496 			(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
    497 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
    498 			0u,													// deUint32							inputAttachmentCount;
    499 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
    500 			1u,													// deUint32							colorAttachmentCount;
    501 			&attachmentReferences[0],							// const VkAttachmentReference*		pColorAttachments;
    502 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
    503 			&attachmentReferences[depthReferenceNdx],			// const VkAttachmentReference*		pDepthStencilAttachment;
    504 			0u,													// deUint32							preserveAttachmentCount;
    505 			DE_NULL												// const deUint32*					pPreserveAttachments;
    506 		};
    507 
    508 		const VkRenderPassCreateInfo renderPassInfo =
    509 		{
    510 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    511 			DE_NULL,											// const void*						pNext;
    512 			(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    513 			(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount;
    514 			&attachmentDescriptions[0],							// const VkAttachmentDescription*	pAttachments;
    515 			1u,													// deUint32							subpassCount;
    516 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    517 			0u,													// deUint32							dependencyCount;
    518 			DE_NULL												// const VkSubpassDependency*		pDependencies;
    519 		};
    520 
    521 		m_renderPass = createRenderPass(vk, device, &renderPassInfo);
    522 	}
    523 
    524 	// Framebuffer
    525 	{
    526 		std::vector<VkImageView>	attachmentBindInfos;
    527 		deUint32					numAttachments;
    528 		attachmentBindInfos.push_back(*m_colorImageView);
    529 		if (!!vulkanProgram.depthImageView)
    530 			attachmentBindInfos.push_back(vulkanProgram.depthImageView);
    531 
    532 		numAttachments = (deUint32)(attachmentBindInfos.size());
    533 		const VkFramebufferCreateInfo framebufferInfo = {
    534 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType						sType;
    535 			DE_NULL,										// const void*							pNext;
    536 			(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags				flags;
    537 			*m_renderPass,									// VkRenderPass							renderPass;
    538 			numAttachments,									// uint32_t								attachmentCount;
    539 			&attachmentBindInfos[0],						// const VkImageView*					pAttachments;
    540 			m_drawState.renderSize.x(),						// uint32_t								width;
    541 			m_drawState.renderSize.y(),						// uint32_t								height;
    542 			1u,												// uint32_t								layers;
    543 		};
    544 
    545 		m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
    546 	}
    547 
    548 	// Graphics pipeline
    549 	{
    550 		const deUint32	vertexStride	= sizeof(Vec4);
    551 		const VkFormat	vertexFormat	= VK_FORMAT_R32G32B32A32_SFLOAT;
    552 
    553 		DE_ASSERT(m_drawState.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST || m_drawState.numPatchControlPoints > 0);
    554 
    555 		const VkVertexInputBindingDescription bindingDesc =
    556 		{
    557 			0u,									// uint32_t				binding;
    558 			vertexStride,						// uint32_t				stride;
    559 			VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
    560 		};
    561 		const VkVertexInputAttributeDescription attributeDesc =
    562 		{
    563 			0u,									// uint32_t			location;
    564 			0u,									// uint32_t			binding;
    565 			vertexFormat,						// VkFormat			format;
    566 			0u,									// uint32_t			offset;
    567 		};
    568 
    569 		const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
    570 		{
    571 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
    572 			DE_NULL,														// const void*									pNext;
    573 			(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags;
    574 			1u,																// uint32_t										vertexBindingDescriptionCount;
    575 			&bindingDesc,													// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
    576 			1u,																// uint32_t										vertexAttributeDescriptionCount;
    577 			&attributeDesc,													// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
    578 		};
    579 
    580 		const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
    581 		{
    582 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType								sType;
    583 			DE_NULL,														// const void*									pNext;
    584 			(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags		flags;
    585 			m_drawState.topology,											// VkPrimitiveTopology							topology;
    586 			VK_FALSE,														// VkBool32										primitiveRestartEnable;
    587 		};
    588 
    589 		const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
    590 		{
    591 			VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType								sType;
    592 			DE_NULL,														// const void*									pNext;
    593 			(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags		flags;
    594 			m_drawState.numPatchControlPoints,								// uint32_t										patchControlPoints;
    595 		};
    596 
    597 		const VkViewport viewport = makeViewport(
    598 			0.0f, 0.0f,
    599 			static_cast<float>(m_drawState.renderSize.x()), static_cast<float>(m_drawState.renderSize.y()),
    600 			0.0f, 1.0f);
    601 
    602 		const VkRect2D scissor = {
    603 			makeOffset2D(0, 0),
    604 			makeExtent2D(m_drawState.renderSize.x(), m_drawState.renderSize.y()),
    605 		};
    606 
    607 		const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
    608 		{
    609 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType									sType;
    610 			DE_NULL,												// const void*										pNext;
    611 			(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags				flags;
    612 			1u,														// uint32_t											viewportCount;
    613 			&viewport,												// const VkViewport*								pViewports;
    614 			1u,														// uint32_t											scissorCount;
    615 			&scissor,												// const VkRect2D*									pScissors;
    616 		};
    617 
    618 		const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
    619 		{
    620 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    621 			DE_NULL,														// const void*								pNext;
    622 			(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
    623 			m_drawState.depthClampEnable,									// VkBool32									depthClampEnable;
    624 			VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
    625 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    626 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    627 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    628 			VK_FALSE,														// VkBool32									depthBiasEnable;
    629 			0.0f,															// float									depthBiasConstantFactor;
    630 			0.0f,															// float									depthBiasClamp;
    631 			0.0f,															// float									depthBiasSlopeFactor;
    632 			m_drawState.lineWidth,											// float									lineWidth;
    633 		};
    634 
    635 		const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
    636 		{
    637 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
    638 			DE_NULL,													// const void*								pNext;
    639 			(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
    640 			(VkSampleCountFlagBits)m_drawState.numSamples,				// VkSampleCountFlagBits					rasterizationSamples;
    641 			m_drawState.sampleShadingEnable ? VK_TRUE : VK_FALSE,		// VkBool32									sampleShadingEnable;
    642 			m_drawState.sampleShadingEnable ? 1.0f : 0.0f,				// float									minSampleShading;
    643 			DE_NULL,													// const VkSampleMask*						pSampleMask;
    644 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
    645 			VK_FALSE													// VkBool32									alphaToOneEnable;
    646 		};
    647 
    648 		const VkStencilOpState stencilOpState = makeStencilOpState(
    649 			VK_STENCIL_OP_KEEP,		// stencil fail
    650 			VK_STENCIL_OP_KEEP,		// depth & stencil pass
    651 			VK_STENCIL_OP_KEEP,		// depth only fail
    652 			VK_COMPARE_OP_NEVER,	// compare op
    653 			0u,						// compare mask
    654 			0u,						// write mask
    655 			0u);					// reference
    656 
    657 		if (m_drawState.depthBoundsTestEnable && context.getDeviceFeatures().depthBounds)
    658 			TCU_THROW(NotSupportedError, "depthBounds not supported");
    659 
    660 		const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
    661 		{
    662 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
    663 			DE_NULL,													// const void*								pNext;
    664 			(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
    665 			m_drawState.depthTestEnable,								// VkBool32									depthTestEnable;
    666 			m_drawState.depthWriteEnable,								// VkBool32									depthWriteEnable;
    667 			mapCompareOp(m_drawState.compareOp),						// VkCompareOp								depthCompareOp;
    668 			m_drawState.depthBoundsTestEnable,							// VkBool32									depthBoundsTestEnable
    669 			VK_FALSE,													// VkBool32									stencilTestEnable;
    670 			stencilOpState,												// VkStencilOpState							front;
    671 			stencilOpState,												// VkStencilOpState							back;
    672 			0.0f,														// float									minDepthBounds;
    673 			1.0f,														// float									maxDepthBounds;
    674 		};
    675 
    676 		const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
    677 		const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
    678 		{
    679 			m_drawState.blendEnable,			// VkBool32					blendEnable;
    680 			VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
    681 			VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
    682 			VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
    683 			VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
    684 			VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
    685 			VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
    686 			colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
    687 		};
    688 
    689 		const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
    690 		{
    691 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    692 			DE_NULL,													// const void*									pNext;
    693 			(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
    694 			VK_FALSE,													// VkBool32										logicOpEnable;
    695 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    696 			1u,															// deUint32										attachmentCount;
    697 			&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
    698 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
    699 		};
    700 
    701 		// Create shader stages
    702 
    703 		std::vector<VkPipelineShaderStageCreateInfo>	shaderStages;
    704 		VkShaderStageFlags								stageFlags = (VkShaderStageFlags)0;
    705 
    706 		DE_ASSERT(m_program.shaders.size() <= MAX_NUM_SHADER_MODULES);
    707 		for (deUint32 shaderNdx = 0; shaderNdx < m_program.shaders.size(); ++shaderNdx)
    708 		{
    709 			m_shaderModules[shaderNdx] = createShaderModule(vk, device, *m_program.shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
    710 
    711 			const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
    712 			{
    713 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
    714 				DE_NULL,												// const void*							pNext;
    715 				(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
    716 				m_program.shaders[shaderNdx].stage,						// VkShaderStageFlagBits				stage;
    717 				*m_shaderModules[shaderNdx],							// VkShaderModule						module;
    718 				"main",													// const char*							pName;
    719 				DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
    720 			};
    721 
    722 			shaderStages.push_back(pipelineShaderStageInfo);
    723 			stageFlags |= m_program.shaders[shaderNdx].stage;
    724 		}
    725 
    726 		DE_ASSERT(
    727 			(m_drawState.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
    728 			(stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
    729 
    730 		const bool tessellationEnabled = (m_drawState.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
    731 		const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
    732 		{
    733 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
    734 			DE_NULL,																// const void*										pNext;
    735 			(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
    736 			static_cast<deUint32>(shaderStages.size()),								// deUint32											stageCount;
    737 			&shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
    738 			&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    739 			&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    740 			(tessellationEnabled ? &pipelineTessellationStateInfo : DE_NULL),		// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    741 			&pipelineViewportStateInfo,												// const VkPipelineViewportStateCreateInfo*			pViewportState;
    742 			&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    743 			&pipelineMultisampleStateInfo,											// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    744 			&pipelineDepthStencilStateInfo,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    745 			&pipelineColorBlendStateInfo,											// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    746 			DE_NULL,																// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    747 			*m_pipelineLayout,														// VkPipelineLayout									layout;
    748 			*m_renderPass,															// VkRenderPass										renderPass;
    749 			0u,																		// deUint32											subpass;
    750 			DE_NULL,																// VkPipeline										basePipelineHandle;
    751 			0,																		// deInt32											basePipelineIndex;
    752 		};
    753 
    754 		m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
    755 	}
    756 
    757 	// Record commands
    758 	{
    759 		const VkDeviceSize zeroOffset = 0ull;
    760 
    761 		beginCommandBuffer(vk, *m_cmdBuffer);
    762 		if (!!vulkanProgram.descriptorSet)
    763 			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &vulkanProgram.descriptorSet, 0u, DE_NULL);
    764 
    765 		// Begin render pass
    766 		{
    767 			std::vector<VkClearValue> clearValues;
    768 
    769 			clearValues.push_back(makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
    770 			if (!!vulkanProgram.depthImageView)
    771 				clearValues.push_back(makeClearValueDepthStencil(0.0, 0));
    772 
    773 			const VkRect2D		renderArea =
    774 			{
    775 				makeOffset2D(0, 0),
    776 				makeExtent2D(m_drawState.renderSize.x(), m_drawState.renderSize.y())
    777 			};
    778 
    779 			const VkRenderPassBeginInfo renderPassBeginInfo = {
    780 				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType								sType;
    781 				DE_NULL,															// const void*									pNext;
    782 				*m_renderPass,														// VkRenderPass									renderPass;
    783 				*m_framebuffer,														// VkFramebuffer								framebuffer;
    784 				renderArea,															// VkRect2D										renderArea;
    785 				static_cast<deUint32>(clearValues.size()),							// uint32_t										clearValueCount;
    786 				&clearValues[0],													// const VkClearValue*							pClearValues;
    787 			};
    788 
    789 			vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    790 		}
    791 
    792 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
    793 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**m_vertexBuffer), &zeroOffset);
    794 
    795 		vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_drawCallData.vertices.size()), 1u, 0u, 0u);
    796 		vk.cmdEndRenderPass(*m_cmdBuffer);
    797 
    798 		// Barrier: draw -> copy from image
    799 		{
    800 			const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
    801 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
    802 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    803 				**m_colorImage, colorSubresourceRange);
    804 
    805 			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
    806 				0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
    807 		}
    808 
    809 		// Resolve multisample image
    810 		{
    811 			if (m_drawState.numSamples != VK_SAMPLE_COUNT_1_BIT)
    812 			{
    813 				const VkImageResolve imageResolve =
    814 				{
    815 					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
    816 					{ 0, 0, 0},
    817 					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
    818 					{ 0, 0, 0},
    819 					makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u)
    820 				};
    821 
    822 				const VkImageCreateInfo resolveImageCreateInfo =
    823 				{
    824 					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType
    825 					DE_NULL,											// const void*				pNext
    826 					(VkImageCreateFlags)0,								// VkImageCreateFlags		flags
    827 					VK_IMAGE_TYPE_2D,									// VkImageType				imageType
    828 					m_drawState.colorFormat,							// VkFormat					format
    829 					makeExtent3D(m_drawState.renderSize.x(),			// VkExtent3D				extent;
    830 							m_drawState.renderSize.y(), 1u),
    831 					1u,													// uint32_t					mipLevels
    832 					1u,													// uint32_t					arrayLayers
    833 					VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits	samples
    834 					VK_IMAGE_TILING_OPTIMAL,							// VkImaageTiling			tiling
    835 					VK_IMAGE_USAGE_TRANSFER_DST_BIT |					// VkImageUsageFlags		usage
    836 					VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
    837 					VK_SHARING_MODE_EXCLUSIVE,							// VkSharingModeExclusive	sharingMode
    838 					0u,													// uint32_t					queueFamilyIndexCount
    839 					DE_NULL,											// const uint32_t*			pQueueFamilyIndices
    840 					VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout			initialLayout
    841 				};
    842 
    843 				m_resolveImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, resolveImageCreateInfo, MemoryRequirement::Any));
    844 
    845 				const VkImageMemoryBarrier resolveBarrier = makeImageMemoryBarrier(
    846 						0u, VK_ACCESS_TRANSFER_READ_BIT,
    847 						VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    848 						**m_resolveImage, colorSubresourceRange);
    849 
    850 				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
    851 						0u, DE_NULL, 0u, DE_NULL, 1u, &resolveBarrier);
    852 
    853 				vk.cmdResolveImage(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    854 						**m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &imageResolve);
    855 
    856 				const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
    857 					VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
    858 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    859 					**m_resolveImage, colorSubresourceRange);
    860 
    861 				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
    862 					0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
    863 			}
    864 			else
    865 				m_resolveImage = m_colorImage;
    866 
    867 			const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
    868 					makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u));
    869 			vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
    870 		}
    871 
    872 		// Barrier: copy to buffer -> host read
    873 		{
    874 			const VkBufferMemoryBarrier barrier = makeBufferMemoryBarrier(
    875 				VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
    876 				**m_colorAttachmentBuffer, 0ull, VK_WHOLE_SIZE);
    877 
    878 			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
    879 				0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
    880 		}
    881 
    882 		endCommandBuffer(vk, *m_cmdBuffer);
    883 	}
    884 }
    885 
    886 VulkanDrawContext::~VulkanDrawContext (void)
    887 {
    888 }
    889 
    890 void VulkanDrawContext::draw (void)
    891 {
    892 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
    893 	const VkDevice			device		= m_context.getDevice();
    894 	const VkQueue			queue		= m_context.getUniversalQueue();
    895 	tcu::TestLog&			log			= m_context.getTestContext().getLog();
    896 
    897 	submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
    898 
    899 	log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels()) << tcu::TestLog::EndImageSet;
    900 }
    901 
    902 tcu::ConstPixelBufferAccess VulkanDrawContext::getColorPixels (void) const
    903 {
    904 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
    905 	const VkDevice			device		= m_context.getDevice();
    906 
    907 	const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
    908 	invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
    909 
    910 	return tcu::ConstPixelBufferAccess(mapVkFormat(m_drawState.colorFormat), m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u, alloc.getHostPtr());
    911 }
    912 } // drawutil
    913 } // vkt
    914