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