Я довольно новичок в вычислении шейдеров, и я только что начал реализацию одного для моделирования Nbody, и я столкнулся с проблемой, которую я не могу решить самостоятельно.Ошибка вычисления в вычислительном шейдере. HLSL DX11
Вот все, что содержится в вычислительном файле, а точкой входа является ParticleComputeShader. Я только отправляю 1 поток и создаю 1024 в шейдере. Есть только 1024 частицы, в то время как я отлаживаю и настраиваю его, чтобы каждый поток имел свою собственную частицу, к которой относится.
Проблема, кажется, distance != 0.0f
и расчет, связанный с расстоянием. До того, как я проверил, он возвращал позицию как 1.QNaN, поэтому он делил на 0 где-то в коде. Мои мысли по этому поводу в том, что я неправильно обращаюсь к StructuredBuffer с помощью j
, и это затмевает следующие несколько расчетов.
Другое примечание: 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]
в любой момент времени.
Вы сказали, что отправляете только один поток во время отладки, но почему это numthreads (1024,1,1), если это так? –
Я думал, что вы можете отправить 1 и создать 1024 потока внутри самого шейдера. Я думал, что эти ценности независимы. Я, вероятно, исказил то, что я имел в виду; Я отправляю только 1 экземпляр (1, 1, 1), но у меня есть потоки шейдерного запуска 1024 (1024, 1, 1). Если это не так, как это работает, мне бы хотелось услышать больше, но именно так я интерпретировал документацию MSDN. – DHudson
Вы правы, хотя правильная терминология в начальном вопросе была бы «Я только отправляю 1 группу нитей», а не «1 поток». Теперь я понимаю. –