2016-02-05 12 views
0

Я довольно новичок в вычислении шейдеров, и я только что начал реализацию одного для моделирования 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] в любой момент времени.

+0

Вы сказали, что отправляете только один поток во время отладки, но почему это numthreads (1024,1,1), если это так? –

+0

Я думал, что вы можете отправить 1 и создать 1024 потока внутри самого шейдера. Я думал, что эти ценности независимы. Я, вероятно, исказил то, что я имел в виду; Я отправляю только 1 экземпляр (1, 1, 1), но у меня есть потоки шейдерного запуска 1024 (1024, 1, 1). Если это не так, как это работает, мне бы хотелось услышать больше, но именно так я интерпретировал документацию MSDN. – DHudson

+0

Вы правы, хотя правильная терминология в начальном вопросе была бы «Я только отправляю 1 группу нитей», а не «1 поток». Теперь я понимаю. –

ответ

0

Проблема с этим кодом заключалась в том, что переменная Namespace Constants::BIG_G не работает или используется правильно. Перемещение этого внутри функции и просто объявление его просто как float BIG_G устраняло проблемы, которые у меня были.

1

Вы не можете действительно установить глобальные переменные в HLSL. Компилятор разрешает их, потому что если вы используете шейдер через FX, это установит глобальные переменные для вас через постоянные буферы. Рад видеть, что вы решили это, просто захотелось опубликовать , почему, имея поплавок, определяемый как локальная переменная, исправил проблему.