Are IUnknown AddRef and Release interfaces are thread safe (atomic)? I know what they do are incrementing/decrementing reference counts, but I wonder how they do.
Particularly, IUnknown interface that inherits to Direct 3D components such as ID3D12DeviceChild. Version of Direct 3D is 12 if necessary. The reason why I'm mentioning Direct 3D is I've read a statement "DirectX APIs are not "true COM"". So it might differ from "true COM".
The reason why I got confused is due to failure in finding official document or proof that the interfaces are internally using whether Interlocked API or using simple increment/decrement operator.
Reference of simple increment/decrement operator implementation.
ULONG CMyObj::Release()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
References of Interlocked API (1), (2).
ULONG CMyMAPIObject::Release()
{
// Decrement the object's internal counter.
ULONG ulRefCount = InterlockedDecrement(m_cRef);
if (0 == m_cRef)
{
delete this;
}
return ulRefCount;
}
Other related references :
- Programming DirectX with COM
- How IUnknown Works
- It is invalid to use an immediate context concurrently with most of the DXGI interface functions. For the March 2009 and later DirectX SDKs, the only DXGI functions that are safe are AddRef, Release, and QueryInterface.
I need to know whether they are thread safe because my project is multithreaded so that how I should treat them. If anyone can help, it will be really appreciated.
CodePudding user response:
TL;DR: For Direct3D 11, Direct3D 12, and DXGI, all use of the IUnknown
methods should be 'thread-safe'.
For Direct3D 11, the methods of ID3D11Device
are all 'thread-safe' by design. The methods of ID3D11DeviceContext
are not 'thread-safe'. That said, you can safely call AddRef
and Release
on all ID3D11DeviceChild
-derived classes from any thread.
For Direct3D 12, the methods of ID3D12Device
are also 'thread-safe'. Individual command-lists are not 'thread-safe' so you are expected to only use a command list interface from one thread at time. Keep in mind that in Direct3D 12, the application is responsible for handling all the CPU/GPU synchronization as well.
A key difference with Direct3D Device Child objects is that they are NOT immediately cleaned up when their reference counts hit 0. Since it uses 'deferred destruction' they get cleaned up at some later point, typically a Flush
or Present
.