Add stereo support for Dx11 RHI

Change-Id: I10ef8f80b4b4bcb91fc99ab4ab77f2ac031dbd33
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Ilya Doroshenko 2023-07-21 22:03:21 +02:00
parent 4694a1b2ae
commit 9316689551
3 changed files with 42 additions and 5 deletions

View File

@ -7221,8 +7221,8 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
is backed by two color buffers, one for each eye, instead of just one.
When stereoscopic rendering is not supported, the return value will be
the default target. For the time being the only backend and 3D API where traditional
stereoscopic rendering is supported is OpenGL (excluding OpenGL ES), in
the default target. For the time being the only backends and 3D API where traditional
stereoscopic rendering is supported are OpenGL (excluding OpenGL ES) and Direct3D 11, in
combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
by the graphics and display driver stack at run time. All other backends
are going to return the default render target from this overload.

View File

@ -4781,9 +4781,7 @@ bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context,
}
QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
rt(rhi, this),
cb(rhi)
: QRhiSwapChain(rhi), rt(rhi, this), rtRight(rhi, this), cb(rhi)
{
backBufferTex = nullptr;
backBufferRtv = nullptr;
@ -4804,6 +4802,10 @@ void QD3D11SwapChain::releaseBuffers()
backBufferRtv->Release();
backBufferRtv = nullptr;
}
if (backBufferRtvRight) {
backBufferRtvRight->Release();
backBufferRtvRight = nullptr;
}
if (backBufferTex) {
backBufferTex->Release();
backBufferTex = nullptr;
@ -4857,6 +4859,11 @@ QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget()
return &rt;
}
QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
{
return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
}
QSize QD3D11SwapChain::surfacePixelSize()
{
Q_ASSERT(m_window);
@ -4965,6 +4972,7 @@ bool QD3D11SwapChain::createOrResize()
// resize the buffers then.
const bool needsRegistration = !window || window != m_window;
const bool stereo = m_window->format().stereo();
// except if the window actually changes
if (window && window != m_window)
@ -5064,6 +5072,7 @@ bool QD3D11SwapChain::createOrResize()
desc.Flags = swapChainFlags;
desc.Scaling = DXGI_SCALING_NONE;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.Stereo = stereo;
if (dcompVisual) {
// With DirectComposition setting AlphaMode to STRAIGHT fails the
@ -5179,6 +5188,19 @@ bool QD3D11SwapChain::createOrResize()
return false;
}
if (stereo) {
// Create a second render target view for the right eye
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.FirstArraySlice = 1;
rtvDesc.Texture2DArray.ArraySize = 1;
hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
if (FAILED(hr)) {
qWarning("Failed to create rtv for swapchain backbuffer (right eye): %s",
qPrintable(QSystemError::windowsComString(hr)));
return false;
}
}
// Try to reduce stalls by having a dedicated MSAA texture per swapchain buffer.
for (int i = 0; i < BUFFER_COUNT; ++i) {
if (sampleDesc.Count > 1) {
@ -5217,6 +5239,18 @@ bool QD3D11SwapChain::createOrResize()
rtD->d.colorAttCount = 1;
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
if (stereo) {
rtD = QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
rtD->d.pixelSize = pixelSize;
rtD->d.dpr = float(window->devicePixelRatio());
rtD->d.sampleCount = int(sampleDesc.Count);
rtD->d.colorAttCount = 1;
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
rtD->d.rtv[0] = backBufferRtvRight;
rtD->d.dsv = ds ? ds->dsv : nullptr;
}
if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
timestamps.prepare(BUFFER_COUNT, rhiD);
// timestamp queries are optional so we can go on even if they failed

View File

@ -579,6 +579,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
QRhiCommandBuffer *currentFrameCommandBuffer() override;
QRhiRenderTarget *currentFrameRenderTarget() override;
QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
QSize surfacePixelSize() override;
bool isFormatSupported(Format f) override;
@ -594,6 +595,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
QWindow *window = nullptr;
QSize pixelSize;
QD3D11SwapChainRenderTarget rt;
QD3D11SwapChainRenderTarget rtRight;
QD3D11CommandBuffer cb;
DXGI_FORMAT colorFormat;
DXGI_FORMAT srgbAdjustedColorFormat;
@ -601,6 +603,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
UINT swapChainFlags = 0;
ID3D11Texture2D *backBufferTex;
ID3D11RenderTargetView *backBufferRtv;
ID3D11RenderTargetView *backBufferRtvRight = nullptr;
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];