Sign in to follow this  
discman1028

What can I do between shader pass Begin() and End()?

Recommended Posts

discman1028    212
[XNA Game Studio 3.0, C#] How can I find out what I can do between calls to Begin() and End() w/o penalty? Can I change shader constants? Render states? None of the above?
Effect m_fx;

m_fx.Begin();
m_fx.CurrentTechnique.Passes[0].Begin();
// ... ?
m_fx.CurrentTechnique.Passes[0].End();
m_fx.End();


I know the idea is to batch as many primitives together that use the same shader, render state, etc, but I have some confusion about the Begin()/End() api, and where that lies with respect to where shader constants/render states can be set.

Share this post


Link to post
Share on other sites
MJP    19755
When you call EffectPass.Begin(), it "talks" to the GraphicsDevice to make sure that everything is set up the way you have it laid out in your .fx file. This includes render states, sampler states, constants, shaders, and textures. This means if you want to call DrawPrimitives multiple times to draw multiple instances of geometry with the same shaders/textures/constants, you can go right ahead and do so.

If you do need to change a constant or texture via an EffectParameter inside the Begin/End block, just make sure you call Effect.CommitChanges(). This will make sure that the new state gets set onto the GraphicsDevice.

Share this post


Link to post
Share on other sites
discman1028    212
Quote:
Original post by MJP
If you do need to change a constant or texture via an EffectParameter inside the Begin/End block, just make sure you call Effect.CommitChanges(). This will make sure that the new state gets set onto the GraphicsDevice.


So which is a preferable design pattern, given that I only one to change one shader constant? Will the second choice here be slower than the first? (Or is the fx system smart enough about being lazy that it won't re-set all the states that are already set?)


Effect m_fx;

m_fx.Begin();
m_fx.CurrentTechnique.Passes[0].Begin();

DrawPrimitives();
MyChangeStates();
m_fx.CommitChanges();
DrawPrimitives();

m_fx.CurrentTechnique.Passes[0].End();
m_fx.End();




OR


Effect m_fx;

m_fx.Begin();
m_fx.CurrentTechnique.Passes[0].Begin();

DrawPrimitives();

m_fx.CurrentTechnique.Passes[0].End();
m_fx.End();

m_fx.CurrentTechnique = (new technique w/new states)

m_fx.Begin();
m_fx.CurrentTechnique.Passes[0].Begin();

DrawPrimitives();

m_fx.CurrentTechnique.Passes[0].End();
m_fx.End();




?

Share this post


Link to post
Share on other sites
MJP    19755
It's preferable to do the first. Calling Begin on the EffectPass again will cause it to re-set device state again. The XNA framework should do some checks to avoid sending redundant state changes, but this may not cover all cases so I'd think you're better off going with the first.

Share this post


Link to post
Share on other sites

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