xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Memory binding test excercising VK_KHR_bind_memory2 extension.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktMemoryBindingTests.hpp"
25 
26 #include "vktTestCase.hpp"
27 #include "tcuTestLog.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 
30 #include "vkPlatform.hpp"
31 #include "tcuCommandLine.hpp"
32 #include "gluVarType.hpp"
33 #include "deStringUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "deSharedPtr.hpp"
38 #include "vktTestCase.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkImageUtil.hpp"
42 
43 #include <algorithm>
44 
45 namespace vkt
46 {
47 namespace memory
48 {
49 namespace
50 {
51 
52 using namespace vk;
53 
54 typedef const VkMemoryDedicatedAllocateInfo ConstDedicatedInfo;
55 typedef de::SharedPtr<Move<VkDeviceMemory>> MemoryRegionPtr;
56 typedef std::vector<MemoryRegionPtr> MemoryRegionsList;
57 typedef de::SharedPtr<Move<VkBuffer>> BufferPtr;
58 typedef std::vector<BufferPtr> BuffersList;
59 typedef de::SharedPtr<Move<VkImage>> ImagePtr;
60 typedef std::vector<ImagePtr> ImagesList;
61 typedef std::vector<VkBindBufferMemoryInfo> BindBufferMemoryInfosList;
62 typedef std::vector<VkBindImageMemoryInfo> BindImageMemoryInfosList;
63 #ifndef CTS_USES_VULKANSC
64 typedef std::vector<VkBindMemoryStatusKHR> BindMemoryStatusList;
65 #endif // CTS_USES_VULKANSC
66 
67 class MemoryMappingRAII
68 {
69 public:
MemoryMappingRAII(const DeviceInterface & deviceInterface,const VkDevice & device,VkDeviceMemory deviceMemory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags)70     MemoryMappingRAII(const DeviceInterface &deviceInterface, const VkDevice &device, VkDeviceMemory deviceMemory,
71                       VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
72         : vk(deviceInterface)
73         , dev(device)
74         , memory(deviceMemory)
75         , hostPtr(DE_NULL)
76 
77     {
78         vk.mapMemory(dev, memory, offset, size, flags, &hostPtr);
79     }
80 
~MemoryMappingRAII()81     ~MemoryMappingRAII()
82     {
83         vk.unmapMemory(dev, memory);
84         hostPtr = DE_NULL;
85     }
86 
ptr()87     void *ptr()
88     {
89         return hostPtr;
90     }
91 
flush()92     void flush()
93     {
94         const VkMappedMemoryRange range = makeMemoryRange(0, VK_WHOLE_SIZE);
95         VK_CHECK(vk.flushMappedMemoryRanges(dev, 1u, &range));
96     }
97 
invalidate()98     void invalidate()
99     {
100         const VkMappedMemoryRange range = makeMemoryRange(0, VK_WHOLE_SIZE);
101         VK_CHECK(vk.invalidateMappedMemoryRanges(dev, 1u, &range));
102     }
103 
104 protected:
105     const DeviceInterface &vk;
106     const VkDevice &dev;
107     VkDeviceMemory memory;
108     void *hostPtr;
109 
makeMemoryRange(VkDeviceSize offset,VkDeviceSize size)110     const VkMappedMemoryRange makeMemoryRange(VkDeviceSize offset, VkDeviceSize size)
111     {
112         const VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, DE_NULL, memory, offset, size};
113         return range;
114     }
115 };
116 
117 class SimpleRandomGenerator
118 {
119 public:
SimpleRandomGenerator(uint32_t seed)120     SimpleRandomGenerator(uint32_t seed) : value(seed)
121     {
122     }
getNext()123     uint32_t getNext()
124     {
125         value += 1;
126         value ^= (value << 21);
127         value ^= (value >> 15);
128         value ^= (value << 4);
129         return value;
130     }
131 
132 protected:
133     uint32_t value;
134 };
135 
136 enum PriorityMode
137 {
138     PRIORITY_MODE_DEFAULT,
139     PRIORITY_MODE_STATIC,
140     PRIORITY_MODE_DYNAMIC,
141 };
142 
143 struct BindingCaseParameters
144 {
145     VkBufferCreateFlags flags;
146     VkBufferUsageFlags usage;
147     VkSharingMode sharing;
148     VkDeviceSize bufferSize;
149     VkExtent3D imageSize;
150     uint32_t targetsCount;
151     VkImageCreateFlags imageCreateFlags;
152     PriorityMode priorityMode;
153     bool checkIndividualResult;
154 };
155 
makeBindingCaseParameters(uint32_t targetsCount,uint32_t width,uint32_t height,VkImageCreateFlags imageCreateFlags,PriorityMode priorityMode,bool checkIndividualResult)156 BindingCaseParameters makeBindingCaseParameters(uint32_t targetsCount, uint32_t width, uint32_t height,
157                                                 VkImageCreateFlags imageCreateFlags, PriorityMode priorityMode,
158                                                 bool checkIndividualResult)
159 {
160     BindingCaseParameters params;
161     deMemset(&params, 0, sizeof(BindingCaseParameters));
162     params.imageSize.width  = width;
163     params.imageSize.height = height;
164     params.imageSize.depth  = 1;
165     params.bufferSize   = params.imageSize.width * params.imageSize.height * params.imageSize.depth * sizeof(uint32_t);
166     params.usage        = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
167     params.targetsCount = targetsCount;
168     params.imageCreateFlags      = imageCreateFlags;
169     params.priorityMode          = priorityMode;
170     params.checkIndividualResult = checkIndividualResult;
171     return params;
172 }
173 
makeBindingCaseParameters(uint32_t targetsCount,VkBufferUsageFlags usage,VkSharingMode sharing,VkDeviceSize bufferSize,VkImageCreateFlags imageCreateFlags,PriorityMode priorityMode,bool checkIndividualResult)174 BindingCaseParameters makeBindingCaseParameters(uint32_t targetsCount, VkBufferUsageFlags usage, VkSharingMode sharing,
175                                                 VkDeviceSize bufferSize, VkImageCreateFlags imageCreateFlags,
176                                                 PriorityMode priorityMode, bool checkIndividualResult)
177 {
178     BindingCaseParameters params = {
179         0,                    // VkBufferCreateFlags flags;
180         usage,                // VkBufferUsageFlags usage;
181         sharing,              // VkSharingMode sharing;
182         bufferSize,           // VkDeviceSize bufferSize;
183         {0u, 0u, 0u},         // VkExtent3D imageSize;
184         targetsCount,         // uint32_t targetsCount;
185         imageCreateFlags,     // VkImageCreateFlags    imageCreateFlags
186         priorityMode,         // PriorityMode            priorityMode
187         checkIndividualResult // bool                checkIndividualResult
188     };
189     return params;
190 }
191 
makeImageCreateInfo(BindingCaseParameters & params)192 VkImageCreateInfo makeImageCreateInfo(BindingCaseParameters &params)
193 {
194     const VkImageCreateInfo imageParams = {
195         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                               // VkStructureType sType;
196         DE_NULL,                                                           // const void* pNext;
197         params.imageCreateFlags,                                           // VkImageCreateFlags flags;
198         VK_IMAGE_TYPE_2D,                                                  // VkImageType imageType;
199         VK_FORMAT_R8G8B8A8_UINT,                                           // VkFormat format;
200         params.imageSize,                                                  // VkExtent3D extent;
201         1u,                                                                // uint32_t mipLevels;
202         1u,                                                                // uint32_t arrayLayers;
203         VK_SAMPLE_COUNT_1_BIT,                                             // VkSampleCountFlagBits samples;
204         VK_IMAGE_TILING_LINEAR,                                            // VkImageTiling tiling;
205         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
206         VK_SHARING_MODE_EXCLUSIVE,                                         // VkSharingMode sharingMode;
207         0u,                                                                // uint32_t queueFamilyIndexCount;
208         DE_NULL,                                                           // const uint32_t* pQueueFamilyIndices;
209         VK_IMAGE_LAYOUT_UNDEFINED,                                         // VkImageLayout initialLayout;
210     };
211     return imageParams;
212 }
213 
makeBufferCreateInfo(Context & ctx,BindingCaseParameters & params)214 VkBufferCreateInfo makeBufferCreateInfo(Context &ctx, BindingCaseParameters &params)
215 {
216     const uint32_t queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
217     VkBufferCreateInfo bufferParams = {
218         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
219         DE_NULL,                              // const void* pNext;
220         params.flags,                         // VkBufferCreateFlags flags;
221         params.bufferSize,                    // VkDeviceSize size;
222         params.usage,                         // VkBufferUsageFlags usage;
223         params.sharing,                       // VkSharingMode sharingMode;
224         1u,                                   // uint32_t queueFamilyIndexCount;
225         &queueFamilyIndex,                    // const uint32_t* pQueueFamilyIndices;
226     };
227     return bufferParams;
228 }
229 
makeMemoryAllocateInfo(VkMemoryRequirements & memReqs,const void * next)230 const VkMemoryAllocateInfo makeMemoryAllocateInfo(VkMemoryRequirements &memReqs, const void *next)
231 {
232     const uint32_t heapTypeIndex              = (uint32_t)deCtz32(memReqs.memoryTypeBits);
233     const VkMemoryAllocateInfo allocateParams = {
234         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
235         next,                                   // const void* pNext;
236         memReqs.size,                           // VkDeviceSize allocationSize;
237         heapTypeIndex,                          // uint32_t memoryTypeIndex;
238     };
239     return allocateParams;
240 }
241 
242 enum MemoryHostVisibility
243 {
244     MemoryAny,
245     MemoryHostVisible
246 };
247 
selectMatchingMemoryType(Context & ctx,VkMemoryRequirements & memReqs,MemoryHostVisibility memoryVisibility)248 uint32_t selectMatchingMemoryType(Context &ctx, VkMemoryRequirements &memReqs, MemoryHostVisibility memoryVisibility)
249 {
250     const VkPhysicalDevice vkPhysicalDevice = ctx.getPhysicalDevice();
251     const InstanceInterface &vkInstance     = ctx.getInstanceInterface();
252     VkPhysicalDeviceMemoryProperties memoryProperties;
253 
254     vkInstance.getPhysicalDeviceMemoryProperties(vkPhysicalDevice, &memoryProperties);
255     if (memoryVisibility == MemoryHostVisible)
256     {
257         for (uint32_t typeNdx = 0; typeNdx < memoryProperties.memoryTypeCount; ++typeNdx)
258         {
259             const bool isInAllowed = (memReqs.memoryTypeBits & (1u << typeNdx)) != 0u;
260             const bool hasRightProperties =
261                 (memoryProperties.memoryTypes[typeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u;
262             if (isInAllowed && hasRightProperties)
263                 return typeNdx;
264         }
265     }
266     return (uint32_t)deCtz32(memReqs.memoryTypeBits);
267 }
268 
makeMemoryAllocateInfo(Context & ctx,VkMemoryRequirements & memReqs,MemoryHostVisibility memoryVisibility)269 const VkMemoryAllocateInfo makeMemoryAllocateInfo(Context &ctx, VkMemoryRequirements &memReqs,
270                                                   MemoryHostVisibility memoryVisibility)
271 {
272     const uint32_t heapTypeIndex              = selectMatchingMemoryType(ctx, memReqs, memoryVisibility);
273     const VkMemoryAllocateInfo allocateParams = {
274         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
275         DE_NULL,                                // const void* pNext;
276         memReqs.size,                           // VkDeviceSize allocationSize;
277         heapTypeIndex,                          // uint32_t memoryTypeIndex;
278     };
279     return allocateParams;
280 }
281 
makeDedicatedAllocationInfo(VkBuffer buffer)282 ConstDedicatedInfo makeDedicatedAllocationInfo(VkBuffer buffer)
283 {
284     ConstDedicatedInfo dedicatedAllocationInfo = {
285         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // VkStructureType        sType
286         DE_NULL,                                          // const void*            pNext
287         DE_NULL,                                          // VkImage                image
288         buffer                                            // VkBuffer                buffer
289     };
290     return dedicatedAllocationInfo;
291 }
292 
makeDedicatedAllocationInfo(VkImage image)293 ConstDedicatedInfo makeDedicatedAllocationInfo(VkImage image)
294 {
295     ConstDedicatedInfo dedicatedAllocationInfo = {
296         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // VkStructureType        sType
297         DE_NULL,                                          // const void*            pNext
298         image,                                            // VkImage                image
299         DE_NULL                                           // VkBuffer                buffer
300     };
301     return dedicatedAllocationInfo;
302 }
303 
makeBufferMemoryBindingInfo(VkBuffer buffer,VkDeviceMemory memory,const void * pNext)304 const VkBindBufferMemoryInfo makeBufferMemoryBindingInfo(VkBuffer buffer, VkDeviceMemory memory, const void *pNext)
305 {
306     const VkBindBufferMemoryInfo bufferMemoryBinding = {
307         VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, // VkStructureType sType;
308         pNext,                                     // const void* pNext;
309         buffer,                                    // VkBuffer buffer;
310         memory,                                    // VkDeviceMemory memory;
311         0u,                                        // VkDeviceSize memoryOffset;
312     };
313     return bufferMemoryBinding;
314 }
315 
makeImageMemoryBindingInfo(VkImage image,VkDeviceMemory memory,const void * pNext)316 const VkBindImageMemoryInfo makeImageMemoryBindingInfo(VkImage image, VkDeviceMemory memory, const void *pNext)
317 {
318     const VkBindImageMemoryInfo imageMemoryBinding = {
319         VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, // VkStructureType sType;
320         pNext,                                    // const void* pNext;
321         image,                                    // VkImage image;
322         memory,                                   // VkDeviceMemory memory;
323         0u,                                       // VkDeviceSize memoryOffset;
324     };
325     return imageMemoryBinding;
326 }
327 
328 #ifndef CTS_USES_VULKANSC
makeMemoryPriorityAllocateInfo(const void * pNext,float priority)329 const VkMemoryPriorityAllocateInfoEXT makeMemoryPriorityAllocateInfo(const void *pNext, float priority)
330 {
331     const VkMemoryPriorityAllocateInfoEXT info = {
332         VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT, // VkStructureType sType;
333         pNext,                                               // const void* pNext;
334         priority,                                            // float                priority
335     };
336     return info;
337 }
338 
makeBindMemoryStatus(VkResult * pResult)339 const VkBindMemoryStatusKHR makeBindMemoryStatus(VkResult *pResult)
340 {
341     const VkBindMemoryStatusKHR bindMemoryStatus = {
342         VK_STRUCTURE_TYPE_BIND_MEMORY_STATUS_KHR, // VkStructureType sType;
343         DE_NULL,                                  // const void* pNext;
344         pResult,                                  // VkResult* pResult;
345     };
346     return bindMemoryStatus;
347 }
348 #endif
349 
350 enum TransferDirection
351 {
352     TransferToResource   = 0,
353     TransferFromResource = 1
354 };
355 
makeMemoryBarrierInfo(VkBuffer buffer,VkDeviceSize size,TransferDirection direction)356 const VkBufferMemoryBarrier makeMemoryBarrierInfo(VkBuffer buffer, VkDeviceSize size, TransferDirection direction)
357 {
358     const bool fromRes = direction == TransferFromResource;
359     const VkAccessFlags srcMask =
360         static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_HOST_WRITE_BIT : VK_ACCESS_TRANSFER_WRITE_BIT);
361     const VkAccessFlags dstMask =
362         static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_HOST_READ_BIT);
363     const VkBufferMemoryBarrier bufferBarrier = {
364         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
365         DE_NULL,                                 // const void* pNext;
366         srcMask,                                 // VkAccessFlags srcAccessMask;
367         dstMask,                                 // VkAccessFlags dstAccessMask;
368         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t srcQueueFamilyIndex;
369         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t dstQueueFamilyIndex;
370         buffer,                                  // VkBuffer buffer;
371         0u,                                      // VkDeviceSize offset;
372         size                                     // VkDeviceSize size;
373     };
374     return bufferBarrier;
375 }
376 
makeMemoryBarrierInfo(VkImage image,VkAccessFlags srcAccess,VkAccessFlags dstAccess,VkImageLayout oldLayout,VkImageLayout newLayout)377 const VkImageMemoryBarrier makeMemoryBarrierInfo(VkImage image, VkAccessFlags srcAccess, VkAccessFlags dstAccess,
378                                                  VkImageLayout oldLayout, VkImageLayout newLayout)
379 {
380     const VkImageAspectFlags aspect         = VK_IMAGE_ASPECT_COLOR_BIT;
381     const VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
382                                                DE_NULL,                                // const void* pNext;
383                                                srcAccess,                              // VkAccessFlags srcAccessMask;
384                                                dstAccess,                              // VkAccessFlags dstAccessMask;
385                                                oldLayout,                              // VkImageLayout oldLayout;
386                                                newLayout,                              // VkImageLayout newLayout;
387                                                VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
388                                                VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
389                                                image,                                  // VkImage image;
390                                                {
391                                                    // VkImageSubresourceRange subresourceRange;
392                                                    aspect, // VkImageAspectFlags aspect;
393                                                    0u,     // uint32_t baseMipLevel;
394                                                    1u,     // uint32_t mipLevels;
395                                                    0u,     // uint32_t baseArraySlice;
396                                                    1u,     // uint32_t arraySize;
397                                                }};
398     return imageBarrier;
399 }
400 
createCommandBuffer(const DeviceInterface & vk,VkDevice device,VkCommandPool commandPool)401 Move<VkCommandBuffer> createCommandBuffer(const DeviceInterface &vk, VkDevice device, VkCommandPool commandPool)
402 {
403     const VkCommandBufferAllocateInfo allocInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, DE_NULL, commandPool,
404                                                    VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
405     return allocateCommandBuffer(vk, device, &allocInfo);
406 }
407 
408 class BaseTestInstance : public TestInstance
409 {
410 public:
BaseTestInstance(Context & ctx,BindingCaseParameters params)411     BaseTestInstance(Context &ctx, BindingCaseParameters params) : TestInstance(ctx), m_params(params)
412     {
413 #ifndef CTS_USES_VULKANSC
414         if (m_params.priorityMode == PRIORITY_MODE_DYNAMIC)
415         {
416             VkInstance instance(m_context.getInstance());
417             InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
418             const float queuePriority = 1.0f;
419 
420             VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT pageableDeviceLocalMemoryFeature = {
421                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT, // VkStructureType                    sType
422                 DE_NULL,  // const void*                        pNext
423                 VK_FALSE, // VkBool32 pageableDeviceLocalMemory;
424             };
425 
426             VkPhysicalDeviceMaintenance6FeaturesKHR maintenance6Feature = {
427                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR, // VkStructureType                    sType
428                 DE_NULL,  // const void*                        pNext
429                 VK_FALSE, // VkBool32 maintenance6;
430             };
431             if (m_params.checkIndividualResult)
432                 pageableDeviceLocalMemoryFeature.pNext = &maintenance6Feature;
433 
434             VkPhysicalDeviceFeatures features;
435             deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
436 
437             VkPhysicalDeviceFeatures2 features2 = {
438                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType                    sType
439                 &pageableDeviceLocalMemoryFeature,            // const void*                        pNext
440                 features                                      // VkPhysicalDeviceFeatures            features
441             };
442 
443             instanceDriver.getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &features2);
444 
445             if (!pageableDeviceLocalMemoryFeature.pageableDeviceLocalMemory)
446                 TCU_FAIL("pageableDeviceLocalMemory feature not supported but VK_EXT_pageable_device_local_memory "
447                          "advertised");
448 
449             if (m_params.checkIndividualResult && !maintenance6Feature.maintenance6)
450                 TCU_FAIL("maintenance6 feature not supported but VK_KHR_maintenance6 advertised");
451 
452             pageableDeviceLocalMemoryFeature.pageableDeviceLocalMemory = VK_TRUE;
453 
454             std::vector<const char *> deviceExtensions;
455             deviceExtensions.push_back("VK_EXT_memory_priority");
456             deviceExtensions.push_back("VK_EXT_pageable_device_local_memory");
457             if (m_params.checkIndividualResult)
458                 deviceExtensions.push_back("VK_KHR_maintenance6");
459 
460             VkDeviceQueueCreateInfo queueInfo = {
461                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
462                 DE_NULL,                                    // const void* pNext;
463                 0u,                                         // VkDeviceQueueCreateFlags flags;
464                 0u,                                         // uint32_t queueFamilyIndex;
465                 1u,                                         // uint32_t queueCount;
466                 &queuePriority                              // const float* pQueuePriorities;
467             };
468 
469             const VkDeviceCreateInfo deviceInfo = {
470                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
471                 &features2,                           // const void* pNext;
472                 (VkDeviceCreateFlags)0,               // VkDeviceCreateFlags flags;
473                 1u,                                   // uint32_t queueCreateInfoCount;
474                 &queueInfo,                           // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
475                 0u,                                   // uint32_t enabledLayerCount;
476                 DE_NULL,                              // const char* const* ppEnabledLayerNames;
477                 uint32_t(deviceExtensions.size()),    // uint32_t enabledExtensionCount;
478                 (deviceExtensions.empty()) ? DE_NULL :
479                                              deviceExtensions.data(), // const char* const* ppEnabledExtensionNames;
480                 DE_NULL // const VkPhysicalDeviceFeatures* pEnabledFeatures;
481             };
482 
483             m_logicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
484                                                  m_context.getPlatformInterface(), instance, instanceDriver,
485                                                  m_context.getPhysicalDevice(), &deviceInfo);
486         }
487 #endif // CTS_USES_VULKANSC
488         m_logicalDeviceInterface = de::MovePtr<DeviceDriver>(
489             new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), getDevice(),
490                              m_context.getUsedApiVersion(), m_context.getTestContext().getCommandLine()));
491         m_logicalDeviceInterface->getDeviceQueue(getDevice(), m_context.getUniversalQueueFamilyIndex(), 0,
492                                                  &m_logicalDeviceQueue);
493     };
494 
495 protected:
getDevice(void)496     vk::VkDevice getDevice(void)
497     {
498         return (m_params.priorityMode == PRIORITY_MODE_DYNAMIC) ? m_logicalDevice.get() : m_context.getDevice();
499     }
getDeviceInterface(void)500     const DeviceInterface &getDeviceInterface(void)
501     {
502         return (m_params.priorityMode == PRIORITY_MODE_DYNAMIC) ? *m_logicalDeviceInterface.get() :
503                                                                   m_context.getDeviceInterface();
504     }
getUniversalQueue(void)505     VkQueue getUniversalQueue(void)
506     {
507         return (m_params.priorityMode == PRIORITY_MODE_DYNAMIC) ? m_logicalDeviceQueue : m_context.getUniversalQueue();
508     }
509 
510     template <typename TTarget>
511     void createBindingTargets(std::vector<de::SharedPtr<Move<TTarget>>> &targets);
512 
513     template <typename TTarget, bool TDedicated>
514     void createMemory(std::vector<de::SharedPtr<Move<TTarget>>> &targets, MemoryRegionsList &memory);
515 
516     template <typename TTarget>
517     void makeBinding(std::vector<de::SharedPtr<Move<TTarget>>> &targets, MemoryRegionsList &memory);
518 
519     template <typename TTarget>
520     void fillUpResource(Move<VkBuffer> &source, Move<TTarget> &target);
521 
522     template <typename TTarget>
523     void readUpResource(Move<TTarget> &source, Move<VkBuffer> &target);
524 
525     template <typename TTarget>
526     void layoutTransitionResource(Move<TTarget> &target);
527 
528     void createBuffer(Move<VkBuffer> &buffer, Move<VkDeviceMemory> &memory, VkDeviceSize *memorySize);
529 
530     void pushData(VkDeviceMemory memory, uint32_t dataSeed, VkDeviceSize size);
531 
532     bool checkData(VkDeviceMemory memory, uint32_t dataSeed, VkDeviceSize size);
533 
534     BindingCaseParameters m_params;
535 
536 private:
537     vk::Move<vk::VkDevice> m_logicalDevice;
538     de::MovePtr<DeviceDriver> m_logicalDeviceInterface;
539     VkQueue m_logicalDeviceQueue;
540 };
541 
542 template <>
createBindingTargets(BuffersList & targets)543 void BaseTestInstance::createBindingTargets<VkBuffer>(BuffersList &targets)
544 {
545     const uint32_t count      = m_params.targetsCount;
546     const VkDevice vkDevice   = getDevice();
547     const DeviceInterface &vk = getDeviceInterface();
548 
549     targets.reserve(count);
550     for (uint32_t i = 0u; i < count; ++i)
551     {
552         VkBufferCreateInfo bufferParams = makeBufferCreateInfo(m_context, m_params);
553         targets.push_back(BufferPtr(new Move<VkBuffer>(vk::createBuffer(vk, vkDevice, &bufferParams))));
554     }
555 }
556 
557 template <>
createBindingTargets(ImagesList & targets)558 void BaseTestInstance::createBindingTargets<VkImage>(ImagesList &targets)
559 {
560     const uint32_t count      = m_params.targetsCount;
561     const VkDevice vkDevice   = getDevice();
562     const DeviceInterface &vk = getDeviceInterface();
563 
564     targets.reserve(count);
565     for (uint32_t i = 0u; i < count; ++i)
566     {
567         VkImageCreateInfo imageParams = makeImageCreateInfo(m_params);
568         targets.push_back(ImagePtr(new Move<VkImage>(createImage(vk, vkDevice, &imageParams))));
569     }
570 }
571 
572 template <>
createMemory(BuffersList & targets,MemoryRegionsList & memory)573 void BaseTestInstance::createMemory<VkBuffer, false>(BuffersList &targets, MemoryRegionsList &memory)
574 {
575     const uint32_t count      = static_cast<uint32_t>(targets.size());
576     const DeviceInterface &vk = getDeviceInterface();
577     const VkDevice vkDevice   = getDevice();
578 
579     memory.reserve(count);
580     for (uint32_t i = 0; i < count; ++i)
581     {
582         VkMemoryRequirements memReqs;
583 
584         vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs);
585 
586 #ifdef CTS_USES_VULKANSC
587         const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, DE_NULL);
588 #else
589         VkMemoryPriorityAllocateInfoEXT priority = makeMemoryPriorityAllocateInfo(DE_NULL, ((float)i) / ((float)count));
590         const VkMemoryAllocateInfo memAlloc =
591             makeMemoryAllocateInfo(memReqs, (m_params.priorityMode == PRIORITY_MODE_STATIC) ? &priority : DE_NULL);
592 #endif
593         VkDeviceMemory rawMemory = DE_NULL;
594 
595         vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks *)DE_NULL, &rawMemory);
596 
597 #ifndef CTS_USES_VULKANSC
598         if (m_params.priorityMode == PRIORITY_MODE_DYNAMIC)
599             vk.setDeviceMemoryPriorityEXT(vkDevice, rawMemory, priority.priority);
600 #endif // CTS_USES_VULKANSC
601 
602         memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory),
603                                                                   Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
604     }
605 }
606 
607 template <>
createMemory(ImagesList & targets,MemoryRegionsList & memory)608 void BaseTestInstance::createMemory<VkImage, false>(ImagesList &targets, MemoryRegionsList &memory)
609 {
610     const uint32_t count      = static_cast<uint32_t>(targets.size());
611     const DeviceInterface &vk = getDeviceInterface();
612     const VkDevice vkDevice   = getDevice();
613 
614     memory.reserve(count);
615     for (uint32_t i = 0; i < count; ++i)
616     {
617         VkMemoryRequirements memReqs;
618         vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs);
619 
620 #ifdef CTS_USES_VULKANSC
621         const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, DE_NULL);
622 #else
623         VkMemoryPriorityAllocateInfoEXT priority = makeMemoryPriorityAllocateInfo(DE_NULL, ((float)i) / ((float)count));
624         const VkMemoryAllocateInfo memAlloc =
625             makeMemoryAllocateInfo(memReqs, (m_params.priorityMode == PRIORITY_MODE_STATIC) ? &priority : DE_NULL);
626 #endif
627 
628         VkDeviceMemory rawMemory = DE_NULL;
629 
630         vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks *)DE_NULL, &rawMemory);
631 
632 #ifndef CTS_USES_VULKANSC
633         if (m_params.priorityMode == PRIORITY_MODE_DYNAMIC)
634             vk.setDeviceMemoryPriorityEXT(vkDevice, rawMemory, priority.priority);
635 #endif // CTS_USES_VULKANSC
636 
637         memory.push_back(de::SharedPtr<Move<VkDeviceMemory>>(new Move<VkDeviceMemory>(
638             check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
639     }
640 }
641 
642 template <>
createMemory(BuffersList & targets,MemoryRegionsList & memory)643 void BaseTestInstance::createMemory<VkBuffer, true>(BuffersList &targets, MemoryRegionsList &memory)
644 {
645     const uint32_t count      = static_cast<uint32_t>(targets.size());
646     const DeviceInterface &vk = getDeviceInterface();
647     const VkDevice vkDevice   = getDevice();
648 
649     memory.reserve(count);
650     for (uint32_t i = 0; i < count; ++i)
651     {
652         VkMemoryRequirements memReqs;
653 
654         vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs);
655 
656         ConstDedicatedInfo dedicatedAllocationInfo = makeDedicatedAllocationInfo(**targets[i]);
657 #ifdef CTS_USES_VULKANSC
658         const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, (const void *)&dedicatedAllocationInfo);
659 #else
660         VkMemoryPriorityAllocateInfoEXT priority =
661             makeMemoryPriorityAllocateInfo(&dedicatedAllocationInfo, ((float)i) / ((float)count));
662         const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(
663             memReqs,
664             (m_params.priorityMode == PRIORITY_MODE_STATIC) ? &priority : (const void *)&dedicatedAllocationInfo);
665 #endif
666 
667         VkDeviceMemory rawMemory = DE_NULL;
668 
669         vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks *>(DE_NULL), &rawMemory);
670 
671 #ifndef CTS_USES_VULKANSC
672         if (m_params.priorityMode == PRIORITY_MODE_DYNAMIC)
673             vk.setDeviceMemoryPriorityEXT(vkDevice, rawMemory, priority.priority);
674 #endif // CTS_USES_VULKANSC
675 
676         memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory),
677                                                                   Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
678     }
679 }
680 
681 template <>
createMemory(ImagesList & targets,MemoryRegionsList & memory)682 void BaseTestInstance::createMemory<VkImage, true>(ImagesList &targets, MemoryRegionsList &memory)
683 {
684     const uint32_t count      = static_cast<uint32_t>(targets.size());
685     const DeviceInterface &vk = getDeviceInterface();
686     const VkDevice vkDevice   = getDevice();
687 
688     memory.reserve(count);
689     for (uint32_t i = 0; i < count; ++i)
690     {
691         VkMemoryRequirements memReqs;
692         vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs);
693 
694         ConstDedicatedInfo dedicatedAllocationInfo = makeDedicatedAllocationInfo(**targets[i]);
695 
696 #ifdef CTS_USES_VULKANSC
697         const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, (const void *)&dedicatedAllocationInfo);
698 #else
699         VkMemoryPriorityAllocateInfoEXT priority =
700             makeMemoryPriorityAllocateInfo(&dedicatedAllocationInfo, ((float)i) / ((float)count));
701         const VkMemoryAllocateInfo memAlloc =
702             makeMemoryAllocateInfo(memReqs, m_params.priorityMode ? &priority : (const void *)&dedicatedAllocationInfo);
703 #endif
704 
705         VkDeviceMemory rawMemory = DE_NULL;
706 
707         vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks *>(DE_NULL), &rawMemory);
708 
709 #ifndef CTS_USES_VULKANSC
710         if (m_params.priorityMode == PRIORITY_MODE_DYNAMIC)
711             vk.setDeviceMemoryPriorityEXT(vkDevice, rawMemory, priority.priority);
712 #endif // CTS_USES_VULKANSC
713 
714         memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory),
715                                                                   Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
716     }
717 }
718 
719 template <>
makeBinding(BuffersList & targets,MemoryRegionsList & memory)720 void BaseTestInstance::makeBinding<VkBuffer>(BuffersList &targets, MemoryRegionsList &memory)
721 {
722     const uint32_t count      = static_cast<uint32_t>(targets.size());
723     const VkDevice vkDevice   = getDevice();
724     const DeviceInterface &vk = getDeviceInterface();
725     BindBufferMemoryInfosList bindMemoryInfos;
726 #ifndef CTS_USES_VULKANSC
727     std::vector<VkResult> bindResults;
728     BindMemoryStatusList bindMemoryStatus;
729 
730     if (m_params.checkIndividualResult)
731     {
732         bindResults.reserve(count);
733         for (uint32_t i = 0; i < count; ++i)
734         {
735             bindResults.push_back(VK_ERROR_UNKNOWN);
736             bindMemoryStatus.push_back(makeBindMemoryStatus(&bindResults[i]));
737         }
738     }
739 #endif // CTS_USES_VULKANSC
740 
741     for (uint32_t i = 0; i < count; ++i)
742     {
743 #ifndef CTS_USES_VULKANSC
744         VkBindBufferMemoryInfo bindMemoryInfo = makeBufferMemoryBindingInfo(
745             **targets[i], **memory[i], m_params.checkIndividualResult ? &bindMemoryStatus[i] : nullptr);
746 #else
747         VkBindBufferMemoryInfo bindMemoryInfo = makeBufferMemoryBindingInfo(**targets[i], **memory[i], nullptr);
748 #endif // CTS_USES_VULKANSC
749         bindMemoryInfos.push_back(bindMemoryInfo);
750     }
751 
752     VK_CHECK(vk.bindBufferMemory2(vkDevice, count, &bindMemoryInfos.front()));
753 #ifndef CTS_USES_VULKANSC
754     if (m_params.checkIndividualResult)
755     {
756         for (uint32_t i = 0; i < count; ++i)
757         {
758             VK_CHECK(*bindMemoryStatus[i].pResult);
759         }
760     }
761 #endif // CTS_USES_VULKANSC
762 }
763 
764 template <>
makeBinding(ImagesList & targets,MemoryRegionsList & memory)765 void BaseTestInstance::makeBinding<VkImage>(ImagesList &targets, MemoryRegionsList &memory)
766 {
767     const uint32_t count      = static_cast<uint32_t>(targets.size());
768     const VkDevice vkDevice   = getDevice();
769     const DeviceInterface &vk = getDeviceInterface();
770     BindImageMemoryInfosList bindMemoryInfos;
771 #ifndef CTS_USES_VULKANSC
772     std::vector<VkResult> bindResults;
773     BindMemoryStatusList bindMemoryStatus;
774 
775     if (m_params.checkIndividualResult)
776     {
777         bindResults.reserve(count);
778         for (uint32_t i = 0; i < count; ++i)
779         {
780             bindResults.push_back(VK_ERROR_UNKNOWN);
781             bindMemoryStatus.push_back(makeBindMemoryStatus(&bindResults[i]));
782         }
783     }
784 #endif // CTS_USES_VULKANSC
785 
786     for (uint32_t i = 0; i < count; ++i)
787     {
788 #ifndef CTS_USES_VULKANSC
789         VkBindImageMemoryInfo bindMemoryInfo = makeImageMemoryBindingInfo(
790             **targets[i], **memory[i], m_params.checkIndividualResult ? &bindMemoryStatus[i] : nullptr);
791 #else
792         VkBindImageMemoryInfo bindMemoryInfo  = makeImageMemoryBindingInfo(**targets[i], **memory[i], nullptr);
793 #endif // CTS_USES_VULKANSC
794         bindMemoryInfos.push_back(bindMemoryInfo);
795     }
796 
797     VK_CHECK(vk.bindImageMemory2(vkDevice, count, &bindMemoryInfos.front()));
798 
799 #ifndef CTS_USES_VULKANSC
800     if (m_params.checkIndividualResult)
801     {
802         for (uint32_t i = 0; i < count; ++i)
803         {
804             VK_CHECK(*bindMemoryStatus[i].pResult);
805         }
806     }
807 #endif // CTS_USES_VULKANSC
808 }
809 
810 template <>
fillUpResource(Move<VkBuffer> & source,Move<VkBuffer> & target)811 void BaseTestInstance::fillUpResource<VkBuffer>(Move<VkBuffer> &source, Move<VkBuffer> &target)
812 {
813     const DeviceInterface &vk = getDeviceInterface();
814     const VkDevice vkDevice   = getDevice();
815     const VkQueue queue       = getUniversalQueue();
816 
817     const VkBufferMemoryBarrier srcBufferBarrier =
818         makeMemoryBarrierInfo(*source, m_params.bufferSize, TransferFromResource);
819     const VkBufferMemoryBarrier dstBufferBarrier =
820         makeMemoryBarrierInfo(*target, m_params.bufferSize, TransferToResource);
821 
822     Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
823     Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool);
824     VkBufferCopy bufferCopy         = {0u, 0u, m_params.bufferSize};
825 
826     beginCommandBuffer(vk, *cmdBuffer);
827     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
828                           0, (const VkMemoryBarrier *)DE_NULL, 1, &srcBufferBarrier, 0,
829                           (const VkImageMemoryBarrier *)DE_NULL);
830     vk.cmdCopyBuffer(*cmdBuffer, *source, *target, 1, &bufferCopy);
831     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
832                           0, (const VkMemoryBarrier *)DE_NULL, 1, &dstBufferBarrier, 0,
833                           (const VkImageMemoryBarrier *)DE_NULL);
834     endCommandBuffer(vk, *cmdBuffer);
835 
836     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
837 }
838 
839 template <>
fillUpResource(Move<VkBuffer> & source,Move<VkImage> & target)840 void BaseTestInstance::fillUpResource<VkImage>(Move<VkBuffer> &source, Move<VkImage> &target)
841 {
842     const DeviceInterface &vk = getDeviceInterface();
843     const VkDevice vkDevice   = getDevice();
844     const VkQueue queue       = getUniversalQueue();
845 
846     const VkBufferMemoryBarrier srcBufferBarrier =
847         makeMemoryBarrierInfo(*source, m_params.bufferSize, TransferFromResource);
848     const VkImageMemoryBarrier preImageBarrier = makeMemoryBarrierInfo(
849         *target, 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
850     const VkImageMemoryBarrier dstImageBarrier =
851         makeMemoryBarrierInfo(*target, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
852                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
853 
854     Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
855     Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool);
856 
857     const VkBufferImageCopy copyRegion = {
858         0u,                        // VkDeviceSize bufferOffset;
859         m_params.imageSize.width,  // uint32_t bufferRowLength;
860         m_params.imageSize.height, // uint32_t bufferImageHeight;
861         {
862             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
863             0u,                        // uint32_t mipLevel;
864             0u,                        // uint32_t baseArrayLayer;
865             1u,                        // uint32_t layerCount;
866         },                             // VkImageSubresourceLayers imageSubresource;
867         {0, 0, 0},                     // VkOffset3D imageOffset;
868         m_params.imageSize             // VkExtent3D imageExtent;
869     };
870 
871     beginCommandBuffer(vk, *cmdBuffer);
872     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
873                           0, (const VkMemoryBarrier *)DE_NULL, 1, &srcBufferBarrier, 1, &preImageBarrier);
874     vk.cmdCopyBufferToImage(*cmdBuffer, *source, *target, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, (&copyRegion));
875     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
876                           (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
877                           (const VkBufferMemoryBarrier *)DE_NULL, 1, &dstImageBarrier);
878     endCommandBuffer(vk, *cmdBuffer);
879 
880     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
881 }
882 
883 template <>
readUpResource(Move<VkBuffer> & source,Move<VkBuffer> & target)884 void BaseTestInstance::readUpResource(Move<VkBuffer> &source, Move<VkBuffer> &target)
885 {
886     fillUpResource(source, target);
887 }
888 
889 template <>
readUpResource(Move<VkImage> & source,Move<VkBuffer> & target)890 void BaseTestInstance::readUpResource(Move<VkImage> &source, Move<VkBuffer> &target)
891 {
892     const DeviceInterface &vk = getDeviceInterface();
893     const VkDevice vkDevice   = getDevice();
894     const VkQueue queue       = getUniversalQueue();
895 
896     Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
897     Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool);
898 
899     beginCommandBuffer(vk, *cmdBuffer);
900     copyImageToBuffer(vk, *cmdBuffer, *source, *target, tcu::IVec2(m_params.imageSize.width, m_params.imageSize.height),
901                       VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
902     endCommandBuffer(vk, *cmdBuffer);
903 
904     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
905 }
906 
907 template <>
layoutTransitionResource(Move<VkBuffer> & target)908 void BaseTestInstance::layoutTransitionResource(Move<VkBuffer> &target)
909 {
910     DE_UNREF(target);
911 }
912 
913 template <>
layoutTransitionResource(Move<VkImage> & target)914 void BaseTestInstance::layoutTransitionResource<VkImage>(Move<VkImage> &target)
915 {
916     const DeviceInterface &vk = getDeviceInterface();
917     const VkDevice vkDevice   = getDevice();
918     const VkQueue queue       = getUniversalQueue();
919 
920     const VkImageMemoryBarrier preImageBarrier = makeMemoryBarrierInfo(
921         *target, 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
922 
923     Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
924     Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool);
925 
926     beginCommandBuffer(vk, *cmdBuffer);
927     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
928                           0, (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1,
929                           &preImageBarrier);
930     endCommandBuffer(vk, *cmdBuffer);
931 
932     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
933 }
934 
createBuffer(Move<VkBuffer> & buffer,Move<VkDeviceMemory> & memory,VkDeviceSize * memorySize)935 void BaseTestInstance::createBuffer(Move<VkBuffer> &buffer, Move<VkDeviceMemory> &memory, VkDeviceSize *memorySize)
936 {
937     const DeviceInterface &vk       = getDeviceInterface();
938     const VkDevice vkDevice         = getDevice();
939     VkBufferCreateInfo bufferParams = makeBufferCreateInfo(m_context, m_params);
940     VkMemoryRequirements memReqs;
941 
942     buffer = vk::createBuffer(vk, vkDevice, &bufferParams);
943     vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
944     *memorySize = memReqs.size;
945 
946     const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(m_context, memReqs, MemoryHostVisible);
947     VkDeviceMemory rawMemory            = DE_NULL;
948 
949     vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks *>(DE_NULL), &rawMemory);
950     memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
951     VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, *memory, 0u));
952 }
953 
pushData(VkDeviceMemory memory,uint32_t dataSeed,VkDeviceSize size)954 void BaseTestInstance::pushData(VkDeviceMemory memory, uint32_t dataSeed, VkDeviceSize size)
955 {
956     const DeviceInterface &vk = getDeviceInterface();
957     const VkDevice vkDevice   = getDevice();
958     MemoryMappingRAII hostMemory(vk, vkDevice, memory, 0u, size, 0u);
959     uint8_t *hostBuffer = static_cast<uint8_t *>(hostMemory.ptr());
960     SimpleRandomGenerator random(dataSeed);
961 
962     for (uint32_t i = 0u; i < size; ++i)
963     {
964         hostBuffer[i] = static_cast<uint8_t>(random.getNext() & 0xFFu);
965     }
966     hostMemory.flush();
967 }
968 
checkData(VkDeviceMemory memory,uint32_t dataSeed,VkDeviceSize size)969 bool BaseTestInstance::checkData(VkDeviceMemory memory, uint32_t dataSeed, VkDeviceSize size)
970 {
971     const DeviceInterface &vk = getDeviceInterface();
972     const VkDevice vkDevice   = getDevice();
973     MemoryMappingRAII hostMemory(vk, vkDevice, memory, 0u, size, 0u);
974     uint8_t *hostBuffer = static_cast<uint8_t *>(hostMemory.ptr());
975     SimpleRandomGenerator random(dataSeed);
976 
977     hostMemory.invalidate();
978 
979     for (uint32_t i = 0u; i < m_params.bufferSize; ++i)
980     {
981         if (hostBuffer[i] != static_cast<uint8_t>(random.getNext() & 0xFFu))
982             return false;
983     }
984     return true;
985 }
986 
987 template <typename TTarget, bool TDedicated>
988 class MemoryBindingInstance : public BaseTestInstance
989 {
990 public:
MemoryBindingInstance(Context & ctx,BindingCaseParameters params)991     MemoryBindingInstance(Context &ctx, BindingCaseParameters params) : BaseTestInstance(ctx, params)
992     {
993     }
994 
iterate(void)995     virtual tcu::TestStatus iterate(void)
996     {
997         const InstanceInterface &vkInstance     = m_context.getInstanceInterface();
998         const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
999         VkPhysicalDeviceProperties properties;
1000         vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &properties);
1001         std::vector<de::SharedPtr<Move<TTarget>>> targets;
1002         MemoryRegionsList memory;
1003 
1004         createBindingTargets<TTarget>(targets);
1005         createMemory<TTarget, TDedicated>(targets, memory);
1006         makeBinding<TTarget>(targets, memory);
1007 
1008         Move<VkBuffer> srcBuffer;
1009         Move<VkDeviceMemory> srcMemory;
1010         VkDeviceSize srcMemorySize;
1011 
1012         createBuffer(srcBuffer, srcMemory, &srcMemorySize);
1013         pushData(*srcMemory, 1, srcMemorySize);
1014 
1015         Move<VkBuffer> dstBuffer;
1016         Move<VkDeviceMemory> dstMemory;
1017         VkDeviceSize dstMemorySize;
1018 
1019         createBuffer(dstBuffer, dstMemory, &dstMemorySize);
1020 
1021         bool passed = true;
1022         for (uint32_t i = 0; i < m_params.targetsCount; ++i)
1023         {
1024             fillUpResource(srcBuffer, *targets[i]);
1025             readUpResource(*targets[i], dstBuffer);
1026             passed = checkData(*dstMemory, 1, dstMemorySize) && passed;
1027         }
1028 
1029         return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed");
1030     }
1031 };
1032 
1033 template <typename TTarget, bool TDedicated>
1034 class AliasedMemoryBindingInstance : public BaseTestInstance
1035 {
1036 public:
AliasedMemoryBindingInstance(Context & ctx,BindingCaseParameters params)1037     AliasedMemoryBindingInstance(Context &ctx, BindingCaseParameters params) : BaseTestInstance(ctx, params)
1038     {
1039     }
1040 
iterate(void)1041     virtual tcu::TestStatus iterate(void)
1042     {
1043         const InstanceInterface &vkInstance     = m_context.getInstanceInterface();
1044         const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
1045         VkPhysicalDeviceProperties properties;
1046         vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &properties);
1047         std::vector<de::SharedPtr<Move<TTarget>>> targets[2];
1048         MemoryRegionsList memory;
1049 
1050         for (uint32_t i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i)
1051             createBindingTargets<TTarget>(targets[i]);
1052         createMemory<TTarget, TDedicated>(targets[0], memory);
1053         for (uint32_t i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i)
1054             makeBinding<TTarget>(targets[i], memory);
1055 
1056         Move<VkBuffer> srcBuffer;
1057         Move<VkDeviceMemory> srcMemory;
1058         VkDeviceSize srcMemorySize;
1059 
1060         createBuffer(srcBuffer, srcMemory, &srcMemorySize);
1061         pushData(*srcMemory, 2, srcMemorySize);
1062 
1063         Move<VkBuffer> dstBuffer;
1064         Move<VkDeviceMemory> dstMemory;
1065         VkDeviceSize dstMemorySize;
1066 
1067         createBuffer(dstBuffer, dstMemory, &dstMemorySize);
1068 
1069         bool passed = true;
1070         for (uint32_t i = 0; i < m_params.targetsCount; ++i)
1071         {
1072             // Do a layout transition on alias 1 before we transition and write to alias 0
1073             layoutTransitionResource(*(targets[1][i]));
1074             fillUpResource(srcBuffer, *(targets[0][i]));
1075             readUpResource(*(targets[1][i]), dstBuffer);
1076             passed = checkData(*dstMemory, 2, dstMemorySize) && passed;
1077         }
1078 
1079         return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed");
1080     }
1081 };
1082 
1083 template <typename TInstance>
1084 class MemoryBindingTest : public TestCase
1085 {
1086 public:
MemoryBindingTest(tcu::TestContext & testCtx,const std::string & name,BindingCaseParameters params)1087     MemoryBindingTest(tcu::TestContext &testCtx, const std::string &name, BindingCaseParameters params)
1088         : TestCase(testCtx, name)
1089         , m_params(params)
1090     {
1091     }
1092 
~MemoryBindingTest(void)1093     virtual ~MemoryBindingTest(void)
1094     {
1095     }
1096 
createInstance(Context & ctx) const1097     virtual TestInstance *createInstance(Context &ctx) const
1098     {
1099         return new TInstance(ctx, m_params);
1100     }
1101 
checkSupport(Context & ctx) const1102     virtual void checkSupport(Context &ctx) const
1103     {
1104         ctx.requireDeviceFunctionality("VK_KHR_bind_memory2");
1105 
1106 #ifndef CTS_USES_VULKANSC
1107         if ((m_params.priorityMode != PRIORITY_MODE_DEFAULT) && !ctx.getMemoryPriorityFeaturesEXT().memoryPriority)
1108             TCU_THROW(NotSupportedError, "VK_EXT_memory_priority Not supported");
1109         if ((m_params.priorityMode == PRIORITY_MODE_DYNAMIC) &&
1110             !ctx.isDeviceFunctionalitySupported("VK_EXT_pageable_device_local_memory"))
1111             TCU_THROW(NotSupportedError, "VK_EXT_pageable_device_local_memory Not supported");
1112         if (m_params.checkIndividualResult)
1113             ctx.requireDeviceFunctionality("VK_KHR_maintenance6");
1114 #endif
1115     }
1116 
1117 private:
1118     BindingCaseParameters m_params;
1119 };
1120 
1121 } // unnamed namespace
1122 
createMemoryBindingTests(tcu::TestContext & testCtx)1123 tcu::TestCaseGroup *createMemoryBindingTests(tcu::TestContext &testCtx)
1124 {
1125     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "binding", "Memory binding tests."));
1126     de::MovePtr<tcu::TestCaseGroup> maint6(
1127         new tcu::TestCaseGroup(testCtx, "maintenance6", "Maintenance6 memory binding tests."));
1128 
1129 #ifdef CTS_USES_VULKANSC
1130     const int iterations = 1;
1131 #else
1132     const int iterations = 6;
1133 #endif
1134 
1135     for (int i = 0; i < iterations; ++i)
1136     {
1137         PriorityMode priorityMode       = PriorityMode(i % 3);
1138         bool checkIndividualBindResults = i / 3;
1139 
1140         // Basic memory binding tests.
1141         de::MovePtr<tcu::TestCaseGroup> regular(new tcu::TestCaseGroup(testCtx, "regular"));
1142         // Memory binding tests with aliasing of two resources.
1143         de::MovePtr<tcu::TestCaseGroup> aliasing(new tcu::TestCaseGroup(testCtx, "aliasing"));
1144 
1145         de::MovePtr<tcu::TestCaseGroup> regular_suballocated(new tcu::TestCaseGroup(testCtx, "suballocated"));
1146         de::MovePtr<tcu::TestCaseGroup> regular_dedicated(new tcu::TestCaseGroup(testCtx, "dedicated"));
1147 
1148         de::MovePtr<tcu::TestCaseGroup> aliasing_suballocated(new tcu::TestCaseGroup(testCtx, "suballocated"));
1149 
1150         const VkDeviceSize allocationSizes[] = {33, 257, 4087, 8095, 1 * 1024 * 1024 + 1};
1151 
1152         for (uint32_t sizeNdx = 0u; sizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); ++sizeNdx)
1153         {
1154             const VkDeviceSize bufferSize      = allocationSizes[sizeNdx];
1155             const BindingCaseParameters params = makeBindingCaseParameters(
1156                 10, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE,
1157                 bufferSize, 0u, priorityMode, checkIndividualBindResults);
1158             const BindingCaseParameters aliasparams = makeBindingCaseParameters(
1159                 10, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE,
1160                 bufferSize, VK_IMAGE_CREATE_ALIAS_BIT, priorityMode, checkIndividualBindResults);
1161             std::ostringstream testName;
1162 
1163             testName << "buffer_" << bufferSize;
1164             regular_suballocated->addChild(
1165                 new MemoryBindingTest<MemoryBindingInstance<VkBuffer, false>>(testCtx, testName.str(), params));
1166             regular_dedicated->addChild(
1167                 new MemoryBindingTest<MemoryBindingInstance<VkBuffer, true>>(testCtx, testName.str(), params));
1168             aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkBuffer, false>>(
1169                 testCtx, testName.str(), aliasparams));
1170         }
1171 
1172         const uint32_t imageSizes[] = {8, 33, 257};
1173 
1174         for (uint32_t widthNdx = 0u; widthNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++widthNdx)
1175             for (uint32_t heightNdx = 0u; heightNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++heightNdx)
1176             {
1177                 const uint32_t width  = imageSizes[widthNdx];
1178                 const uint32_t height = imageSizes[heightNdx];
1179                 const BindingCaseParameters regularparams =
1180                     makeBindingCaseParameters(10, width, height, 0u, priorityMode, checkIndividualBindResults);
1181                 const BindingCaseParameters aliasparams = makeBindingCaseParameters(
1182                     10, width, height, VK_IMAGE_CREATE_ALIAS_BIT, priorityMode, checkIndividualBindResults);
1183                 std::ostringstream testName;
1184 
1185                 testName << "image_" << width << '_' << height;
1186                 regular_suballocated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, false>>(
1187                     testCtx, testName.str(), regularparams));
1188                 regular_dedicated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, true>>(
1189                     testCtx, testName.str(), regularparams));
1190                 aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkImage, false>>(
1191                     testCtx, testName.str(), aliasparams));
1192             }
1193 
1194         regular->addChild(regular_suballocated.release());
1195         regular->addChild(regular_dedicated.release());
1196 
1197         aliasing->addChild(aliasing_suballocated.release());
1198 
1199         tcu::TestCaseGroup *parent = checkIndividualBindResults ? maint6.get() : group.get();
1200         if (priorityMode != PRIORITY_MODE_DEFAULT)
1201         {
1202             de::MovePtr<tcu::TestCaseGroup> priority(new tcu::TestCaseGroup(
1203                 testCtx, (priorityMode == PRIORITY_MODE_DYNAMIC) ? "priority_dynamic" : "priority",
1204                 (priorityMode == PRIORITY_MODE_DYNAMIC) ? "Using VK_EXT_pageable_device_local_memory" :
1205                                                           "Using VK_EXT_memory_priority."));
1206             priority->addChild(regular.release());
1207             priority->addChild(aliasing.release());
1208             parent->addChild(priority.release());
1209         }
1210         else
1211         {
1212             parent->addChild(regular.release());
1213             parent->addChild(aliasing.release());
1214         }
1215     }
1216     group->addChild(maint6.release());
1217     return group.release();
1218 }
1219 
1220 } // namespace memory
1221 } // namespace vkt
1222