1 /* 2 * Copyright (c) 2015-2017 The Khronos Group Inc. 3 * Copyright (c) 2015-2017 Valve Corporation 4 * Copyright (c) 2015-2017 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Jeremy Hayes <jeremy (at) lunarG.com> 26 * Author: Mark Young <marky (at) lunarG.com> 27 */ 28 29 // Following items are needed for C++ to work with PRIxLEAST64 30 #define __STDC_FORMAT_MACROS 31 #include <inttypes.h> 32 33 #include <stdint.h> // For UINT32_MAX 34 35 #include <algorithm> 36 #include <iostream> 37 #include <memory> 38 #include <string> 39 #include <vector> 40 41 #include "test_common.h" 42 #include <vulkan/vulkan.h> 43 44 namespace VK { 45 46 struct InstanceCreateInfo { 47 InstanceCreateInfo() 48 : info // MSVC can't handle list initialization, thus explicit construction herein. 49 (VkInstanceCreateInfo{ 50 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType 51 nullptr, // pNext 52 0, // flags 53 nullptr, // pApplicationInfo 54 0, // enabledLayerCount 55 nullptr, // ppEnabledLayerNames 56 0, // enabledExtensionCount 57 nullptr // ppEnabledExtensionNames 58 }) {} 59 60 InstanceCreateInfo &sType(VkStructureType const &sType) { 61 info.sType = sType; 62 63 return *this; 64 } 65 66 InstanceCreateInfo &pNext(void const *const pNext) { 67 info.pNext = pNext; 68 69 return *this; 70 } 71 72 InstanceCreateInfo &flags(VkInstanceCreateFlags const &flags) { 73 info.flags = flags; 74 75 return *this; 76 } 77 78 InstanceCreateInfo &pApplicationInfo(VkApplicationInfo const *const pApplicationInfo) { 79 info.pApplicationInfo = pApplicationInfo; 80 81 return *this; 82 } 83 84 InstanceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) { 85 info.enabledLayerCount = enabledLayerCount; 86 87 return *this; 88 } 89 90 InstanceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) { 91 info.ppEnabledLayerNames = ppEnabledLayerNames; 92 93 return *this; 94 } 95 96 InstanceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) { 97 info.enabledExtensionCount = enabledExtensionCount; 98 99 return *this; 100 } 101 102 InstanceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) { 103 info.ppEnabledExtensionNames = ppEnabledExtensionNames; 104 105 return *this; 106 } 107 108 operator VkInstanceCreateInfo const *() const { return &info; } 109 110 operator VkInstanceCreateInfo *() { return &info; } 111 112 VkInstanceCreateInfo info; 113 }; 114 115 struct DeviceQueueCreateInfo { 116 DeviceQueueCreateInfo() 117 : info // MSVC can't handle list initialization, thus explicit construction herein. 118 (VkDeviceQueueCreateInfo{ 119 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType 120 nullptr, // pNext 121 0, // flags 122 0, // queueFamilyIndex 123 0, // queueCount 124 nullptr // pQueuePriorities 125 }) {} 126 127 DeviceQueueCreateInfo &sType(VkStructureType const &sType) { 128 info.sType = sType; 129 130 return *this; 131 } 132 133 DeviceQueueCreateInfo &pNext(void const *const pNext) { 134 info.pNext = pNext; 135 136 return *this; 137 } 138 139 DeviceQueueCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) { 140 info.flags = flags; 141 142 return *this; 143 } 144 145 DeviceQueueCreateInfo &queueFamilyIndex(uint32_t const &queueFamilyIndex) { 146 info.queueFamilyIndex = queueFamilyIndex; 147 148 return *this; 149 } 150 151 DeviceQueueCreateInfo &queueCount(uint32_t const &queueCount) { 152 info.queueCount = queueCount; 153 154 return *this; 155 } 156 157 DeviceQueueCreateInfo &pQueuePriorities(float const *const pQueuePriorities) { 158 info.pQueuePriorities = pQueuePriorities; 159 160 return *this; 161 } 162 163 operator VkDeviceQueueCreateInfo() { return info; } 164 165 VkDeviceQueueCreateInfo info; 166 }; 167 168 struct DeviceCreateInfo { 169 DeviceCreateInfo() 170 : info // MSVC can't handle list initialization, thus explicit construction herein. 171 (VkDeviceCreateInfo{ 172 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType 173 nullptr, // pNext 174 0, // flags 175 0, // queueCreateInfoCount 176 nullptr, // pQueueCreateInfos 177 0, // enabledLayerCount 178 nullptr, // ppEnabledLayerNames 179 0, // enabledExtensionCount 180 nullptr, // ppEnabledExtensionNames 181 nullptr // pEnabledFeatures 182 }) {} 183 184 DeviceCreateInfo &sType(VkStructureType const &sType) { 185 info.sType = sType; 186 187 return *this; 188 } 189 190 DeviceCreateInfo &pNext(void const *const pNext) { 191 info.pNext = pNext; 192 193 return *this; 194 } 195 196 DeviceCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) { 197 info.flags = flags; 198 199 return *this; 200 } 201 202 DeviceCreateInfo &queueCreateInfoCount(uint32_t const &queueCreateInfoCount) { 203 info.queueCreateInfoCount = queueCreateInfoCount; 204 205 return *this; 206 } 207 208 DeviceCreateInfo &pQueueCreateInfos(VkDeviceQueueCreateInfo const *const pQueueCreateInfos) { 209 info.pQueueCreateInfos = pQueueCreateInfos; 210 211 return *this; 212 } 213 214 DeviceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) { 215 info.enabledLayerCount = enabledLayerCount; 216 217 return *this; 218 } 219 220 DeviceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) { 221 info.ppEnabledLayerNames = ppEnabledLayerNames; 222 223 return *this; 224 } 225 226 DeviceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) { 227 info.enabledExtensionCount = enabledExtensionCount; 228 229 return *this; 230 } 231 232 DeviceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) { 233 info.ppEnabledExtensionNames = ppEnabledExtensionNames; 234 235 return *this; 236 } 237 238 DeviceCreateInfo &pEnabledFeatures(VkPhysicalDeviceFeatures const *const pEnabledFeatures) { 239 info.pEnabledFeatures = pEnabledFeatures; 240 241 return *this; 242 } 243 244 operator VkDeviceCreateInfo const *() const { return &info; } 245 246 operator VkDeviceCreateInfo *() { return &info; } 247 248 VkDeviceCreateInfo info; 249 }; 250 } // namespace VK 251 252 struct CommandLine : public ::testing::Test { 253 static void Initialize(int argc, char **argv) { arguments.assign(argv, argv + argc); }; 254 255 static void SetUpTestCase(){}; 256 static void TearDownTestCase(){}; 257 258 static std::vector<std::string> arguments; 259 }; 260 std::vector<std::string> CommandLine::arguments; 261 262 struct EnumerateInstanceLayerProperties : public CommandLine {}; 263 struct EnumerateInstanceExtensionProperties : public CommandLine {}; 264 struct ImplicitLayer : public CommandLine {}; 265 266 // Allocation tracking utilities 267 struct AllocTrack { 268 bool active; 269 bool was_allocated; 270 void *aligned_start_addr; 271 char *actual_start_addr; 272 size_t requested_size_bytes; 273 size_t actual_size_bytes; 274 VkSystemAllocationScope alloc_scope; 275 uint64_t user_data; 276 277 AllocTrack() 278 : active(false), 279 was_allocated(false), 280 aligned_start_addr(nullptr), 281 actual_start_addr(nullptr), 282 requested_size_bytes(0), 283 actual_size_bytes(0), 284 alloc_scope(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND), 285 user_data(0) {} 286 }; 287 288 // Global vector to track allocations. This will be resized before each test and emptied after. 289 // However, we have to globally define it so the allocation callback functions work properly. 290 std::vector<AllocTrack> g_allocated_vector; 291 bool g_intentional_fail_enabled = false; 292 uint32_t g_intenional_fail_index = 0; 293 uint32_t g_intenional_fail_count = 0; 294 295 void FreeAllocTracker() { g_allocated_vector.clear(); } 296 297 void InitAllocTracker(size_t size, uint32_t intentional_fail_index = UINT32_MAX) { 298 if (g_allocated_vector.size() > 0) { 299 FreeAllocTracker(); 300 } 301 g_allocated_vector.resize(size); 302 if (intentional_fail_index != UINT32_MAX) { 303 g_intentional_fail_enabled = true; 304 g_intenional_fail_index = intentional_fail_index; 305 g_intenional_fail_count = 0; 306 } else { 307 g_intentional_fail_enabled = false; 308 g_intenional_fail_index = 0; 309 g_intenional_fail_count = 0; 310 } 311 } 312 313 bool IsAllocTrackerEmpty() { 314 bool success = true; 315 bool was_allocated = false; 316 char print_command[1024]; 317 sprintf(print_command, "\t%%04d\t%%p (%%p) : 0x%%%s (0x%%%s) : scope %%d : user_data 0x%%%s\n", PRIxLEAST64, PRIxLEAST64, 318 PRIxLEAST64); 319 for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) { 320 if (g_allocated_vector[iii].active) { 321 if (success) { 322 printf("ERROR: Allocations still remain!\n"); 323 } 324 printf(print_command, iii, g_allocated_vector[iii].aligned_start_addr, g_allocated_vector[iii].actual_start_addr, 325 g_allocated_vector[iii].requested_size_bytes, g_allocated_vector[iii].actual_size_bytes, 326 g_allocated_vector[iii].alloc_scope, g_allocated_vector[iii].user_data); 327 success = false; 328 } else if (!was_allocated && g_allocated_vector[iii].was_allocated) { 329 was_allocated = true; 330 } 331 } 332 if (!g_intentional_fail_enabled && !was_allocated) { 333 printf("No allocations ever generated!"); 334 success = false; 335 } 336 return success; 337 } 338 339 VKAPI_ATTR void *VKAPI_CALL AllocCallbackFunc(void *pUserData, size_t size, size_t alignment, 340 VkSystemAllocationScope allocationScope) { 341 if (g_intentional_fail_enabled) { 342 if (++g_intenional_fail_count >= g_intenional_fail_index) { 343 return nullptr; 344 } 345 } 346 for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) { 347 if (!g_allocated_vector[iii].active) { 348 g_allocated_vector[iii].requested_size_bytes = size; 349 g_allocated_vector[iii].actual_size_bytes = size + (alignment - 1); 350 g_allocated_vector[iii].aligned_start_addr = NULL; 351 g_allocated_vector[iii].actual_start_addr = new char[g_allocated_vector[iii].actual_size_bytes]; 352 if (g_allocated_vector[iii].actual_start_addr != NULL) { 353 uint64_t addr = (uint64_t)g_allocated_vector[iii].actual_start_addr; 354 addr += (alignment - 1); 355 addr &= ~(alignment - 1); 356 g_allocated_vector[iii].aligned_start_addr = (void *)addr; 357 g_allocated_vector[iii].alloc_scope = allocationScope; 358 g_allocated_vector[iii].user_data = (uint64_t)pUserData; 359 g_allocated_vector[iii].active = true; 360 g_allocated_vector[iii].was_allocated = true; 361 } 362 return g_allocated_vector[iii].aligned_start_addr; 363 } 364 } 365 return nullptr; 366 } 367 368 VKAPI_ATTR void VKAPI_CALL FreeCallbackFunc(void *pUserData, void *pMemory) { 369 for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) { 370 if (g_allocated_vector[iii].active && g_allocated_vector[iii].aligned_start_addr == pMemory) { 371 delete[] g_allocated_vector[iii].actual_start_addr; 372 g_allocated_vector[iii].active = false; 373 break; 374 } 375 } 376 } 377 378 VKAPI_ATTR void *VKAPI_CALL ReallocCallbackFunc(void *pUserData, void *pOriginal, size_t size, size_t alignment, 379 VkSystemAllocationScope allocationScope) { 380 if (pOriginal != NULL) { 381 for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) { 382 if (g_allocated_vector[iii].active && g_allocated_vector[iii].aligned_start_addr == pOriginal) { 383 if (size == 0) { 384 FreeCallbackFunc(pUserData, pOriginal); 385 return nullptr; 386 } else if (size < g_allocated_vector[iii].requested_size_bytes) { 387 return pOriginal; 388 } else { 389 void *pNew = AllocCallbackFunc(pUserData, size, alignment, allocationScope); 390 if (pNew != NULL) { 391 size_t copy_size = size; 392 if (g_allocated_vector[iii].requested_size_bytes < size) { 393 copy_size = g_allocated_vector[iii].requested_size_bytes; 394 } 395 memcpy(pNew, pOriginal, copy_size); 396 FreeCallbackFunc(pUserData, pOriginal); 397 } 398 return pNew; 399 } 400 } 401 } 402 return nullptr; 403 } else { 404 return AllocCallbackFunc(pUserData, size, alignment, allocationScope); 405 } 406 } 407 408 // Test groups: 409 // LX = lunar exchange 410 // LVLGH = loader and validation github 411 // LVLGL = lodaer and validation gitlab 412 413 TEST(LX435, InstanceCreateInfoConst) { 414 VkInstanceCreateInfo const info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}; 415 416 VkInstance instance = VK_NULL_HANDLE; 417 VkResult result = vkCreateInstance(&info, VK_NULL_HANDLE, &instance); 418 EXPECT_EQ(result, VK_SUCCESS); 419 420 vkDestroyInstance(instance, nullptr); 421 } 422 423 TEST(LX475, DestroyInstanceNullHandle) { vkDestroyInstance(VK_NULL_HANDLE, nullptr); } 424 425 TEST(LX475, DestroyDeviceNullHandle) { vkDestroyDevice(VK_NULL_HANDLE, nullptr); } 426 427 TEST(CreateInstance, ExtensionNotPresent) { 428 char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. 429 auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names); 430 431 VkInstance instance = VK_NULL_HANDLE; 432 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 433 ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); 434 435 // It's not necessary to destroy the instance because it will not be created successfully. 436 } 437 438 TEST(CreateInstance, LayerNotPresent) { 439 char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. 440 auto const info = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names); 441 442 VkInstance instance = VK_NULL_HANDLE; 443 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 444 ASSERT_EQ(result, VK_ERROR_LAYER_NOT_PRESENT); 445 446 // It's not necessary to destroy the instance because it will not be created successfully. 447 } 448 449 // Used by run_loader_tests.sh to test for layer insertion. 450 TEST(CreateInstance, LayerPresent) { 451 char const *const names1[] = {"VK_LAYER_LUNARG_parameter_validation"}; // Temporary required due to MSVC bug. 452 char const *const names2[] = {"VK_LAYER_LUNARG_standard_validation"}; // Temporary required due to MSVC bug. 453 auto const info1 = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names1); 454 VkInstance instance = VK_NULL_HANDLE; 455 VkResult result = vkCreateInstance(info1, VK_NULL_HANDLE, &instance); 456 ASSERT_EQ(result, VK_SUCCESS); 457 vkDestroyInstance(instance, nullptr); 458 459 auto const info2 = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names2); 460 instance = VK_NULL_HANDLE; 461 result = vkCreateInstance(info2, VK_NULL_HANDLE, &instance); 462 ASSERT_EQ(result, VK_SUCCESS); 463 vkDestroyInstance(instance, nullptr); 464 } 465 466 // Used by run_loader_tests.sh to test that calling vkEnumeratePhysicalDevices without first querying 467 // the count, works. 468 TEST(EnumeratePhysicalDevices, OneCall) { 469 VkInstance instance = VK_NULL_HANDLE; 470 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 471 ASSERT_EQ(result, VK_SUCCESS); 472 473 uint32_t physicalCount = 500; 474 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 475 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 476 ASSERT_EQ(result, VK_SUCCESS); 477 ASSERT_GT(physicalCount, 0u); 478 479 vkDestroyInstance(instance, nullptr); 480 } 481 482 // Used by run_loader_tests.sh to test for the expected usage of the vkEnumeratePhysicalDevices call. 483 TEST(EnumeratePhysicalDevices, TwoCall) { 484 VkInstance instance = VK_NULL_HANDLE; 485 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 486 ASSERT_EQ(result, VK_SUCCESS); 487 488 uint32_t physicalCount = 0; 489 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 490 ASSERT_EQ(result, VK_SUCCESS); 491 ASSERT_GT(physicalCount, 0u); 492 493 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 494 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 495 ASSERT_EQ(result, VK_SUCCESS); 496 ASSERT_GT(physicalCount, 0u); 497 498 vkDestroyInstance(instance, nullptr); 499 } 500 501 // Used by run_loader_tests.sh to test that calling vkEnumeratePhysicalDevices without first querying 502 // the count, matches the count from the standard call. 503 TEST(EnumeratePhysicalDevices, MatchOneAndTwoCallNumbers) { 504 VkInstance instance_one = VK_NULL_HANDLE; 505 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance_one); 506 ASSERT_EQ(result, VK_SUCCESS); 507 508 uint32_t physicalCount_one = 500; 509 std::unique_ptr<VkPhysicalDevice[]> physical_one(new VkPhysicalDevice[physicalCount_one]); 510 result = vkEnumeratePhysicalDevices(instance_one, &physicalCount_one, physical_one.get()); 511 ASSERT_EQ(result, VK_SUCCESS); 512 ASSERT_GT(physicalCount_one, 0u); 513 514 VkInstance instance_two = VK_NULL_HANDLE; 515 result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance_two); 516 ASSERT_EQ(result, VK_SUCCESS); 517 518 uint32_t physicalCount_two = 0; 519 result = vkEnumeratePhysicalDevices(instance_two, &physicalCount_two, nullptr); 520 ASSERT_EQ(result, VK_SUCCESS); 521 ASSERT_GT(physicalCount_two, 0u); 522 523 std::unique_ptr<VkPhysicalDevice[]> physical_two(new VkPhysicalDevice[physicalCount_two]); 524 result = vkEnumeratePhysicalDevices(instance_two, &physicalCount_two, physical_two.get()); 525 ASSERT_EQ(result, VK_SUCCESS); 526 ASSERT_GT(physicalCount_two, 0u); 527 528 ASSERT_EQ(physicalCount_one, physicalCount_two); 529 530 vkDestroyInstance(instance_one, nullptr); 531 vkDestroyInstance(instance_two, nullptr); 532 } 533 534 // Used by run_loader_tests.sh to test for the expected usage of the vkEnumeratePhysicalDevices 535 // call if not enough numbers are provided for the final list. 536 TEST(EnumeratePhysicalDevices, TwoCallIncomplete) { 537 VkInstance instance = VK_NULL_HANDLE; 538 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 539 ASSERT_EQ(result, VK_SUCCESS); 540 541 uint32_t physicalCount = 0; 542 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 543 ASSERT_EQ(result, VK_SUCCESS); 544 ASSERT_GT(physicalCount, 0u); 545 546 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 547 548 // Remove one from the physical device count so we can get the VK_INCOMPLETE message 549 physicalCount -= 1; 550 551 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 552 ASSERT_EQ(result, VK_INCOMPLETE); 553 554 vkDestroyInstance(instance, nullptr); 555 } 556 557 // Test to make sure that layers enabled in the instance show up in the list of device layers. 558 TEST(EnumerateDeviceLayers, LayersMatch) { 559 char const *const names1[] = {"VK_LAYER_LUNARG_standard_validation"}; 560 char const *const names2[3] = {"VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_core_validation", 561 "VK_LAYER_LUNARG_object_tracker"}; 562 auto const info1 = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names1); 563 VkInstance instance = VK_NULL_HANDLE; 564 VkResult result = vkCreateInstance(info1, VK_NULL_HANDLE, &instance); 565 ASSERT_EQ(result, VK_SUCCESS); 566 567 uint32_t physicalCount = 0; 568 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 569 ASSERT_EQ(result, VK_SUCCESS); 570 ASSERT_GT(physicalCount, 0u); 571 572 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 573 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 574 ASSERT_EQ(result, VK_SUCCESS); 575 ASSERT_GT(physicalCount, 0u); 576 uint32_t count = 24; 577 VkLayerProperties layer_props[24]; 578 vkEnumerateDeviceLayerProperties(physical[0], &count, layer_props); 579 ASSERT_GE(count, 1u); 580 bool found = false; 581 for (uint32_t iii = 0; iii < count; iii++) { 582 if (!strcmp(layer_props[iii].layerName, names1[0])) { 583 found = true; 584 break; 585 } 586 } 587 if (!found) { 588 ASSERT_EQ(count, 0); 589 } 590 591 vkDestroyInstance(instance, nullptr); 592 593 auto const info2 = VK::InstanceCreateInfo().enabledLayerCount(3).ppEnabledLayerNames(names2); 594 instance = VK_NULL_HANDLE; 595 result = vkCreateInstance(info2, VK_NULL_HANDLE, &instance); 596 ASSERT_EQ(result, VK_SUCCESS); 597 598 physicalCount = 0; 599 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 600 ASSERT_EQ(result, VK_SUCCESS); 601 ASSERT_GT(physicalCount, 0u); 602 603 std::unique_ptr<VkPhysicalDevice[]> physical2(new VkPhysicalDevice[physicalCount]); 604 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical2.get()); 605 ASSERT_EQ(result, VK_SUCCESS); 606 ASSERT_GT(physicalCount, 0u); 607 608 count = 24; 609 vkEnumerateDeviceLayerProperties(physical2[0], &count, layer_props); 610 ASSERT_GE(count, 3u); 611 for (uint32_t jjj = 0; jjj < 3; jjj++) { 612 found = false; 613 for (uint32_t iii = 0; iii < count; iii++) { 614 if (!strcmp(layer_props[iii].layerName, names2[jjj])) { 615 found = true; 616 break; 617 } 618 } 619 if (!found) { 620 ASSERT_EQ(count, 0); 621 } 622 } 623 624 vkDestroyInstance(instance, nullptr); 625 } 626 627 TEST(CreateDevice, ExtensionNotPresent) { 628 VkInstance instance = VK_NULL_HANDLE; 629 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 630 ASSERT_EQ(result, VK_SUCCESS); 631 632 uint32_t physicalCount = 0; 633 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 634 ASSERT_EQ(result, VK_SUCCESS); 635 ASSERT_GT(physicalCount, 0u); 636 637 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 638 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 639 ASSERT_EQ(result, VK_SUCCESS); 640 ASSERT_GT(physicalCount, 0u); 641 642 for (uint32_t p = 0; p < physicalCount; ++p) { 643 uint32_t familyCount = 0; 644 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 645 ASSERT_GT(familyCount, 0u); 646 647 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 648 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 649 ASSERT_GT(familyCount, 0u); 650 651 for (uint32_t q = 0; q < familyCount; ++q) { 652 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 653 continue; 654 } 655 656 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 657 VkDeviceQueueCreateInfo const queueInfo[1]{ 658 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 659 660 char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. 661 auto const deviceInfo = VK::DeviceCreateInfo() 662 .queueCreateInfoCount(1) 663 .pQueueCreateInfos(queueInfo) 664 .enabledExtensionCount(1) 665 .ppEnabledExtensionNames(names); 666 667 VkDevice device; 668 result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); 669 ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); 670 671 // It's not necessary to destroy the device because it will not be created successfully. 672 } 673 } 674 675 vkDestroyInstance(instance, nullptr); 676 } 677 678 // LX535 / MI-76: Device layers are deprecated. 679 // For backwards compatibility, they are allowed, but must be ignored. 680 // Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice. 681 TEST(CreateDevice, LayersNotPresent) { 682 VkInstance instance = VK_NULL_HANDLE; 683 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 684 ASSERT_EQ(result, VK_SUCCESS); 685 686 uint32_t physicalCount = 0; 687 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 688 ASSERT_EQ(result, VK_SUCCESS); 689 ASSERT_GT(physicalCount, 0u); 690 691 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 692 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 693 ASSERT_EQ(result, VK_SUCCESS); 694 ASSERT_GT(physicalCount, 0u); 695 696 for (uint32_t p = 0; p < physicalCount; ++p) { 697 uint32_t familyCount = 0; 698 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 699 ASSERT_EQ(result, VK_SUCCESS); 700 ASSERT_GT(familyCount, 0u); 701 702 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 703 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 704 ASSERT_EQ(result, VK_SUCCESS); 705 ASSERT_GT(familyCount, 0u); 706 707 for (uint32_t q = 0; q < familyCount; ++q) { 708 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 709 continue; 710 } 711 712 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 713 VkDeviceQueueCreateInfo const queueInfo[1]{ 714 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 715 716 char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. 717 auto const deviceInfo = VK::DeviceCreateInfo() 718 .queueCreateInfoCount(1) 719 .pQueueCreateInfos(queueInfo) 720 .enabledLayerCount(1) 721 .ppEnabledLayerNames(names); 722 723 VkDevice device; 724 result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); 725 ASSERT_EQ(result, VK_SUCCESS); 726 727 vkDestroyDevice(device, nullptr); 728 } 729 } 730 731 vkDestroyInstance(instance, nullptr); 732 } 733 734 TEST_F(EnumerateInstanceLayerProperties, PropertyCountLessThanAvailable) { 735 uint32_t count = 0u; 736 VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); 737 ASSERT_EQ(result, VK_SUCCESS); 738 739 // We need atleast two for the test to be relevant. 740 if (count < 2u) { 741 return; 742 } 743 744 std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); 745 count = 1; 746 result = vkEnumerateInstanceLayerProperties(&count, properties.get()); 747 ASSERT_EQ(result, VK_INCOMPLETE); 748 } 749 750 TEST(EnumerateDeviceLayerProperties, PropertyCountLessThanAvailable) { 751 VkInstance instance = VK_NULL_HANDLE; 752 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 753 ASSERT_EQ(result, VK_SUCCESS); 754 755 uint32_t physicalCount = 0; 756 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 757 ASSERT_EQ(result, VK_SUCCESS); 758 ASSERT_GT(physicalCount, 0u); 759 760 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 761 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 762 ASSERT_EQ(result, VK_SUCCESS); 763 ASSERT_GT(physicalCount, 0u); 764 765 for (uint32_t p = 0; p < physicalCount; ++p) { 766 uint32_t count = 0u; 767 result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr); 768 ASSERT_EQ(result, VK_SUCCESS); 769 770 // We need atleast two for the test to be relevant. 771 if (count < 2u) { 772 continue; 773 } 774 775 std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); 776 count = 1; 777 result = vkEnumerateDeviceLayerProperties(physical[p], &count, properties.get()); 778 ASSERT_EQ(result, VK_INCOMPLETE); 779 } 780 781 vkDestroyInstance(instance, nullptr); 782 } 783 784 TEST_F(EnumerateInstanceLayerProperties, Count) { 785 uint32_t count = 0u; 786 VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); 787 ASSERT_EQ(result, VK_SUCCESS); 788 789 if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) { 790 std::cout << "count=" << count << '\n'; 791 } 792 } 793 794 TEST_F(EnumerateInstanceLayerProperties, OnePass) { 795 // Count required for this test. 796 if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) { 797 return; 798 } 799 800 uint32_t count = std::stoul(arguments[2]); 801 802 std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); 803 VkResult result = vkEnumerateInstanceLayerProperties(&count, properties.get()); 804 ASSERT_EQ(result, VK_SUCCESS); 805 806 if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { 807 for (uint32_t p = 0; p < count; ++p) { 808 std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' 809 << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; 810 } 811 } 812 } 813 814 TEST_F(EnumerateInstanceLayerProperties, TwoPass) { 815 uint32_t count = 0u; 816 VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); 817 ASSERT_EQ(result, VK_SUCCESS); 818 819 std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); 820 result = vkEnumerateInstanceLayerProperties(&count, properties.get()); 821 ASSERT_EQ(result, VK_SUCCESS); 822 823 if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { 824 for (uint32_t p = 0; p < count; ++p) { 825 std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' 826 << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; 827 } 828 } 829 } 830 831 TEST_F(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) { 832 uint32_t count = 0u; 833 VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 834 ASSERT_EQ(result, VK_SUCCESS); 835 836 // We need atleast two for the test to be relevant. 837 if (count < 2u) { 838 return; 839 } 840 841 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 842 count = 1; 843 result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); 844 ASSERT_EQ(result, VK_INCOMPLETE); 845 } 846 847 TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable) { 848 VkInstance instance = VK_NULL_HANDLE; 849 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 850 ASSERT_EQ(result, VK_SUCCESS); 851 852 uint32_t physicalCount = 0; 853 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 854 ASSERT_EQ(result, VK_SUCCESS); 855 ASSERT_GT(physicalCount, 0u); 856 857 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 858 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 859 ASSERT_EQ(result, VK_SUCCESS); 860 ASSERT_GT(physicalCount, 0u); 861 862 for (uint32_t p = 0; p < physicalCount; ++p) { 863 uint32_t count = 0u; 864 result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); 865 ASSERT_EQ(result, VK_SUCCESS); 866 867 // We need atleast two for the test to be relevant. 868 if (count < 2u) { 869 continue; 870 } 871 872 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 873 count = 1; 874 result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); 875 ASSERT_EQ(result, VK_INCOMPLETE); 876 } 877 878 vkDestroyInstance(instance, nullptr); 879 } 880 881 TEST_F(EnumerateInstanceExtensionProperties, Count) { 882 uint32_t count = 0u; 883 VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 884 ASSERT_EQ(result, VK_SUCCESS); 885 886 if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) { 887 std::cout << "count=" << count << '\n'; 888 } 889 } 890 891 TEST_F(EnumerateInstanceExtensionProperties, OnePass) { 892 // Count required for this test. 893 if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) { 894 return; 895 } 896 897 uint32_t count = std::stoul(arguments[2]); 898 899 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 900 VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); 901 ASSERT_EQ(result, VK_SUCCESS); 902 903 if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { 904 for (uint32_t p = 0; p < count; ++p) { 905 std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion 906 << '\n'; 907 } 908 } 909 } 910 911 TEST_F(EnumerateInstanceExtensionProperties, TwoPass) { 912 uint32_t count = 0u; 913 VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 914 ASSERT_EQ(result, VK_SUCCESS); 915 916 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 917 result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); 918 ASSERT_EQ(result, VK_SUCCESS); 919 920 if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { 921 for (uint32_t p = 0; p < count; ++p) { 922 std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion 923 << '\n'; 924 } 925 } 926 } 927 928 TEST_F(EnumerateInstanceExtensionProperties, InstanceExtensionEnumerated) { 929 uint32_t count = 0u; 930 VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 931 ASSERT_EQ(result, VK_SUCCESS); 932 933 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 934 result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); 935 ASSERT_EQ(result, VK_SUCCESS); 936 937 ASSERT_NE(std::find_if( 938 &properties[0], &properties[count], 939 [](VkExtensionProperties const &properties) { return strcmp(properties.extensionName, "VK_KHR_surface") == 0; }), 940 &properties[count]); 941 } 942 943 TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) { 944 VkInstance instance = VK_NULL_HANDLE; 945 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 946 ASSERT_EQ(result, VK_SUCCESS); 947 948 uint32_t physicalCount = 0; 949 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 950 ASSERT_EQ(result, VK_SUCCESS); 951 ASSERT_GT(physicalCount, 0u); 952 953 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 954 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 955 ASSERT_EQ(result, VK_SUCCESS); 956 ASSERT_GT(physicalCount, 0u); 957 958 for (uint32_t p = 0; p < physicalCount; ++p) { 959 uint32_t count = 0u; 960 result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); 961 ASSERT_EQ(result, VK_SUCCESS); 962 963 std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); 964 result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); 965 ASSERT_EQ(result, VK_SUCCESS); 966 967 ASSERT_NE(std::find_if(&properties[0], &properties[count], 968 [](VkExtensionProperties const &properties) { 969 return strcmp(properties.extensionName, "VK_KHR_swapchain") == 0; 970 }), 971 &properties[count]); 972 } 973 974 vkDestroyInstance(instance, nullptr); 975 } 976 977 TEST_F(ImplicitLayer, Present) { 978 auto const info = VK::InstanceCreateInfo(); 979 VkInstance instance = VK_NULL_HANDLE; 980 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 981 ASSERT_EQ(result, VK_SUCCESS); 982 983 vkDestroyInstance(instance, nullptr); 984 } 985 986 TEST(WrapObjects, Insert) { 987 VkInstance instance = VK_NULL_HANDLE; 988 VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); 989 ASSERT_EQ(result, VK_SUCCESS); 990 991 uint32_t physicalCount = 0; 992 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 993 ASSERT_EQ(result, VK_SUCCESS); 994 ASSERT_GT(physicalCount, 0u); 995 996 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 997 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 998 ASSERT_EQ(result, VK_SUCCESS); 999 ASSERT_GT(physicalCount, 0u); 1000 1001 for (uint32_t p = 0; p < physicalCount; ++p) { 1002 uint32_t familyCount = 0; 1003 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 1004 ASSERT_EQ(result, VK_SUCCESS); 1005 ASSERT_GT(familyCount, 0u); 1006 1007 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1008 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 1009 ASSERT_EQ(result, VK_SUCCESS); 1010 ASSERT_GT(familyCount, 0u); 1011 1012 for (uint32_t q = 0; q < familyCount; ++q) { 1013 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1014 continue; 1015 } 1016 1017 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1018 VkDeviceQueueCreateInfo const queueInfo[1]{ 1019 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 1020 1021 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1022 1023 VkDevice device; 1024 result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); 1025 ASSERT_EQ(result, VK_SUCCESS); 1026 1027 vkDestroyDevice(device, nullptr); 1028 } 1029 } 1030 1031 vkDestroyInstance(instance, nullptr); 1032 } 1033 1034 // Test making sure the allocation functions are called to allocate and cleanup everything during 1035 // a CreateInstance/DestroyInstance call pair. 1036 TEST(Allocation, Instance) { 1037 auto const info = VK::InstanceCreateInfo(); 1038 VkInstance instance = VK_NULL_HANDLE; 1039 VkAllocationCallbacks alloc_callbacks = {}; 1040 alloc_callbacks.pUserData = (void *)0x00000001; 1041 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1042 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1043 alloc_callbacks.pfnFree = FreeCallbackFunc; 1044 1045 InitAllocTracker(2048); 1046 1047 VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance); 1048 ASSERT_EQ(result, VK_SUCCESS); 1049 1050 alloc_callbacks.pUserData = (void *)0x00000002; 1051 vkDestroyInstance(instance, &alloc_callbacks); 1052 1053 // Make sure everything's been freed 1054 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1055 FreeAllocTracker(); 1056 } 1057 1058 // Test making sure the allocation functions are called to allocate and cleanup everything during 1059 // a CreateInstance/DestroyInstance call pair with a call to GetInstanceProcAddr. 1060 TEST(Allocation, GetInstanceProcAddr) { 1061 auto const info = VK::InstanceCreateInfo(); 1062 VkInstance instance = VK_NULL_HANDLE; 1063 VkAllocationCallbacks alloc_callbacks = {}; 1064 alloc_callbacks.pUserData = (void *)0x00000010; 1065 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1066 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1067 alloc_callbacks.pfnFree = FreeCallbackFunc; 1068 1069 InitAllocTracker(2048); 1070 1071 VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance); 1072 ASSERT_EQ(result, VK_SUCCESS); 1073 1074 void *pfnCreateDevice = (void *)vkGetInstanceProcAddr(instance, "vkCreateDevice"); 1075 void *pfnDestroyDevice = (void *)vkGetInstanceProcAddr(instance, "vkDestroyDevice"); 1076 ASSERT_TRUE(pfnCreateDevice != NULL && pfnDestroyDevice != NULL); 1077 1078 alloc_callbacks.pUserData = (void *)0x00000011; 1079 vkDestroyInstance(instance, &alloc_callbacks); 1080 1081 // Make sure everything's been freed 1082 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1083 FreeAllocTracker(); 1084 } 1085 1086 // Test making sure the allocation functions are called to allocate and cleanup everything during 1087 // a vkEnumeratePhysicalDevices call pair. 1088 TEST(Allocation, EnumeratePhysicalDevices) { 1089 auto const info = VK::InstanceCreateInfo(); 1090 VkInstance instance = VK_NULL_HANDLE; 1091 VkAllocationCallbacks alloc_callbacks = {}; 1092 alloc_callbacks.pUserData = (void *)0x00000021; 1093 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1094 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1095 alloc_callbacks.pfnFree = FreeCallbackFunc; 1096 1097 InitAllocTracker(2048); 1098 1099 VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance); 1100 ASSERT_EQ(result, VK_SUCCESS); 1101 1102 uint32_t physicalCount = 0; 1103 alloc_callbacks.pUserData = (void *)0x00000022; 1104 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1105 ASSERT_EQ(result, VK_SUCCESS); 1106 ASSERT_GT(physicalCount, 0u); 1107 1108 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1109 alloc_callbacks.pUserData = (void *)0x00000023; 1110 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1111 ASSERT_EQ(result, VK_SUCCESS); 1112 ASSERT_GT(physicalCount, 0u); 1113 1114 alloc_callbacks.pUserData = (void *)0x00000024; 1115 vkDestroyInstance(instance, &alloc_callbacks); 1116 1117 // Make sure everything's been freed 1118 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1119 FreeAllocTracker(); 1120 } 1121 1122 // Test making sure the allocation functions are called to allocate and cleanup everything from 1123 // vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 1124 // allocators used on both the instance and device. 1125 TEST(Allocation, InstanceAndDevice) { 1126 auto const info = VK::InstanceCreateInfo(); 1127 VkInstance instance = VK_NULL_HANDLE; 1128 VkAllocationCallbacks alloc_callbacks = {}; 1129 alloc_callbacks.pUserData = (void *)0x00000031; 1130 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1131 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1132 alloc_callbacks.pfnFree = FreeCallbackFunc; 1133 1134 InitAllocTracker(2048); 1135 1136 VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance); 1137 ASSERT_EQ(result, VK_SUCCESS); 1138 1139 uint32_t physicalCount = 0; 1140 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1141 ASSERT_EQ(result, VK_SUCCESS); 1142 ASSERT_GT(physicalCount, 0u); 1143 1144 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1145 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1146 ASSERT_EQ(result, VK_SUCCESS); 1147 ASSERT_GT(physicalCount, 0u); 1148 1149 for (uint32_t p = 0; p < physicalCount; ++p) { 1150 uint32_t familyCount = 0; 1151 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 1152 ASSERT_GT(familyCount, 0u); 1153 1154 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1155 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 1156 ASSERT_GT(familyCount, 0u); 1157 1158 for (uint32_t q = 0; q < familyCount; ++q) { 1159 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1160 continue; 1161 } 1162 1163 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1164 VkDeviceQueueCreateInfo const queueInfo[1]{ 1165 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 1166 1167 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1168 1169 VkDevice device; 1170 alloc_callbacks.pUserData = (void *)0x00000032; 1171 result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device); 1172 ASSERT_EQ(result, VK_SUCCESS); 1173 1174 alloc_callbacks.pUserData = (void *)0x00000033; 1175 vkDestroyDevice(device, &alloc_callbacks); 1176 } 1177 } 1178 1179 alloc_callbacks.pUserData = (void *)0x00000034; 1180 vkDestroyInstance(instance, &alloc_callbacks); 1181 1182 // Make sure everything's been freed 1183 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1184 FreeAllocTracker(); 1185 } 1186 1187 // Test making sure the allocation functions are called to allocate and cleanup everything from 1188 // vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 1189 // allocators used on only the instance and not the device. 1190 TEST(Allocation, InstanceButNotDevice) { 1191 auto const info = VK::InstanceCreateInfo(); 1192 VkInstance instance = VK_NULL_HANDLE; 1193 VkAllocationCallbacks alloc_callbacks = {}; 1194 alloc_callbacks.pUserData = (void *)0x00000041; 1195 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1196 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1197 alloc_callbacks.pfnFree = FreeCallbackFunc; 1198 1199 InitAllocTracker(2048); 1200 1201 VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance); 1202 ASSERT_EQ(result, VK_SUCCESS); 1203 1204 uint32_t physicalCount = 0; 1205 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1206 ASSERT_EQ(result, VK_SUCCESS); 1207 ASSERT_GT(physicalCount, 0u); 1208 1209 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1210 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1211 ASSERT_EQ(result, VK_SUCCESS); 1212 ASSERT_GT(physicalCount, 0u); 1213 1214 for (uint32_t p = 0; p < physicalCount; ++p) { 1215 uint32_t familyCount = 0; 1216 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 1217 ASSERT_GT(familyCount, 0u); 1218 1219 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1220 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 1221 ASSERT_GT(familyCount, 0u); 1222 1223 for (uint32_t q = 0; q < familyCount; ++q) { 1224 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1225 continue; 1226 } 1227 1228 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1229 VkDeviceQueueCreateInfo const queueInfo[1]{ 1230 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 1231 1232 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1233 1234 VkDevice device; 1235 result = vkCreateDevice(physical[p], deviceInfo, NULL, &device); 1236 ASSERT_EQ(result, VK_SUCCESS); 1237 1238 vkDestroyDevice(device, NULL); 1239 } 1240 } 1241 1242 alloc_callbacks.pUserData = (void *)0x00000042; 1243 vkDestroyInstance(instance, &alloc_callbacks); 1244 1245 // Make sure everything's been freed 1246 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1247 FreeAllocTracker(); 1248 } 1249 1250 // Test making sure the allocation functions are called to allocate and cleanup everything from 1251 // vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 1252 // allocators used on only the device and not the instance. 1253 TEST(Allocation, DeviceButNotInstance) { 1254 auto const info = VK::InstanceCreateInfo(); 1255 VkInstance instance = VK_NULL_HANDLE; 1256 VkAllocationCallbacks alloc_callbacks = {}; 1257 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1258 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1259 alloc_callbacks.pfnFree = FreeCallbackFunc; 1260 1261 InitAllocTracker(2048); 1262 1263 VkResult result = vkCreateInstance(info, NULL, &instance); 1264 ASSERT_EQ(result, VK_SUCCESS); 1265 1266 uint32_t physicalCount = 0; 1267 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1268 ASSERT_EQ(result, VK_SUCCESS); 1269 ASSERT_GT(physicalCount, 0u); 1270 1271 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1272 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1273 ASSERT_EQ(result, VK_SUCCESS); 1274 ASSERT_GT(physicalCount, 0u); 1275 1276 for (uint32_t p = 0; p < physicalCount; ++p) { 1277 uint32_t familyCount = 0; 1278 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 1279 ASSERT_GT(familyCount, 0u); 1280 1281 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1282 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 1283 ASSERT_GT(familyCount, 0u); 1284 1285 for (uint32_t q = 0; q < familyCount; ++q) { 1286 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1287 continue; 1288 } 1289 1290 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1291 VkDeviceQueueCreateInfo const queueInfo[1]{ 1292 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 1293 1294 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1295 1296 VkDevice device; 1297 alloc_callbacks.pUserData = (void *)0x00000051; 1298 result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device); 1299 ASSERT_EQ(result, VK_SUCCESS); 1300 1301 alloc_callbacks.pUserData = (void *)0x00000052; 1302 vkDestroyDevice(device, &alloc_callbacks); 1303 } 1304 } 1305 1306 vkDestroyInstance(instance, NULL); 1307 1308 // Make sure everything's been freed 1309 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1310 FreeAllocTracker(); 1311 } 1312 1313 // Test failure during vkCreateInstance to make sure we don't leak memory if 1314 // one of the out-of-memory conditions trigger. 1315 TEST(Allocation, CreateInstanceIntentionalAllocFail) { 1316 auto const info = VK::InstanceCreateInfo(); 1317 VkInstance instance = VK_NULL_HANDLE; 1318 VkAllocationCallbacks alloc_callbacks = {}; 1319 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1320 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1321 alloc_callbacks.pfnFree = FreeCallbackFunc; 1322 1323 VkResult result; 1324 uint32_t fail_index = 1; 1325 do { 1326 InitAllocTracker(9999, fail_index); 1327 1328 result = vkCreateInstance(info, &alloc_callbacks, &instance); 1329 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1330 if (!IsAllocTrackerEmpty()) { 1331 std::cout << "Failed on index " << fail_index << '\n'; 1332 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1333 } 1334 } 1335 fail_index++; 1336 // Make sure we don't overrun the memory 1337 ASSERT_LT(fail_index, 9999u); 1338 1339 FreeAllocTracker(); 1340 } while (result == VK_ERROR_OUT_OF_HOST_MEMORY); 1341 1342 vkDestroyInstance(instance, &alloc_callbacks); 1343 } 1344 1345 // Test failure during vkCreateDevice to make sure we don't leak memory if 1346 // one of the out-of-memory conditions trigger. 1347 TEST(Allocation, CreateDeviceIntentionalAllocFail) { 1348 auto const info = VK::InstanceCreateInfo(); 1349 VkInstance instance = VK_NULL_HANDLE; 1350 VkDevice device = VK_NULL_HANDLE; 1351 VkAllocationCallbacks alloc_callbacks = {}; 1352 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1353 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1354 alloc_callbacks.pfnFree = FreeCallbackFunc; 1355 1356 VkResult result = vkCreateInstance(info, NULL, &instance); 1357 ASSERT_EQ(result, VK_SUCCESS); 1358 1359 uint32_t physicalCount = 0; 1360 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1361 ASSERT_EQ(result, VK_SUCCESS); 1362 ASSERT_GT(physicalCount, 0u); 1363 1364 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1365 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1366 ASSERT_EQ(result, VK_SUCCESS); 1367 ASSERT_GT(physicalCount, 0u); 1368 1369 for (uint32_t p = 0; p < physicalCount; ++p) { 1370 uint32_t familyCount = 0; 1371 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); 1372 ASSERT_GT(familyCount, 0u); 1373 1374 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1375 vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); 1376 ASSERT_GT(familyCount, 0u); 1377 1378 for (uint32_t q = 0; q < familyCount; ++q) { 1379 if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1380 continue; 1381 } 1382 1383 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1384 VkDeviceQueueCreateInfo const queueInfo[1]{ 1385 VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; 1386 1387 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1388 1389 uint32_t fail_index = 1; 1390 do { 1391 InitAllocTracker(9999, fail_index); 1392 1393 result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device); 1394 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1395 if (!IsAllocTrackerEmpty()) { 1396 std::cout << "Failed on index " << fail_index << '\n'; 1397 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1398 } 1399 } 1400 fail_index++; 1401 // Make sure we don't overrun the memory 1402 ASSERT_LT(fail_index, 9999u); 1403 1404 FreeAllocTracker(); 1405 } while (result == VK_ERROR_OUT_OF_HOST_MEMORY); 1406 vkDestroyDevice(device, &alloc_callbacks); 1407 break; 1408 } 1409 } 1410 1411 vkDestroyInstance(instance, NULL); 1412 } 1413 1414 // Test failure during vkCreateInstance and vkCreateDevice to make sure we don't 1415 // leak memory if one of the out-of-memory conditions trigger. 1416 TEST(Allocation, CreateInstanceDeviceIntentionalAllocFail) { 1417 auto const info = VK::InstanceCreateInfo(); 1418 VkInstance instance = VK_NULL_HANDLE; 1419 VkDevice device = VK_NULL_HANDLE; 1420 VkAllocationCallbacks alloc_callbacks = {}; 1421 alloc_callbacks.pfnAllocation = AllocCallbackFunc; 1422 alloc_callbacks.pfnReallocation = ReallocCallbackFunc; 1423 alloc_callbacks.pfnFree = FreeCallbackFunc; 1424 1425 VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 1426 uint32_t fail_index = 0; 1427 uint32_t physicalCount = 0; 1428 while (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1429 InitAllocTracker(9999, ++fail_index); 1430 ASSERT_LT(fail_index, 9999u); 1431 1432 result = vkCreateInstance(info, &alloc_callbacks, &instance); 1433 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1434 if (!IsAllocTrackerEmpty()) { 1435 std::cout << "Failed on index " << fail_index << '\n'; 1436 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1437 } 1438 FreeAllocTracker(); 1439 continue; 1440 } 1441 ASSERT_EQ(result, VK_SUCCESS); 1442 1443 physicalCount = 0; 1444 result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); 1445 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1446 vkDestroyInstance(instance, &alloc_callbacks); 1447 if (!IsAllocTrackerEmpty()) { 1448 std::cout << "Failed on index " << fail_index << '\n'; 1449 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1450 } 1451 FreeAllocTracker(); 1452 continue; 1453 } 1454 ASSERT_EQ(result, VK_SUCCESS); 1455 1456 std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); 1457 result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); 1458 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1459 vkDestroyInstance(instance, &alloc_callbacks); 1460 if (!IsAllocTrackerEmpty()) { 1461 std::cout << "Failed on index " << fail_index << '\n'; 1462 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1463 } 1464 FreeAllocTracker(); 1465 continue; 1466 } 1467 ASSERT_EQ(result, VK_SUCCESS); 1468 1469 uint32_t familyCount = 0; 1470 vkGetPhysicalDeviceQueueFamilyProperties(physical[0], &familyCount, nullptr); 1471 ASSERT_GT(familyCount, 0u); 1472 1473 std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]); 1474 vkGetPhysicalDeviceQueueFamilyProperties(physical[0], &familyCount, family.get()); 1475 ASSERT_GT(familyCount, 0u); 1476 1477 uint32_t queue_index = 0; 1478 for (uint32_t q = 0; q < familyCount; ++q) { 1479 if (family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1480 queue_index = q; 1481 break; 1482 } 1483 } 1484 1485 float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. 1486 VkDeviceQueueCreateInfo const queueInfo[1]{ 1487 VK::DeviceQueueCreateInfo().queueFamilyIndex(queue_index).queueCount(1).pQueuePriorities(priorities)}; 1488 1489 auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); 1490 1491 result = vkCreateDevice(physical[0], deviceInfo, &alloc_callbacks, &device); 1492 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 1493 vkDestroyInstance(instance, &alloc_callbacks); 1494 if (!IsAllocTrackerEmpty()) { 1495 std::cout << "Failed on index " << fail_index << '\n'; 1496 ASSERT_EQ(true, IsAllocTrackerEmpty()); 1497 } 1498 FreeAllocTracker(); 1499 continue; 1500 } 1501 vkDestroyDevice(device, &alloc_callbacks); 1502 vkDestroyInstance(instance, &alloc_callbacks); 1503 FreeAllocTracker(); 1504 } 1505 } 1506 1507 // Used by run_loader_tests.sh to test that calling vkEnumeratePhysicalDeviceGroupsKHX without first querying 1508 // the count, works. And, that it also returns only physical devices made available by the standard 1509 // enumerate call 1510 TEST(EnumeratePhysicalDeviceGroupsKHX, OneCall) { 1511 VkInstance instance = VK_NULL_HANDLE; 1512 char const *const names[] = {VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME}; 1513 auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names); 1514 uint32_t group; 1515 uint32_t dev; 1516 std::vector<std::pair<VkPhysicalDevice, bool>> phys_dev_normal_found; 1517 std::vector<std::pair<VkPhysicalDevice, bool>> phys_dev_group_found; 1518 1519 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 1520 if (result == VK_ERROR_EXTENSION_NOT_PRESENT) { 1521 // Extension isn't present, just skip this test 1522 ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); 1523 std::cout << "Skipping EnumeratePhysicalDeviceGroupsKHX : OneCall due to Instance lacking support" 1524 << " for " << VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME << " extension\n"; 1525 return; 1526 } 1527 1528 uint32_t phys_dev_count = 500; 1529 std::unique_ptr<VkPhysicalDevice[]> phys_devs(new VkPhysicalDevice[phys_dev_count]); 1530 result = vkEnumeratePhysicalDevices(instance, &phys_dev_count, phys_devs.get()); 1531 ASSERT_EQ(result, VK_SUCCESS); 1532 ASSERT_GT(phys_dev_count, 0u); 1533 1534 // Initialize the normal physical device boolean pair array 1535 for (dev = 0; dev < phys_dev_count; dev++) { 1536 phys_dev_normal_found.push_back(std::make_pair(phys_devs[dev], false)); 1537 } 1538 1539 // Get a pointer to the new vkEnumeratePhysicalDeviceGroupsKHX call 1540 PFN_vkEnumeratePhysicalDeviceGroupsKHX p_vkEnumeratePhysicalDeviceGroupsKHX = 1541 (PFN_vkEnumeratePhysicalDeviceGroupsKHX)vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHX"); 1542 1543 // Setup the group information in preparation for the call 1544 uint32_t group_count = 30; 1545 std::unique_ptr<VkPhysicalDeviceGroupPropertiesKHX[]> phys_dev_groups(new VkPhysicalDeviceGroupPropertiesKHX[group_count]); 1546 for (group = 0; group < group_count; group++) { 1547 phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX; 1548 phys_dev_groups[group].pNext = nullptr; 1549 phys_dev_groups[group].physicalDeviceCount = 0; 1550 memset(phys_dev_groups[group].physicalDevices, 0, sizeof(VkPhysicalDevice) * VK_MAX_DEVICE_GROUP_SIZE_KHX); 1551 phys_dev_groups[group].subsetAllocation = VK_FALSE; 1552 } 1553 1554 result = p_vkEnumeratePhysicalDeviceGroupsKHX(instance, &group_count, phys_dev_groups.get()); 1555 ASSERT_EQ(result, VK_SUCCESS); 1556 ASSERT_GT(group_count, 0u); 1557 1558 // Initialize the group physical device boolean pair array 1559 for (group = 0; group < group_count; group++) { 1560 for (dev = 0; dev < phys_dev_groups[group].physicalDeviceCount; dev++) { 1561 phys_dev_group_found.push_back(std::make_pair(phys_dev_groups[group].physicalDevices[dev], false)); 1562 } 1563 } 1564 1565 // Now, make sure we can find each normal and group item in the other list 1566 for (dev = 0; dev < phys_dev_count; dev++) { 1567 for (group = 0; group < phys_dev_group_found.size(); group++) { 1568 if (phys_dev_normal_found[dev].first == phys_dev_group_found[group].first) { 1569 phys_dev_normal_found[dev].second = true; 1570 phys_dev_group_found[group].second = true; 1571 break; 1572 } 1573 } 1574 } 1575 1576 for (dev = 0; dev < phys_dev_count; dev++) { 1577 ASSERT_EQ(phys_dev_normal_found[dev].second, true); 1578 } 1579 for (dev = 0; dev < phys_dev_group_found.size(); dev++) { 1580 ASSERT_EQ(phys_dev_group_found[dev].second, true); 1581 } 1582 1583 vkDestroyInstance(instance, nullptr); 1584 } 1585 1586 // Used by run_loader_tests.sh to test for the expected usage of the 1587 // vkEnumeratePhysicalDeviceGroupsKHX call in a two call fasion (once with NULL data 1588 // to get count, and then again with data). 1589 TEST(EnumeratePhysicalDeviceGroupsKHX, TwoCall) { 1590 VkInstance instance = VK_NULL_HANDLE; 1591 char const *const names[] = {VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME}; 1592 auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names); 1593 uint32_t group; 1594 uint32_t group_count; 1595 uint32_t dev; 1596 std::vector<std::pair<VkPhysicalDevice, bool>> phys_dev_normal_found; 1597 std::vector<std::pair<VkPhysicalDevice, bool>> phys_dev_group_found; 1598 1599 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 1600 if (result == VK_ERROR_EXTENSION_NOT_PRESENT) { 1601 // Extension isn't present, just skip this test 1602 ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); 1603 std::cout << "Skipping EnumeratePhysicalDeviceGroupsKHX : TwoCall due to Instance lacking support" 1604 << " for " << VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME << " extension\n"; 1605 return; 1606 } 1607 1608 // Get a pointer to the new vkEnumeratePhysicalDeviceGroupsKHX call 1609 PFN_vkEnumeratePhysicalDeviceGroupsKHX p_vkEnumeratePhysicalDeviceGroupsKHX = 1610 (PFN_vkEnumeratePhysicalDeviceGroupsKHX)vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHX"); 1611 1612 // Setup the group information in preparation for the call 1613 uint32_t array_group_count = 30; 1614 std::unique_ptr<VkPhysicalDeviceGroupPropertiesKHX[]> phys_dev_groups( 1615 new VkPhysicalDeviceGroupPropertiesKHX[array_group_count]); 1616 for (group = 0; group < array_group_count; group++) { 1617 phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX; 1618 phys_dev_groups[group].pNext = nullptr; 1619 phys_dev_groups[group].physicalDeviceCount = 0; 1620 memset(phys_dev_groups[group].physicalDevices, 0, sizeof(VkPhysicalDevice) * VK_MAX_DEVICE_GROUP_SIZE_KHX); 1621 phys_dev_groups[group].subsetAllocation = VK_FALSE; 1622 } 1623 1624 result = p_vkEnumeratePhysicalDeviceGroupsKHX(instance, &group_count, nullptr); 1625 ASSERT_EQ(result, VK_SUCCESS); 1626 ASSERT_GT(group_count, 0u); 1627 ASSERT_LT(group_count, array_group_count); 1628 1629 result = p_vkEnumeratePhysicalDeviceGroupsKHX(instance, &group_count, phys_dev_groups.get()); 1630 ASSERT_EQ(result, VK_SUCCESS); 1631 ASSERT_GT(group_count, 0u); 1632 ASSERT_LT(group_count, array_group_count); 1633 1634 // Initialize the group physical device boolean pair array 1635 for (group = 0; group < group_count; group++) { 1636 for (dev = 0; dev < phys_dev_groups[group].physicalDeviceCount; dev++) { 1637 phys_dev_group_found.push_back(std::make_pair(phys_dev_groups[group].physicalDevices[dev], false)); 1638 } 1639 } 1640 1641 uint32_t phys_dev_count = 500; 1642 std::unique_ptr<VkPhysicalDevice[]> phys_devs(new VkPhysicalDevice[phys_dev_count]); 1643 result = vkEnumeratePhysicalDevices(instance, &phys_dev_count, phys_devs.get()); 1644 ASSERT_EQ(result, VK_SUCCESS); 1645 ASSERT_GT(phys_dev_count, 0u); 1646 1647 // Initialize the normal physical device boolean pair array 1648 for (dev = 0; dev < phys_dev_count; dev++) { 1649 phys_dev_normal_found.push_back(std::make_pair(phys_devs[dev], false)); 1650 } 1651 1652 // Now, make sure we can find each normal and group item in the other list 1653 for (dev = 0; dev < phys_dev_count; dev++) { 1654 for (group = 0; group < phys_dev_group_found.size(); group++) { 1655 if (phys_dev_normal_found[dev].first == phys_dev_group_found[group].first) { 1656 phys_dev_normal_found[dev].second = true; 1657 phys_dev_group_found[group].second = true; 1658 break; 1659 } 1660 } 1661 } 1662 1663 for (dev = 0; dev < phys_dev_count; dev++) { 1664 ASSERT_EQ(phys_dev_normal_found[dev].second, true); 1665 } 1666 for (dev = 0; dev < phys_dev_group_found.size(); dev++) { 1667 ASSERT_EQ(phys_dev_group_found[dev].second, true); 1668 } 1669 1670 vkDestroyInstance(instance, nullptr); 1671 } 1672 1673 // Used by run_loader_tests.sh to test for the expected usage of the EnumeratePhysicalDeviceGroupsKHX 1674 // call if not enough numbers are provided for the final list. 1675 TEST(EnumeratePhysicalDeviceGroupsKHX, TwoCallIncomplete) { 1676 VkInstance instance = VK_NULL_HANDLE; 1677 char const *const names[] = {VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME}; 1678 auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names); 1679 uint32_t group; 1680 uint32_t group_count; 1681 1682 VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); 1683 if (result == VK_ERROR_EXTENSION_NOT_PRESENT) { 1684 // Extension isn't present, just skip this test 1685 ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); 1686 std::cout << "Skipping EnumeratePhysicalDeviceGroupsKHX : TwoCallIncomplete due to Instance lacking support" 1687 << " for " << VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME << " extension\n"; 1688 return; 1689 } 1690 1691 // Get a pointer to the new vkEnumeratePhysicalDeviceGroupsKHX call 1692 PFN_vkEnumeratePhysicalDeviceGroupsKHX p_vkEnumeratePhysicalDeviceGroupsKHX = 1693 (PFN_vkEnumeratePhysicalDeviceGroupsKHX)vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHX"); 1694 1695 // Setup the group information in preparation for the call 1696 uint32_t array_group_count = 30; 1697 std::unique_ptr<VkPhysicalDeviceGroupPropertiesKHX[]> phys_dev_groups( 1698 new VkPhysicalDeviceGroupPropertiesKHX[array_group_count]); 1699 for (group = 0; group < array_group_count; group++) { 1700 phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX; 1701 phys_dev_groups[group].pNext = nullptr; 1702 phys_dev_groups[group].physicalDeviceCount = 0; 1703 memset(phys_dev_groups[group].physicalDevices, 0, sizeof(VkPhysicalDevice) * VK_MAX_DEVICE_GROUP_SIZE_KHX); 1704 phys_dev_groups[group].subsetAllocation = VK_FALSE; 1705 } 1706 1707 result = p_vkEnumeratePhysicalDeviceGroupsKHX(instance, &group_count, nullptr); 1708 ASSERT_EQ(result, VK_SUCCESS); 1709 ASSERT_GT(group_count, 0u); 1710 ASSERT_LT(group_count, array_group_count); 1711 1712 group_count -= 1; 1713 1714 result = p_vkEnumeratePhysicalDeviceGroupsKHX(instance, &group_count, phys_dev_groups.get()); 1715 ASSERT_EQ(result, VK_INCOMPLETE); 1716 1717 vkDestroyInstance(instance, nullptr); 1718 } 1719 1720 int main(int argc, char **argv) { 1721 int result; 1722 1723 ::testing::InitGoogleTest(&argc, argv); 1724 1725 if (argc > 0) { 1726 CommandLine::Initialize(argc, argv); 1727 } 1728 1729 result = RUN_ALL_TESTS(); 1730 1731 return result; 1732 } 1733