Skip to content

Commit

Permalink
Add Vulkan QML backend (#467)
Browse files Browse the repository at this point in the history
This PR adds native Vulkan backend using Qt's QML Vulkan RHI.
This PR breaks ABI slightly, so it's best if it targets post-Garden.

With a few global variables we could workaround it and backport it to Garden though. Note that Garden supports Vulkan via a fallback that is very slow. This PR offers native, full speed integration.

Note: Qt 5.14 is the minimum requirement, which means it's not available on Ubuntu 20.04 but rather Ubuntu 22.04. I put macros to use at least 5.15.2 because that's what I tested against.

Note: Qt 5 considers Vulkan QML interface to be 'experimental' and I've submitted a patch to Qt to improve compliance with the Vulkan standard. Ideally Gazebo should eventually migrate to Qt 6.

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>
Signed-off-by: Ian Chen <ichen@osrfoundation.org>
Co-authored-by: Ian Chen <ichen@osrfoundation.org>
  • Loading branch information
darksylinc and iche033 authored Jan 5, 2023
1 parent fce993b commit 91ed341
Show file tree
Hide file tree
Showing 13 changed files with 785 additions and 46 deletions.
5 changes: 4 additions & 1 deletion include/gz/gui/Application.hh
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ namespace gz
/// \param[in] _argc Argument count.
/// \param[in] _argv Argument values.
/// \param[in] _type Window type, by default it's a main window.
/// \param[in] _renderEngineGuiApiBackend --render-engine-gui-api-backend
/// option
public: Application(int &_argc, char **_argv,
const WindowType _type = WindowType::kMainWindow);
const WindowType _type = WindowType::kMainWindow,
const char *_renderEngineGuiApiBackend = nullptr);

/// \brief Destructor
public: virtual ~Application();
Expand Down
9 changes: 9 additions & 0 deletions include/gz/gui/Helpers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ namespace gz
GZ_GUI_VISIBLE
std::string renderEngineName();

/// \brief Just like renderEngineName(), but valid entries are:
/// - opengl (default)
/// - metal (Apple only)
/// - vulkan
/// \return Name of API backend used on the GUI, as stored in the
/// `MainWindow`'s "renderEngineBackendApiName" property.
GZ_GUI_VISIBLE
std::string renderEngineBackendApiName();

/// \brief Import path for gz-gui QML modules added to the Qt resource
/// system. This helper function returns the QRC resource path where custom
/// Gazebo QML modules can be imported from. To import a Gazebo QML
Expand Down
89 changes: 81 additions & 8 deletions src/Application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,48 @@ namespace gz
using namespace gz;
using namespace gui;

enum class GZ_COMMON_HIDDEN AvailableAPIs
{
OpenGL,
Vulkan,
Metal
};

/////////////////////////////////////////////////
Application::Application(int &_argc, char **_argv, const WindowType _type)
: QApplication(_argc, _argv), dataPtr(new ApplicationPrivate)
Application::Application(int &_argc, char **_argv, const WindowType _type,
const char *_renderEngineGuiApiBackend) :
QApplication(_argc, _argv),
dataPtr(new ApplicationPrivate)
{
gzdbg << "Initializing application." << std::endl;

this->setOrganizationName("Gazebo");
this->setOrganizationDomain("gazebosim.org");
this->setApplicationName("Gazebo GUI");

#if __APPLE__
// Use the Metal graphics API on macOS.
gzdbg << "Qt using Metal graphics interface" << std::endl;
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::MetalRhi);
#ifdef __APPLE__
AvailableAPIs api = AvailableAPIs::Metal;
#else
AvailableAPIs api = AvailableAPIs::OpenGL;
#endif
if (_renderEngineGuiApiBackend)
{
const std::string renderEngineGuiApiBackend = _renderEngineGuiApiBackend;
if (renderEngineGuiApiBackend == "vulkan")
api = AvailableAPIs::Vulkan;
#ifdef __APPLE__
if (renderEngineGuiApiBackend == "metal")
api = AvailableAPIs::Metal;
#endif
}

#ifdef __APPLE__
if (api == AvailableAPIs::Metal)
{
// Use the Metal graphics API on macOS.
gzdbg << "Qt using Metal graphics interface" << std::endl;
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::MetalRhi);
}

// TODO(srmainwaring): implement facility for overriding the default
// graphics API in macOS, in which case there are restrictions on
Expand All @@ -118,8 +146,32 @@ Application::Application(int &_argc, char **_argv, const WindowType _type)
// format.setRenderableType(QSurfaceFormat::OpenGL);
// QSurfaceFormat::setDefaultFormat(format);
#else
// Otherwise use OpenGL
gzdbg << "Qt using OpenGL graphics interface" << std::endl;
// Otherwise use OpenGL (or Vulkan when supported and requested)

if (api == AvailableAPIs::Vulkan)
{
gzdbg << "Qt using Vulkan graphics interface" << std::endl;

# ifdef GZ_USE_VULKAN_DEBUG_EXT
qputenv("QT_VULKAN_INSTANCE_EXTENSIONS",
"VK_EXT_debug_report;VK_EXT_debug_utils");
# endif
qputenv("QT_VULKAN_DEVICE_EXTENSIONS",
"VK_KHR_maintenance2;VK_EXT_shader_subgroup_vote;"
"VK_EXT_shader_viewport_index_layer;"
# ifdef GZ_USE_VULKAN_DEBUG_EXT
";VK_EXT_debug_marker"
# endif
);

# if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2) && QT_CONFIG(vulkan)
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::VulkanRhi);
# endif
}
else
{
gzdbg << "Qt using OpenGL graphics interface" << std::endl;
}
#endif

// Configure console
Expand Down Expand Up @@ -149,7 +201,28 @@ Application::Application(int &_argc, char **_argv, const WindowType _type)
if (_type == WindowType::kMainWindow)
{
if (!this->InitializeMainWindow())
{
gzerr << "Failed to initialize main window." << std::endl;
}
else
{
switch (api)
{
default:
case AvailableAPIs::OpenGL:
this->dataPtr->mainWin->setProperty("renderEngineBackendApiName",
"opengl");
break;
case AvailableAPIs::Vulkan:
this->dataPtr->mainWin->setProperty("renderEngineBackendApiName",
"vulkan");
break;
case AvailableAPIs::Metal:
this->dataPtr->mainWin->setProperty("renderEngineBackendApiName",
"metal");
break;
}
}
}
else if (_type == WindowType::kDialog)
{
Expand Down
14 changes: 14 additions & 0 deletions src/Helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,20 @@ std::string gz::gui::renderEngineName()
return renderEngineNameVariant.toString().toStdString();
}

/////////////////////////////////////////////////
std::string gz::gui::renderEngineBackendApiName()
{
auto win = App()->findChild<MainWindow *>();
if (nullptr == win)
return {};

auto renderEngineNameVariant = win->property("renderEngineBackendApiName");
if (!renderEngineNameVariant.isValid())
return {};

return renderEngineNameVariant.toString().toStdString();
}

/////////////////////////////////////////////////
const QString gz::gui::qmlQrcImportPath()
{
Expand Down
1 change: 1 addition & 0 deletions src/plugins/minimal_scene/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(SOURCES
MinimalScene.cc
MinimalSceneRhi.cc
MinimalSceneRhiOpenGL.cc
MinimalSceneRhiVulkan.cc
EngineToQtInterface.cc
)

Expand Down
Loading

0 comments on commit 91ed341

Please sign in to comment.