2 * Copyright 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/prctl.h>
28 // #define ENABLE_ALLOC_CALLSTACKS 1
29 #if ENABLE_ALLOC_CALLSTACKS
30 #include <utils/CallStack.h>
31 #define ALOGD_CALLSTACK(...) \
34 android::CallStack callstack; \
36 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
39 #define ALOGD_CALLSTACK(...) \
49 class CreateInfoWrapper {
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);
61 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
62 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
64 explicit operator const VkInstanceCreateInfo*() const;
65 explicit operator const VkDeviceCreateInfo*() const;
68 struct ExtensionFilter {
69 VkExtensionProperties* exts;
76 VkResult SanitizePNext();
78 VkResult SanitizeLayers();
79 VkResult SanitizeExtensions();
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);
87 const bool is_instance_;
88 const VkAllocationCallbacks& allocator_;
91 const hwvulkan_device_t* hw_dev_;
92 VkPhysicalDevice physical_dev_;
96 VkInstanceCreateInfo instance_info_;
97 VkDeviceCreateInfo dev_info_;
100 ExtensionFilter extension_filter_;
102 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
103 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
106 CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
107 const VkInstanceCreateInfo& create_info,
108 const VkAllocationCallbacks& allocator)
109 : is_instance_(true),
110 allocator_(allocator),
112 instance_info_(create_info),
113 extension_filter_() {
114 hook_extensions_.set(ProcHook::EXTENSION_CORE);
115 hal_extensions_.set(ProcHook::EXTENSION_CORE);
118 CreateInfoWrapper::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);
130 CreateInfoWrapper::~CreateInfoWrapper() {
131 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
132 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
135 VkResult CreateInfoWrapper::Validate() {
136 VkResult result = SanitizePNext();
137 if (result == VK_SUCCESS)
138 result = SanitizeLayers();
139 if (result == VK_SUCCESS)
140 result = SanitizeExtensions();
145 const std::bitset<ProcHook::EXTENSION_COUNT>&
146 CreateInfoWrapper::GetHookExtensions() const {
147 return hook_extensions_;
150 const std::bitset<ProcHook::EXTENSION_COUNT>&
151 CreateInfoWrapper::GetHalExtensions() const {
152 return hal_extensions_;
155 CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
156 return &instance_info_;
159 CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
163 VkResult CreateInfoWrapper::SanitizePNext() {
164 const struct StructHeader {
165 VkStructureType type;
170 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
172 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
174 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
175 header = reinterpret_cast<const StructHeader*>(header->next);
177 instance_info_.pNext = header;
179 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
181 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
183 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
184 header = reinterpret_cast<const StructHeader*>(header->next);
186 dev_info_.pNext = header;
192 VkResult 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;
199 layer_names = nullptr;
205 VkResult 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;
213 VkResult result = InitExtensionFilter();
214 if (result != VK_SUCCESS)
217 for (uint32_t i = 0; i < ext_count; i++)
218 FilterExtension(ext_names[i]);
220 ext_names = extension_filter_.names;
221 ext_count = extension_filter_.name_count;
226 VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
228 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
231 const auto& driver = GetData(physical_dev_).driver;
232 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
237 VkResult CreateInfoWrapper::EnumerateExtensions(
239 VkExtensionProperties* props) const {
241 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
244 const auto& driver = GetData(physical_dev_).driver;
245 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
250 VkResult CreateInfoWrapper::InitExtensionFilter() {
251 // query extension count
253 VkResult result = QueryExtensionCount(count);
254 if (result != VK_SUCCESS || count == 0)
257 auto& filter = extension_filter_;
259 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
260 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
261 alignof(VkExtensionProperties),
262 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
264 return VK_ERROR_OUT_OF_HOST_MEMORY;
266 // enumerate extensions
267 result = EnumerateExtensions(count, filter.exts);
268 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
274 filter.ext_count = count;
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));
285 return VK_ERROR_OUT_OF_HOST_MEMORY;
290 void CreateInfoWrapper::FilterExtension(const char* name) {
291 auto& filter = extension_filter_;
293 ProcHook::Extension ext_bit = GetProcHookExtension(name);
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
301 case ProcHook::EXT_debug_report:
302 // both we and HAL can take part in
303 hook_extensions_.set(ext_bit);
305 case ProcHook::EXTENSION_UNKNOWN:
309 ALOGW("Ignored invalid instance extension %s", name);
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;
319 case ProcHook::EXTENSION_UNKNOWN:
323 ALOGW("Ignored invalid device extension %s", name);
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)
334 if (ext_bit == ProcHook::ANDROID_native_buffer)
335 hook_extensions_.set(ProcHook::KHR_swapchain);
337 filter.names[filter.name_count++] = name;
338 hal_extensions_.set(ext_bit);
344 const hwvulkan_device_t* g_hwdevice = nullptr;
346 VKAPI_ATTR void* DefaultAllocate(void*,
349 VkSystemAllocationScope) {
351 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
352 // additionally requires that it be at least sizeof(void*).
353 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
354 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
356 return ret == 0 ? ptr : nullptr;
359 VKAPI_ATTR void* DefaultReallocate(void*,
363 VkSystemAllocationScope) {
369 // TODO(jessehall): Right now we never shrink allocations; if the new
370 // request is smaller than the existing chunk, we just continue using it.
371 // Right now the loader never reallocs, so this doesn't matter. If that
372 // changes, or if this code is copied into some other project, this should
373 // probably have a heuristic to allocate-copy-free when doing so will save
375 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
376 if (size <= old_size)
379 void* new_ptr = nullptr;
380 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
383 memcpy(new_ptr, ptr, std::min(old_size, size));
389 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
390 ALOGD_CALLSTACK("Free: %p", ptr);
394 InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
395 void* data_mem = allocator.pfnAllocation(
396 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
397 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
401 return new (data_mem) InstanceData(allocator);
404 void FreeInstanceData(InstanceData* data,
405 const VkAllocationCallbacks& allocator) {
406 data->~InstanceData();
407 allocator.pfnFree(allocator.pUserData, data);
410 DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
411 void* data_mem = allocator.pfnAllocation(
412 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
413 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
417 return new (data_mem) DeviceData(allocator);
420 void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
422 allocator.pfnFree(allocator.pUserData, data);
425 } // anonymous namespace
428 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
432 ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
434 // Use a stub device unless we successfully open a real HAL device.
435 g_hwdevice = &stubhal::kDevice;
437 const hwvulkan_module_t* module;
439 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
441 ALOGV("no Vulkan HAL present, using stub HAL");
445 hwvulkan_device_t* device;
447 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
448 reinterpret_cast<hw_device_t**>(&device));
450 // Any device with a Vulkan HAL should be able to open the device.
451 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
461 const VkAllocationCallbacks& GetDefaultAllocator() {
462 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
463 .pUserData = nullptr,
464 .pfnAllocation = DefaultAllocate,
465 .pfnReallocation = DefaultReallocate,
466 .pfnFree = DefaultFree,
469 return kDefaultAllocCallbacks;
472 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
473 const ProcHook* hook = GetProcHook(pName);
475 return g_hwdevice->GetInstanceProcAddr(instance, pName);
478 if (hook->type == ProcHook::GLOBAL)
482 "Invalid use of vkGetInstanceProcAddr to query %s without an "
486 // Some naughty layers expect
488 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
491 return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
494 PFN_vkVoidFunction proc;
496 switch (hook->type) {
497 case ProcHook::INSTANCE:
498 proc = (GetData(instance).hook_extensions[hook->extension])
500 : hook->disabled_proc;
502 case ProcHook::DEVICE:
503 proc = (hook->extension == ProcHook::EXTENSION_CORE)
505 : hook->checked_proc;
509 "Invalid use of vkGetInstanceProcAddr to query %s with an "
519 PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
520 const ProcHook* hook = GetProcHook(pName);
522 return GetData(device).driver.GetDeviceProcAddr(device, pName);
524 if (hook->type != ProcHook::DEVICE) {
525 ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
529 return (GetData(device).hook_extensions[hook->extension])
531 : hook->disabled_proc;
534 VkResult EnumerateInstanceExtensionProperties(
535 const char* pLayerName,
536 uint32_t* pPropertyCount,
537 VkExtensionProperties* pProperties) {
538 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
540 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
541 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
542 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
545 // enumerate our extensions first
546 if (!pLayerName && pProperties) {
547 uint32_t count = std::min(
548 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
550 std::copy_n(loader_extensions.begin(), count, pProperties);
552 if (count < loader_extensions.size()) {
553 *pPropertyCount = count;
554 return VK_INCOMPLETE;
557 pProperties += count;
558 *pPropertyCount -= count;
561 VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
562 pLayerName, pPropertyCount, pProperties);
564 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
565 *pPropertyCount += loader_extensions.size();
570 VkResult EnumerateDeviceExtensionProperties(
571 VkPhysicalDevice physicalDevice,
572 const char* pLayerName,
573 uint32_t* pPropertyCount,
574 VkExtensionProperties* pProperties) {
575 const InstanceData& data = GetData(physicalDevice);
577 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
578 physicalDevice, pLayerName, pPropertyCount, pProperties);
579 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
585 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
586 for (uint32_t i = 0; i < *pPropertyCount; i++) {
587 auto& prop = pProperties[i];
589 if (strcmp(prop.extensionName,
590 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
593 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
594 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
595 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
601 VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
602 const VkAllocationCallbacks* pAllocator,
603 VkInstance* pInstance) {
604 const VkAllocationCallbacks& data_allocator =
605 (pAllocator) ? *pAllocator : GetDefaultAllocator();
607 CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
608 VkResult result = wrapper.Validate();
609 if (result != VK_SUCCESS)
612 InstanceData* data = AllocateInstanceData(data_allocator);
614 return VK_ERROR_OUT_OF_HOST_MEMORY;
616 data->hook_extensions |= wrapper.GetHookExtensions();
617 data->hal_extensions |= wrapper.GetHalExtensions();
619 // call into the driver
621 result = g_hwdevice->CreateInstance(
622 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
624 if (result != VK_SUCCESS) {
625 FreeInstanceData(data, data_allocator);
629 // initialize InstanceDriverTable
630 if (!SetData(instance, *data) ||
631 !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr)) {
632 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
633 g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
634 if (data->driver.DestroyInstance)
635 data->driver.DestroyInstance(instance, pAllocator);
637 FreeInstanceData(data, data_allocator);
639 return VK_ERROR_INCOMPATIBLE_DRIVER;
642 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
643 g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
644 if (!data->get_device_proc_addr) {
645 data->driver.DestroyInstance(instance, pAllocator);
646 FreeInstanceData(data, data_allocator);
648 return VK_ERROR_INCOMPATIBLE_DRIVER;
651 *pInstance = instance;
656 void DestroyInstance(VkInstance instance,
657 const VkAllocationCallbacks* pAllocator) {
658 InstanceData& data = GetData(instance);
659 data.driver.DestroyInstance(instance, pAllocator);
661 VkAllocationCallbacks local_allocator;
663 local_allocator = data.allocator;
664 pAllocator = &local_allocator;
667 FreeInstanceData(&data, *pAllocator);
670 VkResult CreateDevice(VkPhysicalDevice physicalDevice,
671 const VkDeviceCreateInfo* pCreateInfo,
672 const VkAllocationCallbacks* pAllocator,
674 const InstanceData& instance_data = GetData(physicalDevice);
675 const VkAllocationCallbacks& data_allocator =
676 (pAllocator) ? *pAllocator : instance_data.allocator;
678 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
679 VkResult result = wrapper.Validate();
680 if (result != VK_SUCCESS)
683 DeviceData* data = AllocateDeviceData(data_allocator);
685 return VK_ERROR_OUT_OF_HOST_MEMORY;
687 data->hook_extensions |= wrapper.GetHookExtensions();
688 data->hal_extensions |= wrapper.GetHalExtensions();
690 // call into the driver
692 result = instance_data.driver.CreateDevice(
693 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
695 if (result != VK_SUCCESS) {
696 FreeDeviceData(data, data_allocator);
700 // initialize DeviceDriverTable
701 if (!SetData(dev, *data) ||
702 !InitDriverTable(dev, instance_data.get_device_proc_addr)) {
703 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
704 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
705 if (data->driver.DestroyDevice)
706 data->driver.DestroyDevice(dev, pAllocator);
708 FreeDeviceData(data, data_allocator);
710 return VK_ERROR_INCOMPATIBLE_DRIVER;
718 void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
719 DeviceData& data = GetData(device);
720 data.driver.DestroyDevice(device, pAllocator);
722 VkAllocationCallbacks local_allocator;
724 local_allocator = data.allocator;
725 pAllocator = &local_allocator;
728 FreeDeviceData(&data, *pAllocator);
731 VkResult EnumeratePhysicalDevices(VkInstance instance,
732 uint32_t* pPhysicalDeviceCount,
733 VkPhysicalDevice* pPhysicalDevices) {
734 const auto& data = GetData(instance);
736 VkResult result = data.driver.EnumeratePhysicalDevices(
737 instance, pPhysicalDeviceCount, pPhysicalDevices);
738 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
739 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
740 SetData(pPhysicalDevices[i], data);
746 void GetDeviceQueue(VkDevice device,
747 uint32_t queueFamilyIndex,
750 const auto& data = GetData(device);
752 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
753 SetData(*pQueue, data);
757 AllocateCommandBuffers(VkDevice device,
758 const VkCommandBufferAllocateInfo* pAllocateInfo,
759 VkCommandBuffer* pCommandBuffers) {
760 const auto& data = GetData(device);
762 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
764 if (result == VK_SUCCESS) {
765 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
766 SetData(pCommandBuffers[i], data);
772 } // namespace driver
773 } // namespace vulkan