D3DX Line.DrawTransform Performance Issue

Started by
9 comments, last by gadgetsuh 16 years, 6 months ago
Hi, I am using C#,and I am replacing DrawPrimitives with Line.DrawTransformation so that I can change the line thickness. In doing so, I found the Line drawing function hits significant performance degradation. I am drawing a 3D scene, and the CPU usage go up to the top as I rotate the model (repainting) with 10-20 rectangles drawn. It looks like the system memory usage also goes up. Is this a known issue and is there any solution? I am using Windows XP with a ATI Radeon X1600 128M graphics card. Direct9 June 2007 SDK. Thank you, Gadget
Advertisement
Without seeing your code it's difficult to say what could be wrong.

These are probably the most important things we need to know to find out where your performance problem is:

1. How many times per frame are you calling ID3DXLine::Begin()?
2. How many lines are in your line strips passed to ID3DXLine::DrawTransform()?
3. How many calls to ID3DXLine::DrawTransform() per frame?
4. What frame rate are you getting in each of the two cases?

Also note that almost any D3D program that's rendering continuously will use 100% of the CPU time. If you want to change that you need a Sleep() call in your render loop somewhere.
Thank you for your reply. I guess I am directly comparing the performance with the DrawPrimitives under the same condition, the items you listed may not be relevant (because they are the same for both cases). Here is part of my code below. As I am converting the code from using DrawPrimitives to Line, the code is not optimized for the line draw function. But I guess it's enough for direct comparisons.

line = new Line(device);
line.Width = 3.0f;

for ( int j=0; j<renderArr.Count; jj++ )
{
MyBufferWrapperObject buffer = (MyBufferWrapperObject )renderArr[j];
int nVertex = buffer.nVertices;

Vector3[] vecs = (Vector3[])buffer.vertBuffer.Lock(0, typeof(vector3), LockFlags.None, nVerts);

// This code is for line DrawTransform
line.Begin();
line.DrawTransform( vecs, transX, color );
line.End();
// For comparison, the above three lines are commented out and replace with
// device.DrawPrimitives(PrimitiveType.LineStrip, 0, buffer.nIndices - 1 );
}

As commented, switching between the DrawTransform and DrawPrimitives shows a significant performance difference. The more lines, obviously, the greater the difference is. The CPU usage for DrawPrimitives is kept minimum, but the DrawTransform goes up to almost 100% of CPU usage for many lines.

Thanks,
Gadget

[Edited by - gadgetsuh on September 28, 2007 6:15:01 PM]
Try this - it should be significantly quicker:

line = new Line(device);line.Width = 3.0f;line.Begin();for ( int j=0; j<renderArr.Count; jj++ ){MyBufferWrapperObject buffer = (MyBufferWrapperObject )renderArr[j];int nVertex = buffer.nVertices;Vector3[] vecs = (Vector3[])buffer.vertBuffer.Lock(0, typeof(vector3), LockFlags.ReadOnly, nVerts);// This code is for line DrawTransformline.DrawTransform( vecs, transX, color );// For comparison, the above three lines are commented out and replace with// device.DrawPrimitives(PrimitiveType.LineStrip, 0, buffer.nIndices - 1 );buffer.vertBuffer.Unlock();}line.End();


What you should also do is store the data in a Vector3[] instead of a vertex buffer when using ID3DXLine - locking a vertex buffer can be rather slow.

Also if you only need read access to a vertex buffer, lock it with LockFlags.ReadOnly for a significant speed up - it won't copy the buffer back across to the graphics card when you unlock it.

You also seem to be missing an unlock in the code you posted. I added one for you.
Thank you, Adam_42, for your reply.

I am certain that your suggestion is valuable and I'll include those, but I still don't have the answer I want.

The code snippet was originally using the DrawPrimitives to draw a bunch of lines. (Hence, using vertex buffer.) I just replaced the DrawPrimitives line with the DrawTransform function, and I found it significantly increases the CPU usage, hence downgrading the performance. Leaving all other code the same, just switching between DrawPrimitives and DrawTransform shows a significant performance difference.

I draw it once, and as I rotate the view with the mouse, I redraw the lines. The redrawing time per frame is not that high. But while rotating the view (redrawing the lines), the CPU usage bar go up well above 50%. (Is there a display-list kind of thing as in OpenGL in DirectX, so I don't need to redraw everything? I am new to DirectX.)

Although I understand DrawTransform does much more (texture, etc), but the performance difference is unacceptably severe. I am wondering if I am doing something wrong, otherwise this must be a known issue by now.

Thanks,
Yong
this code will use 100% of the CPU:

int poop = 0;while (1){    ++poop;}


what are the framerates you are getting with the two methods. CPU usage just means you're not yielding to other applications (sleep statements, blocking calls, etc). it is not a measure of performance.

In fact, counter-intuitively, less CPU usage probably means less performance because it means that your CPU is stalling for _more_ time waiting for the GPU to render.

-me
True, if the CPU keep crunching numbers as in your code. But if CPU do a finite set of instructions and finish it early enough to have time before the next round of computation, the CPU usage will be low.

If DrawPrimitives is used, the CPU usage is low because it finishes much earlier (drawing lines). It looks like the DrawTransform takes much more time, and it keep computing, showing higher CPU usage (for the same set of lines).

Like I said, it draws the lines continuously as I rotate the view. For the DrawPrimitives, the movement is very smooth and fast. When DrawTransform is used, noticeable blinking, and less responsive to the mouse movement with high CPU usage.

Depending on the mouse speed and the number of line segments, the fps goes from 200 - 300 fps.

Thanks,
gadget

[Edited by - gadgetsuh on October 1, 2007 10:56:12 PM]
Quote:Original post by gadgetsuh
Like I said, it draws the lines continuously as I rotate the view. For the DrawPrimitives, the movement is very smooth and fast. When DrawTransform is used, noticeable blinking, and less responsive to the mouse movement with high CPU usage.


That's not a CPU usage problem. it's a problem with your code. Stop using CPU usage as a metric for performance, it's correlative, not causative.

What you need to do is profile your application and try to find out where the bottlenecks are during this specific unresponsive scenario.

The problem is likely as Adam pointed out, you are not using the DirectX calls properly.

It could also be that for whatever reason DrawTransform is defaulting to software emulation instead of being executed on the graphics card. I don't really know anything about DirectX =)

The only important piece of data is that when you use DrawTransform, your framerate is crappy and you have graphical glitches. Again, never use CPU usage as an indicator of performance.

-me
Thank you for trying to help me.

I don't care how slow my code is. That is not my concern right now. I know my code is not optimized; it is in a sense intended because I want to compare the DrawPrimitives and DrawTransform side by side by changing just one line.

If you think my call the DrawTransform is wrong, please point it out. If not, it's not very helpful.

If CPU is high, it means it uses software emulation not GPU as you mentioned. Then why?
Quote:Like I said, it draws the lines continuously as I rotate the view. For the DrawPrimitives, the movement is very smooth and fast. When DrawTransform is used, noticeable blinking, and less responsive to the mouse movement with high CPU usage.

Depending on the mouse speed and the number of line segments, the fps goes from 200 - 300 fps.


200 FPS should be more than enough for a smooth display - monitor refresh rates are about 60-100. I'm guessing you have some kind of problem in your repaint code, and maybe the mouse update code as well.

For example, have you stopped Windows from erasing the background of your window by handling WM_ERASEBKGND appropriately?

This topic is closed to new replies.

Advertisement