Sign in to follow this  

SetRenderState each frame

This topic is 4833 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I recently realized that every call to a DrawPrimitive leads to a bunch of SetRenderstates, SetTextureStages and SetSamplerStages which are ignored because of redundancy. I wonder now how this comes and how I can prevent it. I would understand it if I set the States myself but the Call to Draw executes them and not me?!? Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites
You should sort your renderable objects so that you can draw them using as few state changes and draw calls as possible.

While it is usually difficult and even unpractical to get a perfect partitioning of the drawable objects, it pays to strive towards that - graphics hardware likes big data portions infinitely better than small ones, for various reasons.

Also, it is not so relevant to you if the hardware states are actually set before or during the rendering. The card is free to cache instructions, as long as it executes them in the time of need (by the time of the draw call).

Share this post


Link to post
Share on other sites
Quote:
Original post by MannyCalavera

I recently realized that every call to a DrawPrimitive leads to a bunch of SetRenderstates, SetTextureStages and SetSamplerStages which are ignored because of redundancy.


I don't think it does. What gave you this impression?

Share this post


Link to post
Share on other sites
@Nik02

Thanks. That explains it much better. But I find it still strange that calls to SetTextureStage and SetSamplerState are even necessary since there is no point in my code where I call them. How can something be cached and latere ignored because of redundance if i don't even set it?

@DBX

When I debugged (step for step) I could see with the dbmon.exe that the call to Draw did spawn those warnings (SetRenderState[..]ignored[..]).

Share this post


Link to post
Share on other sites
This is what I think, though I'm not 100% sure, I haven't read it in a DX document. DirectX internally caches the render states. That's why it is ignoring them, so it's not really a problem. You could also cache these states with some type of Render Manager. If you tell the render manager to set texture 0, and it knows that it was set previously, it can ignore your request to set it. Then again, DirectX is going to check that for you too, so then there are two places in the software where the state is cached and checked before setting. This is my understanding of it anyway.

How is your code structured? Do you set the render states during the render loop? Or did you just make a test application where you load everything, set the render states, then just call Draw every frame?

Chris

Share this post


Link to post
Share on other sites
Quote:
Original post by MannyCalavera
@Nik02

Thanks. That explains it much better. But I find it still strange that calls to SetTextureStage and SetSamplerState are even necessary since there is no point in my code where I call them. How can something be cached and latere ignored because of redundance if i don't even set it?


Are you using the .fx framework, by any chance? It can be configured to set various device states upon application (and more often than not, it is configured that way). If this is not the case, then something is wrong - and badly - because states do not magically set themselves. Period. [smile]

If the code you run isn't your own, run it thru debugger; stepping every line, until you either see a state change or an effect begin().

Share this post


Link to post
Share on other sites
Thanks so far.

Quote:
How is your code structured? Do you set the render states during the render loop? Or did you just make a test application where you load everything, set the render states, then just call Draw every frame?


I set some renderstates (Backfaceculling and Alphachannelusage)but long before I go into the render loop but I don't ever set Texturestages or Samplerstates.

In the renderloop I only call beginscene, draw, endscene and present, nothing more.

Quote:

Are you using the .fx framework, by any chance? It can be configured to set various device states upon application (and more often than not, it is configured that way). If this is not the case, then something is wrong - and badly - because states do not magically set themselves. Period.

If the code you run isn't your own, run it thru debugger; stepping every line, until you either see a state change or an effect begin().


I've to admit I don't even know the .fx Framework, so I suppose I haven't even touched it. ;) I stepped through every line and the only one that executes this behaviour is my call to draw. The few places I set renderstated don't generate the ignorance out of redundancy.

Well, I'm so confused.

Share this post


Link to post
Share on other sites
Quote:
Original post by Supernat02
This is what I think, though I'm not 100% sure, I haven't read it in a DX document. DirectX internally caches the render states. That's why it is ignoring them, so it's not really a problem.

Direct3D does state-filtering only for non-pure devices - your only cost is a call to D3D.
However, with pure devices, any state changes get passed directly to the driver (which might or might not filter). An exception of this is changing a state that is supported by an interface (i.e. changing a texture will get filtered even with pure devices, because there's an IDirect3DTexture9). IIRC, the exception to this is pixel shaders. Even though they have an interface they don't got filtered.

In general, your application is in better position to filter redundant states - you'll be more efficient this way. Also, using PURE devices is recommended for improving performance, and with these redundant states will hurt.

Share this post


Link to post
Share on other sites
Quote:
Original post by Coder
Quote:
Original post by Supernat02
This is what I think, though I'm not 100% sure, I haven't read it in a DX document. DirectX internally caches the render states. That's why it is ignoring them, so it's not really a problem.

Direct3D does state-filtering only for non-pure devices - your only cost is a call to D3D.
However, with pure devices, any state changes get passed directly to the driver (which might or might not filter). An exception of this is changing a state that is supported by an interface (i.e. changing a texture will get filtered even with pure devices, because there's an IDirect3DTexture9). IIRC, the exception to this is pixel shaders. Even though they have an interface they don't got filtered.

In general, your application is in better position to filter redundant states - you'll be more efficient this way. Also, using PURE devices is recommended for improving performance, and with these redundant states will hurt.



Yep. Just to expand on this:

when you're changing state, more often than not, you're changing more than one state at the same time; This knowledge of groups of states which change at the same time is why your application is in a much better position than the "if (currentstate!=newstate)" checking in the non-PURE Direct3D runtime.

If you use D3D state blocks and/or D3DX effects, then this can be as simple as sorting by block handle/effect and then making sure you don't set the same effect/state block twice in a row.

Share this post


Link to post
Share on other sites
I have a BSP loader which sets the render/texture/sampler-states with every Render() call. using the normal pDevice->SetxxxState() calls results in 80 fps and my debug window being spammed with "rednundand xxx state" messages.
So I decided to write my own statemanager (states are stored in a vector), and this is the result:

release build, debug DX runtime:
- no state manager: 80 FPS
- state manager: 230 FPS

Truly unbelievable, isn't it? :)
I thought the DX runtime would filter the redundant state changes, but obviously it doesn't.

Share this post


Link to post
Share on other sites
Quote:
Truly unbelievable, isn't it? :)
I thought the DX runtime would filter the redundant state changes, but obviously it doesn't.


Assuming you are definately not using a PURE device (where the runtime won't perform any state filtering) for your profiling:

Try the same test with the Retail D3D runtime... [smile]

Bear in mind that D3D sending all that "redundant renderstate" spam to your debug output stream does take a fairly significant chunk of time!!


Of course, by filtering at your application end you avoid a COM/DLL call into the D3D runtime - but that isn't at all significant except in pathalogical cases.

Share this post


Link to post
Share on other sites

This topic is 4833 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this