1From 08d6a8d2e5e16d4a15cb58871c591adec0691ee8 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Mon, 23 May 2022 10:57:27 +0800 4Subject: [PATCH 2/3] kms: Drop dependency on vkCreateDmaBufImageINTEL 5 6Based on chromium's gpu/vulkan/vulkan_image{_linux,}.cc 7 8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 9--- 10 meson.build | 7 +- 11 src/ws/kms_window_system.cpp | 172 ++++++++++++++++++++++++++--------- 12 src/ws/kms_window_system.h | 1 - 13 3 files changed, 130 insertions(+), 50 deletions(-) 14 15diff --git a/meson.build b/meson.build 16index 7d305dc..0d83918 100644 17--- a/meson.build 18+++ b/meson.build 19@@ -32,16 +32,11 @@ wayland_protocols_dep = dependency('wayland-protocols', version : '>= 1.12', 20 wayland_scanner_dep = dependency('wayland-scanner', required : get_option('wayland') == 'true') 21 libdrm_dep = dependency('libdrm', required : get_option('kms') == 'true') 22 gbm_dep = dependency('gbm', required : get_option('kms') == 'true') 23-has_vulkan_intel_header = cpp.has_header('vulkan/vulkan_intel.h', dependencies: vulkan_dep) 24- 25-if get_option('kms') == 'true' and not has_vulkan_intel_header 26- error('KMS plugin needs the vulkan_intel.h header, but it couldn\'t be found') 27-endif 28 29 build_xcb_ws = xcb_dep.found() and xcb_icccm_dep.found() and get_option('xcb') != 'false' 30 build_wayland_ws = (wayland_client_dep.found() and wayland_protocols_dep.found() and 31 wayland_scanner_dep.found() and get_option('wayland') != 'false') 32-build_kms_ws = libdrm_dep.found() and gbm_dep.found() and has_vulkan_intel_header and get_option('kms') != 'false' 33+build_kms_ws = libdrm_dep.found() and gbm_dep.found() and get_option('kms') != 'false' 34 35 if not build_xcb_ws and not build_wayland_ws and not build_kms_ws 36 error('vkmark needs at least one winsys to work - xcb, wayland or kms') 37diff --git a/src/ws/kms_window_system.cpp b/src/ws/kms_window_system.cpp 38index ca8220f..66618f6 100644 39--- a/src/ws/kms_window_system.cpp 40+++ b/src/ws/kms_window_system.cpp 41@@ -29,7 +29,6 @@ 42 43 #include <xf86drm.h> 44 #include <drm_fourcc.h> 45-#include <vulkan/vulkan_intel.h> 46 47 #include <system_error> 48 #include <fcntl.h> 49@@ -352,7 +351,6 @@ void KMSWindowSystem::init_vulkan(VulkanState& vulkan_) 50 51 vk_image_format = vk::Format::eB8G8R8A8Srgb; 52 create_gbm_bos(); 53- create_drm_fbs(); 54 create_vk_images(); 55 } 56 57@@ -428,68 +426,122 @@ void KMSWindowSystem::create_gbm_bos() 58 } 59 } 60 61-void KMSWindowSystem::create_drm_fbs() 62-{ 63- for (auto const& gbm_bo : gbm_bos) 64- { 65- uint32_t fb = 0; 66- 67- uint32_t handles[4] = {gbm_bo_get_handle(gbm_bo).u32, 0, 0, 0}; 68- uint32_t strides[4] = {gbm_bo_get_stride(gbm_bo), 0, 0, 0}; 69- uint32_t offsets[4] = {0, 0, 0, 0}; 70- 71- auto const ret = drmModeAddFB2( 72- drm_fd, vk_extent.width, vk_extent.height, 73- DRM_FORMAT_XRGB8888, 74- handles, strides, offsets, &fb, 0); 75- 76- if (ret < 0) 77- throw std::system_error{-ret, std::system_category(), "Failed to add drm fb"}; 78+// TODO: Use an official extension to create the VkImages when it becomes 79+// available (e.g. VK_MESAX_external_image_dma_buf) 80 81- drm_fbs.push_back( 82- ManagedResource<uint32_t>{ 83- std::move(fb), 84- [this] (auto& fb) { drmModeRmFB(drm_fd, fb); }}); 85+static int find_memory_type_index(VkPhysicalDevice physical_device, 86+ const VkMemoryRequirements* requirements, 87+ VkMemoryPropertyFlags flags) { 88+ VkPhysicalDeviceMemoryProperties properties; 89+ vkGetPhysicalDeviceMemoryProperties(physical_device, &properties); 90+ for (int i = 0; i <= 31; i++) { 91+ if (((1u << i) & requirements->memoryTypeBits) == 0) 92+ continue; 93+ if ((properties.memoryTypes[i].propertyFlags & flags) != flags) 94+ continue; 95+ return i; 96 } 97+ return -1; 98 } 99 100-// TODO: Use an official extension to create the VkImages when it becomes 101-// available (e.g. VK_MESAX_external_image_dma_buf) 102 void KMSWindowSystem::create_vk_images() 103 { 104- auto const create_dma_buf_image = 105- reinterpret_cast<PFN_vkCreateDmaBufImageINTEL>( 106- vulkan->device().getProcAddr("vkCreateDmaBufImageINTEL")); 107- 108- if (!create_dma_buf_image) 109- throw std::runtime_error{"Failed to get vkCreateDmaBufImageINTEL function pointer"}; 110- 111 for (auto const& gbm_bo : gbm_bos) 112 { 113 auto const fd = ManagedResource<int>{gbm_bo_get_fd(gbm_bo), close}; 114- auto const stride = gbm_bo_get_stride(gbm_bo); 115 116- VkDmaBufImageCreateInfo create_info{}; 117- create_info.sType = static_cast<VkStructureType>(VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL); 118- create_info.fd = fd; 119- create_info.format = static_cast<VkFormat>(vk_image_format); 120- create_info.extent = {vk_extent.width, vk_extent.height, 1}; 121- create_info.strideInBytes = stride; 122+ VkExternalMemoryImageCreateInfoKHR external_image_create_info = { 123+ .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR, 124+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 125+ }; 126+ 127+ uint64_t modifier = DRM_FORMAT_MOD_LINEAR; 128+ VkImageDrmFormatModifierListCreateInfoEXT modifier_info = { 129+ .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, 130+ .drmFormatModifierCount = 1, 131+ .pDrmFormatModifiers = &modifier, 132+ }; 133+ external_image_create_info.pNext = &modifier_info; 134+ 135+ VkImportMemoryFdInfoKHR import_memory_fd_info = { 136+ .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 137+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 138+ .fd = fd, 139+ }; 140+ 141+ VkImageCreateInfo create_info{}; 142+ create_info = { 143+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 144+ .pNext = &external_image_create_info, 145+ .flags = 0, 146+ .imageType = VK_IMAGE_TYPE_2D, 147+ .format = static_cast<VkFormat>(vk_image_format), 148+ .extent = {vk_extent.width, vk_extent.height, 1}, 149+ .mipLevels = 1, 150+ .arrayLayers = 1, 151+ .samples = VK_SAMPLE_COUNT_1_BIT, 152+ .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, 153+ .usage = 0, 154+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 155+ .queueFamilyIndexCount = 0, 156+ .pQueueFamilyIndices = nullptr, 157+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 158+ }; 159 160 VkImage image; 161- VkDeviceMemory device_memory; 162 163- VkResult result = create_dma_buf_image( 164+ VkResult result = vkCreateImage( 165 vulkan->device(), 166 &create_info, 167 nullptr, 168- &device_memory, 169 &image); 170+ if (result != VK_SUCCESS) 171+ { 172+ vk::throwResultException(static_cast<vk::Result>(result), 173+ "vkCreateImage"); 174+ } 175+ 176+ VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = { 177+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 178+ .pNext = &import_memory_fd_info, 179+ .image = image, 180+ }; 181+ 182+ VkMemoryRequirements requirements; 183+ vkGetImageMemoryRequirements(vulkan->device(), image, &requirements); 184+ if (!requirements.memoryTypeBits) { 185+ throw std::runtime_error{"Failed in vkGetImageMemoryRequirements"}; 186+ } 187+ 188+ int index = find_memory_type_index(vulkan->physical_device(), 189+ &requirements, 190+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 191+ if (index < 0) { 192+ throw std::runtime_error{"Failed to get memoryTypeIndex"}; 193+ } 194+ 195+ VkMemoryAllocateInfo memory_allocate_info = { 196+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 197+ .pNext = &dedicated_memory_info, 198+ .allocationSize = requirements.size, 199+ .memoryTypeIndex = (uint32_t)index, 200+ }; 201+ 202+ VkDeviceMemory device_memory = VK_NULL_HANDLE; 203+ result = vkAllocateMemory(vulkan->device(), &memory_allocate_info, 204+ nullptr /* pAllocator */, &device_memory); 205 206 if (result != VK_SUCCESS) 207 { 208 vk::throwResultException(static_cast<vk::Result>(result), 209- "vkCreateDmbBufImageINTEL"); 210+ "vkAllocateMemory"); 211+ } 212+ 213+ result = vkBindImageMemory(vulkan->device(), image, device_memory, 214+ 0 /* memoryOffset */); 215+ if (result != VK_SUCCESS) { 216+ vk::throwResultException(static_cast<vk::Result>(result), 217+ "vkBindImageMemory"); 218 } 219 220 vk_images.push_back( 221@@ -500,6 +552,40 @@ void KMSWindowSystem::create_vk_images() 222 vptr->device().destroyImage(image); 223 vptr->device().freeMemory(device_memory); 224 }}); 225+ 226+ std::array<VkSubresourceLayout, 4> layouts = {}; 227+ const VkImageSubresource image_subresource = { 228+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 229+ .mipLevel = 0, 230+ .arrayLayer = 0, 231+ }; 232+ vkGetImageSubresourceLayout(vulkan->device(), image, 233+ &image_subresource, &layouts[0]); 234+ 235+ uint32_t fb = 0; 236+ 237+ uint32_t handles[4] = {0,}; 238+ uint32_t strides[4] = {0,}; 239+ uint32_t offsets[4] = {0,}; 240+ 241+ for (auto i = 0; i < gbm_bo_get_plane_count(gbm_bo); i++) { 242+ handles[i] = gbm_bo_get_handle(gbm_bo).u32; 243+ offsets[i] = layouts[i].offset; 244+ strides[i] = layouts[i].rowPitch; 245+ } 246+ 247+ auto const ret = drmModeAddFB2( 248+ drm_fd, vk_extent.width, vk_extent.height, 249+ DRM_FORMAT_XRGB8888, 250+ handles, strides, offsets, &fb, 0); 251+ 252+ if (ret < 0) 253+ throw std::system_error{-ret, std::system_category(), "Failed to add drm fb"}; 254+ 255+ drm_fbs.push_back( 256+ ManagedResource<uint32_t>{ 257+ std::move(fb), 258+ [this] (auto& fb) { drmModeRmFB(drm_fd, fb); }}); 259 } 260 } 261 262diff --git a/src/ws/kms_window_system.h b/src/ws/kms_window_system.h 263index 4389ef7..ca304c0 100644 264--- a/src/ws/kms_window_system.h 265+++ b/src/ws/kms_window_system.h 266@@ -68,7 +68,6 @@ public: 267 268 protected: 269 void create_gbm_bos(); 270- void create_drm_fbs(); 271 void create_vk_images(); 272 void wait_for_drm_page_flip_event(); 273 274-- 2752.20.1 276 277