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