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