driver.cpp revision 31b2e4f01d31aae107340cbc4221b8d49fb42767
1/* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <string.h> 19#include <algorithm> 20#include <array> 21#include <new> 22#include <malloc.h> 23#include <sys/prctl.h> 24 25#include "driver.h" 26#include "stubhal.h" 27 28// #define ENABLE_ALLOC_CALLSTACKS 1 29#if ENABLE_ALLOC_CALLSTACKS 30#include <utils/CallStack.h> 31#define ALOGD_CALLSTACK(...) \ 32 do { \ 33 ALOGD(__VA_ARGS__); \ 34 android::CallStack callstack; \ 35 callstack.update(); \ 36 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \ 37 } while (false) 38#else 39#define ALOGD_CALLSTACK(...) \ 40 do { \ 41 } while (false) 42#endif 43 44namespace vulkan { 45namespace driver { 46 47namespace { 48 49class Hal { 50 public: 51 static bool Open(); 52 53 static const Hal& Get() { return hal_; } 54 static const hwvulkan_device_t& Device() { return *Get().dev_; } 55 56 private: 57 Hal() : dev_(nullptr) {} 58 Hal(const Hal&) = delete; 59 Hal& operator=(const Hal&) = delete; 60 61 static Hal hal_; 62 63 const hwvulkan_device_t* dev_; 64}; 65 66class CreateInfoWrapper { 67 public: 68 CreateInfoWrapper(const VkInstanceCreateInfo& create_info, 69 const VkAllocationCallbacks& allocator); 70 CreateInfoWrapper(VkPhysicalDevice physical_dev, 71 const VkDeviceCreateInfo& create_info, 72 const VkAllocationCallbacks& allocator); 73 ~CreateInfoWrapper(); 74 75 VkResult Validate(); 76 77 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const; 78 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const; 79 80 explicit operator const VkInstanceCreateInfo*() const; 81 explicit operator const VkDeviceCreateInfo*() const; 82 83 private: 84 struct ExtensionFilter { 85 VkExtensionProperties* exts; 86 uint32_t ext_count; 87 88 const char** names; 89 uint32_t name_count; 90 }; 91 92 VkResult SanitizePNext(); 93 94 VkResult SanitizeLayers(); 95 VkResult SanitizeExtensions(); 96 97 VkResult QueryExtensionCount(uint32_t& count) const; 98 VkResult EnumerateExtensions(uint32_t& count, 99 VkExtensionProperties* props) const; 100 VkResult InitExtensionFilter(); 101 void FilterExtension(const char* name); 102 103 const bool is_instance_; 104 const VkAllocationCallbacks& allocator_; 105 106 VkPhysicalDevice physical_dev_; 107 108 union { 109 VkInstanceCreateInfo instance_info_; 110 VkDeviceCreateInfo dev_info_; 111 }; 112 113 ExtensionFilter extension_filter_; 114 115 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_; 116 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_; 117}; 118 119Hal Hal::hal_; 120 121bool Hal::Open() { 122 ALOG_ASSERT(!dev_, "OpenHAL called more than once"); 123 124 // Use a stub device unless we successfully open a real HAL device. 125 hal_.dev_ = &stubhal::kDevice; 126 127 const hwvulkan_module_t* module; 128 int result = 129 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module)); 130 if (result != 0) { 131 ALOGI("no Vulkan HAL present, using stub HAL"); 132 return true; 133 } 134 135 hwvulkan_device_t* device; 136 result = 137 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0, 138 reinterpret_cast<hw_device_t**>(&device)); 139 if (result != 0) { 140 // Any device with a Vulkan HAL should be able to open the device. 141 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result), 142 result); 143 return false; 144 } 145 146 hal_.dev_ = device; 147 148 return true; 149} 150 151CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info, 152 const VkAllocationCallbacks& allocator) 153 : is_instance_(true), 154 allocator_(allocator), 155 physical_dev_(VK_NULL_HANDLE), 156 instance_info_(create_info), 157 extension_filter_() { 158 hook_extensions_.set(ProcHook::EXTENSION_CORE); 159 hal_extensions_.set(ProcHook::EXTENSION_CORE); 160} 161 162CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev, 163 const VkDeviceCreateInfo& create_info, 164 const VkAllocationCallbacks& allocator) 165 : is_instance_(false), 166 allocator_(allocator), 167 physical_dev_(physical_dev), 168 dev_info_(create_info), 169 extension_filter_() { 170 hook_extensions_.set(ProcHook::EXTENSION_CORE); 171 hal_extensions_.set(ProcHook::EXTENSION_CORE); 172} 173 174CreateInfoWrapper::~CreateInfoWrapper() { 175 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts); 176 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names); 177} 178 179VkResult CreateInfoWrapper::Validate() { 180 VkResult result = SanitizePNext(); 181 if (result == VK_SUCCESS) 182 result = SanitizeLayers(); 183 if (result == VK_SUCCESS) 184 result = SanitizeExtensions(); 185 186 return result; 187} 188 189const std::bitset<ProcHook::EXTENSION_COUNT>& 190CreateInfoWrapper::GetHookExtensions() const { 191 return hook_extensions_; 192} 193 194const std::bitset<ProcHook::EXTENSION_COUNT>& 195CreateInfoWrapper::GetHalExtensions() const { 196 return hal_extensions_; 197} 198 199CreateInfoWrapper::operator const VkInstanceCreateInfo*() const { 200 return &instance_info_; 201} 202 203CreateInfoWrapper::operator const VkDeviceCreateInfo*() const { 204 return &dev_info_; 205} 206 207VkResult CreateInfoWrapper::SanitizePNext() { 208 const struct StructHeader { 209 VkStructureType type; 210 const void* next; 211 } * header; 212 213 if (is_instance_) { 214 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext); 215 216 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs 217 while (header && 218 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO) 219 header = reinterpret_cast<const StructHeader*>(header->next); 220 221 instance_info_.pNext = header; 222 } else { 223 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext); 224 225 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs 226 while (header && 227 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO) 228 header = reinterpret_cast<const StructHeader*>(header->next); 229 230 dev_info_.pNext = header; 231 } 232 233 return VK_SUCCESS; 234} 235 236VkResult CreateInfoWrapper::SanitizeLayers() { 237 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames 238 : dev_info_.ppEnabledLayerNames; 239 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount 240 : dev_info_.enabledLayerCount; 241 242 // remove all layers 243 layer_names = nullptr; 244 layer_count = 0; 245 246 return VK_SUCCESS; 247} 248 249VkResult CreateInfoWrapper::SanitizeExtensions() { 250 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames 251 : dev_info_.ppEnabledExtensionNames; 252 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount 253 : dev_info_.enabledExtensionCount; 254 if (!ext_count) 255 return VK_SUCCESS; 256 257 VkResult result = InitExtensionFilter(); 258 if (result != VK_SUCCESS) 259 return result; 260 261 for (uint32_t i = 0; i < ext_count; i++) 262 FilterExtension(ext_names[i]); 263 264 ext_names = extension_filter_.names; 265 ext_count = extension_filter_.name_count; 266 267 return VK_SUCCESS; 268} 269 270VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const { 271 if (is_instance_) { 272 return Hal::Device().EnumerateInstanceExtensionProperties( 273 nullptr, &count, nullptr); 274 } else { 275 const auto& driver = GetData(physical_dev_).driver; 276 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr, 277 &count, nullptr); 278 } 279} 280 281VkResult CreateInfoWrapper::EnumerateExtensions( 282 uint32_t& count, 283 VkExtensionProperties* props) const { 284 if (is_instance_) { 285 return Hal::Device().EnumerateInstanceExtensionProperties( 286 nullptr, &count, props); 287 } else { 288 const auto& driver = GetData(physical_dev_).driver; 289 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr, 290 &count, props); 291 } 292} 293 294VkResult CreateInfoWrapper::InitExtensionFilter() { 295 // query extension count 296 uint32_t count; 297 VkResult result = QueryExtensionCount(count); 298 if (result != VK_SUCCESS || count == 0) 299 return result; 300 301 auto& filter = extension_filter_; 302 filter.exts = 303 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation( 304 allocator_.pUserData, sizeof(VkExtensionProperties) * count, 305 alignof(VkExtensionProperties), 306 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); 307 if (!filter.exts) 308 return VK_ERROR_OUT_OF_HOST_MEMORY; 309 310 // enumerate extensions 311 result = EnumerateExtensions(count, filter.exts); 312 if (result != VK_SUCCESS && result != VK_INCOMPLETE) 313 return result; 314 315 if (!count) 316 return VK_SUCCESS; 317 318 filter.ext_count = count; 319 320 // allocate name array 321 uint32_t enabled_ext_count = (is_instance_) 322 ? instance_info_.enabledExtensionCount 323 : dev_info_.enabledExtensionCount; 324 count = std::min(filter.ext_count, enabled_ext_count); 325 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation( 326 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*), 327 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); 328 if (!filter.names) 329 return VK_ERROR_OUT_OF_HOST_MEMORY; 330 331 return VK_SUCCESS; 332} 333 334void CreateInfoWrapper::FilterExtension(const char* name) { 335 auto& filter = extension_filter_; 336 337 ProcHook::Extension ext_bit = GetProcHookExtension(name); 338 if (is_instance_) { 339 switch (ext_bit) { 340 case ProcHook::KHR_android_surface: 341 case ProcHook::KHR_surface: 342 hook_extensions_.set(ext_bit); 343 // return now as these extensions do not require HAL support 344 return; 345 case ProcHook::EXT_debug_report: 346 // both we and HAL can take part in 347 hook_extensions_.set(ext_bit); 348 break; 349 case ProcHook::EXTENSION_UNKNOWN: 350 // HAL's extensions 351 break; 352 default: 353 ALOGW("Ignored invalid instance extension %s", name); 354 return; 355 } 356 } else { 357 switch (ext_bit) { 358 case ProcHook::KHR_swapchain: 359 // map VK_KHR_swapchain to VK_ANDROID_native_buffer 360 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME; 361 ext_bit = ProcHook::ANDROID_native_buffer; 362 break; 363 case ProcHook::EXTENSION_UNKNOWN: 364 // HAL's extensions 365 break; 366 default: 367 ALOGW("Ignored invalid device extension %s", name); 368 return; 369 } 370 } 371 372 for (uint32_t i = 0; i < filter.ext_count; i++) { 373 const VkExtensionProperties& props = filter.exts[i]; 374 // ignore unknown extensions 375 if (strcmp(name, props.extensionName) != 0) 376 continue; 377 378 filter.names[filter.name_count++] = name; 379 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) { 380 if (ext_bit == ProcHook::ANDROID_native_buffer) 381 hook_extensions_.set(ProcHook::KHR_swapchain); 382 383 hal_extensions_.set(ext_bit); 384 } 385 386 break; 387 } 388} 389 390VKAPI_ATTR void* DefaultAllocate(void*, 391 size_t size, 392 size_t alignment, 393 VkSystemAllocationScope) { 394 void* ptr = nullptr; 395 // Vulkan requires 'alignment' to be a power of two, but posix_memalign 396 // additionally requires that it be at least sizeof(void*). 397 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size); 398 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment, 399 ret, ptr); 400 return ret == 0 ? ptr : nullptr; 401} 402 403VKAPI_ATTR void* DefaultReallocate(void*, 404 void* ptr, 405 size_t size, 406 size_t alignment, 407 VkSystemAllocationScope) { 408 if (size == 0) { 409 free(ptr); 410 return nullptr; 411 } 412 413 // TODO(jessehall): Right now we never shrink allocations; if the new 414 // request is smaller than the existing chunk, we just continue using it. 415 // Right now the loader never reallocs, so this doesn't matter. If that 416 // changes, or if this code is copied into some other project, this should 417 // probably have a heuristic to allocate-copy-free when doing so will save 418 // "enough" space. 419 size_t old_size = ptr ? malloc_usable_size(ptr) : 0; 420 if (size <= old_size) 421 return ptr; 422 423 void* new_ptr = nullptr; 424 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0) 425 return nullptr; 426 if (ptr) { 427 memcpy(new_ptr, ptr, std::min(old_size, size)); 428 free(ptr); 429 } 430 return new_ptr; 431} 432 433VKAPI_ATTR void DefaultFree(void*, void* ptr) { 434 ALOGD_CALLSTACK("Free: %p", ptr); 435 free(ptr); 436} 437 438InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) { 439 void* data_mem = allocator.pfnAllocation( 440 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData), 441 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 442 if (!data_mem) 443 return nullptr; 444 445 return new (data_mem) InstanceData(allocator); 446} 447 448void FreeInstanceData(InstanceData* data, 449 const VkAllocationCallbacks& allocator) { 450 data->~InstanceData(); 451 allocator.pfnFree(allocator.pUserData, data); 452} 453 454DeviceData* AllocateDeviceData( 455 const VkAllocationCallbacks& allocator, 456 const DebugReportCallbackList& debug_report_callbacks) { 457 void* data_mem = allocator.pfnAllocation( 458 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData), 459 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 460 if (!data_mem) 461 return nullptr; 462 463 return new (data_mem) DeviceData(allocator, debug_report_callbacks); 464} 465 466void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) { 467 data->~DeviceData(); 468 allocator.pfnFree(allocator.pUserData, data); 469} 470 471} // anonymous namespace 472 473bool Debuggable() { 474 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0); 475} 476 477bool OpenHAL() { 478 return Hal::Open(); 479} 480 481const VkAllocationCallbacks& GetDefaultAllocator() { 482 static const VkAllocationCallbacks kDefaultAllocCallbacks = { 483 .pUserData = nullptr, 484 .pfnAllocation = DefaultAllocate, 485 .pfnReallocation = DefaultReallocate, 486 .pfnFree = DefaultFree, 487 }; 488 489 return kDefaultAllocCallbacks; 490} 491 492PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) { 493 const ProcHook* hook = GetProcHook(pName); 494 if (!hook) 495 return Hal::Device().GetInstanceProcAddr(instance, pName); 496 497 if (!instance) { 498 if (hook->type == ProcHook::GLOBAL) 499 return hook->proc; 500 501 // v0 layers expect 502 // 503 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice"); 504 // 505 // to work. 506 if (strcmp(pName, "vkCreateDevice") == 0) 507 return hook->proc; 508 509 ALOGE( 510 "internal vkGetInstanceProcAddr called for %s without an instance", 511 pName); 512 513 return nullptr; 514 } 515 516 PFN_vkVoidFunction proc; 517 518 switch (hook->type) { 519 case ProcHook::INSTANCE: 520 proc = (GetData(instance).hook_extensions[hook->extension]) 521 ? hook->proc 522 : nullptr; 523 break; 524 case ProcHook::DEVICE: 525 proc = (hook->extension == ProcHook::EXTENSION_CORE) 526 ? hook->proc 527 : hook->checked_proc; 528 break; 529 default: 530 ALOGE( 531 "internal vkGetInstanceProcAddr called for %s with an instance", 532 pName); 533 proc = nullptr; 534 break; 535 } 536 537 return proc; 538} 539 540PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) { 541 const ProcHook* hook = GetProcHook(pName); 542 if (!hook) 543 return GetData(device).driver.GetDeviceProcAddr(device, pName); 544 545 if (hook->type != ProcHook::DEVICE) { 546 ALOGE("internal vkGetDeviceProcAddr called for %s", pName); 547 return nullptr; 548 } 549 550 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc 551 : nullptr; 552} 553 554VkResult EnumerateInstanceExtensionProperties( 555 const char* pLayerName, 556 uint32_t* pPropertyCount, 557 VkExtensionProperties* pProperties) { 558 static const std::array<VkExtensionProperties, 2> loader_extensions = {{ 559 // WSI extensions 560 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION}, 561 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 562 VK_KHR_ANDROID_SURFACE_SPEC_VERSION}, 563 }}; 564 565 // enumerate our extensions first 566 if (!pLayerName && pProperties) { 567 uint32_t count = std::min( 568 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size())); 569 570 std::copy_n(loader_extensions.begin(), count, pProperties); 571 572 if (count < loader_extensions.size()) { 573 *pPropertyCount = count; 574 return VK_INCOMPLETE; 575 } 576 577 pProperties += count; 578 *pPropertyCount -= count; 579 } 580 581 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties( 582 pLayerName, pPropertyCount, pProperties); 583 584 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) 585 *pPropertyCount += loader_extensions.size(); 586 587 return result; 588} 589 590VkResult EnumerateDeviceExtensionProperties( 591 VkPhysicalDevice physicalDevice, 592 const char* pLayerName, 593 uint32_t* pPropertyCount, 594 VkExtensionProperties* pProperties) { 595 const InstanceData& data = GetData(physicalDevice); 596 597 VkResult result = data.driver.EnumerateDeviceExtensionProperties( 598 physicalDevice, pLayerName, pPropertyCount, pProperties); 599 if (result != VK_SUCCESS && result != VK_INCOMPLETE) 600 return result; 601 602 if (!pProperties) 603 return result; 604 605 // map VK_ANDROID_native_buffer to VK_KHR_swapchain 606 for (uint32_t i = 0; i < *pPropertyCount; i++) { 607 auto& prop = pProperties[i]; 608 609 if (strcmp(prop.extensionName, 610 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0) 611 continue; 612 613 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME, 614 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); 615 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION; 616 } 617 618 return result; 619} 620 621VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, 622 const VkAllocationCallbacks* pAllocator, 623 VkInstance* pInstance) { 624 const VkAllocationCallbacks& data_allocator = 625 (pAllocator) ? *pAllocator : GetDefaultAllocator(); 626 627 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator); 628 VkResult result = wrapper.Validate(); 629 if (result != VK_SUCCESS) 630 return result; 631 632 InstanceData* data = AllocateInstanceData(data_allocator); 633 if (!data) 634 return VK_ERROR_OUT_OF_HOST_MEMORY; 635 636 data->hook_extensions |= wrapper.GetHookExtensions(); 637 638 // call into the driver 639 VkInstance instance; 640 result = Hal::Device().CreateInstance( 641 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator, 642 &instance); 643 if (result != VK_SUCCESS) { 644 FreeInstanceData(data, data_allocator); 645 return result; 646 } 647 648 // initialize InstanceDriverTable 649 if (!SetData(instance, *data) || 650 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr, 651 wrapper.GetHalExtensions())) { 652 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>( 653 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance")); 654 if (data->driver.DestroyInstance) 655 data->driver.DestroyInstance(instance, pAllocator); 656 657 FreeInstanceData(data, data_allocator); 658 659 return VK_ERROR_INCOMPATIBLE_DRIVER; 660 } 661 662 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>( 663 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr")); 664 if (!data->get_device_proc_addr) { 665 data->driver.DestroyInstance(instance, pAllocator); 666 FreeInstanceData(data, data_allocator); 667 668 return VK_ERROR_INCOMPATIBLE_DRIVER; 669 } 670 671 *pInstance = instance; 672 673 return VK_SUCCESS; 674} 675 676void DestroyInstance(VkInstance instance, 677 const VkAllocationCallbacks* pAllocator) { 678 InstanceData& data = GetData(instance); 679 data.driver.DestroyInstance(instance, pAllocator); 680 681 VkAllocationCallbacks local_allocator; 682 if (!pAllocator) { 683 local_allocator = data.allocator; 684 pAllocator = &local_allocator; 685 } 686 687 FreeInstanceData(&data, *pAllocator); 688} 689 690VkResult CreateDevice(VkPhysicalDevice physicalDevice, 691 const VkDeviceCreateInfo* pCreateInfo, 692 const VkAllocationCallbacks* pAllocator, 693 VkDevice* pDevice) { 694 const InstanceData& instance_data = GetData(physicalDevice); 695 const VkAllocationCallbacks& data_allocator = 696 (pAllocator) ? *pAllocator : instance_data.allocator; 697 698 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator); 699 VkResult result = wrapper.Validate(); 700 if (result != VK_SUCCESS) 701 return result; 702 703 DeviceData* data = AllocateDeviceData(data_allocator, 704 instance_data.debug_report_callbacks); 705 if (!data) 706 return VK_ERROR_OUT_OF_HOST_MEMORY; 707 708 data->hook_extensions |= wrapper.GetHookExtensions(); 709 710 // call into the driver 711 VkDevice dev; 712 result = instance_data.driver.CreateDevice( 713 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper), 714 pAllocator, &dev); 715 if (result != VK_SUCCESS) { 716 FreeDeviceData(data, data_allocator); 717 return result; 718 } 719 720 // initialize DeviceDriverTable 721 if (!SetData(dev, *data) || 722 !InitDriverTable(dev, instance_data.get_device_proc_addr, 723 wrapper.GetHalExtensions())) { 724 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>( 725 instance_data.get_device_proc_addr(dev, "vkDestroyDevice")); 726 if (data->driver.DestroyDevice) 727 data->driver.DestroyDevice(dev, pAllocator); 728 729 FreeDeviceData(data, data_allocator); 730 731 return VK_ERROR_INCOMPATIBLE_DRIVER; 732 } 733 734 *pDevice = dev; 735 736 return VK_SUCCESS; 737} 738 739void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) { 740 DeviceData& data = GetData(device); 741 data.driver.DestroyDevice(device, pAllocator); 742 743 VkAllocationCallbacks local_allocator; 744 if (!pAllocator) { 745 local_allocator = data.allocator; 746 pAllocator = &local_allocator; 747 } 748 749 FreeDeviceData(&data, *pAllocator); 750} 751 752VkResult EnumeratePhysicalDevices(VkInstance instance, 753 uint32_t* pPhysicalDeviceCount, 754 VkPhysicalDevice* pPhysicalDevices) { 755 const auto& data = GetData(instance); 756 757 VkResult result = data.driver.EnumeratePhysicalDevices( 758 instance, pPhysicalDeviceCount, pPhysicalDevices); 759 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) { 760 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) 761 SetData(pPhysicalDevices[i], data); 762 } 763 764 return result; 765} 766 767void GetDeviceQueue(VkDevice device, 768 uint32_t queueFamilyIndex, 769 uint32_t queueIndex, 770 VkQueue* pQueue) { 771 const auto& data = GetData(device); 772 773 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 774 SetData(*pQueue, data); 775} 776 777VKAPI_ATTR VkResult 778AllocateCommandBuffers(VkDevice device, 779 const VkCommandBufferAllocateInfo* pAllocateInfo, 780 VkCommandBuffer* pCommandBuffers) { 781 const auto& data = GetData(device); 782 783 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo, 784 pCommandBuffers); 785 if (result == VK_SUCCESS) { 786 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) 787 SetData(pCommandBuffers[i], data); 788 } 789 790 return result; 791} 792 793} // namespace driver 794} // namespace vulkan 795