diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-12-31 14:39:53 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2022-01-03 14:35:13 +0100 |
commit | 5ae238f90fb31ac216f83c0290737bbbec8ff565 (patch) | |
tree | e2211c4ddafce12b8ff5b527ca6708346a8320e2 /src/gui/rhi/qrhi_p.h | |
parent | 8e2f101a6bf6c59e707b2747d6df76e8e221e319 (diff) |
rhi: Add the basics for HDR swapchains
...backed by support in the backends for D3D11 and Vulkan.
Expose only what works in practice: scRGB with RGBA16F and HDR10 with
RGB10A2 (or A2BGRA10 etc.). For general use, e.g. to render 2D/3D
content, scRGB (i.e. extended sRGB linear) should be chosen because
that is a linear space.
On Windows with a HDR10 display (and an NVIDIA card) both of these are
known to work, as long as Use HDR is enabled in the Settings for the
display on which the window is created.
When requesting a HDR format and it is not supported, we will fall
back to the default SDR RGBA8/BGRA8 format. However, the behavior
seems to be a bit weird with Vulkan and NVIDIA at least when there is
a HDR display but Use HDR is set to Off: this seems to enable HDR mode
for the lifetime of the window (with the usual set of black screens
while switching over the entire display). Not sure why the driver does
this. With D3D/DXGI, with fewer abstractions in the way, we can check
upfront properly, so that will nicely fall back to the defaults
regardless of why HDR is not available.
Support can also be checked in advance via
QRhiSwapChain::isFormatSupported() as long as the QWindow is
available. (though with Vulkan, as said above, this also seems to
ignore the Use HDR setting of Windows)
Complications, such as moving a window from one screen to another, are
currently not known how they behave. To be seen how this is handled by
the Windows compositor. (from 1903 and up it is said to be able to
automatically downconvert scRGB to SDR so perhaps moving from a HDR to
a non-HDR screen would work - remains to be seen if this needs
something more involved)
When it comes to other platforms and potential future support:
- based on its docs Android 8+ may support scRGB with Vulkan as-is on
a suitable device/display, as long as the application declares
android:colorMode="wideColorGamut" in the manifest.
- for Metal the layer can be made EDR enabled and then
e.g. MTLPixelFormatRGBA16Float/kCGColorSpaceExtendedLinearSRGB should
work. However, this won't be added unless we can test it.
- Linux is unknown.
If one needs access to display specific values such as the min/max
luminance when implementing tonemapping or a transfer function, that
needs platform/API specific approaches, and sadly the kind of data
exposed seems to vary, potentially making it difficult to maintain a
single cross-platform logic. With D3D one can get the
DXGI_OUTPUT_DESC1 from the IDXGIOutput6. This has the min/max
luminances in nits and a bunch of other things. For convenience the
output object is now exposed from the swapchain's nativeHandles()
whenever the D3D backend is used at run time. For Metal one would
presumably access maximumExtendedDynamicRangeColorComponentValue and
co. in the NSScreen. Elsewhere one needs to rely on platform/winsys
specific approaches, if there are any. Remains to be seen longer term
if/how this needs/can be better supported.
Change-Id: I2e61a0e062282d4bfdfba39655941c0f9a795112
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhi_p.h')
-rw-r--r-- | src/gui/rhi/qrhi_p.h | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 5344046841..7a3bfff0c7 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1327,6 +1327,12 @@ public: }; Q_DECLARE_FLAGS(Flags, Flag) + enum Format { + SDR, + HDRExtendedSrgbLinear, + HDR10 + }; + QRhiResource::Type resourceType() const override; QWindow *window() const { return m_window; } @@ -1335,6 +1341,9 @@ public: Flags flags() const { return m_flags; } void setFlags(Flags f) { m_flags = f; } + Format format() const { return m_format; } + void setFormat(Format f) { m_format = f; } + QRhiRenderBuffer *depthStencil() const { return m_depthStencil; } void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; } @@ -1349,13 +1358,17 @@ public: virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0; virtual QRhiRenderTarget *currentFrameRenderTarget() = 0; virtual QSize surfacePixelSize() = 0; + virtual bool isFormatSupported(Format f) = 0; virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0; virtual bool createOrResize() = 0; + virtual const QRhiNativeHandles *nativeHandles(); + protected: QRhiSwapChain(QRhiImplementation *rhi); QWindow *m_window = nullptr; Flags m_flags; + Format m_format = SDR; QRhiRenderBuffer *m_depthStencil = nullptr; int m_sampleCount = 1; QRhiRenderPassDescriptor *m_renderPassDesc = nullptr; |