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 vktPipelineRenderToImageTests.cpp 21 * \brief Render to image tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktPipelineRenderToImageTests.hpp" 25 #include "vktPipelineMakeUtil.hpp" 26 #include "vktTestCase.hpp" 27 #include "vktTestCaseUtil.hpp" 28 #include "vktPipelineVertexUtil.hpp" 29 #include "vktTestGroupUtil.hpp" 30 31 #include "vkMemUtil.hpp" 32 #include "vkQueryUtil.hpp" 33 #include "vkTypeUtil.hpp" 34 #include "vkRefUtil.hpp" 35 #include "vkBuilderUtil.hpp" 36 #include "vkPrograms.hpp" 37 #include "vkImageUtil.hpp" 38 #include "vkCmdUtil.hpp" 39 40 #include "tcuTextureUtil.hpp" 41 #include "tcuImageCompare.hpp" 42 #include "tcuTestLog.hpp" 43 44 #include "deUniquePtr.hpp" 45 #include "deSharedPtr.hpp" 46 47 #include <string> 48 #include <vector> 49 #include <set> 50 51 namespace vkt 52 { 53 namespace pipeline 54 { 55 namespace 56 { 57 using namespace vk; 58 using de::UniquePtr; 59 using de::MovePtr; 60 using de::SharedPtr; 61 using tcu::IVec3; 62 using tcu::Vec4; 63 using tcu::UVec4; 64 using tcu::IVec2; 65 using tcu::IVec4; 66 using tcu::BVec4; 67 using std::vector; 68 69 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView; 70 typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline; 71 72 enum Constants 73 { 74 NUM_CUBE_FACES = 6, 75 REFERENCE_COLOR_VALUE = 125, 76 REFERENCE_STENCIL_VALUE = 42, 77 MAX_SIZE = -1, //!< Should be queried at runtime and replaced with max possible value 78 MAX_VERIFICATION_REGION_SIZE = 32, //!< Limit the checked area to a small size, especially for huge images 79 MAX_VERIFICATION_REGION_DEPTH = 8, 80 81 MASK_W = (1 | 0 | 0 | 0), 82 MASK_W_LAYERS = (1 | 0 | 0 | 8), 83 MASK_WH = (1 | 2 | 0 | 0), 84 MASK_WH_LAYERS = (1 | 2 | 0 | 8), 85 MASK_WHD = (1 | 2 | 4 | 0), 86 }; 87 88 enum AllocationKind 89 { 90 ALLOCATION_KIND_SUBALLOCATED = 0, 91 ALLOCATION_KIND_DEDICATED, 92 }; 93 94 static const float REFERENCE_DEPTH_VALUE = 1.0f; 95 static const Vec4 COLOR_TABLE[] = 96 { 97 Vec4(0.9f, 0.0f, 0.0f, 1.0f), 98 Vec4(0.6f, 1.0f, 0.0f, 1.0f), 99 Vec4(0.3f, 0.0f, 1.0f, 1.0f), 100 Vec4(0.1f, 1.0f, 1.0f, 1.0f), 101 Vec4(0.8f, 1.0f, 0.0f, 1.0f), 102 Vec4(0.5f, 0.0f, 1.0f, 1.0f), 103 Vec4(0.2f, 0.0f, 0.0f, 1.0f), 104 Vec4(1.0f, 1.0f, 0.0f, 1.0f), 105 }; 106 107 struct CaseDef 108 { 109 VkImageViewType viewType; 110 IVec4 imageSizeHint; //!< (w, h, d, layers), a component may have a symbolic value MAX_SIZE 111 VkFormat colorFormat; 112 VkFormat depthStencilFormat; //! A depth/stencil format, or UNDEFINED if not used 113 AllocationKind allocationKind; 114 }; 115 116 template<typename T> 117 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move) 118 { 119 return SharedPtr<Unique<T> >(new Unique<T>(move)); 120 } 121 122 template<typename T> 123 inline VkDeviceSize sizeInBytes (const vector<T>& vec) 124 { 125 return vec.size() * sizeof(vec[0]); 126 } 127 128 inline bool isCube (const VkImageViewType viewType) 129 { 130 return (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); 131 } 132 133 inline VkDeviceSize product (const IVec4& v) 134 { 135 return ((static_cast<VkDeviceSize>(v.x()) * v.y()) * v.z()) * v.w(); 136 } 137 138 template<typename T> 139 inline T sum (const vector<T>& v) 140 { 141 T total = static_cast<T>(0); 142 for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); ++it) 143 total += *it; 144 return total; 145 } 146 147 template <typename T, int Size> 148 int findIndexOfMaxComponent (const tcu::Vector<T, Size>& vec) 149 { 150 int index = 0; 151 T value = vec[0]; 152 153 for (int i = 1; i < Size; ++i) 154 { 155 if (vec[i] > value) 156 { 157 index = i; 158 value = vec[i]; 159 } 160 } 161 162 return index; 163 } 164 165 inline int maxLayersOrDepth (const IVec4& size) 166 { 167 // This is safe because 3D images must have layers (w) = 1 168 return deMax32(size.z(), size.w()); 169 } 170 171 de::MovePtr<Allocation> bindBuffer (const InstanceInterface& vki, 172 const DeviceInterface& vkd, 173 const VkPhysicalDevice& physDevice, 174 const VkDevice device, 175 const VkBuffer& buffer, 176 const MemoryRequirement requirement, 177 Allocator& allocator, 178 AllocationKind allocationKind) 179 { 180 switch (allocationKind) 181 { 182 case ALLOCATION_KIND_SUBALLOCATED: 183 { 184 return ::vkt::pipeline::bindBuffer(vkd, device, allocator, buffer, requirement); 185 } 186 187 case ALLOCATION_KIND_DEDICATED: 188 { 189 return bindBufferDedicated(vki, vkd, physDevice, device, buffer, requirement); 190 } 191 192 default: 193 { 194 TCU_THROW(InternalError, "Invalid allocation kind"); 195 } 196 } 197 } 198 199 de::MovePtr<Allocation> bindImage (const InstanceInterface& vki, 200 const DeviceInterface& vkd, 201 const VkPhysicalDevice& physDevice, 202 const VkDevice device, 203 const VkImage& image, 204 const MemoryRequirement requirement, 205 Allocator& allocator, 206 AllocationKind allocationKind) 207 { 208 switch (allocationKind) 209 { 210 case ALLOCATION_KIND_SUBALLOCATED: 211 { 212 return ::vkt::pipeline::bindImage(vkd, device, allocator, image, requirement); 213 } 214 215 case ALLOCATION_KIND_DEDICATED: 216 { 217 return bindImageDedicated(vki, vkd, physDevice, device, image, requirement); 218 } 219 220 default: 221 { 222 TCU_THROW(InternalError, "Invalid allocation kind"); 223 } 224 } 225 } 226 227 // This is very test specific, so be careful if you want to reuse this code. 228 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 229 const VkDevice device, 230 const VkPipeline basePipeline, // for derivatives 231 const VkPipelineLayout pipelineLayout, 232 const VkRenderPass renderPass, 233 const VkShaderModule vertexModule, 234 const VkShaderModule fragmentModule, 235 const IVec2& renderSize, 236 const VkPrimitiveTopology topology, 237 const deUint32 subpass, 238 const bool useDepth, 239 const bool useStencil) 240 { 241 const VkVertexInputBindingDescription vertexInputBindingDescription = 242 { 243 0u, // uint32_t binding; 244 sizeof(Vertex4RGBA), // uint32_t stride; 245 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 246 }; 247 248 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 249 { 250 { 251 0u, // uint32_t location; 252 0u, // uint32_t binding; 253 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 254 0u, // uint32_t offset; 255 }, 256 { 257 1u, // uint32_t location; 258 0u, // uint32_t binding; 259 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 260 sizeof(Vec4), // uint32_t offset; 261 } 262 }; 263 264 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 265 { 266 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 267 DE_NULL, // const void* pNext; 268 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 269 1u, // uint32_t vertexBindingDescriptionCount; 270 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 271 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 272 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 273 }; 274 275 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 276 { 277 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 278 DE_NULL, // const void* pNext; 279 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 280 topology, // VkPrimitiveTopology topology; 281 VK_FALSE, // VkBool32 primitiveRestartEnable; 282 }; 283 284 const VkViewport viewport = makeViewport(renderSize); 285 const VkRect2D scissor = makeRect2D(renderSize); 286 287 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 288 { 289 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 290 DE_NULL, // const void* pNext; 291 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 292 1u, // uint32_t viewportCount; 293 &viewport, // const VkViewport* pViewports; 294 1u, // uint32_t scissorCount; 295 &scissor, // const VkRect2D* pScissors; 296 }; 297 298 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 299 { 300 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 301 DE_NULL, // const void* pNext; 302 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 303 VK_FALSE, // VkBool32 depthClampEnable; 304 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 305 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 306 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 307 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 308 VK_FALSE, // VkBool32 depthBiasEnable; 309 0.0f, // float depthBiasConstantFactor; 310 0.0f, // float depthBiasClamp; 311 0.0f, // float depthBiasSlopeFactor; 312 1.0f, // float lineWidth; 313 }; 314 315 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 316 { 317 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 318 DE_NULL, // const void* pNext; 319 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 320 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 321 VK_FALSE, // VkBool32 sampleShadingEnable; 322 0.0f, // float minSampleShading; 323 DE_NULL, // const VkSampleMask* pSampleMask; 324 VK_FALSE, // VkBool32 alphaToCoverageEnable; 325 VK_FALSE // VkBool32 alphaToOneEnable; 326 }; 327 328 const VkStencilOpState stencilOpState = makeStencilOpState( 329 VK_STENCIL_OP_KEEP, // stencil fail 330 VK_STENCIL_OP_KEEP, // depth & stencil pass 331 VK_STENCIL_OP_KEEP, // depth only fail 332 VK_COMPARE_OP_EQUAL, // compare op 333 ~0u, // compare mask 334 ~0u, // write mask 335 static_cast<deUint32>(REFERENCE_STENCIL_VALUE)); // reference 336 337 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 338 { 339 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 340 DE_NULL, // const void* pNext; 341 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 342 useDepth, // VkBool32 depthTestEnable; 343 VK_FALSE, // VkBool32 depthWriteEnable; 344 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 345 VK_FALSE, // VkBool32 depthBoundsTestEnable; 346 useStencil, // VkBool32 stencilTestEnable; 347 stencilOpState, // VkStencilOpState front; 348 stencilOpState, // VkStencilOpState back; 349 0.0f, // float minDepthBounds; 350 1.0f, // float maxDepthBounds; 351 }; 352 353 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 354 // Number of blend attachments must equal the number of color attachments during any subpass. 355 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 356 { 357 VK_FALSE, // VkBool32 blendEnable; 358 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 359 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 360 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 361 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 362 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 363 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 364 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 365 }; 366 367 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 368 { 369 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 370 DE_NULL, // const void* pNext; 371 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 372 VK_FALSE, // VkBool32 logicOpEnable; 373 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 374 1u, // deUint32 attachmentCount; 375 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 376 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 377 }; 378 379 const VkPipelineShaderStageCreateInfo pShaderStages[] = 380 { 381 { 382 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 383 DE_NULL, // const void* pNext; 384 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 385 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 386 vertexModule, // VkShaderModule module; 387 "main", // const char* pName; 388 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 389 }, 390 { 391 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 392 DE_NULL, // const void* pNext; 393 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 394 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 395 fragmentModule, // VkShaderModule module; 396 "main", // const char* pName; 397 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 398 } 399 }; 400 401 const VkPipelineCreateFlags flags = (basePipeline == DE_NULL ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT 402 : VK_PIPELINE_CREATE_DERIVATIVE_BIT); 403 404 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 405 { 406 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 407 DE_NULL, // const void* pNext; 408 flags, // VkPipelineCreateFlags flags; 409 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 410 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 411 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 412 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 413 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 414 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 415 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 416 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 417 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 418 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 419 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 420 pipelineLayout, // VkPipelineLayout layout; 421 renderPass, // VkRenderPass renderPass; 422 subpass, // deUint32 subpass; 423 basePipeline, // VkPipeline basePipelineHandle; 424 -1, // deInt32 basePipelineIndex; 425 }; 426 427 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 428 } 429 430 //! Make a render pass with one subpass per color attachment and depth/stencil attachment (if used). 431 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 432 const VkDevice device, 433 const VkFormat colorFormat, 434 const VkFormat depthStencilFormat, 435 const deUint32 numLayers, 436 const VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, 437 const VkImageLayout initialDepthStencilImageLayout = VK_IMAGE_LAYOUT_UNDEFINED) 438 { 439 const VkAttachmentDescription colorAttachmentDescription = 440 { 441 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 442 colorFormat, // VkFormat format; 443 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 444 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 445 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 446 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 447 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 448 initialColorImageLayout, // VkImageLayout initialLayout; 449 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 450 }; 451 vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription); 452 453 const VkAttachmentDescription depthStencilAttachmentDescription = 454 { 455 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 456 depthStencilFormat, // VkFormat format; 457 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 458 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 459 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; 460 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp; 461 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 462 initialDepthStencilImageLayout, // VkImageLayout initialLayout; 463 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 464 }; 465 466 if (depthStencilFormat != VK_FORMAT_UNDEFINED) 467 attachmentDescriptions.insert(attachmentDescriptions.end(), numLayers, depthStencilAttachmentDescription); 468 469 // Create a subpass for each attachment (each attachement is a layer of an arrayed image). 470 vector<VkAttachmentReference> colorAttachmentReferences (numLayers); 471 vector<VkAttachmentReference> depthStencilAttachmentReferences(numLayers); 472 vector<VkSubpassDescription> subpasses; 473 474 // Ordering here must match the framebuffer attachments 475 for (deUint32 i = 0; i < numLayers; ++i) 476 { 477 const VkAttachmentReference attachmentRef = 478 { 479 i, // deUint32 attachment; 480 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 481 }; 482 const VkAttachmentReference depthStencilAttachmentRef = 483 { 484 i + numLayers, // deUint32 attachment; 485 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout; 486 }; 487 488 colorAttachmentReferences[i] = attachmentRef; 489 depthStencilAttachmentReferences[i] = depthStencilAttachmentRef; 490 491 const VkAttachmentReference* pDepthStencilAttachment = (depthStencilFormat != VK_FORMAT_UNDEFINED ? &depthStencilAttachmentReferences[i] : DE_NULL); 492 const VkSubpassDescription subpassDescription = 493 { 494 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 495 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 496 0u, // deUint32 inputAttachmentCount; 497 DE_NULL, // const VkAttachmentReference* pInputAttachments; 498 1u, // deUint32 colorAttachmentCount; 499 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments; 500 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 501 pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment; 502 0u, // deUint32 preserveAttachmentCount; 503 DE_NULL // const deUint32* pPreserveAttachments; 504 }; 505 subpasses.push_back(subpassDescription); 506 } 507 508 const VkRenderPassCreateInfo renderPassInfo = 509 { 510 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 511 DE_NULL, // const void* pNext; 512 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 513 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 514 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 515 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 516 &subpasses[0], // const VkSubpassDescription* pSubpasses; 517 0u, // deUint32 dependencyCount; 518 DE_NULL // const VkSubpassDependency* pDependencies; 519 }; 520 521 return createRenderPass(vk, device, &renderPassInfo); 522 } 523 524 Move<VkImage> makeImage (const DeviceInterface& vk, 525 const VkDevice device, 526 VkImageCreateFlags flags, 527 VkImageType imageType, 528 const VkFormat format, 529 const IVec3& size, 530 const deUint32 numMipLevels, 531 const deUint32 numLayers, 532 const VkImageUsageFlags usage) 533 { 534 const VkImageCreateInfo imageParams = 535 { 536 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 537 DE_NULL, // const void* pNext; 538 flags, // VkImageCreateFlags flags; 539 imageType, // VkImageType imageType; 540 format, // VkFormat format; 541 makeExtent3D(size), // VkExtent3D extent; 542 numMipLevels, // deUint32 mipLevels; 543 numLayers, // deUint32 arrayLayers; 544 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 545 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 546 usage, // VkImageUsageFlags usage; 547 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 548 0u, // deUint32 queueFamilyIndexCount; 549 DE_NULL, // const deUint32* pQueueFamilyIndices; 550 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 551 }; 552 return createImage(vk, device, &imageParams); 553 } 554 555 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) 556 { 557 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); 558 return createBuffer(vk, device, &bufferCreateInfo); 559 } 560 561 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount) 562 { 563 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount)); 564 } 565 566 //! Get a reference clear value based on color format. 567 VkClearValue getClearValue (const VkFormat format) 568 { 569 if (isUintFormat(format) || isIntFormat(format)) 570 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE); 571 else 572 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f); 573 } 574 575 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint) 576 { 577 std::ostringstream str; 578 if (numComponents == 1) 579 str << (isUint ? "uint" : isSint ? "int" : "float"); 580 else 581 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents; 582 583 return str.str(); 584 } 585 586 //! A half-viewport quad. Use with TRIANGLE_STRIP topology. 587 vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount) 588 { 589 vector<Vertex4RGBA> vectorData; 590 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx) 591 { 592 Vertex4RGBA data = 593 { 594 Vec4(0.0f, -1.0f, 0.0f, 1.0f), 595 COLOR_TABLE[subpassNdx % DE_LENGTH_OF_ARRAY(COLOR_TABLE)], 596 }; 597 vectorData.push_back(data); 598 data.position = Vec4(0.0f, 1.0f, 0.0f, 1.0f); 599 vectorData.push_back(data); 600 data.position = Vec4(1.0f, -1.0f, 0.0f, 1.0f); 601 vectorData.push_back(data); 602 data.position = Vec4(1.0f, 1.0f, 0.0f, 1.0f); 603 vectorData.push_back(data); 604 } 605 return vectorData; 606 } 607 608 VkImageType getImageType (const VkImageViewType viewType) 609 { 610 switch (viewType) 611 { 612 case VK_IMAGE_VIEW_TYPE_1D: 613 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 614 return VK_IMAGE_TYPE_1D; 615 616 case VK_IMAGE_VIEW_TYPE_2D: 617 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 618 case VK_IMAGE_VIEW_TYPE_CUBE: 619 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 620 return VK_IMAGE_TYPE_2D; 621 622 case VK_IMAGE_VIEW_TYPE_3D: 623 return VK_IMAGE_TYPE_3D; 624 625 default: 626 DE_ASSERT(0); 627 return VK_IMAGE_TYPE_LAST; 628 } 629 } 630 631 //! ImageViewType for accessing a single layer/slice of an image 632 VkImageViewType getImageViewSliceType (const VkImageViewType viewType) 633 { 634 switch (viewType) 635 { 636 case VK_IMAGE_VIEW_TYPE_1D: 637 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 638 return VK_IMAGE_VIEW_TYPE_1D; 639 640 case VK_IMAGE_VIEW_TYPE_2D: 641 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 642 case VK_IMAGE_VIEW_TYPE_CUBE: 643 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 644 case VK_IMAGE_VIEW_TYPE_3D: 645 return VK_IMAGE_VIEW_TYPE_2D; 646 647 default: 648 DE_ASSERT(0); 649 return VK_IMAGE_VIEW_TYPE_LAST; 650 } 651 } 652 653 VkImageCreateFlags getImageCreateFlags (const VkImageViewType viewType) 654 { 655 VkImageCreateFlags flags = (VkImageCreateFlags)0; 656 657 if (viewType == VK_IMAGE_VIEW_TYPE_3D) flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR; 658 if (isCube(viewType)) flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 659 660 return flags; 661 } 662 663 void generateExpectedImage (const tcu::PixelBufferAccess& outputImage, const IVec2& renderSize, const int colorDepthOffset) 664 { 665 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(outputImage.getFormat().type); 666 const bool isInt = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); 667 const VkClearValue clearValue = getClearValue(mapTextureFormat(outputImage.getFormat())); 668 669 if (isInt) 670 tcu::clear(outputImage, IVec4(clearValue.color.int32)); 671 else 672 tcu::clear(outputImage, Vec4(clearValue.color.float32)); 673 674 for (int z = 0; z < outputImage.getDepth(); ++z) 675 { 676 const Vec4& setColor = COLOR_TABLE[(z + colorDepthOffset) % DE_LENGTH_OF_ARRAY(COLOR_TABLE)]; 677 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>(); 678 679 for (int y = 0; y < renderSize.y(); ++y) 680 for (int x = renderSize.x()/2; x < renderSize.x(); ++x) 681 { 682 if (isInt) 683 outputImage.setPixel(setColorInt, x, y, z); 684 else 685 outputImage.setPixel(setColor, x, y, z); 686 } 687 } 688 } 689 690 deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement) 691 { 692 const deUint32 compatibleTypes = getCompatibleMemoryTypes(deviceMemProps, requirement); 693 const deUint32 candidates = allowedMemTypeBits & compatibleTypes; 694 695 if (candidates == 0) 696 TCU_THROW(NotSupportedError, "No compatible memory type found"); 697 698 return (deUint32)deCtz32(candidates); 699 } 700 701 IVec4 getMaxImageSize (const VkImageViewType viewType, const IVec4& sizeHint) 702 { 703 //Limits have been taken from the vulkan specification 704 IVec4 size = IVec4( 705 sizeHint.x() != MAX_SIZE ? sizeHint.x() : 4096, 706 sizeHint.y() != MAX_SIZE ? sizeHint.y() : 4096, 707 sizeHint.z() != MAX_SIZE ? sizeHint.z() : 256, 708 sizeHint.w() != MAX_SIZE ? sizeHint.w() : 256); 709 710 switch (viewType) 711 { 712 case VK_IMAGE_VIEW_TYPE_1D: 713 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 714 size.x() = deMin32(4096, size.x()); 715 break; 716 717 case VK_IMAGE_VIEW_TYPE_2D: 718 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 719 size.x() = deMin32(4096, size.x()); 720 size.y() = deMin32(4096, size.y()); 721 break; 722 723 case VK_IMAGE_VIEW_TYPE_3D: 724 size.x() = deMin32(256, size.x()); 725 size.y() = deMin32(256, size.y()); 726 break; 727 728 case VK_IMAGE_VIEW_TYPE_CUBE: 729 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 730 size.x() = deMin32(4096, size.x()); 731 size.y() = deMin32(4096, size.y()); 732 size.w() = deMin32(252, size.w()); 733 size.w() = NUM_CUBE_FACES * (size.w() / NUM_CUBE_FACES); // round down to 6 faces 734 break; 735 736 default: 737 DE_ASSERT(0); 738 return IVec4(); 739 } 740 741 return size; 742 } 743 744 deUint32 getMemoryTypeNdx (Context& context, const CaseDef& caseDef) 745 { 746 const DeviceInterface& vk = context.getDeviceInterface(); 747 const InstanceInterface& vki = context.getInstanceInterface(); 748 const VkDevice device = context.getDevice(); 749 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 750 751 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice); 752 Move<VkImage> colorImage; 753 VkMemoryRequirements memReqs; 754 755 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 756 const IVec4 imageSize = getMaxImageSize(caseDef.viewType, caseDef.imageSizeHint); 757 758 //create image, don't bind any memory to it 759 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat, 760 imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage); 761 762 vk.getImageMemoryRequirements(device, *colorImage, &memReqs); 763 return selectMatchingMemoryType(memoryProperties, memReqs.memoryTypeBits, MemoryRequirement::Any); 764 } 765 766 VkDeviceSize getMaxDeviceHeapSize (Context& context, const CaseDef& caseDef) 767 { 768 const InstanceInterface& vki = context.getInstanceInterface(); 769 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 770 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice); 771 const deUint32 memoryTypeNdx = getMemoryTypeNdx (context, caseDef); 772 773 return memoryProperties.memoryHeaps[memoryProperties.memoryTypes[memoryTypeNdx].heapIndex].size; 774 } 775 776 //! Get a smaller image size. Returns a vector of zeroes, if it can't reduce more. 777 IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size) 778 { 779 const int maxIndex = findIndexOfMaxComponent(size); 780 const int reducedSize = size[maxIndex] >> 1; 781 782 switch (caseDef.viewType) 783 { 784 case VK_IMAGE_VIEW_TYPE_CUBE: 785 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 786 if (maxIndex < 2) 787 size.x() = size.y() = reducedSize; 788 else if (maxIndex == 3 && reducedSize >= NUM_CUBE_FACES) 789 size.w() = NUM_CUBE_FACES * (reducedSize / NUM_CUBE_FACES); // round down to a multiple of 6 790 else 791 size = IVec4(0); 792 break; 793 794 default: 795 size[maxIndex] = reducedSize; 796 break; 797 } 798 799 if (reducedSize == 0) 800 size = IVec4(0); 801 802 return size; 803 } 804 805 bool isDepthStencilFormatSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format) 806 { 807 const VkFormatProperties properties = getPhysicalDeviceFormatProperties(vki, physDevice, format); 808 return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; 809 } 810 811 VkImageAspectFlags getFormatAspectFlags (const VkFormat format) 812 { 813 if (format == VK_FORMAT_UNDEFINED) 814 return 0; 815 816 const tcu::TextureFormat::ChannelOrder order = mapVkFormat(format).order; 817 818 switch (order) 819 { 820 case tcu::TextureFormat::DS: return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 821 case tcu::TextureFormat::D: return VK_IMAGE_ASPECT_DEPTH_BIT; 822 case tcu::TextureFormat::S: return VK_IMAGE_ASPECT_STENCIL_BIT; 823 default: return VK_IMAGE_ASPECT_COLOR_BIT; 824 } 825 } 826 827 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 828 { 829 const int numComponents = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order); 830 const bool isUint = isUintFormat(caseDef.colorFormat); 831 const bool isSint = isIntFormat(caseDef.colorFormat); 832 833 // Vertex shader 834 { 835 std::ostringstream src; 836 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 837 << "\n" 838 << "layout(location = 0) in vec4 in_position;\n" 839 << "layout(location = 1) in vec4 in_color;\n" 840 << "layout(location = 0) out vec4 out_color;\n" 841 << "\n" 842 << "out gl_PerVertex {\n" 843 << " vec4 gl_Position;\n" 844 << "};\n" 845 << "\n" 846 << "void main(void)\n" 847 << "{\n" 848 << " gl_Position = in_position;\n" 849 << " out_color = in_color;\n" 850 << "}\n"; 851 852 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 853 } 854 855 // Fragment shader 856 { 857 std::ostringstream colorValue; 858 colorValue << REFERENCE_COLOR_VALUE; 859 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint); 860 const std::string colorInteger = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :""); 861 862 std::ostringstream src; 863 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 864 << "\n" 865 << "layout(location = 0) in vec4 in_color;\n" 866 << "layout(location = 0) out " << colorFormat << " o_color;\n" 867 << "\n" 868 << "void main(void)\n" 869 << "{\n" 870 << " o_color = " << colorFormat << "(" 871 << (numComponents == 1 ? "in_color.r" : 872 numComponents == 2 ? "in_color.rg" : 873 numComponents == 3 ? "in_color.rgb" : "in_color") 874 << colorInteger 875 << ");\n" 876 << "}\n"; 877 878 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 879 } 880 } 881 882 //! See testAttachmentSize() description 883 tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef) 884 { 885 const DeviceInterface& vk = context.getDeviceInterface(); 886 const InstanceInterface& vki = context.getInstanceInterface(); 887 const VkDevice device = context.getDevice(); 888 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 889 const VkQueue queue = context.getUniversalQueue(); 890 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 891 Allocator& allocator = context.getDefaultAllocator(); 892 893 // The memory might be too small to allocate a largest possible attachment, so try to account for that. 894 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED); 895 896 IVec4 imageSize = getMaxImageSize(caseDef.viewType, caseDef.imageSizeHint); 897 VkDeviceSize colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 898 VkDeviceSize depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull); 899 900 const VkDeviceSize reserveForChecking = 500ull * 1024ull; //left 512KB 901 const float additionalMemory = 1.15f; //left some free memory on device (15%) 902 VkDeviceSize neededMemory = static_cast<VkDeviceSize>(static_cast<float>(colorSize + depthStencilSize) * additionalMemory) + reserveForChecking; 903 VkDeviceSize maxMemory = getMaxDeviceHeapSize(context, caseDef) >> 2; 904 905 const VkDeviceSize deviceMemoryBudget = std::min(neededMemory, maxMemory); 906 bool allocationPossible = false; 907 908 // Keep reducing the size, if image size is too big 909 while (neededMemory > deviceMemoryBudget) 910 { 911 imageSize = getReducedImageSize(caseDef, imageSize); 912 913 if (imageSize == IVec4()) 914 return tcu::TestStatus::fail("Couldn't create an image with required size"); 915 916 colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 917 depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull); 918 neededMemory = static_cast<VkDeviceSize>(static_cast<double>(colorSize + depthStencilSize) * additionalMemory); 919 } 920 921 // Keep reducing the size, if allocation return out of any memory 922 while (!allocationPossible) 923 { 924 VkDeviceMemory object = 0; 925 const VkMemoryAllocateInfo allocateInfo = 926 { 927 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, //VkStructureType sType; 928 DE_NULL, //const void* pNext; 929 neededMemory, //VkDeviceSize allocationSize; 930 getMemoryTypeNdx(context, caseDef) //deUint32 memoryTypeIndex; 931 }; 932 933 const VkResult result = vk.allocateMemory(device, &allocateInfo, DE_NULL, &object); 934 935 if (VK_ERROR_OUT_OF_DEVICE_MEMORY == result || VK_ERROR_OUT_OF_HOST_MEMORY == result) 936 { 937 imageSize = getReducedImageSize(caseDef, imageSize); 938 939 if (imageSize == IVec4()) 940 return tcu::TestStatus::fail("Couldn't create an image with required size"); 941 942 colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 943 depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull); 944 neededMemory = static_cast<VkDeviceSize>(static_cast<double>(colorSize + depthStencilSize) * additionalMemory) + reserveForChecking; 945 } 946 else if (VK_SUCCESS != result) 947 { 948 return tcu::TestStatus::fail("Couldn't allocate memory"); 949 } 950 else 951 { 952 //free memory using Move pointer 953 Move<VkDeviceMemory> memoryAllocated (check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device, DE_NULL)); 954 allocationPossible = true; 955 } 956 } 957 958 context.getTestContext().getLog() 959 << tcu::TestLog::Message << "Using an image with size (width, height, depth, layers) = " << imageSize << tcu::TestLog::EndMessage; 960 961 // "Slices" is either the depth of a 3D image, or the number of layers of an arrayed image 962 const deInt32 numSlices = maxLayersOrDepth(imageSize); 963 964 965 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat)) 966 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format"); 967 968 // Determine the verification bounds. The checked region will be in the center of the rendered image 969 const IVec4 checkSize = tcu::min(imageSize, IVec4(MAX_VERIFICATION_REGION_SIZE, 970 MAX_VERIFICATION_REGION_SIZE, 971 MAX_VERIFICATION_REGION_DEPTH, 972 MAX_VERIFICATION_REGION_DEPTH)); 973 const IVec4 checkOffset = (imageSize - checkSize) / 2; 974 975 // Only make enough space for the check region 976 const VkDeviceSize colorBufferSize = product(checkSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 977 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 978 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vki, vk, physDevice, device, *colorBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind)); 979 980 { 981 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 982 flushAlloc(vk, device, *colorBufferAlloc); 983 } 984 985 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 986 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 987 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices), 988 (caseDef.viewType == VK_IMAGE_VIEW_TYPE_3D) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 989 : VK_IMAGE_LAYOUT_UNDEFINED)); 990 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 991 vector<SharedPtrVkPipeline> pipelines; 992 993 Move<VkImage> colorImage; 994 MovePtr<Allocation> colorImageAlloc; 995 vector<SharedPtrVkImageView> colorAttachments; 996 Move<VkImage> depthStencilImage; 997 MovePtr<Allocation> depthStencilImageAlloc; 998 vector<SharedPtrVkImageView> depthStencilAttachments; 999 vector<VkImageView> attachmentHandles; // all attachments (color and d/s) 1000 Move<VkBuffer> vertexBuffer; 1001 MovePtr<Allocation> vertexBufferAlloc; 1002 Move<VkFramebuffer> framebuffer; 1003 1004 // Create a color image 1005 { 1006 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 1007 1008 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat, 1009 imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage); 1010 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind); 1011 } 1012 1013 // Create a depth/stencil image (always a 2D image, optionally layered) 1014 if (useDepthStencil) 1015 { 1016 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 1017 1018 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat, 1019 IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage); 1020 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind); 1021 } 1022 1023 // Create a vertex buffer 1024 { 1025 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices); 1026 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 1027 1028 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1029 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind); 1030 1031 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 1032 flushAlloc(vk, device, *vertexBufferAlloc); 1033 } 1034 1035 // Prepare color image upfront for rendering to individual slices. 3D slices aren't separate subresources, so they shouldn't be transitioned 1036 // during each subpass like array layers. 1037 if (caseDef.viewType == VK_IMAGE_VIEW_TYPE_3D) 1038 { 1039 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1040 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1041 1042 beginCommandBuffer(vk, *cmdBuffer); 1043 1044 const VkImageMemoryBarrier imageBarrier = 1045 { 1046 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1047 DE_NULL, // const void* pNext; 1048 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 1049 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 1050 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1051 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 1052 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1053 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1054 *colorImage, // VkImage image; 1055 { // VkImageSubresourceRange subresourceRange; 1056 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1057 0u, // uint32_t baseMipLevel; 1058 1u, // uint32_t levelCount; 1059 0u, // uint32_t baseArrayLayer; 1060 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount; 1061 } 1062 }; 1063 1064 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 1065 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier); 1066 1067 endCommandBuffer(vk, *cmdBuffer); 1068 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1069 } 1070 1071 // For each image layer or slice (3D), create an attachment and a pipeline 1072 { 1073 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat); 1074 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; 1075 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; 1076 VkPipeline basePipeline = DE_NULL; 1077 1078 // Color attachments are first in the framebuffer 1079 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx) 1080 { 1081 colorAttachments.push_back(makeSharedPtr( 1082 makeImageView(vk, device, *colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, makeColorSubresourceRange(subpassNdx, 1)))); 1083 attachmentHandles.push_back(**colorAttachments.back()); 1084 1085 // We also have to create pipelines for each subpass 1086 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline( 1087 vk, device, basePipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, imageSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1088 static_cast<deUint32>(subpassNdx), useDepth, useStencil))); 1089 1090 basePipeline = **pipelines.front(); 1091 } 1092 1093 // Then D/S attachments, if any 1094 if (useDepthStencil) 1095 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx) 1096 { 1097 depthStencilAttachments.push_back(makeSharedPtr( 1098 makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, makeImageSubresourceRange(depthStencilAspect, 0u, 1u, subpassNdx, 1u)))); 1099 attachmentHandles.push_back(**depthStencilAttachments.back()); 1100 } 1101 } 1102 1103 framebuffer = makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], static_cast<deUint32>(imageSize.x()), static_cast<deUint32>(imageSize.y())); 1104 1105 { 1106 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1107 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1108 1109 beginCommandBuffer(vk, *cmdBuffer); 1110 { 1111 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat)); 1112 1113 if (useDepthStencil) 1114 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE)); 1115 1116 const VkDeviceSize vertexBufferOffset = 0ull; 1117 1118 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageSize.x(), imageSize.y()), (deUint32)clearValues.size(), &clearValues[0]); 1119 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 1120 } 1121 1122 // Draw 1123 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx) 1124 { 1125 if (subpassNdx != 0) 1126 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 1127 1128 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]); 1129 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u); 1130 } 1131 1132 endRenderPass(vk, *cmdBuffer); 1133 1134 // Copy colorImage -> host visible colorBuffer 1135 { 1136 const VkImageMemoryBarrier imageBarriers[] = 1137 { 1138 { 1139 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1140 DE_NULL, // const void* pNext; 1141 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 1142 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 1143 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1144 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1145 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1146 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1147 *colorImage, // VkImage image; 1148 makeColorSubresourceRange(0, imageSize.w()) // VkImageSubresourceRange subresourceRange; 1149 } 1150 }; 1151 1152 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1153 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); 1154 1155 // Copy the checked region rather than the whole image 1156 const VkImageSubresourceLayers subresource = 1157 { 1158 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1159 0u, // uint32_t mipLevel; 1160 static_cast<deUint32>(checkOffset.w()), // uint32_t baseArrayLayer; 1161 static_cast<deUint32>(checkSize.w()), // uint32_t layerCount; 1162 }; 1163 1164 const VkBufferImageCopy region = 1165 { 1166 0ull, // VkDeviceSize bufferOffset; 1167 0u, // uint32_t bufferRowLength; 1168 0u, // uint32_t bufferImageHeight; 1169 subresource, // VkImageSubresourceLayers imageSubresource; 1170 makeOffset3D(checkOffset.x(), checkOffset.y(), checkOffset.z()), // VkOffset3D imageOffset; 1171 makeExtent3D(checkSize.swizzle(0, 1, 2)), // VkExtent3D imageExtent; 1172 }; 1173 1174 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 1175 1176 const VkBufferMemoryBarrier bufferBarriers[] = 1177 { 1178 { 1179 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1180 DE_NULL, // const void* pNext; 1181 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1182 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1183 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1184 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1185 *colorBuffer, // VkBuffer buffer; 1186 0ull, // VkDeviceSize offset; 1187 VK_WHOLE_SIZE, // VkDeviceSize size; 1188 }, 1189 }; 1190 1191 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1192 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 1193 } 1194 1195 endCommandBuffer(vk, *cmdBuffer); 1196 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1197 } 1198 1199 // Verify results 1200 { 1201 invalidateAlloc(vk, device, *colorBufferAlloc); 1202 1203 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat); 1204 const int checkDepth = maxLayersOrDepth(checkSize); 1205 const int depthOffset = maxLayersOrDepth(checkOffset); 1206 const tcu::ConstPixelBufferAccess resultImage (format, checkSize.x(), checkSize.y(), checkDepth, colorBufferAlloc->getHostPtr()); 1207 tcu::TextureLevel textureLevel (format, checkSize.x(), checkSize.y(), checkDepth); 1208 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess(); 1209 bool ok = false; 1210 1211 generateExpectedImage(expectedImage, checkSize.swizzle(0, 1), depthOffset); 1212 1213 if (isFloatFormat(caseDef.colorFormat)) 1214 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT); 1215 else 1216 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT); 1217 1218 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail"); 1219 } 1220 } 1221 1222 void checkImageViewTypeRequirements (Context& context, const VkImageViewType viewType) 1223 { 1224 if (viewType == VK_IMAGE_VIEW_TYPE_3D && 1225 (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1"))) 1226 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported"); 1227 1228 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray) 1229 TCU_THROW(NotSupportedError, "Missing feature: imageCubeArray"); 1230 } 1231 1232 //! A test that can exercise very big color and depth/stencil attachment sizes. 1233 //! If the total memory consumed by images is too large, or if the implementation returns OUT_OF_MEMORY error somewhere, 1234 //! the test can be retried with a next increment of size reduction index, making the attachments smaller. 1235 tcu::TestStatus testAttachmentSize (Context& context, const CaseDef caseDef) 1236 { 1237 checkImageViewTypeRequirements(context, caseDef.viewType); 1238 1239 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED) 1240 { 1241 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_dedicated_allocation")) 1242 TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported"); 1243 } 1244 1245 return testWithSizeReduction(context, caseDef); 1246 // Never reached 1247 } 1248 1249 vector<IVec4> getMipLevelSizes (IVec4 baseSize) 1250 { 1251 vector<IVec4> levels; 1252 levels.push_back(baseSize); 1253 1254 while (baseSize.x() != 1 || baseSize.y() != 1 || baseSize.z() != 1) 1255 { 1256 baseSize.x() = deMax32(baseSize.x() >> 1, 1); 1257 baseSize.y() = deMax32(baseSize.y() >> 1, 1); 1258 baseSize.z() = deMax32(baseSize.z() >> 1, 1); 1259 levels.push_back(baseSize); 1260 } 1261 1262 return levels; 1263 } 1264 1265 //! Compute memory consumed by each mip level, including all layers. Sizes include a padding for alignment. 1266 vector<VkDeviceSize> getPerMipLevelStorageSize (const vector<IVec4>& mipLevelSizes, const VkDeviceSize pixelSize) 1267 { 1268 const deInt64 levelAlignment = 16; 1269 vector<VkDeviceSize> storageSizes; 1270 1271 for (vector<IVec4>::const_iterator it = mipLevelSizes.begin(); it != mipLevelSizes.end(); ++it) 1272 storageSizes.push_back(deAlign64(pixelSize * product(*it), levelAlignment)); 1273 1274 return storageSizes; 1275 } 1276 1277 void drawToMipLevel (const Context& context, 1278 const CaseDef& caseDef, 1279 const int mipLevel, 1280 const IVec4& mipSize, 1281 const int numSlices, 1282 const VkImage colorImage, 1283 const VkImage depthStencilImage, 1284 const VkBuffer vertexBuffer, 1285 const VkPipelineLayout pipelineLayout, 1286 const VkShaderModule vertexModule, 1287 const VkShaderModule fragmentModule) 1288 { 1289 const DeviceInterface& vk = context.getDeviceInterface(); 1290 const VkDevice device = context.getDevice(); 1291 const VkQueue queue = context.getUniversalQueue(); 1292 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1293 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat); 1294 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; 1295 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; 1296 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices), 1297 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1298 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); 1299 vector<SharedPtrVkPipeline> pipelines; 1300 vector<SharedPtrVkImageView> colorAttachments; 1301 vector<SharedPtrVkImageView> depthStencilAttachments; 1302 vector<VkImageView> attachmentHandles; // all attachments (color and d/s) 1303 1304 // For each image layer or slice (3D), create an attachment and a pipeline 1305 { 1306 VkPipeline basePipeline = DE_NULL; 1307 1308 // Color attachments are first in the framebuffer 1309 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx) 1310 { 1311 colorAttachments.push_back(makeSharedPtr(makeImageView( 1312 vk, device, colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, 1313 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, subpassNdx, 1u)))); 1314 attachmentHandles.push_back(**colorAttachments.back()); 1315 1316 // We also have to create pipelines for each subpass 1317 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline( 1318 vk, device, basePipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, mipSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1319 static_cast<deUint32>(subpassNdx), useDepth, useStencil))); 1320 1321 basePipeline = **pipelines.front(); 1322 } 1323 1324 // Then D/S attachments, if any 1325 if (useDepth || useStencil) 1326 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx) 1327 { 1328 depthStencilAttachments.push_back(makeSharedPtr(makeImageView( 1329 vk, device, depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, 1330 makeImageSubresourceRange(depthStencilAspect, mipLevel, 1u, subpassNdx, 1u)))); 1331 attachmentHandles.push_back(**depthStencilAttachments.back()); 1332 } 1333 } 1334 1335 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], 1336 static_cast<deUint32>(mipSize.x()), static_cast<deUint32>(mipSize.y()))); 1337 1338 { 1339 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1340 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1341 1342 beginCommandBuffer(vk, *cmdBuffer); 1343 { 1344 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat)); 1345 1346 if (useDepth || useStencil) 1347 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE)); 1348 1349 const VkDeviceSize vertexBufferOffset = 0ull; 1350 1351 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, mipSize.x(), mipSize.y()), (deUint32)clearValues.size(), &clearValues[0]); 1352 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset); 1353 } 1354 1355 // Draw 1356 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx) 1357 { 1358 if (subpassNdx != 0) 1359 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 1360 1361 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]); 1362 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u); 1363 } 1364 1365 endRenderPass(vk, *cmdBuffer); 1366 1367 endCommandBuffer(vk, *cmdBuffer); 1368 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1369 } 1370 } 1371 1372 //! Use image mip levels as attachments 1373 tcu::TestStatus testRenderToMipMaps (Context& context, const CaseDef caseDef) 1374 { 1375 checkImageViewTypeRequirements(context, caseDef.viewType); 1376 1377 const DeviceInterface& vk = context.getDeviceInterface(); 1378 const InstanceInterface& vki = context.getInstanceInterface(); 1379 const VkDevice device = context.getDevice(); 1380 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 1381 const VkQueue queue = context.getUniversalQueue(); 1382 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1383 Allocator& allocator = context.getDefaultAllocator(); 1384 1385 const IVec4 imageSize = caseDef.imageSizeHint; // MAX_SIZE is not used in this test 1386 const deInt32 numSlices = maxLayersOrDepth(imageSize); 1387 const vector<IVec4> mipLevelSizes = getMipLevelSizes(imageSize); 1388 const vector<VkDeviceSize> mipLevelStorageSizes = getPerMipLevelStorageSize(mipLevelSizes, tcu::getPixelSize(mapVkFormat(caseDef.colorFormat))); 1389 const int numMipLevels = static_cast<int>(mipLevelSizes.size()); 1390 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED); 1391 1392 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED) 1393 { 1394 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_dedicated_allocation")) 1395 TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported"); 1396 } 1397 1398 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat)) 1399 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format"); 1400 1401 // Create a color buffer big enough to hold all layers and mip levels 1402 const VkDeviceSize colorBufferSize = sum(mipLevelStorageSizes); 1403 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 1404 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vki, vk, physDevice, device, *colorBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind)); 1405 1406 { 1407 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 1408 flushAlloc(vk, device, *colorBufferAlloc); 1409 } 1410 1411 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 1412 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 1413 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 1414 1415 Move<VkImage> colorImage; 1416 MovePtr<Allocation> colorImageAlloc; 1417 Move<VkImage> depthStencilImage; 1418 MovePtr<Allocation> depthStencilImageAlloc; 1419 Move<VkBuffer> vertexBuffer; 1420 MovePtr<Allocation> vertexBufferAlloc; 1421 1422 // Create a color image 1423 { 1424 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 1425 1426 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat, 1427 imageSize.swizzle(0, 1, 2), numMipLevels, imageSize.w(), imageUsage); 1428 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind); 1429 } 1430 1431 // Create a depth/stencil image (always a 2D image, optionally layered) 1432 if (useDepthStencil) 1433 { 1434 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 1435 1436 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat, 1437 IVec3(imageSize.x(), imageSize.y(), 1), numMipLevels, numSlices, imageUsage); 1438 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind); 1439 } 1440 1441 // Create a vertex buffer 1442 { 1443 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices); 1444 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 1445 1446 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1447 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind); 1448 1449 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 1450 flushAlloc(vk, device, *vertexBufferAlloc); 1451 } 1452 1453 // Prepare images 1454 { 1455 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1456 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1457 1458 beginCommandBuffer(vk, *cmdBuffer); 1459 1460 const VkImageMemoryBarrier imageBarriers[] = 1461 { 1462 { 1463 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1464 DE_NULL, // const void* pNext; 1465 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 1466 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 1467 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1468 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 1469 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1470 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1471 *colorImage, // VkImage image; 1472 { // VkImageSubresourceRange subresourceRange; 1473 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1474 0u, // uint32_t baseMipLevel; 1475 static_cast<deUint32>(numMipLevels), // uint32_t levelCount; 1476 0u, // uint32_t baseArrayLayer; 1477 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount; 1478 }, 1479 }, 1480 { 1481 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1482 DE_NULL, // const void* pNext; 1483 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 1484 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 1485 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1486 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 1487 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1488 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1489 *depthStencilImage, // VkImage image; 1490 { // VkImageSubresourceRange subresourceRange; 1491 getFormatAspectFlags(caseDef.depthStencilFormat), // VkImageAspectFlags aspectMask; 1492 0u, // uint32_t baseMipLevel; 1493 static_cast<deUint32>(numMipLevels), // uint32_t levelCount; 1494 0u, // uint32_t baseArrayLayer; 1495 static_cast<deUint32>(numSlices), // uint32_t layerCount; 1496 }, 1497 } 1498 }; 1499 1500 const deUint32 numImageBarriers = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(imageBarriers) - (useDepthStencil ? 0 : 1)); 1501 1502 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 1503 0u, DE_NULL, 0u, DE_NULL, numImageBarriers, imageBarriers); 1504 1505 endCommandBuffer(vk, *cmdBuffer); 1506 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1507 } 1508 1509 // Draw 1510 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel) 1511 { 1512 const IVec4& mipSize = mipLevelSizes[mipLevel]; 1513 const int levelSlices = maxLayersOrDepth(mipSize); 1514 1515 drawToMipLevel (context, caseDef, mipLevel, mipSize, levelSlices, *colorImage, *depthStencilImage, *vertexBuffer, *pipelineLayout, 1516 *vertexModule, *fragmentModule); 1517 } 1518 1519 // Copy results: colorImage -> host visible colorBuffer 1520 { 1521 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1522 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1523 1524 beginCommandBuffer(vk, *cmdBuffer); 1525 1526 { 1527 const VkImageMemoryBarrier imageBarriers[] = 1528 { 1529 { 1530 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1531 DE_NULL, // const void* pNext; 1532 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 1533 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 1534 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1535 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1536 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1537 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1538 *colorImage, // VkImage image; 1539 { // VkImageSubresourceRange subresourceRange; 1540 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1541 0u, // uint32_t baseMipLevel; 1542 static_cast<deUint32>(numMipLevels), // uint32_t levelCount; 1543 0u, // uint32_t baseArrayLayer; 1544 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount; 1545 }, 1546 } 1547 }; 1548 1549 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1550 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); 1551 } 1552 { 1553 vector<VkBufferImageCopy> regions; 1554 VkDeviceSize levelOffset = 0ull; 1555 VkBufferImageCopy workRegion = 1556 { 1557 0ull, // VkDeviceSize bufferOffset; 1558 0u, // uint32_t bufferRowLength; 1559 0u, // uint32_t bufferImageHeight; 1560 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageSize.w()), // VkImageSubresourceLayers imageSubresource; 1561 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1562 makeExtent3D(0, 0, 0), // VkExtent3D imageExtent; 1563 }; 1564 1565 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel) 1566 { 1567 workRegion.bufferOffset = levelOffset; 1568 workRegion.imageSubresource.mipLevel = static_cast<deUint32>(mipLevel); 1569 workRegion.imageExtent = makeExtent3D(mipLevelSizes[mipLevel].swizzle(0, 1, 2)); 1570 1571 regions.push_back(workRegion); 1572 1573 levelOffset += mipLevelStorageSizes[mipLevel]; 1574 } 1575 1576 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, static_cast<deUint32>(regions.size()), ®ions[0]); 1577 } 1578 { 1579 const VkBufferMemoryBarrier bufferBarriers[] = 1580 { 1581 { 1582 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1583 DE_NULL, // const void* pNext; 1584 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1585 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1586 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1587 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1588 *colorBuffer, // VkBuffer buffer; 1589 0ull, // VkDeviceSize offset; 1590 VK_WHOLE_SIZE, // VkDeviceSize size; 1591 }, 1592 }; 1593 1594 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1595 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 1596 } 1597 1598 endCommandBuffer(vk, *cmdBuffer); 1599 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1600 } 1601 1602 // Verify results (per mip level) 1603 { 1604 invalidateAlloc(vk, device, *colorBufferAlloc); 1605 1606 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat); 1607 1608 VkDeviceSize levelOffset = 0ull; 1609 bool allOk = true; 1610 1611 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel) 1612 { 1613 const IVec4& mipSize = mipLevelSizes[mipLevel]; 1614 const void* const pLevelData = static_cast<const deUint8*>(colorBufferAlloc->getHostPtr()) + levelOffset; 1615 const int levelDepth = maxLayersOrDepth(mipSize); 1616 const tcu::ConstPixelBufferAccess resultImage (format, mipSize.x(), mipSize.y(), levelDepth, pLevelData); 1617 tcu::TextureLevel textureLevel (format, mipSize.x(), mipSize.y(), levelDepth); 1618 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess(); 1619 const std::string comparisonName = "Mip level " + de::toString(mipLevel); 1620 bool ok = false; 1621 1622 generateExpectedImage(expectedImage, mipSize.swizzle(0, 1), 0); 1623 1624 if (isFloatFormat(caseDef.colorFormat)) 1625 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT); 1626 else 1627 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT); 1628 1629 allOk = allOk && ok; // keep testing all levels, even if we know it's a fail overall 1630 levelOffset += mipLevelStorageSizes[mipLevel]; 1631 } 1632 1633 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail"); 1634 } 1635 } 1636 1637 std::string getSizeDescription (const IVec4& size) 1638 { 1639 std::ostringstream str; 1640 1641 const char* const description[4] = 1642 { 1643 "width", "height", "depth", "layers" 1644 }; 1645 1646 int numMaxComponents = 0; 1647 1648 for (int i = 0; i < 4; ++i) 1649 { 1650 if (size[i] == MAX_SIZE) 1651 { 1652 if (numMaxComponents > 0) 1653 str << "_"; 1654 1655 str << description[i]; 1656 ++numMaxComponents; 1657 } 1658 } 1659 1660 if (numMaxComponents == 0) 1661 str << "small"; 1662 1663 return str.str(); 1664 } 1665 1666 inline std::string getFormatString (const VkFormat format) 1667 { 1668 std::string name(getFormatName(format)); 1669 return de::toLower(name.substr(10)); 1670 } 1671 1672 std::string getFormatString (const VkFormat colorFormat, const VkFormat depthStencilFormat) 1673 { 1674 std::ostringstream str; 1675 str << getFormatString(colorFormat); 1676 if (depthStencilFormat != VK_FORMAT_UNDEFINED) 1677 str << "_" << getFormatString(depthStencilFormat); 1678 return str.str(); 1679 } 1680 1681 std::string getShortImageViewTypeName (const VkImageViewType imageViewType) 1682 { 1683 std::string s(getImageViewTypeName(imageViewType)); 1684 return de::toLower(s.substr(19)); 1685 } 1686 1687 inline BVec4 bvecFromMask (deUint32 mask) 1688 { 1689 return BVec4((mask >> 0) & 1, 1690 (mask >> 1) & 1, 1691 (mask >> 2) & 1, 1692 (mask >> 3) & 1); 1693 } 1694 1695 vector<IVec4> genSizeCombinations (const IVec4& baselineSize, const deUint32 sizeMask, const VkImageViewType imageViewType) 1696 { 1697 vector<IVec4> sizes; 1698 std::set<deUint32> masks; 1699 1700 for (deUint32 i = 0; i < (1u << 4); ++i) 1701 { 1702 // Cube images have square faces 1703 if (isCube(imageViewType) && ((i & MASK_WH) != 0)) 1704 i |= MASK_WH; 1705 1706 masks.insert(i & sizeMask); 1707 } 1708 1709 for (std::set<deUint32>::const_iterator it = masks.begin(); it != masks.end(); ++it) 1710 sizes.push_back(tcu::select(IVec4(MAX_SIZE), baselineSize, bvecFromMask(*it))); 1711 1712 return sizes; 1713 } 1714 1715 void addTestCasesWithFunctions (tcu::TestCaseGroup* group, AllocationKind allocationKind) 1716 { 1717 const struct 1718 { 1719 VkImageViewType viewType; 1720 IVec4 baselineSize; //!< image size: (dimX, dimY, dimZ, arraySize) 1721 deUint32 sizeMask; //!< if a dimension is masked, generate a huge size case for it 1722 } testCase[] = 1723 { 1724 { VK_IMAGE_VIEW_TYPE_1D, IVec4(54, 1, 1, 1), MASK_W }, 1725 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec4(54, 1, 1, 4), MASK_W_LAYERS }, 1726 { VK_IMAGE_VIEW_TYPE_2D, IVec4(44, 23, 1, 1), MASK_WH }, 1727 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec4(44, 23, 1, 4), MASK_WH_LAYERS }, 1728 { VK_IMAGE_VIEW_TYPE_3D, IVec4(22, 31, 7, 1), MASK_WHD }, 1729 { VK_IMAGE_VIEW_TYPE_CUBE, IVec4(35, 35, 1, 6), MASK_WH }, 1730 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec4(35, 35, 1, 2*6), MASK_WH_LAYERS }, 1731 }; 1732 1733 const VkFormat format[] = 1734 { 1735 VK_FORMAT_R8G8B8A8_UNORM, 1736 VK_FORMAT_R32_UINT, 1737 VK_FORMAT_R16G16_SINT, 1738 VK_FORMAT_R32G32B32A32_SFLOAT, 1739 }; 1740 1741 const VkFormat depthStencilFormat[] = 1742 { 1743 VK_FORMAT_UNDEFINED, // don't use a depth/stencil attachment 1744 VK_FORMAT_D16_UNORM, 1745 VK_FORMAT_S8_UINT, 1746 VK_FORMAT_D24_UNORM_S8_UINT, // one of the following mixed formats must be supported 1747 VK_FORMAT_D32_SFLOAT_S8_UINT, 1748 }; 1749 1750 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCase); ++caseNdx) 1751 { 1752 MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(testCase[caseNdx].viewType).c_str(), "")); 1753 1754 // Generate attachment size cases 1755 { 1756 const vector<IVec4> sizes = genSizeCombinations(testCase[caseNdx].baselineSize, testCase[caseNdx].sizeMask, testCase[caseNdx].viewType); 1757 1758 MovePtr<tcu::TestCaseGroup> smallGroup(new tcu::TestCaseGroup(group->getTestContext(), "small", "")); 1759 MovePtr<tcu::TestCaseGroup> hugeGroup (new tcu::TestCaseGroup(group->getTestContext(), "huge", "")); 1760 1761 imageGroup->addChild(smallGroup.get()); 1762 imageGroup->addChild(hugeGroup.get()); 1763 1764 for (vector<IVec4>::const_iterator sizeIter = sizes.begin(); sizeIter != sizes.end(); ++sizeIter) 1765 { 1766 // The first size is the baseline size, put it in a dedicated group 1767 if (sizeIter == sizes.begin()) 1768 { 1769 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx) 1770 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx) 1771 { 1772 const CaseDef caseDef = 1773 { 1774 testCase[caseNdx].viewType, // VkImageViewType imageType; 1775 *sizeIter, // IVec4 imageSizeHint; 1776 format[formatNdx], // VkFormat colorFormat; 1777 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat; 1778 allocationKind // AllocationKind allocationKind; 1779 }; 1780 addFunctionCaseWithPrograms(smallGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef); 1781 } 1782 } 1783 else // All huge cases go into a separate group 1784 { 1785 if (allocationKind != ALLOCATION_KIND_DEDICATED) 1786 { 1787 MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(group->getTestContext(), getSizeDescription(*sizeIter).c_str(), "")); 1788 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 1789 1790 // Use the same color format for all cases, to reduce the number of permutations 1791 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx) 1792 { 1793 const CaseDef caseDef = 1794 { 1795 testCase[caseNdx].viewType, // VkImageViewType viewType; 1796 *sizeIter, // IVec4 imageSizeHint; 1797 colorFormat, // VkFormat colorFormat; 1798 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat; 1799 allocationKind // AllocationKind allocationKind; 1800 }; 1801 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(colorFormat, depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef); 1802 } 1803 hugeGroup->addChild(sizeGroup.release()); 1804 } 1805 } 1806 } 1807 smallGroup.release(); 1808 hugeGroup.release(); 1809 } 1810 1811 // Generate mip map cases 1812 { 1813 MovePtr<tcu::TestCaseGroup> mipmapGroup(new tcu::TestCaseGroup(group->getTestContext(), "mipmap", "")); 1814 1815 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx) 1816 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx) 1817 { 1818 const CaseDef caseDef = 1819 { 1820 testCase[caseNdx].viewType, // VkImageViewType imageType; 1821 testCase[caseNdx].baselineSize, // IVec4 imageSizeHint; 1822 format[formatNdx], // VkFormat colorFormat; 1823 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat; 1824 allocationKind // AllocationKind allocationKind; 1825 }; 1826 addFunctionCaseWithPrograms(mipmapGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testRenderToMipMaps, caseDef); 1827 } 1828 imageGroup->addChild(mipmapGroup.release()); 1829 } 1830 1831 group->addChild(imageGroup.release()); 1832 } 1833 } 1834 1835 void addCoreRenderToImageTests (tcu::TestCaseGroup* group) 1836 { 1837 addTestCasesWithFunctions(group, ALLOCATION_KIND_SUBALLOCATED); 1838 } 1839 1840 void addDedicatedAllocationRenderToImageTests (tcu::TestCaseGroup* group) 1841 { 1842 addTestCasesWithFunctions(group, ALLOCATION_KIND_DEDICATED); 1843 } 1844 1845 } // anonymous ns 1846 1847 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx) 1848 { 1849 de::MovePtr<tcu::TestCaseGroup> renderToImageTests (new tcu::TestCaseGroup(testCtx, "render_to_image", "Render to image tests")); 1850 1851 renderToImageTests->addChild(createTestGroup(testCtx, "core", "Core render to image tests", addCoreRenderToImageTests)); 1852 renderToImageTests->addChild(createTestGroup(testCtx, "dedicated_allocation", "Render to image tests for dedicated memory allocation", addDedicatedAllocationRenderToImageTests)); 1853 1854 return renderToImageTests.release(); 1855 } 1856 1857 } // pipeline 1858 } // vkt 1859