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