Using SurfaceFormat.Single and HLSL for GPGPU with XNA
- by giancarlo todone
I'm trying to implement a so-called ping-pong technique in XNA; you basically have two RenderTarget2D A and B and at each iteration you use one as texture and the other as target - and vice versa - for a quad rendered through an HLSL pixel shader.
step1: A--PS--B
step2: B--PS--A
step3: A--PS--B
...
In my setup, both RenderTargets are SurfaceFormat.Single.
In my .fx file, I have a tachnique to do the update, and another to render the "current buffer" to the screen.
Before starting the "ping-pong", buffer A is filled with test data with SetData<float>(float[]) function: this seems to work properly, because if I render a quad on the screen through the "Draw" pixel shader, i do see the test data being correctly rendered.
However, if i do update buffer B, something does not function proerly and the next rendering to screen will be all black.
For debug purposes, i replaced the "Update" HLSL pixel shader with one that should simply copy buffer A into B (or B into A depending on which among "ping" and "pong" phases we are...).
From some examples i found on the net, i see that in order to correctly fetch a float value from a texture sampler from HLSL code, i should only need to care for the red channel.
So, basically the debug "Update" HLSL function is:
float4 ComputePS(float2 inPos : TEXCOORD0) : COLOR0
{
float v1 = tex2D(bufSampler, inPos.xy).r;
return float4(v1,0,0,1);
}
which still doesn't work and results in a all-zeroes ouput.
Here's the "Draw" function that seems to properly display initial data:
float4 DrawPS(float2 inPos : TEXCOORD0) : COLOR0
{
float v1 = tex2D(bufSampler, inPos.xy).r;
return float4(v1,v1,v1,1);
}
Now: playing around with HLSL doesn't change anything, so maybe I'm missing something on the c# side of this, so here's the infamous Update() function:
_effect.Parameters["bufTexture"].SetValue(buf[_currentBuf]);
_graphicsDevice.SetRenderTarget(buf[1 - _currentBuf]);
_graphicsDevice.Clear(Color.Black); // probably not needed since RenderTargetUsage is DiscardContents
_effect.CurrentTechnique = _computeTechnique;
_computeTechnique.Passes[0].Apply();
_quadRender.Render();
_graphicsDevice.SetRenderTarget(null);
_currentBuf = 1 - _currentBuf;
Any clue?