1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Samsung Electronics Co., Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Vulkan Get Render Area Granularity Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktApiGranularityTests.hpp" 26 27 #include "deRandom.hpp" 28 #include "deSharedPtr.hpp" 29 #include "deStringUtil.hpp" 30 #include "deUniquePtr.hpp" 31 32 #include "vkImageUtil.hpp" 33 #include "vkMemUtil.hpp" 34 #include "vkQueryUtil.hpp" 35 #include "vkRefUtil.hpp" 36 #include "vktTestCase.hpp" 37 38 #include "tcuTestLog.hpp" 39 #include "tcuTextureUtil.hpp" 40 41 #include <string> 42 43 namespace vkt 44 { 45 46 namespace api 47 { 48 49 using namespace vk; 50 51 namespace 52 { 53 54 struct AttachmentInfo 55 { 56 AttachmentInfo (const VkFormat vkFormat, 57 const deUint32 width, 58 const deUint32 height, 59 const deUint32 depth) 60 : format (vkFormat) 61 { 62 extent.width = width; 63 extent.height = height; 64 extent.depth = depth; 65 } 66 67 ~AttachmentInfo (void) 68 {} 69 70 VkFormat format; 71 VkExtent3D extent; 72 }; 73 74 typedef de::SharedPtr<Allocation> AllocationSp; 75 typedef de::SharedPtr<Unique<VkImage> > VkImageSp; 76 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp; 77 78 class GranularityInstance : public vkt::TestInstance 79 { 80 public: 81 GranularityInstance (Context& context, 82 const std::vector<AttachmentInfo>& attachments, 83 const bool useRenderPass); 84 virtual ~GranularityInstance (void); 85 void checkFormatSupport (const VkFormat format); 86 void initAttachmentDescriptions (void); 87 void initImages (void); 88 void initRenderPass (void); 89 void beginRenderPass (void); 90 void endRenderPass (void); 91 virtual tcu::TestStatus iterate (void); 92 private: 93 const std::vector<AttachmentInfo> m_attachments; 94 const bool m_useRenderPass; 95 96 Move<VkRenderPass> m_renderPass; 97 Move<VkFramebuffer> m_frameBuffer; 98 Move<VkCommandPool> m_cmdPool; 99 Move<VkCommandBuffer> m_cmdBuffer; 100 std::vector<VkAttachmentDescription> m_attachmentDescriptions; 101 std::vector<VkImageSp> m_images; 102 std::vector<AllocationSp> m_imageAllocs; 103 std::vector<VkImageViewSp> m_imageViews; 104 }; 105 106 GranularityInstance::GranularityInstance (Context& context, 107 const std::vector<AttachmentInfo>& attachments, 108 const bool useRenderPass) 109 : vkt::TestInstance (context) 110 , m_attachments (attachments) 111 , m_useRenderPass (useRenderPass) 112 { 113 initAttachmentDescriptions(); 114 } 115 116 GranularityInstance::~GranularityInstance (void) 117 { 118 } 119 120 void GranularityInstance::checkFormatSupport (const VkFormat format) 121 { 122 VkImageFormatProperties properties; 123 124 VkResult result = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(), 125 format, VK_IMAGE_TYPE_2D, 126 VK_IMAGE_TILING_OPTIMAL, 127 VK_IMAGE_USAGE_SAMPLED_BIT, 128 0, 129 &properties); 130 131 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) 132 TCU_THROW(NotSupportedError, "Format not supported"); 133 } 134 135 void GranularityInstance::initAttachmentDescriptions (void) 136 { 137 VkAttachmentDescription attachmentDescription = 138 { 139 0u, // VkAttachmentDescriptionFlags flags; 140 VK_FORMAT_UNDEFINED, // VkFormat format; 141 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 142 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; 143 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; 144 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 145 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 146 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 147 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout finalLayout; 148 }; 149 150 for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) 151 { 152 checkFormatSupport(it->format); 153 attachmentDescription.format = it->format; 154 m_attachmentDescriptions.push_back(attachmentDescription); 155 } 156 } 157 158 void GranularityInstance::initImages (void) 159 { 160 const DeviceInterface& vk = m_context.getDeviceInterface(); 161 const VkDevice device = m_context.getDevice(); 162 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 163 SimpleAllocator memAlloc (vk, device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 164 165 for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) 166 { 167 const VkImageCreateInfo imageInfo = 168 { 169 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 170 DE_NULL, // const void* pNext; 171 0u, // VkImageCreateFlags flags; 172 VK_IMAGE_TYPE_2D, // VkImageType imageType; 173 it->format, // VkFormat format; 174 it->extent, // VkExtent3D extent; 175 1u, // deUint32 mipLevels; 176 1u, // deUint32 arrayLayers; 177 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; 178 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 179 VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage; 180 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 181 1u, // deUint32 queueFamilyCount; 182 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 183 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 184 }; 185 186 // Create the image 187 Move<VkImage> image = createImage(vk, device, &imageInfo); 188 de::MovePtr<Allocation> imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any); 189 VK_CHECK(vk.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset())); 190 191 VkImageAspectFlags aspectFlags = 0; 192 const tcu::TextureFormat tcuFormat = mapVkFormat(it->format); 193 194 if (tcu::hasDepthComponent(tcuFormat.order)) 195 aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT; 196 197 if (tcu::hasStencilComponent(tcuFormat.order)) 198 aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; 199 200 if (!aspectFlags) 201 aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; 202 203 VkFormatProperties formatProperties; 204 m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), 205 it->format, &formatProperties); 206 207 if ((formatProperties.optimalTilingFeatures & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | 208 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) == 0) 209 throw tcu::NotSupportedError("Format not supported as attachment"); 210 211 const VkImageViewCreateInfo createInfo = 212 { 213 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 214 DE_NULL, // const void* pNext; 215 0, // VkImageViewCreateFlags flags; 216 *image, // VkImage image; 217 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 218 it->format, // VkFormat format; 219 { 220 VK_COMPONENT_SWIZZLE_R, 221 VK_COMPONENT_SWIZZLE_G, 222 VK_COMPONENT_SWIZZLE_B, 223 VK_COMPONENT_SWIZZLE_A 224 }, // VkComponentMapping components; 225 { aspectFlags, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 226 }; 227 228 // Create the Image View 229 Move<VkImageView> imageView = createImageView(vk, device, &createInfo); 230 231 // To prevent object free 232 m_images.push_back(VkImageSp(new Unique<VkImage>(image))); 233 m_imageAllocs.push_back(AllocationSp(imageAlloc.release())); 234 m_imageViews.push_back(VkImageViewSp(new Unique<VkImageView>(imageView))); 235 } 236 } 237 238 void GranularityInstance::initRenderPass (void) 239 { 240 const DeviceInterface& vk = m_context.getDeviceInterface(); 241 const VkDevice device = m_context.getDevice(); 242 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 243 244 { // Create RenderPass 245 const VkSubpassDescription subpassDesc = 246 { 247 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; 248 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 249 0u, // deUint32 inputCount; 250 DE_NULL, // const VkAttachmentReference* pInputAttachments; 251 0u, // deUint32 colorCount; 252 DE_NULL, // const VkAttachmentReference* pColorAttachments; 253 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 254 DE_NULL, // VkAttachmentReference depthStencilAttachment; 255 0u, // deUint32 preserveCount; 256 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 257 }; 258 259 const VkRenderPassCreateInfo renderPassParams = 260 { 261 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 262 DE_NULL, // const void* pNext; 263 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 264 (deUint32)m_attachmentDescriptions.size(), // deUint32 attachmentCount; 265 &m_attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 266 1u, // deUint32 subpassCount; 267 &subpassDesc, // const VkSubpassDescription* pSubpasses; 268 0u, // deUint32 dependencyCount; 269 DE_NULL // const VkSubpassDependency* pDependencies; 270 }; 271 272 m_renderPass = createRenderPass(vk, device, &renderPassParams); 273 } 274 275 initImages(); 276 277 { // Create Framebuffer 278 std::vector<VkImageView> imageViews; 279 280 for (std::vector<VkImageViewSp>::const_iterator it = m_imageViews.begin(); it != m_imageViews.end(); ++it) 281 imageViews.push_back(it->get()->get()); 282 283 const VkFramebufferCreateInfo framebufferParams = 284 { 285 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 286 DE_NULL, // const void* pNext; 287 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 288 *m_renderPass, // VkRenderPass renderPass; 289 (deUint32)imageViews.size(), // deUint32 attachmentCount; 290 &imageViews[0], // const VkImageView* pAttachments; 291 1, // deUint32 width; 292 1, // deUint32 height; 293 1 // deUint32 layers; 294 }; 295 296 m_frameBuffer = createFramebuffer(vk, device, &framebufferParams); 297 } 298 299 { // Create CommandPool 300 const VkCommandPoolCreateInfo cmdPoolParams = 301 { 302 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 303 DE_NULL, // const void* pNext; 304 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags; 305 queueFamilyIndex, // deUint32 queueFamilyIndex; 306 }; 307 308 m_cmdPool = createCommandPool(vk, device, &cmdPoolParams); 309 } 310 311 { // Create CommandBuffer 312 const VkCommandBufferAllocateInfo bufferAllocInfo = 313 { 314 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 315 DE_NULL, // const void* pNext; 316 *m_cmdPool, // VkCmdPool cmdPool; 317 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level; 318 1u // deUint32 count; 319 }; 320 321 m_cmdBuffer = allocateCommandBuffer(vk, device, &bufferAllocInfo); 322 } 323 324 { // Begin CommandBuffer 325 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 326 { 327 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 328 DE_NULL, // const void* pNext; 329 0u, // VkCmdBufferOptimizeFlags flags; 330 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; 331 }; 332 333 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); 334 } 335 } 336 337 void GranularityInstance::beginRenderPass (void) 338 { 339 const DeviceInterface& vk = m_context.getDeviceInterface(); 340 341 const VkRect2D renderArea = 342 { 343 { 0, 0 }, // VkOffset2D offset; 344 { 1, 1 } // VkExtent2D extent; 345 }; 346 347 const VkRenderPassBeginInfo renderPassBeginInfo = 348 { 349 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 350 DE_NULL, // const void* pNext; 351 *m_renderPass, // VkRenderPass renderPass; 352 *m_frameBuffer, // VkFramebuffer framebuffer; 353 renderArea, // VkRect2D renderArea; 354 0u, // uint32_t clearValueCount; 355 DE_NULL // const VkClearValue* pClearValues; 356 }; 357 358 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 359 } 360 361 void GranularityInstance::endRenderPass (void) 362 { 363 const DeviceInterface& vk = m_context.getDeviceInterface(); 364 365 vk.cmdEndRenderPass(*m_cmdBuffer); 366 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 367 } 368 369 tcu::TestStatus GranularityInstance::iterate (void) 370 { 371 const DeviceInterface& vk = m_context.getDeviceInterface(); 372 const VkDevice device = m_context.getDevice(); 373 tcu::TestLog& log = m_context.getTestContext().getLog(); 374 375 initRenderPass(); 376 377 VkExtent2D prePassGranularity = { ~0u, ~0u }; 378 vk.getRenderAreaGranularity(device, *m_renderPass, &prePassGranularity); 379 380 if(m_useRenderPass) 381 beginRenderPass(); 382 383 VkExtent2D granularity = { 0u, 0u }; 384 vk.getRenderAreaGranularity(device, *m_renderPass, &granularity); 385 TCU_CHECK(granularity.width >= 1 && granularity.height >= 1); 386 TCU_CHECK(prePassGranularity.width == granularity.width && prePassGranularity.height == granularity.height); 387 TCU_CHECK(granularity.width <= m_context.getDeviceProperties().limits.maxFramebufferWidth && granularity.height <= m_context.getDeviceProperties().limits.maxFramebufferHeight); 388 389 if(m_useRenderPass) 390 endRenderPass(); 391 392 log << tcu::TestLog::Message << "Horizontal granularity: " << granularity.width << " Vertical granularity: " << granularity.height << tcu::TestLog::EndMessage; 393 return tcu::TestStatus::pass("Granularity test"); 394 } 395 396 class GranularityCase : public vkt::TestCase 397 { 398 public: 399 GranularityCase (tcu::TestContext& testCtx, 400 const std::string& name, 401 const std::string& description, 402 const std::vector<AttachmentInfo>& attachments, 403 const bool useRenderPass); 404 virtual ~GranularityCase (void); 405 406 virtual TestInstance* createInstance (Context& context) const; 407 private: 408 const std::vector<AttachmentInfo> m_attachments; 409 const bool m_useRenderPass; 410 }; 411 412 GranularityCase::GranularityCase (tcu::TestContext& testCtx, 413 const std::string& name, 414 const std::string& description, 415 const std::vector<AttachmentInfo>& attachments, 416 const bool useRenderPass = false) 417 : vkt::TestCase (testCtx, name, description) 418 , m_attachments (attachments) 419 , m_useRenderPass (useRenderPass) 420 { 421 } 422 423 GranularityCase::~GranularityCase (void) 424 { 425 } 426 427 TestInstance* GranularityCase::createInstance (Context& context) const 428 { 429 return new GranularityInstance(context, m_attachments, m_useRenderPass); 430 } 431 432 } // anonymous 433 434 tcu::TestCaseGroup* createGranularityQueryTests (tcu::TestContext& testCtx) 435 { 436 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "granularity", "Granularity query tests")); 437 // Subgroups 438 de::MovePtr<tcu::TestCaseGroup> single (new tcu::TestCaseGroup(testCtx, "single", "Single texture granularity tests.")); 439 de::MovePtr<tcu::TestCaseGroup> multi (new tcu::TestCaseGroup(testCtx, "multi", "Multiple textures with same format granularity tests.")); 440 de::MovePtr<tcu::TestCaseGroup> random (new tcu::TestCaseGroup(testCtx, "random", "Multiple textures with a guaranteed format occurence.")); 441 de::MovePtr<tcu::TestCaseGroup> inRenderPass (new tcu::TestCaseGroup(testCtx, "in_render_pass", "Single texture granularity tests, inside render pass")); 442 443 de::Random rnd(215); 444 const char* description = "Granularity case."; 445 446 const VkFormat mandatoryFormats[] = 447 { 448 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 449 VK_FORMAT_R5G6B5_UNORM_PACK16, 450 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 451 VK_FORMAT_R8_UNORM, 452 VK_FORMAT_R8_SNORM, 453 VK_FORMAT_R8_UINT, 454 VK_FORMAT_R8_SINT, 455 VK_FORMAT_R8G8_UNORM, 456 VK_FORMAT_R8G8_SNORM, 457 VK_FORMAT_R8G8_UINT, 458 VK_FORMAT_R8G8_SINT, 459 VK_FORMAT_R8G8B8A8_UNORM, 460 VK_FORMAT_R8G8B8A8_SNORM, 461 VK_FORMAT_R8G8B8A8_UINT, 462 VK_FORMAT_R8G8B8A8_SINT, 463 VK_FORMAT_R8G8B8A8_SRGB, 464 VK_FORMAT_B8G8R8A8_UNORM, 465 VK_FORMAT_B8G8R8A8_SRGB, 466 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 467 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 468 VK_FORMAT_A8B8G8R8_UINT_PACK32, 469 VK_FORMAT_A8B8G8R8_SINT_PACK32, 470 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 471 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 472 VK_FORMAT_A2B10G10R10_UINT_PACK32, 473 VK_FORMAT_R16_UINT, 474 VK_FORMAT_R16_SINT, 475 VK_FORMAT_R16_SFLOAT, 476 VK_FORMAT_R16G16_UINT, 477 VK_FORMAT_R16G16_SINT, 478 VK_FORMAT_R16G16_SFLOAT, 479 VK_FORMAT_R16G16B16A16_UINT, 480 VK_FORMAT_R16G16B16A16_SINT, 481 VK_FORMAT_R16G16B16A16_SFLOAT, 482 VK_FORMAT_R32_UINT, 483 VK_FORMAT_R32_SINT, 484 VK_FORMAT_R32_SFLOAT, 485 VK_FORMAT_R32G32_UINT, 486 VK_FORMAT_R32G32_SINT, 487 VK_FORMAT_R32G32_SFLOAT, 488 VK_FORMAT_R32G32B32A32_UINT, 489 VK_FORMAT_R32G32B32A32_SINT, 490 VK_FORMAT_R32G32B32A32_SFLOAT, 491 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 492 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 493 VK_FORMAT_D16_UNORM, 494 VK_FORMAT_D32_SFLOAT, 495 }; 496 497 const deUint32 maxDimension = 500; 498 const deUint32 minIteration = 2; 499 const deUint32 maxIteration = 10; 500 501 for (deUint32 formatIdx = 1; formatIdx <= VK_FORMAT_D32_SFLOAT_S8_UINT; ++formatIdx) 502 { 503 VkFormat format = VkFormat(formatIdx); 504 std::string name = de::toLower(getFormatName(format)).substr(10); 505 506 { 507 std::vector<AttachmentInfo> attachments; 508 attachments.push_back(AttachmentInfo(format, rnd.getInt(1, maxDimension), rnd.getInt(1, maxDimension), 1)); 509 single->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); 510 } 511 512 { 513 std::vector<AttachmentInfo> attachments; 514 deUint32 iterations = rnd.getInt(minIteration, maxIteration); 515 for (deUint32 idx = 0; idx < iterations; ++idx) 516 attachments.push_back(AttachmentInfo(VkFormat(formatIdx), rnd.getInt(1, maxDimension), rnd.getInt(1, maxDimension), 1)); 517 multi->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); 518 } 519 520 { 521 std::vector<AttachmentInfo> attachments; 522 deUint32 iterations = rnd.getInt(minIteration, maxIteration); 523 attachments.push_back(AttachmentInfo(VkFormat(formatIdx), rnd.getInt(1, maxDimension), rnd.getInt(1, maxDimension), 1)); 524 for (deUint32 idx = 0; idx < iterations; ++idx) 525 attachments.push_back(AttachmentInfo(mandatoryFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(mandatoryFormats) - 1)], rnd.getInt(1, maxDimension), rnd.getInt(1, maxDimension), 1)); 526 random->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); 527 } 528 529 { 530 std::vector<AttachmentInfo> attachments; 531 attachments.push_back(AttachmentInfo(format, rnd.getInt(1, maxDimension), rnd.getInt(1, maxDimension), 1)); 532 inRenderPass->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments, true)); 533 } 534 } 535 536 group->addChild(single.release()); 537 group->addChild(multi.release()); 538 group->addChild(random.release()); 539 group->addChild(inRenderPass.release()); 540 541 return group.release(); 542 } 543 544 } // api 545 } // vkt 546