diff --git a/packages/mesa-vulkan-icd-wrapper/0001-fix-for-anon-file.patch b/packages/mesa-vulkan-icd-wrapper/0001-fix-for-anon-file.patch new file mode 100644 index 00000000000000..85e6a033df63ac --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/0001-fix-for-anon-file.patch @@ -0,0 +1,16 @@ +Fallback to `@TERMUX_PREFIX@/tmp` if env `XDG_RUNTIME_DIR` is not set. + +--- a/src/util/anon_file.c ++++ b/src/util/anon_file.c +@@ -136,6 +136,11 @@ + char *name; + + path = getenv("XDG_RUNTIME_DIR"); ++#ifdef __TERMUX__ ++ if (!path) { ++ path = "@TERMUX_PREFIX@/tmp"; ++ } ++#endif + if (!path) { + errno = ENOENT; + return -1; diff --git a/packages/mesa-vulkan-icd-wrapper/0002-wsi-no-pthread_cancel.patch b/packages/mesa-vulkan-icd-wrapper/0002-wsi-no-pthread_cancel.patch new file mode 100644 index 00000000000000..809bbb116022d9 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/0002-wsi-no-pthread_cancel.patch @@ -0,0 +1,88 @@ +diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c +index c91633e9bc4..4ce516d6276 100644 +--- a/src/vulkan/wsi/wsi_common_display.c ++++ b/src/vulkan/wsi/wsi_common_display.c +@@ -176,6 +176,12 @@ struct wsi_display_sync { + + static uint64_t fence_sequence; + ++#ifdef __TERMUX__ ++static void thread_signal_handler (int signum) { ++ pthread_exit (0); ++} ++#endif ++ + ICD_DEFINE_NONDISP_HANDLE_CASTS(wsi_display_mode, VkDisplayModeKHR) + ICD_DEFINE_NONDISP_HANDLE_CASTS(wsi_display_connector, VkDisplayKHR) + +@@ -1341,7 +1347,9 @@ wsi_display_wait_thread(void *data) + .events = POLLIN + }; + ++#ifndef __TERMUX__ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); ++#endif + for (;;) { + int ret = poll(&pollfd, 1, -1); + if (ret > 0) { +@@ -1369,9 +1377,22 @@ wsi_display_start_wait_thread(struct wsi_display *wsi) + static void + wsi_display_stop_wait_thread(struct wsi_display *wsi) + { ++#ifdef __TERMUX__ ++ struct sigaction actions; ++ memset (&actions, 0, sizeof (actions)); ++ sigemptyset (&actions.sa_mask); ++ actions.sa_flags = 0; ++ actions.sa_handler = thread_signal_handler; ++ sigaction (SIGUSR2, &actions, NULL); ++#endif ++ + mtx_lock(&wsi->wait_mutex); + if (wsi->wait_thread) { ++#ifndef __TERMUX__ + pthread_cancel(wsi->wait_thread); ++#else ++ pthread_kill(wsi->wait_thread, SIGUSR2); ++#endif + pthread_join(wsi->wait_thread, NULL); + wsi->wait_thread = 0; + } +@@ -2215,7 +2236,9 @@ udev_event_listener_thread(void *data) + + int udev_fd = udev_monitor_get_fd(mon); + ++#ifndef __TERMUX__ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); ++#endif + + for (;;) { + nfds_t nfds = 1; +@@ -2340,6 +2363,15 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device, + struct wsi_display *wsi = + (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; + ++#ifdef __TERMUX__ ++ struct sigaction actions; ++ memset (&actions, 0, sizeof (actions)); ++ sigemptyset (&actions.sa_mask); ++ actions.sa_flags = 0; ++ actions.sa_handler = thread_signal_handler; ++ sigaction (SIGUSR2, &actions, NULL); ++#endif ++ + if (wsi) { + wsi_for_each_connector(connector, wsi) { + wsi_for_each_display_mode(mode, connector) { +@@ -2351,7 +2383,11 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device, + wsi_display_stop_wait_thread(wsi); + + if (wsi->hotplug_thread) { ++#ifndef __TERMUX__ + pthread_cancel(wsi->hotplug_thread); ++#else ++ pthread_kill(wsi->hotplug_thread, SIGUSR2); ++#endif + pthread_join(wsi->hotplug_thread, NULL); + } + diff --git a/packages/mesa-vulkan-icd-wrapper/0003-Android-Vulkan-wrapper.patch b/packages/mesa-vulkan-icd-wrapper/0003-Android-Vulkan-wrapper.patch new file mode 100644 index 00000000000000..90b547c8e29628 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/0003-Android-Vulkan-wrapper.patch @@ -0,0 +1,158 @@ +From fc392d32760bc8f705e2299f4a5f817cd0bb04a7 Mon Sep 17 00:00:00 2001 +From: xMeM +Date: Sat, 26 Oct 2024 19:19:39 +0800 +Subject: [PATCH 1/2] Android Vulkan wrapper + +Wrap the Android Vulkan loader into ICD, using common WSI to provide X11 platform surface support. + +Signed-off-by: xMeM +--- + meson.build | 5 +++-- + meson_options.txt | 2 +- + src/android_stub/nativewindow_stub.cpp | 7 +++++++ + src/vulkan/meson.build | 5 ++++- + src/vulkan/wsi/wsi_common.c | 26 ++++++++++++++++++++++---- + src/vulkan/wsi/wsi_common.h | 2 ++ + 6 files changed, 39 insertions(+), 8 deletions(-) + +diff --git a/meson.build b/meson.build +index de9c9af53a1..b812f72e3b1 100644 +--- a/meson.build ++++ b/meson.build +@@ -250,6 +250,7 @@ elif _vulkan_drivers.contains('all') + 'nouveau', 'asahi', 'gfxstream-experimental'] + endif + ++with_wrapper_vk = _vulkan_drivers.contains('wrapper') + with_intel_vk = _vulkan_drivers.contains('intel') + with_intel_hasvk = _vulkan_drivers.contains('intel_hasvk') + with_amd_vk = _vulkan_drivers.contains('amd') +@@ -850,8 +851,8 @@ endif + pre_args += '-DGLAPI_EXPORT_PROTO_ENTRY_POINTS=@0@'.format(with_glapi_export_proto_entry_points.to_int()) + + with_android_stub = get_option('android-stub') +-if with_android_stub and not with_platform_android +- error('`-D android-stub=true` makes no sense without `-D platforms=android`') ++if with_wrapper_vk ++ with_android_stub = true + endif + + with_libbacktrace = get_option('android-libbacktrace') \ +diff --git a/meson_options.txt b/meson_options.txt +index 79ee65e6094..95049229682 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -214,7 +214,7 @@ option( + choices : ['auto', 'amd', 'broadcom', 'freedreno', 'intel', 'intel_hasvk', + 'panfrost', 'swrast', 'virtio', 'imagination-experimental', + 'microsoft-experimental', 'nouveau', 'asahi', +- 'gfxstream-experimental', 'all'], ++ 'gfxstream-experimental', 'wrapper', 'all'], + description : 'List of vulkan drivers to build. If this is set to auto ' + + 'all drivers applicable to the target OS/architecture ' + + 'will be built' +diff --git a/src/android_stub/nativewindow_stub.cpp b/src/android_stub/nativewindow_stub.cpp +index 9276a9c3d2e..4bd0cfe25ab 100644 +--- a/src/android_stub/nativewindow_stub.cpp ++++ b/src/android_stub/nativewindow_stub.cpp +@@ -43,6 +43,13 @@ AHardwareBuffer_getNativeHandle(const AHardwareBuffer *buffer) + return NULL; + } + ++int ++AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, ++ int socketFd) ++{ ++ return 0; ++} ++ + void + ANativeWindow_acquire(ANativeWindow *window) + { +diff --git a/src/vulkan/meson.build b/src/vulkan/meson.build +index b0bc67a8a4f..0b56cf00150 100644 +--- a/src/vulkan/meson.build ++++ b/src/vulkan/meson.build +@@ -62,7 +62,7 @@ if with_xlib_lease + vulkan_wsi_deps += [dep_xlib_xrandr] + vulkan_wsi_list += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT' + endif +-if with_platform_android ++if with_platform_android or with_wrapper_vk + vulkan_wsi_list += '-DVK_USE_PLATFORM_ANDROID_KHR' + endif + if with_platform_windows +@@ -95,3 +95,6 @@ endif + if with_vulkan_screenshot_layer + subdir('screenshot-layer') + endif ++if with_wrapper_vk ++ subdir('wrapper') ++endif +diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c +index 548bbc8c930..809f5726262 100644 +--- a/src/vulkan/wsi/wsi_common.c ++++ b/src/vulkan/wsi/wsi_common.c +@@ -203,6 +203,8 @@ wsi_device_init(struct wsi_device *wsi, + WSI_GET_CB(GetPhysicalDeviceFormatProperties2); + WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2); + WSI_GET_CB(GetSemaphoreFdKHR); ++ WSI_GET_CB(ImportSemaphoreFdKHR); ++ WSI_GET_CB(ImportFenceFdKHR); + WSI_GET_CB(ResetFences); + WSI_GET_CB(QueueSubmit); + WSI_GET_CB(WaitForFences); +@@ -1178,8 +1180,16 @@ wsi_signal_semaphore_for_image(struct vk_device *device, + const struct wsi_image *image, + VkSemaphore _semaphore) + { +- if (device->physical->supported_sync_types == NULL) +- return VK_SUCCESS; ++ if (device->physical->supported_sync_types == NULL) { ++ const VkImportSemaphoreFdInfoKHR import_fd_info = { ++ .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, ++ .semaphore = _semaphore, ++ .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, ++ .fd = -1, ++ .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, ++ }; ++ return chain->wsi->ImportSemaphoreFdKHR(chain->device, &import_fd_info); ++ } + + VK_FROM_HANDLE(vk_semaphore, semaphore, _semaphore); + +@@ -1214,8 +1224,16 @@ wsi_signal_fence_for_image(struct vk_device *device, + const struct wsi_image *image, + VkFence _fence) + { +- if (device->physical->supported_sync_types == NULL) +- return VK_SUCCESS; ++ if (device->physical->supported_sync_types == NULL) { ++ const VkImportFenceFdInfoKHR import_fd_info = { ++ .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, ++ .fence = _fence, ++ .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, ++ .fd = -1, ++ .flags = VK_FENCE_IMPORT_TEMPORARY_BIT, ++ }; ++ return chain->wsi->ImportFenceFdKHR(chain->device, &import_fd_info); ++ } + + VK_FROM_HANDLE(vk_fence, fence, _fence); + +diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h +index fee70909b70..5fda2a7e45f 100644 +--- a/src/vulkan/wsi/wsi_common.h ++++ b/src/vulkan/wsi/wsi_common.h +@@ -268,6 +268,8 @@ struct wsi_device { + WSI_CB(GetPhysicalDeviceFormatProperties2); + WSI_CB(GetPhysicalDeviceImageFormatProperties2); + WSI_CB(GetSemaphoreFdKHR); ++ WSI_CB(ImportSemaphoreFdKHR); ++ WSI_CB(ImportFenceFdKHR); + WSI_CB(ResetFences); + WSI_CB(QueueSubmit); + WSI_CB(WaitForFences); +-- +2.47.1 + diff --git a/packages/mesa-vulkan-icd-wrapper/0004-vulkan-x11-termux-x11-dri3-support.patch b/packages/mesa-vulkan-icd-wrapper/0004-vulkan-x11-termux-x11-dri3-support.patch new file mode 100644 index 00000000000000..8dc1bb773116a5 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/0004-vulkan-x11-termux-x11-dri3-support.patch @@ -0,0 +1,665 @@ +From 767d74b47b1c70733f46ea8a7b1cd4b47b2b8e09 Mon Sep 17 00:00:00 2001 +From: xMeM +Date: Tue, 10 Dec 2024 11:48:12 +0800 +Subject: [PATCH 2/2] vulkan/x11: termux-x11 dri3 support + +Signed-off-by: xMeM +--- + src/vulkan/wsi/meson.build | 4 + + src/vulkan/wsi/wsi_common.c | 40 +- + src/vulkan/wsi/wsi_common.h | 7 + + src/vulkan/wsi/wsi_common_ahardware_buffer.c | 365 +++++++++++++++++++ + src/vulkan/wsi/wsi_common_private.h | 19 + + src/vulkan/wsi/wsi_common_x11.c | 33 ++ + 6 files changed, 467 insertions(+), 1 deletion(-) + create mode 100644 src/vulkan/wsi/wsi_common_ahardware_buffer.c + +diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build +index 6933eb780c4..61e9f1ab300 100644 +--- a/src/vulkan/wsi/meson.build ++++ b/src/vulkan/wsi/meson.build +@@ -9,6 +9,10 @@ if dep_libdrm.found() + files_vulkan_wsi += files('wsi_common_drm.c') + endif + ++if with_wrapper_vk ++ files_vulkan_wsi += files('wsi_common_ahardware_buffer.c') ++endif ++ + if with_platform_x11 + files_vulkan_wsi += files('wsi_common_x11.c') + endif +diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c +index 809f5726262..6a32a940c33 100644 +--- a/src/vulkan/wsi/wsi_common.c ++++ b/src/vulkan/wsi/wsi_common.c +@@ -47,6 +47,10 @@ + #include + #endif + ++#ifdef __TERMUX__ ++#include ++#endif ++ + uint64_t WSI_DEBUG; + + static const struct debug_control debug_control[] = { +@@ -56,6 +60,7 @@ static const struct debug_control debug_control[] = { + { "linear", WSI_DEBUG_LINEAR }, + { "dxgi", WSI_DEBUG_DXGI }, + { "nowlts", WSI_DEBUG_NOWLTS }, ++ { "blit", WSI_DEBUG_BLIT }, + { NULL, }, + }; + +@@ -88,6 +93,7 @@ wsi_device_init(struct wsi_device *wsi, + wsi->wants_linear = (WSI_DEBUG & WSI_DEBUG_LINEAR) != 0; + wsi->x11.extra_xwayland_image = device_options->extra_xwayland_image; + wsi->wayland.disable_timestamps = (WSI_DEBUG & WSI_DEBUG_NOWLTS) != 0; ++ wsi->needs_blit = (WSI_DEBUG & WSI_DEBUG_BLIT) != 0; + #define WSI_GET_CB(func) \ + PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) + WSI_GET_CB(GetPhysicalDeviceExternalSemaphoreProperties); +@@ -101,12 +107,19 @@ wsi_device_init(struct wsi_device *wsi, + wsi->pci_bus_info.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT; + wsi->pci_bus_info.pNext = &wsi->drm_info; ++ VkPhysicalDeviceDriverProperties pddp = { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, ++ .pNext = &wsi->pci_bus_info, ++ }; + VkPhysicalDeviceProperties2 pdp2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, +- .pNext = &wsi->pci_bus_info, ++ .pNext = &pddp, + }; + GetPhysicalDeviceProperties2(pdevice, &pdp2); + ++ if (pddp.driverID == VK_DRIVER_ID_ARM_PROPRIETARY) ++ wsi->needs_blit = true; ++ + wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D; + assert(pdp2.properties.limits.optimalBufferCopyRowPitchAlignment <= UINT32_MAX); + wsi->optimalBufferCopyRowPitchAlignment = +@@ -212,6 +225,10 @@ wsi_device_init(struct wsi_device *wsi, + WSI_GET_CB(UnmapMemory); + if (wsi->khr_present_wait) + WSI_GET_CB(WaitSemaphores); ++#ifdef __TERMUX__ ++ WSI_GET_CB(GetMemoryAndroidHardwareBufferANDROID); ++ WSI_GET_CB(GetAndroidHardwareBufferPropertiesANDROID); ++#endif + #undef WSI_GET_CB + + #if defined(VK_USE_PLATFORM_XCB_KHR) +@@ -377,6 +394,11 @@ get_blit_type(const struct wsi_device *wsi, + return wsi_cpu_image_needs_buffer_blit(wsi, cpu_params) ? + WSI_SWAPCHAIN_BUFFER_BLIT : WSI_SWAPCHAIN_NO_BLIT; + } ++#ifdef __TERMUX__ ++ case WSI_IMAGE_TYPE_AHB: { ++ return wsi_get_ahardware_buffer_blit_type(wsi, params, device); ++ } ++#endif + #ifdef HAVE_LIBDRM + case WSI_IMAGE_TYPE_DRM: { + const struct wsi_drm_image_params *drm_params = +@@ -410,6 +432,11 @@ configure_image(const struct wsi_swapchain *chain, + container_of(params, const struct wsi_cpu_image_params, base); + return wsi_configure_cpu_image(chain, pCreateInfo, cpu_params, info); + } ++#ifdef __TERMUX__ ++ case WSI_IMAGE_TYPE_AHB: { ++ return wsi_configure_ahardware_buffer_image(chain, pCreateInfo, params, info); ++ } ++#endif + #ifdef HAVE_LIBDRM + case WSI_IMAGE_TYPE_DRM: { + const struct wsi_drm_image_params *drm_params = +@@ -709,6 +736,12 @@ wsi_destroy_image_info(const struct wsi_swapchain *chain, + vk_free(&chain->alloc, info->modifier_props); + info->modifier_props = NULL; + } ++#ifdef __TERMUX__ ++ if (info->ahardware_buffer_desc != NULL) { ++ vk_free(&chain->alloc, info->ahardware_buffer_desc); ++ info->ahardware_buffer_desc = NULL; ++ } ++#endif + } + + VkResult +@@ -771,6 +804,11 @@ wsi_destroy_image(const struct wsi_swapchain *chain, + { + const struct wsi_device *wsi = chain->wsi; + ++#ifdef __TERMUX__ ++ if (image->ahardware_buffer) ++ AHardwareBuffer_release(image->ahardware_buffer); ++#endif ++ + #ifndef _WIN32 + if (image->dma_buf_fd >= 0) + close(image->dma_buf_fd); +diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h +index 5fda2a7e45f..2c0626761d7 100644 +--- a/src/vulkan/wsi/wsi_common.h ++++ b/src/vulkan/wsi/wsi_common.h +@@ -179,6 +179,9 @@ struct wsi_device { + + bool sw; + ++ bool wants_ahardware_buffer; ++ bool needs_blit; ++ + /* Set to true if the implementation is ok with linear WSI images. */ + bool wants_linear; + +@@ -276,6 +279,10 @@ struct wsi_device { + WSI_CB(MapMemory); + WSI_CB(UnmapMemory); + WSI_CB(WaitSemaphores); ++#ifdef __TERMUX__ ++ WSI_CB(GetMemoryAndroidHardwareBufferANDROID); ++ WSI_CB(GetAndroidHardwareBufferPropertiesANDROID); ++#endif + #undef WSI_CB + + struct wsi_interface * wsi[VK_ICD_WSI_PLATFORM_MAX]; +diff --git a/src/vulkan/wsi/wsi_common_ahardware_buffer.c b/src/vulkan/wsi/wsi_common_ahardware_buffer.c +new file mode 100644 +index 00000000000..1b3c4253134 +--- /dev/null ++++ b/src/vulkan/wsi/wsi_common_ahardware_buffer.c +@@ -0,0 +1,365 @@ ++#include "wsi_common.h" ++#include "wsi_common_private.h" ++ ++#include ++ ++#define AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM 5 ++ ++enum wsi_swapchain_blit_type ++wsi_get_ahardware_buffer_blit_type(const struct wsi_device *wsi, ++ const struct wsi_base_image_params *params, ++ VkDevice device) ++{ ++ AHardwareBuffer *ahardware_buffer; ++ VkResult result; ++ ++ if (wsi->needs_blit) ++ return WSI_SWAPCHAIN_IMAGE_BLIT; ++ ++ if (AHardwareBuffer_allocate(&(AHardwareBuffer_Desc){ ++ .width = 500, ++ .height = 500, ++ .layers = 1, ++ .format = AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM, ++ .usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | ++ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | ++ AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | ++ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN }, ++ &ahardware_buffer) != 0) ++ return WSI_SWAPCHAIN_IMAGE_BLIT; ++ ++ VkAndroidHardwareBufferFormatPropertiesANDROID ahardware_buffer_format_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, ++ .pNext = NULL, ++ }; ++ VkAndroidHardwareBufferPropertiesANDROID ahardware_buffer_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, ++ .pNext = &ahardware_buffer_format_props, ++ }; ++ result = wsi->GetAndroidHardwareBufferPropertiesANDROID( ++ device, ahardware_buffer, &ahardware_buffer_props); ++ ++ AHardwareBuffer_release(ahardware_buffer); ++ ++ if (result != VK_SUCCESS) ++ return WSI_SWAPCHAIN_IMAGE_BLIT; ++ ++ VkPhysicalDeviceExternalImageFormatInfo external_format_info = { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, ++ .pNext = NULL, ++ .handleType = ++ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, ++ }; ++ VkPhysicalDeviceImageFormatInfo2 format_info = { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, ++ .pNext = &external_format_info, ++ .format = ahardware_buffer_format_props.format, ++ .type = VK_IMAGE_TYPE_2D, ++ .tiling = VK_IMAGE_TILING_OPTIMAL, ++ .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ++ VK_IMAGE_USAGE_SAMPLED_BIT, ++ .flags = 0u, ++ }; ++ VkExternalImageFormatProperties external_format_props = { ++ .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, ++ .pNext = NULL, ++ }; ++ VkImageFormatProperties2 format_props = { ++ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, ++ .pNext = &external_format_props, ++ }; ++ result = wsi->GetPhysicalDeviceImageFormatProperties2( ++ wsi->pdevice, &format_info, &format_props); ++ if (result != VK_SUCCESS) ++ return WSI_SWAPCHAIN_IMAGE_BLIT; ++ ++ if (!(external_format_props.externalMemoryProperties.externalMemoryFeatures ++ & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) ++ return WSI_SWAPCHAIN_IMAGE_BLIT; ++ ++ return WSI_SWAPCHAIN_NO_BLIT; ++} ++ ++static VkResult ++wsi_create_ahardware_buffer_image_mem(const struct wsi_swapchain *chain, ++ const struct wsi_image_info *info, ++ struct wsi_image *image) ++{ ++ const struct wsi_device *wsi = chain->wsi; ++ VkImage old_image = image->image; ++ VkResult result; ++ ++ if (AHardwareBuffer_allocate(info->ahardware_buffer_desc, ++ &image->ahardware_buffer) != 0) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ ++ VkAndroidHardwareBufferFormatPropertiesANDROID ahardware_buffer_format_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, ++ .pNext = NULL, ++ }; ++ VkAndroidHardwareBufferPropertiesANDROID ahardware_buffer_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, ++ .pNext = &ahardware_buffer_format_props, ++ }; ++ result = wsi->GetAndroidHardwareBufferPropertiesANDROID( ++ chain->device, image->ahardware_buffer, &ahardware_buffer_props); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ VkImageCreateInfo new_image_create_info = info->create; ++ if (ahardware_buffer_format_props.externalFormat) ++ new_image_create_info.flags &= ++ ~VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; ++ new_image_create_info.format = ahardware_buffer_format_props.format; ++ ++ result = wsi->CreateImage(chain->device, ++ &new_image_create_info, ++ &chain->alloc, &image->image); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ wsi->DestroyImage(chain->device, old_image, &chain->alloc); ++ ++ const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, ++ .image = image->image, ++ .buffer = VK_NULL_HANDLE, ++ }; ++ VkImportAndroidHardwareBufferInfoANDROID import_ahardware_buffer_info = { ++ .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, ++ .pNext = &memory_dedicated_info, ++ .buffer = image->ahardware_buffer, ++ }; ++ VkMemoryAllocateInfo memory_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, ++ .pNext = &import_ahardware_buffer_info, ++ .allocationSize = ahardware_buffer_props.allocationSize, ++ .memoryTypeIndex = ++ wsi_select_device_memory_type(wsi, ahardware_buffer_props.memoryTypeBits), ++ }; ++ ++ result = wsi->AllocateMemory(chain->device, &memory_info, ++ &chain->alloc, &image->memory); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ image->num_planes = 1; ++ image->drm_modifier = 1255; ++ ++ return VK_SUCCESS; ++} ++ ++static VkResult ++wsi_create_ahardware_buffer_blit_context(const struct wsi_swapchain *chain, ++ const struct wsi_image_info *info, ++ struct wsi_image *image) ++{ ++ assert(chain->blit.type == WSI_SWAPCHAIN_IMAGE_BLIT); ++ const struct wsi_device *wsi = chain->wsi; ++ VkResult result; ++ ++ const VkExternalMemoryHandleTypeFlags handle_types = ++ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; ++ ++ if (AHardwareBuffer_allocate(info->ahardware_buffer_desc, ++ &image->ahardware_buffer) != 0) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ ++ VkAndroidHardwareBufferFormatPropertiesANDROID ahardware_buffer_format_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, ++ .pNext = NULL, ++ }; ++ VkAndroidHardwareBufferPropertiesANDROID ahardware_buffer_props = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, ++ .pNext = &ahardware_buffer_format_props, ++ }; ++ result = wsi->GetAndroidHardwareBufferPropertiesANDROID( ++ chain->device, image->ahardware_buffer, &ahardware_buffer_props); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ const VkExternalFormatANDROID external_format = { ++ .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, ++ .externalFormat = ahardware_buffer_format_props.externalFormat, ++ }; ++ const VkExternalMemoryImageCreateInfo external_memory_info = { ++ .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, ++ .pNext = &external_format, ++ .handleTypes = handle_types, ++ }; ++ const VkImageCreateInfo image_info = { ++ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, ++ .pNext = &external_memory_info, ++ .flags = 0u, ++ .extent = info->create.extent, ++ .format = ahardware_buffer_format_props.format, ++ .imageType = VK_IMAGE_TYPE_2D, ++ .mipLevels = 1, ++ .arrayLayers = 1, ++ .samples = VK_SAMPLE_COUNT_1_BIT, ++ .tiling = VK_IMAGE_TILING_LINEAR, ++ .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, ++ .sharingMode = VK_SHARING_MODE_EXCLUSIVE, ++ .queueFamilyIndexCount = ++ info->create.queueFamilyIndexCount, ++ .pQueueFamilyIndices = ++ info->create.pQueueFamilyIndices, ++ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, ++ }; ++ result = wsi->CreateImage(chain->device, &image_info, ++ &chain->alloc, &image->blit.image); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ VkMemoryDedicatedAllocateInfo blit_mem_dedicated_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, ++ .pNext = NULL, ++ .image = image->blit.image, ++ .buffer = VK_NULL_HANDLE, ++ }; ++ VkImportAndroidHardwareBufferInfoANDROID import_ahardware_buffer_info = { ++ .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, ++ .pNext = &blit_mem_dedicated_info, ++ .buffer = image->ahardware_buffer, ++ }; ++ VkMemoryAllocateInfo blit_mem_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, ++ .pNext = &import_ahardware_buffer_info, ++ .allocationSize = ahardware_buffer_props.allocationSize, ++ .memoryTypeIndex = ++ wsi_select_device_memory_type( ++ wsi, ahardware_buffer_props.memoryTypeBits), ++ }; ++ ++ result = wsi->AllocateMemory(chain->device, &blit_mem_info, ++ &chain->alloc, &image->blit.memory); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ result = wsi->BindImageMemory(chain->device, image->blit.image, ++ image->blit.memory, 0); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ VkMemoryRequirements reqs; ++ wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); ++ ++ const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, ++ .image = image->image, ++ }; ++ const VkMemoryAllocateInfo memory_info = { ++ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, ++ .pNext = &memory_dedicated_info, ++ .allocationSize = reqs.size, ++ .memoryTypeIndex = ++ wsi_select_device_memory_type(wsi, reqs.memoryTypeBits), ++ }; ++ ++ result = wsi->AllocateMemory(chain->device, &memory_info, ++ &chain->alloc, &image->memory); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ image->num_planes = 1; ++ image->drm_modifier = 1255; ++ ++ return VK_SUCCESS; ++} ++ ++inline static uint32_t ++to_ahardware_buffer_format(VkFormat format) { ++ switch (format) { ++ case VK_FORMAT_B8G8R8A8_SRGB: ++ case VK_FORMAT_B8G8R8A8_UNORM: ++ return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM; ++ case VK_FORMAT_R5G6B5_UNORM_PACK16: ++ return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; ++ case VK_FORMAT_A2R10G10B10_UNORM_PACK32: ++ return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; ++ default: ++ unreachable("unsupported format"); ++ } ++} ++ ++VkResult ++wsi_configure_ahardware_buffer_image( ++ const struct wsi_swapchain *chain, ++ const VkSwapchainCreateInfoKHR *pCreateInfo, ++ const struct wsi_base_image_params *params, ++ struct wsi_image_info *info) ++{ ++ assert(params->image_type == WSI_IMAGE_TYPE_AHB); ++ assert(chain->blit.type == WSI_SWAPCHAIN_NO_BLIT || ++ chain->blit.type == WSI_SWAPCHAIN_IMAGE_BLIT); ++ ++ const bool blit = chain->blit.type == WSI_SWAPCHAIN_IMAGE_BLIT; ++ VkResult result; ++ ++ VkExternalMemoryHandleTypeFlags handle_type = ++ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; ++ ++ result = wsi_configure_image(chain, pCreateInfo, ++ blit ? 0 : handle_type, info); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ VkPhysicalDeviceExternalImageFormatInfo external_format_info = { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, ++ .pNext = NULL, ++ .handleType = handle_type, ++ }; ++ VkPhysicalDeviceImageFormatInfo2 format_info = { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, ++ .pNext = &external_format_info, ++ .format = blit ? VK_FORMAT_R8G8B8A8_UNORM ++ : info->create.format, ++ .type = VK_IMAGE_TYPE_2D, ++ .tiling = blit ? VK_IMAGE_TILING_LINEAR ++ : info->create.tiling, ++ .usage = blit ? VK_IMAGE_USAGE_TRANSFER_DST_BIT ++ : info->create.usage, ++ .flags = blit ? 0u : info->create.flags, ++ }; ++ VkAndroidHardwareBufferUsageANDROID ahardware_buffer_usage = { ++ .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID, ++ .pNext = NULL, ++ }; ++ VkImageFormatProperties2 format_props = { ++ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, ++ .pNext = &ahardware_buffer_usage, ++ }; ++ result = chain->wsi->GetPhysicalDeviceImageFormatProperties2( ++ chain->wsi->pdevice, &format_info, &format_props); ++ if (result != VK_SUCCESS) ++ return result; ++ ++ info->ahardware_buffer_desc = vk_zalloc(&chain->alloc, ++ sizeof(AHardwareBuffer_Desc), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); ++ if (!info->ahardware_buffer_desc) { ++ wsi_destroy_image_info(chain, info); ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ } ++ ++ *info->ahardware_buffer_desc = (AHardwareBuffer_Desc) { ++ .width = pCreateInfo->imageExtent.width, ++ .height = pCreateInfo->imageExtent.height, ++ .layers = pCreateInfo->imageArrayLayers, ++ .format = blit ++ ? AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM ++ : to_ahardware_buffer_format(info->create.format), ++ .usage = ahardware_buffer_usage.androidHardwareBufferUsage | ++ AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | ++ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, ++ }; ++ ++ if (blit) { ++ wsi_configure_image_blit_image(chain, info); ++ info->create_mem = wsi_create_ahardware_buffer_blit_context; ++ } else { ++ info->create_mem = wsi_create_ahardware_buffer_image_mem; ++ } ++ ++ return VK_SUCCESS; ++} ++ +diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h +index 8d4c2072003..e52acdf99dd 100644 +--- a/src/vulkan/wsi/wsi_common_private.h ++++ b/src/vulkan/wsi/wsi_common_private.h +@@ -41,6 +41,7 @@ struct wsi_swapchain; + #define WSI_DEBUG_LINEAR (1ull << 3) + #define WSI_DEBUG_DXGI (1ull << 4) + #define WSI_DEBUG_NOWLTS (1ull << 5) ++#define WSI_DEBUG_BLIT (1ull << 8) + + extern uint64_t WSI_DEBUG; + +@@ -48,6 +49,7 @@ enum wsi_image_type { + WSI_IMAGE_TYPE_CPU, + WSI_IMAGE_TYPE_DRM, + WSI_IMAGE_TYPE_DXGI, ++ WSI_IMAGE_TYPE_AHB, + }; + + struct wsi_base_image_params { +@@ -85,6 +87,9 @@ struct wsi_image_info { + VkExternalMemoryImageCreateInfo ext_mem; + VkImageFormatListCreateInfo format_list; + VkImageDrmFormatModifierListCreateInfoEXT drm_mod_list; ++#ifdef __TERMUX__ ++ struct AHardwareBuffer_Desc *ahardware_buffer_desc; ++#endif + + enum wsi_image_type image_type; + bool explicit_sync; +@@ -166,6 +171,9 @@ struct wsi_image { + int dma_buf_fd; + #endif + void *cpu_map; ++#ifdef __TERMUX__ ++ struct AHardwareBuffer *ahardware_buffer; ++#endif + }; + + struct wsi_swapchain { +@@ -447,6 +455,17 @@ void wsi_headless_finish_wsi(struct wsi_device *wsi_device, + VK_DEFINE_NONDISP_HANDLE_CASTS(wsi_swapchain, base, VkSwapchainKHR, + VK_OBJECT_TYPE_SWAPCHAIN_KHR) + ++enum wsi_swapchain_blit_type ++wsi_get_ahardware_buffer_blit_type(const struct wsi_device *wsi, ++ const struct wsi_base_image_params *params, ++ VkDevice device); ++ ++VkResult wsi_configure_ahardware_buffer_image( ++ const struct wsi_swapchain *chain, ++ const VkSwapchainCreateInfoKHR *pCreateInfo, ++ const struct wsi_base_image_params *params, ++ struct wsi_image_info *info); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c +index 03980b8d583..4a1d6d5609d 100644 +--- a/src/vulkan/wsi/wsi_common_x11.c ++++ b/src/vulkan/wsi/wsi_common_x11.c +@@ -69,6 +69,11 @@ + #include + #endif + ++#ifdef __TERMUX__ ++#include ++#include ++#endif ++ + #ifndef XCB_PRESENT_OPTION_ASYNC_MAY_TEAR + #define XCB_PRESENT_OPTION_ASYNC_MAY_TEAR 16 + #endif +@@ -2103,6 +2108,17 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain, + /* If the image has a modifier, we must have DRI3 v1.2. */ + assert(chain->has_dri3_modifiers); + ++#ifdef __TERMUX__ ++ int sock_fds[2] = { -1, -1 }; ++ if (image->base.ahardware_buffer) { ++ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) < 0) { ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ } ++ AHardwareBuffer_sendHandleToUnixSocket( ++ image->base.ahardware_buffer, sock_fds[0]); ++ image->base.dma_buf_fd = sock_fds[1]; ++ } ++#endif + /* XCB requires an array of file descriptors but we only have one */ + int fds[4] = { -1, -1, -1, -1 }; + for (int i = 0; i < image->base.num_planes; i++) { +@@ -2133,6 +2149,17 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain, + chain->depth, bpp, + image->base.drm_modifier, + fds); ++#ifdef __TERMUX__ ++ if (image->base.ahardware_buffer) { ++ xcb_flush(chain->conn); ++ uint8_t read_buf; ++ read(sock_fds[0], &read_buf, 1); ++ for (int i = 0; i < ARRAY_SIZE(sock_fds); i++) { ++ close(sock_fds[i]); ++ } ++ image->base.dma_buf_fd = -1; ++ } ++#endif + } else { + /* Without passing modifiers, we can't have multi-plane RGB images. */ + assert(image->base.num_planes == 1); +@@ -2628,6 +2655,12 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, + .alloc_shm = wsi_conn->has_mit_shm ? &alloc_shm : NULL, + }; + image_params = &cpu_image_params.base; ++#ifdef __TERMUX__ ++ } else if (wsi_device->wants_ahardware_buffer) { ++ image_params = &(struct wsi_base_image_params){ ++ .image_type = WSI_IMAGE_TYPE_AHB, ++ }; ++#endif + } else { + #ifdef HAVE_X11_DRM + drm_image_params = (struct wsi_drm_image_params) { +-- +2.47.1 + diff --git a/packages/mesa-vulkan-icd-wrapper/0005-vulkan-x11-disable-immediate-mode.patch b/packages/mesa-vulkan-icd-wrapper/0005-vulkan-x11-disable-immediate-mode.patch new file mode 100644 index 00000000000000..1d0ec0b0676cfc --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/0005-vulkan-x11-disable-immediate-mode.patch @@ -0,0 +1,14 @@ +diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c +index 22ac573cca2..9e0eb25f45f 100644 +--- a/src/vulkan/wsi/wsi_common_x11.c ++++ b/src/vulkan/wsi/wsi_common_x11.c +@@ -462,7 +462,9 @@ static const VkFormat formats[] = { + }; + + static const VkPresentModeKHR present_modes[] = { ++#ifndef __TERMUX__ + VK_PRESENT_MODE_IMMEDIATE_KHR, ++#endif + VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_KHR, + VK_PRESENT_MODE_FIFO_RELAXED_KHR, diff --git a/packages/mesa-vulkan-icd-wrapper/build.sh b/packages/mesa-vulkan-icd-wrapper/build.sh new file mode 100644 index 00000000000000..793c32952bb179 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/build.sh @@ -0,0 +1,54 @@ +TERMUX_PKG_HOMEPAGE=https://www.mesa3d.org +TERMUX_PKG_DESCRIPTION="Android Vulkan wrapper" +TERMUX_PKG_LICENSE="MIT" +TERMUX_PKG_LICENSE_FILE="docs/license.rst" +TERMUX_PKG_MAINTAINER="xMeM " +TERMUX_PKG_VERSION="24.3.1" +TERMUX_PKG_REVISION=1 +TERMUX_PKG_SRCURL=https://archive.mesa3d.org/mesa-${TERMUX_PKG_VERSION}.tar.xz +TERMUX_PKG_SHA256=9c795900449ce5bc7c526ba0ab3532a22c3c951cab7e0dd9de5fcac41b0843af +TERMUX_PKG_DEPENDS="libandroid-shmem, libc++, libdrm, libx11, libxcb, libxshmfence, libwayland, vulkan-loader-generic, zlib, zstd" +TERMUX_PKG_BUILD_DEPENDS="libwayland-protocols, libxrandr, xorgproto" +TERMUX_PKG_API_LEVEL=26 + +TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" +--cmake-prefix-path $TERMUX_PREFIX +-Dcpp_rtti=false +-Dgbm=disabled +-Dopengl=false +-Dllvm=disabled +-Dshared-llvm=disabled +-Dplatforms=x11,wayland +-Dgallium-drivers= +-Dxmlconfig=disabled +-Dvulkan-drivers=wrapper +" + +termux_step_post_get_source() { + cp -r $TERMUX_PKG_BUILDER_DIR/src/* $TERMUX_PKG_SRCDIR/src/ + # Do not use meson wrap projects + rm -rf subprojects +} + +termux_step_pre_configure() { + termux_setup_cmake + + CPPFLAGS+=" -D__USE_GNU" + CPPFLAGS+=" -U__ANDROID__" + LDFLAGS+=" -landroid-shmem" + + _WRAPPER_BIN=$TERMUX_PKG_BUILDDIR/_wrapper/bin + mkdir -p $_WRAPPER_BIN + if [ "$TERMUX_ON_DEVICE_BUILD" = "false" ]; then + sed 's|@CMAKE@|'"$(command -v cmake)"'|g' \ + $TERMUX_PKG_BUILDER_DIR/cmake-wrapper.in \ + > $_WRAPPER_BIN/cmake + chmod 0700 $_WRAPPER_BIN/cmake + termux_setup_wayland_cross_pkg_config_wrapper + fi + export PATH=$_WRAPPER_BIN:$PATH +} + +termux_step_post_configure() { + rm -f $_WRAPPER_BIN/cmake +} diff --git a/packages/mesa-vulkan-icd-wrapper/cmake-wrapper.in b/packages/mesa-vulkan-icd-wrapper/cmake-wrapper.in new file mode 100644 index 00000000000000..7cd20167cc824d --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/cmake-wrapper.in @@ -0,0 +1,16 @@ +#!/bin/sh + +if [ -e CMakeLists.txt ]; then + sed -i '1s|^|project(foo LANGUAGES C CXX)\n|' CMakeLists.txt +fi + +for f in "$@"; do + case "${f}" in + -DCMAKE_TOOLCHAIN_FILE=* ) + sed -i "${f#-DCMAKE_TOOLCHAIN_FILE=}" \ + -e 's|\(set(CMAKE_SYSTEM_NAME\) "Android")|\1 "Linux")|g' + ;; + esac +done + +exec @CMAKE@ "$@" diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/meson.build b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/meson.build new file mode 100644 index 00000000000000..8960fb6249314a --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/meson.build @@ -0,0 +1,93 @@ +wrapper_icd = custom_target( + 'wrapper_icd', + input: [vk_icd_gen, vk_api_xml], + output: 'wrapper_icd.@0@.json'.format(host_machine.cpu()), + command: [ + prog_python, + '@INPUT0@', + '--api-version', '1.3', + '--xml', '@INPUT1@', + '--lib-path', join_paths(get_option('prefix'), get_option('libdir'), 'libvulkan_wrapper.so'), + '--out', '@OUTPUT@', + ], + build_by_default: true, + install_dir: with_vulkan_icd_dir, + install: true, +) + +wrapper_entrypoints = custom_target( + 'wrapper_entrypoints', + input: [vk_entrypoints_gen, vk_api_xml], + output: ['wrapper_entrypoints.h', 'wrapper_entrypoints.c'], + command: [ + prog_python, + '@INPUT0@', + '--xml', '@INPUT1@', + '--proto', + '--weak', + '--beta', with_vulkan_beta.to_string(), + '--out-h', '@OUTPUT0@', + '--out-c', '@OUTPUT1@', + '--prefix', 'wrapper', + ], + depend_files: vk_entrypoints_gen_depend_files, +) + +wrapper_trampolines_gen = files('vk_wrapper_trampolines_gen.py') + +wrapper_trampolines = custom_target( + 'wrapper_trampolines', + input: [wrapper_trampolines_gen, vk_api_xml], + output: ['wrapper_trampolines.c', 'wrapper_trampolines.h'], + command: [ + prog_python, + '@INPUT0@', + '--xml', '@INPUT1@', + '--out-c', '@OUTPUT0@', + '--out-h', '@OUTPUT1@', + '--beta', with_vulkan_beta.to_string(), + ], + depend_files: vk_dispatch_trampolines_gen_depend_files, +) + +wrapper_features_gen = files('vk_wrapper_features_gen.py') + +wrapper_features = custom_target( + 'vk_wrapper_features', + input: [wrapper_features_gen, vk_api_xml], + output: ['wrapper_features.c'], + command: [ + prog_python, + '@INPUT0@', + '--xml', '@INPUT1@', + '--out-c', '@OUTPUT0@', + '--beta', with_vulkan_beta.to_string(), + ], + depend_files: vk_physical_device_features_gen_depend_files, +) + +wrapper_files = files( + 'wrapper_device.c', + 'wrapper_device_memory.c', + 'wrapper_instance.c', + 'wrapper_physical_device.c', +) + +wrapper_deps = [ + idep_vulkan_runtime, + idep_vulkan_util, + idep_vulkan_wsi, + dep_android, +] + +libvulkan_wrapper = shared_library( + 'vulkan_wrapper', + [wrapper_entrypoints, wrapper_trampolines, wrapper_features, wrapper_files], + include_directories: [ + inc_include, + inc_src, + ], + dependencies: [wrapper_deps, vulkan_wsi_deps], + gnu_symbol_visibility: 'hidden', + install: true, +) diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_entrypoints.py b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_entrypoints.py new file mode 120000 index 00000000000000..bbc9deb820f803 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_entrypoints.py @@ -0,0 +1 @@ +../util/vk_entrypoints.py \ No newline at end of file diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_extensions.py b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_extensions.py new file mode 120000 index 00000000000000..4407eca87b3679 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_extensions.py @@ -0,0 +1 @@ +../util/vk_extensions.py \ No newline at end of file diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_features_gen.py b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_features_gen.py new file mode 100644 index 00000000000000..eef8d4bf85b31f --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_features_gen.py @@ -0,0 +1,298 @@ +COPYRIGHT=u""" +/* Copyright © 2021 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. + */ +""" + +import argparse +from collections import OrderedDict +from dataclasses import dataclass +import os +import sys +import typing +import xml.etree.ElementTree as et + +import mako +from mako.template import Template +from vk_extensions import Requirements, get_all_required, filter_api + +def str_removeprefix(s, prefix): + if s.startswith(prefix): + return s[len(prefix):] + return s + +RENAMED_FEATURES = { + # See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17272#note_1446477 for details + ('BufferDeviceAddressFeaturesEXT', 'bufferDeviceAddressCaptureReplay'): 'bufferDeviceAddressCaptureReplayEXT', + + ('MeshShaderFeaturesNV', 'taskShader'): 'taskShaderNV', + ('MeshShaderFeaturesNV', 'meshShader'): 'meshShaderNV', + + ('CooperativeMatrixFeaturesNV', 'cooperativeMatrix'): 'cooperativeMatrixNV', + ('CooperativeMatrixFeaturesNV', 'cooperativeMatrixRobustBufferAccess'): 'cooperativeMatrixRobustBufferAccessNV', + + ('DeviceGeneratedCommandsFeaturesNV', 'deviceGeneratedCommands'): 'deviceGeneratedCommandsNV', +} + +KNOWN_ALIASES = [ + (['Vulkan11Features', '16BitStorageFeatures'], ['storageBuffer16BitAccess', 'uniformAndStorageBuffer16BitAccess', 'storagePushConstant16', 'storageInputOutput16']), + (['Vulkan11Features', 'MultiviewFeatures'], ['multiview', 'multiviewGeometryShader', 'multiviewTessellationShader']), + (['Vulkan11Features', 'VariablePointersFeatures'], ['variablePointersStorageBuffer', 'variablePointers']), + (['Vulkan11Features', 'ProtectedMemoryFeatures'], ['protectedMemory']), + (['Vulkan11Features', 'SamplerYcbcrConversionFeatures'], ['samplerYcbcrConversion']), + (['Vulkan11Features', 'ShaderDrawParametersFeatures'], ['shaderDrawParameters']), + + (['Vulkan12Features', '8BitStorageFeatures'], ['storageBuffer8BitAccess', 'uniformAndStorageBuffer8BitAccess', 'storagePushConstant8']), + (['Vulkan12Features', 'ShaderAtomicInt64Features'], ['shaderBufferInt64Atomics', 'shaderSharedInt64Atomics']), + (['Vulkan12Features', 'ShaderFloat16Int8Features'], ['shaderFloat16', 'shaderInt8']), + ( + ['Vulkan12Features', 'DescriptorIndexingFeatures'], + [ + 'shaderInputAttachmentArrayDynamicIndexing', + 'shaderUniformTexelBufferArrayDynamicIndexing', + 'shaderStorageTexelBufferArrayDynamicIndexing', + 'shaderUniformBufferArrayNonUniformIndexing', + 'shaderSampledImageArrayNonUniformIndexing', + 'shaderStorageBufferArrayNonUniformIndexing', + 'shaderStorageImageArrayNonUniformIndexing', + 'shaderInputAttachmentArrayNonUniformIndexing', + 'shaderUniformTexelBufferArrayNonUniformIndexing', + 'shaderStorageTexelBufferArrayNonUniformIndexing', + 'descriptorBindingUniformBufferUpdateAfterBind', + 'descriptorBindingSampledImageUpdateAfterBind', + 'descriptorBindingStorageImageUpdateAfterBind', + 'descriptorBindingStorageBufferUpdateAfterBind', + 'descriptorBindingUniformTexelBufferUpdateAfterBind', + 'descriptorBindingStorageTexelBufferUpdateAfterBind', + 'descriptorBindingUpdateUnusedWhilePending', + 'descriptorBindingPartiallyBound', + 'descriptorBindingVariableDescriptorCount', + 'runtimeDescriptorArray', + ], + ), + (['Vulkan12Features', 'ScalarBlockLayoutFeatures'], ['scalarBlockLayout']), + (['Vulkan12Features', 'ImagelessFramebufferFeatures'], ['imagelessFramebuffer']), + (['Vulkan12Features', 'UniformBufferStandardLayoutFeatures'], ['uniformBufferStandardLayout']), + (['Vulkan12Features', 'ShaderSubgroupExtendedTypesFeatures'], ['shaderSubgroupExtendedTypes']), + (['Vulkan12Features', 'SeparateDepthStencilLayoutsFeatures'], ['separateDepthStencilLayouts']), + (['Vulkan12Features', 'HostQueryResetFeatures'], ['hostQueryReset']), + (['Vulkan12Features', 'TimelineSemaphoreFeatures'], ['timelineSemaphore']), + (['Vulkan12Features', 'BufferDeviceAddressFeatures', 'BufferDeviceAddressFeaturesEXT'], ['bufferDeviceAddress', 'bufferDeviceAddressMultiDevice']), + (['Vulkan12Features', 'BufferDeviceAddressFeatures'], ['bufferDeviceAddressCaptureReplay']), + (['Vulkan12Features', 'VulkanMemoryModelFeatures'], ['vulkanMemoryModel', 'vulkanMemoryModelDeviceScope', 'vulkanMemoryModelAvailabilityVisibilityChains']), + + (['Vulkan13Features', 'ImageRobustnessFeatures'], ['robustImageAccess']), + (['Vulkan13Features', 'InlineUniformBlockFeatures'], ['inlineUniformBlock', 'descriptorBindingInlineUniformBlockUpdateAfterBind']), + (['Vulkan13Features', 'PipelineCreationCacheControlFeatures'], ['pipelineCreationCacheControl']), + (['Vulkan13Features', 'PrivateDataFeatures'], ['privateData']), + (['Vulkan13Features', 'ShaderDemoteToHelperInvocationFeatures'], ['shaderDemoteToHelperInvocation']), + (['Vulkan13Features', 'ShaderTerminateInvocationFeatures'], ['shaderTerminateInvocation']), + (['Vulkan13Features', 'SubgroupSizeControlFeatures'], ['subgroupSizeControl', 'computeFullSubgroups']), + (['Vulkan13Features', 'Synchronization2Features'], ['synchronization2']), + (['Vulkan13Features', 'TextureCompressionASTCHDRFeatures'], ['textureCompressionASTC_HDR']), + (['Vulkan13Features', 'ZeroInitializeWorkgroupMemoryFeatures'], ['shaderZeroInitializeWorkgroupMemory']), + (['Vulkan13Features', 'DynamicRenderingFeatures'], ['dynamicRendering']), + (['Vulkan13Features', 'ShaderIntegerDotProductFeatures'], ['shaderIntegerDotProduct']), + (['Vulkan13Features', 'Maintenance4Features'], ['maintenance4']), +] + +for (feature_structs, features) in KNOWN_ALIASES: + for flag in features: + for f in feature_structs: + rename = (f, flag) + assert rename not in RENAMED_FEATURES, f"{rename} already exists in RENAMED_FEATURES" + RENAMED_FEATURES[rename] = flag + +def get_renamed_feature(c_type, feature): + return RENAMED_FEATURES.get((str_removeprefix(c_type, 'VkPhysicalDevice'), feature), feature) + +@dataclass +class FeatureStruct: + reqs: Requirements + c_type: str + s_type: str + features: typing.List[str] + +TEMPLATE_C = Template(COPYRIGHT + """ +/* This file generated from ${filename}, don't edit directly. */ + +#include "wrapper_private.h" +#include "vk_physical_device_features.h" +#include "vk_util.h" + +void +wrapper_setup_device_features(struct wrapper_physical_device *physical_device) +{ + VkPhysicalDevice vk_physical_device = physical_device->dispatch_handle; + + /* Query the device what kind of features are supported. */ + VkPhysicalDeviceFeatures2 supported_features2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + }; + +% for f in feature_structs: + ${f.c_type} supported_${f.c_type} = { + .sType = ${f.s_type}, + .pNext = NULL, + }; + __vk_append_struct(&supported_features2, &supported_${f.c_type}); +% endfor + + physical_device->dispatch_table.GetPhysicalDeviceFeatures2( + vk_physical_device, &supported_features2); + + vk_set_physical_device_features(&physical_device->vk.supported_features, + &supported_features2); +} +""") + +def get_pdev_features(doc): + _type = doc.find(".types/type[@name='VkPhysicalDeviceFeatures']") + if _type is not None: + flags = [] + for p in _type.findall('./member'): + assert p.find('./type').text == 'VkBool32' + flags.append(p.find('./name').text) + return flags + return None + +def filter_api(elem, api): + if 'api' not in elem.attrib: + return True + + return api in elem.attrib['api'].split(',') + +def get_feature_structs(doc, api, beta): + feature_structs = OrderedDict() + + required = get_all_required(doc, 'type', api, beta) + + # parse all struct types where structextends VkPhysicalDeviceFeatures2 + for _type in doc.findall('./types/type[@category="struct"]'): + if _type.attrib.get('structextends') != 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo': + continue + if _type.attrib['name'] not in required: + continue + + reqs = required[_type.attrib['name']] + # Skip extensions with a define for now + guard = reqs.guard + if guard is not None and (guard != "VK_ENABLE_BETA_EXTENSIONS" or beta != "true"): + continue + + # find Vulkan structure type + for elem in _type: + if "STRUCTURE_TYPE" in str(elem.attrib): + s_type = elem.attrib.get('values') + + # collect a list of feature flags + flags = [] + + for p in _type.findall('./member'): + if not filter_api(p, api): + continue + + m_name = p.find('./name').text + if m_name == 'pNext': + pass + elif m_name == 'sType': + s_type = p.attrib.get('values') + else: + assert p.find('./type').text == 'VkBool32' + flags.append(m_name) + + feature_struct = FeatureStruct(reqs=reqs, c_type=_type.attrib.get('name'), s_type=s_type, features=flags) + feature_structs[feature_struct.c_type] = feature_struct + + return feature_structs.values() + +def get_feature_structs_from_xml(xml_files, beta, api='vulkan'): + diagnostics = [] + + pdev_features = None + feature_structs = [] + + for filename in xml_files: + doc = et.parse(filename) + feature_structs += get_feature_structs(doc, api, beta) + if not pdev_features: + pdev_features = get_pdev_features(doc) + + unused_renames = {**RENAMED_FEATURES} + + features = OrderedDict() + + for flag in pdev_features: + features[flag] = 'VkPhysicalDeviceFeatures' + + for f in feature_structs: + for flag in f.features: + renamed_flag = get_renamed_feature(f.c_type, flag) + if renamed_flag not in features: + features[renamed_flag] = f.c_type + else: + a = str_removeprefix(features[renamed_flag], 'VkPhysicalDevice') + b = str_removeprefix(f.c_type, 'VkPhysicalDevice') + if (a, flag) not in RENAMED_FEATURES or (b, flag) not in RENAMED_FEATURES: + diagnostics.append(f'{a} and {b} both define {flag}') + + unused_renames.pop((str_removeprefix(f.c_type, 'VkPhysicalDevice'), flag), None) + + for rename in unused_renames: + diagnostics.append(f'unused rename {rename}') + + assert len(diagnostics) == 0, '\n'.join(diagnostics) + + return pdev_features, feature_structs, features + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--out-c', required=True, help='Output C file.') + parser.add_argument('--beta', required=True, help='Enable beta extensions.') + parser.add_argument('--xml', + help='Vulkan API XML file.', + required=True, action='append', dest='xml_files') + args = parser.parse_args() + + pdev_features, feature_structs, all_flags = get_feature_structs_from_xml(args.xml_files, args.beta) + + environment = { + 'filename': os.path.basename(__file__), + 'pdev_features': pdev_features, + 'feature_structs': feature_structs, + 'all_flags': all_flags, + 'get_renamed_feature': get_renamed_feature, + } + + try: + with open(args.out_c, 'w', encoding='utf-8') as f: + f.write(TEMPLATE_C.render(**environment)) + except Exception: + # In the event there's an error, this uses some helpers from mako + # to print a useful stack trace and prints it, then exits with + # status 1, if python is run with debug; otherwise it just raises + # the exception + print(mako.exceptions.text_error_template().render(), file=sys.stderr) + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py new file mode 100644 index 00000000000000..f20fde16034bdb --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/vk_wrapper_trampolines_gen.py @@ -0,0 +1,222 @@ +# coding=utf-8 +COPYRIGHT = """\ +/* + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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. + */ +""" + +import argparse +import os + +from mako.template import Template + +# Mesa-local imports must be declared in meson variable +# '{file_without_suffix}_depend_files'. +from vk_entrypoints import get_entrypoints_from_xml + +TEMPLATE_H = Template(COPYRIGHT + """\ +/* This file generated from ${filename}, don't edit directly. */ + +#ifndef WRAPPER_TRAMPOLINES_H +#define WRAPPER_TRAMPOLINES_H + +#include "vk_dispatch_table.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct vk_physical_device_entrypoint_table wrapper_physical_device_trampolines; +extern struct vk_device_entrypoint_table wrapper_device_trampolines; + +#ifdef __cplusplus +} +#endif + +#endif /* WRAPPER_TRAMPOLINES_H */ +""") + +TEMPLATE_C = Template(COPYRIGHT + """\ +/* This file generated from ${filename}, don't edit directly. */ + +#include "wrapper_private.h" +#include "wrapper_trampolines.h" + +% for e in entrypoints: + % if not e.is_physical_device_entrypoint() or e.alias: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif +static VKAPI_ATTR ${e.return_type} VKAPI_CALL +${e.prefixed_name('wrapper_tramp')}(${e.decl_params()}) +{ + <% assert e.params[0].type == 'VkPhysicalDevice' %> + VK_FROM_HANDLE(wrapper_physical_device, vk_physical_device, ${e.params[0].name}); + % if e.return_type == 'void': + vk_physical_device->dispatch_table.${e.name}(vk_physical_device->dispatch_handle, ${e.call_params(1)}); + % else: + return vk_physical_device->dispatch_table.${e.name}(vk_physical_device->dispatch_handle, ${e.call_params(1)}); + % endif +} + % if e.guard is not None: +#endif + % endif +% endfor + +struct vk_physical_device_entrypoint_table wrapper_physical_device_trampolines = { +% for e in entrypoints: + % if not e.is_physical_device_entrypoint() or e.alias: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + .${e.name} = ${e.prefixed_name('wrapper_tramp')}, + % if e.guard is not None: +#endif + % endif +% endfor +}; + +% for e in entrypoints: + % if not e.is_device_entrypoint() or e.alias: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif +static VKAPI_ATTR ${e.return_type} VKAPI_CALL +${e.prefixed_name('wrapper_tramp')}(${e.decl_params()}) +{ + % if e.params[0].type == 'VkDevice': + VK_FROM_HANDLE(wrapper_device, vk_device, ${e.params[0].name}); + % if e.return_type == 'void': + % if len(e.params) > 1: + vk_device->dispatch_table.${e.name}(vk_device->dispatch_handle, ${e.call_params(1)}); + % else: + vk_device->dispatch_table.${e.name}(vk_device->dispatch_handle); + % endif + % else: + % if len(e.params) > 1: + return vk_device->dispatch_table.${e.name}(vk_device->dispatch_handle, ${e.call_params(1)}); + % else: + return vk_device->dispatch_table.${e.name}(vk_device->dispatch_handle); + % endif + % endif + % elif e.params[0].type == 'VkCommandBuffer': + VK_FROM_HANDLE(wrapper_command_buffer, wcb, ${e.params[0].name}); + % if e.return_type == 'void': + % if len(e.params) > 1: + wcb->device->dispatch_table.${e.name}(wcb->dispatch_handle, ${e.call_params(1)}); + % else: + wcb->device->dispatch_table.${e.name}(wcb->dispatch_handle); + % endif + % else: + % if len(e.params) > 1: + return wcb->device->dispatch_table.${e.name}(wcb->dispatch_handle, ${e.call_params(1)}); + % else: + return wcb->device->dispatch_table.${e.name}(wcb->dispatch_handle); + % endif + % endif + % elif e.params[0].type == 'VkQueue': + VK_FROM_HANDLE(wrapper_queue, wqueue, ${e.params[0].name}); + % if e.return_type == 'void': + % if len(e.params) > 1: + wqueue->device->dispatch_table.${e.name}(wqueue->dispatch_handle, ${e.call_params(1)}); + % else: + wqueue->device->dispatch_table.${e.name}(wqueue->dispatch_handle); + % endif + % else: + % if len(e.params) > 1: + return wqueue->device->dispatch_table.${e.name}(wqueue->dispatch_handle, ${e.call_params(1)}); + % else: + return wqueue->device->dispatch_table.${e.name}(wqueue->dispatch_handle); + % endif + % endif + % else: + assert(!"Unhandled device child trampoline case: ${e.params[0].type}"); + % endif +} + % if e.guard is not None: +#endif + % endif +% endfor + +struct vk_device_entrypoint_table wrapper_device_trampolines = { +% for e in entrypoints: + % if not e.is_device_entrypoint() or e.alias: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + .${e.name} = ${e.prefixed_name('wrapper_tramp')}, + % if e.guard is not None: +#endif + % endif +% endfor +}; +""") + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--out-c', help='Output C file.') + parser.add_argument('--out-h', help='Output H file.') + parser.add_argument('--beta', required=True, help='Enable beta extensions.') + parser.add_argument('--xml', + help='Vulkan API XML file.', + required=True, + action='append', + dest='xml_files') + args = parser.parse_args() + + entrypoints = get_entrypoints_from_xml(args.xml_files, args.beta) + + # For outputting entrypoints.h we generate a anv_EntryPoint() prototype + # per entry point. + try: + if args.out_h: + with open(args.out_h, 'w', encoding='utf-8') as f: + f.write(TEMPLATE_H.render(entrypoints=entrypoints, + filename=os.path.basename(__file__))) + if args.out_c: + with open(args.out_c, 'w', encoding='utf-8') as f: + f.write(TEMPLATE_C.render(entrypoints=entrypoints, + filename=os.path.basename(__file__))) + except Exception: + # In the event there's an error, this imports some helpers from mako + # to print a useful stack trace and prints it, then exits with + # status 1, if python is run with debug; otherwise it just raises + # the exception + if __debug__: + import sys + from mako import exceptions + sys.stderr.write(exceptions.text_error_template().render() + '\n') + sys.exit(1) + raise + + +if __name__ == '__main__': + main() diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device.c b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device.c new file mode 100644 index 00000000000000..c2207e12cbdbf7 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device.c @@ -0,0 +1,409 @@ +#include "wrapper_private.h" +#include "wrapper_entrypoints.h" +#include "wrapper_trampolines.h" +#include "vk_alloc.h" +#include "vk_common_entrypoints.h" +#include "vk_device.h" +#include "vk_dispatch_table.h" +#include "vk_extensions.h" +#include "vk_queue.h" +#include "vk_util.h" +#include "util/list.h" + +const struct vk_device_extension_table wrapper_device_extensions = +{ + .KHR_swapchain = true, + .EXT_swapchain_maintenance1 = true, + .KHR_swapchain_mutable_format = true, +#ifdef VK_USE_PLATFORM_DISPLAY_KHR + .EXT_display_control = true, +#endif + .KHR_present_id = true, + .KHR_present_wait = true, + .KHR_incremental_present = true, + .KHR_map_memory2 = true, + .EXT_map_memory_placed = true, +}; + +const struct vk_device_extension_table wrapper_filter_extensions = +{ + .EXT_hdr_metadata = true, + .GOOGLE_display_timing = true, + .KHR_shared_presentable_image = true, + .EXT_image_compression_control_swapchain = true, +}; + +static void +wrapper_filter_enabled_extensions(const struct vk_device *device, + uint32_t *enable_extension_count, + const char **enable_extensions) +{ + for (int idx = 0; idx < VK_DEVICE_EXTENSION_COUNT; idx++) { + if (!device->enabled_extensions.extensions[idx]) + continue; + + if (wrapper_device_extensions.extensions[idx]) + continue; + + if (wrapper_filter_extensions.extensions[idx]) + continue; + + enable_extensions[(*enable_extension_count)++] = + vk_device_extensions[idx].extensionName; + } +} + +static inline void +wrapper_append_required_extensions(const struct vk_device *device, + uint32_t *count, + const char **exts) { +#define REQUIRED_EXTENSION(name) \ + if (!device->enabled_extensions.name && \ + device->physical->supported_extensions.name) { \ + exts[(*count)++] = "VK_" #name; \ + } + REQUIRED_EXTENSION(KHR_external_fence); + REQUIRED_EXTENSION(KHR_external_semaphore); + REQUIRED_EXTENSION(KHR_external_memory); + REQUIRED_EXTENSION(KHR_external_fence_fd); + REQUIRED_EXTENSION(KHR_external_semaphore_fd); + REQUIRED_EXTENSION(KHR_external_memory_fd); + REQUIRED_EXTENSION(KHR_dedicated_allocation); + REQUIRED_EXTENSION(EXT_queue_family_foreign); + REQUIRED_EXTENSION(KHR_maintenance1) + REQUIRED_EXTENSION(KHR_maintenance2) + REQUIRED_EXTENSION(KHR_image_format_list) + REQUIRED_EXTENSION(KHR_timeline_semaphore); + REQUIRED_EXTENSION(EXT_external_memory_host); + REQUIRED_EXTENSION(EXT_external_memory_dma_buf); + REQUIRED_EXTENSION(EXT_image_drm_format_modifier); + REQUIRED_EXTENSION(ANDROID_external_memory_android_hardware_buffer); +#undef REQUIRED_EXTENSION +} + +static VkResult +wrapper_create_device_queue(struct wrapper_device *device, + const VkDeviceCreateInfo* pCreateInfo) +{ + const VkDeviceQueueCreateInfo *create_info; + struct wrapper_queue *queue; + VkResult result; + + for (int i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { + create_info = &pCreateInfo->pQueueCreateInfos[i]; + for (int j = 0; j < create_info->queueCount; j++) { + queue = vk_zalloc(&device->vk.alloc, sizeof(*queue), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!queue) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + device->dispatch_table.GetDeviceQueue(device->dispatch_handle, + create_info->queueFamilyIndex, + j, &queue->dispatch_handle);; + queue->device = device; + + result = vk_queue_init(&queue->vk, &device->vk, create_info, j); + if (result != VK_SUCCESS) { + vk_free(&device->vk.alloc, queue); + return result; + } + } + } + + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_CreateDevice(VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice) +{ + VK_FROM_HANDLE(wrapper_physical_device, physical_device, physicalDevice); + const char *wrapper_enable_extensions[VK_DEVICE_EXTENSION_COUNT]; + uint32_t wrapper_enable_extension_count = 0; + VkDeviceCreateInfo wrapper_create_info = *pCreateInfo; + struct vk_device_dispatch_table dispatch_table; + struct wrapper_device *device; + VkPhysicalDeviceFeatures2 *pdf2; + VkPhysicalDeviceFeatures *pdf; + VkResult result; + + device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator, + sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + if (!device) + return vk_error(physical_device, VK_ERROR_OUT_OF_HOST_MEMORY); + + list_inithead(&device->command_buffers); + device->physical = physical_device; + device->memorys = _mesa_hash_table_create(NULL, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + if (!device->memorys) { + vk_free2(&physical_device->instance->vk.alloc, pAllocator, + device); + return vk_error(physical_device, VK_ERROR_OUT_OF_HOST_MEMORY); + } + + vk_device_dispatch_table_from_entrypoints( + &dispatch_table, &wrapper_device_entrypoints, true); + vk_device_dispatch_table_from_entrypoints( + &dispatch_table, &wsi_device_entrypoints, false); + vk_device_dispatch_table_from_entrypoints( + &dispatch_table, &wrapper_device_trampolines, false); + + result = vk_device_init(&device->vk, &physical_device->vk, + &dispatch_table, pCreateInfo, pAllocator); + + if (result != VK_SUCCESS) { + _mesa_hash_table_destroy(device->memorys, NULL); + vk_free2(&physical_device->instance->vk.alloc, pAllocator, + device); + return vk_error(physical_device, result); + } + + wrapper_filter_enabled_extensions(&device->vk, + &wrapper_enable_extension_count, + wrapper_enable_extensions); + wrapper_append_required_extensions(&device->vk, + &wrapper_enable_extension_count, + wrapper_enable_extensions); + + wrapper_create_info.enabledExtensionCount = wrapper_enable_extension_count; + wrapper_create_info.ppEnabledExtensionNames = wrapper_enable_extensions; + + pdf = (void *)pCreateInfo->pEnabledFeatures; + if (pdf && pdf->textureCompressionBC) { + pdf->textureCompressionBC &= + physical_device->backup_supported_features.textureCompressionBC; + } + pdf2 = __vk_find_struct((void *)pCreateInfo->pNext, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2); + if (pdf2 && pdf2->features.textureCompressionBC) { + pdf2->features.textureCompressionBC &= + physical_device->backup_supported_features.textureCompressionBC; + } + + result = physical_device->dispatch_table.CreateDevice( + physical_device->dispatch_handle, &wrapper_create_info, + pAllocator, &device->dispatch_handle); + + if (result != VK_SUCCESS) { + wrapper_DestroyDevice(wrapper_device_to_handle(device), + &device->vk.alloc); + return vk_error(physical_device, result); + } + + void *gdpa = physical_device->instance->dispatch_table.GetInstanceProcAddr( + physical_device->instance->dispatch_handle, "vkGetDeviceProcAddr"); + vk_device_dispatch_table_load(&device->dispatch_table, gdpa, + device->dispatch_handle); + + result = wrapper_create_device_queue(device, pCreateInfo); + if (result != VK_SUCCESS) { + wrapper_DestroyDevice(wrapper_device_to_handle(device), + &device->vk.alloc); + return vk_error(physical_device, result); + } + + *pDevice = wrapper_device_to_handle(device); + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, + uint32_t queueIndex, VkQueue* pQueue) { + vk_common_GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, + VkQueue* pQueue) { + vk_common_GetDeviceQueue2(device, pQueueInfo, pQueue); +} + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +wrapper_GetDeviceProcAddr(VkDevice _device, const char* pName) { + VK_FROM_HANDLE(wrapper_device, device, _device); + return vk_device_get_proc_addr(&device->vk, pName); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_QueueSubmit(VkQueue _queue, uint32_t submitCount, + const VkSubmitInfo* pSubmits, VkFence fence) +{ + VK_FROM_HANDLE(wrapper_queue, queue, _queue); + VkCommandBuffer wrapper_command_buffers[submitCount][32]; + VkSubmitInfo wrapper_submits[submitCount]; + + for (int i = 0; i < submitCount; i++) { + const VkSubmitInfo *submit_info = &pSubmits[i]; + for (int j = 0; j < submit_info->commandBufferCount; j++) { + VK_FROM_HANDLE(wrapper_command_buffer, wcb, + submit_info->pCommandBuffers[j]); + wrapper_command_buffers[i][j] = wcb->dispatch_handle; + } + wrapper_submits[i] = pSubmits[i]; + wrapper_submits[i].pCommandBuffers = wrapper_command_buffers[i]; + } + return queue->device->dispatch_table.QueueSubmit(queue->dispatch_handle, + submitCount, + wrapper_submits, + fence); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_QueueSubmit2(VkQueue _queue, uint32_t submitCount, + const VkSubmitInfo2* pSubmits, VkFence fence) +{ + VK_FROM_HANDLE(wrapper_queue, queue, _queue); + VkCommandBufferSubmitInfo wrapper_command_buffers[submitCount][32]; + VkSubmitInfo2 wrapper_submits[submitCount]; + + for (int i = 0; i < submitCount; i++) { + const VkSubmitInfo2 *submit_info = &pSubmits[i]; + for (int j = 0; j < submit_info->commandBufferInfoCount; j++) { + VK_FROM_HANDLE(wrapper_command_buffer, wcb, + submit_info->pCommandBufferInfos[j].commandBuffer); + wrapper_command_buffers[i][j] = pSubmits[i].pCommandBufferInfos[j]; + wrapper_command_buffers[i][j].commandBuffer = wcb->dispatch_handle; + } + wrapper_submits[i] = pSubmits[i]; + wrapper_submits[i].pCommandBufferInfos = wrapper_command_buffers[i]; + } + return queue->device->dispatch_table.QueueSubmit2(queue->dispatch_handle, + submitCount, + wrapper_submits, + fence); +} + +static VkResult +wrapper_command_buffer_create(struct wrapper_device *device, + VkCommandPool pool, + VkCommandBuffer dispatch_handle, + VkCommandBuffer *pCommandBuffers) { + struct wrapper_command_buffer *wrapper_command_buffer; + wrapper_command_buffer = vk_object_zalloc(&device->vk, &device->vk.alloc, + sizeof(struct wrapper_command_buffer), + VK_OBJECT_TYPE_COMMAND_BUFFER); + if (!wrapper_command_buffer) + return vk_error(&device->vk, VK_ERROR_OUT_OF_HOST_MEMORY); + + wrapper_command_buffer->device = device; + wrapper_command_buffer->pool = pool; + wrapper_command_buffer->dispatch_handle = dispatch_handle; + list_add(&wrapper_command_buffer->link, &device->command_buffers); + + *pCommandBuffers = wrapper_command_buffer_to_handle(wrapper_command_buffer); + + return VK_SUCCESS; +} + +static void +wrapper_command_buffer_destroy(struct wrapper_device *device, + struct wrapper_command_buffer *wcb) { + list_del(&wcb->link); + vk_object_free(&device->vk, NULL, wcb); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_AllocateCommandBuffers(VkDevice _device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + VkCommandBuffer dispatch_handles[pAllocateInfo->commandBufferCount]; + VkResult result; + uint32_t i; + + result = device->dispatch_table.AllocateCommandBuffers(device->dispatch_handle, + pAllocateInfo, + dispatch_handles); + if (result != VK_SUCCESS) + return result; + + for (i = 0; i < pAllocateInfo->commandBufferCount; i++) { + result = wrapper_command_buffer_create(device, + pAllocateInfo->commandPool, + dispatch_handles[i], + &pCommandBuffers[i]); + if (result != VK_SUCCESS) + break; + } + + if (result != VK_SUCCESS) { + device->dispatch_table.FreeCommandBuffers(device->dispatch_handle, + pAllocateInfo->commandPool, + pAllocateInfo->commandBufferCount, + dispatch_handles); + for (int q = 0; q < i; q++) { + VK_FROM_HANDLE(wrapper_command_buffer, wcb, pCommandBuffers[q]); + wrapper_command_buffer_destroy(device, wcb); + } + + for (i = 0; i < pAllocateInfo->commandBufferCount; i++) + pCommandBuffers[i] = VK_NULL_HANDLE; + + return result; + } + + return VK_SUCCESS; +} + + +VKAPI_ATTR void VKAPI_CALL +wrapper_FreeCommandBuffers(VkDevice _device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + VkCommandBuffer dispatch_handles[commandBufferCount]; + + for (int i = 0; i < commandBufferCount; i++) { + VK_FROM_HANDLE(wrapper_command_buffer, wcb, pCommandBuffers[i]); + dispatch_handles[i] = wcb->dispatch_handle; + wrapper_command_buffer_destroy(device, wcb); + } + device->dispatch_table.FreeCommandBuffers(device->dispatch_handle, + commandPool, commandBufferCount, + dispatch_handles); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_DestroyCommandPool(VkDevice _device, VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + list_for_each_entry_safe(struct wrapper_command_buffer, wcb, + &device->command_buffers, link) { + if (wcb->pool == commandPool) { + wrapper_command_buffer_destroy(device, wcb); + } + } + device->dispatch_table.DestroyCommandPool(device->dispatch_handle, + commandPool, pAllocator); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_DestroyDevice(VkDevice _device, const VkAllocationCallbacks* pAllocator) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + list_for_each_entry_safe(struct wrapper_command_buffer, wcb, + &device->command_buffers, link) { + wrapper_command_buffer_destroy(device, wcb); + } + list_for_each_entry_safe(struct vk_queue, queue, &device->vk.queues, link) { + vk_queue_finish(queue); + vk_free2(&device->vk.alloc, pAllocator, queue); + } + if (device->dispatch_handle != VK_NULL_HANDLE) { + device->dispatch_table.DestroyDevice(device-> + dispatch_handle, pAllocator); + } + _mesa_hash_table_destroy(device->memorys, NULL); + vk_device_finish(&device->vk); + vk_free2(&device->vk.alloc, pAllocator, device); +} + diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device_memory.c b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device_memory.c new file mode 100644 index 00000000000000..99bffeeceb8784 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_device_memory.c @@ -0,0 +1,427 @@ +#define native_handle_t __native_handle_t +#define buffer_handle_t __buffer_handle_t +#include "wrapper_private.h" +#include "wrapper_entrypoints.h" +#include "vk_common_entrypoints.h" +#undef native_handle_t +#undef buffer_handle_t +#include "util/hash_table.h" +#include "util/os_file.h" +#include "vk_util.h" + +#include +#include +#include +#include +#include + +static int +safe_ioctl(int fd, unsigned long request, void *arg) +{ + int ret; + + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + return ret; +} + +static int +dma_heap_alloc(int heap_fd, size_t size) { + struct dma_heap_allocation_data alloc_data = { + .len = size, + .fd_flags = O_RDWR | O_CLOEXEC, + }; + if (safe_ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &alloc_data) < 0) + return -1; + + return alloc_data.fd; +} + +static int +ion_heap_alloc(int heap_fd, size_t size) { + struct ion_allocation_data { + __u64 len; + __u32 heap_id_mask; + __u32 flags; + __u32 fd; + __u32 unused; + } alloc_data = { + .len = size, + /* ION_HEAP_SYSTEM | ION_SYSTEM_HEAP_ID */ + .heap_id_mask = (1U << 0) | (1U << 25), + .flags = 0, /* uncached */ + }; + + if (safe_ioctl(heap_fd, _IOWR('I', 0, struct ion_allocation_data), + &alloc_data) < 0) + return -1; + + return alloc_data.fd; +} + +static int +wrapper_dmabuf_alloc(struct wrapper_device *device, size_t size) +{ + int fd; + + fd = dma_heap_alloc(device->physical->dma_heap_fd, size); + + if (fd < 0) + fd = ion_heap_alloc(device->physical->dma_heap_fd, size); + + return fd; +} + +static VkResult +wrapper_get_import_dmabuf_info(struct wrapper_device *device, + VkMemoryAllocateInfo *alloc_info, + VkImportMemoryFdInfoKHR *fd_info, + const void *pnext) +{ + int import_dmabuf_fd; + int memory_type_index; + VkResult result; + + import_dmabuf_fd = wrapper_dmabuf_alloc(device, + alloc_info->allocationSize); + if (import_dmabuf_fd < 0) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + VkMemoryFdPropertiesKHR memory_fd_props = { + .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR, + .pNext = NULL, + }; + result = device->dispatch_table.GetMemoryFdPropertiesKHR( + device->dispatch_handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + import_dmabuf_fd, &memory_fd_props); + if (result != VK_SUCCESS) { + close(import_dmabuf_fd); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + memory_type_index = wrapper_select_memory_type( + device->physical->memory_properties, + device->physical->memory_properties.memoryTypes[ + alloc_info->memoryTypeIndex].propertyFlags | + memory_fd_props.memoryTypeBits); + if (memory_type_index >= UINT32_MAX) { + close(import_dmabuf_fd); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + *fd_info = (VkImportMemoryFdInfoKHR) { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, + .pNext = pnext, + .fd = import_dmabuf_fd, + .handleType = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + + alloc_info->pNext = fd_info; + alloc_info->memoryTypeIndex = memory_type_index; + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_AllocateMemory(VkDevice _device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + const VkImportAndroidHardwareBufferInfoANDROID *import_ahb_info; + const VkImportMemoryFdInfoKHR *import_fd_info; + const VkExportMemoryAllocateInfo *export_info; + VkImportMemoryFdInfoKHR local_import_info = { .fd = -1 }; + VkExportMemoryAllocateInfo local_export_info; + VkMemoryAllocateInfo wrapper_allocate_info; + struct wrapper_device_memory *memory; + VkMemoryPropertyFlags memory_type; + bool can_get_ahardware_buffer; + bool can_get_dmabuf_fd; + VkResult result; + + memory_type = device->physical->memory_properties.memoryTypes + [pAllocateInfo->memoryTypeIndex].propertyFlags; + + if (!device->vk.enabled_extensions.EXT_map_memory_placed || + !device->vk.enabled_features.memoryMapPlaced || + !(memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + { + return device->dispatch_table.AllocateMemory( + device->dispatch_handle, pAllocateInfo, pAllocator, + pMemory); + } + + memory = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*memory), + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!memory) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + memory->alloc_size = pAllocateInfo->allocationSize; + memory->dmabuf_fd = -1; + wrapper_allocate_info = *pAllocateInfo; + + import_ahb_info = vk_find_struct_const(pAllocateInfo, + IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); + import_fd_info = vk_find_struct_const(pAllocateInfo, + IMPORT_MEMORY_FD_INFO_KHR); + export_info = vk_find_struct_const(pAllocateInfo, + EXPORT_MEMORY_ALLOCATE_INFO); + + if (import_ahb_info) { + memory->ahardware_buffer = import_ahb_info->buffer; + AHardwareBuffer_acquire(memory->ahardware_buffer); + } else if (import_fd_info) { + memory->dmabuf_fd = os_dupfd_cloexec(import_fd_info->fd); + } else if (!export_info) { + export_info = &local_export_info; + } + + if (export_info == &local_export_info) { + local_export_info = (VkExportMemoryAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + .pNext = pAllocateInfo->pNext, + .handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + wrapper_allocate_info.pNext = &local_export_info; + } + + result = device->dispatch_table.AllocateMemory( + device->dispatch_handle, &wrapper_allocate_info, + pAllocator, pMemory); + + if (export_info == &local_export_info && result != VK_SUCCESS) + { + result = wrapper_get_import_dmabuf_info(device, + &wrapper_allocate_info, &local_import_info, + pAllocateInfo->pNext); + + if (result == VK_SUCCESS) { + memory->dmabuf_fd = os_dupfd_cloexec( + local_import_info.fd); + + result = device->dispatch_table.AllocateMemory( + device->dispatch_handle, &wrapper_allocate_info, + pAllocator, pMemory); + + if (result != VK_SUCCESS) { + close(local_import_info.fd); + local_import_info.fd = -1; + close(memory->dmabuf_fd); + memory->dmabuf_fd = -1; + } else { + export_info = NULL; + } + } + } + + if (export_info == &local_export_info && result != VK_SUCCESS) + { + local_export_info.handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + + wrapper_allocate_info.pNext = &local_export_info; + + result = device->dispatch_table.AllocateMemory( + device->dispatch_handle, &wrapper_allocate_info, + pAllocator, pMemory); + } + + if (result != VK_SUCCESS) { + if (memory->ahardware_buffer) + AHardwareBuffer_release(memory->ahardware_buffer); + if (memory->dmabuf_fd != -1) + close(memory->dmabuf_fd); + vk_free2(&device->vk.alloc, pAllocator, memory); + return vk_error(device, result); + } + + _mesa_hash_table_insert(device->memorys, (void *)(*pMemory), memory); + + can_get_dmabuf_fd = (export_info && export_info->handleTypes == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + can_get_ahardware_buffer = (export_info && export_info->handleTypes == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID); + + if (can_get_dmabuf_fd) { + const VkMemoryGetFdInfoKHR get_fd_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .memory = *pMemory, + .handleType = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + result = device->dispatch_table.GetMemoryFdKHR( + device->dispatch_handle, &get_fd_info, &memory->dmabuf_fd); + } else if (can_get_ahardware_buffer) { + const VkMemoryGetAndroidHardwareBufferInfoANDROID get_ahb_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, + .memory = *pMemory, + }; + result = device->dispatch_table.GetMemoryAndroidHardwareBufferANDROID( + device->dispatch_handle, &get_ahb_info, &memory->ahardware_buffer); + } + + if (result != VK_SUCCESS) { + wrapper_FreeMemory(_device, *pMemory, pAllocator); + *pMemory = VK_NULL_HANDLE; + return vk_error(device, result); + } + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_FreeMemory(VkDevice _device, VkDeviceMemory _memory, + const VkAllocationCallbacks* pAllocator) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + struct wrapper_device_memory *memory; + struct hash_entry *entry = NULL; + + entry = _memory != VK_NULL_HANDLE ? _mesa_hash_table_search( + device->memorys, (void *)_memory) : NULL; + memory = entry ? entry->data : NULL; + + if (memory) { + if (memory->map_address && memory->map_size) + munmap(memory->map_address, memory->map_size); + if (memory->ahardware_buffer) + AHardwareBuffer_release(memory->ahardware_buffer); + if (memory->dmabuf_fd != -1) + close(memory->dmabuf_fd); + vk_free2(&device->vk.alloc, pAllocator, memory); + _mesa_hash_table_remove(device->memorys, entry); + } + + device->dispatch_table.FreeMemory(device->dispatch_handle, + _memory, + pAllocator); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_MapMemory2KHR(VkDevice _device, + const VkMemoryMapInfoKHR* pMemoryMapInfo, + void** ppData) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + const VkMemoryMapPlacedInfoEXT *placed_info = NULL; + struct wrapper_device_memory *memory; + struct hash_entry *entry; + int fd; + + if (pMemoryMapInfo->flags & VK_MEMORY_MAP_PLACED_BIT_EXT) + placed_info = vk_find_struct_const(pMemoryMapInfo->pNext, + MEMORY_MAP_PLACED_INFO_EXT); + + entry = pMemoryMapInfo->memory != VK_NULL_HANDLE + ? _mesa_hash_table_search(device->memorys, + (void *)pMemoryMapInfo->memory) : NULL; + memory = entry ? entry->data : NULL; + + if (!placed_info || !memory) { + return device->dispatch_table.MapMemory( + device->dispatch_handle, + pMemoryMapInfo->memory, + pMemoryMapInfo->offset, + pMemoryMapInfo->size, + 0, + ppData); + } + + if (memory->map_address) { + if (placed_info->pPlacedAddress != memory->map_address) { + return VK_ERROR_MEMORY_MAP_FAILED; + } else { + *ppData = (char *)memory->map_address + + pMemoryMapInfo->offset; + return VK_SUCCESS; + } + } + assert(memory->dmabuf_fd >= 0 || memory->ahardware_buffer != NULL); + + if (memory->ahardware_buffer) { + const native_handle_t *handle; + const int *handle_fds; + + handle = AHardwareBuffer_getNativeHandle(memory->ahardware_buffer); + handle_fds = &handle->data[0]; + + int idx; + for (idx = 0; idx < handle->numFds; idx++) { + size_t size = lseek(handle_fds[idx], 0, SEEK_END); + if (size >= memory->alloc_size) { + break; + } + } + assert(idx < handle->numFds); + fd = handle_fds[idx]; + } else { + fd = memory->dmabuf_fd; + } + + if (pMemoryMapInfo->size == VK_WHOLE_SIZE) + memory->map_size = memory->alloc_size > 0 ? + memory->alloc_size : lseek(fd, 0, SEEK_END); + else + memory->map_size = pMemoryMapInfo->size; + + memory->map_address = mmap(placed_info->pPlacedAddress, + memory->map_size, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, + fd, 0); + if (memory->map_address == MAP_FAILED) { + memory->map_address = NULL; + memory->map_size = 0; + fprintf(stderr, "%s: mmap failed\n", __func__); + return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); + } + + *ppData = (char *)memory->map_address + pMemoryMapInfo->offset; + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_UnmapMemory(VkDevice _device, VkDeviceMemory _memory) { + vk_common_UnmapMemory(_device, _memory); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_UnmapMemory2KHR(VkDevice _device, + const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo) +{ + VK_FROM_HANDLE(wrapper_device, device, _device); + struct wrapper_device_memory *memory; + struct hash_entry *entry; + + entry = pMemoryUnmapInfo->memory != VK_NULL_HANDLE ? + _mesa_hash_table_search(device->memorys, + (void *)pMemoryUnmapInfo->memory) : NULL; + memory = entry ? entry->data : NULL; + + if (memory) { + if (pMemoryUnmapInfo->flags & VK_MEMORY_UNMAP_RESERVE_BIT_EXT) { + memory->map_address = mmap(memory->map_address, memory->map_size, + PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (memory->map_address == MAP_FAILED) { + fprintf(stderr, "Failed to replace mapping with reserved memory"); + return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); + } + } else { + munmap(memory->map_address, memory->map_size); + } + + memory->map_size = 0; + memory->map_address = NULL; + } + + device->dispatch_table.UnmapMemory(device->dispatch_handle, + pMemoryUnmapInfo->memory); + return VK_SUCCESS; +} + diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_instance.c b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_instance.c new file mode 100644 index 00000000000000..3b083ec40d8264 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_instance.c @@ -0,0 +1,297 @@ +#include "wrapper_private.h" +#include "wrapper_entrypoints.h" +#include "vk_alloc.h" +#include "vk_common_entrypoints.h" +#include "vk_dispatch_table.h" +#include "vk_extensions.h" + +const struct vk_instance_extension_table wrapper_instance_extensions = { + .KHR_get_surface_capabilities2 = true, + .EXT_surface_maintenance1 = true, + .KHR_surface_protected_capabilities = true, + .KHR_surface = true, + .EXT_swapchain_colorspace = true, +#ifdef VK_USE_PLATFORM_ANDROID_KHR + .KHR_android_surface = true, +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR + .KHR_xcb_surface = true, +#endif +#ifdef VK_USE_PLATFORM_XLIB_KHR + .KHR_xlib_surface = true, +#endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + .KHR_wayland_surface = true, +#endif +#ifdef VK_USE_PLATFORM_DISPLAY_KHR + .KHR_display = true, + .KHR_get_display_properties2 = true, + .EXT_display_surface_counter = true, + .EXT_acquire_drm_display = true, + .EXT_direct_mode_display = true, +#endif + .EXT_headless_surface = true, + .EXT_debug_utils = true, + .EXT_debug_report = true, +}; + +static void *vulkan_library_handle; +static PFN_vkCreateInstance create_instance; +static PFN_vkGetInstanceProcAddr get_instance_proc_addr; +static PFN_vkEnumerateInstanceVersion enumerate_instance_version; +static PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extension_properties; +static struct vk_instance_extension_table *supported_instance_extensions; + +#ifdef __LP64__ +#define DEFAULT_VULKAN_PATH "/system/lib64/libvulkan.so" +#else +#define DEFAULT_VULKAN_PATH "/system/lib/libvulkan.so" +#endif + +#include + +static bool vulkan_library_init() +{ + if (vulkan_library_handle) + return true; + + const char *env = getenv("WRAPPER_VULKAN_PATH"); + vulkan_library_handle = dlopen(env ? env : DEFAULT_VULKAN_PATH, + RTLD_LOCAL | RTLD_NOW); + + if (vulkan_library_handle) { + create_instance = dlsym(vulkan_library_handle, "vkCreateInstance"); + get_instance_proc_addr = dlsym(vulkan_library_handle, + "vkGetInstanceProcAddr"); + enumerate_instance_version = dlsym(vulkan_library_handle, + "vkEnumerateInstanceVersion"); + enumerate_instance_extension_properties = + dlsym(vulkan_library_handle, "vkEnumerateInstanceExtensionProperties"); + } + else { + fprintf(stderr, "%s", dlerror()); + } + + return vulkan_library_handle ? true : false; +} + +static VkResult wrapper_vulkan_init() +{ + VkExtensionProperties props[VK_INSTANCE_EXTENSION_COUNT]; + uint32_t prop_count = VK_INSTANCE_EXTENSION_COUNT; + VkResult result; + + if (supported_instance_extensions) + return VK_SUCCESS; + + if (!vulkan_library_init()) + return VK_ERROR_INCOMPATIBLE_DRIVER; + + result = enumerate_instance_extension_properties(NULL, &prop_count, props); + if (result != VK_SUCCESS) + return result; + + supported_instance_extensions = malloc(sizeof(*supported_instance_extensions)); + if (!supported_instance_extensions) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + *supported_instance_extensions = wrapper_instance_extensions; + + for(int i = 0; i < prop_count; i++) { + int idx; + for (idx = 0; idx < VK_INSTANCE_EXTENSION_COUNT; idx++) { + if (strcmp(vk_instance_extensions[idx].extensionName, + props[i].extensionName) == 0) + break; + } + + if (idx >= VK_INSTANCE_EXTENSION_COUNT) + continue; + + supported_instance_extensions->extensions[idx] = true; + } + + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_EnumerateInstanceVersion(uint32_t* pApiVersion) +{ + + if (!vulkan_library_init()) + return vk_error(NULL, VK_ERROR_INCOMPATIBLE_DRIVER); + + return enumerate_instance_version(pApiVersion); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_EnumerateInstanceExtensionProperties(const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + VkResult result; + + result = wrapper_vulkan_init(); + if (result != VK_SUCCESS) + return vk_error(NULL, result); + + return vk_enumerate_instance_extension_properties(supported_instance_extensions, + pPropertyCount, + pProperties); +} + +static inline void +set_wrapper_required_extensions(const struct vk_instance *instance, + uint32_t *enable_extension_count, + const char **enable_extensions) +{ + uint32_t count = *enable_extension_count; +#define REQUIRED_EXTENSION(name) \ + assert (count < VK_INSTANCE_EXTENSION_COUNT); \ + if (!instance->enabled_extensions.name && \ + supported_instance_extensions->name) { \ + enable_extensions[count++] = "VK_" #name; \ + } + REQUIRED_EXTENSION(KHR_get_physical_device_properties2); + REQUIRED_EXTENSION(KHR_external_fence_capabilities); + REQUIRED_EXTENSION(KHR_external_memory_capabilities); + REQUIRED_EXTENSION(KHR_external_semaphore_capabilities); +#undef REQUIRED_EXTENSION + *enable_extension_count = count; +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkInstance *pInstance) +{ + const char *wrapper_enable_extensions[VK_INSTANCE_EXTENSION_COUNT]; + uint32_t wrapper_enable_extension_count = 0; + VkInstanceCreateInfo wrapper_create_info = *pCreateInfo; + struct vk_instance_dispatch_table dispatch_table; + struct wrapper_instance *instance; + VkResult result; + + result = wrapper_vulkan_init(); + if (result != VK_SUCCESS) + return vk_error(NULL, result); + + instance = vk_zalloc2(vk_default_allocator(), pAllocator, sizeof(*instance), + 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!instance) + return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + + vk_instance_dispatch_table_from_entrypoints( + &dispatch_table, &wrapper_instance_entrypoints, true); + vk_instance_dispatch_table_from_entrypoints( + &dispatch_table, &wsi_instance_entrypoints, false); + + result = vk_instance_init(&instance->vk, supported_instance_extensions, + &dispatch_table, pCreateInfo, + pAllocator ? pAllocator : vk_default_allocator()); + + if (result != VK_SUCCESS) { + vk_free2(vk_default_allocator(), pAllocator, instance); + return vk_error(NULL, result); + } + + instance->vk.physical_devices.enumerate = enumerate_physical_device; + instance->vk.physical_devices.destroy = destroy_physical_device; + + for (int idx = 0; idx < pCreateInfo->enabledExtensionCount; idx++) { + if (wrapper_instance_extensions.extensions[idx]) + continue; + + if (!instance->vk.enabled_extensions.extensions[idx]) + continue; + + wrapper_enable_extensions[wrapper_enable_extension_count++] = + vk_instance_extensions[idx].extensionName; + } + + set_wrapper_required_extensions(&instance->vk, + &wrapper_enable_extension_count, + wrapper_enable_extensions); + + wrapper_create_info.enabledExtensionCount = wrapper_enable_extension_count; + wrapper_create_info.ppEnabledExtensionNames = wrapper_enable_extensions; + + result = create_instance(&wrapper_create_info, pAllocator, + &instance->dispatch_handle); + if (result != VK_SUCCESS) { + vk_instance_finish(&instance->vk); + vk_free2(vk_default_allocator(), pAllocator, instance); + return vk_error(NULL, result); + } + vk_instance_dispatch_table_load(&instance->dispatch_table, + get_instance_proc_addr, + instance->dispatch_handle); + + *pInstance = wrapper_instance_to_handle(instance); + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_DestroyInstance(VkInstance _instance, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(wrapper_instance, instance, _instance); + instance->dispatch_table.DestroyInstance(instance->dispatch_handle, + pAllocator); + vk_instance_finish(&instance->vk); + vk_free2(&instance->vk.alloc, pAllocator, instance); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_DebugReportMessageEXT(VkInstance _instance, + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage) +{ + VK_FROM_HANDLE(wrapper_instance, instance, _instance); + + switch (objectType) { + case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: + case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: + break; + default: + object = (uint64_t)VK_NULL_HANDLE; + } + + vk_common_DebugReportMessageEXT(instance->dispatch_handle, flags, + objectType, object, location, messageCode, + pLayerPrefix, pMessage); +} + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +wrapper_GetInstanceProcAddr(VkInstance _instance, + const char *pName) +{ + VK_FROM_HANDLE(wrapper_instance, instance, _instance); + return vk_instance_get_proc_addr(&instance->vk, + &wrapper_instance_entrypoints, + pName); +} + +PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +vk_icdGetInstanceProcAddr(VkInstance instance, + const char *pName); + + +PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +vk_icdGetInstanceProcAddr(VkInstance instance, + const char *pName) +{ + return wrapper_GetInstanceProcAddr(instance, pName); +} diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_physical_device.c b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_physical_device.c new file mode 100644 index 00000000000000..ca1892a317654a --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_physical_device.c @@ -0,0 +1,240 @@ +#include "wrapper_private.h" +#include "wrapper_entrypoints.h" +#include "wrapper_trampolines.h" +#include "vk_alloc.h" +#include "vk_common_entrypoints.h" +#include "vk_dispatch_table.h" +#include "vk_extensions.h" +#include "vk_physical_device.h" +#include "vk_util.h" +#include "wsi_common.h" +#include "util/os_misc.h" + +static VkResult +wrapper_setup_device_extensions(struct wrapper_physical_device *pdevice) { + struct vk_device_extension_table *exts = &pdevice->vk.supported_extensions; + VkExtensionProperties pdevice_extensions[VK_DEVICE_EXTENSION_COUNT]; + uint32_t pdevice_extension_count = VK_DEVICE_EXTENSION_COUNT; + VkResult result; + + result = pdevice->dispatch_table.EnumerateDeviceExtensionProperties( + pdevice->dispatch_handle, NULL, &pdevice_extension_count, pdevice_extensions); + + if (result != VK_SUCCESS) + return result; + + *exts = wrapper_device_extensions; + + for (int i = 0; i < pdevice_extension_count; i++) { + int idx; + for (idx = 0; idx < VK_DEVICE_EXTENSION_COUNT; idx++) { + if (strcmp(vk_device_extensions[idx].extensionName, + pdevice_extensions[i].extensionName) == 0) + break; + } + + if (idx >= VK_DEVICE_EXTENSION_COUNT) + continue; + + if (wrapper_filter_extensions.extensions[idx]) + continue; + + exts->extensions[idx] = true; + } + + exts->KHR_present_wait = exts->KHR_timeline_semaphore; + + return VK_SUCCESS; +} + +static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +wrapper_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName) +{ + VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice); + return vk_instance_get_proc_addr_unchecked(pdevice->instance, pName); +} + +VkResult enumerate_physical_device(struct vk_instance *_instance) +{ + struct wrapper_instance *instance = (struct wrapper_instance *)_instance; + VkPhysicalDevice physical_devices[16]; + uint32_t physical_device_count = 16; + VkResult result; + + result = instance->dispatch_table.EnumeratePhysicalDevices( + instance->dispatch_handle, &physical_device_count, physical_devices); + + if (result != VK_SUCCESS) + return result; + + for (int i = 0; i < physical_device_count; i++) { + PFN_vkGetInstanceProcAddr get_instance_proc_addr; + struct wrapper_physical_device *pdevice; + + pdevice = vk_zalloc(&_instance->alloc, sizeof(*pdevice), 8, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!pdevice) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + struct vk_physical_device_dispatch_table dispatch_table; + vk_physical_device_dispatch_table_from_entrypoints( + &dispatch_table, &wrapper_physical_device_entrypoints, true); + vk_physical_device_dispatch_table_from_entrypoints( + &dispatch_table, &wsi_physical_device_entrypoints, false); + vk_physical_device_dispatch_table_from_entrypoints( + &dispatch_table, &wrapper_physical_device_trampolines, false); + + result = vk_physical_device_init(&pdevice->vk, + &instance->vk, + NULL, NULL, NULL, + &dispatch_table); + if (result != VK_SUCCESS) { + vk_free(&_instance->alloc, pdevice); + return result; + } + + pdevice->instance = instance; + pdevice->dispatch_handle = physical_devices[i]; + get_instance_proc_addr = instance->dispatch_table.GetInstanceProcAddr; + + vk_physical_device_dispatch_table_load(&pdevice->dispatch_table, + get_instance_proc_addr, + instance->dispatch_handle); + + wrapper_setup_device_extensions(pdevice); + wrapper_setup_device_features(pdevice); + + const char *env = getenv("DISABLE_MAP_MEMORY_PLACED"); + const bool disable_map_memory_placed = env && atoi(env) != 0; + + if (disable_map_memory_placed) + pdevice->vk.supported_extensions.EXT_map_memory_placed = false; + + struct vk_features *supported_features = &pdevice->vk.supported_features; + pdevice->backup_supported_features = *supported_features; + supported_features->presentId = true; + supported_features->presentWait = supported_features->timelineSemaphore; + supported_features->swapchainMaintenance1 = true; + supported_features->imageCompressionControlSwapchain = false; + supported_features->memoryMapPlaced = !disable_map_memory_placed; + supported_features->memoryUnmapReserve = !disable_map_memory_placed; + supported_features->textureCompressionBC = true; + + result = wsi_device_init(&pdevice->wsi_device, + wrapper_physical_device_to_handle(pdevice), + wrapper_wsi_proc_addr, &_instance->alloc, -1, + NULL, &(struct wsi_device_options){}); + if (result != VK_SUCCESS) { + vk_physical_device_finish(&pdevice->vk); + vk_free(&_instance->alloc, pdevice); + return result; + } + pdevice->vk.wsi_device = &pdevice->wsi_device; + pdevice->wsi_device.force_bgra8_unorm_first = true; +#ifdef __TERMUX__ + pdevice->wsi_device.wants_ahardware_buffer = true; +#endif + + pdevice->driver_properties = (VkPhysicalDeviceDriverProperties) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + }; + pdevice->properties2 = (VkPhysicalDeviceProperties2) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &pdevice->driver_properties, + }; + pdevice->dispatch_table.GetPhysicalDeviceProperties2( + pdevice->dispatch_handle, &pdevice->properties2); + + if (strstr(pdevice->properties2.properties.deviceName, "Adreno") && + strstr(pdevice->properties2.properties.deviceName, "750")) { + if (strstr(instance->vk.app_info.app_name, "clvk")) { + /* HACK: clvk failed to create device on Adreno 750 + * with error VK_ERROR_NOT_PERMITTED, so disable it. */ + supported_features->globalPriorityQuery = false; + } + } + + pdevice->dispatch_table.GetPhysicalDeviceMemoryProperties( + pdevice->dispatch_handle, &pdevice->memory_properties); + + pdevice->dma_heap_fd = open("/dev/dma_heap/system", O_RDONLY); + if (pdevice->dma_heap_fd < 0) + pdevice->dma_heap_fd = open("/dev/ion", O_RDONLY); + + list_addtail(&pdevice->vk.link, &_instance->physical_devices.list); + } + + return VK_SUCCESS; +} + +void destroy_physical_device(struct vk_physical_device *pdevice) { + VK_FROM_HANDLE(wrapper_physical_device, wpdevice, + vk_physical_device_to_handle(pdevice)); + if (wpdevice->dma_heap_fd != -1) + close(wpdevice->dma_heap_fd); + wsi_device_finish(pdevice->wsi_device, &pdevice->instance->alloc); + vk_physical_device_finish(pdevice); + vk_free(&pdevice->instance->alloc, pdevice); +} + +VKAPI_ATTR VkResult VKAPI_CALL +wrapper_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + return vk_common_EnumerateDeviceExtensionProperties(physicalDevice, + pLayerName, + pPropertyCount, + pProperties); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures* pFeatures) +{ + return vk_common_GetPhysicalDeviceFeatures(physicalDevice, pFeatures); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures) { + vk_common_GetPhysicalDeviceFeatures2(physicalDevice, pFeatures); +} + +VKAPI_ATTR void VKAPI_CALL +wrapper_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties) +{ + VK_FROM_HANDLE(wrapper_physical_device, pdevice, physicalDevice); + pdevice->dispatch_table.GetPhysicalDeviceProperties2( + pdevice->dispatch_handle, pProperties); + + vk_foreach_struct(prop, pProperties->pNext) { + switch (prop->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT *placed_prop = + (VkPhysicalDeviceMapMemoryPlacedPropertiesEXT *)prop; + uint64_t os_page_size; + os_get_page_size(&os_page_size); + placed_prop->minPlacedMemoryMapAlignment = os_page_size; + break; + } + default: + break; + } + } +} + +uint32_t +wrapper_select_memory_type(VkPhysicalDeviceMemoryProperties props, + VkMemoryPropertyFlags flags) { + int idx; + for (idx = 0; idx < props.memoryTypeCount; idx ++) { + if (props.memoryTypes[idx].propertyFlags & flags) { + break; + } + } + return idx < props.memoryTypeCount ? idx : UINT32_MAX; +} diff --git a/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_private.h b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_private.h new file mode 100644 index 00000000000000..ba52243f757184 --- /dev/null +++ b/packages/mesa-vulkan-icd-wrapper/src/vulkan/wrapper/wrapper_private.h @@ -0,0 +1,94 @@ +#include "vulkan/runtime/vk_instance.h" +#include "vulkan/runtime/vk_physical_device.h" +#include "vulkan/runtime/vk_device.h" +#include "vulkan/runtime/vk_queue.h" +#include "vulkan/runtime/vk_command_buffer.h" +#include "vulkan/runtime/vk_log.h" +#include "vulkan/util/vk_dispatch_table.h" +#include "vulkan/wsi/wsi_common.h" +#include "util/hash_table.h" + +extern const struct vk_instance_extension_table wrapper_instance_extensions; +extern const struct vk_device_extension_table wrapper_device_extensions; +extern const struct vk_device_extension_table wrapper_filter_extensions; + +struct wrapper_instance { + struct vk_instance vk; + + VkInstance dispatch_handle; + struct vk_instance_dispatch_table dispatch_table; +}; + +VK_DEFINE_HANDLE_CASTS(wrapper_instance, vk.base, VkInstance, + VK_OBJECT_TYPE_INSTANCE) + +struct wrapper_physical_device { + struct vk_physical_device vk; + + int dma_heap_fd; + VkPhysicalDevice dispatch_handle; + VkPhysicalDeviceProperties2 properties2; + VkPhysicalDeviceDriverProperties driver_properties; + VkPhysicalDeviceMemoryProperties memory_properties; + struct wsi_device wsi_device; + struct wrapper_instance *instance; + struct vk_features backup_supported_features; + struct vk_physical_device_dispatch_table dispatch_table; +}; + +VK_DEFINE_HANDLE_CASTS(wrapper_physical_device, vk.base, VkPhysicalDevice, + VK_OBJECT_TYPE_PHYSICAL_DEVICE) + +struct wrapper_queue { + struct vk_queue vk; + + struct wrapper_device *device; + VkQueue dispatch_handle; +}; + +VK_DEFINE_HANDLE_CASTS(wrapper_queue, vk.base, VkQueue, + VK_OBJECT_TYPE_QUEUE) + +struct wrapper_device { + struct vk_device vk; + + VkDevice dispatch_handle; + struct list_head command_buffers; + struct hash_table *memorys; + struct wrapper_physical_device *physical; + struct vk_device_dispatch_table dispatch_table; +}; + +VK_DEFINE_HANDLE_CASTS(wrapper_device, vk.base, VkDevice, + VK_OBJECT_TYPE_DEVICE) + +struct wrapper_command_buffer { + struct vk_command_buffer vk; + + struct wrapper_device *device; + struct list_head link; + VkCommandPool pool; + VkCommandBuffer dispatch_handle; +}; + +VK_DEFINE_HANDLE_CASTS(wrapper_command_buffer, vk.base, VkCommandBuffer, + VK_OBJECT_TYPE_COMMAND_BUFFER) + +struct wrapper_device_memory { + struct AHardwareBuffer *ahardware_buffer; + int dmabuf_fd; + void *map_address; + size_t map_size; + size_t alloc_size; +}; + +VkResult enumerate_physical_device(struct vk_instance *_instance); +void destroy_physical_device(struct vk_physical_device *pdevice); + +void +wrapper_setup_device_features(struct wrapper_physical_device *physical_device); + +uint32_t +wrapper_select_memory_type(VkPhysicalDeviceMemoryProperties props, + VkMemoryPropertyFlags flags); +