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