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, ®ion_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