Does SetRenderState cause a GPU stall?

Started by
3 comments, last by AndyTX 18 years, 7 months ago
Hi guys, got a question again :). The title can be a bit confusing, so I'll explain what I'm trying to do. I've got one VB, which I use as two different ones. The first is for rendering normal primitives, and the other is for the alphablended ones. Now, What I do, is lock the first half of the buffer (D3DLOCK_DISCARD|D3DLOCK_NOOVERWRITE, of course), memcpy, and then render the whole thing. Next, supposedly while the GPU is still rendering, I lock the second half (again, D3DLOCK_DISCARD|D3DLOCK_NOOVERWRITE), memcpy and then render. Now, From what I know, if I'm using the two flags, I'm not causing a GPU stall, so I do the memcpy while the GPU is doing the actual drawing of the first batch. This all seems logical and efficient, but like I said, I need to change a renderstate. Now, IIRC, that does cause a GPU stall. So, in reality, I end up waiting for the GPU to finish drawing anyways. I also don't know when to call the renderstate. Heres my current sequence, looking for ideas :): 1) Lock first half. 2) Render first half. 3) SetRenderState. 4) Lock second half. 5) Render second half. I intend to profile the whole thing once my codebase is stable enough (too many factors now), but is the SetRenderState going to be a problem? any ways around it? Thanks a bunch.
Sirob Yes.» - status: Work-O-Rama.
Advertisement
Don't D3DLOCK_DISCARD and D3DLOCK_NOOVERWRITE contradict each other?
I mean, with D3DLOCK_DISCARD, doesn't the old buffer get dumped when it's locked? This would make the D3DLOCK_NOOVERWRITE flag pointless because the buffer would be empty to begin with. Am I wrong here?
--m_nPostCount++
You need the GPU to be in the right state before rendering, so there's really no other way of doing it.

That said changes to render state do not usually cause the GPU to "stall" (if by stall you mean a forced synchronization between CPU and GPU). The change of state is simply put into the command queue and executed when it comes.

Changes of state are not particularly cheap (although it depends heavily WHICH state), so try to do them as infrequently as possible and always change all your state at once if you can (in "blocks"), but if you need the state a certain way for a certain render call, there's no way around that.

Regarding you locking flags, you only need to specify DISCARD. However this tells Direct3D that you no longer need the data previous in the buffer... the WHOLE buffer, not just the portion that you are locking! Thus in your situation you shouldn't work with "half" buffers and instead simply lock the whole buffer with DISCARD, write your data, render, and repeat as needed. If you need to read back the data that you're putting in the buffer then you can't use DISCARD in ANY lock calls to that buffer. Thus if you need the data in the first half of the buffer, you want to use NOOVERWRITE when you lock the second half (promising D3D that you won't overwrite anything that you've already written) and not DISCARD.
Quote:
That said changes to render state do not usually cause the GPU to "stall" (if by stall you mean a forced synchronization between CPU and GPU). The change of state is simply put into the command queue and executed when it comes.


This is good news :). Is there any specific way to make sure? Maybe a list of which do and which don't? I need to set the alphablend, alphaop and all the alpha related settings.

Quote:
Changes of state are not particularly cheap (although it depends heavily WHICH state), so try to do them as infrequently as possible and always change all your state at once if you can (in "blocks")...

Only once a frame, no big issue.

Quote:
but if you need the state a certain way for a certain render call, there's no way around that.

Yes, but I might consider changing the render order to render some other stuff, so I make the change at a different time, possibly when I need to force a sync anyways...

Thanks for the speedy answer :).

@DirectXFreak: D3DLOCK_NOOVERWRITE simply means you're informing DX that there is no way the memory use inside the buffer is being used. Since the GPU can render while it's copying data, theres a chance of overwriting data that's in use. Normally, (without the flag) DX halts drawing for the proccess of the Lock. On the other hand, when you specify the flag, DX is possitive that data isn't in use, so theres no need to halt the GPU.
Generally, it's used if you havn't used the data you're locking in the current frame.
(I hope this is all accurate :)).
Sirob Yes.» - status: Work-O-Rama.
Quote:Original post by sirob
This is good news :). Is there any specific way to make sure? Maybe a list of which do and which don't? I need to set the alphablend, alphaop and all the alpha related settings.

It depends on the card and drivers, etc. but in general you can read the documentation or just think about it :) Anything that requires data in one place to be moved to the other BEFORE asynchronous operation can continue will probably "stall" the CPU/GPU. Sometimes these things are unavoidable but profiling will often reveal problematic parts of your program.

I did a quick google (site:gamedev.net) and came up with a few good threads although I couldn't find the one that I remember reading a while back. Oh well, here's one (feel free to search for more):
http://www.gamedev.net/community/forums/topic.asp?topic_id=170344

Quote:Original post by sirob
Thanks for the speedy answer :).

No problem - sorry for the slow follow-up (I've been pretty busy today).

This topic is closed to new replies.

Advertisement