/**************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // This is a compact, minimal demo of deciding the backend at runtime while // using the exact same shaders and rendering code without any branching // whatsoever once the QWindow is up and the RHI is initialized. #include #include #include "hellowindow.h" QString graphicsApiName(QRhi::Implementation graphicsApi) { switch (graphicsApi) { case QRhi::Null: return QLatin1String("Null (no output)"); case QRhi::OpenGLES2: return QLatin1String("OpenGL 2.x"); case QRhi::Vulkan: return QLatin1String("Vulkan"); case QRhi::D3D11: return QLatin1String("Direct3D 11"); case QRhi::Metal: return QLatin1String("Metal"); default: break; } return QString(); } int main(int argc, char **argv) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QRhi::Implementation graphicsApi; #if defined(Q_OS_WIN) graphicsApi = QRhi::D3D11; #elif defined(Q_OS_MACOS) || defined(Q_OS_IOS) graphicsApi = QRhi::Metal; #elif QT_CONFIG(vulkan) graphicsApi = QRhi::Vulkan; #else graphicsApi = QRhi::OpenGLES2; #endif QCommandLineParser cmdLineParser; cmdLineParser.addHelpOption(); QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null")); cmdLineParser.addOption(nullOption); QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)")); cmdLineParser.addOption(glOption); QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan")); cmdLineParser.addOption(vkOption); QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11")); cmdLineParser.addOption(d3dOption); QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal")); cmdLineParser.addOption(mtlOption); cmdLineParser.process(app); if (cmdLineParser.isSet(nullOption)) graphicsApi = QRhi::Null; if (cmdLineParser.isSet(glOption)) graphicsApi = QRhi::OpenGLES2; if (cmdLineParser.isSet(vkOption)) graphicsApi = QRhi::Vulkan; if (cmdLineParser.isSet(d3dOption)) graphicsApi = QRhi::D3D11; if (cmdLineParser.isSet(mtlOption)) graphicsApi = QRhi::Metal; qDebug("Selected graphics API is %s", qPrintable(graphicsApiName(graphicsApi))); qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText())); QSurfaceFormat fmt; fmt.setDepthBufferSize(24); fmt.setStencilBufferSize(8); QSurfaceFormat::setDefaultFormat(fmt); #if QT_CONFIG(vulkan) QVulkanInstance inst; if (graphicsApi == QRhi::Vulkan) { #ifndef Q_OS_ANDROID inst.setLayers({ "VK_LAYER_LUNARG_standard_validation" }); #else inst.setLayers({ "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_image", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects"}); #endif inst.setExtensions({ "VK_KHR_get_physical_device_properties2" }); if (!inst.create()) { qWarning("Failed to create Vulkan instance, switching to OpenGL"); graphicsApi = QRhi::OpenGLES2; } } #endif HelloWindow w(graphicsApi); #if QT_CONFIG(vulkan) if (graphicsApi == QRhi::Vulkan) w.setVulkanInstance(&inst); #endif w.resize(1280, 720); w.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName(graphicsApi)); w.show(); int ret = app.exec(); // Window::event() will not get invoked when the // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow // destruction. That happens only when exiting via app::quit() instead of // the more common QWindow::close(). Take care of it: if the QPlatformWindow // is still around (there was no close() yet), get rid of the swapchain // while it's not too late. if (w.handle()) w.releaseSwapChain(); return ret; }