1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Intel Corporation
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief VK_EXT_external_memory_host extension tests.
23 *//*--------------------------------------------------------------------*/
24 
25 #include "vktMemoryExternalMemoryHostTests.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 
29 #include "deMath.h"
30 
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 
40 #include "tcuTestLog.hpp"
41 #include "tcuImageCompare.hpp"
42 
43 namespace vkt
44 {
45 namespace memory
46 {
47 namespace
48 {
49 
50 using namespace vk;
51 
getBit(deUint32 src,int ndx)52 inline deUint32 getBit (deUint32 src, int ndx)
53 {
54 	return (src >> ndx) & 1;
55 }
56 
isBitSet(deUint32 src,int ndx)57 inline bool isBitSet (deUint32 src, int ndx)
58 {
59 	return getBit(src, ndx) != 0;
60 }
61 
62 struct TestParams
63 {
64 	VkFormat		m_format;
65 	bool			m_useOffset;
66 
TestParamsvkt::memory::__anon67350ce20111::TestParams67 	TestParams		(VkFormat f, bool offset = false) : m_format(f) , m_useOffset(offset) {}
68 };
69 
70 class ExternalMemoryHostBaseTestInstance : public TestInstance
71 {
72 public:
73 									ExternalMemoryHostBaseTestInstance			(Context& context, VkDeviceSize allocationSize);
74 									~ExternalMemoryHostBaseTestInstance			(void);
75 protected:
76 	virtual tcu::TestStatus			iterate										(void);
77 	VkDeviceSize					getMinImportedHostPointerAlignment			(void);
78 	deUint32						getHostPointerMemoryTypeBits				(void* hostPointer);
79 	Move<VkDeviceMemory>			allocateMemoryFromHostPointer				(deUint32 memoryTypeIndex);
80 	void							logMemoryTypeIndexPropertyFlags				(deUint32 index);
81 	bool							findCompatibleMemoryTypeIndexToTest			(deUint32 resourceMemoryTypeBits, deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest);
82 	bool							findMemoryTypeIndexToTest					(deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest);
83 
84 	const InstanceInterface&						m_vki;
85 	const DeviceInterface&							m_vkd;
86 	tcu::TestLog&									m_log;
87 	const VkDevice									m_device;
88 	const VkPhysicalDevice							m_physicalDevice;
89 	const VkQueue									m_queue;
90 	const vk::VkPhysicalDeviceMemoryProperties		m_memoryProps;
91 	VkDeviceSize									m_minImportedHostPointerAlignment;
92 	VkDeviceSize									m_allocationSize;
93 	void*											m_hostMemoryAlloc;
94 	Allocator&										m_allocator;
95 	Move<VkDeviceMemory>							m_deviceMemoryAllocatedFromHostPointer;
96 };
97 
98 class ExternalMemoryHostRenderImageTestInstance : public ExternalMemoryHostBaseTestInstance
99 {
100 public:
101 									ExternalMemoryHostRenderImageTestInstance	(Context& context, TestParams testParams);
102 protected:
103 	virtual tcu::TestStatus			iterate										(void);
104 	Move<VkImage>					createImage									(VkImageTiling tiling);
105 	Move<VkImageView>				createImageView								(void);
106 	Move<VkBuffer>					createBindMemoryInitializeVertexBuffer		(void);
107 	Move<VkBuffer>					createBindMemoryResultBuffer				(void);
108 	Move<VkFramebuffer>				createFramebuffer							(void);
109 	Move<VkDescriptorSet>			createAndUpdateDescriptorSet				(void);
110 	Move<VkPipelineLayout>			createPipelineLayout						(void);
111 	Move<VkPipeline>				createPipeline								(void);
112 	Move<VkRenderPass>				createRenderPass							(void);
113 	void							clear										(VkClearColorValue color);
114 	void							draw										(void);
115 	void							copyResultImagetoBuffer						(void);
116 	void							prepareReferenceImage						(tcu::PixelBufferAccess& reference);
117 
118 	TestParams										m_testParams;
119 	Move<VkImage>									m_image;
120 	Move<VkImageView>								m_imageView;
121 	Move<VkRenderPass>								m_renderPass;
122 	Move<VkFramebuffer>								m_framebuffer;
123 	Move<VkBuffer>									m_vertexBuffer;
124 	Move<VkBuffer>									m_resultBuffer;
125 	de::MovePtr<Allocation>							m_vertexBufferAllocation;
126 	de::MovePtr<Allocation>							m_resultBufferAllocation;
127 	Move<VkDescriptorPool>							m_descriptorPool;
128 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
129 	Move<VkDescriptorSet>							m_descriptorSet;
130 	Move<VkShaderModule>							m_vertexShaderModule;
131 	Move<VkShaderModule>							m_fragmentShaderModule;
132 	Move<VkPipelineLayout>							m_pipelineLayout;
133 	Move<VkPipeline>								m_pipeline;
134 	Move<VkCommandPool>								m_cmdPool;
135 	Move<VkCommandBuffer>							m_cmdBuffer;
136 };
137 
138 class ExternalMemoryHostSynchronizationTestInstance : public ExternalMemoryHostRenderImageTestInstance
139 {
140 public:
141 								ExternalMemoryHostSynchronizationTestInstance	(Context& context, TestParams testParams);
142 protected:
143 	virtual tcu::TestStatus		iterate											(void);
144 	void						prepareBufferForHostAccess						(void);
145 	void						copyResultBuffertoBuffer						(void);
146 	void						submitCommands									(VkCommandBuffer commandBuffer, VkFence fence);
147 	Move<VkBuffer>				createDataBuffer								(void);
148 	void						fillBuffer										(void);
149 
150 	Move<VkBuffer>				m_dataBuffer;
151 	Move<VkCommandPool>			m_cmdPoolCopy;
152 	Move<VkCommandBuffer>		m_cmdBufferCopy;
153 	Move<VkFence>				m_fence_1;
154 	Move<VkFence>				m_fence_2;
155 	Move<VkEvent>				m_event;
156 };
157 
ExternalMemoryHostBaseTestInstance(Context & context,VkDeviceSize allocationSize)158 ExternalMemoryHostBaseTestInstance::ExternalMemoryHostBaseTestInstance (Context& context, VkDeviceSize allocationSize)
159 	: TestInstance							(context)
160 	, m_vki									(m_context.getInstanceInterface())
161 	, m_vkd									(m_context.getDeviceInterface())
162 	, m_log									(m_context.getTestContext().getLog())
163 	, m_device								(m_context.getDevice())
164 	, m_physicalDevice						(m_context.getPhysicalDevice())
165 	, m_queue								(m_context.getUniversalQueue())
166 	, m_memoryProps							(getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
167 	, m_minImportedHostPointerAlignment		(getMinImportedHostPointerAlignment())
168 	, m_allocationSize						(m_minImportedHostPointerAlignment * allocationSize)
169 	, m_allocator							(m_context.getDefaultAllocator())
170 {
171 	if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_external_memory_host"))
172 		throw tcu::NotSupportedError("VK_EXT_external_memory_host is not supported");
173 
174 	m_hostMemoryAlloc	=	deAlignedMalloc((size_t)m_allocationSize, (size_t)m_minImportedHostPointerAlignment);
175 
176 	if (!m_hostMemoryAlloc)
177 		TCU_FAIL("Failed to allocate memory block.");
178 
179 	DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
180 }
181 
~ExternalMemoryHostBaseTestInstance(void)182 ExternalMemoryHostBaseTestInstance::~ExternalMemoryHostBaseTestInstance (void)
183 {
184 	deAlignedFree(m_hostMemoryAlloc);
185 }
186 
getMinImportedHostPointerAlignment(void)187 VkDeviceSize ExternalMemoryHostBaseTestInstance::getMinImportedHostPointerAlignment (void)
188 {
189 	VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties	=
190 	{
191 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,		//VkStructureType		sType
192 		DE_NULL,																	//void*					pNext
193 		0																			//VkDeviceSize			minImportedHostPointerAlignment
194 	};
195 
196 	VkPhysicalDeviceProperties2						propertiesDeviceProperties2;
197 	propertiesDeviceProperties2.sType				= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
198 	propertiesDeviceProperties2.pNext				= &externalMemoryHostProperties;
199 
200 	m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &propertiesDeviceProperties2);
201 
202 	m_log	<< tcu::TestLog::Message << "VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment is "
203 			<< externalMemoryHostProperties.minImportedHostPointerAlignment << tcu::TestLog::EndMessage;
204 
205 	if (externalMemoryHostProperties.minImportedHostPointerAlignment > 65536)
206 		TCU_FAIL("minImportedHostPointerAlignment is exceeding the supported limit");
207 
208 	return externalMemoryHostProperties.minImportedHostPointerAlignment;
209 }
210 
getHostPointerMemoryTypeBits(void * hostPointer)211 deUint32 ExternalMemoryHostBaseTestInstance::getHostPointerMemoryTypeBits (void* hostPointer)
212 {
213 	VkExternalMemoryHandleTypeFlagBits			externalMemoryHandleTypeFlagBits = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
214 
215 	VkMemoryHostPointerPropertiesEXT			memoryHostPointerProperties;
216 	memoryHostPointerProperties.sType			= VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT;
217 	memoryHostPointerProperties.pNext			= DE_NULL;
218 
219 	VK_CHECK(m_vkd.getMemoryHostPointerPropertiesEXT(m_device, externalMemoryHandleTypeFlagBits, hostPointer, &memoryHostPointerProperties));
220 
221 	m_log << tcu::TestLog::Message << "memoryTypeBits value: " << memoryHostPointerProperties.memoryTypeBits << tcu::TestLog::EndMessage;
222 
223 	return memoryHostPointerProperties.memoryTypeBits;
224 }
225 
allocateMemoryFromHostPointer(deUint32 memoryTypeIndex)226 Move<VkDeviceMemory> ExternalMemoryHostBaseTestInstance::allocateMemoryFromHostPointer (deUint32 memoryTypeIndex)
227 {
228 	VkImportMemoryHostPointerInfoEXT							importMemoryHostPointerInfo;
229 	importMemoryHostPointerInfo.sType							= VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
230 	importMemoryHostPointerInfo.pNext							= DE_NULL;
231 	importMemoryHostPointerInfo.handleType						= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
232 	importMemoryHostPointerInfo.pHostPointer					= m_hostMemoryAlloc;
233 
234 	VkMemoryAllocateInfo										memoryAllocateInfo;
235 	memoryAllocateInfo.sType									= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
236 	memoryAllocateInfo.pNext									= &importMemoryHostPointerInfo;
237 	memoryAllocateInfo.allocationSize							= m_allocationSize;
238 	memoryAllocateInfo.memoryTypeIndex							= memoryTypeIndex;
239 
240 	return allocateMemory(m_vkd, m_device, &memoryAllocateInfo, DE_NULL);
241 }
242 
logMemoryTypeIndexPropertyFlags(deUint32 index)243 void ExternalMemoryHostBaseTestInstance::logMemoryTypeIndexPropertyFlags (deUint32 index)
244 {
245 	m_log << tcu::TestLog::Message << "Memory Type index " << index << " property flags:" << tcu::TestLog::EndMessage;
246 	m_log << tcu::TestLog::Message << getMemoryPropertyFlagsStr(m_memoryProps.memoryTypes[index].propertyFlags) << tcu::TestLog::EndMessage;
247 }
248 
findCompatibleMemoryTypeIndexToTest(deUint32 resourceMemoryTypeBits,deUint32 hostPointerMemoryTypeBits,deUint32 * outMemoryTypeIndexToTest)249 bool ExternalMemoryHostBaseTestInstance::findCompatibleMemoryTypeIndexToTest (deUint32 resourceMemoryTypeBits, deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest)
250 {
251 	for (deUint32 bitMaskPosition = 0; bitMaskPosition < VK_MAX_MEMORY_TYPES; bitMaskPosition++)
252 	{
253 		if (isBitSet(resourceMemoryTypeBits & hostPointerMemoryTypeBits, bitMaskPosition))
254 		{
255 			logMemoryTypeIndexPropertyFlags(bitMaskPosition);
256 			*outMemoryTypeIndexToTest = bitMaskPosition;
257 			return true;
258 		}
259 	}
260 	return false;
261 }
262 
findMemoryTypeIndexToTest(deUint32 hostPointerMemoryTypeBits,deUint32 * outMemoryTypeIndexToTest)263 bool ExternalMemoryHostBaseTestInstance::findMemoryTypeIndexToTest (deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest)
264 {
265 	return findCompatibleMemoryTypeIndexToTest(~0u, hostPointerMemoryTypeBits, outMemoryTypeIndexToTest);
266 }
267 
iterate(void)268 tcu::TestStatus ExternalMemoryHostBaseTestInstance::iterate (void)
269 {
270 	deUint32			hostPointerMemoryTypeBits;
271 	deUint32			memoryTypeIndexToTest;
272 
273 	//realocate to meet requirements for host memory alignment
274 	m_hostMemoryAlloc			= deAlignedRealloc(m_hostMemoryAlloc, (size_t)m_minImportedHostPointerAlignment, (size_t)m_minImportedHostPointerAlignment);
275 	m_allocationSize			= m_minImportedHostPointerAlignment;
276 
277 	//check if reallocation is successfull
278 	if (!m_hostMemoryAlloc)
279 		TCU_FAIL("Failed to reallocate memory block.");
280 
281 	DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
282 
283 	//find the usable memory type index
284 	hostPointerMemoryTypeBits	= getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
285 	if (findMemoryTypeIndexToTest(hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
286 		m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
287 	else
288 		return tcu::TestStatus::fail("Fail");
289 
290 	return tcu::TestStatus::pass("Pass");
291 }
292 
ExternalMemoryHostRenderImageTestInstance(Context & context,TestParams testParams)293 ExternalMemoryHostRenderImageTestInstance::ExternalMemoryHostRenderImageTestInstance (Context& context, TestParams testParams)
294 		: ExternalMemoryHostBaseTestInstance	(context, 1)
295 		, m_testParams							(testParams)
296 {
297 }
298 
iterate()299 tcu::TestStatus ExternalMemoryHostRenderImageTestInstance::iterate ()
300 {
301 	VkClearColorValue					clearColorBlue					= { { 0.0f, 0.0f, 1.0f, 1.0f } };
302 	const deUint32						queueFamilyIndex				= m_context.getUniversalQueueFamilyIndex();
303 	deUint32							hostPointerMemoryTypeBits;
304 	deUint32							memoryTypeIndexToTest;
305 	VkMemoryRequirements				imageMemoryRequirements;
306 
307 	m_image								= createImage(VK_IMAGE_TILING_OPTIMAL);
308 
309 	//check memory requirements and reallocate memory if needed
310 	imageMemoryRequirements				= getImageMemoryRequirements(m_vkd, m_device, *m_image);
311 
312 	if (m_testParams.m_useOffset == false)
313 	{
314 		VkDeviceSize requiredSize = imageMemoryRequirements.size;
315 		if (requiredSize > m_allocationSize)
316 		{
317 			//calculate new size, this must me a multiple of minImportedHostPointerAlignment
318 			VkDeviceSize newHostAllocationSize	= VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
319 
320 			m_log	<< tcu::TestLog::Message << "Realloc needed (required size: "  << requiredSize <<  "). " << "New host allocation size: " << newHostAllocationSize << ")."
321 					<< tcu::TestLog::EndMessage;
322 			//realocate
323 			m_hostMemoryAlloc					= deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
324 			m_allocationSize					= newHostAllocationSize;
325 		}
326 	}
327 
328 	if (m_testParams.m_useOffset == true)
329 	{
330 		VkDeviceSize requiredSize = imageMemoryRequirements.size + imageMemoryRequirements.alignment;
331 		if (requiredSize > m_allocationSize)
332 		{
333 			VkDeviceSize newHostAllocationSize	= VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
334 
335 			m_log	<< tcu::TestLog::Message << "Realloc needed (required size: " << requiredSize << "). " << "New host allocation size: " << newHostAllocationSize << ")."
336 					<< tcu::TestLog::EndMessage;
337 			m_hostMemoryAlloc					= deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
338 			m_allocationSize					= newHostAllocationSize;
339 		}
340 	}
341 	//check if reallocation is successfull
342 	if (!m_hostMemoryAlloc)
343 		TCU_FAIL("Failed to reallocate memory block.");
344 
345 	DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
346 
347 	//find the usable memory type index
348 	hostPointerMemoryTypeBits			= getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
349 	if (findCompatibleMemoryTypeIndexToTest(imageMemoryRequirements.memoryTypeBits, hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
350 		m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
351 	else
352 		TCU_THROW(NotSupportedError, "Compatible memory type not found");
353 
354 	VK_CHECK(m_vkd.bindImageMemory(m_device, *m_image, *m_deviceMemoryAllocatedFromHostPointer, (m_testParams.m_useOffset ? imageMemoryRequirements.alignment : 0)));
355 
356 	m_imageView								= createImageView();
357 	m_renderPass							= createRenderPass();
358 	m_framebuffer							= createFramebuffer();
359 	m_vertexBuffer							= createBindMemoryInitializeVertexBuffer();
360 	m_resultBuffer							= createBindMemoryResultBuffer();
361 
362 	vk::DescriptorSetLayoutBuilder			builder;
363 
364 	builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
365 
366 	m_descriptorSetLayout					= builder.build(m_vkd, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
367 
368 	m_descriptorPool						= DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
369 																	 .build(m_vkd, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
370 
371 	m_pipelineLayout						= createPipelineLayout();
372 	m_descriptorSet							= createAndUpdateDescriptorSet();
373 
374 	m_vertexShaderModule					= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("position_only.vert"), 0);
375 	m_fragmentShaderModule					= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("only_color_out.frag"), 0);
376 
377 
378 	m_pipeline								= createPipeline();
379 
380 	m_cmdPool								= createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
381 	m_cmdBuffer								= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
382 
383 
384 	beginCommandBuffer(m_vkd, *m_cmdBuffer);
385 
386 	clear(clearColorBlue);
387 	draw();
388 	copyResultImagetoBuffer();
389 
390 	endCommandBuffer(m_vkd, *m_cmdBuffer);
391 
392 	submitCommandsAndWait(m_vkd, m_device, m_queue, *m_cmdBuffer);
393 
394 	tcu::ConstPixelBufferAccess				result(mapVkFormat(m_testParams.m_format), tcu::IVec3(100,100,1), m_resultBufferAllocation->getHostPtr());
395 
396 	std::vector<float>						referenceData(40000, 0);
397 	tcu::PixelBufferAccess					reference(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), referenceData.data());
398 
399 	prepareReferenceImage(reference);
400 
401 	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
402 		return tcu::TestStatus::fail("Fail");
403 
404 	return tcu::TestStatus::pass("Pass");
405 }
406 
createImage(VkImageTiling tiling)407 Move<VkImage>  ExternalMemoryHostRenderImageTestInstance::createImage (VkImageTiling tiling)
408 {
409 	const VkImageCreateInfo			imageCreateInfo =
410 	{
411 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
412 		DE_NULL,												// const void*				pNext
413 		DE_NULL,												// VkImageCreateFlags		flags
414 		VK_IMAGE_TYPE_2D,										// VkImageType				imageType
415 		m_testParams.m_format,									// VkFormat					format
416 		{ 100, 100, 1 },										// VkExtent3D				extent
417 		1,														// deUint32					mipLevels
418 		1,														// deUint32					arrayLayers
419 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples
420 		tiling,													// VkImageTiling			tiling
421 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
422 		VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
423 		VK_IMAGE_USAGE_TRANSFER_DST_BIT,						// VkImageUsageFlags		usage
424 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode
425 		0,														// deUint32					queueFamilyIndexCount
426 		DE_NULL,												// const deUint32*			pQueueFamilyIndices
427 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout
428 	};
429 
430 	return vk::createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
431 }
432 
createFramebuffer()433 Move<VkFramebuffer>  ExternalMemoryHostRenderImageTestInstance::createFramebuffer ()
434 {
435 	const VkFramebufferCreateInfo framebufferCreateInfo =
436 	{
437 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType
438 		DE_NULL,											// const void*					pNext
439 		(VkFramebufferCreateFlags)0,
440 		*m_renderPass,										// VkRenderPass					renderPass
441 		1,													// deUint32						attachmentCount
442 		&m_imageView.get(),									// const VkImageView*			pAttachments
443 		100,												// deUint32						width
444 		100,												// deUint32						height
445 		1													// deUint32						layers
446 	};
447 	return vk::createFramebuffer(m_vkd, m_device, &framebufferCreateInfo);
448 }
449 
createImageView()450 Move<VkImageView>  ExternalMemoryHostRenderImageTestInstance::createImageView ()
451 {
452 	const VkImageViewCreateInfo		imageViewCreateInfo =
453 	{
454 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,																// VkStructureType			sType
455 		DE_NULL,																								// const void*				pNext
456 		0,																										// VkImageViewCreateFlags	flags
457 		*m_image,																								// VkImage					image
458 		VK_IMAGE_VIEW_TYPE_2D,																					// VkImageViewType			viewType
459 		m_testParams.m_format,																					// VkFormat					format
460 		{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A},		// VkComponentMapping		components
461 		{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }																// VkImageSubresourceRange	subresourceRange
462 	};
463 	return vk::createImageView(m_vkd, m_device, &imageViewCreateInfo);
464 }
465 
createBindMemoryInitializeVertexBuffer()466 Move<VkBuffer>  ExternalMemoryHostRenderImageTestInstance::createBindMemoryInitializeVertexBuffer ()
467 {
468 	Move<VkBuffer>						buffer;
469 	float								triangleData[]					= { -1.0f,  -1.0f, 0.0f, 1.0f,
470 																		    -1.0f,   1.0f, 0.0f, 1.0f,
471 																			 0.0f,   1.0f, 0.0f, 1.0f,
472 																			 0.0f,  -1.0f, 0.0f, 1.0f };
473 	const VkBufferCreateInfo			vertexBufferCreateInfo =
474 	{
475 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType
476 		DE_NULL,								// const void*			pNext
477 		0,										// VkBufferCreateFlags	flag
478 		sizeof(triangleData),					// VkDeviceSize			size
479 		VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags	usage
480 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode
481 		0,										// deUint32				queueFamilyCount
482 		DE_NULL									// const deUint32*		pQueueFamilyIndices
483 	};
484 	buffer																= vk::createBuffer(m_vkd, m_device, &vertexBufferCreateInfo, DE_NULL);
485 	const VkMemoryRequirements			bufferMemoryRequirements		= getBufferMemoryRequirements(m_vkd, m_device, *buffer);
486 										m_vertexBufferAllocation		= m_allocator.allocate(bufferMemoryRequirements, MemoryRequirement::HostVisible);
487 
488 	VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, m_vertexBufferAllocation->getMemory(), m_vertexBufferAllocation->getOffset()));
489 
490 	void* const							mapPtr							= m_vertexBufferAllocation->getHostPtr();
491 
492 	deMemcpy(mapPtr, triangleData, sizeof(triangleData));
493 	flushMappedMemoryRange(m_vkd, m_device, m_vertexBufferAllocation->getMemory(), m_vertexBufferAllocation->getOffset(), sizeof(triangleData));
494 
495 	return buffer;
496 }
497 
createBindMemoryResultBuffer()498 Move<VkBuffer>  ExternalMemoryHostRenderImageTestInstance::createBindMemoryResultBuffer ()
499 {
500 	Move<VkBuffer>						buffer;
501 	VkDeviceSize						size						= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
502 
503 	const VkBufferCreateInfo			resultBufferCreateInfo =
504 	{
505 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType
506 		DE_NULL,													// const void*			pNext
507 		0,															// VkBufferCreateFlags	flags
508 		size,														// VkDeviceSize			size
509 		VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
510 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,							// VkBufferUsageFlags	usage
511 		VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode
512 		0,															// deUint32				queueFamilyCount
513 		DE_NULL														// const deUint32*		pQueueFamilyIndices
514 	};
515 	buffer															= vk::createBuffer(m_vkd, m_device, &resultBufferCreateInfo, DE_NULL);
516 
517 	const VkMemoryRequirements			bufferMemoryRequirements	= getBufferMemoryRequirements(m_vkd, m_device, *buffer);
518 	m_resultBufferAllocation									    = m_allocator.allocate(bufferMemoryRequirements, MemoryRequirement::HostVisible);
519 
520 	VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, m_resultBufferAllocation->getMemory(), m_resultBufferAllocation->getOffset()));
521 
522 	return buffer;
523 }
524 
createAndUpdateDescriptorSet()525 Move<VkDescriptorSet>  ExternalMemoryHostRenderImageTestInstance::createAndUpdateDescriptorSet ()
526 {
527 	Move<VkDescriptorSet>				descriptorSet;
528 	VkDescriptorBufferInfo				descriptorInfo;
529 
530 	const VkDescriptorSetAllocateInfo	allocInfo =
531 	{
532 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType                             sType
533 		DE_NULL,										// const void*                                 pNext
534 		*m_descriptorPool,								// VkDescriptorPool                            descriptorPool
535 		1u,												// deUint32                                    setLayoutCount
536 		&(m_descriptorSetLayout.get())					// const VkDescriptorSetLayout*                pSetLayouts
537 	};
538 
539 	descriptorSet						= allocateDescriptorSet(m_vkd, m_device, &allocInfo);
540 	descriptorInfo						= makeDescriptorBufferInfo(*m_vertexBuffer, (VkDeviceSize)0u, sizeof(float) * 16);
541 
542 	DescriptorSetUpdateBuilder()
543 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
544 		.update(m_vkd, m_device);
545 
546 	return descriptorSet;
547 }
548 
createPipelineLayout()549 Move<VkPipelineLayout> ExternalMemoryHostRenderImageTestInstance::createPipelineLayout ()
550 {
551 	const VkPipelineLayoutCreateInfo	pipelineLayoutParams =
552 	{
553 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType
554 		DE_NULL,										// const void*					pNext
555 		(VkPipelineLayoutCreateFlags)0,					// VkPipelineLayoutCreateFlags	flags
556 		1u,												// deUint32						descriptorSetCount
557 		&(m_descriptorSetLayout.get()),					// const VkDescriptorSetLayout*	pSetLayouts
558 		0u,												// deUint32						pushConstantRangeCount
559 		DE_NULL											// const VkPushConstantRange*	pPushConstantRanges
560 	};
561 
562 	return vk::createPipelineLayout(m_vkd, m_device, &pipelineLayoutParams);
563 }
564 
createPipeline()565 Move<VkPipeline> ExternalMemoryHostRenderImageTestInstance::createPipeline ()
566 {
567 	Move<VkPipeline>								pipeline;
568 	const std::vector<VkViewport>					viewports(1, makeViewport(tcu::UVec2(100,100)));
569 	const std::vector<VkRect2D>						scissors(1, makeRect2D(tcu::UVec2(100, 100)));
570 	const VkPrimitiveTopology						topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
571 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams =
572 	{
573 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType								sType
574 		DE_NULL,													// const void*									pNext
575 		0u,															// vkPipelineVertexInputStateCreateFlags		flags
576 		0u,															// deUint32										bindingCount
577 		DE_NULL,													// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
578 		0u,															// deUint32										attributeCount
579 		DE_NULL,													// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
580 	};
581 
582 	return	    makeGraphicsPipeline(	m_vkd,						// const DeviceInterface&                       vk
583 										m_device,					// const VkDevice                               device
584 										*m_pipelineLayout,			// const VkPipelineLayout                       pipelineLayout
585 										*m_vertexShaderModule,		// const VkShaderModule                         vertexShaderModule
586 										DE_NULL,					// const VkShaderModule                         tessellationControlShaderModule
587 										DE_NULL,					// const VkShaderModule                         tessellationEvalShaderModule
588 										DE_NULL,					// const VkShaderModule                         geometryShaderModule
589 										*m_fragmentShaderModule,	// const VkShaderModule                         fragmentShaderModule
590 										*m_renderPass,				// const VkRenderPass                           renderPass
591 										viewports,					// const std::vector<VkViewport>&               viewports
592 										scissors,					// const std::vector<VkRect2D>&                 scissors
593 										topology,					// const VkPrimitiveTopology                    topology
594 										0u,							// const deUint32                               subpass
595 										0u,							// const deUint32                               patchControlPoints
596 										&vertexInputStateParams);	// const VkPipelineVertexInputStateCreateInfo*  vertexInputStateCreateInfo
597 }
598 
clear(VkClearColorValue color)599 void ExternalMemoryHostRenderImageTestInstance::clear (VkClearColorValue color)
600 {
601 	const struct VkImageSubresourceRange	subRangeColor	=
602 	{
603 		VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags  aspectMask
604 		0u,                         // deUint32            baseMipLevel
605 		1u,                         // deUint32            mipLevels
606 		0u,                         // deUint32            baseArrayLayer
607 		1u,                         // deUint32            arraySize
608 	};
609 	const VkImageMemoryBarrier				imageBarrier	=
610 	{
611 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType
612 		DE_NULL,										// const void*				pNext
613 		0u,												// VkAccessFlags			srcAccessMask
614 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask
615 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout
616 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout
617 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex
618 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex
619 		*m_image,										// VkImage					image
620 		subRangeColor									// VkImageSubresourceRange	subresourceRange
621 	};
622 
623 	m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
624 	m_vkd.cmdClearColorImage(*m_cmdBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &subRangeColor);
625 }
626 
draw()627 void ExternalMemoryHostRenderImageTestInstance::draw ()
628 {
629 	const struct VkImageSubresourceRange	subRangeColor =
630 	{
631 		VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags  aspectMask
632 		0u,                         // deUint32            baseMipLevel
633 		1u,                         // deUint32            mipLevels
634 		0u,                         // deUint32            baseArrayLayer
635 		1u,                         // deUint32            arraySize
636 	};
637 	const VkImageMemoryBarrier				imageBarrier =
638 	{
639 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType
640 		DE_NULL,										// const void*				pNext
641 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask
642 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask
643 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout
644 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout
645 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex
646 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex
647 		*m_image,										// VkImage					image
648 		subRangeColor									// VkImageSubresourceRange	subresourceRange
649 	};
650 	m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
651 
652 	beginRenderPass(m_vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, 75, 100), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
653 	m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
654 	m_vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
655 	m_vkd.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
656 	endRenderPass(m_vkd, *m_cmdBuffer);
657 }
658 
copyResultImagetoBuffer()659 void ExternalMemoryHostRenderImageTestInstance::copyResultImagetoBuffer ()
660 {
661 	copyImageToBuffer(m_vkd, *m_cmdBuffer, *m_image, *m_resultBuffer, tcu::IVec2(100, 100));
662 }
663 
prepareReferenceImage(tcu::PixelBufferAccess & reference)664 void ExternalMemoryHostRenderImageTestInstance::prepareReferenceImage (tcu::PixelBufferAccess& reference)
665 {
666 	for (int w=0; w < 100; w++)
667 		for (int h = 0; h < 100; h++)
668 		{
669 			if (w < 50)					reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
670 			if ((w >= 50) && (w < 75))	reference.setPixel(tcu::Vec4(1, 0, 0, 1), w, h);
671 			if (w >=75)					reference.setPixel(tcu::Vec4(0, 0, 1, 1), w, h);
672 		}
673 }
674 
createRenderPass()675 Move<VkRenderPass> ExternalMemoryHostRenderImageTestInstance::createRenderPass ()
676 {
677 	const VkAttachmentDescription			colorAttachmentDescription =
678 	{
679 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
680 		m_testParams.m_format,						// VkFormat                        format
681 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits           samples
682 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
683 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
684 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
685 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
686 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout                   initialLayout
687 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
688 	};
689 
690 	std::vector<VkAttachmentDescription>	attachmentDescriptions;
691 	attachmentDescriptions.push_back(colorAttachmentDescription);
692 
693 	const VkAttachmentReference				colorAttachmentRef =
694 	{
695 		0u,											// deUint32         attachment
696 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout    layout
697 	};
698 
699 	const VkSubpassDescription				subpassDescription =
700 	{
701 		(VkSubpassDescriptionFlags)0,				// VkSubpassDescriptionFlags       flags
702 		VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint             pipelineBindPoint
703 		0u,											// deUint32                        inputAttachmentCount
704 		DE_NULL,									// const VkAttachmentReference*    pInputAttachments
705 		1u,											// deUint32                        colorAttachmentCount
706 		&colorAttachmentRef,						// const VkAttachmentReference*    pColorAttachments
707 		DE_NULL,									// const VkAttachmentReference*    pResolveAttachments
708 		DE_NULL,									// const VkAttachmentReference*    pDepthStencilAttachment
709 		0u,											// deUint32                        preserveAttachmentCount
710 		DE_NULL										// const deUint32*                 pPreserveAttachments
711 	};
712 
713 	const VkRenderPassCreateInfo			renderPassInfo =
714 	{
715 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType                   sType
716 		DE_NULL,									// const void*                       pNext
717 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags           flags
718 		(deUint32)attachmentDescriptions.size(),	// deUint32                          attachmentCount
719 		&attachmentDescriptions[0],					// const VkAttachmentDescription*    pAttachments
720 		1u,											// deUint32                          subpassCount
721 		&subpassDescription,						// const VkSubpassDescription*       pSubpasses
722 		0u,											// deUint32                          dependencyCount
723 		DE_NULL										// const VkSubpassDependency*        pDependencies
724 	};
725 
726 	return vk::createRenderPass(m_vkd, m_device, &renderPassInfo);
727 }
728 
ExternalMemoryHostSynchronizationTestInstance(Context & context,TestParams testParams)729 ExternalMemoryHostSynchronizationTestInstance::ExternalMemoryHostSynchronizationTestInstance (Context& context, TestParams testParams)
730 	: ExternalMemoryHostRenderImageTestInstance (context, testParams)
731 {
732 }
733 
iterate()734 tcu::TestStatus ExternalMemoryHostSynchronizationTestInstance::iterate ()
735 {
736 	DE_ASSERT(m_testParams.m_format == VK_FORMAT_R8G8B8A8_UNORM);
737 
738 	const deUint32							queueFamilyIndex							= m_context.getUniversalQueueFamilyIndex();
739 	const VkDeviceSize						dataBufferSize								= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
740 	void*									pointerReturnedByMapMemory;
741 	deUint32								hostPointerMemoryTypeBits;
742 	deUint32								memoryTypeIndexToTest;
743 	VkMemoryRequirements					bufferMemoryRequirements;
744 
745 	m_dataBuffer							= createDataBuffer();
746 
747 	//check memory requirements
748 	bufferMemoryRequirements				= getBufferMemoryRequirements(m_vkd, m_device, *m_dataBuffer);
749 	VkDeviceSize requiredSize				= bufferMemoryRequirements.size;
750 	//reallocate memory if needed
751 	if (requiredSize > m_allocationSize)
752 	{
753 		VkDeviceSize newHostAllocationSize	= VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
754 
755 		m_log << tcu::TestLog::Message << "Realloc needed (required size: " << requiredSize << "). "
756 			<< "New host allocation size: " << newHostAllocationSize << ")." << tcu::TestLog::EndMessage;
757 
758 		m_hostMemoryAlloc					= deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
759 		m_allocationSize					= newHostAllocationSize;
760 	}
761 
762 	//check if reallocation is successfull
763 	if (!m_hostMemoryAlloc)
764 		TCU_FAIL("Failed to reallocate memory block.");
765 
766 	DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
767 
768 	//find the usable memory type index
769 	hostPointerMemoryTypeBits				= getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
770 	if (findCompatibleMemoryTypeIndexToTest(bufferMemoryRequirements.memoryTypeBits, hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
771 		m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
772 	else
773 		TCU_THROW(NotSupportedError, "Compatible memory type not found");
774 
775 	VK_CHECK(m_vkd.bindBufferMemory(m_device, *m_dataBuffer, *m_deviceMemoryAllocatedFromHostPointer, 0));
776 
777 	m_resultBuffer							= createBindMemoryResultBuffer();
778 	m_cmdPool								= createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
779 	m_cmdBuffer								= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
780 	m_cmdBufferCopy							= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
781 
782 	m_event									= createEvent(m_vkd, m_device);
783 	m_fence_1								= createFence(m_vkd, m_device);
784 	m_fence_2								= createFence(m_vkd, m_device);
785 
786 	//record first command buffer
787 	beginCommandBuffer(m_vkd, *m_cmdBuffer);
788 	fillBuffer();
789 	prepareBufferForHostAccess();
790 	endCommandBuffer(m_vkd, *m_cmdBuffer);
791 
792 	//record second command buffer
793 	beginCommandBuffer(m_vkd, *m_cmdBufferCopy);
794 	copyResultBuffertoBuffer();
795 	endCommandBuffer(m_vkd, *m_cmdBufferCopy);
796 
797 	submitCommands(*m_cmdBuffer, *m_fence_1);
798 	submitCommands(*m_cmdBufferCopy, *m_fence_2);
799 
800 	//wait for fence_1 and modify image on host
801 	VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_1.get(), DE_TRUE, ~0ull));
802 	pointerReturnedByMapMemory				= mapMemory(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize, 0);
803 	invalidateMappedMemoryRange(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize);
804 	tcu::PixelBufferAccess bufferSurface(mapVkFormat(m_testParams.m_format), 100, 100, 1, (100 * vk::mapVkFormat(m_testParams.m_format).getPixelSize()), 0, m_hostMemoryAlloc);
805 	prepareReferenceImage(bufferSurface);
806 	flushMappedMemoryRange(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize);
807 	//compare memory pointed by both pointers
808 	if (deMemCmp(m_hostMemoryAlloc, pointerReturnedByMapMemory, (size_t)dataBufferSize) != 0)
809 		TCU_FAIL("Failed memcmp check.");
810 	m_vkd.unmapMemory(m_device, *m_deviceMemoryAllocatedFromHostPointer);
811 	VK_CHECK(m_vkd.setEvent(m_device, *m_event));
812 
813 	//wait for fence_2 before checking result
814 	VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_2.get(), DE_TRUE, ~0ull));
815 
816 	void * bufferDataPointer				= static_cast<char*>(m_resultBufferAllocation->getHostPtr()) + m_resultBufferAllocation->getOffset();
817 	tcu::ConstPixelBufferAccess				result(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), bufferDataPointer);
818 
819 	std::vector<float>						referenceData((unsigned int)dataBufferSize, 0);
820 	tcu::PixelBufferAccess					reference(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), referenceData.data());
821 
822 	prepareReferenceImage(reference);
823 
824 	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
825 		return tcu::TestStatus::fail("Fail");
826 
827 	return tcu::TestStatus::pass("Pass");
828 }
829 
prepareBufferForHostAccess()830 void ExternalMemoryHostSynchronizationTestInstance::prepareBufferForHostAccess ()
831 {
832 	VkDeviceSize					size								= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
833 	const VkBufferMemoryBarrier		bufferBarrier =
834 	{
835 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
836 		DE_NULL,									// const void*		pNext;
837 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
838 		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	dstAccessMask;
839 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
840 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
841 		*m_dataBuffer,								// VkBuffer			buffer;
842 		0u,											// VkDeviceSize		offset;
843 		size										// VkDeviceSize		size;
844 	};
845 
846 	m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
847 }
848 
copyResultBuffertoBuffer()849 void ExternalMemoryHostSynchronizationTestInstance::copyResultBuffertoBuffer ()
850 {
851 	VkDeviceSize					size								= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
852 	const VkBufferMemoryBarrier		bufferBarrier =
853 	{
854 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
855 		DE_NULL,									// const void*		pNext;
856 		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
857 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
858 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
859 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
860 		*m_dataBuffer,								// VkBuffer			buffer;
861 		0u,											// VkDeviceSize		offset;
862 		size										// VkDeviceSize		size;
863 	};
864 
865 	const VkBufferCopy				region_all =
866 	{
867 		0,		//VkDeviceSize srcOffset;
868 		0,		//VkDeviceSize dstOffset;
869 		size	//VkDeviceSize size;
870 	};
871 
872 	m_vkd.cmdWaitEvents(*m_cmdBufferCopy, 1, &m_event.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, DE_NULL, 1, &bufferBarrier, 0, DE_NULL);
873 	m_vkd.cmdCopyBuffer(*m_cmdBufferCopy, *m_dataBuffer, *m_resultBuffer, 1, &region_all);
874 }
875 
submitCommands(VkCommandBuffer commandBuffer,VkFence fence)876 void ExternalMemoryHostSynchronizationTestInstance::submitCommands (VkCommandBuffer commandBuffer, VkFence fence)
877 {
878 	const VkSubmitInfo		submitInfo =
879 	{
880 		VK_STRUCTURE_TYPE_SUBMIT_INFO,						// VkStructureType				sType
881 		DE_NULL,											// const void*					pNext
882 		0u,													// deUint32						waitSemaphoreCount
883 		DE_NULL,											// const VkSemaphore*			pWaitSemaphores
884 		(const VkPipelineStageFlags*)DE_NULL,				// const VkPipelineStageFlags*	pWaitDstStageMask
885 		1u,													// deUint32						commandBufferCount
886 		&commandBuffer,										// const VkCommandBuffer*		pCommandBuffers
887 		0u,													// deUint32						signalSemaphoreCount
888 		DE_NULL,											// const VkSemaphore*			pSignalSemaphores
889 	};
890 
891 	VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
892 }
893 
createDataBuffer()894 Move<VkBuffer> ExternalMemoryHostSynchronizationTestInstance::createDataBuffer ()
895 {
896 	VkDeviceSize					size								= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
897 	const VkBufferCreateInfo		dataBufferCreateInfo =
898 	{
899 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType
900 		DE_NULL,								// const void*			pNext
901 		0,										// VkBufferCreateFlags	flag
902 		size,									// VkDeviceSize			size
903 		VK_BUFFER_USAGE_TRANSFER_DST_BIT |
904 		VK_BUFFER_USAGE_TRANSFER_SRC_BIT,		// VkBufferUsageFlags	usage
905 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode
906 		0,										// deUint32				queueFamilyCount
907 		DE_NULL									// const deUint32*		pQueueFamilyIndices
908 	};
909 	return vk::createBuffer(m_vkd, m_device, &dataBufferCreateInfo, DE_NULL);
910 }
911 
fillBuffer()912 void ExternalMemoryHostSynchronizationTestInstance::fillBuffer ()
913 {
914 	VkDeviceSize					size								= 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
915 	const VkBufferMemoryBarrier		bufferBarrier =
916 	{
917 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
918 		DE_NULL,									// const void*		pNext;
919 		0u,											// VkAccessFlags	srcAccessMask;
920 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	dstAccessMask;
921 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
922 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
923 		*m_dataBuffer,								// VkBuffer			buffer;
924 		0u,											// VkDeviceSize		offset;
925 		size										// VkDeviceSize		size;
926 	};
927 
928 	m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
929 	m_vkd.cmdFillBuffer(*m_cmdBuffer, *m_dataBuffer, 0, size, 0xFFFFFFFF);
930 }
931 
932 struct AddPrograms
933 {
initvkt::memory::__anon67350ce20111::AddPrograms934 	void init (vk::SourceCollections& sources, TestParams testParams) const
935 	{
936 			//unused parameter
937 			DE_UNREF(testParams);
938 
939 			const char* const vertexShader =
940 			"#version 430\n"
941 
942 			"layout(std430, binding = 0) buffer BufferPos {\n"
943 			"vec4 p[100];\n"
944 			"} pos;\n"
945 
946 			"out gl_PerVertex{\n"
947 			"vec4 gl_Position;\n"
948 			"};\n"
949 
950 			"void main() {\n"
951 			"gl_Position = pos.p[gl_VertexIndex];\n"
952 			"}\n";
953 
954 		sources.glslSources.add("position_only.vert")
955 			<< glu::VertexSource(vertexShader);
956 
957 		const char* const fragmentShader =
958 			"#version 430\n"
959 
960 			"layout(location = 0) out vec4 my_FragColor;\n"
961 
962 			"void main() {\n"
963 			"my_FragColor = vec4(0,1,0,1);\n"
964 			"}\n";
965 
966 		sources.glslSources.add("only_color_out.frag")
967 			<< glu::FragmentSource(fragmentShader);
968 	}
969 };
970 
971 } // unnamed namespace
972 
createMemoryExternalMemoryHostTests(tcu::TestContext & testCtx)973 tcu::TestCaseGroup* createMemoryExternalMemoryHostTests (tcu::TestContext& testCtx)
974 {
975 	de::MovePtr<tcu::TestCaseGroup>	group(new tcu::TestCaseGroup(testCtx, "external_memory_host", "VK_EXT_external_memory_host extension tests."));
976 	de::MovePtr<tcu::TestCaseGroup>	simpleAllocation(new tcu::TestCaseGroup(testCtx, "simple_allocation", "simple allocation tests."));
977 	de::MovePtr<tcu::TestCaseGroup>	bind_image_memory_and_render(new tcu::TestCaseGroup(testCtx, "bind_image_memory_and_render", "render tests."));
978 	de::MovePtr<tcu::TestCaseGroup>	with_zero_offset(new tcu::TestCaseGroup(testCtx, "with_zero_offset", "bind object with zero offset specified"));
979 	de::MovePtr<tcu::TestCaseGroup>	with_non_zero_offset(new tcu::TestCaseGroup(testCtx, "with_non_zero_offset", "bind object with zero offset specified"));
980 	de::MovePtr<tcu::TestCaseGroup>	synchronization(new tcu::TestCaseGroup(testCtx, "synchronization", "synchronization tests."));
981 
982 	//test cases:
983 	simpleAllocation->addChild(new InstanceFactory1<ExternalMemoryHostBaseTestInstance, VkDeviceSize> (testCtx, tcu::NODETYPE_SELF_VALIDATE, "minImportedHostPointerAlignment_x1",
984 																									  "allocate minImportedHostPointerAlignment multiplied by 1", 1));
985 	simpleAllocation->addChild(new InstanceFactory1<ExternalMemoryHostBaseTestInstance, VkDeviceSize> (testCtx, tcu::NODETYPE_SELF_VALIDATE, "minImportedHostPointerAlignment_x3",
986 																									  "allocate minImportedHostPointerAlignment multiplied by 3", 3));
987 	group ->addChild(simpleAllocation.release());
988 
989 	const VkFormat testFormats[] = {
990 		VK_FORMAT_R8G8B8A8_UNORM,
991 		VK_FORMAT_R16G16B16A16_UNORM,
992 		VK_FORMAT_R16G16B16A16_SFLOAT,
993 		VK_FORMAT_R32G32B32A32_SFLOAT
994 	};
995 
996 	const std::string testNames[] = {
997 		"r8g8b8a8_unorm",
998 		"r16g16b16a16_unorm",
999 		"r16g16b16a16_sfloat",
1000 		"r32g32b32a32_sfloat"
1001 	};
1002 
1003 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(testFormats); formatNdx++)
1004 	{
1005 		std::string testName = testNames[formatNdx];
1006 		with_zero_offset->addChild(new InstanceFactory1<ExternalMemoryHostRenderImageTestInstance, TestParams, AddPrograms>	(testCtx, tcu::NODETYPE_SELF_VALIDATE,
1007 																															testName, testName, AddPrograms(),
1008 																															TestParams(testFormats[formatNdx])));
1009 	}
1010 	bind_image_memory_and_render->addChild(with_zero_offset.release());
1011 
1012 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(testFormats); formatNdx++)
1013 	{
1014 		std::string testName = testNames[formatNdx];
1015 		with_non_zero_offset->addChild(new InstanceFactory1<ExternalMemoryHostRenderImageTestInstance, TestParams, AddPrograms>	(testCtx, tcu::NODETYPE_SELF_VALIDATE,
1016 																																testName, testName, AddPrograms(),
1017 																																TestParams(testFormats[formatNdx], true)));
1018 	}
1019 	bind_image_memory_and_render->addChild(with_non_zero_offset.release());
1020 
1021 	group->addChild(bind_image_memory_and_render.release());
1022 
1023 	synchronization->addChild(new InstanceFactory1<ExternalMemoryHostSynchronizationTestInstance, TestParams, AddPrograms>	(testCtx, tcu::NODETYPE_SELF_VALIDATE,
1024 																															"synchronization", "synchronization", AddPrograms(),
1025 																															TestParams(testFormats[0], true)));
1026 	group->addChild(synchronization.release());
1027 	return group.release();
1028 }
1029 
1030 } // memory
1031 } // vkt
1032