summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2022-10-27 14:33:16 +0200
committerPeter Varga <pvarga@inf.u-szeged.hu>2022-11-10 09:42:16 +0100
commitb32f5e5b495ef73f25d3156d24a83fffd33f02be (patch)
tree5651504ad55f3609163c85879e0ac6d726c6db27
parent6fb80f47941b555f1a9455d3bd3d189b90092b60 (diff)
Add Vulkan rendering support
Updates 3rdparty: * 8b7ce4ef70d Make GrVkImage external Task-number: QTBUG-107669 Change-Id: If7fbe1f20538598dd1d4f3a67be17c9f7d06a3cd Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
m---------src/3rdparty0
-rw-r--r--src/core/CMakeLists.txt5
-rw-r--r--src/core/api/configure.cmake10
-rw-r--r--src/core/api/qtwebenginecoreglobal.cpp33
-rw-r--r--src/core/chromium_overrides.cpp43
-rw-r--r--src/core/compositor/compositor.cpp20
-rw-r--r--src/core/compositor/compositor.h18
-rw-r--r--src/core/compositor/display_skia_output_device.cpp278
-rw-r--r--src/core/compositor/display_skia_output_device.h14
-rw-r--r--src/core/compositor/vulkan_implementation_qt.cpp153
-rw-r--r--src/core/compositor/vulkan_implementation_qt.h47
-rw-r--r--src/core/ozone/ozone_platform_qt.cpp17
-rw-r--r--src/core/ozone/surface_factory_qt.cpp19
-rw-r--r--src/core/ozone/surface_factory_qt.h4
-rw-r--r--src/core/render_widget_host_view_qt_delegate_item.cpp32
-rw-r--r--src/core/render_widget_host_view_qt_delegate_item.h1
-rw-r--r--src/core/web_engine_context.cpp13
-rw-r--r--src/webenginequick/api/qtwebenginequickglobal.cpp5
18 files changed, 681 insertions, 31 deletions
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 9457651ead9b7034edb37532c2f33a558b1700b
+Subproject 8b7ce4ef70d2e3588f3ae4143356b77edd5caae
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c0a2441d3..f50b48807 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -204,6 +204,11 @@ foreach(arch ${archs})
ozone/gl_surface_glx_qt.cpp ozone/gl_surface_glx_qt.h
)
+ extend_gn_target(${buildGn} CONDITION QT_FEATURE_webengine_vulkan
+ SOURCES
+ compositor/vulkan_implementation_qt.cpp compositor/vulkan_implementation_qt.h
+ )
+
extend_gn_target(${buildGn} CONDITION QT_FEATURE_opengl
SOURCES
compositor/compositor_resource_fence.cpp compositor/compositor_resource_fence.h
diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake
index 4e54ad2a9..333039a42 100644
--- a/src/core/api/configure.cmake
+++ b/src/core/api/configure.cmake
@@ -150,6 +150,12 @@ qt_feature("webengine-sanitizer" PRIVATE
AUTODETECT CLANG
CONDITION CLANG AND ECM_ENABLE_SANITIZERS
)
+qt_feature("webengine-vulkan" PRIVATE
+ SECTION "WebEngine"
+ LABEL "Vulkan support"
+ PURPOSE "Enables support for Vulkan rendering"
+ CONDITION QT_FEATURE_vulkan
+)
# internal testing feature
qt_feature("webengine-system-poppler" PRIVATE
LABEL "popler"
@@ -178,6 +184,10 @@ qt_configure_add_summary_entry(
CONDITION UNIX
)
qt_configure_add_summary_entry(
+ ARGS "webengine-vulkan"
+ CONDITION QT_FEATURE_vulkan
+)
+qt_configure_add_summary_entry(
ARGS "webengine-v8-snapshot-support"
CONDITION UNIX AND cross_compile
)
diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp
index 3c2eefdf5..1dded1086 100644
--- a/src/core/api/qtwebenginecoreglobal.cpp
+++ b/src/core/api/qtwebenginecoreglobal.cpp
@@ -195,22 +195,25 @@ sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterf
static void initialize()
{
#if QT_CONFIG(opengl)
- if (QCoreApplication::instance()) {
- // On window/ANGLE, calling QtWebEngineQuick::initialize from DllMain will result in a crash.
- if (!qt_gl_global_share_context() &&
- !(QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts) &&
- QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGLRhi)
- ) {
- qWarning("Qt WebEngine seems to be initialized from a plugin. Please "
- "set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute and "
- "QSGRendererInterface::OpenGLRhi using QQuickWindow::setGraphicsApi "
- "before constructing QGuiApplication.");
+ if (QCoreApplication::instance()) {
+ // On Windows/ANGLE, calling QtWebEngineQuick::initialize from DllMain will result in a
+ // crash.
+ if (!qt_gl_global_share_context()
+ && !(QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts)
+ && QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGLRhi)) {
+ qWarning("Qt WebEngine seems to be initialized from a plugin. Please "
+ "set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute and "
+ "QSGRendererInterface::OpenGLRhi using QQuickWindow::setGraphicsApi "
+ "before constructing QGuiApplication.");
+ }
+ return;
}
- return;
- }
- // QCoreApplication is not yet instantiated, ensuring the call will be deferred
- qAddPreRoutine(QtWebEngineCore::initialize);
- QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
+
+ // QCoreApplication is not yet instantiated, ensuring the call will be deferred
+ qAddPreRoutine(QtWebEngineCore::initialize);
+ auto api = QQuickWindow::graphicsApi();
+ if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi)
+ QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
#endif // QT_CONFIG(opengl)
}
diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp
index 3a183d0d8..7462b4157 100644
--- a/src/core/chromium_overrides.cpp
+++ b/src/core/chromium_overrides.cpp
@@ -12,6 +12,7 @@
#include "content/common/font_list.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/constants.h"
+#include "gpu/vulkan/buildflags.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
@@ -23,6 +24,17 @@
#include "chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h"
#endif
+#if BUILDFLAG(ENABLE_VULKAN)
+#include "compositor/vulkan_implementation_qt.h"
+
+#include "gpu/vulkan/init/vulkan_factory.h"
+
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+#endif // defined(USE_OZONE)
+#endif // defined(ENABLE_VULKAN)
+
void *GetQtXDisplay()
{
return GLContextHelper::getXDisplay();
@@ -93,6 +105,37 @@ ActivationClient *GetActivationClient(aura::Window *)
} // namespace wm
#endif // defined(USE_AURA) || defined(USE_OZONE)
+#if BUILDFLAG(ENABLE_VULKAN)
+namespace gpu {
+std::unique_ptr<VulkanImplementation> CreateVulkanImplementation(bool use_swiftshader,
+ bool allow_protected_memory)
+{
+#if BUILDFLAG(IS_APPLE)
+ // TODO: Investigate if we can support MoltenVK.
+ NOTIMPLEMENTED();
+ return nullptr;
+#else
+#if defined(USE_OZONE)
+ return ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone()->CreateVulkanImplementation(
+ use_swiftshader, allow_protected_memory);
+#endif
+
+#if !BUILDFLAG(IS_WIN)
+ // TODO(samans): Support Swiftshader on more platforms.
+ // https://crbug.com/963988
+ DCHECK(!use_swiftshader) << "Vulkan Swiftshader is not supported on this platform.";
+#endif // !BUILDFLAG(IS_WIN)
+
+ // Protected memory is supported only on Fuchsia, which uses Ozone, i.e.
+ // VulkanImplementation is initialized above.
+ DCHECK(!allow_protected_memory) << "Protected memory is not supported on this platform.";
+
+ return std::make_unique<VulkanImplementationQt>();
+#endif // BUILDFLAG(IS_APPLE)
+}
+} // namespace gpu
+#endif // BUILDFLAG(ENABLE_VULKAN)
+
std::unique_ptr<ui::OSExchangeDataProvider> ui::OSExchangeDataProviderFactory::CreateProvider()
{
return nullptr;
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp
index ada039afc..fed395cb1 100644
--- a/src/core/compositor/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -9,6 +9,7 @@
#include <QHash>
#include <QImage>
#include <QMutex>
+#include <QQuickWindow>
namespace QtWebEngineCore {
@@ -153,6 +154,25 @@ int Compositor::textureId()
return 0;
}
+#if QT_CONFIG(webengine_vulkan)
+VkImage Compositor::vkImage(QQuickWindow *)
+{
+ Q_UNREACHABLE();
+ return {};
+}
+
+VkImageLayout Compositor::vkImageLayout()
+{
+ Q_UNREACHABLE();
+ return {};
+}
+
+void Compositor::releaseVulkanResources(QQuickWindow *)
+{
+ Q_UNREACHABLE();
+}
+#endif
+
// static
void Compositor::unlockBindings()
{
diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h
index 9cadab4d4..7c6590134 100644
--- a/src/core/compositor/compositor.h
+++ b/src/core/compositor/compositor.h
@@ -4,10 +4,16 @@
#ifndef COMPOSITOR_H
#define COMPOSITOR_H
+#include <QtGui/qtguiglobal.h>
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
+#if QT_CONFIG(webengine_vulkan)
+#include <QVulkanInstance>
+#endif
+
QT_BEGIN_NAMESPACE
class QImage;
+class QQuickWindow;
class QSize;
QT_END_NAMESPACE
@@ -31,6 +37,7 @@ public:
enum class Type {
Software,
OpenGL,
+ Vulkan,
};
// Identifies a compositor.
@@ -139,6 +146,17 @@ public:
// (OpenGL) Texture of the frame.
virtual int textureId();
+#if QT_CONFIG(webengine_vulkan)
+ // (Vulkan) VkImage of the frame.
+ virtual VkImage vkImage(QQuickWindow *win);
+
+ // (Vulkan) Layout for vkImage().
+ virtual VkImageLayout vkImageLayout();
+
+ // (Vulkan) Release Vulkan resources created by Qt's Vulkan instance.
+ virtual void releaseVulkanResources(QQuickWindow *win);
+#endif
+
protected:
Compositor(Type type) : m_type(type) { }
virtual ~Compositor() { if (m_binding) unbind(); }
diff --git a/src/core/compositor/display_skia_output_device.cpp b/src/core/compositor/display_skia_output_device.cpp
index ee693ed81..7f42d61de 100644
--- a/src/core/compositor/display_skia_output_device.cpp
+++ b/src/core/compositor/display_skia_output_device.cpp
@@ -8,6 +8,30 @@
#include "gpu/command_buffer/service/skia_utils.h"
#include "third_party/skia/include/core/SkSurfaceProps.h"
+#if QT_CONFIG(webengine_vulkan)
+#if defined(USE_OZONE)
+#include "ui/ozone/buildflags.h"
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+// We need to define USE_VULKAN_XCB for proper vulkan function pointers.
+// Avoiding it may lead to call wrong vulkan functions.
+// This is originally defined in chromium/gpu/vulkan/BUILD.gn.
+#define USE_VULKAN_XCB
+#endif // BUILDFLAG(OZONE_PLATFORM_X11)
+#endif // defined(USE_OZONE)
+#include "gpu/vulkan/vulkan_function_pointers.h"
+
+#include "components/viz/common/gpu/vulkan_context_provider.h"
+#include "compositor/display_skia_output_device.h"
+#include "gpu/vulkan/vma_wrapper.h"
+#include "gpu/vulkan/vulkan_device_queue.h"
+#include "third_party/vulkan_memory_allocator/include/vk_mem_alloc.h"
+
+#include <QQuickWindow>
+#include <QVulkanInstance>
+#include <QVulkanFunctions>
+#include <QVulkanDeviceFunctions>
+#endif // QT_CONFIG(webengine_vulkan)
+
namespace QtWebEngineCore {
class DisplaySkiaOutputDevice::Buffer
@@ -26,11 +50,8 @@ public:
DCHECK(m_texture.isValid());
if (m_texture.backend() == GrBackendApi::kVulkan) {
-#if BUILDFLAG(ENABLE_VULKAN)
- GrVkImageInfo info;
- bool result = m_texture.getVkImageInfo(&info);
- DCHECK(result);
- m_estimatedSize = info.fAlloc.fSize;
+#if QT_CONFIG(webengine_vulkan)
+ initVulkan();
#else
NOTREACHED();
#endif
@@ -53,6 +74,9 @@ public:
~Buffer()
{
+#if QT_CONFIG(webengine_vulkan) && defined(Q_OS_WIN)
+ CloseHandle(m_win32Handle);
+#endif
DeleteGrBackendTexture(m_parent->m_contextState.get(), &m_texture);
m_parent->memory_type_tracker_->TrackMemFree(m_estimatedSize);
}
@@ -74,6 +98,42 @@ public:
const GrBackendTexture &texture() const { return m_texture; }
SkSurface *surface() const { return m_surface.get(); }
+#if QT_CONFIG(webengine_vulkan)
+ const VkImageCreateInfo *imageCreateInfo() const { return &m_imageCreateInfo; }
+ uint64_t allocationSize() const { return m_estimatedSize; }
+ VkImageLayout imageLayout() const { return m_imageLayout; }
+ uint32_t memoryTypeIndex() const { return m_memoryTypeIndex.value(); }
+
+#if defined(Q_OS_WIN)
+ const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType() const
+ {
+ return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
+ }
+
+ HANDLE externalMemoryHandle() const { return m_win32Handle; }
+#else
+ const VkExternalMemoryHandleTypeFlagBits externalMemoryHandleType() const
+ {
+ return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+ }
+
+ int externalMemoryHandle() const
+ {
+ VkMemoryGetFdInfoKHR exportInfo = { VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR };
+ exportInfo.pNext = nullptr;
+ exportInfo.memory = m_imageInfo.fAlloc.fMemory;
+ exportInfo.handleType = externalMemoryHandleType();
+
+ // Importing Vulkan memory object closes the file descriptor.
+ int fd = -1;
+ if (m_vfp->vkGetMemoryFdKHR(m_vulkanDevice, &exportInfo, &fd) != VK_SUCCESS)
+ qFatal("VULKAN: Unable to extract file descriptor out of external VkImage!");
+
+ return fd;
+ }
+#endif // defined(Q_OS_WIN)
+#endif // QT_CONFIG(webengine_vulkan)
+
private:
DisplaySkiaOutputDevice *m_parent;
Shape m_shape;
@@ -81,17 +141,125 @@ private:
sk_sp<SkSurface> m_surface;
uint64_t m_estimatedSize = 0;
scoped_refptr<CompositorResourceFence> m_fence;
+
+#if QT_CONFIG(webengine_vulkan)
+ static VkSampleCountFlagBits vkSampleCount(uint32_t sampleCount)
+ {
+ Q_ASSERT(sampleCount >= 1);
+ switch (sampleCount) {
+ case 1:
+ return VK_SAMPLE_COUNT_1_BIT;
+ case 2:
+ return VK_SAMPLE_COUNT_2_BIT;
+ case 4:
+ return VK_SAMPLE_COUNT_4_BIT;
+ case 8:
+ return VK_SAMPLE_COUNT_8_BIT;
+ case 16:
+ return VK_SAMPLE_COUNT_16_BIT;
+ default:
+ Q_UNREACHABLE();
+ }
+
+ return VK_SAMPLE_COUNT_1_BIT;
+ }
+
+ void initVulkan()
+ {
+ bool success = m_texture.getVkImageInfo(&m_imageInfo);
+ if (!success)
+ qFatal("VULKAN: Failed to get external Vulkan resources from Skia!");
+
+ m_vfp = gpu::GetVulkanFunctionPointers();
+ gpu::VulkanDeviceQueue *vulkanDeviceQueue =
+ m_parent->m_contextState->vk_context_provider()->GetDeviceQueue();
+ m_vulkanDevice = vulkanDeviceQueue->GetVulkanDevice();
+
+ // Store allocation size for the external VkImage.
+ m_estimatedSize = m_imageInfo.fAlloc.fSize;
+
+ // Store initial layout for the imported image.
+ if (vulkanDeviceQueue->vk_physical_device_properties().vendorID == 0x10DE) {
+ // FIXME: This is a workaround for Nvidia driver.
+ // The imported image is empty if the initialLayout is not PREINITIALIZED.
+ m_imageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ } else {
+ // The initialLayout should be undefined for the external image.
+ // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageCreateInfo.html#VUID-VkImageCreateInfo-pNext-01443
+ m_imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ }
+
+ // Specify VkCreateImageInfo for the imported VkImage.
+ // The specification should match with the texture's VkImage.
+ m_externalMemoryImageCreateInfo.sType =
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
+ m_externalMemoryImageCreateInfo.pNext = nullptr;
+ m_externalMemoryImageCreateInfo.handleTypes = externalMemoryHandleType();
+
+ m_imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ m_imageCreateInfo.pNext = &m_externalMemoryImageCreateInfo;
+ m_imageCreateInfo.flags =
+ m_imageInfo.fProtected == GrProtected::kYes ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
+ m_imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+ m_imageCreateInfo.format = m_imageInfo.fFormat;
+ m_imageCreateInfo.extent.width = static_cast<uint32_t>(m_shape.characterization.width());
+ m_imageCreateInfo.extent.height = static_cast<uint32_t>(m_shape.characterization.height());
+ m_imageCreateInfo.extent.depth = 1;
+ m_imageCreateInfo.mipLevels = m_imageInfo.fLevelCount;
+ m_imageCreateInfo.arrayLayers = 1;
+ m_imageCreateInfo.samples = vkSampleCount(m_imageInfo.fSampleCount);
+ m_imageCreateInfo.tiling = m_imageInfo.fImageTiling;
+ m_imageCreateInfo.usage = m_imageInfo.fImageUsageFlags;
+ m_imageCreateInfo.sharingMode = m_imageInfo.fSharingMode;
+ m_imageCreateInfo.queueFamilyIndexCount = 0;
+ m_imageCreateInfo.pQueueFamilyIndices = nullptr;
+ m_imageCreateInfo.initialLayout = m_imageLayout;
+
+#if defined(Q_OS_WIN)
+ // Extract Windows handle for the memory of the external VkImage.
+ // Ownership should be released at the destruction of the Buffer object.
+ // Multiple handles for the same memory cause issues on Windows even if one is
+ // released before extracting the other.
+ VkMemoryGetWin32HandleInfoKHR exportInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR
+ };
+ exportInfo.pNext = nullptr;
+ exportInfo.memory = m_imageInfo.fAlloc.fMemory;
+ exportInfo.handleType = externalMemoryHandleType();
+
+ if (m_vfp->vkGetMemoryWin32HandleKHR(m_vulkanDevice, &exportInfo, &m_win32Handle)
+ != VK_SUCCESS) {
+ qFatal("VULKAN: Unable to extract handle out of external VkImage!");
+ }
+#endif // defined(Q_OS_WIN)
+
+ VmaAllocator vmaAllocator = vulkanDeviceQueue->vma_allocator();
+ const VmaAllocation vmaAllocation =
+ reinterpret_cast<const VmaAllocation>(m_imageInfo.fAlloc.fBackendMemory);
+ VmaAllocationInfo vmaInfo;
+ gpu::vma::GetAllocationInfo(vmaAllocator, vmaAllocation, &vmaInfo);
+ m_memoryTypeIndex = vmaInfo.memoryType;
+ }
+
+ gpu::VulkanFunctionPointers *m_vfp = nullptr;
+ VkDevice m_vulkanDevice = VK_NULL_HANDLE;
+ VkImageLayout m_imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ GrVkImageInfo m_imageInfo;
+ VkExternalMemoryImageCreateInfoKHR m_externalMemoryImageCreateInfo = {};
+ VkImageCreateInfo m_imageCreateInfo = {};
+#if defined(Q_OS_WIN)
+ HANDLE m_win32Handle = nullptr;
+#endif
+ absl::optional<uint32_t> m_memoryTypeIndex;
+#endif // QT_CONFIG(webengine_vulkan)
};
DisplaySkiaOutputDevice::DisplaySkiaOutputDevice(
- scoped_refptr<gpu::SharedContextState> contextState,
- gpu::MemoryTracker *memoryTracker,
+ scoped_refptr<gpu::SharedContextState> contextState, gpu::MemoryTracker *memoryTracker,
DidSwapBufferCompleteCallback didSwapBufferCompleteCallback)
- : SkiaOutputDevice(
- contextState->gr_context(),
- memoryTracker,
- didSwapBufferCompleteCallback)
- , Compositor(Compositor::Type::OpenGL)
+ : SkiaOutputDevice(contextState->gr_context(), memoryTracker, didSwapBufferCompleteCallback)
+ , Compositor(contextState->GrContextIsVulkan() ? Compositor::Type::Vulkan
+ : Compositor::Type::OpenGL)
, m_contextState(contextState)
{
capabilities_.uses_default_gl_framebuffer = false;
@@ -211,6 +379,92 @@ float DisplaySkiaOutputDevice::devicePixelRatio()
return m_frontBuffer ? m_frontBuffer->shape().devicePixelRatio : 1;
}
+#if QT_CONFIG(webengine_vulkan)
+VkImage DisplaySkiaOutputDevice::vkImage(QQuickWindow *win)
+{
+ if (!m_frontBuffer)
+ return VK_NULL_HANDLE;
+
+ QSGRendererInterface *ri = win->rendererInterface();
+ VkDevice qtVulkanDevice =
+ *static_cast<VkDevice *>(ri->getResource(win, QSGRendererInterface::DeviceResource));
+ QVulkanDeviceFunctions *df = win->vulkanInstance()->deviceFunctions(qtVulkanDevice);
+
+ df->vkDestroyImage(qtVulkanDevice, m_importedImage, nullptr);
+ df->vkFreeMemory(qtVulkanDevice, m_importedImageMemory, nullptr);
+
+ if (df->vkCreateImage(qtVulkanDevice, m_frontBuffer->imageCreateInfo(), nullptr,
+ &m_importedImage)
+ != VK_SUCCESS) {
+ qFatal("VULKAN: Failed to create imported image!");
+ }
+
+ VkMemoryDedicatedAllocateInfoKHR dedicatedAllocateInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
+ };
+ dedicatedAllocateInfo.pNext = nullptr;
+ dedicatedAllocateInfo.image = m_importedImage;
+ dedicatedAllocateInfo.buffer = VK_NULL_HANDLE;
+
+#if defined(Q_OS_WIN)
+ VkImportMemoryWin32HandleInfoKHR importInfo = {
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR
+ };
+ importInfo.handle = m_frontBuffer->externalMemoryHandle();
+#else
+ VkImportMemoryFdInfoKHR importInfo = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR };
+ importInfo.fd = m_frontBuffer->externalMemoryHandle();
+#endif // defined(Q_OS_WIN)
+ importInfo.pNext = &dedicatedAllocateInfo;
+ importInfo.handleType = m_frontBuffer->externalMemoryHandleType();
+
+ VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocateInfo.pNext = &importInfo;
+ allocateInfo.allocationSize = m_frontBuffer->allocationSize();
+ allocateInfo.memoryTypeIndex = m_frontBuffer->memoryTypeIndex();
+
+ if (df->vkAllocateMemory(qtVulkanDevice, &allocateInfo, nullptr, &m_importedImageMemory)
+ != VK_SUCCESS) {
+ qFatal("VULKAN: Failed to allocate memory for imported VkImage!");
+ }
+
+ df->vkBindImageMemory(qtVulkanDevice, m_importedImage, m_importedImageMemory, 0);
+
+ return m_importedImage;
+}
+
+VkImageLayout DisplaySkiaOutputDevice::vkImageLayout()
+{
+ if (!m_frontBuffer)
+ return VK_IMAGE_LAYOUT_UNDEFINED;
+
+ return m_frontBuffer->imageLayout();
+}
+
+void DisplaySkiaOutputDevice::releaseVulkanResources(QQuickWindow *win)
+{
+ VkDevice *vkDevicePtr = static_cast<VkDevice *>(
+ win->rendererInterface()->getResource(win, QSGRendererInterface::DeviceResource));
+
+ if (!vkDevicePtr) {
+ Q_ASSERT(m_importedImage == VK_NULL_HANDLE && m_importedImageMemory == VK_NULL_HANDLE);
+ return;
+ }
+
+ QVulkanDeviceFunctions *df = win->vulkanInstance()->deviceFunctions(*vkDevicePtr);
+
+ if (m_importedImage != VK_NULL_HANDLE) {
+ df->vkDestroyImage(*vkDevicePtr, m_importedImage, nullptr);
+ m_importedImage = VK_NULL_HANDLE;
+ }
+
+ if (m_importedImageMemory != VK_NULL_HANDLE) {
+ df->vkFreeMemory(*vkDevicePtr, m_importedImageMemory, nullptr);
+ m_importedImageMemory = VK_NULL_HANDLE;
+ }
+}
+#endif // QT_CONFIG(webengine_vulkan)
+
void DisplaySkiaOutputDevice::SwapBuffersFinished()
{
{
diff --git a/src/core/compositor/display_skia_output_device.h b/src/core/compositor/display_skia_output_device.h
index 943d37214..e2818d604 100644
--- a/src/core/compositor/display_skia_output_device.h
+++ b/src/core/compositor/display_skia_output_device.h
@@ -13,6 +13,10 @@
#include <QMutex>
+QT_BEGIN_NAMESPACE
+class QQuickWindow;
+QT_END_NAMESPACE
+
namespace QtWebEngineCore {
class DisplaySkiaOutputDevice final : public viz::SkiaOutputDevice, public Compositor
@@ -43,6 +47,11 @@ public:
QSize size() override;
bool hasAlphaChannel() override;
float devicePixelRatio() override;
+#if QT_CONFIG(webengine_vulkan)
+ VkImage vkImage(QQuickWindow *win) override;
+ VkImageLayout vkImageLayout() override;
+ void releaseVulkanResources(QQuickWindow *win) override;
+#endif
private:
struct Shape
@@ -73,6 +82,11 @@ private:
viz::OutputSurfaceFrame m_frame;
bool m_readyToUpdate = false;
scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner;
+
+#if QT_CONFIG(webengine_vulkan)
+ VkImage m_importedImage = VK_NULL_HANDLE;
+ VkDeviceMemory m_importedImageMemory = VK_NULL_HANDLE;
+#endif // QT_CONFIG(webengine_vulkan)
};
} // namespace QtWebEngineCore
diff --git a/src/core/compositor/vulkan_implementation_qt.cpp b/src/core/compositor/vulkan_implementation_qt.cpp
new file mode 100644
index 000000000..713e5d7a1
--- /dev/null
+++ b/src/core/compositor/vulkan_implementation_qt.cpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "vulkan_implementation_qt.h"
+
+#include "base/environment.h"
+#include "base/logging.h"
+#include "gpu/vulkan/vulkan_image.h"
+#include "gpu/vulkan/vulkan_surface.h"
+#include "gpu/vulkan/vulkan_util.h"
+#include "ui/gfx/gpu_fence.h"
+
+namespace gpu {
+
+VulkanImplementationQt::VulkanImplementationQt() : VulkanImplementation(false) { }
+
+VulkanImplementationQt::~VulkanImplementationQt() = default;
+
+bool VulkanImplementationQt::InitializeVulkanInstance(bool /*using_surface*/)
+{
+ std::vector<const char *> required_extensions = {
+ VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+ };
+
+ auto env = base::Environment::Create();
+ std::string vulkan_path;
+ if (!env->GetVar("QT_VULKAN_LIB", &vulkan_path))
+#ifdef Q_OS_WIN
+ vulkan_path = "vulkan-1.dll";
+#else
+ vulkan_path = "libvulkan.so.1";
+#endif
+
+ if (!vulkan_instance_.Initialize(base::FilePath::FromUTF8Unsafe(vulkan_path),
+ required_extensions, {})) {
+ LOG(ERROR) << "Failed to initialize vulkan instance";
+ return false;
+ }
+
+ return true;
+}
+
+VulkanInstance *VulkanImplementationQt::GetVulkanInstance()
+{
+ return &vulkan_instance_;
+}
+
+std::unique_ptr<VulkanSurface>
+VulkanImplementationQt::CreateViewSurface(gfx::AcceleratedWidget /*window*/)
+{
+ NOTREACHED();
+ return nullptr;
+}
+
+bool VulkanImplementationQt::GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice /*device*/,
+ const std::vector<VkQueueFamilyProperties> & /*queue_family_properties*/,
+ uint32_t /*queue_family_index*/)
+{
+ NOTREACHED();
+ return true;
+}
+
+std::vector<const char *> VulkanImplementationQt::GetRequiredDeviceExtensions()
+{
+ return {
+ VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+#ifdef Q_OS_WIN
+ VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
+#else
+ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
+#endif
+ };
+}
+
+std::vector<const char *> VulkanImplementationQt::GetOptionalDeviceExtensions()
+{
+ return {
+ VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
+#ifdef Q_OS_WIN
+ VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
+#else
+ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
+#endif
+ };
+}
+
+VkFence VulkanImplementationQt::CreateVkFenceForGpuFence(VkDevice /*vk_device*/)
+{
+ NOTREACHED();
+ return VK_NULL_HANDLE;
+}
+
+std::unique_ptr<gfx::GpuFence>
+VulkanImplementationQt::ExportVkFenceToGpuFence(VkDevice /*vk_device*/, VkFence /*vk_fence*/)
+{
+ NOTREACHED();
+ return nullptr;
+}
+
+VkSemaphore VulkanImplementationQt::CreateExternalSemaphore(VkDevice vk_device)
+{
+ return CreateExternalVkSemaphore(
+#ifdef Q_OS_WIN
+ vk_device, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT);
+#else
+ vk_device, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
+#endif
+}
+
+VkSemaphore VulkanImplementationQt::ImportSemaphoreHandle(VkDevice vk_device,
+ SemaphoreHandle sync_handle)
+{
+ return ImportVkSemaphoreHandle(vk_device, std::move(sync_handle));
+}
+
+SemaphoreHandle VulkanImplementationQt::GetSemaphoreHandle(VkDevice vk_device,
+ VkSemaphore vk_semaphore)
+{
+ return GetVkSemaphoreHandle(vk_device, vk_semaphore,
+#ifdef Q_OS_WIN
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT);
+#else
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
+#endif
+}
+
+VkExternalMemoryHandleTypeFlagBits VulkanImplementationQt::GetExternalImageHandleType()
+{
+#ifdef Q_OS_WIN
+ return VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT;
+#else
+ return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+#endif
+}
+
+bool VulkanImplementationQt::CanImportGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType /*memory_buffer_type*/)
+{
+ return false;
+}
+
+std::unique_ptr<VulkanImage>
+VulkanImplementationQt::CreateImageFromGpuMemoryHandle(VulkanDeviceQueue * /*device_queue*/,
+ gfx::GpuMemoryBufferHandle /*gmb_handle*/,
+ gfx::Size /*size*/, VkFormat /*vk_format*/)
+{
+ NOTREACHED();
+ return nullptr;
+}
+
+} // namespace gpu
diff --git a/src/core/compositor/vulkan_implementation_qt.h b/src/core/compositor/vulkan_implementation_qt.h
new file mode 100644
index 000000000..6e7a68b49
--- /dev/null
+++ b/src/core/compositor/vulkan_implementation_qt.h
@@ -0,0 +1,47 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef VULKAN_IMPLEMENTATION_QT_H
+#define VULKAN_IMPLEMENTATION_QT_H
+
+#include "gpu/vulkan/vulkan_implementation.h"
+#include "gpu/vulkan/vulkan_instance.h"
+
+namespace gpu {
+
+class VulkanImplementationQt : public VulkanImplementation
+{
+public:
+ VulkanImplementationQt();
+ ~VulkanImplementationQt() override;
+
+ // Overridden from VulkanImplementation.
+ bool InitializeVulkanInstance(bool using_surface) override;
+ VulkanInstance *GetVulkanInstance() override;
+ std::unique_ptr<VulkanSurface> CreateViewSurface(gfx::AcceleratedWidget window) override;
+ bool GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice device,
+ const std::vector<VkQueueFamilyProperties> &queue_family_properties,
+ uint32_t queue_family_index) override;
+ std::vector<const char *> GetRequiredDeviceExtensions() override;
+ std::vector<const char *> GetOptionalDeviceExtensions() override;
+ VkFence CreateVkFenceForGpuFence(VkDevice vk_device) override;
+ std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(VkDevice vk_device,
+ VkFence vk_fence) override;
+ VkSemaphore CreateExternalSemaphore(VkDevice vk_device) override;
+ VkSemaphore ImportSemaphoreHandle(VkDevice vk_device, SemaphoreHandle handle) override;
+ SemaphoreHandle GetSemaphoreHandle(VkDevice vk_device, VkSemaphore vk_semaphore) override;
+ VkExternalMemoryHandleTypeFlagBits GetExternalImageHandleType() override;
+ bool CanImportGpuMemoryBuffer(gfx::GpuMemoryBufferType memory_buffer_type) override;
+ std::unique_ptr<VulkanImage>
+ CreateImageFromGpuMemoryHandle(VulkanDeviceQueue *device_queue,
+ gfx::GpuMemoryBufferHandle gmb_handle, gfx::Size size,
+ VkFormat vk_format) override;
+
+private:
+ VulkanInstance vulkan_instance_;
+};
+
+} // namespace gpu
+
+#endif // VULKAN_IMPLEMENTATION_QT_H
diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp
index 8ab3aa1a7..71315a049 100644
--- a/src/core/ozone/ozone_platform_qt.cpp
+++ b/src/core/ozone/ozone_platform_qt.cpp
@@ -4,6 +4,7 @@
#include "ozone_platform_qt.h"
#if defined(USE_OZONE)
+#include "base/no_destructor.h"
#include "ui/base/buildflags.h"
#include "ui/base/ime/input_method.h"
#include "ui/display/types/native_display_delegate.h"
@@ -52,6 +53,8 @@ public:
ui::OverlayManagerOzone* GetOverlayManager() override;
std::unique_ptr<InputMethod> CreateInputMethod(internal::InputMethodDelegate *delegate, gfx::AcceleratedWidget widget) override;
std::unique_ptr<ui::PlatformScreen> CreateScreen() override { return nullptr; }
+ const PlatformProperties &GetPlatformProperties() override;
+
private:
bool InitializeUI(const ui::OzonePlatform::InitParams &) override;
void InitializeGPU(const ui::OzonePlatform::InitParams &) override;
@@ -76,6 +79,20 @@ OzonePlatformQt::OzonePlatformQt() {}
OzonePlatformQt::~OzonePlatformQt() {}
+const ui::OzonePlatform::PlatformProperties &OzonePlatformQt::GetPlatformProperties()
+{
+ static base::NoDestructor<ui::OzonePlatform::PlatformProperties> properties;
+ static bool initialized = false;
+ if (!initialized) {
+ properties->uses_external_vulkan_image_factory = true;
+ properties->fetch_buffer_formats_for_gmb_on_gpu = true;
+
+ initialized = true;
+ }
+
+ return *properties;
+}
+
ui::SurfaceFactoryOzone* OzonePlatformQt::GetSurfaceFactoryOzone()
{
return surface_factory_ozone_.get();
diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp
index 33164d076..13c1a7b11 100644
--- a/src/core/ozone/surface_factory_qt.cpp
+++ b/src/core/ozone/surface_factory_qt.cpp
@@ -10,6 +10,12 @@
#include "ozone/gl_ozone_glx_qt.h"
#endif
+#include "qtwebenginecoreglobal_p.h"
+
+#if QT_CONFIG(webengine_vulkan)
+#include "compositor/vulkan_implementation_qt.h"
+#endif
+
namespace QtWebEngineCore {
SurfaceFactoryQt::SurfaceFactoryQt()
@@ -27,7 +33,6 @@ SurfaceFactoryQt::SurfaceFactoryQt()
gl::GLImplementationParts(gl::kGLImplementationDisabled) };
m_ozone.reset(new ui::GLOzoneEGLQt());
} else {
- qWarning("No suitable graphics backend found\n");
m_impl = { gl::GLImplementationParts(gl::kGLImplementationDisabled) };
}
}
@@ -41,6 +46,18 @@ ui::GLOzone *SurfaceFactoryQt::GetGLOzone(const gl::GLImplementationParts &imple
{
return m_ozone.get();
}
+#if BUILDFLAG(ENABLE_VULKAN)
+std::unique_ptr<gpu::VulkanImplementation>
+SurfaceFactoryQt::CreateVulkanImplementation(bool /*allow_protected_memory*/,
+ bool /*enforce_protected_memory*/)
+{
+#if QT_CONFIG(webengine_vulkan)
+ return std::make_unique<gpu::VulkanImplementationQt>();
+#else
+ return nullptr;
+#endif
+}
+#endif
} // namespace QtWebEngineCore
#endif // defined(USE_OZONE)
diff --git a/src/core/ozone/surface_factory_qt.h b/src/core/ozone/surface_factory_qt.h
index 767b69b85..bfcfa014b 100644
--- a/src/core/ozone/surface_factory_qt.h
+++ b/src/core/ozone/surface_factory_qt.h
@@ -16,6 +16,10 @@ public:
SurfaceFactoryQt();
std::vector<gl::GLImplementationParts> GetAllowedGLImplementations() override;
ui::GLOzone *GetGLOzone(const gl::GLImplementationParts &implementation) override;
+#if BUILDFLAG(ENABLE_VULKAN)
+ std::unique_ptr<gpu::VulkanImplementation>
+ CreateVulkanImplementation(bool allow_protected_memory, bool enforce_protected_memory) override;
+#endif
private:
std::vector<gl::GLImplementationParts> m_impl;
std::unique_ptr<ui::GLOzone> m_ozone;
diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp
index a44046aac..f90a201b6 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_item.cpp
@@ -29,6 +29,7 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid
RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem()
{
+ releaseVulkanResources();
if (m_widgetDelegate) {
m_widgetDelegate->Unbind();
m_widgetDelegate->Destroy();
@@ -315,6 +316,12 @@ void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const Ite
this, &RenderWidgetHostViewQtDelegateItem::onBeforeRendering, Qt::DirectConnection));
m_windowConnections.append(connect(value.window, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged())));
m_windowConnections.append(connect(value.window, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged())));
+#if QT_CONFIG(webengine_vulkan)
+ m_windowConnections.append(
+ connect(value.window, &QQuickWindow::sceneGraphAboutToStop, this,
+ &RenderWidgetHostViewQtDelegateItem::releaseVulkanResources,
+ Qt::DirectConnection));
+#endif
if (!m_isPopup)
m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent *)), SLOT(onHide())));
}
@@ -362,6 +369,18 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U
node->setTexture(QNativeInterface::QSGOpenGLTexture::fromNative(texId, win, texSize, texOpts));
node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
#endif
+#if QT_CONFIG(webengine_vulkan)
+ } else if (comp->type() == Compositor::Type::Vulkan) {
+ QQuickWindow::CreateTextureOptions texOpts;
+ if (comp->hasAlphaChannel())
+ texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel);
+
+ VkImage image = comp->vkImage(win);
+ VkImageLayout layout = comp->vkImageLayout();
+ node->setTexture(QNativeInterface::QSGVulkanTexture::fromNative(image, layout, win, texSize,
+ texOpts));
+ node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
+#endif // QT_CONFIG(webengine_vulkan)
} else {
Q_UNREACHABLE();
}
@@ -372,7 +391,7 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U
void RenderWidgetHostViewQtDelegateItem::onBeforeRendering()
{
auto comp = compositor();
- if (!comp || comp->type() != Compositor::Type::OpenGL)
+ if (!comp || comp->type() == Compositor::Type::Software)
return;
comp->waitForTexture();
}
@@ -388,6 +407,17 @@ void RenderWidgetHostViewQtDelegateItem::onHide()
m_client->forwardEvent(&event);
}
+void RenderWidgetHostViewQtDelegateItem::releaseVulkanResources()
+{
+#if QT_CONFIG(webengine_vulkan)
+ auto comp = compositor();
+ if (!comp || comp->type() != Compositor::Type::Vulkan)
+ return;
+
+ comp->releaseVulkanResources(QQuickItem::window());
+#endif
+}
+
void RenderWidgetHostViewQtDelegateItem::adapterClientChanged(WebContentsAdapterClient *client)
{
m_adapterClient = client;
diff --git a/src/core/render_widget_host_view_qt_delegate_item.h b/src/core/render_widget_host_view_qt_delegate_item.h
index e057d37d9..6f3289157 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.h
+++ b/src/core/render_widget_host_view_qt_delegate_item.h
@@ -101,6 +101,7 @@ protected:
private Q_SLOTS:
void onBeforeRendering();
void onWindowPosChanged();
+ void releaseVulkanResources();
void onHide();
private:
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 94ff5f7b2..f6c60daf3 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -55,6 +55,7 @@
#include "content/public/common/network_service_util.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
+#include "gpu/config/gpu_finch_features.h"
#include "media/audio/audio_manager.h"
#include "media/base/media_switches.h"
#include "mojo/core/embedder/embedder.h"
@@ -123,7 +124,8 @@ namespace QtWebEngineCore {
static bool usingSupportedSGBackend()
{
- if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL)
+ if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL
+ && QQuickWindow::graphicsApi() != QSGRendererInterface::Vulkan)
return false;
const QStringList args = QGuiApplication::arguments();
@@ -683,6 +685,15 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing);
}
+#if QT_CONFIG(webengine_vulkan)
+ if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) {
+ enableFeatures.push_back(features::kVulkan.name);
+ enableFeatures.push_back(features::kUseSkiaRenderer.name);
+ parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan,
+ switches::kVulkanImplementationNameNative);
+ }
+#endif
+
initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures);
GLContextHelper::initialize();
diff --git a/src/webenginequick/api/qtwebenginequickglobal.cpp b/src/webenginequick/api/qtwebenginequickglobal.cpp
index 607777e55..b16305dae 100644
--- a/src/webenginequick/api/qtwebenginequickglobal.cpp
+++ b/src/webenginequick/api/qtwebenginequickglobal.cpp
@@ -43,9 +43,12 @@ void initialize()
QtWebEngineCore::initialize();
return;
}
+
// call initialize the same way as widgets do
qAddPreRoutine(QtWebEngineCore::initialize);
- QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
+ auto api = QQuickWindow::graphicsApi();
+ if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi)
+ QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
}
} // namespace QtWebEngineQuick