Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Hi everyone.

 

I am trying to write a .NET application that displays some simple 2D graphics in a window. The graphics that are displayed consist of many individual lines of varying shades of green, depending on the data received by the application.

 

All of this is working, but the program consumes nearly all of my CPU. I really need to improve the performance of my code and I have identified that the bottleneck occurs when I call DrawLine on my offscreen surface for each of the many lines that are displayed.

 

As extra information, I am refreshing the display at 50Hz to get a nice smooth display. I have a NVidia Riva TNT2 Model 64 video card but it does not seem to improve the performance over using the display chipset on the motherboard.

 

Any ideas on how I can improve the performance of the DrawLine command would be great.

 

Bye.

Posted
Without seeing any actual code, one can only assume that the problem is with your outdated video card.
Gamer extraordinaire. Programmer wannabe.
Posted

Here is the code that I am using. A lot of the code has been removed but I think that I have kept all of the relevant parts. Almost all of the CPU time is spent doing the DrawLines at the end of the code.

 

public class DXTest
{
int[,] ValuesToDraw;
private Device device;
private Surface primary;
private Surface offscreen;

public void Setup()
{
 device = new Microsoft.DirectX.DirectDraw.Device();
 device.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
 CreatePrimarySurface(); 
 CreateOffscreenSurface();
}

private void CreatePrimarySurface()
{
 SurfaceDescription desc = new SurfaceDescription();
 desc.SurfaceCaps.PrimarySurface = true; 
 primary = new Surface(desc, device);
 Clipper pClipper = new Clipper(device); 
 pClipper.Window = OIApp.OIGUI.GetSelectedTabPage(); 
 primary.Clipper = pClipper;
}

private void CreateOffscreenSurface()
{
 SurfaceDescription desc = new SurfaceDescription(); 
 desc.SurfaceCaps.OffScreenPlain = true; 
 desc.Width = this.ClientRectangle.Width; 
 desc.Height = this.ClientRectangle.Height; 
 offscreen = new Surface(desc, device); 

 Clipper oClipper = new Clipper(device); 
 Rectangle oClipRect = new Rectangle(0,
  0,
  this.ClientRectangle.Width,
  this.ClientRectangle.Height); 
 oClipper.ClipList = new Rectangle[] { oClipRect }; 
 offscreen.Clipper = oClipper;
}

public void Run(Object state)
{
 for(int i=0; i<360; i++)
 {
  for(int j=0; j<10; j++)
  {
   offscreen.ForeColor = Color.FromArgb(0,250,0);
   offscreen.DrawLine(xs+xt, -ys+yt, xe+xt, -ye+yt);
  }
 }
 
 primary.Draw(this.ClientRectangle, offscreen, DrawFlags.Wait);
}
}

Posted

Possible Reason for Slow DrawLine

 

I've been looking at this problem some more and I have come to the following conclusion. Perhaps someone can say whether this is right or wrong?

 

The DirectDraw DrawLine() function calls the getDC() and releaseDC() as part of it's operation. As a consequence, multiple calls to DrawLine() involve multiple calls to getDC() and releaseDC(), which make it VERY slow.

 

I have worked around this using the GDI calls moveTo() and LineTo() for a massive performance boost, up to 20x faster in my worst case.

 

Any other ideas out there??

Posted
Changing the DrawFlags from Wait to DoNoWait only affects the drawing of the offscreen surface to the primary surface. This may provide a small performance improvement (it's a bit hard to see any change using the Task Manager) but the majority of the time is spent on the DrawLine function, which is performed on the offscreen surface.
Posted
Well.. the only other improvement that I see would be putting the call to ForeColor outside of the two for loops (calling it once before the looping). Whether or not that'd improve your speed, I don't know, but I don't see anything else.
Gamer extraordinaire. Programmer wannabe.
Posted

I actually use the Forecolor to change the color of the lines that I draw in my application, but this is not fully shown in the code that I submitted. However, from my testing it is definitely the call to DrawLine that takes up most of the execution time.

 

What are your thoughts on my guess that the DrawLine function calls the getDC and releaseDC at the next level down in the code??

Posted
unless the code specifically sleep()s or does something of an idle loop, this is what happens (100% cpu). look at any game, it will consume 100% cpu even if you turn down all the details. in order to make it take less cpu, you have to implement FIXED FRAMERATE. that is, you go idle if you are too fast.
Posted

Although it is nto obvious from the code that is posted, the program is frame rate limited, to 50 frames per second in fact.

 

Because the DrawLine function takes so long, the software is unable to execute all of the required DrawLine functions within 20ms and the program falls behind, i.e. doesn't display the line data as quickly as it should.

 

As I have said in a previous post, the DrawLine command is using the CPU.

Posted

another tip is forgetting about directdraw and usem direct3d for hardware accelerated line drawing

 

bet you could draw thousands on your old gfx card and still maintain framerate :)

Posted

Unfortunately, the lines can differ for each frame.

 

I also think that Direct3D would provide the required speed, but I have been trying to avoid it as it will take some time for me to learn how to use it properly.

 

At this stage, I am getting pretty good performance from using the GDI calls MoveTo and LineTo.

Posted

Aha! I think I have the solution now that I've had some experience programming in DD.

 

I noticed that you set a clipper to your offscreen (backbuffer) surface. NO! Bad. Evil. A clipper should only be used on the primary surface. You should make your own clipping routines for the backbuffer.

 

Comment out this block of code and give it a go, I bet you'll gain quite a bit of performance;

 

 Clipper oClipper = new Clipper(device); 
 Rectangle oClipRect = new Rectangle(0,
  0,
  this.ClientRectangle.Width,
  this.ClientRectangle.Height); 
 oClipper.ClipList = new Rectangle[] { oClipRect }; 
 offscreen.Clipper = oClipper;

Gamer extraordinaire. Programmer wannabe.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...