Redundant SetSamplerState when using Effects

Started by
6 comments, last by dario_ramos 14 years, 1 month ago
Hi, We use Unmanaged Direct3D9 in C++, and we're trying to start using Effects. Now we have only one problem: redundant SetSamplerStates and SetRenderStates. This is because we set the D3D device's states. Then, when we render the effects, on each render cycle, the .fx saves it states, uses the device's, and then sets its states again. Therefore, it the device and the fx have states in common, redundancy ensues. Is there a way to avoid this? I read somewhere that setting states is quite expensive, performance-wise.
Advertisement
The performance overhead depends on how many times you call it. You generally have to start getting into the high hundreds/thousands before it gets really bad. You can use PIX to tell you how many times you call it per frame, and you can use tools like NVPerfHUD to tell you how much time you're spending in the driver each frame.

If you want to prevent redundant state calls, you have to implement ID3DXEffectStateManager and pass it to your effect. There's a sample in the SDK called "StateManager" with a stock implementation that you can use.
I'm not so sure but I think the driver takes care of (optimizes away) redundant state changes, so you only should really care about sorting your rendering order by texture or shader to minimize "actual" state changes. But again, I'm not so sure.
Quote:Original post by Amr0
I'm not so sure but I think the driver takes care of (optimizes away) redundant state changes, so you only should really care about sorting your rendering order by texture or shader to minimize "actual" state changes. But again, I'm not so sure.


No you definitely can't rely on that. And even if you could, it wouldn't matter since what you're trying to avoid is going into the driver at all (since user-mode to kernel-mode transitions are so slow).

Apparently, both the driver and the Direct3D runtime will try to optimize. This talks about accurate D3D profiling and is a good read actually. This part is relevant I think:
Quote:Optimizations in the runtime and/or the driver are designed to speed up rendering by reducing the amount of work required. The following are a couple of state change optimizations that may pollute profile averages:
* A driver (or the runtime) could save a state change as a local state. Because the driver could operate in a "lazy" algorithm (postponing work until it is absolutely necessary), work associated with some state changes could get delayed.
* The runtime (or a driver) may remove state changes by optimizing. An example of this might be to remove a redundant state change that disables lighting because lighting has previously been disabled.


But here it says "could" and "may", supporting what MJP said about it being unreliable, but perhaps in practice it just might be "reliable enough" in a lot of cases. Again, I'm not sure and I'm rather just mentioning things in hopes for informative comments since the subject is of interest to me.
The problem with relying on driver optimizations is that if you have to go to the driver, you've lost. Driver optimizations might spare you any GPU overhead that results from state changes, but because of the nature of drivers any time you go into the driver you pay a hefty penalty. Thus for DX9 the fastest path is to make sure you only go into the driver when you really need to, and this is done pretty easily by filtering out redundant calls. It's pretty easy to do...you just store the states you set into a bunch of variables and do a compare before actually doing any DX calls.

In DX10 and above things are different since the IHV's have to provide a user-mode driver and a kernel-mode driver, which allows the user-mode portion to perform a lot of filtering and optimizations without hitting the driver so much.
Silly me, somehow I completely forgot about this yesterday: D3DX Effects State Management. Cool useful article.
Quote:Original post by Amr0
Silly me, somehow I completely forgot about this yesterday: D3DX Effects State Management. Cool useful article.


We don't change states after initialization, so just turning off that flag works fine for us. Anyway, that's a very interesting article. I knew this was important, the guy got a 38% speedup by eliminating redundant state setting. Thanks guys!

This topic is closed to new replies.

Advertisement