I'm using XNA and creating a bunch of forms that roll their own 'game loop' to handle drawing and such. Each new form is opened on its own thread, with a subsequent Application.Run(form) to make the thread handle the messages for that form.
When I started I noticed that despite me not implementing any kind of frame limiting timing, the window drew at 60 fps. This was the number I was aiming for anyway so I left it at that.
However now I discovered that when I open multiple windows, the original 60 fps gets divided evenly between them: 2 windows 30 each, 3 20 each, etc.
I also tried a loop with Application.DoEvents instead of Application.Run, but with the same results.
Anyone know where this 60fps limit coming from, how to overcome it?
Go to your graphic driver settings window. Turn off VSYNC.
I'm not an XNA expert, but it sounds that you're being limited by vsync, did you check that?
You say "forms" which leads me to believe you are running in windows on the desktop and not using a dedicated full screen display?
I believe that with Vista and Windows 7, the desktop compositor ("dwm") handles all of the actual drawing. It probably runs at 60 fps (or less when on battery). I am not sure why it divides the FPS between the two windows, but it could be some interaction of locking between graphics calls.
You can't benefit from multi threading drawing calls to the GPU. The GPU, although very good at parallel processing in it's own right, interacts with the CPU one thing at a time only and everything is blocked until it finishes the task at hand. Two draw calls on one thread will take just as long as two Draw calls on separate threads. Actually slower because of threading overhead.
Related
I've searched but couldn't find a result for this that didn't involve XNA.
Basically, I'm making a map editor using a C# binding of SFML attached to a panel's handle in my form. It runs at 550 FPS, which results in my main loop being called way too much, using too much resources (10% CPU for a small map editor).
I only really need 60 fps for this, and I know that will result in the cpu usage going down a lot.
Does anyone know how to do this? I've heard that it's impossible because WinForms s no function to access the graphic drivers VSync setting; but there must be a way, right?
Thanks.
I ended up using a WinForms timer to do my game loop processing. I get an effective 60 FPS by setting the interval of the ticks.
This reduces the CPU usage to 0.1% while still having the same functionality.
I've been searching and testing different kinds of rendering libraries for C# days for many weeks now. So far I haven't found a single library that works well on multi-windowed rendering setups. The requirement is to be able to run the program on 12+ monitor setups (financial charting) without latencies on a fast computer. Each window needs to update multiple times every second. While doing this CPU needs to do lots of intensive and time critical tasks so some of the burden has to be shifted to GPUs. That's where hardware rendering steps in, in another words DirectX or OpenGL.
I have tried GDI+ with windows forms and figured it's way too slow for my needs. I have tried OpenGL via OpenTK (on windows forms control) which seemed decently quick (I still have some tests to run on it) but painfully difficult to get working properly (hard to find/program good text rendering libraries). Recently I tried DirectX9, DirectX10 and Direct2D with Windows forms via SharpDX. I tried a separate device for each window and a single device/multiple swap chains approaches. All of these resulted in very poor performance on multiple windows. For example if I set target FPS to 20 and open 4 full screen windows on different monitors the whole operating system starts lagging very badly. Rendering is simply clearing the screen to black, no primitives rendered. CPU usage on this test was about 0% and GPU usage about 10%, I don't understand what is the bottleneck here? My development computer is very fast, i7 2700k, AMD HD7900, 16GB ram so the tests should definitely run on this one.
In comparison I did some DirectX9 tests on C++/Win32 API one device/multiple swap chains and I could open 100 windows spread all over the 4-monitor workspace (with 3D teapot rotating on them) and still had perfectly responsible operating system (fps was dropping of course on the rendering windows quite badly to around 5 which is what I would expect running 100 simultaneous renderings).
Does anyone know any good ways to do multi-windowed rendering on C# or am I forced to re-write my program in C++ to get that performance (major pain)? I guess I'm giving OpenGL another shot before I go the C++ route. I'll report any findings here.
Test methods for reference:
For C# DirectX one-device multiple swapchain test I used the method from this excellent answer:
Display Different images per monitor directX 10
Direct3D10 version:
I created the d3d10device and DXGIFactory like this:
D3DDev = new SharpDX.Direct3D10.Device(SharpDX.Direct3D10.DriverType.Hardware,
SharpDX.Direct3D10.DeviceCreationFlags.None);
DXGIFac = new SharpDX.DXGI.Factory();
Then initialized the rendering windows like this:
var scd = new SwapChainDescription();
scd.BufferCount = 1;
scd.ModeDescription = new ModeDescription(control.Width, control.Height,
new Rational(60, 1), Format.R8G8B8A8_UNorm);
scd.IsWindowed = true;
scd.OutputHandle = control.Handle;
scd.SampleDescription = new SampleDescription(1, 0);
scd.SwapEffect = SwapEffect.Discard;
scd.Usage = Usage.RenderTargetOutput;
SC = new SwapChain(Parent.DXGIFac, Parent.D3DDev, scd);
var backBuffer = Texture2D.FromSwapChain<Texture2D>(SC, 0);
_rt = new RenderTargetView(Parent.D3DDev, backBuffer);
Drawing command executed on each rendering iteration is simply:
Parent.D3DDev.ClearRenderTargetView(_rt, new Color4(0, 0, 0, 0));
SC.Present(0, SharpDX.DXGI.PresentFlags.None);
DirectX9 version is very similar:
Device initialization:
PresentParameters par = new PresentParameters();
par.PresentationInterval = PresentInterval.Immediate;
par.Windowed = true;
par.SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard;
par.PresentationInterval = PresentInterval.Immediate;
par.AutoDepthStencilFormat = SharpDX.Direct3D9.Format.D16;
par.EnableAutoDepthStencil = true;
par.BackBufferFormat = SharpDX.Direct3D9.Format.X8R8G8B8;
// firsthandle is the handle of first rendering window
D3DDev = new SharpDX.Direct3D9.Device(new Direct3D(), 0, DeviceType.Hardware, firsthandle,
CreateFlags.SoftwareVertexProcessing, par);
Rendering window initialization:
if (parent.D3DDev.SwapChainCount == 0)
{
SC = parent.D3DDev.GetSwapChain(0);
}
else
{
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard;
pp.BackBufferFormat = SharpDX.Direct3D9.Format.X8R8G8B8;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = SharpDX.Direct3D9.Format.D16;
pp.PresentationInterval = PresentInterval.Immediate;
SC = new SharpDX.Direct3D9.SwapChain(parent.D3DDev, pp);
}
Code for drawing loop:
SharpDX.Direct3D9.Surface bb = SC.GetBackBuffer(0);
Parent.D3DDev.SetRenderTarget(0, bb);
Parent.D3DDev.Clear(ClearFlags.Target, Color.Black, 1f, 0);
SC.Present(Present.None, new SharpDX.Rectangle(), new SharpDX.Rectangle(), HWND);
bb.Dispose();
C++ DirectX9/Win32 API test with multiple swapchains and one device code is here:
[C++] DirectX9 Multi-window test - Pastebin.com
It's a modified version from Kevin Harris's nice example code.
Edit:
Just to make it clear, my main problem is not low fps here when doing multi-window rendering, it's the general latency caused to all operating system functions (window animations, dragging&dropping scrolling etc).
Speaking of DirectX only here, but I remember we had the same kind of issue once (5 graphics card and 9 screens for a single PC).
Lot of times full screen switch seems to want to enable vertical sync on monitors, and since Present can't be threaded, the more screens with vertical sync the higher drop you will have (since you will wait between 0 and 16 milliseconds) for each present call.
Solution we had in our case was to create window as maximised and remove borders, it's not ideal but turned from 10 fps drawing a rectangle back to standard speed (60).
If you want code sample let me know I'll prepare one.
Also just for testing I had a go creating 30 windows on my engine using c#/slimdx/dx11, rendering a sphere with basic shading, still well over 40 fps.
We have a similar problem (need to render 3D views on 9+ monitors using 3+ graphics cards). We opted to use raw DirectX11 after finding that 3rd party rendering libraries are all very poor at multiple windows across multiple monitors, let alone with multiple adapters too. (It seems most engines are designed for a fullscreen game, and tend to suck at windowed views). Rather than using a 3rd party layer like SlimDX or SharpDX, we decided in the end to write the core renderer directly in C++ and just expose the simple API that our application needs via C++/CLI - this should maximise performance and minimise maintainability issues (relying on 3rd party vendor for bug fixes etc).
However, just like you, we found in testing that if we rendered 9 views from a single process (each rendered on its own thread), we got terrible performance (very low frame rates). However, if we ran 9 separate processes (one per view/monitor), the performance was as expected (excellent).
So having spent days trawling the net fruitlessly for a better solution, we opted for simply running our renderers in separate processes. Not entirely a bad solution for us as our renderers need to support distribution over multiple PCs anyway, so it just means we'll use this facility permanently instead of only when required.
(I don't know if this is helpful to you as an answer, but we'd also be very keen to know if there are any other solutions out there that work across multiple graphics cards, in case we're missing a better trick)
Never had the opportunity to run this kind of scenarios, but the only thing I'm pretty sure is that there is absolutely no concern using a managed wrapper, you would have exactly the same problem with C++ code.
Also, in your description, It is pretty unclear how many graphics card do you have installed on your system. Also you should follow more closely the "DirectX Graphics Infrastructure (DXGI): Best Practices" as they are describing lots of problem that you could have. Running with different graphics card in fullscreen with correctly swapchain setup for fullscreen should be ok (using "flip" instead of "blit", see msdn doc about this ), but if you are running your app in maximized window, I don't think that performance will be good, as the blit will interfere and produce some lags.
You can perfectly have a single multithreaded application using multiple device, one device per thread and they should be able to schedule things correctly... but again, as I have no experience in this kind of scenarios, there could be some kind of GPU scheduling problem in this specific case.
If the problem persist even after following carefully DXGI setup, I would suggest you to debug the whole thing with GPUView in order to check more carefully these problems. It is intended exactly for this kind of scenarios, but you will have to take some time to understand how to make a diagnostic with this kind of tool. There was also one talk about GPUView at last GDC 2012: Using GPUView to Understand your DirectX 11 Game (Jon Story) that is probably worth reading.
Make sure you've disabled security checks for calls to native code (via SuppressUnmanagedCodeSecurityAttribute).
The associated stack walking is a performance killer.
Its always a good idea to use doublebuffering because that can prevent flickering - atleast it does with windows forms.
I'm having a problem with timing in XNA 4.0, writing in C# and using Visual Studio 2010 express.
I'm not writing a game exactly, but I'm trying to use XNA for it's simplified content pipeline, drawing, and timing. What I'm trying to do is write a program that can time a user's response to onscreen stimuli at very fine resolutions - less than 5 ms, ideally.
To do this, I need to call the update routine (so I can poll the keyboard) no less than once every 5 ms. Even in variable step timing, I can't get the timing below about 16 ms per call. This doesn't appear to have anything to do with the amount of processing that I do in my update and draw routines. I can comment out everything in both routines and the program still spends roughly 16.66 ms on each iteration.
In fixed step timing, I can set the target to about 60 iterations per second (16.66 ms between updates), but if I try to go any faster than that, the IsRunningSlowly flag is tripped, and the game seems to try to compensate - several iterations will run faster than 60 iterations per second, and then 1 iteration will run slower.
So I guess my question is this: is the 60 iterations per second the upper limit for XNA? Is it possible to circumvent it? Should I just ditch XNA altogether?
I really appreciate your time and knowledge. Thanks in advance.
The problem you are having is due to VSync. Disable it in XNA by adding this line to your game's constructor (assuming you have the default GraphicsDeviceManager graphics):
graphics.SynchronizeWithVerticalRetrace = false;
This will allow your game to run "fast as possible". This should be "good enough" for your purposes.
See this blog post for a description of timing in XNA.
If you wanted to get more fancy: For XNA on Windows I would consider using the Windows event loop and a high resolution timer directly. Note that Game in XNA (on Windows and Xbox 360) is entirely optional.
You'd want to move as many slow operations (eg: update and draw) and blocking operations (eg: vsync) off the main thread. Note that input in XNA can only be handled on the main thread. I think you can create the graphics device on a separate thread - although I have never tried it.
You should note that, if you are measuring reaction times, there is lag in between sending a "present" command to the GPU, and that content actually appearing on screen.
I'm not expert to XNA development, but, I know I have already similar "problem" in windows phone. (slowly problem).
When you have a lot of treatment, use multithreading programming,,
msdn : "Applications that use multithreading are more responsive to user input because the user interface stays active as processor-intensive tasks execute on separate threads. Multithreading is also useful when you create scalable applications, because you can add threads as the workload increases. "
Hope I help you...
I'm working on a quite big application that is in charge of doing real-time motion tracking and camera movement controlling. Its tasks are:
Motion tracking (done by a native module, which decodes a video stream from a network camera and supplies both image buffers as big as 1280x720 pixels and the tracking results to the managed application via callbacks)
Receiving positioning feedback data from and sending movement data to a pan/tilt hardware about 20 times a second as well as zoom commands from/to the camera
Displaying the image data including live visualizations
Encoding and writing of the image and session data
Automatic postprocessing of the video is done by another process
The application uses .NET 4.0 and has a WPF user interface.
Managed threads freezing
From the beginning we had to face managed threads that freeze for between 500 to 1500ms, which is really much for a real-time application like this.
To find out when these hangs occur I created a thread whose only task is to do a sleep for 100ms all the time. I then calculated how long the sleep really took and got exactly the times when the camera movement stopped. It works very reliably, the threads all hang at the same time!
Unmanaged threads don't freeze
While all the managed threads freeze the unmanaged threads work without any problem. We check that by logs that are written independent from the managed part of the application.
Analysis
I tried to figure out with phenomenons could maybe cause this behaviour:
The whole machine slows down when we encounter these problems: Windows is responding very slowly (e.g. directory listings hang for half a minute in both Windows Explorer and my application, or launching applications takes incredibly long)
We read and write thousands of files at the same time (the tracking and postprocessing application), maybe this overcharges windows
The response of the GUI becomes very slow
The app uses about 1.3GB of virtual memory (according to Process.VirtualMemory64) / 500MB of working set memory (Process.WorkingSet64) - could it be that some of that is swapped onto the harddisk? (How can that be checked or solved?)
Of course if we kill the process Windows is responding fast again, but it takes Windows a while to be responding normally again
Hints on how to investigate into this would be highly appreciated. Thank you very much!
Maybe GC is working?
See the great article: http://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the-net-garbage-collector
I would suggest taking a process dump as you are encountering the performance problem. You can do this several ways (taskmgr.exe or procdump.exe from SysInternals). Take a full memory dump.
Once you have the .dmp file, you can analyze it with windbg (or Visual Studio 2010). For managed processes you need to load the sos.dll extensions.
There are a lot of good windbg resources out there, but here are a few that have helped me:
1) Tess Fernandez video (ASP.NET process, but the techniques are the same)
2) WinDbg cheatsheet
The memory analysis will be able to give you the stack (!clrstack) while you are encountering the problem and tell you the exact culprit.
I have a problem drawing something quickly in .NET. I don't think that any thing in particular should take much time, but on every machine I've tried it on, I get serious issues. This is implemented in vs2008 .NET, using C# (with some stuff in C++, but nothing relevant to the drawing).
I have three screens, and the user should be able to toggle between them with no lag. On the first screen, there are four buttons, eight user controls consisting of two buttons and 6 labels each, a text field, and a dropdown box. I don't think of it as being that much.
On the second screen, I have four labels, six buttons, and two controls that have six buttons, one opengl drawing context, and about ten labels each.
On the third screen, I have one opengl context and 10 buttons.
Flipping from any screen to any screen takes literally about a second. For instance, if I flip from the second screen to the first, the entire application blanks out, showing the background screen, and then the first screen is drawn. Many times, a screen is drawn piecemeal, as if the machine were deliberately handcrafting delicate and delicious letters in a factory in Sweden and then shipping each one individually to my screen. I exaggerate, and I want to make that clear, because I don't think Swedes are as slow as this redraw.
The first and second screen are drawn in memory, and stored there, with just a '.Hide()' and '.Show()' to make them appear and disappear. Double buffering doesn't seem to matter. The third screen is drawn anew each time, and appears to take the same amount of time to draw as the first and second.
Any thoughts? What could be going on? How can I track it down?
Thanks!
Edit: I should add that any C++ processing and the like happens in its own thread. There is the occasional MethodInvoke to draw the results of the operation to the screen, but this problem happens without calling any functions, just by pressing buttons to go from one screen to the next.
In addition to the profiler that was mentioned, you might also turn off your OpenGL contexts. If you notice a speed-up, then you'll know it's your graphics stuff, and you can focus your optimisations accordingly.
Points awarded for Swedish humour.
How can I track it down?
dotTrace - http://www.jetbrains.com/profiler/
Are you doing any other processing during the "screen flip" event? other than just letting the form be redrawn? If you are processing something between flips (maybe your c++ addition?), and you are not multi-threading, you get that white out effect. The form is probably waiting for CPU time to redraw itself.
I have never used OpenGL in such a way myself, but you might want to look at the way in that the OpenGL contexts are flipped. When switching from one page to another you might be getting a device reset (in DirectX terms), which could be causing the delay.
If at all possible have a device draw to a back System.Drawing.Bitmap, and use that bitmap on the screens. Make your OpenGL code aware of the current page the user is on, and you might get the speed up you seek.
To test this before making huge changes, try removing the OpenGL displays on your form.
This is all a whim.