question about rendering

question about rendering

Post by Jan Hammerschmid » Sun, 06 Jul 2003 02:26:25



..and hello again .. ;)

while trying to figure out, what eats up so much time in my little app, i
structured it in several blocks and calculated how much time each one costs.
it was no surprise to see that the rendering block took almost all the time.

ok, after splitting up this render-block into several smaller blocks, i
found out that BeginScene() and the Present() call are both eating most of
the time .. but why ?

according to the documentation Present simply "presents the contents
of the next buffer in the sequence of back buffers owned by the device" and
BeginScene "begins a scene", but what actually happens there ? (both
descriptions doesn't sound like much work to me ..)

..and a second question about the "fillmode": when switching to wireframe
mode, i could see that the time used for rendering was *very* unsteady,
varying from very low to very high, while generally rising, when
interpolated .. again: why ? i mean, d3d doesn't have to render more (in
fact you see less on screen ...)

 
 
 

question about rendering

Post by Jan Hammerschmid » Sun, 06 Jul 2003 21:15:02


ok, i was wrong when saying BeginScene takes much time, but Present() still
does .. :>
presuming that Present() really only puts some backbuffer to screen, i
thought, perhaps the function only waits until the rendering on this buffer
is completed, but i got the swapchain of my device and called present with
the "DoNotWait"-flag which should, according to the documentation, return a
"WasStillDrawing"-error, if "the hardware is busy processing", but this
never happens ...

another thing i don't understand: there are two situations, where 1) my
mouse gets updated not as frequently as usual and 2) winamp begins
"stuttering" although processor load is only 30-40%. this happens, if my
whole rendering window is covered by another window or if i simply turn on
wireframe mode (on several occasions you also get this stuttering without
wireframe mode).

*sigh* why is it soo difficult to get d3d properly running ? :/

 
 
 

question about rendering

Post by Donavon Keithle » Mon, 07 Jul 2003 03:54:44


First, Present does not wait until the frame is finished rendering and has
been presented.  If it did then the GPU would be idle on return, and that's
something everyone wants to avoid as much as possible.  Rather, it's queued
like most other renering operations.

As for D3DPRESENT_DONOTWAIT, I've never been able to get this to return
D3DERR_WASSTILLDRAWING under the debug runtime.  That may be a bug or it may
be by design, I don't know.

I've also never gotten it with D3DSWAPEFFECT_COPY.  If you look at the DDI
docs, the driver is instructed to return WASSTILLDRAWING in response to a
flip when the flip can't be scheduled.  (Without D3DPRESENT_DONOTWAIT the
driver would spin lock.)  With the COPY swap effect, the back buffer it
blitted, not flipped, and it appears that with blits you don't get
WASSTILLDRAWING.  Note that in windowed mode all swap effects are performed
via blit.

Also, in the tests that I've done I get WASSTILLDRAWING only if the present
queue is full -- that is, when the driver has queued up the maximum 3
frames.  The docs say that you can also get WASSTILLDRAWING when the driver
needs to wait for a vsync but I've never gotten it to happen and in fact I
don't see how it can.  Because the flip is queueable, it executes
asynchronously with respect to the app -- possibly long after Present has
returned.

To summarize: If you're running on the retail runtime, and you're
full-screen, and you're using D3DSWAPEFFECT_DISCARD or D3DSWAPEFFECT_FLIP,
and your app is GPU-bound, you might get D3DERR_WASSTILLDRAWING -- at least
in my observation.

What you're seeing when the window is covered is something I and others have
seen too.  As a workaround you can detect that the window is covered and
sleep for a bit.  There are a couple of ways to do this.  Peter Arsoff came
up with the simplest one I've seen:

RECT r;
HDC dc = GetDC(hwnd);
int bounds = GetClipBox(dc, &r);
ReleaseDC(hwnd, dc);
if (bounds == NULLREGION)
    Sleep(100);

Just out of curiosity, what hardware/driver are you running on?  This may be
a driver issue.

--
Donavon Keithley


