From 08d6a8d2e5e16d4a15cb58871c591adec0691ee8 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 23 May 2022 10:57:27 +0800 Subject: [PATCH 2/3] kms: Drop dependency on vkCreateDmaBufImageINTEL Based on chromium's gpu/vulkan/vulkan_image{_linux,}.cc Signed-off-by: Jeffy Chen --- meson.build | 7 +- src/ws/kms_window_system.cpp | 172 ++++++++++++++++++++++++++--------- src/ws/kms_window_system.h | 1 - 3 files changed, 130 insertions(+), 50 deletions(-) diff --git a/meson.build b/meson.build index 7d305dc..0d83918 100644 --- a/meson.build +++ b/meson.build @@ -32,16 +32,11 @@ wayland_protocols_dep = dependency('wayland-protocols', version : '>= 1.12', wayland_scanner_dep = dependency('wayland-scanner', required : get_option('wayland') == 'true') libdrm_dep = dependency('libdrm', required : get_option('kms') == 'true') gbm_dep = dependency('gbm', required : get_option('kms') == 'true') -has_vulkan_intel_header = cpp.has_header('vulkan/vulkan_intel.h', dependencies: vulkan_dep) - -if get_option('kms') == 'true' and not has_vulkan_intel_header - error('KMS plugin needs the vulkan_intel.h header, but it couldn\'t be found') -endif build_xcb_ws = xcb_dep.found() and xcb_icccm_dep.found() and get_option('xcb') != 'false' build_wayland_ws = (wayland_client_dep.found() and wayland_protocols_dep.found() and wayland_scanner_dep.found() and get_option('wayland') != 'false') -build_kms_ws = libdrm_dep.found() and gbm_dep.found() and has_vulkan_intel_header and get_option('kms') != 'false' +build_kms_ws = libdrm_dep.found() and gbm_dep.found() and get_option('kms') != 'false' if not build_xcb_ws and not build_wayland_ws and not build_kms_ws error('vkmark needs at least one winsys to work - xcb, wayland or kms') diff --git a/src/ws/kms_window_system.cpp b/src/ws/kms_window_system.cpp index ca8220f..66618f6 100644 --- a/src/ws/kms_window_system.cpp +++ b/src/ws/kms_window_system.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -352,7 +351,6 @@ void KMSWindowSystem::init_vulkan(VulkanState& vulkan_) vk_image_format = vk::Format::eB8G8R8A8Srgb; create_gbm_bos(); - create_drm_fbs(); create_vk_images(); } @@ -428,68 +426,122 @@ void KMSWindowSystem::create_gbm_bos() } } -void KMSWindowSystem::create_drm_fbs() -{ - for (auto const& gbm_bo : gbm_bos) - { - uint32_t fb = 0; - - uint32_t handles[4] = {gbm_bo_get_handle(gbm_bo).u32, 0, 0, 0}; - uint32_t strides[4] = {gbm_bo_get_stride(gbm_bo), 0, 0, 0}; - uint32_t offsets[4] = {0, 0, 0, 0}; - - auto const ret = drmModeAddFB2( - drm_fd, vk_extent.width, vk_extent.height, - DRM_FORMAT_XRGB8888, - handles, strides, offsets, &fb, 0); - - if (ret < 0) - throw std::system_error{-ret, std::system_category(), "Failed to add drm fb"}; +// TODO: Use an official extension to create the VkImages when it becomes +// available (e.g. VK_MESAX_external_image_dma_buf) - drm_fbs.push_back( - ManagedResource{ - std::move(fb), - [this] (auto& fb) { drmModeRmFB(drm_fd, fb); }}); +static int find_memory_type_index(VkPhysicalDevice physical_device, + const VkMemoryRequirements* requirements, + VkMemoryPropertyFlags flags) { + VkPhysicalDeviceMemoryProperties properties; + vkGetPhysicalDeviceMemoryProperties(physical_device, &properties); + for (int i = 0; i <= 31; i++) { + if (((1u << i) & requirements->memoryTypeBits) == 0) + continue; + if ((properties.memoryTypes[i].propertyFlags & flags) != flags) + continue; + return i; } + return -1; } -// TODO: Use an official extension to create the VkImages when it becomes -// available (e.g. VK_MESAX_external_image_dma_buf) void KMSWindowSystem::create_vk_images() { - auto const create_dma_buf_image = - reinterpret_cast( - vulkan->device().getProcAddr("vkCreateDmaBufImageINTEL")); - - if (!create_dma_buf_image) - throw std::runtime_error{"Failed to get vkCreateDmaBufImageINTEL function pointer"}; - for (auto const& gbm_bo : gbm_bos) { auto const fd = ManagedResource{gbm_bo_get_fd(gbm_bo), close}; - auto const stride = gbm_bo_get_stride(gbm_bo); - VkDmaBufImageCreateInfo create_info{}; - create_info.sType = static_cast(VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL); - create_info.fd = fd; - create_info.format = static_cast(vk_image_format); - create_info.extent = {vk_extent.width, vk_extent.height, 1}; - create_info.strideInBytes = stride; + VkExternalMemoryImageCreateInfoKHR external_image_create_info = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + + uint64_t modifier = DRM_FORMAT_MOD_LINEAR; + VkImageDrmFormatModifierListCreateInfoEXT modifier_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, + .drmFormatModifierCount = 1, + .pDrmFormatModifiers = &modifier, + }; + external_image_create_info.pNext = &modifier_info; + + VkImportMemoryFdInfoKHR import_memory_fd_info = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .fd = fd, + }; + + VkImageCreateInfo create_info{}; + create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = &external_image_create_info, + .flags = 0, + .imageType = VK_IMAGE_TYPE_2D, + .format = static_cast(vk_image_format), + .extent = {vk_extent.width, vk_extent.height, 1}, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, + .usage = 0, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; VkImage image; - VkDeviceMemory device_memory; - VkResult result = create_dma_buf_image( + VkResult result = vkCreateImage( vulkan->device(), &create_info, nullptr, - &device_memory, &image); + if (result != VK_SUCCESS) + { + vk::throwResultException(static_cast(result), + "vkCreateImage"); + } + + VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, + .pNext = &import_memory_fd_info, + .image = image, + }; + + VkMemoryRequirements requirements; + vkGetImageMemoryRequirements(vulkan->device(), image, &requirements); + if (!requirements.memoryTypeBits) { + throw std::runtime_error{"Failed in vkGetImageMemoryRequirements"}; + } + + int index = find_memory_type_index(vulkan->physical_device(), + &requirements, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (index < 0) { + throw std::runtime_error{"Failed to get memoryTypeIndex"}; + } + + VkMemoryAllocateInfo memory_allocate_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = &dedicated_memory_info, + .allocationSize = requirements.size, + .memoryTypeIndex = (uint32_t)index, + }; + + VkDeviceMemory device_memory = VK_NULL_HANDLE; + result = vkAllocateMemory(vulkan->device(), &memory_allocate_info, + nullptr /* pAllocator */, &device_memory); if (result != VK_SUCCESS) { vk::throwResultException(static_cast(result), - "vkCreateDmbBufImageINTEL"); + "vkAllocateMemory"); + } + + result = vkBindImageMemory(vulkan->device(), image, device_memory, + 0 /* memoryOffset */); + if (result != VK_SUCCESS) { + vk::throwResultException(static_cast(result), + "vkBindImageMemory"); } vk_images.push_back( @@ -500,6 +552,40 @@ void KMSWindowSystem::create_vk_images() vptr->device().destroyImage(image); vptr->device().freeMemory(device_memory); }}); + + std::array layouts = {}; + const VkImageSubresource image_subresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .arrayLayer = 0, + }; + vkGetImageSubresourceLayout(vulkan->device(), image, + &image_subresource, &layouts[0]); + + uint32_t fb = 0; + + uint32_t handles[4] = {0,}; + uint32_t strides[4] = {0,}; + uint32_t offsets[4] = {0,}; + + for (auto i = 0; i < gbm_bo_get_plane_count(gbm_bo); i++) { + handles[i] = gbm_bo_get_handle(gbm_bo).u32; + offsets[i] = layouts[i].offset; + strides[i] = layouts[i].rowPitch; + } + + auto const ret = drmModeAddFB2( + drm_fd, vk_extent.width, vk_extent.height, + DRM_FORMAT_XRGB8888, + handles, strides, offsets, &fb, 0); + + if (ret < 0) + throw std::system_error{-ret, std::system_category(), "Failed to add drm fb"}; + + drm_fbs.push_back( + ManagedResource{ + std::move(fb), + [this] (auto& fb) { drmModeRmFB(drm_fd, fb); }}); } } diff --git a/src/ws/kms_window_system.h b/src/ws/kms_window_system.h index 4389ef7..ca304c0 100644 --- a/src/ws/kms_window_system.h +++ b/src/ws/kms_window_system.h @@ -68,7 +68,6 @@ public: protected: void create_gbm_bos(); - void create_drm_fbs(); void create_vk_images(); void wait_for_drm_page_flip_event(); -- 2.20.1