Go Premium for a chance to win a PS4. Enter to Win


IDirect3DSwapChain9 Device Reset problem with different size back buffers.

Posted on 2004-09-22
Medium Priority
Last Modified: 2013-12-08
IDirect3DSwapChain9 Device Reset problem with different size back buffers.

I am developing a Direct3D X file GUI editor and am having a problem with how to display multiple views with the same device.  I started out with the Skinned Mesh Direct3D example and added four views using MFC classes derived from CMDIFrameWnd as the main frame, CMDIChildWnd as the child windows that have four splitter windows displayed in the child windows client area.  Each splitter window pane in each MDI child window displays a different view of the model (a perspective view, and orthogonal top, left, and front).  Since I started with the Skinned Mesh example, the splitter pane views actually use the same render view and is pretty much implemented the same as the Skinned Mesh example.

What I am doing right now, just to get it working, is loading my meshes four different times for each splitter pane view.  I have not changed the code yet nor have I moved the mesh, frame, and animation data into the document class where it would only be loaded once.  I would now like to do that, but there is a problem…

If I load the mesh from the derived CDocument class, I would need to first setup the ID3DXDevice9 interface and then load the mesh.  My Document View class for each splitter pane would have to create a IDirect3DSwapChain9 interface each time a view is created – the problem is that if the splitter panes are resized, the IDirect3DDevice9::Reset() function needs to be called to reset the device… which takes a pointer to the D3DPRESENT_PARAMETERS where the back buffer height and width are defined for the device… but if my splitter panes have different widths and heights, their back buffers will also.

How do you use a device swap chain if the back buffers are different sizes?


And to anyone that responds to this post, could explain exactly what I would have to do to implement the swap chains, it would help.  I also assume that I should create a different device9 interface for each MDI Child Window (one for all 4 splitter panes)… if there is more than one document open at a time, then there will have been just as many devices created.  I am pretty sure this is the way it should be – as far as I know, if the program has multiple documents open, there should NOT be just one device opened for the entire program - Is this the right way to do things – (I just want to make sure) – or is there a way to not link a mesh to a device when you load it.  And if so, how would you render the mesh.

My email address is:  vallas@comcast.net

Question by:danielvallas
  • 2
  • 2
LVL 17

Expert Comment

ID: 12143155
The way I used to do this was to create a single context the size of the entire window, and handle the 'splitter' myself.  Then you have virtual viewport rects into a unified buffer.  But that was a while ago, when DX was much more simple. ;)

Under DX9, you could do something similar, but you'd have to manage splitters yourself, which you probably don't want to do.

The other option is to create a single backbuffer for the entire window, and render each viewport as an independent pass, and blit them to the window.  Also one I don't like.

I agree that it seems like with DX9, you'd want to create a separate device interface for every splitter plane, so that they are independently managed contexts.  That will use a huge amount of resources, but the only way to avoid that is a single unified backbuffer approach....


Author Comment

ID: 12146775

Is there anyway to link the meshs loaded to multiple device's... or at least draw a mesh on a different device than the one that it was loaded with.

If not...

If I created a single backbuffer for the entire window, how would I blit the rendered pixels to a window that had a smaller size - like the individual panes - without only bliting a portion of the full size backbuffer window.  Is there a way to scale it to the size of the smaller splitter panes?  If you know how to do this, could you show a little example code of what I would have to do.

I really have to figure out how to use only one device for all 4 views of splitter panes - otherwise, I have to load the mesh file 4 different times for each device and splitter view... and every time I make a change to the mesh, I have to update 4 different meshes, etc.... like my program is currenlty doing.


Expert Comment

ID: 12149918
No, do not create a device for each view.  This is unnecessary and just a really bad idea because it requires duplicating resources across each device.  There is no reason to ever create more than one device per process unless you intend to drive multiple adapters.  That's fine, but multiple devices per adapter is always the wrong solution.

> the problem is that if the splitter panes are resized, the IDirect3DDevice9::Reset() function needs to be called to reset the device…

You do not have to reset the device here.  If you're creating a swap chain for each view then you simply have to recreate the swap chains when the splitter is moved.  Once the splitter has been moved call Release on each swap chain and then CreateAdditionalSwapChain for each view.  There are more sophisticated approaches that can reduce the swap chain destruction & recreation, but this is a very straightforward and simple solution that will work fine for most purposes.

Also note: The device has an implicit swap chain when you create it and reset it, as described by D3DPRESENT_PARAMETERS.  But if you're creating a swap chain for each view, then this implicit swap chain is not necessary, right?  So, while you can't avoid creating it, you can minimize the resources that it consumes by specifying a width and height of 1 when creating/resetting the device.  Which is what I recommend you do. ;-)

Accepted Solution

dkeithley earned 1500 total points
ID: 12149942
Follow up: Just to clarify, what you want is one swap chain per view.  There are other solutions, but this is the one I'm recommending here.

You use the CreateAdditionalSwapChain function to create them.  It takes a D3DPRESENT_PARAMETERS structure describing the swap chain.  Ignore the structure members which describe z-buffer and stencil buffer -- they are not used by this function.  So this means that if you're z-buffering, you need a z buffer that can accomodate each view.  In most cases you can just create a single z-buffer using CreateDepthStencilSurface and share it among the views.  Just make sure it's larger than each view in x and y.

To render a view, call GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, ...) on the view's swap chain.  This gives you back a surface.  Pass that surface to SetRenderTarget(0, ...) on the device.  Make sure the z-buffer is set via SetDepthStencilSurface.  When you're done rendering, call Present on the IDirect3DSwapChain9 interface -- not on IDirect3DDevice9.

And I think that about covers it.  Good luck!

Author Comment

ID: 12150706

Thanks for the solution.  I will not be able to actually fix my program and see whether your solution will work for another couple of weeks, because it is a major fix, and I have other things to do to the program right now.  I will save it and assume it will work and accept the solution for now.  

As far as having multiple device's open at the same time... What I want is to have one device per mesh file that you open - and then have 4 swap chain entries created for the 4 different views of each mesh file loaded.  I don't think I would actually want one device created for multiple files... one device for multiple views of a file, yes...  but not multiple files (it is a Multi-Document-Interface, MDI, program).

I would just like to add that you seem knowlegeable on the Direct3X subject - maybe you could help with my other posts...
   Problem translating Direct3D Skinned Mesh Bones with SOFTWARE skinning method
   Selecting Vertexes with a Bounding Selection Box in Perspective View

Thanks again.


Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is RenderMan: RenderMan is a not any particular piece of software. RenderMan is an industry standard, defining set of rules that any rendering software should use, to be RenderMan-compliant. Pixar's RenderMan is a flagship implementation of …
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…

916 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question