Reputation: 26766
I'm trying to use SlimDX to create a DirectX9 application.
If I use .PresentationInterval = PresentInterval.Default
, it renders at ~The refresh rate of my monitor and looks fine.
If I use .PresentationInterval = PresentInterval.Immediate
, I get ~6,000 FPS but there is severe flickering - presumably because the device is being updated when the immediate presentation happens and thus it may or may not be correctly drawn.
Can someone tell me how I can use a back-buffer so that immediate doesn't flicker and the buffers are swapped when I've finished drawing?
Obviously, I don't actually want 6K FPS but I do want control the frame rate cap and also have a better understanding of buffering.
PresentParameters = New PresentParameters()
With PresentParameters
.BackBufferFormat = Format.X8R8G8B8
.BackBufferCount = 2
.Multisample = MultisampleType.None
.SwapEffect = SwapEffect.Discard
.EnableAutoDepthStencil = True
.AutoDepthStencilFormat = Format.D24S8
.PresentFlags = PresentFlags.DiscardDepthStencil
.PresentationInterval = PresentInterval.Default '' or PresentInterval.Immediate
Select Case Settings.Display.Mode
Case WindowMode.FullScreen
.BackBufferWidth = Settings.Display.Width
.BackBufferHeight = Settings.Display.Height
.Windowed = False
Case WindowMode.Windowed Or WindowMode.WindowedNoBorder
.BackBufferWidth = Settings.Display.Width
.BackBufferHeight = Settings.Display.Height
.Windowed = True
End Select
.DeviceWindowHandle = Handle
End With
Direct3D = New Direct3D()
Device = New Device(Direct3D,
Settings.Display.Adapter,
DeviceType.Hardware,
Handle,
CreateFlags.HardwareVertexProcessing,
PresentParameters)
Context9.Device.BeginScene()
Context9.Device.Clear(Direct3D9.ClearFlags.Target Or Direct3D9.ClearFlags.ZBuffer,
Color.Black,
1.0F,
0)
Game.Render(Context9)
Using Sprite As New Sprite(Context9.Device)
Sprite.Begin(SpriteFlags.AlphaBlend)
Dim Mtx = Matrix.Translation(125, 200, 0)
Dim Scaling = Matrix.Scaling(0.5, 0.5, 1)
Matrix.Multiply(Mtx, Scaling, Mtx)
Sprite.Transform = Mtx
Dim Fade As Single = CSng(Math.Min(1, Math.Sin(FrameI / 30) * 0.5 + 0.5))
Sprite.Draw(TestTex,
Nothing,
Nothing,
Nothing,
New Color4(Fade, Fade, Fade))
Sprite.End()
End Using
Context9.Device.EndScene()
Context9.Device.Present()
Private Sub Run()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Window = New RenderForm("Test")
InitializeDevice()
''Add lots of key handlers, etc here
LoadResources()
Clock.Start()
MessagePump.Run(Window, AddressOf MessageLoop)
Cleanup()
Window.Dispose()
End Sub
Sub MessageLoop()
Update()
If Not IsResizing Then
Render()
End If
End Sub
(I've omitted the code to show FPS / some other bits as it's just noise but can provide it if required)
Upvotes: 0
Views: 717
Reputation: 26766
So.... It turns out this was a case of stupidity.
Dim Fade As Single = CSng(Math.Min(1, Math.Sin(FrameI / 30) * 0.5 + 0.5))
As you'll notice, the fading was based on the frame number not the elapsed time. So when the frame rate shot up, so did the fade speed...
Upvotes: 0
Reputation: 17185
DirectX is always using double buffering, you cannot dissable this (you could go for tripple buffering, but so far I have not seen an use case for this).
What happens is that with Default, the backbuffer is copied to the screen between two frames of the monitor. With Immediate, this happens directly. This will always flicker a bit, especially if the new image is very different from the old, because the top half of the screen will show one image and the bottom the next. For most cases, it is not useful to render faster than with the refresh rate of the monitor.
Upvotes: 1
Reputation: 13003
I can be wrong, but I believe this have nothing with DirectX. You must enable double buffering on window creation.
If you using System.Windows.Forms
, then call Control.SetStyle()
as described here:
public void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
Or better, just use SlimDX.Windows.RenderForm
. It is derived from Form
and has double buffering enabled by default.
Another cause of flickering can be wrong main loop structure. You didn't show us your main loop and how you invoke your rendering function. You can find typical rendering loop in tutorials.
Hope it helps!
Upvotes: 1