diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-01-15 09:08:24 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-04-11 18:23:55 +0200 |
commit | 400d176760de84626500787674b1ece387b25893 (patch) | |
tree | dbb8b5fd50440e6c01d6b940fe1692ba8e6a1f5c /examples/quick/rendercontrol/rendercontrol_d3d11/engine.h | |
parent | 654959e2e2b74855036f949a9c23c9d9c7a614ac (diff) |
Allow redirecting QRhi-based rendering via QQuickRenderControl
Implement the Qt 6 TODO for using an externally-provided render target
when rendering the scene via QRhi.
And say hello to QQuickRenderTarget. This class exists to allow
potentially extending later what a "render target" consists
of. Instead of hard-coding taking a single void * in the
setRenderTarget() function, it takes a (implicitly shared,
d-pointered) QQuickRenderTarget, which in turn can be created via
static factory functions - of which new ones can be added later on.
The new version of QQuickWindow::setRenderTarget() takes a
QQuickRenderTarget.
QQuickRenderControl gets a new initialize() variant, and a few extra
functions (beginFrame(), endFrame()). This allows it to, by using
QSGRhiSupport internally, create a QRhi under the hood.
As a bonus, this also fixes an existing scenegraph resource leak when
destroying the QQuickRenderControl.
The qquickrendercontrol autotest is extended, with a QRhi-based test
case that is executed for all of the QRhi backends that succeed to
initialize. This is the internal verification. In addition, there is
a Vulkan-based one that creates its own VkDevice, VkImage, and
friends, and then uses Qt Quick with the same Vulkan device, targeting
the VkImage. This test verifies the typical application use
case. (sadly, life is too short to waste it on writing Vulkan
boilerplate for an on-screen version of this, but we have the D3D11
example instead)
What QQuickRenderControl loses, when used in combination with QRhi, is
the grab() function. This never made much sense as a public API:
QQuickWindow::grabWindow() call this when the window is associated
with a rendercontrol, so as a public API QQuickRenderControl::grab()
is redundant, because one gets the same result via the standard
QQuickWindow API. It is now made private.
More importantly, reading back the content is no longer supported,
unless the 'software' backend is in use. The reasoning here is that,
if the client of the API manages and provides the render target (as
abstracted by QQuickRenderTarget), it is then expected to be capable
of reading back the content in whatever way it sees fit, because it
owns and manages the resource (e.g. the texture) in the first
place. Providing fragile convenience functions for this is not
reasonable anymore, and was questionable even with OpenGL, given that
it is not future proof - what if the target is suddenly a floating
point texture, for instance? The software backend case makes sense
because that relies on private APIs - and has no render target concept
either - so there the same cannot be achieved by applications by
relying on public APIs only.
Another new class is QQuickGraphicsDevice. This is very similar to
QQuickRenderTarget, it is a simple container capable of holding a set
of of native objects, mostly in the form of void*s, with future
extensibility thanks to the static factory functions. (examples of
native object sets would be a ID3D11Device + ID3D11DeviceContext, or a
QOpenGLContext, or a MTLDevice + MTLCommandQueue, or a number of
Vulkan device-related objects, etc.) This allows one to specify that
the QRhi created under the hood (either by QQuickRenderControl or by
the render loop) should use an existing graphics device (i.e. it is
basically a public wrapper for values that go into a QRhi*InitParams
under the hood).
QQuickRenderTarget and QQuickGraphicsDevice are both demonstrated in a
new example: rendercontrol_d3d11. We choose D3D11 because it is
reasonably simple to set up a renderer with a window, and, because
there is known user demand for Qt Quick - external D3D engine
interop. Passing in the custom engine's own ID3D11Device and
ID3D11DeviceContext is essential: the texture (ID3D11Texture2D) Qt
Quick is targeting would not be usable if Qt Quick's QRhi was using a
different ID3D11Device.
Task-number: QTBUG-78595
Change-Id: I5dfe7f6cf1540daffc2f11136be114a08e87202b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'examples/quick/rendercontrol/rendercontrol_d3d11/engine.h')
-rw-r--r-- | examples/quick/rendercontrol/rendercontrol_d3d11/engine.h | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/examples/quick/rendercontrol/rendercontrol_d3d11/engine.h b/examples/quick/rendercontrol/rendercontrol_d3d11/engine.h new file mode 100644 index 0000000000..8b1b3ebf39 --- /dev/null +++ b/examples/quick/rendercontrol/rendercontrol_d3d11/engine.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef ENGINE_H +#define ENGINE_H + +#include <QWindow> + +#include <d3d11_1.h> +#include <dxgi1_3.h> + +#define RELEASE(obj) { if (obj) { obj->Release(); obj = nullptr; } } + +QString comErrorMessage(HRESULT hr); + +struct Swapchain +{ + IDXGISwapChain1 *swapchain; + ID3D11Texture2D *tex; + ID3D11RenderTargetView *rtv; + ID3D11Texture2D *ds; + ID3D11DepthStencilView *dsv; + QSize pixelSize; + + void destroy(); +}; + +class Engine +{ +public: + ~Engine(); + bool create(); + QSize swapchainSizeForWindow(QWindow *window) const; + Swapchain createSwapchain(QWindow *window); + void resizeSwapchain(Swapchain *sc, QWindow *window); + ID3D11Device *device() { return m_device; } + ID3D11DeviceContext1 *context() { return m_context; } + +private: + void createSwapchainBuffers(Swapchain *sc); + + IDXGIFactory1 *m_dxgiFactory = nullptr; + ID3D11Device *m_device = nullptr; + ID3D11DeviceContext1 *m_context = nullptr; + D3D_FEATURE_LEVEL m_featureLevel; +}; + +#endif |