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