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, &region_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