Using SurfaceFormat.Single and HLSL for GPGPU with XNA

Posted by giancarlo todone on Game Development See other posts from Game Development or by giancarlo todone
Published on 2012-07-03T18:39:02Z Indexed on 2012/07/03 21:23 UTC
Read the original article Hit count: 441

Filed under:
|
|
|

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?

© Game Development or respective owner

Related posts about XNA

Related posts about c#