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