/* * Copyright © 2020 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "vk_device.h" #include "vk_common_entrypoints.h" #include "vk_instance.h" #include "vk_physical_device.h" #include "util/hash_table.h" #include "util/ralloc.h" VkResult vk_device_init(struct vk_device *device, struct vk_physical_device *physical_device, const struct vk_device_dispatch_table *dispatch_table, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *alloc) { memset(device, 0, sizeof(*device)); vk_object_base_init(device, &device->base, VK_OBJECT_TYPE_DEVICE); if (alloc != NULL) device->alloc = *alloc; else device->alloc = physical_device->instance->alloc; device->physical = physical_device; device->dispatch_table = *dispatch_table; /* Add common entrypoints without overwriting driver-provided ones. */ vk_device_dispatch_table_from_entrypoints( &device->dispatch_table, &vk_common_device_entrypoints, false); for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { int idx; for (idx = 0; idx < VK_DEVICE_EXTENSION_COUNT; idx++) { if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], vk_device_extensions[idx].extensionName) == 0) break; } if (idx >= VK_DEVICE_EXTENSION_COUNT) return VK_ERROR_EXTENSION_NOT_PRESENT; if (!physical_device->supported_extensions.extensions[idx]) return VK_ERROR_EXTENSION_NOT_PRESENT; #ifdef ANDROID if (!vk_android_allowed_device_extensions.extensions[idx]) return VK_ERROR_EXTENSION_NOT_PRESENT; #endif device->enabled_extensions.extensions[idx] = true; } p_atomic_set(&device->private_data_next_index, 0); #ifdef ANDROID mtx_init(&device->swapchain_private_mtx, mtx_plain); device->swapchain_private = NULL; #endif /* ANDROID */ return VK_SUCCESS; } void vk_device_finish(UNUSED struct vk_device *device) { #ifdef ANDROID if (device->swapchain_private) { hash_table_foreach(device->swapchain_private, entry) util_sparse_array_finish(entry->data); ralloc_free(device->swapchain_private); } #endif /* ANDROID */ vk_object_base_finish(&device->base); } PFN_vkVoidFunction vk_device_get_proc_addr(const struct vk_device *device, const char *name) { if (device == NULL || name == NULL) return NULL; struct vk_instance *instance = device->physical->instance; return vk_device_dispatch_table_get_if_supported(&device->dispatch_table, name, instance->app_info.api_version, &instance->enabled_extensions, &device->enabled_extensions); } VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_common_GetDeviceProcAddr(VkDevice _device, const char *pName) { VK_FROM_HANDLE(vk_device, device, _device); return vk_device_get_proc_addr(device, pName); } VKAPI_ATTR void VKAPI_CALL vk_common_GetDeviceQueue(VkDevice _device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { VK_FROM_HANDLE(vk_device, device, _device); const VkDeviceQueueInfo2 info = { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, .pNext = NULL, /* flags = 0 because (Vulkan spec 1.2.170 - vkGetDeviceQueue): * * "vkGetDeviceQueue must only be used to get queues that were * created with the flags parameter of VkDeviceQueueCreateInfo set * to zero. To get queues that were created with a non-zero flags * parameter use vkGetDeviceQueue2." */ .flags = 0, .queueFamilyIndex = queueFamilyIndex, .queueIndex = queueIndex, }; device->dispatch_table.GetDeviceQueue2(_device, &info, pQueue); } VKAPI_ATTR void VKAPI_CALL vk_common_GetBufferMemoryRequirements(VkDevice _device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) { VK_FROM_HANDLE(vk_device, device, _device); VkBufferMemoryRequirementsInfo2 info = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, .buffer = buffer, }; VkMemoryRequirements2 reqs = { .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, }; device->dispatch_table.GetBufferMemoryRequirements2(_device, &info, &reqs); *pMemoryRequirements = reqs.memoryRequirements; } VKAPI_ATTR VkResult VKAPI_CALL vk_common_BindBufferMemory(VkDevice _device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) { VK_FROM_HANDLE(vk_device, device, _device); VkBindBufferMemoryInfo bind = { .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, .buffer = buffer, .memory = memory, .memoryOffset = memoryOffset, }; return device->dispatch_table.BindBufferMemory2(_device, 1, &bind); } VKAPI_ATTR void VKAPI_CALL vk_common_GetImageMemoryRequirements(VkDevice _device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { VK_FROM_HANDLE(vk_device, device, _device); VkImageMemoryRequirementsInfo2 info = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, .image = image, }; VkMemoryRequirements2 reqs = { .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, }; device->dispatch_table.GetImageMemoryRequirements2(_device, &info, &reqs); *pMemoryRequirements = reqs.memoryRequirements; } VKAPI_ATTR VkResult VKAPI_CALL vk_common_BindImageMemory(VkDevice _device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) { VK_FROM_HANDLE(vk_device, device, _device); VkBindImageMemoryInfo bind = { .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, .image = image, .memory = memory, .memoryOffset = memoryOffset, }; return device->dispatch_table.BindImageMemory2(_device, 1, &bind); }