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