Quote:> ok, i was wrong when saying BeginScene takes much time, but Present()
still
> does .. :>
> presuming that Present() really only puts some backbuffer to screen, i
> thought, perhaps the function only waits until the rendering on this
buffer
> is completed, but i got the swapchain of my device and called present with
> the "DoNotWait"-flag which should, according to the documentation, return
a
> "WasStillDrawing"-error, if "the hardware is busy processing", but this
> never happens ...

> another thing i don't understand: there are two situations, where 1) my
> mouse gets updated not as frequently as usual and 2) winamp begins
> "stuttering" although processor load is only 30-40%. this happens, if my
> whole rendering window is covered by another window or if i simply turn on
> wireframe mode (on several occasions you also get this stuttering without
> wireframe mode).

> *sigh* why is it soo difficult to get d3d properly running ? :/

 
 
 

question about rendering

Post by Jan Hammerschmid » Mon, 07 Jul 2003 07:30:33


Quote:> To summarize: If you're running on the retail runtime, and you're
> full-screen, and you're using D3DSWAPEFFECT_DISCARD or D3DSWAPEFFECT_FLIP,
> and your app is GPU-bound, you might get D3DERR_WASSTILLDRAWING -- at
least
> in my observation.

ok, after doing this i finally got my "WasStillDrawing"-error ;)
as my app does almost no cpu work this means, rendering is too slow, yes ?
ok, perhaps this is the only problem - i render too many triangles ..
should be about 250000 .. :>
but recently i saw unreal 2 in wireframe mode and thought, they are
rendering many more triangles than i do (and at least they have a wireframe
mode that is not dropping to 10fps ..)

ok, but even if i accept that i want too much from my hardware, it still
doesn't explain, why winamp begins stuttering, when putting too much load on
my gpu!

2 other things i found out: the more text i draw with D3DXFONT (any chance
to see, what the DrawTextA-function does besides setting endless redundant
renderstates ..?), the longer my rendering-block (between Begin/EndScene)
takes, while the Present() call takes less time and the "winamp-stuttering"
gets less.

the second interesting thing has to do with the two differnt methods i
calculate the framerate: the 1st simply counts the frames and display (and
reset) the number after a second.
the 2nd method uses the time, one frame takes and averages "1 / time"
over 20 frames.
now, if i draw some text with D3DXFONT, the two values are the same, but if
not, the 2nd method gives out much higher values (apparently wrong ones)
than the first.

Quote:> Just out of curiosity, what hardware/driver are you running on?  This may
be
> a driver issue.

i have a Geforce Ti 4200 and the newest detonators (44.03). also tested the
41.09 and the 30.82 but i saw no difference with the winamp stuttering
effect (in fact, general performance get worse ...)



> First, Present does not wait until the frame is finished rendering and has
> been presented.  If it did then the GPU would be idle on return, and
that's
> something everyone wants to avoid as much as possible.  Rather, it's
queued
> like most other renering operations.

> As for D3DPRESENT_DONOTWAIT, I've never been able to get this to return
> D3DERR_WASSTILLDRAWING under the debug runtime.  That may be a bug or it
may
> be by design, I don't know.

> I've also never gotten it with D3DSWAPEFFECT_COPY.  If you look at the DDI
> docs, the driver is instructed to return WASSTILLDRAWING in response to a
> flip when the flip can't be scheduled.  (Without D3DPRESENT_DONOTWAIT the
> driver would spin lock.)  With the COPY swap effect, the back buffer it
> blitted, not flipped, and it appears that with blits you don't get
> WASSTILLDRAWING.  Note that in windowed mode all swap effects are
performed
> via blit.

> Also, in the tests that I've done I get WASSTILLDRAWING only if the
present
> queue is full -- that is, when the driver has queued up the maximum 3
> frames.  The docs say that you can also get WASSTILLDRAWING when the
driver
> needs to wait for a vsync but I've never gotten it to happen and in fact I
> don't see how it can.  Because the flip is queueable, it executes
> asynchronously with respect to the app -- possibly long after Present has
> returned.

