Repository navigation
Conversation
Co-Authored-By: Codex <codex@openai.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Codex <codex@openai.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
hzqst
force-pushed
the
fix/d3d12-fence-wait-816
branch
from
October 24, 2026 07:17
8f88007 to
720904a
Compare
|
Nice! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #816.
FenceD3D12Impl::Wait()armed one shared manual-reset event withID3D12Fence::SetEventOnCompletion()and never reset it. After the first wait that actually blocked, the event stayed signaled, so every laterWait(Value)returned immediately whileGetCompletedValue() < Value. Besides application code like the one in #816, this also breaks the frames-in-flight limit inOffScreenSwapChain::Present(), which relies onIFence::Wait().Changes
This PR has two commits.
D3D12: fix IFence::Wait() returning before the fence reaches the value
SetEventOnCompletion()and remove the shared event. The documentation states: "If hEvent is a null handle, then this API will not return until the specified fence value(s) have been reached." and "This method can be safely called from multiple threads at one time."CommandQueueD3D12Impl:CreateEvent()returnsNULLon failure, notINVALID_HANDLE_VALUE.FenceTest.RepeatedCPUWait: for four consecutive values, a second thread signals the fence on the CPU 20 ms after the main thread starts waiting, and the test checks that eachWait()returns only after its value is reached. It requiresNativeFence, so it is skipped on D3D11, OpenGL and WebGPU.D3D11/D3D12: close DXGI frame-latency waitable object handles
IDXGISwapChain2::GetFrameLatencyWaitableObject()must be closed withCloseHandle()(documentation). It was overwritten every time the swap chain was recreated (SetMaximumFrameLatency(),SetFullscreenMode()) and never closed on destruction. It is now closed at the start ofCreateDXGISwapChain(), where the previous swap chain has already been released, and in the destructor.Validation
Windows x64, MSVC 2022, Debug build of
DiligentCoreAPITest.Regression test against the previous implementation (the pre-PR
FenceD3D12Impl.cpp/.hpptemporarily restored, then this PR's version):FenceTest.RepeatedCPUWait--mode=d3d12_sw)--mode=d3d12, RTX 5060)The previous implementation fails exactly as described in #816: the first wait is correct and every later one returns early:
Handle leak. The API tests render to a testing swap chain and never create a DXGI swap chain, so this was checked with a temporary test that is not part of the PR: create a D3D12 swap chain for a window, recreate it 32 times via
SetMaximumFrameLatency(), destroy it, and compare the process handle count (measured after a warm-up pass; same results on WARP and hardware):Existing tests (
--gtest_filter=FenceTest.*:MultipleContextTest.*:TestingSwapChainBaseTest.*):NativeFenceor multiple queues)