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 41namespace vkt 42{ 43namespace memory 44{ 45namespace 46{ 47 48using namespace vk; 49 50typedef const VkMemoryDedicatedAllocateInfoKHR ConstDedicatedInfo; 51typedef de::SharedPtr<Move<VkDeviceMemory> > MemoryRegionPtr; 52typedef std::vector<MemoryRegionPtr> MemoryRegionsList; 53typedef de::SharedPtr<Move<VkBuffer> > BufferPtr; 54typedef std::vector<BufferPtr> BuffersList; 55typedef de::SharedPtr<Move<VkImage> > ImagePtr; 56typedef std::vector<ImagePtr> ImagesList; 57typedef std::vector<VkBindBufferMemoryInfoKHR> BindBufferMemoryInfosList; 58typedef std::vector<VkBindImageMemoryInfoKHR> BindImageMemoryInfosList; 59 60class MemoryMappingRAII 61{ 62public: 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 96protected: 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 117class SimpleRandomGenerator 118{ 119public: 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 } 131protected: 132 deUint32 value; 133}; 134 135struct BindingCaseParameters 136{ 137 VkBufferCreateFlags flags; 138 VkBufferUsageFlags usage; 139 VkSharingMode sharing; 140 VkDeviceSize bufferSize; 141 VkExtent3D imageSize; 142 deUint32 targetsCount; 143}; 144 145BindingCaseParameters 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 160BindingCaseParameters 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 177VkImageCreateInfo 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 200VkBufferCreateInfo 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 218const 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 232enum MemoryHostVisibility 233{ 234 MemoryAny, 235 MemoryHostVisible 236}; 237 238deUint32 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 260const 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 275ConstDedicatedInfo 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 287ConstDedicatedInfo 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 299const VkBindBufferMemoryInfoKHR makeBufferMemoryBindingInfo (VkBuffer buffer, 300 VkDeviceMemory memory) 301{ 302 const VkBindBufferMemoryInfoKHR 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 313const VkBindImageMemoryInfoKHR makeImageMemoryBindingInfo (VkImage image, 314 VkDeviceMemory memory) 315{ 316 const VkBindImageMemoryInfoKHR 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 327enum TransferDirection 328{ 329 TransferToResource = 0, 330 TransferFromResource = 1 331}; 332 333const 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 355const 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 384const 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 396const 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 413Move<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 429template<typename TTarget> 430void createBindingTargets (std::vector<de::SharedPtr<Move<TTarget> > >& 431 targets, 432 Context& ctx, 433 BindingCaseParameters params); 434 435template<> 436void 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 452template<> 453void 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 469template<typename TTarget, deBool TDedicated> 470void createMemory (std::vector<de::SharedPtr<Move<TTarget> > >& 471 targets, 472 MemoryRegionsList& memory, 473 Context& ctx, 474 BindingCaseParameters params); 475 476template<> 477void 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 502template<> 503void 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 527template<> 528void 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 554template<> 555void 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 580template<typename TTarget> 581void makeBinding (std::vector<de::SharedPtr<Move<TTarget> > >& 582 targets, 583 MemoryRegionsList& memory, 584 Context& ctx, 585 BindingCaseParameters params); 586 587template<> 588void 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.bindBufferMemory2KHR(vkDevice, count, &bindMemoryInfos.front())); 605} 606 607template<> 608void 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.bindImageMemory2KHR(vkDevice, count, &bindMemoryInfos.front())); 625} 626 627template <typename TTarget> 628void fillUpResource (Move<VkBuffer>& source, 629 Move<TTarget>& target, 630 Context& ctx, 631 BindingCaseParameters params); 632 633template <> 634void 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 664template <> 665void 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 710template <typename TTarget> 711void readUpResource (Move<TTarget>& source, 712 Move<VkBuffer>& target, 713 Context& ctx, 714 BindingCaseParameters params); 715 716template <> 717void readUpResource (Move<VkBuffer>& source, 718 Move<VkBuffer>& target, 719 Context& ctx, 720 BindingCaseParameters params) 721{ 722 fillUpResource(source, target, ctx, params); 723} 724 725template <> 726void 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 771void 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 792void 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 810deBool 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 829template<typename TTarget, deBool TDedicated> 830class MemoryBindingInstance : public TestInstance 831{ 832public: 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 = std::find(extensions.begin(), extensions.end(), "VK_KHR_bind_memory2") != extensions.end(); 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 } 878private: 879 BindingCaseParameters m_params; 880}; 881 882template<typename TTarget, deBool TDedicated> 883class AliasedMemoryBindingInstance : public TestInstance 884{ 885public: 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 = std::find(extensions.begin(), extensions.end(), "VK_KHR_bind_memory2") != extensions.end(); 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 } 933private: 934 BindingCaseParameters m_params; 935}; 936 937template<typename TInstance> 938class MemoryBindingTest : public TestCase 939{ 940public: 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 959private: 960 BindingCaseParameters m_params; 961}; 962 963} // unnamed namespace 964 965tcu::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