> To summarize: If you're running on the retail runtime, and you're
> full-screen, and you're using D3DSWAPEFFECT_DISCARD or D3DSWAPEFFECT_FLIP,
> and your app is GPU-bound, you might get D3DERR_WASSTILLDRAWING -- at
least
> in my observation.

> What you're seeing when the window is covered is something I and others
have
> seen too.  As a workaround you can detect that the window is covered and
> sleep for a bit.  There are a couple of ways to do this.  Peter Arsoff
came
> up with the simplest one I've seen:

> RECT r;
> HDC dc = GetDC(hwnd);
> int bounds = GetClipBox(dc, &r);
> ReleaseDC(hwnd, dc);
> if (bounds == NULLREGION)
>     Sleep(100);

> Just out of curiosity, what hardware/driver are you running on?  This may
be
> a driver issue.

> --
> Donavon Keithley



> > ok, i was wrong when saying BeginScene takes much time, but Present()
> still
> > does .. :>
> > presuming that Present() really only puts some backbuffer to screen, i
> > thought, perhaps the function only waits until the rendering on this
> buffer
> > is completed, but i got the swapchain of my device and called present
with
> > the "DoNotWait"-flag which should, according to the documentation,
return
> a
> > "WasStillDrawing"-error, if "the hardware is busy processing", but this
> > never happens ...

> > another thing i don't understand: there are two situations, where 1) my
> > mouse gets updated not as frequently as usual and 2) winamp begins
> > "stuttering" although processor load is only 30-40%. this happens, if my
> > whole rendering window is covered by another window or if i simply turn
on
> > wireframe mode (on several occasions you also get this stuttering
without
> > wireframe mode).

> > *sigh* why is it soo difficult to get d3d properly running ? :/

 
 
 

question about rendering

Post by Donavon Keithle » Mon, 07 Jul 2003 09:58:27



Quote:> ok, after doing this i finally got my "WasStillDrawing"-error ;)
> as my app does almost no cpu work this means, rendering is too slow, yes ?

It means the CPU is feeding frames in faster than the hardware can eat
them -- you are GPU-bound.  (Unless you *are* getting WASSTILLDRAWING on a
vsync, but like I said it's my conjecture that this doesn't happen.)
Anyway, being GPU-bound doesn't by itself indicate a problem.  There's
always a bottleneck somewhere.  It depends on how efficiently you have the
GPU doing its work.

Quote:> ok, perhaps this is the only problem - i render too many triangles ..
> should be about 250000 .. :>
> but recently i saw unreal 2 in wireframe mode and thought, they are
> rendering many more triangles than i do (and at least they have a
wireframe
> mode that is not dropping to 10fps ..)

In my experience wireframe is slower than solid filling, probably because
IHVs just aren't that concerned about wireframe performance.

My advice would be to go through the usual optimization steps: find the
bottleneck, fix the problem, repeat.  ATI and NVIDIA both have excellent
optimization resources on their developer sites.  Also, Microsoft has a new
profiling tool coming down the pike called GPA -- keep an eye out for it.

Quote:> ok, but even if i accept that i want too much from my hardware, it still
> doesn't explain, why winamp begins stuttering, when putting too much load
on
> my gpu!

That's a bug in the runtime or the driver.  I haven't heard any reports of
this on ATI hardware so it may be an NVIDIA thing.  Just use the workaround
I showed you.

Quote:> 2 other things i found out: the more text i draw with D3DXFONT (any chance
> to see, what the DrawTextA-function does besides setting endless redundant
> renderstates ..?), the longer my rendering-block (between Begin/EndScene)
> takes, while the Present() call takes less time and the
"winamp-stuttering"
> gets less.

Are you syncing with the display?  You usually want to be using
D3DPRESENT_INTERVAL_IMMEDIATE when tuning performance.

