2016-02-05 90 views
0

我是计算着色器的新手,我刚刚开始为Nbody模拟实现一个,我遇到了一个我自己无法解决的问题。计算着色器中的计算失败。 HLSL DX11

以下是计算文件中包含的所有内容,入口点是ParticleComputeShader。我只调度1个线程并在着色器中创建1024个线程。当我调试并调整它时,只有1024个粒子,因此每个线程都有自己的粒子。

问题似乎是distance != 0.0f和计算有关的距离。在我进行检查之前,它将位置返回为1.QNaN,所以它在代码中的某个位置除以0。我的想法是,我错误地使用j来访问StructuredBuffer,并且它搞砸了接下来的几个计算。

另一个说明:Position.w是粒子的质量。

struct ConstantParticleData 
{ 
    float4 position; 
    float4 velocity; 
}; 

struct ParticleData 
{ 
    float4 position; 
    float4 velocity; 
}; 

namespace Constants 
{ 
    float BIG_G = 6.674e-11f; 
    float SOFTEN = 0.01f; 
} 

StructuredBuffer<ConstantParticleData> inputConstantParticleData : register(t0); 
RWStructuredBuffer<ParticleData> outputParticleData : register(u0); 


[numthreads(1024, 1, 1)] 
void ParticleComputeShader(int3 dispatchThreadID : SV_DispatchThreadID) 
{ 
    float3 acceleration = float3(0.0f, 0.0f, 0.0f); 

    for(int j = 0; j < 1024; j++) 
    { 
     float3 r_ij; 
     r_ij.x = inputConstantParticleData[j].position.x - inputConstantParticleData[dispatchThreadID.x].position.x; 
     r_ij.y = inputConstantParticleData[j].position.y - inputConstantParticleData[dispatchThreadID.x].position.y; 
     r_ij.z = inputConstantParticleData[j].position.z - inputConstantParticleData[dispatchThreadID.x].position.z; 

     float distance = 0.0f; 
     distance = length(r_ij); 



     if(distance != 0.0f) 
     { 
      float bottomLine = pow(distance, 2) + pow(Constants::SOFTEN, 2); 

      acceleration += Constants::BIG_G * ((inputConstantParticleData[j].position.w * r_ij)/
          pow(bottomLine, 1.5)); 
     } 
    } 

    acceleration = acceleration/inputConstantParticleData[dispatchThreadID.x].position.w; 

    outputParticleData[dispatchThreadID.x].velocity = inputConstantParticleData[dispatchThreadID.x].velocity + 
                 float4(acceleration.x, acceleration.y, acceleration.z, 0.0f); 

    outputParticleData[dispatchThreadID.x].position = inputConstantParticleData[dispatchThreadID.x].position + 
               float4(outputParticleData[dispatchThreadID.x].velocity.x, 
                 outputParticleData[dispatchThreadID.x].velocity.y, 
                 outputParticleData[dispatchThreadID.x].velocity.z, 
                 0.0f); 


} 

任何帮助将不胜感激。着色器适用于简单输入 - >输出,并且当我试图在任何时候使用比inputConstantParticleData[dispatchThreadID.x]更多的输入缓冲区时,才开始给出麻烦。

+0

你说你调度时只调度一个线程,但为什么是numthreads(1024,1,1)如果是这种情况? –

+0

我以为你可以调度1,并在着色器本身内创建1024个线程。我认为这些价值观是独立的。我可能歪曲了我的意思;我只调度1个实例(1,1,1),但我有着色器运行1024(1024,1,1)线程。如果这不是它的工作原理,我很乐意听到更多,但这就是我解读MSDN文档的方式。 – DHudson

+0

你是对的,尽管在最初的问题中正确的术语应该是“我只调度1个线程组”,而不是“1个线程”。我现在明白了。 –

回答

0

此代码的问题在于名称空间变量Constants::BIG_G未能正常工作或正在被正确使用。将它移到函数的内部,只需简单地将其声明为float BIG_G即可解决我遇到的问题。

1

你不能真的在HLSL中设置全局变量。编译器允许它们,因为如果你通过FX使用着色器,那将通过常量缓冲区为你设置全局变量。很高兴看到你解决了这个问题,只想发帖为什么将浮点数定义为局部变量解决了问题。