1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 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 vktSparseResourcesTestsUtil.cpp 21 * \brief Sparse Resources Tests Utility Classes 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktSparseResourcesTestsUtil.hpp" 25 #include "vkQueryUtil.hpp" 26 #include "vkDeviceUtil.hpp" 27 #include "vkTypeUtil.hpp" 28 #include "tcuTextureUtil.hpp" 29 30 #include <deMath.h> 31 32 using namespace vk; 33 34 namespace vkt 35 { 36 namespace sparse 37 { 38 39 tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel) 40 { 41 const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u); 42 const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u); 43 const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u); 44 45 switch (imageType) 46 { 47 case IMAGE_TYPE_1D: 48 return tcu::UVec3(mipLevelX, 1u, 1u); 49 50 case IMAGE_TYPE_BUFFER: 51 return tcu::UVec3(imageSize.x(), 1u, 1u); 52 53 case IMAGE_TYPE_1D_ARRAY: 54 return tcu::UVec3(mipLevelX, imageSize.z(), 1u); 55 56 case IMAGE_TYPE_2D: 57 return tcu::UVec3(mipLevelX, mipLevelY, 1u); 58 59 case IMAGE_TYPE_2D_ARRAY: 60 return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z()); 61 62 case IMAGE_TYPE_3D: 63 return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ); 64 65 case IMAGE_TYPE_CUBE: 66 return tcu::UVec3(mipLevelX, mipLevelY, 6u); 67 68 case IMAGE_TYPE_CUBE_ARRAY: 69 return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z()); 70 71 default: 72 DE_FATAL("Unknown image type"); 73 return tcu::UVec3(1u, 1u, 1u); 74 } 75 } 76 77 tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize) 78 { 79 switch (imageType) 80 { 81 case IMAGE_TYPE_1D: 82 case IMAGE_TYPE_1D_ARRAY: 83 case IMAGE_TYPE_BUFFER: 84 return tcu::UVec3(imageSize.x(), 1u, 1u); 85 86 case IMAGE_TYPE_2D: 87 case IMAGE_TYPE_2D_ARRAY: 88 case IMAGE_TYPE_CUBE: 89 case IMAGE_TYPE_CUBE_ARRAY: 90 return tcu::UVec3(imageSize.x(), imageSize.y(), 1u); 91 92 case IMAGE_TYPE_3D: 93 return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z()); 94 95 default: 96 DE_FATAL("Unknown image type"); 97 return tcu::UVec3(1u, 1u, 1u); 98 } 99 } 100 101 deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize) 102 { 103 switch (imageType) 104 { 105 case IMAGE_TYPE_1D: 106 case IMAGE_TYPE_2D: 107 case IMAGE_TYPE_3D: 108 case IMAGE_TYPE_BUFFER: 109 return 1u; 110 111 case IMAGE_TYPE_1D_ARRAY: 112 case IMAGE_TYPE_2D_ARRAY: 113 return imageSize.z(); 114 115 case IMAGE_TYPE_CUBE: 116 return 6u; 117 118 case IMAGE_TYPE_CUBE_ARRAY: 119 return imageSize.z() * 6u; 120 121 default: 122 DE_FATAL("Unknown image type"); 123 return 0u; 124 } 125 } 126 127 deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize) 128 { 129 const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize); 130 131 return gridSize.x() * gridSize.y() * gridSize.z(); 132 } 133 134 deUint32 getDimensions (const ImageType imageType) 135 { 136 switch (imageType) 137 { 138 case IMAGE_TYPE_1D: 139 case IMAGE_TYPE_BUFFER: 140 return 1u; 141 142 case IMAGE_TYPE_1D_ARRAY: 143 case IMAGE_TYPE_2D: 144 return 2u; 145 146 case IMAGE_TYPE_2D_ARRAY: 147 case IMAGE_TYPE_CUBE: 148 case IMAGE_TYPE_CUBE_ARRAY: 149 case IMAGE_TYPE_3D: 150 return 3u; 151 152 default: 153 DE_FATAL("Unknown image type"); 154 return 0u; 155 } 156 } 157 158 deUint32 getLayerDimensions (const ImageType imageType) 159 { 160 switch (imageType) 161 { 162 case IMAGE_TYPE_1D: 163 case IMAGE_TYPE_BUFFER: 164 case IMAGE_TYPE_1D_ARRAY: 165 return 1u; 166 167 case IMAGE_TYPE_2D: 168 case IMAGE_TYPE_2D_ARRAY: 169 case IMAGE_TYPE_CUBE: 170 case IMAGE_TYPE_CUBE_ARRAY: 171 return 2u; 172 173 case IMAGE_TYPE_3D: 174 return 3u; 175 176 default: 177 DE_FATAL("Unknown image type"); 178 return 0u; 179 } 180 } 181 182 bool isImageSizeSupported (const InstanceInterface& instance, const VkPhysicalDevice physicalDevice, const ImageType imageType, const tcu::UVec3& imageSize) 183 { 184 const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice); 185 186 switch (imageType) 187 { 188 case IMAGE_TYPE_1D: 189 return imageSize.x() <= deviceProperties.limits.maxImageDimension1D; 190 case IMAGE_TYPE_1D_ARRAY: 191 return imageSize.x() <= deviceProperties.limits.maxImageDimension1D && 192 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; 193 case IMAGE_TYPE_2D: 194 return imageSize.x() <= deviceProperties.limits.maxImageDimension2D && 195 imageSize.y() <= deviceProperties.limits.maxImageDimension2D; 196 case IMAGE_TYPE_2D_ARRAY: 197 return imageSize.x() <= deviceProperties.limits.maxImageDimension2D && 198 imageSize.y() <= deviceProperties.limits.maxImageDimension2D && 199 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; 200 case IMAGE_TYPE_CUBE: 201 return imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && 202 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube; 203 case IMAGE_TYPE_CUBE_ARRAY: 204 return imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && 205 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube && 206 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; 207 case IMAGE_TYPE_3D: 208 return imageSize.x() <= deviceProperties.limits.maxImageDimension3D && 209 imageSize.y() <= deviceProperties.limits.maxImageDimension3D && 210 imageSize.z() <= deviceProperties.limits.maxImageDimension3D; 211 case IMAGE_TYPE_BUFFER: 212 return true; 213 default: 214 DE_FATAL("Unknown image type"); 215 return false; 216 } 217 } 218 219 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize, 220 const VkBufferUsageFlags usage) 221 { 222 const VkBufferCreateInfo bufferCreateInfo = 223 { 224 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 225 DE_NULL, // const void* pNext; 226 0u, // VkBufferCreateFlags flags; 227 bufferSize, // VkDeviceSize size; 228 usage, // VkBufferUsageFlags usage; 229 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 230 0u, // deUint32 queueFamilyIndexCount; 231 DE_NULL, // const deUint32* pQueueFamilyIndices; 232 }; 233 return bufferCreateInfo; 234 } 235 236 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent, 237 const deUint32 layerCount, 238 const deUint32 mipmapLevel, 239 const VkDeviceSize bufferOffset) 240 { 241 const VkBufferImageCopy copyParams = 242 { 243 bufferOffset, // VkDeviceSize bufferOffset; 244 0u, // deUint32 bufferRowLength; 245 0u, // deUint32 bufferImageHeight; 246 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipmapLevel, 0u, layerCount), // VkImageSubresourceLayers imageSubresource; 247 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 248 extent, // VkExtent3D imageExtent; 249 }; 250 return copyParams; 251 } 252 253 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex) 254 { 255 const VkCommandPoolCreateInfo commandPoolParams = 256 { 257 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 258 DE_NULL, // const void* pNext; 259 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags; 260 queueFamilyIndex, // deUint32 queueFamilyIndex; 261 }; 262 return createCommandPool(vk, device, &commandPoolParams); 263 } 264 265 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk, 266 const VkDevice device, 267 const VkDescriptorSetLayout descriptorSetLayout) 268 { 269 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 270 { 271 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 272 DE_NULL, // const void* pNext; 273 0u, // VkPipelineLayoutCreateFlags flags; 274 (descriptorSetLayout != DE_NULL ? 1u : 0u), // deUint32 setLayoutCount; 275 (descriptorSetLayout != DE_NULL ? &descriptorSetLayout : DE_NULL), // const VkDescriptorSetLayout* pSetLayouts; 276 0u, // deUint32 pushConstantRangeCount; 277 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 278 }; 279 return createPipelineLayout(vk, device, &pipelineLayoutParams); 280 } 281 282 Move<VkPipeline> makeComputePipeline (const DeviceInterface& vk, 283 const VkDevice device, 284 const VkPipelineLayout pipelineLayout, 285 const VkShaderModule shaderModule, 286 const VkSpecializationInfo* specializationInfo) 287 { 288 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = 289 { 290 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 291 DE_NULL, // const void* pNext; 292 0u, // VkPipelineShaderStageCreateFlags flags; 293 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 294 shaderModule, // VkShaderModule module; 295 "main", // const char* pName; 296 specializationInfo, // const VkSpecializationInfo* pSpecializationInfo; 297 }; 298 const VkComputePipelineCreateInfo pipelineCreateInfo = 299 { 300 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; 301 DE_NULL, // const void* pNext; 302 0u, // VkPipelineCreateFlags flags; 303 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage; 304 pipelineLayout, // VkPipelineLayout layout; 305 DE_NULL, // VkPipeline basePipelineHandle; 306 0, // deInt32 basePipelineIndex; 307 }; 308 return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo); 309 } 310 311 Move<VkBufferView> makeBufferView (const DeviceInterface& vk, 312 const VkDevice vkDevice, 313 const VkBuffer buffer, 314 const VkFormat format, 315 const VkDeviceSize offset, 316 const VkDeviceSize size) 317 { 318 const VkBufferViewCreateInfo bufferViewParams = 319 { 320 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType; 321 DE_NULL, // const void* pNext; 322 0u, // VkBufferViewCreateFlags flags; 323 buffer, // VkBuffer buffer; 324 format, // VkFormat format; 325 offset, // VkDeviceSize offset; 326 size, // VkDeviceSize range; 327 }; 328 return createBufferView(vk, vkDevice, &bufferViewParams); 329 } 330 331 Move<VkImageView> makeImageView (const DeviceInterface& vk, 332 const VkDevice vkDevice, 333 const VkImage image, 334 const VkImageViewType imageViewType, 335 const VkFormat format, 336 const VkImageSubresourceRange subresourceRange) 337 { 338 const VkImageViewCreateInfo imageViewParams = 339 { 340 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 341 DE_NULL, // const void* pNext; 342 0u, // VkImageViewCreateFlags flags; 343 image, // VkImage image; 344 imageViewType, // VkImageViewType viewType; 345 format, // VkFormat format; 346 makeComponentMappingRGBA(), // VkComponentMapping components; 347 subresourceRange, // VkImageSubresourceRange subresourceRange; 348 }; 349 return createImageView(vk, vkDevice, &imageViewParams); 350 } 351 352 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface& vk, 353 const VkDevice device, 354 const VkDescriptorPool descriptorPool, 355 const VkDescriptorSetLayout setLayout) 356 { 357 const VkDescriptorSetAllocateInfo allocateParams = 358 { 359 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; 360 DE_NULL, // const void* pNext; 361 descriptorPool, // VkDescriptorPool descriptorPool; 362 1u, // deUint32 setLayoutCount; 363 &setLayout, // const VkDescriptorSetLayout* pSetLayouts; 364 }; 365 return allocateDescriptorSet(vk, device, &allocateParams); 366 } 367 368 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, 369 const VkDevice device, 370 const VkRenderPass renderPass, 371 const deUint32 attachmentCount, 372 const VkImageView* pAttachments, 373 const deUint32 width, 374 const deUint32 height, 375 const deUint32 layers) 376 { 377 const VkFramebufferCreateInfo framebufferInfo = 378 { 379 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 380 DE_NULL, // const void* pNext; 381 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 382 renderPass, // VkRenderPass renderPass; 383 attachmentCount, // uint32_t attachmentCount; 384 pAttachments, // const VkImageView* pAttachments; 385 width, // uint32_t width; 386 height, // uint32_t height; 387 layers, // uint32_t layers; 388 }; 389 390 return createFramebuffer(vk, device, &framebufferInfo); 391 } 392 393 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement) 394 { 395 de::MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement); 396 VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset())); 397 return alloc; 398 } 399 400 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement) 401 { 402 de::MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement)); 403 VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset())); 404 return alloc; 405 } 406 407 void submitCommands (const DeviceInterface& vk, 408 const VkQueue queue, 409 const VkCommandBuffer commandBuffer, 410 const deUint32 waitSemaphoreCount, 411 const VkSemaphore* pWaitSemaphores, 412 const VkPipelineStageFlags* pWaitDstStageMask, 413 const deUint32 signalSemaphoreCount, 414 const VkSemaphore* pSignalSemaphores) 415 { 416 const VkSubmitInfo submitInfo = 417 { 418 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 419 DE_NULL, // const void* pNext; 420 waitSemaphoreCount, // deUint32 waitSemaphoreCount; 421 pWaitSemaphores, // const VkSemaphore* pWaitSemaphores; 422 pWaitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask; 423 1u, // deUint32 commandBufferCount; 424 &commandBuffer, // const VkCommandBuffer* pCommandBuffers; 425 signalSemaphoreCount, // deUint32 signalSemaphoreCount; 426 pSignalSemaphores, // const VkSemaphore* pSignalSemaphores; 427 }; 428 429 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL)); 430 } 431 432 void submitCommandsAndWait (const DeviceInterface& vk, 433 const VkDevice device, 434 const VkQueue queue, 435 const VkCommandBuffer commandBuffer, 436 const deUint32 waitSemaphoreCount, 437 const VkSemaphore* pWaitSemaphores, 438 const VkPipelineStageFlags* pWaitDstStageMask, 439 const deUint32 signalSemaphoreCount, 440 const VkSemaphore* pSignalSemaphores, 441 const bool useDeviceGroups, 442 const deUint32 physicalDeviceID) 443 { 444 const VkFenceCreateInfo fenceParams = 445 { 446 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 447 DE_NULL, // const void* pNext; 448 0u, // VkFenceCreateFlags flags; 449 }; 450 const Unique<VkFence> fence(createFence (vk, device, &fenceParams)); 451 452 const deUint32 deviceMask = 1 << physicalDeviceID; 453 std::vector<deUint32> deviceIndices (waitSemaphoreCount, physicalDeviceID); 454 VkDeviceGroupSubmitInfo deviceGroupSubmitInfo = 455 { 456 VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR, //VkStructureType sType 457 DE_NULL, // const void* pNext 458 waitSemaphoreCount, // uint32_t waitSemaphoreCount 459 deviceIndices.size() ? &deviceIndices[0] : DE_NULL, // const uint32_t* pWaitSemaphoreDeviceIndices 460 1u, // uint32_t commandBufferCount 461 &deviceMask, // const uint32_t* pCommandBufferDeviceMasks 462 0u, // uint32_t signalSemaphoreCount 463 DE_NULL, // const uint32_t* pSignalSemaphoreDeviceIndices 464 }; 465 const VkSubmitInfo submitInfo = 466 { 467 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 468 useDeviceGroups ? &deviceGroupSubmitInfo : DE_NULL, // const void* pNext; 469 waitSemaphoreCount, // deUint32 waitSemaphoreCount; 470 pWaitSemaphores, // const VkSemaphore* pWaitSemaphores; 471 pWaitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask; 472 1u, // deUint32 commandBufferCount; 473 &commandBuffer, // const VkCommandBuffer* pCommandBuffers; 474 signalSemaphoreCount, // deUint32 signalSemaphoreCount; 475 pSignalSemaphores, // const VkSemaphore* pSignalSemaphores; 476 }; 477 478 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); 479 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); 480 } 481 482 VkImageType mapImageType (const ImageType imageType) 483 { 484 switch (imageType) 485 { 486 case IMAGE_TYPE_1D: 487 case IMAGE_TYPE_1D_ARRAY: 488 case IMAGE_TYPE_BUFFER: 489 return VK_IMAGE_TYPE_1D; 490 491 case IMAGE_TYPE_2D: 492 case IMAGE_TYPE_2D_ARRAY: 493 case IMAGE_TYPE_CUBE: 494 case IMAGE_TYPE_CUBE_ARRAY: 495 return VK_IMAGE_TYPE_2D; 496 497 case IMAGE_TYPE_3D: 498 return VK_IMAGE_TYPE_3D; 499 500 default: 501 DE_ASSERT(false); 502 return VK_IMAGE_TYPE_LAST; 503 } 504 } 505 506 VkImageViewType mapImageViewType (const ImageType imageType) 507 { 508 switch (imageType) 509 { 510 case IMAGE_TYPE_1D: return VK_IMAGE_VIEW_TYPE_1D; 511 case IMAGE_TYPE_1D_ARRAY: return VK_IMAGE_VIEW_TYPE_1D_ARRAY; 512 case IMAGE_TYPE_2D: return VK_IMAGE_VIEW_TYPE_2D; 513 case IMAGE_TYPE_2D_ARRAY: return VK_IMAGE_VIEW_TYPE_2D_ARRAY; 514 case IMAGE_TYPE_3D: return VK_IMAGE_VIEW_TYPE_3D; 515 case IMAGE_TYPE_CUBE: return VK_IMAGE_VIEW_TYPE_CUBE; 516 case IMAGE_TYPE_CUBE_ARRAY: return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; 517 518 default: 519 DE_ASSERT(false); 520 return VK_IMAGE_VIEW_TYPE_LAST; 521 } 522 } 523 524 std::string getImageTypeName (const ImageType imageType) 525 { 526 switch (imageType) 527 { 528 case IMAGE_TYPE_1D: return "1d"; 529 case IMAGE_TYPE_1D_ARRAY: return "1d_array"; 530 case IMAGE_TYPE_2D: return "2d"; 531 case IMAGE_TYPE_2D_ARRAY: return "2d_array"; 532 case IMAGE_TYPE_3D: return "3d"; 533 case IMAGE_TYPE_CUBE: return "cube"; 534 case IMAGE_TYPE_CUBE_ARRAY: return "cube_array"; 535 case IMAGE_TYPE_BUFFER: return "buffer"; 536 537 default: 538 DE_ASSERT(false); 539 return ""; 540 } 541 } 542 543 std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType) 544 { 545 std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" : 546 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : ""; 547 548 std::string imageTypePart; 549 switch (imageType) 550 { 551 case IMAGE_TYPE_1D: imageTypePart = "1D"; break; 552 case IMAGE_TYPE_1D_ARRAY: imageTypePart = "1DArray"; break; 553 case IMAGE_TYPE_2D: imageTypePart = "2D"; break; 554 case IMAGE_TYPE_2D_ARRAY: imageTypePart = "2DArray"; break; 555 case IMAGE_TYPE_3D: imageTypePart = "3D"; break; 556 case IMAGE_TYPE_CUBE: imageTypePart = "Cube"; break; 557 case IMAGE_TYPE_CUBE_ARRAY: imageTypePart = "CubeArray"; break; 558 case IMAGE_TYPE_BUFFER: imageTypePart = "Buffer"; break; 559 560 default: 561 DE_ASSERT(false); 562 } 563 564 return formatPart + "image" + imageTypePart; 565 } 566 567 568 std::string getShaderImageDataType(const tcu::TextureFormat& format) 569 { 570 switch (tcu::getTextureChannelClass(format.type)) 571 { 572 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 573 return "uvec4"; 574 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 575 return "ivec4"; 576 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 577 return "vec4"; 578 default: 579 DE_ASSERT(false); 580 return ""; 581 } 582 } 583 584 585 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format) 586 { 587 const char* orderPart; 588 const char* typePart; 589 590 switch (format.order) 591 { 592 case tcu::TextureFormat::R: orderPart = "r"; break; 593 case tcu::TextureFormat::RG: orderPart = "rg"; break; 594 case tcu::TextureFormat::RGB: orderPart = "rgb"; break; 595 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break; 596 597 default: 598 DE_ASSERT(false); 599 orderPart = DE_NULL; 600 } 601 602 switch (format.type) 603 { 604 case tcu::TextureFormat::FLOAT: typePart = "32f"; break; 605 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break; 606 607 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break; 608 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break; 609 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break; 610 611 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break; 612 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break; 613 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break; 614 615 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break; 616 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break; 617 618 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break; 619 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break; 620 621 default: 622 DE_ASSERT(false); 623 typePart = DE_NULL; 624 } 625 626 return std::string() + orderPart + typePart; 627 } 628 629 std::string getShaderImageCoordinates (const ImageType imageType, 630 const std::string& x, 631 const std::string& xy, 632 const std::string& xyz) 633 { 634 switch (imageType) 635 { 636 case IMAGE_TYPE_1D: 637 case IMAGE_TYPE_BUFFER: 638 return x; 639 640 case IMAGE_TYPE_1D_ARRAY: 641 case IMAGE_TYPE_2D: 642 return xy; 643 644 case IMAGE_TYPE_2D_ARRAY: 645 case IMAGE_TYPE_3D: 646 case IMAGE_TYPE_CUBE: 647 case IMAGE_TYPE_CUBE_ARRAY: 648 return xyz; 649 650 default: 651 DE_ASSERT(0); 652 return ""; 653 } 654 } 655 656 deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatProperties, const VkExtent3D& extent) 657 { 658 const deUint32 widestEdge = std::max(std::max(extent.width, extent.height), extent.depth); 659 660 return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels); 661 } 662 663 deUint32 getImageMipLevelSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment) 664 { 665 const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel); 666 667 return deAlign32(extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format), mipmapMemoryAlignment); 668 } 669 670 deUint32 getImageSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment) 671 { 672 deUint32 imageSizeInBytes = 0; 673 for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel) 674 imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, mipmapMemoryAlignment); 675 676 return imageSizeInBytes; 677 } 678 679 VkSparseImageMemoryBind makeSparseImageMemoryBind (const DeviceInterface& vk, 680 const VkDevice device, 681 const VkDeviceSize allocationSize, 682 const deUint32 memoryType, 683 const VkImageSubresource& subresource, 684 const VkOffset3D& offset, 685 const VkExtent3D& extent) 686 { 687 const VkMemoryAllocateInfo allocInfo = 688 { 689 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; 690 DE_NULL, // const void* pNext; 691 allocationSize, // VkDeviceSize allocationSize; 692 memoryType, // deUint32 memoryTypeIndex; 693 }; 694 695 VkDeviceMemory deviceMemory = 0; 696 VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory)); 697 698 VkSparseImageMemoryBind imageMemoryBind; 699 700 imageMemoryBind.subresource = subresource; 701 imageMemoryBind.memory = deviceMemory; 702 imageMemoryBind.memoryOffset = 0u; 703 imageMemoryBind.flags = 0u; 704 imageMemoryBind.offset = offset; 705 imageMemoryBind.extent = extent; 706 707 return imageMemoryBind; 708 } 709 710 VkSparseMemoryBind makeSparseMemoryBind (const DeviceInterface& vk, 711 const VkDevice device, 712 const VkDeviceSize allocationSize, 713 const deUint32 memoryType, 714 const VkDeviceSize resourceOffset, 715 const VkSparseMemoryBindFlags flags) 716 { 717 const VkMemoryAllocateInfo allocInfo = 718 { 719 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; 720 DE_NULL, // const void* pNext; 721 allocationSize, // VkDeviceSize allocationSize; 722 memoryType, // deUint32 memoryTypeIndex; 723 }; 724 725 VkDeviceMemory deviceMemory = 0; 726 VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory)); 727 728 VkSparseMemoryBind memoryBind; 729 730 memoryBind.resourceOffset = resourceOffset; 731 memoryBind.size = allocationSize; 732 memoryBind.memory = deviceMemory; 733 memoryBind.memoryOffset = 0u; 734 memoryBind.flags = flags; 735 736 return memoryBind; 737 } 738 739 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags) 740 { 741 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice); 742 743 if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader) 744 throw tcu::NotSupportedError("Tessellation shader not supported"); 745 746 if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader) 747 throw tcu::NotSupportedError("Geometry shader not supported"); 748 749 if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64) 750 throw tcu::NotSupportedError("Double-precision floats not supported"); 751 752 if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics) 753 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline"); 754 755 if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics) 756 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader"); 757 758 if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize) 759 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in"); 760 } 761 762 deUint32 findMatchingMemoryType (const InstanceInterface& instance, 763 const VkPhysicalDevice physicalDevice, 764 const VkMemoryRequirements& objectMemoryRequirements, 765 const MemoryRequirement& memoryRequirement) 766 { 767 const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice); 768 769 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx) 770 { 771 if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 && 772 memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags)) 773 { 774 return memoryTypeNdx; 775 } 776 } 777 778 return NO_MATCH_FOUND; 779 } 780 781 deUint32 getHeapIndexForMemoryType (const InstanceInterface& instance, 782 const VkPhysicalDevice physicalDevice, 783 const deUint32 memoryType) 784 { 785 const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice); 786 DE_ASSERT(memoryType < deviceMemoryProperties.memoryTypeCount); 787 return deviceMemoryProperties.memoryTypes[memoryType].heapIndex; 788 } 789 790 bool checkSparseSupportForImageType (const InstanceInterface& instance, 791 const VkPhysicalDevice physicalDevice, 792 const ImageType imageType) 793 { 794 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice); 795 796 if (!deviceFeatures.sparseBinding) 797 return false; 798 799 switch (mapImageType(imageType)) 800 { 801 case VK_IMAGE_TYPE_2D: 802 return deviceFeatures.sparseResidencyImage2D == VK_TRUE; 803 case VK_IMAGE_TYPE_3D: 804 return deviceFeatures.sparseResidencyImage3D == VK_TRUE; 805 default: 806 DE_ASSERT(0); 807 return false; 808 }; 809 } 810 811 bool checkSparseSupportForImageFormat (const InstanceInterface& instance, 812 const VkPhysicalDevice physicalDevice, 813 const VkImageCreateInfo& imageInfo) 814 { 815 const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties( 816 instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling); 817 818 return sparseImageFormatPropVec.size() > 0u; 819 } 820 821 bool checkImageFormatFeatureSupport (const InstanceInterface& instance, 822 const VkPhysicalDevice physicalDevice, 823 const VkFormat format, 824 const VkFormatFeatureFlags featureFlags) 825 { 826 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format); 827 828 return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags; 829 } 830 831 deUint32 getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>& requirements, 832 const VkImageAspectFlags aspectFlags) 833 { 834 for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx) 835 { 836 if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags) 837 return memoryReqNdx; 838 } 839 840 return NO_MATCH_FOUND; 841 } 842 843 } // sparse 844 } // vkt 845