Also, profiling parts of your render loop or individual API calls isn't
typically useful.  Because the GPU operates in parallel, all you're
measuring is your interaction with the API and its internals.  For instance
DrawPrimitive might take, say, twenty-five microseconds to execute, but this
is basically just queueing the command.  Later the queue is flushed to the
driver which might put it in its own queue, and later it's actually
rendered.  As you've observed this time often shows up in Present, at least
when you're GPU-bound.

Hope that helps,

--
Donavon Keithley

 
 
 

question about rendering

Post by Rob » Tue, 08 Jul 2003 04:01:44


| > ok, but even if i accept that i want too much from my hardware, it still
| > doesn't explain, why winamp begins stuttering, when putting too much load
| on
| > my gpu!
|
| That's a bug in the runtime or the driver.  I haven't heard any reports of
| this on ATI hardware so it may be an NVIDIA thing.  Just use the workaround
| I showed you.

I've experienced a stuttering effect on a couple of older nVidia cards,
although it hasn't occured recently. I've never experienced any stuttering
whilst using my ATI card.

Rob

 
 
 

question about rendering

Post by Nico Vrouw » Tue, 08 Jul 2003 04:59:39




Quote:> > ok, but even if i accept that i want too much from my hardware, it still
> > doesn't explain, why winamp begins stuttering, when putting too much
load
> on
> > my gpu!

> That's a bug in the runtime or the driver.  I haven't heard any reports of
> this on ATI hardware so it may be an NVIDIA thing.  Just use the
workaround
> I showed you.

I have noticed the same problem on my system. It's not just when another
window is overlapping my window, it can happen at any time when using too
much power, even in fullscreen mode. On my system it started when I bought a
GF4MX, I never had anything like that on my old TNT2 Ultra.

/Nico

 
 
 

question about rendering

Post by Donavon Keithle » Tue, 08 Jul 2003 06:57:45





> > > ok, but even if i accept that i want too much from my hardware, it
still
> > > doesn't explain, why winamp begins stuttering, when putting too much
> load
> > on
> > > my gpu!

> > That's a bug in the runtime or the driver.  I haven't heard any reports
of
> > this on ATI hardware so it may be an NVIDIA thing.  Just use the
> workaround
> > I showed you.

> I have noticed the same problem on my system. It's not just when another
> window is overlapping my window, it can happen at any time when using too
> much power, even in fullscreen mode. On my system it started when I bought
a
> GF4MX, I never had anything like that on my old TNT2 Ultra.

That's may be something else then.  The problem I've observed is very
specific to running windowed and having the entire present rect covered.  If
so much as a single pixel is visible there's no stuttering.

At any rate I just grabbed the 44.03 drivers and it's gone away.

--
Donavon Keithley

 
 
 

question about rendering

Post by Peter Rac » Tue, 08 Jul 2003 16:54:54




Quote:> ok, i was wrong when saying BeginScene takes much time, but Present()
still
> does .. :>
> presuming that Present() really only puts some backbuffer to screen, i
> thought, perhaps the function only waits until the rendering on this
buffer
> is completed, but i got the swapchain of my device and called present with
> the "DoNotWait"-flag which should, according to the documentation, return
a
> "WasStillDrawing"-error, if "the hardware is busy processing", but this
> never happens ...

My experiences with DX8.1: I have a GPU bound application. The CPU needs
about 3-4 milliseconds to traverse the scene hierarchy an to output the
Draw... calls. The GPU needs about 20 ms to render everything. In the first
rendering loop Present returns quickly, in about 2-3 milliseconds. After
that the CPU outputs the Draw.. calls again, but the GPU is still rendering
the first frame. What happens now? Present does not return until the GPU did
not finish rendering the first frame. So with other words, it is Present,
where the CPU is forced to wait in a GPU bound application.

Quote:> *sigh* why is it soo difficult to get d3d properly running ? :/

Because you are programming a 2 processor system, CPU-GPU, without having
much access on the second proseccor (GPU). Once I have heard, that nvidia
has a "de* driver", which outputs a lot of GPU internal information,
but I never worked with it.

best regards
Peter