• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mapCompareOp(rr::TestFunc compareFunc)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 
mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology & primitiveTopology)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 
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)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 
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)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 
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)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 
makeCommandPool(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)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 
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)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 
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)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 
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)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 
makePipelineLayoutWithoutDescriptors(const DeviceInterface & vk,const VkDevice device)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 
makeImageView(const DeviceInterface & vk,const VkDevice device,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)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 
makeBufferImageCopy(const VkImageSubresourceLayers subresourceLayers,const VkExtent3D extent)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 
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)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 
endCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)267 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
268 {
269 	VK_CHECK(vk.endCommandBuffer(commandBuffer));
270 }
271 
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer)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 
getPrimitiveTopologyShortName(const VkPrimitiveTopology topology)301 std::string getPrimitiveTopologyShortName (const VkPrimitiveTopology topology)
302 {
303 	std::string name(getPrimitiveTopologyName(topology));
304 	return de::toLower(name.substr(22));
305 }
306 
DrawState(const vk::VkPrimitiveTopology topology_,deUint32 renderWidth_,deUint32 renderHeight_)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 
~ReferenceDrawContext(void)325 ReferenceDrawContext::~ReferenceDrawContext (void)
326 {
327 }
328 
draw(void)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 
getColorPixels(void) const356 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 
VulkanDrawContext(Context & context,const DrawState & drawState,const DrawCallData & drawCallData,const VulkanProgram & vulkanProgram)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 
~VulkanDrawContext(void)886 VulkanDrawContext::~VulkanDrawContext (void)
887 {
888 }
889 
draw(void)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 
getColorPixels(void) const902 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