3
votes

I'm using Direct2D to render my user interface.

What I would like is to be more easily able to profile my ui rendering (since I'm using several panels using Graphics debugger is a bit cumbersome).

Since I know that Direct2D uses a Direct3D device (exactly d3d11 device using 10_0 feature level) under the hood, I'd like to know if it is possible to retrieve either a ID310Device or ID3D11Device instance from ID2D1RenderTarget or ID2D1Factory object.

In that case I would easily be able to attach a timestamp query on the BeginDraw/EndDraw calls.

I tried several QueryInterface calls, but none of them have been sucessful so far.

1
I already checked this link, but sadly it doesn't provide a solution for my use case, there's nothing there to allows to retrieve d3d device from render target. - mrvux
I don't think it's possible. But it can be done the other way around. Setup D3D and render D2D in it. On Windows 8.1 you can interop D3D11 with D2D1 easily. - CodeAngry
You're pretty much right, I went that way in my render panels, create a dx11 swapchain and assign a d2d device context to the surface. Was so easy it's even embarassing I didn't do that ove before ;) Now works like a charm, can mix dx11 render and run queries. - mrvux

1 Answers

3
votes

An interesting undocumented secret is that any ID2D1RenderTarget you get from ID2D1Factory will also be an ID2D1DeviceContext (it seems to be intentional from what I've gathered, just accidentally undocumented?). Just call IUnknown::QueryInterface() to snag it. From there you can toy around with methods like GetDevice() and GetTarget(). If you can get the target then you may be able to weasel your way to obtaining the IDXGISurface which supports IDXGIDeviceSubObject::GetDevice() https://msdn.microsoft.com/en-us/library/windows/desktop/bb174529(v=vs.85).aspx (I haven't verified this part)

And in Win10 it looks like ID2D1Device2 gives you precisely what you want: GetDxgiDevice() https://msdn.microsoft.com/en-us/library/windows/desktop/dn917489(v=vs.85).aspx . So in that case, your ID2D1RenderTarget is cast to an ID2D1DeviceContext via IUnknown::QueryInterface(), and then you get an ID2D1Device via ID2D1DeviceContext::GetDevice() and then cast it to an ID2D1Device2 via another call to IUnknown::QueryInterface().