从XNA上的后备缓冲区(HLSL)获取顶点

时间:2009-11-15 16:57:05

标签: xna hlsl gpgpu

您好,对不起晦涩的标题:} 我会尽力解释我能做的最好的事情。

首先,我是HLSL的新手,但我了解来自童话世界的管道和东西。我想要做的是使用gpu进行一般计算(GPGPU)。

我不知道的是:我怎样才能将顶点(使用顶点着色器转换后的顶点)读回我的xna应用程序?我读了一些关于使用gpu的纹理内存的东西,但我找不到任何可靠的东西......

提前感谢任何信息/提示! : - )

*不确定是否可能因为光栅化器和像素着色器(如果有的话),我的意思是,最后它只是关于像素,对吗?

2 个答案:

答案 0 :(得分:2)

据我所知,这通常是不可能的。

你到底想要做什么?可能还有另一种解决方案

编辑::考虑到评论。如果您想要做的就是在GPU上进行常规矢量计算,请尝试在像素着色器中进行,而不是使用顶点着色器。

例如,假设您想要跨越两个向量,首先我们需要将数据写入纹理

//Data must be in the 0-1 range before writing into the texture, so you'll need to scale everything appropriately
Vector4 a = new Vector4(1, 0, 1, 1);
Vector4 b = new Vector4(0, 1, 0, 0);

Texture2D dataTexture = new Texture2D(device, 2, 1);
dataTexture.SetData<Vector4>(new Vector4[] { a, b });

所以现在我们有了2 * 1纹理,数据输入,只需使用spritebatch和效果渲染纹理:

Effect gpgpu;
gpgpu.Begin();
gpgpu.CurrentTechnique = gpgpu.Techniques["DotProduct"];
gpgpu.CurrentTechnique.Begin();
spriteBatch.Begin();
gpgpu.CurrentTechnique.Passes[0].Begin();
spriteBatch.Draw(dataTexture, new Rectangle(0,0,2,1), Color.White);
spriteBatch.end();
gpgpu.CurrentTechnique.Passes[0].End();
gpgpu.CurrentTechnique.End();

我们现在需要的是上面显示的gpgpu效果。这只是一个标准的后处理着色器,看起来像这样:

sampler2D DataSampler = sampler_state
{
    MinFilter = Point;
    MagFilter = Point;
    MipFilter = Point;
    AddressU = Clamp;
    AddressV = Clamp;
};

float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 A = tex2D(s, texCoord);
    float4 B = tex2D(s, texCoord + float2(0.5, 0); //0.5 is the size of 1 pixel, 1 / textureWidth
    float d = dot(a, b)
    return float4(d, 0, 0, 0);
}

technique DotProduct
{
    pass Pass1
    {
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}

这将把A和B的点积写入第一个像素,将B和B的点积写入第二个像素。然后你可以回读这些答案(忽略无用的答案)

Vector4[] v = new Vector4[2];
dataTexture.GetData(v);
float dotOfAandB = v[0];
float dotOfBandB = v[1];

多田! 尝试在更大范围内执行此操作时存在一大堆小问题,请在此处发表评论,并且我会尽力帮助您解决任何问题:)

答案 1 :(得分:0)

如果打开“Stream Output Stage”,顶点着色器的输出将存储在内存缓冲区中。稍后可以根据需要从GPU或CPU读取这些值。