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