Sign in to follow this  
Barguast

[C# / SlimDX /D3D9] Rendering to multiple windows

Recommended Posts

What is the best way to render to multiple windows using SlimDX? I have a single device instance (since all the windows will share the same resources) but I want to be able to render the scene differently (for example, viewed from a different direction) to each window. I had the idea of using SetRenderTarget to draw to an off-screen texture and drawing that to each window, but is there must be another way? If it makes a difference, I want to be able to add windows dynamically without having to reset the device. Windows will also be of varying sizes. Thanks. [Edited by - Barguast on March 31, 2010 5:42:32 PM]

Share this post


Link to post
Share on other sites
I tried using a swap chain, but I'm a bit confused about the involvement of a swap chain with normal Direct3D operations. So here are a couple of questions about that;

- When rendering to a swap chain, is it the correct procedure to use SetRenderTarget with the result of SwapChain.GetBackBuffer(0)? If so, do I have to dispose of this Surface when the frame has been completed?

- When the swap chain target (window) size changes, how do I resize the back buffer? Do I call reset? Do I need to dispose of all swap chains and re-create them in order to do this?


Thanks in advance.

Share this post


Link to post
Share on other sites
Not to nag (well, maybe a little :p) but I'd be amazed if no-one has worked on this kind of problem before! Any help would be appreciated. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Gage64
The first two entries from here seem useful. They use C++, but it's probably very similar in SlimDX.


Thanks but I've read those already and they don't address my questions above. For example, they don't deal with resizing a swap chain, and they Get / Release their back buffer with each render.

I've managed to get an application working, but I still have those questions lingering. I have to dispose of the swap chains before calling Reset, and recreate them afterwards. I'm not sure if that is the required way of doing things?

Also, what is the overhead of calling GetBackBuffer on a swap chain, and Dispose afterwards? I'm doing this every frame at the moment, just for simplicitity, and I don't know if I would be better off just calling GetBackBuffer once and keeping the returned Surface reference around until I close my app?

Share this post


Link to post
Share on other sites
Yes, creating a swap chain for each window is the way to do it as you mentioned. You manually handle the resizing of each window and the according swap chain.

When a window resizes, you dispose each render target (if you use MRT) and then your swap chain. After destroying the views, you recreate them with the new dimensions of the client area.

EDIT: after reading your second post of your thread; you use the SwapChain instance itself as the input SetRenderTarget and not the .GetBackBuffer(0) result.

Share this post


Link to post
Share on other sites
So if one of my windows resizes, I have to reset the entire device in order to resize the swap chain buffers? O_O

Quote:
Original post by Xeile
EDIT: after reading your second post of your thread; you use the SwapChain instance itself as the input SetRenderTarget and not the .GetBackBuffer(0) result.


But SetRenderTarget expects a Surface parameter? So I do:

using (Surface backBuffer = swapChain.GetBackBuffer(0))
{
device.SetRenderTarget(0, backBuffer);

...
}


The above demonstrates my question about disposal of the back buffer. Should I be doing this once per frame, as above, or should I get the reference on creating the swap chain, and disposing of it after I've finished with it?

Share this post


Link to post
Share on other sites
Aaah you are using DX9, somehow I thought DX10. Yes, the way you do it seems approriate.

I do not know the work load you create by calling the GetBackBuffer method each frame, for that should use a profiler is see how big the impact is of the call opposed of the rest of the frame code calls.

Share this post


Link to post
Share on other sites
Quote:
Original post by Barguast

- When the swap chain target (window) size changes, how do I resize the back buffer? Do I call reset? Do I need to dispose of all swap chains and re-create them in order to do this?



If the window is using an additional swap chain (AKA, a swap chain you created manually) then all you have to do is create a new swap chain and dispose of the old one. If the window is using the implicit swap chain (the swap chain created with the device), then you can't destroy it so you have to reset the device.

It's possible to have all windows use additional swap chains and just ignore the implicit swap chain, which means you never have to reset the device for a resize. However if you do this programs that overlay a HUD on your window (NVPerfHUD, PIX, etc.) won't work correctly since they assume that you use the implicit swap chain.

Share this post


Link to post
Share on other sites
Ah, that's good to know. Indeed, I don't use the implicit swap chain at all anyway! Many thanks. :)

Only question remaining (not a biggy) is whether I should be accessing (GetBackBuffer) and disposing the swap chain back buffers once per frame or not. I'm not really fussed on whether it is performant or not, more if I should be doing it in the first place.

I'm worried that calling Dispose on the GetBackBuffer result is destroying the back buffer, causing it to be recreated every frame (which I'd obviously rather avoid).

Share this post


Link to post
Share on other sites
Quote:
Original post by Barguast
Only question remaining (not a biggy) is whether I should be accessing (GetBackBuffer) and disposing the swap chain back buffers once per frame or not. I'm not really fussed on whether it is performant or not, more if I should be doing it in the first place.

I'm worried that calling Dispose on the GetBackBuffer result is destroying the back buffer, causing it to be recreated every frame (which I'd obviously rather avoid).


It's not possible to actually destroy a back buffer unless you dispose the back buffer *and* you dispose the associated swap chain (or device). So there shouldn't be a problem with you calling GetBackBuffer every frame.

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
Quote:
Original post by Barguast
Only question remaining (not a biggy) is whether I should be accessing (GetBackBuffer) and disposing the swap chain back buffers once per frame or not. I'm not really fussed on whether it is performant or not, more if I should be doing it in the first place.

I'm worried that calling Dispose on the GetBackBuffer result is destroying the back buffer, causing it to be recreated every frame (which I'd obviously rather avoid).


It's not possible to actually destroy a back buffer unless you dispose the back buffer *and* you dispose the associated swap chain (or device). So there shouldn't be a problem with you calling GetBackBuffer every frame.

Does Dispose merely reduce the number of references to the back buffer (given that Surface is a COMObject), and as such won't actually destroy the Surface until the last reference (held by the swap chain itself) is disposed? If so, that makes sense.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this