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