273 lines
10 KiB
Diff
273 lines
10 KiB
Diff
From 0dd62e9adff82d51ed67c625a4f456a8e5f1a2e2 Mon Sep 17 00:00:00 2001
|
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
|
Date: Mon, 23 May 2022 10:57:27 +0800
|
|
Subject: [PATCH] kms: Drop dependency on vkCreateDmaBufImageINTEL
|
|
|
|
Based on chromium's gpu/vulkan/vulkan_image{_linux,}.cc
|
|
|
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
|
---
|
|
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..18c5384 100644
|
|
--- a/src/ws/kms_window_system.cpp
|
|
+++ b/src/ws/kms_window_system.cpp
|
|
@@ -29,7 +29,6 @@
|
|
|
|
#include <xf86drm.h>
|
|
#include <drm_fourcc.h>
|
|
-#include <vulkan/vulkan_intel.h>
|
|
|
|
#include <system_error>
|
|
#include <fcntl.h>
|
|
@@ -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<uint32_t>{
|
|
- 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<PFN_vkCreateDmaBufImageINTEL>(
|
|
- 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<int>{gbm_bo_get_fd(gbm_bo), close};
|
|
- auto const stride = gbm_bo_get_stride(gbm_bo);
|
|
|
|
- VkDmaBufImageCreateInfo create_info{};
|
|
- create_info.sType = static_cast<VkStructureType>(VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL);
|
|
- create_info.fd = fd;
|
|
- create_info.format = static_cast<VkFormat>(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<VkFormat>(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<vk::Result>(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<vk::Result>(result),
|
|
- "vkCreateDmbBufImageINTEL");
|
|
+ "vkAllocateMemory");
|
|
+ }
|
|
+
|
|
+ result = vkBindImageMemory(vulkan->device(), image, device_memory,
|
|
+ 0 /* memoryOffset */);
|
|
+ if (result != VK_SUCCESS) {
|
|
+ vk::throwResultException(static_cast<vk::Result>(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<VkSubresourceLayout, 4> 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<uint32_t>{
|
|
+ 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 @@ class KMSWindowSystem : public WindowSystem, public VulkanWSI
|
|
|
|
protected:
|
|
void create_gbm_bos();
|
|
- void create_drm_fbs();
|
|
void create_vk_images();
|
|
void wait_for_drm_page_flip_event();
|
|
|