Zero wonders what these registers are for

Been a while since I last posted... and it's also been a while since I figured this out (i.e. a few weeks ago), but it makes for good posting, so I'll roll with it. We're going back to my forays in shader programming again, even if all I'm doing is really simple stuff.

Now, at this point in the exercise, all I wanted to do was take a scene with a model in it, and do some edge detection on it - so rather than making something look cool, all I really wanted in the end was a flat picture with just the outline of the model.

The exact (and primitive) method I used I'll save for a later blog post if I'm feeling up to it, but there was a point that confused me when I was actually rendering the final (for now) scene. Here I was using SpriteBatch to render my buffer as a big, screen-wide texture.

PostprocessParameters["SceneTexture"].SetValue(m_NormalDepthRenderTarget);
...
m_SpriteBatch.Begin(0, BlendState.Opaque, null, null, null, m_PostprocessEffect);
m_SpriteBatch.Draw(m_SceneRenderTarget, Vector2.Zero, Color.White);
m_SpriteBatch.End();

Now, my shader function in m_PostprocessEffect was pretty simple (and again, primitive), but for some odd reason, it gave me a blank screen of white... even when I reduced it to this.

float4 PixelShaderFunction(float2 TexCoord : TEXCOORD0) : COLOR0 {
  float3 p0 = tex2D(SceneSampler, TexCoord);
  return float4(p0, 1.0);
}

Yep, straight pass-through wasn't doing anything. The rest of my code looked fine at first glance... but upon fiddling around with about everything else I could, there was but one declaration left.

texture SceneTexture;
sampler SceneSampler : register(s0) = sampler_state {
  Texture = (SceneTexture);
  ...
}

Ah... this turned out to be the problem line - specifically because I was using register 0 (as denoted with the s0 - sampler register 0). See, for when I was setting up this effect, I was putting the texture m_NormalDepthRenderTarget into the effect's parameter SceneTexture. I was then making a sampler state and popping that into register 0. Seems harmless, but it wasn't working unless (as I found out) I used any other register for this sampler_state other than s0. It worked for s1, it worked for s2... just not s0. The documentation wasn't yielding any easy answers as to why this was so, either.

However, with the help of some kind people at the XNA forums, well... as I understand it, if XNA is going to put the texture in sampler register 0 in its own register, it should put it in texture register 0, right? That's exactly the problem. The way SpriteBatch works, is that whatever you call the Draw function on it, supplying it a texture in the input parameters, it sticks that texture into texture register 0 all on its own. Here I was inadvertently putting something else in what should have been a reserved spot, which ended up giving me a shader function that did absolutely nothing.

So, lesson learned: when using SpriteBatch for postprocessing, whatever texture you use as input will want to be in register 0. If you want to do something fancy with effects and passing textures into them, then stay away from that register. Just use anything but 0.