Link to home
Start Free TrialLog in
Avatar of SunnyDark
SunnyDarkFlag for Israel

asked on

Direct3D + Windows Forms GUI thread conflict and freezes

I have a direct3d application running in a windows forms custom control that is hosted in a windows forms form.
The form has a toolbar on top, then the 3d control.
I am using SlimDX framefork for the direct3d stuff. The rendering thread has a message pump that runs the rendering stuff, and the windows form obviously has it own message pump to process the input.
The frame rate is manually controlled by the rendering message pump via sleep time which never goes below 10ms , that is at the end of each render loop there is a Sleep(10) at least.
Despite this whenever there is a drop in frame rate below the 50 FPS level when I hover (or try to click) over the buttons in the toolbar (that is direct child of the form) there is a freeze in input processing that is the rendering continues as usual but the mouse input is not processed and also the buttons of the toolbar that are supposed to highlight when hovered are not highlighted. The freeze continues for a few seconds (2-3) then returns to normal until I try to interact with the form again.
Screenshot attached:
 User generated image
Avatar of Member_2_5069294
Member_2_5069294

This is an interesting problem, I'd like a bit more information.

The app is running windowed, its using the copy swap effect?
Which thread created the D3D device?
What messages do you send to the rendering thread's message queue?
Do you send or post messages?
Is the device attached to a child window or the main application window?
Is the device created with D3DCREATE_MULTITHREADED?

I'm curious why you have constant display updates.  Usually the view is updated when something changes, the camera or something in the world.  Is this is a game or some situation where things change without interaction?
Avatar of SunnyDark

ASKER

The app is using directx 10 so it is multithreaded by defailt. The device is created in the main thread.
Swap effect is DISCARD,
The application is .NET c# so there is no direct message sending... The device is attached to a window that is a custom windows control which in turn is inserted into a windows form (you can see that from the screenshot)
I am constantly updating since there are moving objects in the scene, and also the camera may be animated.

The application is .NET c# so there is no direct message sending
Ah, .NET is a layer of potential problems.

While the interface might not involve message functions, messages will be sent or posted.  Whether they are sent or posted affects where deadlocking might occur.  Besides, why do you mention message pumps if message aren't used?  I guess that is the same as message loops, or am I misunderstanding?

Do you know if .NET is posting or sending?  What are the messages sent to the rendering thread for?

Unfortunately, I haven't used DX10.  DX9 has particular limitations with threads and messages.  For example, the thread that creates a device should also handle window messages.  I don't know if this applies in this case.
This thread basically explains what seems to be the same problem:
http://forums.create.msdn.com/forums/p/35720/290266.aspx
Hmm, this is tricky.  I have multi-threaded D3D apps but using D3D9 in XP.  So I can only make guesses based on what I know of D3D.

How does the program do updates?  Given that you're using SWAPEFFECT_DISCARD, I guess it's calling Present on the child window.

I use SWAPEFFECT_COPY and update the window with functions that go through the message loop, like InvalidateRect() and UpdateWindow().  The paint handler just copies data from the back buffer to the display.  This way Windows can prioritise other messages (such as mouse input) with the paint messages.  Could you try that?
BTW, nice looking app.  Apart from the blobby ground texture, using satellite images?
I don't believe that this is the issue since all the mouse messages are handled perfectly well until I touch something on the form itself. So there is no issue with painting the window or any other d3d activity that interrupts with the input.
I do believe that this has to do something with the GDI / D3D mess-up, however I don't know how to even start debugging this.
If both the D3D window and the toolbar are children of the form, then messages will go through the same message loop before reaching either.  If messages processing is held up while waiting for the D3D thread to render, that gives little time for sending other messages.

I notice you mention slow down starts at 50 fps, is that about the frame rate of your monitor?  Would be interesting to see if that has something to do with it.  What is the presentation interval of the device set as?
As I mentioned before the problem occurs only when I am manually controling the render loop : i.e.:
while(true)
{
 ClearRenderTarget();
 Render Scene();
 Present(0);
 Sleep(waittime);
}

Open in new window


However if I use vertical sync instead, the problem is gone:

while(true)
{
 ClearRenderTarget();
 Render Scene();
 Present(1);
}

Open in new window


This however does not present a solution as relying on the vertical sync presents other problem and among them the inability to control the speed of the display beyond the refresh rate.
You want to update the display faster than the refresh rate?  That means you're rendering frames of animation that you don't see.
ASKER CERTIFIED SOLUTION
Avatar of SunnyDark
SunnyDark
Flag of Israel image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
No practical solution was found , so resolving to using VSYNC as a workaround...