SwapEffect.Swap vs Discard...? |
Krisc | DirectX.Direct3D [9]
What is the difference between SwapEffect.Swap and SwapEffect.Discard? I see about a 500fps advantage to Discard...so I am wondering why I should use Swap...?
[I got Swap from Jack's DirectX9 sample.] |
Eric Coleman | I looked at the SDK, and it's a bit confusing. |
Krisc | Ya, I suppose it doesn't matter for a small project such as mine. |
Lachlan87 | It is a little confusing, but after reading a book I got on DX 9, it sounds like in most cases you want to use Swapeffect.Discard. Not only is it faster, some special effects require it. |
Eric Coleman | From reading the SDK some more, it almost seems like you can change the SwapEffect after you've created the rendering surface. The SDK says the "default" swap effect when the rendering surface is created is always the fastest. And from a conceptual point of view, the idea of allocating memory during each frame and then discarding it after seems like it would be slower than just swapping a memory pointer to two constant surfaces. It seems like there would be more work involved to make sure the allocated video memory is contiguous. I guess that's a driver issue, but it still seems like it would slow things down. I'd like to know why swapping a pointer to the active primary buffer is more of a challange than erasing memory and then reallocating memory each and every frame? Does that make any sense to anyone? |
Eric Coleman | What special effect would require discarding the buffer? If anything, I would imagine that Copy would be more usefull for special effects because the buffer contents are retained. if you discard the data, then that's just like clearing the buffer every frame. |
Spodi | This is what I remember from some site about DX8, it may be the same:
Discard is like Flip/Copy, but it is no garentee that 100% of the pixels will be the same as they were on the backbuffer. So faster, but sloppier, and a last-resort kind of thing.
Copy is moving pixels from the backbuffer to the screen pixel by pixel, so it is a sure-way to get exactly what is on the backbuffer.
Copy_Vsync is just like copy, but syncs the copying with the vertical refreshing of the monitor.
Flip is where you take the backbuffer and just copy the whole thing at once onto the screen, instead of pixel-by-pixel, so it requires the two to be the same size.
Those should be correct. So, Flip should be the way to go for a game. |
Peter | Well, flip would probably just pass the pointer to the backbuffer, which would really cause any loss of data, since you're passing the memory address.
I'm not really sure what the difference is though, sorry. |
Lachlan87 | The idea is a little complex, and I don't fully understand it myself; therefore I will just give you guys a nice long quote from Managed DirectX 9 Graphics and Game Programming by Tom Miller so you can see why I suggested using SwapEffect.Discard. Since he was the development lead as well as the API designer, I would hope he knows what he's talking about.
quote:
A swap chain is essentially a series of buffers used to control rendering. There is a back buffer, which is where any drawing on this swap chain occurs. When a swap chain that has been created with SwapEffect.Flip is presented, the back buffer data is "flipped" to the front buffer, which is where your graphics card will actually read the data. At the same time, a third buffer becomes the new back buffer, while the previous front buffer moves to the unused third buffer.
A true "flip" operation is implemented by changing the location of where the video card will read its data and swapping the old one with the current back buffer location. For DirectX 9, this term is used generically to indicate when a back buffer is being updated as the display. In windowed mode, these flip operations are actually a copy of the data, considering our device isn't controlling the entire display, but instead just a small portion of it. The end result is the same in either case, though. In full screen mode, using SwapEffect.Flip, the actual flip occurs; some drivers will also implement SwapEffect.Discard or SwapEffect.Copy with a flip operation in full screen mode.
If you create a swap chain using SwapEffect.Copy or SwapEffect.Flip, it is guaranteed that any present call will not affect the back buffer of the swap chain. The runtime will enforce this by creating extra hidden buffers if necessary. It is recommended that you use SwapEffect.Discard {my bold} to avoid this potential penalty. This mode allows the driver to determine the most efficient way to present the back buffer. It is worth noting that when using SwapEffect.Discard you will want to ensure that you clear the entire back buffer before starting new drawing operations. The runtime will fill the back buffer with random data in the debug runtime so developers can see if they forget to call clear.
The back buffer of a swap chain can also be used as a render target. Implicitly, when your device is created, there is a swap chain created, and the render target of the device is set to that swap chain's back buffer. A render target is simply a surface that will hold the output of the drawing operations that you perform. If you create multiple swap chains to handle different rendering operations, you will want to ensure that you update the render target of your device beforehand.
And then in a side box he says:
quote:
It is worth mentioning that if you plan on using anti-aliasing (or multisampling as it is called in Direct3D), you must use SwapEffect.Discard. Attempting to use any other option will fail.
Unless you understand this some other way than I do, it is most likely you want to use SwapEffect.Discard.
|
Eric Coleman | Perhaps I'm just being dumb, but from all previous versions of directx that supported "flip" operations, I assumed that it was nothing more complicated than the following logic.
[code]
Flip {
int tmp;
tmp = ptrPrimary;
ptrPrimary = ptrBackBuffer;
ptrBackBuffer = tmp;
}
[/code]
All it is doing is simply swapping the pointers. of course, you can't do that in windowed mode, so I'm ignoring windowed mode for now.
What confuses me is this "If you create a swap chain using ... SwapEffect.Flip, it is guaranteed that any present call will not affect the back buffer of the swap chain." What exactly does that mean? Why would there ever be a situation where the memory would be affected? Given the simple logic above, what situation would arrise such the directx has to create extra memory buffers, bitblt the backbuffer to the new buffer, and then I'm not sure what it would do from there. Given the implications of the quoted statement, it seems like this is the true logic behind flipping.
[code]
Flip {
int tmp;
if ptrOldBackBuffer != NULL {
free(ptrOldBackBuffer)
}
if rand(); < 0.5(float) {
tmp = ptrPrimary;
ptrPrimary = ptrBackBuffer;
ptrBackBuffer = tmp;
} else {
tmp = ptrPrimary;
ptrPrimary = ptrBackBuffer;
ptrBackBuffer = malloc(buffersize)
ptrOldBackBuffer = tmp;
if ptrBackBuffer == NULL {
RaiseError(OutOfMemory);
}
}
}
[/code]
Of course, this logic doesn't make any sense at all, but from what the SDK says and what Lachlan quoted, that's the best I can deduce. |
Lachlan87 | I added a paragraph to my quote. . . my brain isn't working too well right now(I did lots of manual labor today), but it seems like you can have swap chains messing with each other. Maybe that is the situation where the memory would be affected? |
EACam | Bah, I'll just make it a user option and let them see what they like better :) |