[plasma/kwin] src: vulkan: split VulkanQueue into its own file
Vlad Zahorodnii <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 0a3dab8821fc4861fd2a55fd6eebac74b63f9226 by Vlad Zahorodnii, on behalf of Xaver Hugl.
Committed on 17/08/2026 at 07:12.
Pushed by vladz into branch 'master'.
vulkan: split VulkanQueue into its own file
M +2 -0 src/CMakeLists.txt
M +0 -116 src/vulkan/vulkan_device.cpp
M +1 -37 src/vulkan/vulkan_device.h
A +132 -0 src/vulkan/vulkan_queue.cpp [License: GPL(v2.0+)]
A +55 -0 src/vulkan/vulkan_queue.h [License: GPL(v2.0+)]
https://invent.kde.org/plasma/kwin/-/commit/0a3dab8821fc4861fd2a55fd6eebac74b63f9226
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0afa4080bee..16166b02176 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -229,6 +229,7 @@ target_sources(kwin PRIVATE
virtualkeyboard_dbus.cpp
vulkan/vulkan_device.cpp
vulkan/vulkan_logging.cpp
+ vulkan/vulkan_queue.cpp
vulkan/vulkan_render_time_query.cpp
vulkan/vulkan_swapchain.cpp
vulkan/vulkan_texture.cpp
@@ -681,6 +682,7 @@ install(FILES
install(FILES
vulkan/vulkan_device.h
vulkan/vulkan_logging.h
+ vulkan/vulkan_queue.h
vulkan/vulkan_render_time_query.h
vulkan/vulkan_swapchain.h
vulkan/vulkan_texture.h
diff --git a/src/vulkan/vulkan_device.cpp b/src/vulkan/vulkan_device.cpp
index e6d454eee2e..5bc6f0518ab 100644
--- a/src/vulkan/vulkan_device.cpp
+++ b/src/vulkan/vulkan_device.cpp
@@ -444,122 +444,6 @@ void VulkanDevice::waitIdle()
m_graphicsQueue->waitIdle();
}
-VulkanQueue::VulkanQueue(VulkanDevice *device, uint32_t familyIndex, vk::raii::Queue &&handle, vk::raii::CommandPool &&commandPool)
- : m_device(device)
- , m_familyIndex(familyIndex)
- , m_handle(std::move(handle))
- , m_commandPool(std::move(commandPool))
-{
-}
-
-VulkanQueue::~VulkanQueue()
-{
- m_handle.waitIdle();
-}
-
-uint32_t VulkanQueue::familyIndex() const
-{
- return m_familyIndex;
-}
-
-const vk::raii::Queue &VulkanQueue::handle() const
-{
- return m_handle;
-}
-
-vk::raii::CommandBuffer VulkanQueue::createCommandBuffer()
-{
- // clean up old command buffers first
- for (auto it = m_submittedCommandBuffers.begin(); it != m_submittedCommandBuffers.end();) {
- const SubmittedCommand &cmd = *it;
- // TODO use a QSocketNotifier per submission to do this asynchronously?
- if (cmd.completionSyncFd.isReadable()) {
- it = m_submittedCommandBuffers.erase(it);
- } else {
- it++;
- }
- }
-
- auto [result, buffers] = m_device->logicalDevice().allocateCommandBuffers(vk::CommandBufferAllocateInfo{
- m_commandPool,
- vk::CommandBufferLevel::ePrimary,
- 1,
- });
- if (result != vk::Result::eSuccess) {
- qCWarning(KWIN_VULKAN) << "Failed to create a command buffer" << vk::to_string(result);
- return nullptr;
- }
- return std::move(buffers.front());
-}
-
-std::optional<FileDescriptor> VulkanQueue::submit(vk::raii::CommandBuffer &&buffer, FileDescriptor &&syncFd)
-{
- vk::ExportFenceCreateInfo exportInfo{
- vk::ExternalFenceHandleTypeFlagBits::eSyncFd,
- };
- auto [fenceResult, fence] = m_device->logicalDevice().createFence(vk::FenceCreateInfo{
- vk::FenceCreateFlags{},
- &exportInfo,
- });
- if (fenceResult != vk::Result::eSuccess) {
- return std::nullopt;
- }
- std::vector<vk::Semaphore> waitSemaphores;
- std::vector<vk::PipelineStageFlags> waitFlags;
- auto waitSemaphore = m_device->importSemaphore(std::move(syncFd));
- if (waitSemaphore.has_value()) {
- waitSemaphores.push_back(*waitSemaphore);
- waitFlags.push_back(vk::PipelineStageFlagBits::eAllCommands);
- }
- vk::Result result = m_handle.submit(vk::SubmitInfo{
- waitSemaphores,
- waitFlags,
- *buffer,
- {},
- },
- fence);
- if (result == vk::Result::eErrorDeviceLost) {
- m_device->handleDeviceLoss();
- return std::nullopt;
- } else if (result != vk::Result::eSuccess) {
- return std::nullopt;
- }
- const auto [fdResult, fd] = m_device->logicalDevice().getFenceFdKHR(vk::FenceGetFdInfoKHR{
- fence,
- vk::ExternalFenceHandleTypeFlagBits::eSyncFd,
- });
- if (fdResult != vk::Result::eSuccess) {
- return std::nullopt;
- }
- FileDescriptor ret{fd};
- m_submittedCommandBuffers.push_back(SubmittedCommand{
- .waitSemaphore = waitSemaphore ? std::move(*waitSemaphore) : nullptr,
- .buffer = std::move(buffer),
- .completionSyncFd = ret.duplicate(),
- });
- return ret;
-}
-
-void VulkanQueue::waitIdle()
-{
- m_handle.waitIdle();
-}
-
-std::unique_ptr<VulkanQueue> VulkanQueue::create(VulkanDevice *device, uint32_t familyIndex)
-{
- auto handle = device->logicalDevice().getQueue(familyIndex, 0);
-
- auto [result, cmdPool] = device->logicalDevice().createCommandPool(vk::CommandPoolCreateInfo{
- vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
- familyIndex,
- });
- if (result != vk::Result::eSuccess) {
- qCCritical(KWIN_VULKAN) << "creating a command pool failed:" << vk::to_string(result);
- return nullptr;
- }
- return std::make_unique<VulkanQueue>(device, familyIndex, std::move(handle), std::move(cmdPool));
-}
-
}
#include "moc_vulkan_device.cpp"
diff --git a/src/vulkan/vulkan_device.h b/src/vulkan/vulkan_device.h
index 336f188b92e..6d939c69add 100644
--- a/src/vulkan/vulkan_device.h
+++ b/src/vulkan/vulkan_device.h
@@ -10,14 +10,13 @@
#include "core/drm_formats.h"
#include "kwin_export.h"
#include "utils/filedescriptor.h"
+#include "vulkan_queue.h"
#include <QHash>
#include <QObject>
#include <QVector>
-#include <deque>
#include <memory>
#include <optional>
-#include <vulkan/vulkan_raii.hpp>
namespace KWin
{
@@ -26,41 +25,6 @@ class VulkanTexture;
class GraphicsBuffer;
struct DmaBufAttributes;
class RenderDevice;
-class VulkanDevice;
-
-class KWIN_EXPORT VulkanQueue
-{
-public:
- explicit VulkanQueue(VulkanDevice *device, uint32_t familyIndex, vk::raii::Queue &&handle, vk::raii::CommandPool &&commandPool);
- ~VulkanQueue();
-
- uint32_t familyIndex() const;
- const vk::raii::Queue &handle() const;
-
- vk::raii::CommandBuffer createCommandBuffer();
- std::optional<FileDescriptor> submit(vk::raii::CommandBuffer &&buffer, FileDescriptor &&syncFd);
-
- /**
- * NOTE avoid using this if at all possible, it's obviously terrible for performance!
- */
- void waitIdle();
-
- static std::unique_ptr<VulkanQueue> create(VulkanDevice *device, uint32_t familyIndex);
-
-private:
- struct SubmittedCommand
- {
- vk::raii::Semaphore waitSemaphore;
- vk::raii::CommandBuffer buffer;
- FileDescriptor completionSyncFd;
- };
-
- VulkanDevice *const m_device;
- const uint32_t m_familyIndex;
- const vk::raii::Queue m_handle;
- const vk::raii::CommandPool m_commandPool;
- std::deque<SubmittedCommand> m_submittedCommandBuffers;
-};
class KWIN_EXPORT VulkanDevice : public QObject
{
diff --git a/src/vulkan/vulkan_queue.cpp b/src/vulkan/vulkan_queue.cpp
new file mode 100644
index 00000000000..fc9532ca4b4
--- /dev/null
+++ b/src/vulkan/vulkan_queue.cpp
@@ -0,0 +1,132 @@
+/*
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ SPDX-FileCopyrightText: 2023-2026 Xaver Hugl <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#include "vulkan_queue.h"
+#include "vulkan_device.h"
+#include "vulkan_logging.h"
+
+namespace KWin
+{
+
+VulkanQueue::VulkanQueue(VulkanDevice *device, uint32_t familyIndex, vk::raii::Queue &&handle, vk::raii::CommandPool &&commandPool)
+ : m_device(device)
+ , m_familyIndex(familyIndex)
+ , m_handle(std::move(handle))
+ , m_commandPool(std::move(commandPool))
+{
+}
+
+VulkanQueue::~VulkanQueue()
+{
+ m_handle.waitIdle();
+}
+
+uint32_t VulkanQueue::familyIndex() const
+{
+ return m_familyIndex;
+}
+
+const vk::raii::Queue &VulkanQueue::handle() const
+{
+ return m_handle;
+}
+
+vk::raii::CommandBuffer VulkanQueue::createCommandBuffer()
+{
+ // clean up old command buffers first
+ for (auto it = m_submittedCommandBuffers.begin(); it != m_submittedCommandBuffers.end();) {
+ const SubmittedCommand &cmd = *it;
+ // TODO use a QSocketNotifier per submission to do this asynchronously?
+ if (cmd.completionSyncFd.isReadable()) {
+ it = m_submittedCommandBuffers.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ auto [result, buffers] = m_device->logicalDevice().allocateCommandBuffers(vk::CommandBufferAllocateInfo{
+ m_commandPool,
+ vk::CommandBufferLevel::ePrimary,
+ 1,
+ });
+ if (result != vk::Result::eSuccess) {
+ qCWarning(KWIN_VULKAN) << "Failed to create a command buffer" << vk::to_string(result);
+ return nullptr;
+ }
+ return std::move(buffers.front());
+}
+
+std::optional<FileDescriptor> VulkanQueue::submit(vk::raii::CommandBuffer &&buffer, FileDescriptor &&syncFd)
+{
+ vk::ExportFenceCreateInfo exportInfo{
+ vk::ExternalFenceHandleTypeFlagBits::eSyncFd,
+ };
+ auto [fenceResult, fence] = m_device->logicalDevice().createFence(vk::FenceCreateInfo{
+ vk::FenceCreateFlags{},
+ &exportInfo,
+ });
+ if (fenceResult != vk::Result::eSuccess) {
+ return std::nullopt;
+ }
+ std::vector<vk::Semaphore> waitSemaphores;
+ std::vector<vk::PipelineStageFlags> waitFlags;
+ auto waitSemaphore = m_device->importSemaphore(std::move(syncFd));
+ if (waitSemaphore.has_value()) {
+ waitSemaphores.push_back(*waitSemaphore);
+ waitFlags.push_back(vk::PipelineStageFlagBits::eAllCommands);
+ }
+ vk::Result result = m_handle.submit(vk::SubmitInfo{
+ waitSemaphores,
+ waitFlags,
+ *buffer,
+ {},
+ },
+ fence);
+ if (result == vk::Result::eErrorDeviceLost) {
+ m_device->handleDeviceLoss();
+ return std::nullopt;
+ } else if (result != vk::Result::eSuccess) {
+ return std::nullopt;
+ }
+ const auto [fdResult, fd] = m_device->logicalDevice().getFenceFdKHR(vk::FenceGetFdInfoKHR{
+ fence,
+ vk::ExternalFenceHandleTypeFlagBits::eSyncFd,
+ });
+ if (fdResult != vk::Result::eSuccess) {
+ return std::nullopt;
+ }
+ FileDescriptor ret{fd};
+ m_submittedCommandBuffers.push_back(SubmittedCommand{
+ .waitSemaphore = waitSemaphore ? std::move(*waitSemaphore) : nullptr,
+ .buffer = std::move(buffer),
+ .completionSyncFd = ret.duplicate(),
+ });
+ return ret;
+}
+
+void VulkanQueue::waitIdle()
+{
+ m_handle.waitIdle();
+}
+
+std::unique_ptr<VulkanQueue> VulkanQueue::create(VulkanDevice *device, uint32_t familyIndex)
+{
+ auto handle = device->logicalDevice().getQueue(familyIndex, 0);
+
+ auto [result, cmdPool] = device->logicalDevice().createCommandPool(vk::CommandPoolCreateInfo{
+ vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
+ familyIndex,
+ });
+ if (result != vk::Result::eSuccess) {
+ qCCritical(KWIN_VULKAN) << "creating a command pool failed:" << vk::to_string(result);
+ return nullptr;
+ }
+ return std::make_unique<VulkanQueue>(device, familyIndex, std::move(handle), std::move(cmdPool));
+}
+
+}
diff --git a/src/vulkan/vulkan_queue.h b/src/vulkan/vulkan_queue.h
new file mode 100644
index 00000000000..f89536d5e72
--- /dev/null
+++ b/src/vulkan/vulkan_queue.h
@@ -0,0 +1,55 @@
+/*
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ SPDX-FileCopyrightText: 2023-2026 Xaver Hugl <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#pragma once
+#include "kwin_export.h"
+#include "utils/filedescriptor.h"
+
+#include <deque>
+#include <vulkan/vulkan_raii.hpp>
+
+namespace KWin
+{
+
+class VulkanDevice;
+
+class KWIN_EXPORT VulkanQueue
+{
+public:
+ explicit VulkanQueue(VulkanDevice *device, uint32_t familyIndex, vk::raii::Queue &&handle, vk::raii::CommandPool &&commandPool);
+ ~VulkanQueue();
+
+ uint32_t familyIndex() const;
+ const vk::raii::Queue &handle() const;
+
+ vk::raii::CommandBuffer createCommandBuffer();
+ std::optional<FileDescriptor> submit(vk::raii::CommandBuffer &&buffer, FileDescriptor &&syncFd);
+
+ /**
+ * NOTE avoid using this if at all possible, it's obviously terrible for performance!
+ */
+ void waitIdle();
+
+ static std::unique_ptr<VulkanQueue> create(VulkanDevice *device, uint32_t familyIndex);
+
+private:
+ struct SubmittedCommand
+ {
+ vk::raii::Semaphore waitSemaphore;
+ vk::raii::CommandBuffer buffer;
+ FileDescriptor completionSyncFd;
+ };
+
+ VulkanDevice *const m_device;
+ const uint32_t m_familyIndex;
+ const vk::raii::Queue m_handle;
+ const vk::raii::CommandPool m_commandPool;
+ std::deque<SubmittedCommand> m_submittedCommandBuffers;
+};
+
+}