From 51c7eb0c8c1cd4872eec176775276cca3565a0a6 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Fri, 9 Sep 2022 18:32:03 +0300 Subject: [PATCH 1/4] github: Build with both ubuntu-20.04 and ubuntu-22.04 in CI --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbb5682..b60ad80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,10 @@ on: jobs: build: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-20.04, ubuntu-22.04] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - name: Install dependencies From 7bbe275e49045237f2cdbc2f441a394b562b0aa5 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Fri, 9 Sep 2022 18:08:12 +0300 Subject: [PATCH 2/4] core: Improve log message consistency --- src/vulkan_state.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vulkan_state.cpp b/src/vulkan_state.cpp index 6f50673..fbd789c 100644 --- a/src/vulkan_state.cpp +++ b/src/vulkan_state.cpp @@ -44,7 +44,7 @@ std::vector VulkanState::available_devices(VulkanWSI& vulkan { if (!vulkan_wsi.is_physical_device_supported(*it_device)) { - Log::debug("device with uuid %s is not supported by window system integration layer", + Log::debug("Device with uuid %s is not supported by window system integration layer\n", static_cast(it_device->getProperties().pipelineCacheUUID).representation().data()); it_device = available_devices.erase(it_device); } @@ -193,17 +193,17 @@ void VulkanState::create_command_pool() vk::PhysicalDevice ChooseFirstSupportedStrategy::operator()(const std::vector& available_devices) { - Log::debug("Trying to use first supported device.\n"); + Log::debug("Trying to use first supported device\n"); for (auto const& physical_device : available_devices) { if (find_queue_family_index(physical_device, vk::QueueFlagBits::eGraphics).second) { - Log::debug("First supported device choosen!\n"); + Log::debug("First supported device chosen\n"); return physical_device; } - Log::debug("device with uuid %s skipped!\n", + Log::debug("Device with uuid %s skipped\n", static_cast(physical_device.getProperties().pipelineCacheUUID).representation().data() ); } @@ -213,7 +213,7 @@ vk::PhysicalDevice ChooseFirstSupportedStrategy::operator()(const std::vector& available_devices) { - Log::debug("Trying to use device with specified UUID %s.\n", + Log::debug("Trying to use device with specified UUID %s\n", m_selected_device_uuid.representation().data()); for (auto const& physical_device: available_devices) @@ -227,5 +227,5 @@ vk::PhysicalDevice ChooseByUUIDStrategy::operator()(const std::vector Date: Fri, 9 Sep 2022 17:48:44 +0300 Subject: [PATCH 3/4] core,ws: Allow WSI backends to request device extensions The backends were able to request instance extensions, support requesting device extensions, too. --- src/vulkan_state.cpp | 5 ++--- src/vulkan_wsi.h | 8 +++++++- src/ws/kms_window_system.cpp | 2 +- src/ws/kms_window_system.h | 2 +- src/ws/native_system.h | 2 +- src/ws/swapchain_window_system.cpp | 4 ++-- src/ws/swapchain_window_system.h | 2 +- src/ws/wayland_native_system.cpp | 2 +- src/ws/wayland_native_system.h | 2 +- src/ws/xcb_native_system.cpp | 2 +- src/ws/xcb_native_system.h | 2 +- tests/null_window_system.h | 2 +- tests/test_window_system_plugin.cpp | 2 +- tests/window_system_loader_test.cpp | 2 +- 14 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/vulkan_state.cpp b/src/vulkan_state.cpp index fbd789c..b1973ed 100644 --- a/src/vulkan_state.cpp +++ b/src/vulkan_state.cpp @@ -87,7 +87,7 @@ void VulkanState::create_instance(VulkanWSI& vulkan_wsi) auto const app_info = vk::ApplicationInfo{} .setPApplicationName("vkmark"); - std::vector enabled_extensions{vulkan_wsi.vulkan_extensions()}; + std::vector enabled_extensions{vulkan_wsi.required_extensions().instance}; enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); auto const create_info = vk::InstanceCreateInfo{} @@ -159,8 +159,7 @@ void VulkanState::create_logical_device(VulkanWSI& vulkan_wsi) Log::debug("VulkanState: Using queue family index %d for rendering\n", graphics_queue_family_index()); - std::array enabled_extensions{ - {VK_KHR_SWAPCHAIN_EXTENSION_NAME}}; + std::vector enabled_extensions{vulkan_wsi.required_extensions().device}; auto const device_features = vk::PhysicalDeviceFeatures{} .setSamplerAnisotropy(true); diff --git a/src/vulkan_wsi.h b/src/vulkan_wsi.h index f8c50eb..22e87f1 100644 --- a/src/vulkan_wsi.h +++ b/src/vulkan_wsi.h @@ -32,7 +32,13 @@ class VulkanWSI public: virtual ~VulkanWSI() = default; - virtual std::vector vulkan_extensions() = 0; + struct Extensions + { + std::vector instance; + std::vector device; + }; + + virtual Extensions required_extensions() = 0; virtual bool is_physical_device_supported(vk::PhysicalDevice const& pd) = 0; virtual std::vector physical_device_queue_family_indices( vk::PhysicalDevice const& pd) = 0; diff --git a/src/ws/kms_window_system.cpp b/src/ws/kms_window_system.cpp index ca8220f..6132e64 100644 --- a/src/ws/kms_window_system.cpp +++ b/src/ws/kms_window_system.cpp @@ -533,7 +533,7 @@ void KMSWindowSystem::wait_for_drm_page_flip_event() } } -std::vector KMSWindowSystem::vulkan_extensions() +VulkanWSI::Extensions KMSWindowSystem::required_extensions() { return {}; } diff --git a/src/ws/kms_window_system.h b/src/ws/kms_window_system.h index 4389ef7..20a067f 100644 --- a/src/ws/kms_window_system.h +++ b/src/ws/kms_window_system.h @@ -61,7 +61,7 @@ class KMSWindowSystem : public WindowSystem, public VulkanWSI bool should_quit() override; // VulkanWSI - std::vector vulkan_extensions() override; + Extensions required_extensions() override; bool is_physical_device_supported(vk::PhysicalDevice const& pd) override; std::vector physical_device_queue_family_indices( vk::PhysicalDevice const& pd) override; diff --git a/src/ws/native_system.h b/src/ws/native_system.h index 076948e..cbe073a 100644 --- a/src/ws/native_system.h +++ b/src/ws/native_system.h @@ -34,7 +34,7 @@ class NativeSystem public: virtual ~NativeSystem() = default; - virtual std::vector vulkan_extensions() = 0; + virtual std::vector instance_extensions() = 0; virtual uint32_t get_presentation_queue_family_index(vk::PhysicalDevice const& pd) = 0; virtual bool should_quit() = 0; virtual vk::Extent2D get_vk_extent() = 0; diff --git a/src/ws/swapchain_window_system.cpp b/src/ws/swapchain_window_system.cpp index d38fa6b..9f9fba3 100644 --- a/src/ws/swapchain_window_system.cpp +++ b/src/ws/swapchain_window_system.cpp @@ -251,9 +251,9 @@ ManagedResource SwapchainWindowSystem::create_vk_swapchain() [this] (auto& s) { vulkan->device().destroySwapchainKHR(s); }}; } -std::vector SwapchainWindowSystem::vulkan_extensions() +VulkanWSI::Extensions SwapchainWindowSystem::required_extensions() { - return native->vulkan_extensions(); + return {native->instance_extensions(), {VK_KHR_SWAPCHAIN_EXTENSION_NAME}}; } bool SwapchainWindowSystem::is_physical_device_supported(vk::PhysicalDevice const& pd) diff --git a/src/ws/swapchain_window_system.h b/src/ws/swapchain_window_system.h index c3b2780..412b924 100644 --- a/src/ws/swapchain_window_system.h +++ b/src/ws/swapchain_window_system.h @@ -51,7 +51,7 @@ class SwapchainWindowSystem : public WindowSystem, public VulkanWSI bool should_quit() override; // VulkanWSI - std::vector vulkan_extensions() override; + Extensions required_extensions() override; bool is_physical_device_supported(vk::PhysicalDevice const& pd) override; std::vector physical_device_queue_family_indices( vk::PhysicalDevice const& pd) override; diff --git a/src/ws/wayland_native_system.cpp b/src/ws/wayland_native_system.cpp index 642d8fe..816a7b9 100644 --- a/src/ws/wayland_native_system.cpp +++ b/src/ws/wayland_native_system.cpp @@ -145,7 +145,7 @@ WaylandNativeSystem::WaylandNativeSystem(int width, int height) create_native_window(); } -std::vector WaylandNativeSystem::vulkan_extensions() +std::vector WaylandNativeSystem::instance_extensions() { return {VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}; } diff --git a/src/ws/wayland_native_system.h b/src/ws/wayland_native_system.h index 400c358..01cdbaa 100644 --- a/src/ws/wayland_native_system.h +++ b/src/ws/wayland_native_system.h @@ -35,7 +35,7 @@ class WaylandNativeSystem : public NativeSystem public: WaylandNativeSystem(int width, int height); - std::vector vulkan_extensions() override; + std::vector instance_extensions() override; uint32_t get_presentation_queue_family_index(vk::PhysicalDevice const& pd) override; bool should_quit() override; vk::Extent2D get_vk_extent() override; diff --git a/src/ws/xcb_native_system.cpp b/src/ws/xcb_native_system.cpp index 59c84f0..b683772 100644 --- a/src/ws/xcb_native_system.cpp +++ b/src/ws/xcb_native_system.cpp @@ -47,7 +47,7 @@ XcbNativeSystem::~XcbNativeSystem() xcb_disconnect(connection); } -std::vector XcbNativeSystem::vulkan_extensions() +std::vector XcbNativeSystem::instance_extensions() { return {VK_KHR_XCB_SURFACE_EXTENSION_NAME}; } diff --git a/src/ws/xcb_native_system.h b/src/ws/xcb_native_system.h index 7fcc44a..dadc32f 100644 --- a/src/ws/xcb_native_system.h +++ b/src/ws/xcb_native_system.h @@ -35,7 +35,7 @@ class XcbNativeSystem : public NativeSystem XcbNativeSystem(int width, int height, xcb_visualid_t visual_id); ~XcbNativeSystem(); - std::vector vulkan_extensions() override; + std::vector instance_extensions() override; uint32_t get_presentation_queue_family_index(vk::PhysicalDevice const& pd) override; bool should_quit() override; vk::Extent2D get_vk_extent() override; diff --git a/tests/null_window_system.h b/tests/null_window_system.h index bc01276..b7cc9ba 100644 --- a/tests/null_window_system.h +++ b/tests/null_window_system.h @@ -39,7 +39,7 @@ class NullWindowSystem : public WindowSystem, public VulkanWSI bool should_quit() override { return false; } - std::vector vulkan_extensions() override { return {}; } + Extensions required_extensions() override { return {}; } bool is_physical_device_supported(vk::PhysicalDevice const&) override { return true; } std::vector physical_device_queue_family_indices( vk::PhysicalDevice const&) override diff --git a/tests/test_window_system_plugin.cpp b/tests/test_window_system_plugin.cpp index 7877c8e..a562958 100644 --- a/tests/test_window_system_plugin.cpp +++ b/tests/test_window_system_plugin.cpp @@ -32,7 +32,7 @@ class TestWindowSystem : public NullWindowSystem { public: TestWindowSystem(std::string const& id) : id{id} {} - std::vector vulkan_extensions() override { return {id.c_str()}; } + Extensions required_extensions() override { return {{id.c_str()}, {}}; } private: std::string const id; diff --git a/tests/window_system_loader_test.cpp b/tests/window_system_loader_test.cpp index 8aed335..c458e61 100644 --- a/tests/window_system_loader_test.cpp +++ b/tests/window_system_loader_test.cpp @@ -84,7 +84,7 @@ class TestWindowSystems int window_system_id(WindowSystem& ws) { - return std::stoi(ws.vulkan_wsi().vulkan_extensions()[0]); + return std::stoi(ws.vulkan_wsi().required_extensions().instance[0]); } } From dd75130a7ddf747eb7fd755946e84baf98a6e05f Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Fri, 9 Sep 2022 16:23:40 +0300 Subject: [PATCH 4/4] kms: Use VK_EXT_external_memory_dmabuf to create dmabuf-backed Vulkan images Drop the vkCreateDmaBufImageINTEL extension function and use the functionality provided by the official VK_EXT_external_memory_dmabuf extension to create dmabuf-backed Vulkan images. Fixes #33 Co-authored-by: Jeffy Chen --- meson.build | 7 +- src/ws/kms_window_system.cpp | 132 +++++++++++++++++++++++------------ 2 files changed, 89 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 6132e64..fc02eae 100644 --- a/src/ws/kms_window_system.cpp +++ b/src/ws/kms_window_system.cpp @@ -29,8 +29,8 @@ #include #include -#include +#include #include #include #include @@ -270,6 +270,24 @@ void restore_vt(int) global_vt_state->restore(); } +uint32_t find_memory_type_index(vk::PhysicalDevice const& physical_device, + vk::MemoryRequirements const& requirements, + vk::MemoryPropertyFlags flags) +{ + auto const properties = physical_device.getMemoryProperties(); + + for (uint32_t i = 0; i < properties.memoryTypeCount; i++) + { + if ((requirements.memoryTypeBits & (1 << i)) && + (properties.memoryTypes[i].propertyFlags & flags) == flags) + { + return i; + } + } + + throw std::runtime_error{"Coudn't find matching memory type"}; +} + } VTState::VTState() @@ -433,14 +451,20 @@ void KMSWindowSystem::create_drm_fbs() for (auto const& gbm_bo : gbm_bos) { uint32_t fb = 0; + uint32_t handles[4] = {0}; + uint32_t strides[4] = {0}; + uint32_t offsets[4] = {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}; + for (auto i = 0; i < gbm_bo_get_plane_count(gbm_bo); i++) + { + handles[i] = gbm_bo_get_handle_for_plane(gbm_bo, i).u32; + offsets[i] = gbm_bo_get_offset(gbm_bo, i); + strides[i] = gbm_bo_get_stride_for_plane(gbm_bo, i); + } auto const ret = drmModeAddFB2( drm_fd, vk_extent.width, vk_extent.height, - DRM_FORMAT_XRGB8888, + gbm_bo_get_format(gbm_bo), handles, strides, offsets, &fb, 0); if (ret < 0) @@ -453,52 +477,65 @@ void KMSWindowSystem::create_drm_fbs() } } -// 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; - - VkImage image; - VkDeviceMemory device_memory; - - VkResult result = create_dma_buf_image( - vulkan->device(), - &create_info, - nullptr, - &device_memory, - &image); - - if (result != VK_SUCCESS) - { - vk::throwResultException(static_cast(result), - "vkCreateDmbBufImageINTEL"); - } + uint64_t modifier = gbm_bo_get_modifier(gbm_bo); + + auto const modifier_info = vk::ImageDrmFormatModifierListCreateInfoEXT{} + .setDrmFormatModifierCount(1) + .setPDrmFormatModifiers(&modifier); + auto const external_memory_create_info = vk::ExternalMemoryImageCreateInfoKHR{} + .setHandleTypes(vk::ExternalMemoryHandleTypeFlagBitsKHR::eDmaBufEXT) + .setPNext(&modifier_info); + auto const image_create_info = vk::ImageCreateInfo{} + .setPNext(&external_memory_create_info) + .setImageType(vk::ImageType::e2D) + .setFormat(vk_image_format) + .setExtent({vk_extent.width, vk_extent.height, 1}) + .setMipLevels(1) + .setArrayLayers(1) + .setSamples(vk::SampleCountFlagBits::e1) + .setTiling(vk::ImageTiling::eDrmFormatModifierEXT) + .setUsage(vk::ImageUsageFlagBits::eColorAttachment) + .setSharingMode(vk::SharingMode::eExclusive) + .setInitialLayout(vk::ImageLayout::eUndefined); + + auto vk_image = ManagedResource{ + vulkan->device().createImage(image_create_info), + [vptr=vulkan] (auto const& i) { vptr->device().destroyImage(i); }}; + + auto const requirements = vulkan->device().getImageMemoryRequirements(vk_image); + uint32_t index = find_memory_type_index(vulkan->physical_device(), + requirements, + vk::MemoryPropertyFlagBits::eDeviceLocal); + + auto const import_memory_fd_info = vk::ImportMemoryFdInfoKHR{} + .setHandleType(vk::ExternalMemoryHandleTypeFlagBitsKHR::eDmaBufEXT) + .setFd(fd); + auto const dedicated_allocate_info = vk::MemoryDedicatedAllocateInfoKHR{} + .setPNext(&import_memory_fd_info) + .setImage(vk_image); + auto const memory_allocate_info = vk::MemoryAllocateInfo{} + .setPNext(&dedicated_allocate_info) + .setAllocationSize(requirements.size) + .setMemoryTypeIndex((uint32_t)index); + + auto device_memory = ManagedResource{ + vulkan->device().allocateMemory(memory_allocate_info), + [vptr=vulkan] (auto const& m) { vptr->device().freeMemory(m); }}; + + vulkan->device().bindImageMemory(vk_image, device_memory, 0); vk_images.push_back( ManagedResource{ - vk::Image{image}, - [vptr=vulkan, device_memory] (auto& image) + vk_image.steal(), + [vptr=vulkan, mem=device_memory.steal()] (auto const& image) { vptr->device().destroyImage(image); - vptr->device().freeMemory(device_memory); + vptr->device().freeMemory(mem); }}); } } @@ -535,12 +572,19 @@ void KMSWindowSystem::wait_for_drm_page_flip_event() VulkanWSI::Extensions KMSWindowSystem::required_extensions() { - return {}; + return {{}, {VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME}}; } -bool KMSWindowSystem::is_physical_device_supported(vk::PhysicalDevice const&) +bool KMSWindowSystem::is_physical_device_supported(vk::PhysicalDevice const& physdev) { - return true; + auto const props = physdev.enumerateDeviceExtensionProperties(); + auto const iter = std::find_if( + props.begin(), props.end(), + [](vk::ExtensionProperties prop) + { + return std::string{VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME} == prop.extensionName; + }); + return iter != props.end(); } std::vector KMSWindowSystem::physical_device_queue_family_indices(