Hi,
Does anyone know if it is safe to call IDXGISwapChain3::Present() on one thread, while at the same time calling ID3D12CommandQueue::ExecuteCommandLists() on another thread?
I have an application that creates two windows, one for each monitor. I have two threads that render to these two windows simultaneously. Each thread has its own ID3D12Device, ID3D12CommandQueue, IDXGISwapChain3, everything... they are completely independent.
Yet the application hangs randomly. Below are the call stacks of the two threads when they hang:
ntdll.dll!NtWaitForAlertByThreadId() ntdll.dll!RtlpWaitOnAddressWithTimeout() ntdll.dll!RtlpWaitOnAddress() ntdll.dll!RtlpWaitOnCriticalSection() ntdll.dll!RtlpEnterCriticalSectionContended() D3D12.dll!CCommandQueue<0>::ExecuteCommandLists(unsigned int,struct ID3D12CommandList * const *) dxgi.dll!CD3D12Device::CloseAndSubmitCommandList(unsigned int,enum CD3D12Device::QueueType) dxgi.dll!CD3D12Device::PresentExtended(struct DXGI_PRESENTSURFACE const *,struct IDXGIResource * const *,unsigned int,struct IDXGIResource *,void *,unsigned int,unsigned int,int *,unsigned int *) dxgi.dll!CDXGISwapChain::FlipPresentToDWM(struct SPresentArgs const *,unsigned int,unsigned int,unsigned int &,unsigned int,struct tagRECT const *,struct DXGI_SCROLL_RECT const *,struct DXGI_INTERNAL_CONTENT_PROTECTION const &) dxgi.dll!CDXGISwapChain::PresentImplCore(struct SPresentArgs const *,unsigned int,unsigned int,unsigned int,struct tagRECT const *,unsigned int,struct DXGI_SCROLL_RECT const *,struct IDXGIResource *,bool &,bool &,bool &) dxgi.dll!CDXGISwapChain::Present(unsigned int,unsigned int) MyApp.exe!gui::CDXProc::CJob::Present() Line 963 C++ ntdll.dll!NtWaitForAlertByThreadId() ntdll.dll!RtlpWaitOnAddressWithTimeout() ntdll.dll!RtlpWaitOnAddress() ntdll.dll!RtlpWaitOnCriticalSection() ntdll.dll!RtlpEnterCriticalSectionContended() dxgi.dll!CDXGISwapChain::GetCurrentBackBufferIndex(void) dxgi.dll!CDXGISwapChain::GetCurrentCommandQueue(struct _GUID const &,void * *) D3D12.dll!CCommandQueue<0>::ExecuteCommandLists(unsigned int,struct ID3D12CommandList * const *) MyApp.exe!gui::CDXProc::CJob::ExecuteCommandList(ID3D12CommandList * iCommandList) Line 1172 C++
As you can see, the one thread is stuck in the Present() call, while the other thread is stuck inside ExecuteCommandLists().
I can get around the problem by putting a critical section around all calls to Present() and ExecuteCommandLists(), but I do not understand why this is necessary. Any ideas?