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 29 #include "vkPlatform.hpp" 30 #include "gluVarType.hpp" 31 #include "deStringUtil.hpp" 32 #include "vkPrograms.hpp" 33 #include "vkQueryUtil.hpp" 34 #include "vkRefUtil.hpp" 35 #include "deSharedPtr.hpp" 36 #include "vktTestCase.hpp" 37 #include "vkTypeUtil.hpp" 38 39 #include <algorithm> 40 41 namespace vkt 42 { 43 namespace memory 44 { 45 namespace 46 { 47 48 using namespace vk; 49 50 typedef const VkMemoryDedicatedAllocateInfo ConstDedicatedInfo; 51 typedef de::SharedPtr<Move<VkDeviceMemory> > MemoryRegionPtr; 52 typedef std::vector<MemoryRegionPtr> MemoryRegionsList; 53 typedef de::SharedPtr<Move<VkBuffer> > BufferPtr; 54 typedef std::vector<BufferPtr> BuffersList; 55 typedef de::SharedPtr<Move<VkImage> > ImagePtr; 56 typedef std::vector<ImagePtr> ImagesList; 57 typedef std::vector<VkBindBufferMemoryInfo> BindBufferMemoryInfosList; 58 typedef std::vector<VkBindImageMemoryInfo> BindImageMemoryInfosList; 59 60 class MemoryMappingRAII 61 { 62 public: 63 MemoryMappingRAII (const DeviceInterface& deviceInterface, 64 const VkDevice& device, 65 VkDeviceMemory deviceMemory, 66 VkDeviceSize offset, 67 VkDeviceSize size, 68 VkMemoryMapFlags flags) 69 : vk (deviceInterface) 70 , dev (device) 71 , memory (deviceMemory) 72 , hostPtr (DE_NULL) 73 74 { 75 vk.mapMemory(dev, memory, offset, size, flags, &hostPtr); 76 } 77 78 ~MemoryMappingRAII () 79 { 80 vk.unmapMemory(dev, memory); 81 hostPtr = DE_NULL; 82 } 83 84 void* ptr () 85 { 86 return hostPtr; 87 } 88 89 void flush (VkDeviceSize offset, 90 VkDeviceSize size) 91 { 92 const VkMappedMemoryRange range = makeMemoryRange(offset, size); 93 VK_CHECK(vk.flushMappedMemoryRanges(dev, 1u, &range)); 94 } 95 96 protected: 97 const DeviceInterface& vk; 98 const VkDevice& dev; 99 VkDeviceMemory memory; 100 void* hostPtr; 101 102 const VkMappedMemoryRange makeMemoryRange (VkDeviceSize offset, 103 VkDeviceSize size) 104 { 105 const VkMappedMemoryRange range = 106 { 107 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 108 DE_NULL, 109 memory, 110 offset, 111 size 112 }; 113 return range; 114 } 115 }; 116 117 class SimpleRandomGenerator 118 { 119 public: 120 SimpleRandomGenerator (deUint32 seed) 121 : value (seed) 122 {} 123 deUint32 getNext () 124 { 125 value += 1; 126 value ^= (value << 21); 127 value ^= (value >> 15); 128 value ^= (value << 4); 129 return value; 130 } 131 protected: 132 deUint32 value; 133 }; 134 135 struct BindingCaseParameters 136 { 137 VkBufferCreateFlags flags; 138 VkBufferUsageFlags usage; 139 VkSharingMode sharing; 140 VkDeviceSize bufferSize; 141 VkExtent3D imageSize; 142 deUint32 targetsCount; 143 }; 144 145 BindingCaseParameters makeBindingCaseParameters (deUint32 targetsCount, 146 deUint32 width, 147 deUint32 height) 148 { 149 BindingCaseParameters params; 150 deMemset(¶ms, 0, sizeof(BindingCaseParameters)); 151 params.imageSize.width = width; 152 params.imageSize.height = height; 153 params.imageSize.depth = 1; 154 params.bufferSize = params.imageSize.width * params.imageSize.height * params.imageSize.depth * sizeof(deUint32); 155 params.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 156 params.targetsCount = targetsCount; 157 return params; 158 } 159 160 BindingCaseParameters makeBindingCaseParameters (deUint32 targetsCount, 161 VkBufferUsageFlags usage, 162 VkSharingMode sharing, 163 VkDeviceSize bufferSize) 164 { 165 BindingCaseParameters params = 166 { 167 0, // VkBufferCreateFlags flags; 168 usage, // VkBufferUsageFlags usage; 169 sharing, // VkSharingMode sharing; 170 bufferSize, // VkDeviceSize bufferSize; 171 {0u, 0u, 0u}, // VkExtent3D imageSize; 172 targetsCount // deUint32 targetsCount; 173 }; 174 return params; 175 } 176 177 VkImageCreateInfo makeImageCreateInfo (BindingCaseParameters& params) 178 { 179 const VkImageCreateInfo imageParams = 180 { 181 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 182 DE_NULL, // const void* pNext; 183 0u, // VkImageCreateFlags flags; 184 VK_IMAGE_TYPE_2D, // VkImageType imageType; 185 VK_FORMAT_R8G8B8A8_UINT, // VkFormat format; 186 params.imageSize, // VkExtent3D extent; 187 1u, // deUint32 mipLevels; 188 1u, // deUint32 arrayLayers; 189 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 190 VK_IMAGE_TILING_LINEAR, // VkImageTiling tiling; 191 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; 192 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 193 0u, // deUint32 queueFamilyIndexCount; 194 DE_NULL, // const deUint32* pQueueFamilyIndices; 195 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 196 }; 197 return imageParams; 198 } 199 200 VkBufferCreateInfo makeBufferCreateInfo (Context& ctx, 201 BindingCaseParameters& params) 202 { 203 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex(); 204 VkBufferCreateInfo bufferParams = 205 { 206 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 207 DE_NULL, // const void* pNext; 208 params.flags, // VkBufferCreateFlags flags; 209 params.bufferSize, // VkDeviceSize size; 210 params.usage, // VkBufferUsageFlags usage; 211 params.sharing, // VkSharingMode sharingMode; 212 1u, // uint32_t queueFamilyIndexCount; 213 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; 214 }; 215 return bufferParams; 216 } 217 218 const VkMemoryAllocateInfo makeMemoryAllocateInfo (VkMemoryRequirements& memReqs, 219 ConstDedicatedInfo* next) 220 { 221 const deUint32 heapTypeIndex = (deUint32)deCtz32(memReqs.memoryTypeBits); 222 const VkMemoryAllocateInfo allocateParams = 223 { 224 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; 225 next, // const void* pNext; 226 memReqs.size, // VkDeviceSize allocationSize; 227 heapTypeIndex, // uint32_t memoryTypeIndex; 228 }; 229 return allocateParams; 230 } 231 232 enum MemoryHostVisibility 233 { 234 MemoryAny, 235 MemoryHostVisible 236 }; 237 238 deUint32 selectMatchingMemoryType (Context& ctx, 239 VkMemoryRequirements& memReqs, 240 MemoryHostVisibility memoryVisibility) 241 { 242 const VkPhysicalDevice vkPhysicalDevice = ctx.getPhysicalDevice(); 243 const InstanceInterface& vkInstance = ctx.getInstanceInterface(); 244 VkPhysicalDeviceMemoryProperties memoryProperties; 245 246 vkInstance.getPhysicalDeviceMemoryProperties(vkPhysicalDevice, &memoryProperties); 247 if (memoryVisibility == MemoryHostVisible) 248 { 249 for (deUint32 typeNdx = 0; typeNdx < memoryProperties.memoryTypeCount; ++typeNdx) 250 { 251 const deBool isInAllowed = (memReqs.memoryTypeBits & (1u << typeNdx)) != 0u; 252 const deBool hasRightProperties = (memoryProperties.memoryTypes[typeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u; 253 if (isInAllowed && hasRightProperties) 254 return typeNdx; 255 } 256 } 257 return (deUint32)deCtz32(memReqs.memoryTypeBits); 258 } 259 260 const VkMemoryAllocateInfo makeMemoryAllocateInfo (Context& ctx, 261 VkMemoryRequirements& memReqs, 262 MemoryHostVisibility memoryVisibility) 263 { 264 const deUint32 heapTypeIndex = selectMatchingMemoryType(ctx, memReqs, memoryVisibility); 265 const VkMemoryAllocateInfo allocateParams = 266 { 267 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; 268 DE_NULL, // const void* pNext; 269 memReqs.size, // VkDeviceSize allocationSize; 270 heapTypeIndex, // uint32_t memoryTypeIndex; 271 }; 272 return allocateParams; 273 } 274 275 ConstDedicatedInfo makeDedicatedAllocationInfo (VkBuffer buffer) 276 { 277 ConstDedicatedInfo dedicatedAllocationInfo = 278 { 279 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, // VkStructureType sType 280 DE_NULL, // const void* pNext 281 DE_NULL, // VkImage image 282 buffer // VkBuffer buffer 283 }; 284 return dedicatedAllocationInfo; 285 } 286 287 ConstDedicatedInfo makeDedicatedAllocationInfo (VkImage image) 288 { 289 ConstDedicatedInfo dedicatedAllocationInfo = 290 { 291 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, // VkStructureType sType 292 DE_NULL, // const void* pNext 293 image, // VkImage image 294 DE_NULL // VkBuffer buffer 295 }; 296 return dedicatedAllocationInfo; 297 } 298 299 const VkBindBufferMemoryInfo makeBufferMemoryBindingInfo (VkBuffer buffer, 300 VkDeviceMemory memory) 301 { 302 const VkBindBufferMemoryInfo bufferMemoryBinding = 303 { 304 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR, // VkStructureType sType; 305 DE_NULL, // const void* pNext; 306 buffer, // VkBuffer buffer; 307 memory, // VkDeviceMemory memory; 308 0u, // VkDeviceSize memoryOffset; 309 }; 310 return bufferMemoryBinding; 311 } 312 313 const VkBindImageMemoryInfo makeImageMemoryBindingInfo (VkImage image, 314 VkDeviceMemory memory) 315 { 316 const VkBindImageMemoryInfo imageMemoryBinding = 317 { 318 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR, // VkStructureType sType; 319 DE_NULL, // const void* pNext; 320 image, // VkImage image; 321 memory, // VkDeviceMemory memory; 322 0u, // VkDeviceSize memoryOffset; 323 }; 324 return imageMemoryBinding; 325 } 326 327 enum TransferDirection 328 { 329 TransferToResource = 0, 330 TransferFromResource = 1 331 }; 332 333 const VkBufferMemoryBarrier makeMemoryBarrierInfo (VkBuffer buffer, 334 VkDeviceSize size, 335 TransferDirection direction) 336 { 337 const deBool fromRes = direction == TransferFromResource; 338 const VkAccessFlags srcMask = static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_HOST_WRITE_BIT : VK_ACCESS_TRANSFER_WRITE_BIT); 339 const VkAccessFlags dstMask = static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_HOST_READ_BIT); 340 const VkBufferMemoryBarrier bufferBarrier = 341 { 342 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 343 DE_NULL, // const void* pNext; 344 srcMask, // VkAccessFlags srcAccessMask; 345 dstMask, // VkAccessFlags dstAccessMask; 346 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 347 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 348 buffer, // VkBuffer buffer; 349 0u, // VkDeviceSize offset; 350 size // VkDeviceSize size; 351 }; 352 return bufferBarrier; 353 } 354 355 const VkImageMemoryBarrier makeMemoryBarrierInfo (VkImage image, 356 VkAccessFlags srcAccess, 357 VkAccessFlags dstAccess, 358 VkImageLayout oldLayout, 359 VkImageLayout newLayout) 360 { 361 const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; 362 const VkImageMemoryBarrier imageBarrier = 363 { 364 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 365 DE_NULL, // const void* pNext; 366 srcAccess, // VkAccessFlags srcAccessMask; 367 dstAccess, // VkAccessFlags dstAccessMask; 368 oldLayout, // VkImageLayout oldLayout; 369 newLayout, // VkImageLayout newLayout; 370 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 371 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 372 image, // VkImage image; 373 { // VkImageSubresourceRange subresourceRange; 374 aspect, // VkImageAspectFlags aspect; 375 0u, // deUint32 baseMipLevel; 376 1u, // deUint32 mipLevels; 377 0u, // deUint32 baseArraySlice; 378 1u, // deUint32 arraySize; 379 } 380 }; 381 return imageBarrier; 382 } 383 384 const VkCommandBufferBeginInfo makeCommandBufferInfo () 385 { 386 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 387 { 388 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 389 DE_NULL, 390 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 391 static_cast<const VkCommandBufferInheritanceInfo*>(DE_NULL) 392 }; 393 return cmdBufferBeginInfo; 394 } 395 396 const VkSubmitInfo makeSubmitInfo (const VkCommandBuffer& commandBuffer) 397 { 398 const VkSubmitInfo submitInfo = 399 { 400 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 401 DE_NULL, // const void* pNext; 402 0u, // deUint32 waitSemaphoreCount; 403 DE_NULL, // const VkSemaphore* pWaitSemaphores; 404 (const VkPipelineStageFlags*)DE_NULL, // const VkPipelineStageFlags* flags; 405 1u, // deUint32 commandBufferCount; 406 &commandBuffer, // const VkCommandBuffer* pCommandBuffers; 407 0u, // deUint32 signalSemaphoreCount; 408 DE_NULL // const VkSemaphore* pSignalSemaphores; 409 }; 410 return submitInfo; 411 } 412 413 Move<VkCommandBuffer> createCommandBuffer (const DeviceInterface& vk, 414 VkDevice device, 415 VkCommandPool commandPool) 416 { 417 const VkCommandBufferAllocateInfo allocInfo = 418 { 419 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 420 DE_NULL, 421 commandPool, 422 VK_COMMAND_BUFFER_LEVEL_PRIMARY, 423 1 424 }; 425 return allocateCommandBuffer(vk, device, &allocInfo); 426 } 427 428 429 template<typename TTarget> 430 void createBindingTargets (std::vector<de::SharedPtr<Move<TTarget> > >& 431 targets, 432 Context& ctx, 433 BindingCaseParameters params); 434 435 template<> 436 void createBindingTargets<VkBuffer> (BuffersList& targets, 437 Context& ctx, 438 BindingCaseParameters params) 439 { 440 const deUint32 count = params.targetsCount; 441 const VkDevice vkDevice = ctx.getDevice(); 442 const DeviceInterface& vk = ctx.getDeviceInterface(); 443 444 targets.reserve(count); 445 for (deUint32 i = 0u; i < count; ++i) 446 { 447 VkBufferCreateInfo bufferParams = makeBufferCreateInfo(ctx, params); 448 targets.push_back(BufferPtr(new Move<VkBuffer>(createBuffer(vk, vkDevice, &bufferParams)))); 449 } 450 } 451 452 template<> 453 void createBindingTargets<VkImage> (ImagesList& targets, 454 Context& ctx, 455 BindingCaseParameters params) 456 { 457 const deUint32 count = params.targetsCount; 458 const VkDevice vkDevice = ctx.getDevice(); 459 const DeviceInterface& vk = ctx.getDeviceInterface(); 460 461 targets.reserve(count); 462 for (deUint32 i = 0u; i < count; ++i) 463 { 464 VkImageCreateInfo imageParams = makeImageCreateInfo(params); 465 targets.push_back(ImagePtr(new Move<VkImage>(createImage(vk, vkDevice, &imageParams)))); 466 } 467 } 468 469 template<typename TTarget, deBool TDedicated> 470 void createMemory (std::vector<de::SharedPtr<Move<TTarget> > >& 471 targets, 472 MemoryRegionsList& memory, 473 Context& ctx, 474 BindingCaseParameters params); 475 476 template<> 477 void createMemory<VkBuffer, DE_FALSE> (BuffersList& targets, 478 MemoryRegionsList& memory, 479 Context& ctx, 480 BindingCaseParameters params) 481 { 482 DE_UNREF(params); 483 const deUint32 count = static_cast<deUint32>(targets.size()); 484 const DeviceInterface& vk = ctx.getDeviceInterface(); 485 const VkDevice vkDevice = ctx.getDevice(); 486 487 memory.reserve(count); 488 for (deUint32 i = 0; i < count; ++i) 489 { 490 VkMemoryRequirements memReqs; 491 492 vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs); 493 494 const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, DE_NULL); 495 VkDeviceMemory rawMemory = DE_NULL; 496 497 vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory); 498 memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)))); 499 } 500 } 501 502 template<> 503 void createMemory<VkImage, DE_FALSE> (ImagesList& targets, 504 MemoryRegionsList& memory, 505 Context& ctx, 506 BindingCaseParameters params) 507 { 508 DE_UNREF(params); 509 const deUint32 count = static_cast<deUint32>(targets.size()); 510 const DeviceInterface& vk = ctx.getDeviceInterface(); 511 const VkDevice vkDevice = ctx.getDevice(); 512 513 memory.reserve(count); 514 for (deUint32 i = 0; i < count; ++i) 515 { 516 VkMemoryRequirements memReqs; 517 vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs); 518 519 const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, DE_NULL); 520 VkDeviceMemory rawMemory = DE_NULL; 521 522 vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory); 523 memory.push_back(de::SharedPtr<Move<VkDeviceMemory> >(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)))); 524 } 525 } 526 527 template<> 528 void createMemory<VkBuffer, DE_TRUE> (BuffersList& targets, 529 MemoryRegionsList& memory, 530 Context& ctx, 531 BindingCaseParameters params) 532 { 533 DE_UNREF(params); 534 const deUint32 count = static_cast<deUint32>(targets.size()); 535 const DeviceInterface& vk = ctx.getDeviceInterface(); 536 const VkDevice vkDevice = ctx.getDevice(); 537 538 memory.reserve(count); 539 for (deUint32 i = 0; i < count; ++i) 540 { 541 VkMemoryRequirements memReqs; 542 543 vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs); 544 545 ConstDedicatedInfo dedicatedAllocationInfo = makeDedicatedAllocationInfo(**targets[i]);; 546 const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, &dedicatedAllocationInfo); 547 VkDeviceMemory rawMemory = DE_NULL; 548 549 vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory); 550 memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)))); 551 } 552 } 553 554 template<> 555 void createMemory<VkImage, DE_TRUE> (ImagesList& targets, 556 MemoryRegionsList& memory, 557 Context& ctx, 558 BindingCaseParameters params) 559 { 560 DE_UNREF(params); 561 const deUint32 count = static_cast<deUint32>(targets.size()); 562 const DeviceInterface& vk = ctx.getDeviceInterface(); 563 const VkDevice vkDevice = ctx.getDevice(); 564 565 memory.reserve(count); 566 for (deUint32 i = 0; i < count; ++i) 567 { 568 VkMemoryRequirements memReqs; 569 vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs); 570 571 ConstDedicatedInfo dedicatedAllocationInfo = makeDedicatedAllocationInfo(**targets[i]); 572 const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(memReqs, &dedicatedAllocationInfo); 573 VkDeviceMemory rawMemory = DE_NULL; 574 575 vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory); 576 memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)))); 577 } 578 } 579 580 template<typename TTarget> 581 void makeBinding (std::vector<de::SharedPtr<Move<TTarget> > >& 582 targets, 583 MemoryRegionsList& memory, 584 Context& ctx, 585 BindingCaseParameters params); 586 587 template<> 588 void makeBinding<VkBuffer> (BuffersList& targets, 589 MemoryRegionsList& memory, 590 Context& ctx, 591 BindingCaseParameters params) 592 { 593 DE_UNREF(params); 594 const deUint32 count = static_cast<deUint32>(targets.size()); 595 const VkDevice vkDevice = ctx.getDevice(); 596 const DeviceInterface& vk = ctx.getDeviceInterface(); 597 BindBufferMemoryInfosList bindMemoryInfos; 598 599 for (deUint32 i = 0; i < count; ++i) 600 { 601 bindMemoryInfos.push_back(makeBufferMemoryBindingInfo(**targets[i], **memory[i])); 602 } 603 604 VK_CHECK(vk.bindBufferMemory2(vkDevice, count, &bindMemoryInfos.front())); 605 } 606 607 template<> 608 void makeBinding<VkImage> (ImagesList& targets, 609 MemoryRegionsList& memory, 610 Context& ctx, 611 BindingCaseParameters params) 612 { 613 DE_UNREF(params); 614 const deUint32 count = static_cast<deUint32>(targets.size()); 615 const VkDevice vkDevice = ctx.getDevice(); 616 const DeviceInterface& vk = ctx.getDeviceInterface(); 617 BindImageMemoryInfosList bindMemoryInfos; 618 619 for (deUint32 i = 0; i < count; ++i) 620 { 621 bindMemoryInfos.push_back(makeImageMemoryBindingInfo(**targets[i], **memory[i])); 622 } 623 624 VK_CHECK(vk.bindImageMemory2(vkDevice, count, &bindMemoryInfos.front())); 625 } 626 627 template <typename TTarget> 628 void fillUpResource (Move<VkBuffer>& source, 629 Move<TTarget>& target, 630 Context& ctx, 631 BindingCaseParameters params); 632 633 template <> 634 void fillUpResource<VkBuffer> (Move<VkBuffer>& source, 635 Move<VkBuffer>& target, 636 Context& ctx, 637 BindingCaseParameters params) 638 { 639 const DeviceInterface& vk = ctx.getDeviceInterface(); 640 const VkDevice vkDevice = ctx.getDevice(); 641 const VkQueue queue = ctx.getUniversalQueue(); 642 643 const VkBufferMemoryBarrier srcBufferBarrier = makeMemoryBarrierInfo(*source, params.bufferSize, TransferFromResource); 644 const VkBufferMemoryBarrier dstBufferBarrier = makeMemoryBarrierInfo(*target, params.bufferSize, TransferToResource); 645 646 const VkCommandBufferBeginInfo cmdBufferBeginInfo = makeCommandBufferInfo(); 647 Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0); 648 Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool); 649 VkBufferCopy bufferCopy = { 0u, 0u, params.bufferSize }; 650 651 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 652 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 653 vk.cmdCopyBuffer(*cmdBuffer, *source, *target, 1, &bufferCopy); 654 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 655 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 656 657 const VkSubmitInfo submitInfo = makeSubmitInfo(*cmdBuffer); 658 Move<VkFence> fence = createFence(vk, vkDevice); 659 660 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 661 VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull))); 662 } 663 664 template <> 665 void fillUpResource<VkImage> (Move<VkBuffer>& source, 666 Move<VkImage>& target, 667 Context& ctx, 668 BindingCaseParameters params) 669 { 670 const DeviceInterface& vk = ctx.getDeviceInterface(); 671 const VkDevice vkDevice = ctx.getDevice(); 672 const VkQueue queue = ctx.getUniversalQueue(); 673 674 const VkBufferMemoryBarrier srcBufferBarrier = makeMemoryBarrierInfo(*source, params.bufferSize, TransferFromResource); 675 const VkImageMemoryBarrier preImageBarrier = makeMemoryBarrierInfo(*target, 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 676 const VkImageMemoryBarrier dstImageBarrier = makeMemoryBarrierInfo(*target, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 677 678 const VkCommandBufferBeginInfo cmdBufferBeginInfo = makeCommandBufferInfo(); 679 Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0); 680 Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool); 681 682 const VkBufferImageCopy copyRegion = 683 { 684 0u, // VkDeviceSize bufferOffset; 685 params.imageSize.width, // deUint32 bufferRowLength; 686 params.imageSize.height, // deUint32 bufferImageHeight; 687 { 688 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; 689 0u, // deUint32 mipLevel; 690 0u, // deUint32 baseArrayLayer; 691 1u, // deUint32 layerCount; 692 }, // VkImageSubresourceLayers imageSubresource; 693 { 0, 0, 0 }, // VkOffset3D imageOffset; 694 params.imageSize // VkExtent3D imageExtent; 695 }; 696 697 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 698 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 1, &preImageBarrier); 699 vk.cmdCopyBufferToImage(*cmdBuffer, *source, *target, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, (©Region)); 700 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier); 701 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 702 703 const VkSubmitInfo submitInfo = makeSubmitInfo(*cmdBuffer); 704 Move<VkFence> fence = createFence(vk, vkDevice); 705 706 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 707 VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull))); 708 } 709 710 template <typename TTarget> 711 void readUpResource (Move<TTarget>& source, 712 Move<VkBuffer>& target, 713 Context& ctx, 714 BindingCaseParameters params); 715 716 template <> 717 void readUpResource (Move<VkBuffer>& source, 718 Move<VkBuffer>& target, 719 Context& ctx, 720 BindingCaseParameters params) 721 { 722 fillUpResource(source, target, ctx, params); 723 } 724 725 template <> 726 void readUpResource (Move<VkImage>& source, 727 Move<VkBuffer>& target, 728 Context& ctx, 729 BindingCaseParameters params) 730 { 731 const DeviceInterface& vk = ctx.getDeviceInterface(); 732 const VkDevice vkDevice = ctx.getDevice(); 733 const VkQueue queue = ctx.getUniversalQueue(); 734 735 const VkImageMemoryBarrier srcImageBarrier = makeMemoryBarrierInfo(*source, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 736 const VkBufferMemoryBarrier dstBufferBarrier = makeMemoryBarrierInfo(*target, params.bufferSize, TransferToResource); 737 const VkImageMemoryBarrier postImageBarrier = makeMemoryBarrierInfo(*source, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 738 739 const VkCommandBufferBeginInfo cmdBufferBeginInfo = makeCommandBufferInfo(); 740 Move<VkCommandPool> commandPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0); 741 Move<VkCommandBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, *commandPool); 742 743 const VkBufferImageCopy copyRegion = 744 { 745 0u, // VkDeviceSize bufferOffset; 746 params.imageSize.width, // deUint32 bufferRowLength; 747 params.imageSize.height, // deUint32 bufferImageHeight; 748 { 749 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; 750 0u, // deUint32 mipLevel; 751 0u, // deUint32 baseArrayLayer; 752 1u, // deUint32 layerCount; 753 }, // VkImageSubresourceLayers imageSubresource; 754 { 0, 0, 0 }, // VkOffset3D imageOffset; 755 params.imageSize // VkExtent3D imageExtent; 756 }; 757 758 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 759 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier); 760 vk.cmdCopyImageToBuffer(*cmdBuffer, *source, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *target, 1, (©Region)); 761 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 1, &postImageBarrier); 762 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 763 764 const VkSubmitInfo submitInfo = makeSubmitInfo(*cmdBuffer); 765 Move<VkFence> fence = createFence(vk, vkDevice); 766 767 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 768 VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull))); 769 } 770 771 void createBuffer (Move<VkBuffer>& buffer, 772 Move<VkDeviceMemory>& memory, 773 Context& ctx, 774 BindingCaseParameters params) 775 { 776 const DeviceInterface& vk = ctx.getDeviceInterface(); 777 const VkDevice vkDevice = ctx.getDevice(); 778 VkBufferCreateInfo bufferParams = makeBufferCreateInfo(ctx, params); 779 VkMemoryRequirements memReqs; 780 781 buffer = createBuffer(vk, vkDevice, &bufferParams); 782 vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs); 783 784 const VkMemoryAllocateInfo memAlloc = makeMemoryAllocateInfo(ctx, memReqs, MemoryHostVisible); 785 VkDeviceMemory rawMemory = DE_NULL; 786 787 vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory); 788 memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)); 789 VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, *memory, 0u)); 790 } 791 792 void pushData (VkDeviceMemory memory, 793 deUint32 dataSeed, 794 Context& ctx, 795 BindingCaseParameters params) 796 { 797 const DeviceInterface& vk = ctx.getDeviceInterface(); 798 const VkDevice vkDevice = ctx.getDevice(); 799 MemoryMappingRAII hostMemory (vk, vkDevice, memory, 0u, params.bufferSize, 0u); 800 deUint8* hostBuffer = static_cast<deUint8*>(hostMemory.ptr()); 801 SimpleRandomGenerator random (dataSeed); 802 803 for (deUint32 i = 0u; i < params.bufferSize; ++i) 804 { 805 hostBuffer[i] = static_cast<deUint8>(random.getNext() & 0xFFu); 806 } 807 hostMemory.flush(0u, params.bufferSize); 808 } 809 810 deBool checkData (VkDeviceMemory memory, 811 deUint32 dataSeed, 812 Context& ctx, 813 BindingCaseParameters params) 814 { 815 const DeviceInterface& vk = ctx.getDeviceInterface(); 816 const VkDevice vkDevice = ctx.getDevice(); 817 MemoryMappingRAII hostMemory (vk, vkDevice, memory, 0u, params.bufferSize, 0u); 818 deUint8* hostBuffer = static_cast<deUint8*>(hostMemory.ptr()); 819 SimpleRandomGenerator random (dataSeed); 820 821 for (deUint32 i = 0u; i < params.bufferSize; ++i) 822 { 823 if (hostBuffer[i] != static_cast<deUint8>(random.getNext() & 0xFFu) ) 824 return DE_FALSE; 825 } 826 return DE_TRUE; 827 } 828 829 template<typename TTarget, deBool TDedicated> 830 class MemoryBindingInstance : public TestInstance 831 { 832 public: 833 MemoryBindingInstance (Context& ctx, 834 BindingCaseParameters params) 835 : TestInstance (ctx) 836 , m_params (params) 837 { 838 } 839 840 virtual tcu::TestStatus iterate (void) 841 { 842 const std::vector<std::string>& extensions = m_context.getDeviceExtensions(); 843 const deBool isSupported = isDeviceExtensionSupported(m_context.getUsedApiVersion(), extensions, "VK_KHR_bind_memory2"); 844 if (!isSupported) 845 { 846 TCU_THROW(NotSupportedError, "Not supported"); 847 } 848 849 std::vector<de::SharedPtr<Move<TTarget> > > 850 targets; 851 MemoryRegionsList memory; 852 853 createBindingTargets<TTarget>(targets, m_context, m_params); 854 createMemory<TTarget, TDedicated>(targets, memory, m_context, m_params); 855 makeBinding<TTarget>(targets, memory, m_context, m_params); 856 857 Move<VkBuffer> srcBuffer; 858 Move<VkDeviceMemory> srcMemory; 859 860 createBuffer(srcBuffer, srcMemory, m_context, m_params); 861 pushData(*srcMemory, 1, m_context, m_params); 862 863 Move<VkBuffer> dstBuffer; 864 Move<VkDeviceMemory> dstMemory; 865 866 createBuffer(dstBuffer, dstMemory, m_context, m_params); 867 868 deBool passed = DE_TRUE; 869 for (deUint32 i = 0; passed && i < m_params.targetsCount; ++i) 870 { 871 fillUpResource(srcBuffer, *targets[i], m_context, m_params); 872 readUpResource(*targets[i], dstBuffer, m_context, m_params); 873 passed = checkData(*dstMemory, 1, m_context, m_params); 874 } 875 876 return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed"); 877 } 878 private: 879 BindingCaseParameters m_params; 880 }; 881 882 template<typename TTarget, deBool TDedicated> 883 class AliasedMemoryBindingInstance : public TestInstance 884 { 885 public: 886 AliasedMemoryBindingInstance (Context& ctx, 887 BindingCaseParameters params) 888 : TestInstance (ctx) 889 , m_params (params) 890 { 891 } 892 893 virtual tcu::TestStatus iterate (void) 894 { 895 const std::vector<std::string>& extensions = m_context.getDeviceExtensions(); 896 const deBool isSupported = isDeviceExtensionSupported(m_context.getUsedApiVersion(), extensions, "VK_KHR_bind_memory2"); 897 if (!isSupported) 898 { 899 TCU_THROW(NotSupportedError, "Not supported"); 900 } 901 902 std::vector<de::SharedPtr<Move<TTarget> > > 903 targets[2]; 904 MemoryRegionsList memory; 905 906 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i) 907 createBindingTargets<TTarget>(targets[i], m_context, m_params); 908 createMemory<TTarget, TDedicated>(targets[0], memory, m_context, m_params); 909 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i) 910 makeBinding<TTarget>(targets[i], memory, m_context, m_params); 911 912 Move<VkBuffer> srcBuffer; 913 Move<VkDeviceMemory> srcMemory; 914 915 createBuffer(srcBuffer, srcMemory, m_context, m_params); 916 pushData(*srcMemory, 2, m_context, m_params); 917 918 Move<VkBuffer> dstBuffer; 919 Move<VkDeviceMemory> dstMemory; 920 921 createBuffer(dstBuffer, dstMemory, m_context, m_params); 922 923 deBool passed = DE_TRUE; 924 for (deUint32 i = 0; passed && i < m_params.targetsCount; ++i) 925 { 926 fillUpResource(srcBuffer, *(targets[0][i]), m_context, m_params); 927 readUpResource(*(targets[1][i]), dstBuffer, m_context, m_params); 928 passed = checkData(*dstMemory, 2, m_context, m_params); 929 } 930 931 return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed"); 932 } 933 private: 934 BindingCaseParameters m_params; 935 }; 936 937 template<typename TInstance> 938 class MemoryBindingTest : public TestCase 939 { 940 public: 941 MemoryBindingTest (tcu::TestContext& testCtx, 942 const std::string& name, 943 const std::string& description, 944 BindingCaseParameters params) 945 : TestCase (testCtx, name, description) 946 , m_params (params) 947 { 948 } 949 950 virtual ~MemoryBindingTest (void) 951 { 952 } 953 954 virtual TestInstance* createInstance (Context& ctx) const 955 { 956 return new TInstance(ctx, m_params); 957 } 958 959 private: 960 BindingCaseParameters m_params; 961 }; 962 963 } // unnamed namespace 964 965 tcu::TestCaseGroup* createMemoryBindingTests (tcu::TestContext& testCtx) 966 { 967 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "binding", "Memory binding tests.")); 968 969 de::MovePtr<tcu::TestCaseGroup> regular (new tcu::TestCaseGroup(testCtx, "regular", "Basic memory binding tests.")); 970 de::MovePtr<tcu::TestCaseGroup> aliasing (new tcu::TestCaseGroup(testCtx, "aliasing", "Memory binding tests with aliasing of two resources.")); 971 972 de::MovePtr<tcu::TestCaseGroup> regular_suballocated (new tcu::TestCaseGroup(testCtx, "suballocated", "Basic memory binding tests with suballocated memory.")); 973 de::MovePtr<tcu::TestCaseGroup> regular_dedicated (new tcu::TestCaseGroup(testCtx, "dedicated", "Basic memory binding tests with deditatedly allocated memory.")); 974 975 de::MovePtr<tcu::TestCaseGroup> aliasing_suballocated (new tcu::TestCaseGroup(testCtx, "suballocated", "Memory binding tests with aliasing of two resources with suballocated mamory.")); 976 977 const VkDeviceSize allocationSizes[] = { 33, 257, 4087, 8095, 1*1024*1024 + 1 }; 978 979 for (deUint32 sizeNdx = 0u; sizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); ++sizeNdx ) 980 { 981 const VkDeviceSize bufferSize = allocationSizes[sizeNdx]; 982 const BindingCaseParameters params = makeBindingCaseParameters(10, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, bufferSize); 983 std::ostringstream testName; 984 985 testName << "buffer_" << bufferSize; 986 regular_suballocated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkBuffer, DE_FALSE> >(testCtx, testName.str(), " ", params)); 987 regular_dedicated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkBuffer, DE_TRUE> >(testCtx, testName.str(), " ", params)); 988 aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkBuffer, DE_FALSE> >(testCtx, testName.str(), " ", params)); 989 } 990 991 const deUint32 imageSizes[] = { 8, 33, 257 }; 992 993 for (deUint32 widthNdx = 0u; widthNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++widthNdx ) 994 for (deUint32 heightNdx = 0u; heightNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++heightNdx ) 995 { 996 const deUint32 width = imageSizes[widthNdx]; 997 const deUint32 height = imageSizes[heightNdx]; 998 const BindingCaseParameters regularparams = makeBindingCaseParameters(10, width, height); 999 std::ostringstream testName; 1000 1001 testName << "image_" << width << '_' << height; 1002 regular_suballocated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, DE_FALSE> >(testCtx, testName.str(), " ", regularparams)); 1003 regular_dedicated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, DE_TRUE> >(testCtx, testName.str(), "", regularparams)); 1004 aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkImage, DE_FALSE> >(testCtx, testName.str(), " ", regularparams)); 1005 } 1006 1007 regular->addChild(regular_suballocated.release()); 1008 regular->addChild(regular_dedicated.release()); 1009 1010 aliasing->addChild(aliasing_suballocated.release()); 1011 1012 group->addChild(regular.release()); 1013 group->addChild(aliasing.release()); 1014 1015 return group.release(); 1016 } 1017 1018 } // memory 1019 } // vkt 1020