rhi: d3d: Fix up non-vsynced presentation
Doing Present(0, 0) is not necessarily sufficient to get rid of blocking. It may very well start blocking after a few frames. This does not apply to a non-flip-discard swapchain (when running with QT_D3D_NO_FLIP=1), but for flip-discard we should also try using DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING and DXGI_PRESENT_ALLOW_TEARING in case a swap interval of 0 is wanted. Pick-to: 6.3 Fixes: QTBUG-99949 Change-Id: I9cb13b139ba04e41b4f25b94bcd3d1e973496414 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
d671bab0e3
commit
6dd09664b2
@ -202,19 +202,32 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
|
||||
dxgiFactory = createDXGIFactory2();
|
||||
if (dxgiFactory != nullptr) {
|
||||
hasDxgi2 = true;
|
||||
supportsFlipDiscardSwapchain = !qEnvironmentVariableIntValue("QT_D3D_NO_FLIP");
|
||||
} else {
|
||||
dxgiFactory = createDXGIFactory1();
|
||||
hasDxgi2 = false;
|
||||
supportsFlipDiscardSwapchain = false;
|
||||
}
|
||||
|
||||
if (dxgiFactory == nullptr)
|
||||
return false;
|
||||
|
||||
qCDebug(QRHI_LOG_INFO, "DXGI 1.2 = %s, FLIP_DISCARD swapchain supported = %s",
|
||||
hasDxgi2 ? "true" : "false", supportsFlipDiscardSwapchain ? "true" : "false");
|
||||
supportsAllowTearing = false;
|
||||
if (supportsFlipDiscardSwapchain) {
|
||||
// For a FLIP_DISCARD swapchain Present(0, 0) is not necessarily
|
||||
// sufficient to get non-blocking behavior, try using ALLOW_TEARING
|
||||
// when available.
|
||||
IDXGIFactory5 *factory5 = nullptr;
|
||||
if (SUCCEEDED(dxgiFactory->QueryInterface(IID_IDXGIFactory5, reinterpret_cast<void **>(&factory5)))) {
|
||||
BOOL allowTearing = false;
|
||||
if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))))
|
||||
supportsAllowTearing = allowTearing;
|
||||
factory5->Release();
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(QRHI_LOG_INFO, "FLIP_DISCARD swapchain supported = %s, ALLOW_TEARING supported = %s",
|
||||
supportsFlipDiscardSwapchain ? "true" : "false",
|
||||
supportsAllowTearing ? "true" : "false");
|
||||
|
||||
if (!importedDeviceAndContext) {
|
||||
IDXGIAdapter1 *adapter;
|
||||
@ -1160,7 +1173,9 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
||||
}
|
||||
|
||||
if (!flags.testFlag(QRhi::SkipPresent)) {
|
||||
const UINT presentFlags = 0;
|
||||
UINT presentFlags = 0;
|
||||
if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
|
||||
presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
|
||||
HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
|
||||
qWarning("Device loss detected in Present()");
|
||||
@ -4551,27 +4566,36 @@ bool QD3D11SwapChain::createOrResize()
|
||||
return false;
|
||||
|
||||
QRHI_RES_RHI(QRhiD3D11);
|
||||
bool useFlipDiscard = rhiD->hasDxgi2 && rhiD->supportsFlipDiscardSwapchain;
|
||||
bool useFlipDiscard = rhiD->supportsFlipDiscardSwapchain;
|
||||
|
||||
// Take a shortcut for alpha: whatever the platform plugin does to enable
|
||||
// transparency for our QWindow will be sufficient on the legacy (DISCARD)
|
||||
// path. For FLIP_DISCARD we'd need to use DirectComposition (create a
|
||||
// IDCompositionDevice/Target/Visual), avoid that for now. (this though
|
||||
// means HDR and semi-transparent windows cannot be combined)
|
||||
if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
|
||||
useFlipDiscard = false;
|
||||
if (window->requestedFormat().alphaBufferSize() <= 0)
|
||||
qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
|
||||
"This may lead to problems.");
|
||||
}
|
||||
|
||||
swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
|
||||
swapChainFlags = 0;
|
||||
|
||||
// A non-flip swapchain can do Present(0) as expected without
|
||||
// ALLOW_TEARING, and ALLOW_TEARING is not compatible with it at all so the
|
||||
// flag must not be set then. Whereas for flip-discard we should use it, if
|
||||
// supported, to get better results for 'unthrottled' presentation.
|
||||
if (swapInterval == 0 && useFlipDiscard && rhiD->supportsAllowTearing)
|
||||
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
|
||||
const UINT swapChainFlags = 0;
|
||||
if (!swapChain) {
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
|
||||
colorFormat = DEFAULT_FORMAT;
|
||||
srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
|
||||
|
||||
// Take a shortcut for alpha: our QWindow is OpenGLSurface so whatever
|
||||
// the platform plugin does to enable transparency for OpenGL window
|
||||
// will be sufficient for us too on the legacy (DISCARD) path. For
|
||||
// FLIP_DISCARD we'd need to use DirectComposition (create a
|
||||
// IDCompositionDevice/Target/Visual), avoid that for now.
|
||||
if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
|
||||
useFlipDiscard = false;
|
||||
if (window->requestedFormat().alphaBufferSize() <= 0)
|
||||
qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
|
||||
"This may lead to problems.");
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
if (useFlipDiscard) {
|
||||
DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // SDR
|
||||
@ -4651,9 +4675,9 @@ bool QD3D11SwapChain::createOrResize()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Windows 7 for instance. Use DISCARD mode. Regardless, keep on
|
||||
// using our manual resolve for symmetry with the FLIP_DISCARD code
|
||||
// path when MSAA is requested.
|
||||
// Fallback: use DISCARD mode. Regardless, keep on using our manual
|
||||
// resolve for symmetry with the FLIP_DISCARD code path when MSAA
|
||||
// is requested. This has no HDR support.
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
@ -4749,7 +4773,6 @@ bool QD3D11SwapChain::createOrResize()
|
||||
currentFrameSlot = 0;
|
||||
frameCount = 0;
|
||||
ds = m_depthStencil ? QRHI_RES(QD3D11RenderBuffer, m_depthStencil) : nullptr;
|
||||
swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
|
||||
|
||||
QD3D11ReferenceRenderTarget *rtD = QRHI_RES(QD3D11ReferenceRenderTarget, &rt);
|
||||
rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
|
||||
|
@ -576,6 +576,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
DXGI_FORMAT colorFormat;
|
||||
DXGI_FORMAT srgbAdjustedColorFormat;
|
||||
IDXGISwapChain *swapChain = nullptr;
|
||||
UINT swapChainFlags = 0;
|
||||
static const int BUFFER_COUNT = 2;
|
||||
ID3D11Texture2D *backBufferTex;
|
||||
ID3D11RenderTargetView *backBufferRtv;
|
||||
@ -727,8 +728,8 @@ public:
|
||||
ID3DUserDefinedAnnotation *annotations = nullptr;
|
||||
IDXGIAdapter1 *activeAdapter = nullptr;
|
||||
IDXGIFactory1 *dxgiFactory = nullptr;
|
||||
bool hasDxgi2 = false;
|
||||
bool supportsFlipDiscardSwapchain = false;
|
||||
bool supportsAllowTearing = false;
|
||||
bool deviceLost = false;
|
||||
QRhiD3D11NativeHandles nativeHandlesStruct;
|
||||
QRhiDriverInfo driverInfoStruct;
|
||||
|
Loading…
Reference in New Issue
Block a user