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(¶ms, 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 ¶ms)
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 ¶ms)
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, (©Region));
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