distribution/packages/graphics/vulkan/vkmark/patches/vkmark-999.01-drop-dependency-on-vkCreateDmaBufImageINTEL.patch
2022-07-01 16:17:33 -04:00

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();