In my app I render my Direct3D content to the window, as recommended, using the swap chain in flip sequential mode (IDXGISwapChain1
, DXGI_SWAP_EFFECT_SEQUENTIAL
), in a window without redirection bitmap (WS_EX_NOREDIRECTIONBITMAP
)
However for the purpose of smooth window resizing (without lags and flicker), I want to intercept live resize enter/exit events and temporarily switch the rendering to ID2D1HwndRenderTarget
to the window's redirection surface, which seems to be offer the smoothest possible resize.
The question is - how to render the Direct3D content to ID2D1HwndRenderTarget
?
The problem is that obviously the Direct3D rendering and ID2D1HwndRenderTarget
belong to different devices and I don't seem to find a way to interop them together.
What ideas come to mind:
A. Somehow assign ID2D1HwndRenderTarget
to be the output frame buffer for 3D rendering. This would be the best case scenario, because it would minimize buffer copying.
- Somehow obtain a
ID3D11Texture2D
or at least anIDXGISurface
from theID2D1HwndRenderTarget
- Create render target
ID3D11Device::CreateRenderTargetView
from the DXGI surface / Direct3D texture - Set render target
ID3D11DeviceContext::OMSetRenderTargets
- Render directly to the
ID2D1HwndRenderTarget
The problem is in step 1. ID2D1HwndRenderTarget
and its ancestor ID2D1RenderTarget
seem pretty scarce and don't seem to provide this capability. Is there a way to obtain a DXGI or D3D surface from the ID2D1HwndRenderTarget
?
B. Create an off-screen Direct3D frame buffer texture, render the 3D content there and then copy it to the window render target.
Create off-screen texture
ID3D11Texture2D
(ID3D11Device::CreateTexture2D
)Create a
ID2D1Device
usingD2D1CreateDevice
(from the sameIDXGIDevice
as myID3D11Device
)Create a
ID2D1DeviceContext
usingID2D1Device::CreateDeviceContext
Create a
ID2D1Bitmap
usingID2D1DeviceContext::CreateBitmapFromDxgiSurface
Draw the bitmap using
ID2D1HwndRenderTarget::DrawBitmap
Unfortunately, I get the error message "An operation failed because a device-dependent resource is associated with the wrong ID2D1Device (resource domain)
". Obviously, the resource comes from a different ID2D1Device
But how to draw a texture bitmap from one Direct2D device onto another?
C. Out of desperation, I tried to map the content of my frame buffer to CPU memory using IDXGISurface::Map
, however this is tricky because it requires D3D11_USAGE_STAGING
and D3D11_CPU_ACCESS_READ
flags when creating the texture, which then seems make it impossible to use this texture as an output frame buffer (or am I missing something?). And generally this technique will be most likely very slow, because it involves syncing between CPU and GPU, and copying the whole texture at least two times.
Has anyone ever succeeded with the task of rendering 3D content to a ID2D1HwndRenderTarget
? Please share your experience. Thanks!