rhi: d3d12: Also default to max frame latency 2
Follow what's been done in the D3D11 backend. Slightly different logic here and there due to always having the newer interfaces available, but does the same thing. Use QT_D3D_MAX_FRAME_LATENCY to override the default 2. [ChangeLog][RHI] The D3D12 backend creates swapchains from now on with DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT by default, with a max frame latency of 2. Task-number: QTBUG-127267 Change-Id: I4d0361ab546a1c0041592389f8954281f588b0ba Reviewed-by: Andy Nichols <andy.nichols@qt.io> (cherry picked from commit 91cae3f9cc9cb97eab69e39d405000f2fd1e533a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
9200606068
commit
1e6950fd77
@ -223,6 +223,11 @@ bool QRhiD3D12::create(QRhi::Flags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qEnvironmentVariableIsSet("QT_D3D_MAX_FRAME_LATENCY"))
|
||||||
|
maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue("QT_D3D_MAX_FRAME_LATENCY")));
|
||||||
|
if (maxFrameLatency != 0)
|
||||||
|
qCDebug(QRHI_LOG_INFO, "Using frame latency waitable object with max frame latency %u", maxFrameLatency);
|
||||||
|
|
||||||
supportsAllowTearing = false;
|
supportsAllowTearing = false;
|
||||||
IDXGIFactory5 *factory5 = nullptr;
|
IDXGIFactory5 *factory5 = nullptr;
|
||||||
if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5), reinterpret_cast<void **>(&factory5)))) {
|
if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5), reinterpret_cast<void **>(&factory5)))) {
|
||||||
@ -1527,6 +1532,9 @@ QRhi::FrameOpResult QRhiD3D12::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
|
|||||||
for (QD3D12SwapChain *sc : std::as_const(swapchains))
|
for (QD3D12SwapChain *sc : std::as_const(swapchains))
|
||||||
sc->waitCommandCompletionForFrameSlot(currentFrameSlot); // note: swapChainD->currentFrameSlot, not sc's
|
sc->waitCommandCompletionForFrameSlot(currentFrameSlot); // note: swapChainD->currentFrameSlot, not sc's
|
||||||
|
|
||||||
|
if (swapChainD->frameLatencyWaitableObject)
|
||||||
|
WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000, true);
|
||||||
|
|
||||||
HRESULT hr = cmdAllocators[currentFrameSlot]->Reset();
|
HRESULT hr = cmdAllocators[currentFrameSlot]->Reset();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
qWarning("Failed to reset command allocator: %s",
|
qWarning("Failed to reset command allocator: %s",
|
||||||
@ -6122,6 +6130,11 @@ void QD3D12SwapChain::destroy()
|
|||||||
dcompTarget = nullptr;
|
dcompTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frameLatencyWaitableObject) {
|
||||||
|
CloseHandle(frameLatencyWaitableObject);
|
||||||
|
frameLatencyWaitableObject = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
QRHI_RES_RHI(QRhiD3D12);
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
if (rhiD) {
|
if (rhiD) {
|
||||||
rhiD->swapchains.remove(this);
|
rhiD->swapchains.remove(this);
|
||||||
@ -6338,6 +6351,14 @@ bool QD3D12SwapChain::createOrResize()
|
|||||||
if (swapInterval == 0 && rhiD->supportsAllowTearing)
|
if (swapInterval == 0 && rhiD->supportsAllowTearing)
|
||||||
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||||
|
|
||||||
|
// maxFrameLatency 0 means no waitable object usage.
|
||||||
|
// Ignore it also when NoVSync is on, and when using WARP.
|
||||||
|
const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
|
||||||
|
&& swapInterval != 0
|
||||||
|
&& rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
|
||||||
|
if (useFrameLatencyWaitableObject)
|
||||||
|
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||||
|
|
||||||
if (!swapChain) {
|
if (!swapChain) {
|
||||||
chooseFormats();
|
chooseFormats();
|
||||||
|
|
||||||
@ -6394,6 +6415,10 @@ bool QD3D12SwapChain::createOrResize()
|
|||||||
qPrintable(QSystemError::windowsComString(hr)));
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (useFrameLatencyWaitableObject) {
|
||||||
|
swapChain->SetMaximumFrameLatency(rhiD->maxFrameLatency);
|
||||||
|
frameLatencyWaitableObject = swapChain->GetFrameLatencyWaitableObject();
|
||||||
|
}
|
||||||
if (dcompVisual) {
|
if (dcompVisual) {
|
||||||
hr = dcompVisual->SetContent(swapChain);
|
hr = dcompVisual->SetContent(swapChain);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
|
@ -1044,6 +1044,7 @@ struct QD3D12SwapChain : public QRhiSwapChain
|
|||||||
QD3D12SwapChainRenderTarget rtWrapper;
|
QD3D12SwapChainRenderTarget rtWrapper;
|
||||||
QD3D12SwapChainRenderTarget rtWrapperRight;
|
QD3D12SwapChainRenderTarget rtWrapperRight;
|
||||||
QD3D12CommandBuffer cbWrapper;
|
QD3D12CommandBuffer cbWrapper;
|
||||||
|
HANDLE frameLatencyWaitableObject = nullptr;
|
||||||
|
|
||||||
struct FrameResources {
|
struct FrameResources {
|
||||||
ID3D12Fence *fence = nullptr;
|
ID3D12Fence *fence = nullptr;
|
||||||
@ -1194,6 +1195,7 @@ public:
|
|||||||
void bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD);
|
void bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD);
|
||||||
|
|
||||||
bool debugLayer = false;
|
bool debugLayer = false;
|
||||||
|
UINT maxFrameLatency = 2; // 1-3, use 2 to keep CPU-GPU parallelism while reducing lag compared to tripple buffering
|
||||||
ID3D12Device2 *dev = nullptr;
|
ID3D12Device2 *dev = nullptr;
|
||||||
D3D_FEATURE_LEVEL minimumFeatureLevel = D3D_FEATURE_LEVEL(0);
|
D3D_FEATURE_LEVEL minimumFeatureLevel = D3D_FEATURE_LEVEL(0);
|
||||||
LUID adapterLuid = {};
|
LUID adapterLuid = {};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user