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