Swap chain rendering to multiple views

Started by
25 comments, last by RobM 9 years, 3 months ago


in windowed mode with a device created when the app in maximized, the front buffer will be created to the full size of the screen

If you mean by default - not quite the full size of the screen. I.e., maximized is not the same as full-screen. The buffer is created the size of client area of the window. When maximized, the window has non-client areas such as the title bar and the frame.


If I then create an additional swap chain with a smaller backbuffer (ie to render to a small window), what would present do on the swap chain?

Not quite sure what the question is about. The action of Present is not dependent on the size of the backbuffer.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Advertisement
When you call Present on the device with no source/dest parameters, the front and back buffer pointers are switched meaning no surface copying is done or anything like that.

My question is, what happens under the hood when you do supply source and dest rects to the Present method? It can't switch the front and back buffer pointers because that would effectively present everything on the back buffer so it must do some form of copy from the back buffer you've drawn to to the front buffer?

When you call Present on the device with no source/dest parameters, the front and back buffer pointers are switched meaning no surface copying is done or anything like that.

Your statement may not be correct. From a further reviewi of the docs, I may have been mistaken when I previously posted that Present [always] flips the pointers. The help docs topic "Flipping Surfaces (Direct3D 9)" state:

"When you use IDirect3DDevice9::Present to request a surface flip operation, the pointers to surface memory for the front buffer and back buffers are swapped. Flipping is performed by switching pointers that the display device uses for referencing memory, not by copying surface memory."

The key words there may be "request a ... flip operation." That is, if the swapchain is created with D3DSWAPPEFFECT_COPY, then Present doesn't request a flip, but a copy, operation.


what happens under the hood when you do supply source and dest rects to the Present method? It can't switch the front and back buffer pointers because that would effectively present everything on the back buffer

Just for clarity, your question is a bit off-topic, perhaps. As L. Spiro mentions above, your problem description indicates syncing is likely the cause.

In any case, unfortunately, I'm not an expert on what happens "under the hood." I just read the Help docs, and experiment a bit.

Your latter (quoted) statement appears to be correct. According to the docs, using non-NULL rects in the Present call requires that the swapchain be created with D3DSWAPEFFECT_COPY. A swapchain created with D3DSWAPEFFECT_COPY must have just a single back buffer, but "will guarantee that [ a Present operation ] will not affect the content of any of the back buffers." I believe all that just means the rects determine what gets copied from the back buffer to the front buffer for display.

My own conclusions-

"Display" appears to be a multi-part process for a swapchain created with D3DSWAPEFFECT_COPY:

The source rectangle in the Present call determines what portion of the back buffer is copied to the front buffer memory.

The front buffer pointer, at any time, points to content which is to be displayed. That front buffer memory is memory mapped by the display adapter driver to some portion of video memory. That memory mapping is affected and can be modified by parameters in the Present call. I.e., given an HWND and destination rectangle in the Present call, the memory map will be from front buffer memory to the portion of video memory representing the destination rectangle in the client area for that HWND.

blink.png I haven't a clue whether that helps or hurts your investigation.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Firstly, I really appreciate your time and the fact that you've obviously done some research yourself. Thanks for that.

I've played around with almost everything on this and the only way I can get it to work is to set each swapchain's presentation parameters to ONE, rather than IMMEDIATE, which means my frame rate reduces by a factor of 60hz for each view I have, with two views I'm down to 33.3ms per frame.

Although this isn't the end of the world, I really would like to render with IMMEDIATE. The theory does work, by rendering using source and dest rects, even when clearing, but the Present won't work correctly unless I match it to the vertical blank.

Thinking about it, the arctifact I'm seeing does make sense. When I present, I'm presenting to the same destination rect both times which means there's bound to be some fighting. I'm wondering if I can Present to separate aread of the front buffer and then just set my two views to point to that area of the front buffer?
I think I'm at the end of my list of things to try on this. I feel like I've researched everything and tried everything and I still can't get it rendering without this big band of missed render tearing (nb, not normal tearing).

What I have managed to do is lock it to the vertical sync regardless of how many views I have rendering, I did this by setting the presentation parameters to ONE rather than IMMEDIATE on the main window. This seems to keep all views at one refresh which is perfectly fine.
Apologies for resurrecting this post but what I thought was a solution doesn't quite work.

I thought maybe if I explain my issue a bit more it might spark something in your minds that I can try? I feel like I've tried everything and read every webpage with the words swapchain and flicker in it.

My left view and right view (views being the left and right side of a splitter control) appear to be rendering correctly but there is a band going across both views. The correct models are being shown in their respective views, on the left is a terrain with a character model and on the right is a simple ground plane with a character model. Each of these models/terrain/plane exist only within the view, so there are two copies of the character model for instance and the terrain only exists in the left view. The 'manager' for each view holds this data.

So on the left, the terrain is rendering normally apart from within the flickering 'band' where the terrain is being rendered but using the shader and camera position of the right view.

The right view is also rendering normally apart from the band which is, again, rendering the correct objects but using the shader and cam position of the left view.

If I clamp the swap chain presentations to ONE the band disappears and everything renders normally and if I do a thread sleep of 1 (which iirc is not accurate to 1ms and likely to be more) everything renders fine. It's only when I render everything as fast as possible that the band appears.

I've checked, rechecked and trichecked my code for cameras and ahaders and everything looks fine. I have tried DISCARD and COPY and also using source and dest rects on the present, I simply can't get rid of this band. I've also tried overriding and returning 0 from the WM_ERASEBKGRND windows message.

Any further clues? I can't believe this can't be done.

To reiterate, my rendering loop is in a separate thread in c# and simply calls (via c++/cli):

While (true)
{
sceneEditor.RenderFrame();
animationEditor.RenderFrame();
}

So I don't render when the system is idle or anything like that. This is obviously just to get the concept working.

Thanks
I've just fixed this.

I'm not 100% sure of why, but it appeared that my local shader objects were being somehow shared as both views were using the same underlying renderer. In theory this should have worked with one renderer but clearly it doesn't so I'll need to do some refactoring and give each view its own renderer instead of sharing it - but very happy to see two perfectly rendered views side by side!

Thanks again

This topic is closed to new replies.

Advertisement