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