1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief VkSwapchain Tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktWsiSwapchainTests.hpp" 25 26 #include "vktTestCaseUtil.hpp" 27 #include "vktTestGroupUtil.hpp" 28 29 #include "vkDefs.hpp" 30 #include "vkPlatform.hpp" 31 #include "vkStrUtil.hpp" 32 #include "vkRef.hpp" 33 #include "vkRefUtil.hpp" 34 #include "vkQueryUtil.hpp" 35 #include "vkMemUtil.hpp" 36 #include "vkDeviceUtil.hpp" 37 #include "vkPrograms.hpp" 38 #include "vkTypeUtil.hpp" 39 #include "vkWsiPlatform.hpp" 40 #include "vkWsiUtil.hpp" 41 #include "vkAllocationCallbackUtil.hpp" 42 43 #include "tcuTestLog.hpp" 44 #include "tcuFormatUtil.hpp" 45 #include "tcuPlatform.hpp" 46 #include "tcuResultCollector.hpp" 47 48 #include "deUniquePtr.hpp" 49 #include "deStringUtil.hpp" 50 #include "deArrayUtil.hpp" 51 #include "deSharedPtr.hpp" 52 53 #include <limits> 54 55 namespace vkt 56 { 57 namespace wsi 58 { 59 60 namespace 61 { 62 63 using namespace vk; 64 using namespace vk::wsi; 65 66 using tcu::TestLog; 67 using tcu::Maybe; 68 using tcu::UVec2; 69 70 using de::MovePtr; 71 using de::UniquePtr; 72 73 using std::string; 74 using std::vector; 75 76 typedef vector<VkExtensionProperties> Extensions; 77 78 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions) 79 { 80 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin(); 81 requiredExtName != requiredExtensions.end(); 82 ++requiredExtName) 83 { 84 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName))) 85 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str()); 86 } 87 } 88 89 Move<VkInstance> createInstanceWithWsi (const PlatformInterface& vkp, 90 deUint32 version, 91 const Extensions& supportedExtensions, 92 Type wsiType, 93 const VkAllocationCallbacks* pAllocator = DE_NULL) 94 { 95 vector<string> extensions; 96 97 extensions.push_back("VK_KHR_surface"); 98 extensions.push_back(getExtensionName(wsiType)); 99 100 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate 101 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled, 102 // but using them without enabling the extension is not allowed. Thus we have 103 // two options: 104 // 105 // 1) Filter out non-core formats to stay within valid usage. 106 // 107 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver. 108 // 109 // We opt for (2) as it provides basic coverage for the extension as a bonus. 110 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace"))) 111 extensions.push_back("VK_EXT_swapchain_colorspace"); 112 113 checkAllSupported(supportedExtensions, extensions); 114 115 return vk::createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator); 116 } 117 118 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void) 119 { 120 VkPhysicalDeviceFeatures features; 121 deMemset(&features, 0, sizeof(features)); 122 return features; 123 } 124 125 Move<VkDevice> createDeviceWithWsi (const InstanceInterface& vki, 126 VkPhysicalDevice physicalDevice, 127 const Extensions& supportedExtensions, 128 const deUint32 queueFamilyIndex, 129 const VkAllocationCallbacks* pAllocator = DE_NULL) 130 { 131 const float queuePriorities[] = { 1.0f }; 132 const VkDeviceQueueCreateInfo queueInfos[] = 133 { 134 { 135 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 136 DE_NULL, 137 (VkDeviceQueueCreateFlags)0, 138 queueFamilyIndex, 139 DE_LENGTH_OF_ARRAY(queuePriorities), 140 &queuePriorities[0] 141 } 142 }; 143 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi(); 144 const char* const extensions[] = { "VK_KHR_swapchain" }; 145 const VkDeviceCreateInfo deviceParams = 146 { 147 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 148 DE_NULL, 149 (VkDeviceCreateFlags)0, 150 DE_LENGTH_OF_ARRAY(queueInfos), 151 &queueInfos[0], 152 0u, // enabledLayerCount 153 DE_NULL, // ppEnabledLayerNames 154 DE_LENGTH_OF_ARRAY(extensions), // enabledExtensionCount 155 DE_ARRAY_BEGIN(extensions), // ppEnabledExtensionNames 156 &features 157 }; 158 159 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx) 160 { 161 if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx]))) 162 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str()); 163 } 164 165 return createDevice(vki, physicalDevice, &deviceParams, pAllocator); 166 } 167 168 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) 169 { 170 deUint32 numFamilies = 0; 171 172 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL); 173 174 return numFamilies; 175 } 176 177 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) 178 { 179 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice); 180 vector<deUint32> supportedFamilyIndices; 181 182 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx) 183 { 184 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE) 185 supportedFamilyIndices.push_back(queueFamilyNdx); 186 } 187 188 return supportedFamilyIndices; 189 } 190 191 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) 192 { 193 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface); 194 195 if (supportedFamilyIndices.empty()) 196 TCU_THROW(NotSupportedError, "Device doesn't support presentation"); 197 198 return supportedFamilyIndices[0]; 199 } 200 201 struct InstanceHelper 202 { 203 const vector<VkExtensionProperties> supportedExtensions; 204 const Unique<VkInstance> instance; 205 const InstanceDriver vki; 206 207 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL) 208 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(), 209 DE_NULL)) 210 , instance (createInstanceWithWsi(context.getPlatformInterface(), 211 context.getUsedApiVersion(), 212 supportedExtensions, 213 wsiType, 214 pAllocator)) 215 , vki (context.getPlatformInterface(), *instance) 216 {} 217 }; 218 219 struct DeviceHelper 220 { 221 const VkPhysicalDevice physicalDevice; 222 const deUint32 queueFamilyIndex; 223 const Unique<VkDevice> device; 224 const DeviceDriver vkd; 225 const VkQueue queue; 226 227 DeviceHelper (Context& context, 228 const InstanceInterface& vki, 229 VkInstance instance, 230 VkSurfaceKHR surface, 231 const VkAllocationCallbacks* pAllocator = DE_NULL) 232 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine())) 233 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface)) 234 , device (createDeviceWithWsi(vki, 235 physicalDevice, 236 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL), 237 queueFamilyIndex, 238 pAllocator)) 239 , vkd (vki, *device) 240 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0)) 241 { 242 } 243 }; 244 245 MovePtr<Display> createDisplay (const vk::Platform& platform, 246 const Extensions& supportedExtensions, 247 Type wsiType) 248 { 249 try 250 { 251 return MovePtr<Display>(platform.createWsiDisplay(wsiType)); 252 } 253 catch (const tcu::NotSupportedError& e) 254 { 255 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType)))) 256 { 257 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation 258 // must support creating native display & window for that WSI type. 259 throw tcu::TestError(e.getMessage()); 260 } 261 else 262 throw; 263 } 264 } 265 266 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize) 267 { 268 try 269 { 270 return MovePtr<Window>(display.createWindow(initialSize)); 271 } 272 catch (const tcu::NotSupportedError& e) 273 { 274 // See createDisplay - assuming that wsi::Display was supported platform port 275 // should also support creating a window. 276 throw tcu::TestError(e.getMessage()); 277 } 278 } 279 280 struct NativeObjects 281 { 282 const UniquePtr<Display> display; 283 const UniquePtr<Window> window; 284 285 NativeObjects (Context& context, 286 const Extensions& supportedExtensions, 287 Type wsiType, 288 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>()) 289 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType)) 290 , window (createWindow(*display, initialWindowSize)) 291 {} 292 }; 293 294 enum TestDimension 295 { 296 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts 297 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats 298 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents 299 TEST_DIMENSION_IMAGE_ARRAY_LAYERS, 300 TEST_DIMENSION_IMAGE_USAGE, 301 TEST_DIMENSION_IMAGE_SHARING_MODE, 302 TEST_DIMENSION_PRE_TRANSFORM, 303 TEST_DIMENSION_COMPOSITE_ALPHA, 304 TEST_DIMENSION_PRESENT_MODE, 305 TEST_DIMENSION_CLIPPED, 306 307 TEST_DIMENSION_LAST 308 }; 309 310 const char* getTestDimensionName (TestDimension dimension) 311 { 312 static const char* const s_names[] = 313 { 314 "min_image_count", 315 "image_format", 316 "image_extent", 317 "image_array_layers", 318 "image_usage", 319 "image_sharing_mode", 320 "pre_transform", 321 "composite_alpha", 322 "present_mode", 323 "clipped" 324 }; 325 return de::getSizedArrayElement<TEST_DIMENSION_LAST>(s_names, dimension); 326 } 327 328 struct TestParameters 329 { 330 Type wsiType; 331 TestDimension dimension; 332 333 TestParameters (Type wsiType_, TestDimension dimension_) 334 : wsiType (wsiType_) 335 , dimension (dimension_) 336 {} 337 338 TestParameters (void) 339 : wsiType (TYPE_LAST) 340 , dimension (TEST_DIMENSION_LAST) 341 {} 342 }; 343 344 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type wsiType, 345 TestDimension dimension, 346 const VkSurfaceCapabilitiesKHR& capabilities, 347 const vector<VkSurfaceFormatKHR>& formats, 348 const vector<VkPresentModeKHR>& presentModes) 349 { 350 const PlatformProperties& platformProperties = getPlatformProperties(wsiType); 351 vector<VkSwapchainCreateInfoKHR> cases; 352 const VkSurfaceTransformFlagBitsKHR defaultTransform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform; 353 const VkSwapchainCreateInfoKHR baseParameters = 354 { 355 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 356 DE_NULL, 357 (VkSwapchainCreateFlagsKHR)0, 358 (VkSurfaceKHR)0, 359 capabilities.minImageCount, 360 formats[0].format, 361 formats[0].colorSpace, 362 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE 363 ? capabilities.minImageExtent : capabilities.currentExtent), 364 1u, // imageArrayLayers 365 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 366 VK_SHARING_MODE_EXCLUSIVE, 367 0u, 368 (const deUint32*)DE_NULL, 369 defaultTransform, 370 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, 371 VK_PRESENT_MODE_FIFO_KHR, 372 VK_FALSE, // clipped 373 (VkSwapchainKHR)0 // oldSwapchain 374 }; 375 376 switch (dimension) 377 { 378 case TEST_DIMENSION_MIN_IMAGE_COUNT: 379 { 380 const deUint32 maxImageCountToTest = de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u); 381 382 for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount) 383 { 384 cases.push_back(baseParameters); 385 cases.back().minImageCount = imageCount; 386 } 387 388 break; 389 } 390 391 case TEST_DIMENSION_IMAGE_FORMAT: 392 { 393 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt) 394 { 395 cases.push_back(baseParameters); 396 cases.back().imageFormat = curFmt->format; 397 cases.back().imageColorSpace = curFmt->colorSpace; 398 } 399 400 break; 401 } 402 403 case TEST_DIMENSION_IMAGE_EXTENT: 404 { 405 static const VkExtent2D s_testSizes[] = 406 { 407 { 1, 1 }, 408 { 16, 32 }, 409 { 32, 16 }, 410 { 632, 231 }, 411 { 117, 998 }, 412 }; 413 414 if (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE || 415 platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE) 416 { 417 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_testSizes); ++ndx) 418 { 419 cases.push_back(baseParameters); 420 cases.back().imageExtent.width = de::clamp(s_testSizes[ndx].width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); 421 cases.back().imageExtent.height = de::clamp(s_testSizes[ndx].height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); 422 } 423 } 424 425 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE) 426 { 427 cases.push_back(baseParameters); 428 cases.back().imageExtent = capabilities.currentExtent; 429 } 430 431 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE) 432 { 433 cases.push_back(baseParameters); 434 cases.back().imageExtent = capabilities.minImageExtent; 435 436 cases.push_back(baseParameters); 437 cases.back().imageExtent = capabilities.maxImageExtent; 438 } 439 440 break; 441 } 442 443 case TEST_DIMENSION_IMAGE_ARRAY_LAYERS: 444 { 445 const deUint32 maxLayers = de::min(capabilities.maxImageArrayLayers, 16u); 446 447 for (deUint32 numLayers = 1; numLayers <= maxLayers; ++numLayers) 448 { 449 cases.push_back(baseParameters); 450 cases.back().imageArrayLayers = numLayers; 451 } 452 453 break; 454 } 455 456 case TEST_DIMENSION_IMAGE_USAGE: 457 { 458 for (deUint32 flags = 1u; flags <= capabilities.supportedUsageFlags; ++flags) 459 { 460 if ((flags & ~capabilities.supportedUsageFlags) == 0) 461 { 462 cases.push_back(baseParameters); 463 cases.back().imageUsage = flags; 464 } 465 } 466 467 break; 468 } 469 470 case TEST_DIMENSION_IMAGE_SHARING_MODE: 471 { 472 cases.push_back(baseParameters); 473 cases.back().imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 474 475 cases.push_back(baseParameters); 476 cases.back().imageSharingMode = VK_SHARING_MODE_CONCURRENT; 477 478 break; 479 } 480 481 case TEST_DIMENSION_PRE_TRANSFORM: 482 { 483 for (deUint32 transform = 1u; 484 transform <= capabilities.supportedTransforms; 485 transform = transform<<1u) 486 { 487 if ((transform & capabilities.supportedTransforms) != 0) 488 { 489 cases.push_back(baseParameters); 490 cases.back().preTransform = (VkSurfaceTransformFlagBitsKHR)transform; 491 } 492 } 493 494 break; 495 } 496 497 case TEST_DIMENSION_COMPOSITE_ALPHA: 498 { 499 for (deUint32 alphaMode = 1u; 500 alphaMode <= capabilities.supportedCompositeAlpha; 501 alphaMode = alphaMode<<1u) 502 { 503 if ((alphaMode & capabilities.supportedCompositeAlpha) != 0) 504 { 505 cases.push_back(baseParameters); 506 cases.back().compositeAlpha = (VkCompositeAlphaFlagBitsKHR)alphaMode; 507 } 508 } 509 510 break; 511 } 512 513 case TEST_DIMENSION_PRESENT_MODE: 514 { 515 for (vector<VkPresentModeKHR>::const_iterator curMode = presentModes.begin(); curMode != presentModes.end(); ++curMode) 516 { 517 cases.push_back(baseParameters); 518 cases.back().presentMode = *curMode; 519 } 520 521 break; 522 } 523 524 case TEST_DIMENSION_CLIPPED: 525 { 526 cases.push_back(baseParameters); 527 cases.back().clipped = VK_FALSE; 528 529 cases.push_back(baseParameters); 530 cases.back().clipped = VK_TRUE; 531 532 break; 533 } 534 535 default: 536 DE_FATAL("Impossible"); 537 } 538 539 DE_ASSERT(!cases.empty()); 540 return cases; 541 } 542 543 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type wsiType, 544 TestDimension dimension, 545 const InstanceInterface& vki, 546 VkPhysicalDevice physicalDevice, 547 VkSurfaceKHR surface) 548 { 549 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki, 550 physicalDevice, 551 surface); 552 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(vki, 553 physicalDevice, 554 surface); 555 const vector<VkPresentModeKHR> presentModes = getPhysicalDeviceSurfacePresentModes(vki, 556 physicalDevice, 557 surface); 558 559 return generateSwapchainParameterCases(wsiType, dimension, capabilities, formats, presentModes); 560 } 561 562 tcu::TestStatus createSwapchainTest (Context& context, TestParameters params) 563 { 564 const InstanceHelper instHelper (context, params.wsiType); 565 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType); 566 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, params.wsiType, *native.display, *native.window)); 567 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); 568 const vector<VkSwapchainCreateInfoKHR> cases (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface)); 569 570 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 571 { 572 VkSwapchainCreateInfoKHR curParams = cases[caseNdx]; 573 574 curParams.surface = *surface; 575 curParams.queueFamilyIndexCount = 1u; 576 curParams.pQueueFamilyIndices = &devHelper.queueFamilyIndex; 577 578 context.getTestContext().getLog() 579 << TestLog::Message << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": " << curParams << TestLog::EndMessage; 580 581 { 582 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams)); 583 } 584 } 585 586 return tcu::TestStatus::pass("Creating swapchain succeeded"); 587 } 588 589 tcu::TestStatus createSwapchainSimulateOOMTest (Context& context, TestParameters params) 590 { 591 const size_t maxCases = 300u; 592 const deUint32 maxAllocs = 1024u; 593 594 tcu::TestLog& log = context.getTestContext().getLog(); 595 tcu::ResultCollector results (log); 596 597 AllocationCallbackRecorder allocationRecorder (getSystemAllocator()); 598 DeterministicFailAllocator failingAllocator (allocationRecorder.getCallbacks(), 599 DeterministicFailAllocator::MODE_DO_NOT_COUNT, 600 0); 601 { 602 const InstanceHelper instHelper (context, params.wsiType, failingAllocator.getCallbacks()); 603 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType); 604 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, 605 *instHelper.instance, 606 params.wsiType, 607 *native.display, 608 *native.window, 609 failingAllocator.getCallbacks())); 610 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface, failingAllocator.getCallbacks()); 611 const vector<VkSwapchainCreateInfoKHR> allCases (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface)); 612 613 if (maxCases < allCases.size()) 614 log << TestLog::Message << "Note: Will only test first " << maxCases << " cases out of total of " << allCases.size() << " parameter combinations" << TestLog::EndMessage; 615 616 for (size_t caseNdx = 0; caseNdx < de::min(maxCases, allCases.size()); ++caseNdx) 617 { 618 log << TestLog::Message << "Testing parameter case " << caseNdx << ": " << allCases[caseNdx] << TestLog::EndMessage; 619 620 for (deUint32 numPassingAllocs = 0; numPassingAllocs <= maxAllocs; ++numPassingAllocs) 621 { 622 bool gotOOM = false; 623 624 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs); 625 626 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage; 627 628 try 629 { 630 VkSwapchainCreateInfoKHR curParams = allCases[caseNdx]; 631 632 curParams.surface = *surface; 633 curParams.queueFamilyIndexCount = 1u; 634 curParams.pQueueFamilyIndices = &devHelper.queueFamilyIndex; 635 636 { 637 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks())); 638 } 639 } 640 catch (const OutOfMemoryError& e) 641 { 642 log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage; 643 gotOOM = true; 644 } 645 646 if (!gotOOM) 647 { 648 log << TestLog::Message << "Creating swapchain succeeded!" << TestLog::EndMessage; 649 650 if (numPassingAllocs == 0) 651 results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used"); 652 653 break; 654 } 655 else if (numPassingAllocs == maxAllocs) 656 results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded"); 657 } 658 } 659 660 context.getTestContext().touchWatchdog(); 661 } 662 663 if (!validateAndLog(log, allocationRecorder, 0u)) 664 results.fail("Detected invalid system allocation callback"); 665 666 return tcu::TestStatus(results.getResult(), results.getMessage()); 667 } 668 669 struct GroupParameters 670 { 671 typedef FunctionInstance1<TestParameters>::Function Function; 672 673 Type wsiType; 674 Function function; 675 676 GroupParameters (Type wsiType_, Function function_) 677 : wsiType (wsiType_) 678 , function (function_) 679 {} 680 681 GroupParameters (void) 682 : wsiType (TYPE_LAST) 683 , function ((Function)DE_NULL) 684 {} 685 }; 686 687 void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters params) 688 { 689 for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx) 690 { 691 const TestDimension testDimension = (TestDimension)dimensionNdx; 692 693 addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension)); 694 } 695 } 696 697 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType, 698 const InstanceInterface& vki, 699 VkPhysicalDevice physicalDevice, 700 VkSurfaceKHR surface, 701 const tcu::UVec2& desiredSize, 702 deUint32 desiredImageCount) 703 { 704 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki, 705 physicalDevice, 706 surface); 707 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(vki, 708 physicalDevice, 709 surface); 710 const PlatformProperties& platformProperties = getPlatformProperties(wsiType); 711 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform; 712 const VkSwapchainCreateInfoKHR parameters = 713 { 714 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 715 DE_NULL, 716 (VkSwapchainCreateFlagsKHR)0, 717 surface, 718 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount), 719 formats[0].format, 720 formats[0].colorSpace, 721 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE 722 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())), 723 1u, // imageArrayLayers 724 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 725 VK_SHARING_MODE_EXCLUSIVE, 726 0u, 727 (const deUint32*)DE_NULL, 728 transform, 729 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, 730 VK_PRESENT_MODE_FIFO_KHR, 731 VK_FALSE, // clipped 732 (VkSwapchainKHR)0 // oldSwapchain 733 }; 734 735 return parameters; 736 } 737 738 typedef de::SharedPtr<Unique<VkImageView> > ImageViewSp; 739 typedef de::SharedPtr<Unique<VkFramebuffer> > FramebufferSp; 740 741 class TriangleRenderer 742 { 743 public: 744 TriangleRenderer (const DeviceInterface& vkd, 745 const VkDevice device, 746 Allocator& allocator, 747 const BinaryCollection& binaryRegistry, 748 const vector<VkImage> swapchainImages, 749 const VkFormat framebufferFormat, 750 const UVec2& renderSize); 751 ~TriangleRenderer (void); 752 753 void recordFrame (VkCommandBuffer cmdBuffer, 754 deUint32 imageNdx, 755 deUint32 frameNdx) const; 756 757 static void getPrograms (SourceCollections& dst); 758 759 private: 760 static Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd, 761 const VkDevice device, 762 const VkFormat colorAttachmentFormat); 763 static Move<VkPipelineLayout> createPipelineLayout(const DeviceInterface& vkd, 764 VkDevice device); 765 static Move<VkPipeline> createPipeline (const DeviceInterface& vkd, 766 const VkDevice device, 767 const VkRenderPass renderPass, 768 const VkPipelineLayout pipelineLayout, 769 const BinaryCollection& binaryCollection, 770 const UVec2& renderSize); 771 772 static Move<VkImageView> createAttachmentView(const DeviceInterface& vkd, 773 const VkDevice device, 774 const VkImage image, 775 const VkFormat format); 776 static Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd, 777 const VkDevice device, 778 const VkRenderPass renderPass, 779 const VkImageView colorAttachment, 780 const UVec2& renderSize); 781 782 static Move<VkBuffer> createBuffer (const DeviceInterface& vkd, 783 VkDevice device, 784 VkDeviceSize size, 785 VkBufferUsageFlags usage); 786 787 const DeviceInterface& m_vkd; 788 789 const vector<VkImage> m_swapchainImages; 790 const tcu::UVec2 m_renderSize; 791 792 const Unique<VkRenderPass> m_renderPass; 793 const Unique<VkPipelineLayout> m_pipelineLayout; 794 const Unique<VkPipeline> m_pipeline; 795 796 const Unique<VkBuffer> m_vertexBuffer; 797 const UniquePtr<Allocation> m_vertexBufferMemory; 798 799 vector<ImageViewSp> m_attachmentViews; 800 vector<FramebufferSp> m_framebuffers; 801 }; 802 803 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface& vkd, 804 const VkDevice device, 805 const VkFormat colorAttachmentFormat) 806 { 807 const VkAttachmentDescription colorAttDesc = 808 { 809 (VkAttachmentDescriptionFlags)0, 810 colorAttachmentFormat, 811 VK_SAMPLE_COUNT_1_BIT, 812 VK_ATTACHMENT_LOAD_OP_CLEAR, 813 VK_ATTACHMENT_STORE_OP_STORE, 814 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 815 VK_ATTACHMENT_STORE_OP_DONT_CARE, 816 VK_IMAGE_LAYOUT_UNDEFINED, 817 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 818 }; 819 const VkAttachmentReference colorAttRef = 820 { 821 0u, 822 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 823 }; 824 const VkSubpassDescription subpassDesc = 825 { 826 (VkSubpassDescriptionFlags)0u, 827 VK_PIPELINE_BIND_POINT_GRAPHICS, 828 0u, // inputAttachmentCount 829 DE_NULL, // pInputAttachments 830 1u, // colorAttachmentCount 831 &colorAttRef, // pColorAttachments 832 DE_NULL, // pResolveAttachments 833 DE_NULL, // depthStencilAttachment 834 0u, // preserveAttachmentCount 835 DE_NULL, // pPreserveAttachments 836 }; 837 const VkSubpassDependency dependencies[] = 838 { 839 { 840 VK_SUBPASS_EXTERNAL, // srcSubpass 841 0u, // dstSubpass 842 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 843 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 844 VK_ACCESS_MEMORY_READ_BIT, 845 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| 846 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 847 VK_DEPENDENCY_BY_REGION_BIT 848 }, 849 { 850 0u, // srcSubpass 851 VK_SUBPASS_EXTERNAL, // dstSubpass 852 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 853 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 854 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| 855 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 856 VK_ACCESS_MEMORY_READ_BIT, 857 VK_DEPENDENCY_BY_REGION_BIT 858 }, 859 }; 860 const VkRenderPassCreateInfo renderPassParams = 861 { 862 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 863 DE_NULL, 864 (VkRenderPassCreateFlags)0, 865 1u, 866 &colorAttDesc, 867 1u, 868 &subpassDesc, 869 DE_LENGTH_OF_ARRAY(dependencies), 870 dependencies, 871 }; 872 873 return vk::createRenderPass(vkd, device, &renderPassParams); 874 } 875 876 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface& vkd, 877 const VkDevice device) 878 { 879 const VkPushConstantRange pushConstantRange = 880 { 881 VK_SHADER_STAGE_VERTEX_BIT, 882 0u, // offset 883 (deUint32)sizeof(deUint32), // size 884 }; 885 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 886 { 887 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 888 DE_NULL, 889 (vk::VkPipelineLayoutCreateFlags)0, 890 0u, // setLayoutCount 891 DE_NULL, // pSetLayouts 892 1u, 893 &pushConstantRange, 894 }; 895 896 return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams); 897 } 898 899 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface& vkd, 900 const VkDevice device, 901 const VkRenderPass renderPass, 902 const VkPipelineLayout pipelineLayout, 903 const BinaryCollection& binaryCollection, 904 const UVec2& renderSize) 905 { 906 // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines() 907 // and can be deleted immediately following that call. 908 const Unique<VkShaderModule> vertShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0)); 909 const Unique<VkShaderModule> fragShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0)); 910 911 const VkSpecializationInfo emptyShaderSpecParams = 912 { 913 0u, // mapEntryCount 914 DE_NULL, // pMap 915 0, // dataSize 916 DE_NULL, // pData 917 }; 918 const VkPipelineShaderStageCreateInfo shaderStageParams[] = 919 { 920 { 921 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 922 DE_NULL, 923 (VkPipelineShaderStageCreateFlags)0, 924 VK_SHADER_STAGE_VERTEX_BIT, 925 *vertShaderModule, 926 "main", 927 &emptyShaderSpecParams, 928 }, 929 { 930 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 931 DE_NULL, 932 (VkPipelineShaderStageCreateFlags)0, 933 VK_SHADER_STAGE_FRAGMENT_BIT, 934 *fragShaderModule, 935 "main", 936 &emptyShaderSpecParams, 937 } 938 }; 939 const VkPipelineDepthStencilStateCreateInfo depthStencilParams = 940 { 941 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 942 DE_NULL, 943 (VkPipelineDepthStencilStateCreateFlags)0, 944 DE_FALSE, // depthTestEnable 945 DE_FALSE, // depthWriteEnable 946 VK_COMPARE_OP_ALWAYS, // depthCompareOp 947 DE_FALSE, // depthBoundsTestEnable 948 DE_FALSE, // stencilTestEnable 949 { 950 VK_STENCIL_OP_KEEP, // failOp 951 VK_STENCIL_OP_KEEP, // passOp 952 VK_STENCIL_OP_KEEP, // depthFailOp 953 VK_COMPARE_OP_ALWAYS, // compareOp 954 0u, // compareMask 955 0u, // writeMask 956 0u, // reference 957 }, // front 958 { 959 VK_STENCIL_OP_KEEP, // failOp 960 VK_STENCIL_OP_KEEP, // passOp 961 VK_STENCIL_OP_KEEP, // depthFailOp 962 VK_COMPARE_OP_ALWAYS, // compareOp 963 0u, // compareMask 964 0u, // writeMask 965 0u, // reference 966 }, // back 967 -1.0f, // minDepthBounds 968 +1.0f, // maxDepthBounds 969 }; 970 const VkViewport viewport0 = 971 { 972 0.0f, // x 973 0.0f, // y 974 (float)renderSize.x(), // width 975 (float)renderSize.y(), // height 976 0.0f, // minDepth 977 1.0f, // maxDepth 978 }; 979 const VkRect2D scissor0 = 980 { 981 { 0u, 0u, }, // offset 982 { renderSize.x(), renderSize.y() }, // extent 983 }; 984 const VkPipelineViewportStateCreateInfo viewportParams = 985 { 986 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 987 DE_NULL, 988 (VkPipelineViewportStateCreateFlags)0, 989 1u, 990 &viewport0, 991 1u, 992 &scissor0 993 }; 994 const VkPipelineMultisampleStateCreateInfo multisampleParams = 995 { 996 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 997 DE_NULL, 998 (VkPipelineMultisampleStateCreateFlags)0, 999 VK_SAMPLE_COUNT_1_BIT, // rasterizationSamples 1000 VK_FALSE, // sampleShadingEnable 1001 0.0f, // minSampleShading 1002 (const VkSampleMask*)DE_NULL, // sampleMask 1003 VK_FALSE, // alphaToCoverageEnable 1004 VK_FALSE, // alphaToOneEnable 1005 }; 1006 const VkPipelineRasterizationStateCreateInfo rasterParams = 1007 { 1008 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 1009 DE_NULL, 1010 (VkPipelineRasterizationStateCreateFlags)0, 1011 VK_FALSE, // depthClampEnable 1012 VK_FALSE, // rasterizerDiscardEnable 1013 VK_POLYGON_MODE_FILL, // polygonMode 1014 VK_CULL_MODE_NONE, // cullMode 1015 VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace 1016 VK_FALSE, // depthBiasEnable 1017 0.0f, // depthBiasConstantFactor 1018 0.0f, // depthBiasClamp 1019 0.0f, // depthBiasSlopeFactor 1020 1.0f, // lineWidth 1021 }; 1022 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = 1023 { 1024 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 1025 DE_NULL, 1026 (VkPipelineInputAssemblyStateCreateFlags)0, 1027 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1028 DE_FALSE, // primitiveRestartEnable 1029 }; 1030 const VkVertexInputBindingDescription vertexBinding0 = 1031 { 1032 0u, // binding 1033 (deUint32)sizeof(tcu::Vec4), // stride 1034 VK_VERTEX_INPUT_RATE_VERTEX, // inputRate 1035 }; 1036 const VkVertexInputAttributeDescription vertexAttrib0 = 1037 { 1038 0u, // location 1039 0u, // binding 1040 VK_FORMAT_R32G32B32A32_SFLOAT, // format 1041 0u, // offset 1042 }; 1043 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 1044 { 1045 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 1046 DE_NULL, 1047 (VkPipelineVertexInputStateCreateFlags)0, 1048 1u, 1049 &vertexBinding0, 1050 1u, 1051 &vertexAttrib0, 1052 }; 1053 const VkPipelineColorBlendAttachmentState attBlendParams0 = 1054 { 1055 VK_FALSE, // blendEnable 1056 VK_BLEND_FACTOR_ONE, // srcColorBlendFactor 1057 VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor 1058 VK_BLEND_OP_ADD, // colorBlendOp 1059 VK_BLEND_FACTOR_ONE, // srcAlphaBlendFactor 1060 VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor 1061 VK_BLEND_OP_ADD, // alphaBlendOp 1062 (VK_COLOR_COMPONENT_R_BIT| 1063 VK_COLOR_COMPONENT_G_BIT| 1064 VK_COLOR_COMPONENT_B_BIT| 1065 VK_COLOR_COMPONENT_A_BIT), // colorWriteMask 1066 }; 1067 const VkPipelineColorBlendStateCreateInfo blendParams = 1068 { 1069 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 1070 DE_NULL, 1071 (VkPipelineColorBlendStateCreateFlags)0, 1072 VK_FALSE, // logicOpEnable 1073 VK_LOGIC_OP_COPY, 1074 1u, 1075 &attBlendParams0, 1076 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants[4] 1077 }; 1078 const VkGraphicsPipelineCreateInfo pipelineParams = 1079 { 1080 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 1081 DE_NULL, 1082 (VkPipelineCreateFlags)0, 1083 (deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams), 1084 shaderStageParams, 1085 &vertexInputStateParams, 1086 &inputAssemblyParams, 1087 (const VkPipelineTessellationStateCreateInfo*)DE_NULL, 1088 &viewportParams, 1089 &rasterParams, 1090 &multisampleParams, 1091 &depthStencilParams, 1092 &blendParams, 1093 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, 1094 pipelineLayout, 1095 renderPass, 1096 0u, // subpass 1097 DE_NULL, // basePipelineHandle 1098 0u, // basePipelineIndex 1099 }; 1100 1101 return vk::createGraphicsPipeline(vkd, device, (VkPipelineCache)0, &pipelineParams); 1102 } 1103 1104 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface& vkd, 1105 const VkDevice device, 1106 const VkImage image, 1107 const VkFormat format) 1108 { 1109 const VkImageViewCreateInfo viewParams = 1110 { 1111 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 1112 DE_NULL, 1113 (VkImageViewCreateFlags)0, 1114 image, 1115 VK_IMAGE_VIEW_TYPE_2D, 1116 format, 1117 vk::makeComponentMappingRGBA(), 1118 { 1119 VK_IMAGE_ASPECT_COLOR_BIT, 1120 0u, // baseMipLevel 1121 1u, // levelCount 1122 0u, // baseArrayLayer 1123 1u, // layerCount 1124 }, 1125 }; 1126 1127 return vk::createImageView(vkd, device, &viewParams); 1128 } 1129 1130 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface& vkd, 1131 const VkDevice device, 1132 const VkRenderPass renderPass, 1133 const VkImageView colorAttachment, 1134 const UVec2& renderSize) 1135 { 1136 const VkFramebufferCreateInfo framebufferParams = 1137 { 1138 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 1139 DE_NULL, 1140 (VkFramebufferCreateFlags)0, 1141 renderPass, 1142 1u, 1143 &colorAttachment, 1144 renderSize.x(), 1145 renderSize.y(), 1146 1u, // layers 1147 }; 1148 1149 return vk::createFramebuffer(vkd, device, &framebufferParams); 1150 } 1151 1152 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface& vkd, 1153 VkDevice device, 1154 VkDeviceSize size, 1155 VkBufferUsageFlags usage) 1156 { 1157 const VkBufferCreateInfo bufferParams = 1158 { 1159 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 1160 DE_NULL, 1161 (VkBufferCreateFlags)0, 1162 size, 1163 usage, 1164 VK_SHARING_MODE_EXCLUSIVE, 1165 0, 1166 DE_NULL 1167 }; 1168 1169 return vk::createBuffer(vkd, device, &bufferParams); 1170 } 1171 1172 TriangleRenderer::TriangleRenderer (const DeviceInterface& vkd, 1173 const VkDevice device, 1174 Allocator& allocator, 1175 const BinaryCollection& binaryRegistry, 1176 const vector<VkImage> swapchainImages, 1177 const VkFormat framebufferFormat, 1178 const UVec2& renderSize) 1179 : m_vkd (vkd) 1180 , m_swapchainImages (swapchainImages) 1181 , m_renderSize (renderSize) 1182 , m_renderPass (createRenderPass(vkd, device, framebufferFormat)) 1183 , m_pipelineLayout (createPipelineLayout(vkd, device)) 1184 , m_pipeline (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize)) 1185 , m_vertexBuffer (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)) 1186 , m_vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer), 1187 MemoryRequirement::HostVisible)) 1188 { 1189 m_attachmentViews.resize(swapchainImages.size()); 1190 m_framebuffers.resize(swapchainImages.size()); 1191 1192 for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx) 1193 { 1194 m_attachmentViews[imageNdx] = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat))); 1195 m_framebuffers[imageNdx] = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize))); 1196 } 1197 1198 VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset())); 1199 1200 { 1201 const VkMappedMemoryRange memRange = 1202 { 1203 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 1204 DE_NULL, 1205 m_vertexBufferMemory->getMemory(), 1206 m_vertexBufferMemory->getOffset(), 1207 VK_WHOLE_SIZE 1208 }; 1209 const tcu::Vec4 vertices[] = 1210 { 1211 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f), 1212 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f), 1213 tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f) 1214 }; 1215 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3); 1216 1217 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices)); 1218 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange)); 1219 } 1220 } 1221 1222 TriangleRenderer::~TriangleRenderer (void) 1223 { 1224 } 1225 1226 void TriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer, 1227 deUint32 imageNdx, 1228 deUint32 frameNdx) const 1229 { 1230 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx]; 1231 1232 { 1233 const VkCommandBufferBeginInfo cmdBufBeginParams = 1234 { 1235 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1236 DE_NULL, 1237 (VkCommandBufferUsageFlags)0, 1238 (const VkCommandBufferInheritanceInfo*)DE_NULL, 1239 }; 1240 VK_CHECK(m_vkd.beginCommandBuffer(cmdBuffer, &cmdBufBeginParams)); 1241 } 1242 1243 { 1244 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); 1245 const VkRenderPassBeginInfo passBeginParams = 1246 { 1247 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 1248 DE_NULL, 1249 *m_renderPass, 1250 curFramebuffer, 1251 { 1252 { 0, 0 }, 1253 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } 1254 }, // renderArea 1255 1u, // clearValueCount 1256 &clearValue, // pClearValues 1257 }; 1258 m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); 1259 } 1260 1261 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); 1262 1263 { 1264 const VkDeviceSize bindingOffset = 0; 1265 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset); 1266 } 1267 1268 m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx); 1269 m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); 1270 m_vkd.cmdEndRenderPass(cmdBuffer); 1271 1272 VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer)); 1273 } 1274 1275 void TriangleRenderer::getPrograms (SourceCollections& dst) 1276 { 1277 dst.glslSources.add("tri-vert") << glu::VertexSource( 1278 "#version 310 es\n" 1279 "layout(location = 0) in highp vec4 a_position;\n" 1280 "layout(push_constant) uniform FrameData\n" 1281 "{\n" 1282 " highp uint frameNdx;\n" 1283 "} frameData;\n" 1284 "void main (void)\n" 1285 "{\n" 1286 " highp float angle = float(frameData.frameNdx) / 100.0;\n" 1287 " highp float c = cos(angle);\n" 1288 " highp float s = sin(angle);\n" 1289 " highp mat4 t = mat4( c, -s, 0, 0,\n" 1290 " s, c, 0, 0,\n" 1291 " 0, 0, 1, 0,\n" 1292 " 0, 0, 0, 1);\n" 1293 " gl_Position = t * a_position;\n" 1294 "}\n"); 1295 dst.glslSources.add("tri-frag") << glu::FragmentSource( 1296 "#version 310 es\n" 1297 "layout(location = 0) out lowp vec4 o_color;\n" 1298 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n"); 1299 } 1300 1301 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp; 1302 typedef de::SharedPtr<Unique<VkFence> > FenceSp; 1303 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp; 1304 1305 vector<FenceSp> createFences (const DeviceInterface& vkd, 1306 const VkDevice device, 1307 size_t numFences) 1308 { 1309 vector<FenceSp> fences(numFences); 1310 1311 for (size_t ndx = 0; ndx < numFences; ++ndx) 1312 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device))); 1313 1314 return fences; 1315 } 1316 1317 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd, 1318 const VkDevice device, 1319 size_t numSemaphores) 1320 { 1321 vector<SemaphoreSp> semaphores(numSemaphores); 1322 1323 for (size_t ndx = 0; ndx < numSemaphores; ++ndx) 1324 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device))); 1325 1326 return semaphores; 1327 } 1328 1329 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd, 1330 const VkDevice device, 1331 const VkCommandPool commandPool, 1332 const VkCommandBufferLevel level, 1333 const size_t numCommandBuffers) 1334 { 1335 vector<CommandBufferSp> buffers (numCommandBuffers); 1336 1337 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx) 1338 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level))); 1339 1340 return buffers; 1341 } 1342 1343 tcu::TestStatus basicRenderTest (Context& context, Type wsiType) 1344 { 1345 const tcu::UVec2 desiredSize (256, 256); 1346 const InstanceHelper instHelper (context, wsiType); 1347 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize)); 1348 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window)); 1349 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); 1350 const DeviceInterface& vkd = devHelper.vkd; 1351 const VkDevice device = *devHelper.device; 1352 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice)); 1353 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2); 1354 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo)); 1355 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain); 1356 1357 const TriangleRenderer renderer (vkd, 1358 device, 1359 allocator, 1360 context.getBinaryCollection(), 1361 swapchainImages, 1362 swapchainInfo.imageFormat, 1363 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height)); 1364 1365 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex)); 1366 1367 const size_t maxQueuedFrames = swapchainImages.size()*2; 1368 1369 // We need to keep hold of fences from vkAcquireNextImageKHR to actually 1370 // limit number of frames we allow to be queued. 1371 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames)); 1372 1373 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass 1374 // the semaphore in same time as the fence we use to meter rendering. 1375 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1)); 1376 1377 // For rest we simply need maxQueuedFrames as we will wait for image 1378 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that 1379 // previous uses must have completed. 1380 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames)); 1381 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames)); 1382 1383 try 1384 { 1385 const deUint32 numFramesToRender = 60*10; 1386 1387 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx) 1388 { 1389 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()]; 1390 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()]; 1391 deUint32 imageNdx = ~0u; 1392 1393 if (frameNdx >= maxQueuedFrames) 1394 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max())); 1395 1396 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence)); 1397 1398 { 1399 const VkResult acquireResult = vkd.acquireNextImageKHR(device, 1400 *swapchain, 1401 std::numeric_limits<deUint64>::max(), 1402 imageReadySemaphore, 1403 (VkFence)0, 1404 &imageNdx); 1405 1406 if (acquireResult == VK_SUBOPTIMAL_KHR) 1407 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage; 1408 else 1409 VK_CHECK(acquireResult); 1410 } 1411 1412 TCU_CHECK((size_t)imageNdx < swapchainImages.size()); 1413 1414 { 1415 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()]; 1416 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()]; 1417 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1418 const VkSubmitInfo submitInfo = 1419 { 1420 VK_STRUCTURE_TYPE_SUBMIT_INFO, 1421 DE_NULL, 1422 1u, 1423 &imageReadySemaphore, 1424 &waitDstStage, 1425 1u, 1426 &commandBuffer, 1427 1u, 1428 &renderingCompleteSemaphore 1429 }; 1430 const VkPresentInfoKHR presentInfo = 1431 { 1432 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 1433 DE_NULL, 1434 1u, 1435 &renderingCompleteSemaphore, 1436 1u, 1437 &*swapchain, 1438 &imageNdx, 1439 (VkResult*)DE_NULL 1440 }; 1441 1442 renderer.recordFrame(commandBuffer, imageNdx, frameNdx); 1443 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence)); 1444 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo)); 1445 } 1446 } 1447 1448 VK_CHECK(vkd.deviceWaitIdle(device)); 1449 } 1450 catch (...) 1451 { 1452 // Make sure device is idle before destroying resources 1453 vkd.deviceWaitIdle(device); 1454 throw; 1455 } 1456 1457 return tcu::TestStatus::pass("Rendering tests succeeded"); 1458 } 1459 1460 vector<tcu::UVec2> getSwapchainSizeSequence (const VkSurfaceCapabilitiesKHR& capabilities, const tcu::UVec2& defaultSize) 1461 { 1462 vector<tcu::UVec2> sizes(3); 1463 sizes[0] = defaultSize / 2u; 1464 sizes[1] = defaultSize; 1465 sizes[2] = defaultSize * 2u; 1466 1467 for (deUint32 i = 0; i < sizes.size(); ++i) 1468 { 1469 sizes[i].x() = de::clamp(sizes[i].x(), capabilities.minImageExtent.width, capabilities.maxImageExtent.width); 1470 sizes[i].y() = de::clamp(sizes[i].y(), capabilities.minImageExtent.height, capabilities.maxImageExtent.height); 1471 } 1472 1473 return sizes; 1474 } 1475 1476 tcu::TestStatus resizeSwapchainTest (Context& context, Type wsiType) 1477 { 1478 const tcu::UVec2 desiredSize (256, 256); 1479 const InstanceHelper instHelper (context, wsiType); 1480 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize)); 1481 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window)); 1482 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); 1483 const PlatformProperties& platformProperties = getPlatformProperties(wsiType); 1484 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface); 1485 const DeviceInterface& vkd = devHelper.vkd; 1486 const VkDevice device = *devHelper.device; 1487 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice)); 1488 vector<tcu::UVec2> sizes = getSwapchainSizeSequence(capabilities, desiredSize); 1489 Move<VkSwapchainKHR> prevSwapchain; 1490 1491 DE_ASSERT(platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE); 1492 DE_UNREF(platformProperties); 1493 1494 for (deUint32 sizeNdx = 0; sizeNdx < sizes.size(); ++sizeNdx) 1495 { 1496 // \todo [2016-05-30 jesse] This test currently waits for idle and 1497 // recreates way more than necessary when recreating the swapchain. Make 1498 // it match expected real app behavior better by smoothly switching from 1499 // old to new swapchain. Once that is done, it will also be possible to 1500 // test creating a new swapchain while images from the previous one are 1501 // still acquired. 1502 1503 VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, sizes[sizeNdx], 2); 1504 swapchainInfo.oldSwapchain = *prevSwapchain; 1505 1506 Move<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo)); 1507 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain); 1508 const TriangleRenderer renderer (vkd, 1509 device, 1510 allocator, 1511 context.getBinaryCollection(), 1512 swapchainImages, 1513 swapchainInfo.imageFormat, 1514 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height)); 1515 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex)); 1516 const size_t maxQueuedFrames = swapchainImages.size()*2; 1517 1518 // We need to keep hold of fences from vkAcquireNextImageKHR to actually 1519 // limit number of frames we allow to be queued. 1520 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames)); 1521 1522 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass 1523 // the semaphore in same time as the fence we use to meter rendering. 1524 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1)); 1525 1526 // For rest we simply need maxQueuedFrames as we will wait for image 1527 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that 1528 // previous uses must have completed. 1529 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames)); 1530 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames)); 1531 1532 try 1533 { 1534 const deUint32 numFramesToRender = 60; 1535 1536 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx) 1537 { 1538 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()]; 1539 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()]; 1540 deUint32 imageNdx = ~0u; 1541 1542 if (frameNdx >= maxQueuedFrames) 1543 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max())); 1544 1545 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence)); 1546 1547 { 1548 const VkResult acquireResult = vkd.acquireNextImageKHR(device, 1549 *swapchain, 1550 std::numeric_limits<deUint64>::max(), 1551 imageReadySemaphore, 1552 imageReadyFence, 1553 &imageNdx); 1554 1555 if (acquireResult == VK_SUBOPTIMAL_KHR) 1556 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage; 1557 else 1558 VK_CHECK(acquireResult); 1559 } 1560 1561 TCU_CHECK((size_t)imageNdx < swapchainImages.size()); 1562 1563 { 1564 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()]; 1565 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()]; 1566 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1567 const VkSubmitInfo submitInfo = 1568 { 1569 VK_STRUCTURE_TYPE_SUBMIT_INFO, 1570 DE_NULL, 1571 1u, 1572 &imageReadySemaphore, 1573 &waitDstStage, 1574 1u, 1575 &commandBuffer, 1576 1u, 1577 &renderingCompleteSemaphore 1578 }; 1579 const VkPresentInfoKHR presentInfo = 1580 { 1581 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 1582 DE_NULL, 1583 1u, 1584 &renderingCompleteSemaphore, 1585 1u, 1586 &*swapchain, 1587 &imageNdx, 1588 (VkResult*)DE_NULL 1589 }; 1590 1591 renderer.recordFrame(commandBuffer, imageNdx, frameNdx); 1592 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, (VkFence)0)); 1593 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo)); 1594 } 1595 } 1596 1597 VK_CHECK(vkd.deviceWaitIdle(device)); 1598 1599 prevSwapchain = swapchain; 1600 } 1601 catch (...) 1602 { 1603 // Make sure device is idle before destroying resources 1604 vkd.deviceWaitIdle(device); 1605 throw; 1606 } 1607 } 1608 1609 return tcu::TestStatus::pass("Resizing tests succeeded"); 1610 } 1611 1612 tcu::TestStatus getImagesIncompleteResultTest (Context& context, Type wsiType) 1613 { 1614 const tcu::UVec2 desiredSize (256, 256); 1615 const InstanceHelper instHelper (context, wsiType); 1616 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize)); 1617 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window)); 1618 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); 1619 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2); 1620 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo)); 1621 1622 vector<VkImage> swapchainImages = getSwapchainImages(devHelper.vkd, *devHelper.device, *swapchain); 1623 1624 ValidateQueryBits::fillBits(swapchainImages.begin(), swapchainImages.end()); 1625 1626 const deUint32 usedCount = static_cast<deUint32>(swapchainImages.size() / 2); 1627 deUint32 count = usedCount; 1628 const VkResult result = devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &count, &swapchainImages[0]); 1629 1630 if (count != usedCount || result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(swapchainImages.begin() + count, swapchainImages.end())) 1631 return tcu::TestStatus::fail("Get swapchain images didn't return VK_INCOMPLETE"); 1632 else 1633 return tcu::TestStatus::pass("Get swapchain images tests succeeded"); 1634 } 1635 1636 tcu::TestStatus destroyNullHandleSwapchainTest (Context& context, Type wsiType) 1637 { 1638 const InstanceHelper instHelper (context, wsiType); 1639 const NativeObjects native (context, instHelper.supportedExtensions, wsiType); 1640 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window)); 1641 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); 1642 const VkSwapchainKHR nullHandle = DE_NULL; 1643 1644 // Default allocator 1645 devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, DE_NULL); 1646 1647 // Custom allocator 1648 { 1649 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); 1650 1651 devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, recordingAllocator.getCallbacks()); 1652 1653 if (recordingAllocator.getNumRecords() != 0u) 1654 return tcu::TestStatus::fail("Implementation allocated/freed the memory"); 1655 } 1656 1657 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect"); 1658 } 1659 1660 void getBasicRenderPrograms (SourceCollections& dst, Type) 1661 { 1662 TriangleRenderer::getPrograms(dst); 1663 } 1664 1665 void populateRenderGroup (tcu::TestCaseGroup* testGroup, Type wsiType) 1666 { 1667 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest, wsiType); 1668 } 1669 1670 void populateGetImagesGroup (tcu::TestCaseGroup* testGroup, Type wsiType) 1671 { 1672 addFunctionCase(testGroup, "incomplete", "Test VK_INCOMPLETE return code", getImagesIncompleteResultTest, wsiType); 1673 } 1674 1675 void populateModifyGroup (tcu::TestCaseGroup* testGroup, Type wsiType) 1676 { 1677 const PlatformProperties& platformProperties = getPlatformProperties(wsiType); 1678 1679 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE) 1680 { 1681 addFunctionCaseWithPrograms(testGroup, "resize", "Resize Swapchain Test", getBasicRenderPrograms, resizeSwapchainTest, wsiType); 1682 } 1683 1684 // \todo [2016-05-30 jesse] Add tests for modifying preTransform, compositeAlpha, presentMode 1685 } 1686 1687 void populateDestroyGroup (tcu::TestCaseGroup* testGroup, Type wsiType) 1688 { 1689 addFunctionCase(testGroup, "null_handle", "Destroying a VK_NULL_HANDLE swapchain", destroyNullHandleSwapchainTest, wsiType); 1690 } 1691 1692 } // anonymous 1693 1694 void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType) 1695 { 1696 addTestGroup(testGroup, "create", "Create VkSwapchain with various parameters", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainTest)); 1697 addTestGroup(testGroup, "simulate_oom", "Simulate OOM using callbacks during swapchain construction", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainSimulateOOMTest)); 1698 addTestGroup(testGroup, "render", "Rendering Tests", populateRenderGroup, wsiType); 1699 addTestGroup(testGroup, "modify", "Modify VkSwapchain", populateModifyGroup, wsiType); 1700 addTestGroup(testGroup, "destroy", "Destroy VkSwapchain", populateDestroyGroup, wsiType); 1701 addTestGroup(testGroup, "get_images", "Get swapchain images", populateGetImagesGroup, wsiType); 1702 } 1703 1704 } // wsi 1705 } // vkt 1706