Подсчет сортировки на графическом процессоре - как использовать атомарные функции?
Я реализую алгоритм сортировки подсчета (для частиц в трехмерном пространстве) с вычислением шейдеров directx11 в vvvv , графической среде программирования (только шейдеры записываются в тексте, все остальное (средство визуализации, буферы и т. Д.) Выполняется путем соединения узлов, следовательно, здесь сложнее поделиться ...).
Я успешно разделил свое пространство на ячейки, подсчитал количество частиц на ячейку и создал префиксную сумму / включающее сканирование количества ячеек. На последнем этапе я сначала копирую буфер суммы префиксов в RWStructuredBuffer следующим образом:
StructuredBuffer<uint> InputBuffer;
RWStructuredBuffer<uint> Prefix : PREFIXBUFFER;
[numthreads(1,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
Prefix[tid.x] = InputBuffer[tid.x];
}
(обратите внимание, что приведенный выше шаг может быть специфическим для моей среды, поскольку я не вижу других вариантов, чтобы сделать этот буфер доступным для записи в следующем шейдере)
Затем для каждой ячейки частицы я ищу значение буфера суммы префикса, использую его в качестве позиции индекса в выходном буфере для соответствующей частицы, затем увеличиваю буфер суммы префикса на 1:
StructuredBuffer<particleID> ParticleIDs;
RWStructuredBuffer<uint> Prefix : PREFIXBUFFER;
RWStructuredBuffer<particleID> ResultBuffer : RESULTBUFFER;
[numthreads(64,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
particleID partID = ParticleIDs[tid.x];
uint oldval;
InterlockedAdd(Prefix[partID.cellID],1,oldval);
ResultBuffer[oldval] = partID;
}
Структура частиц, которую я здесь использую, выглядит так и предварительно вычислена:
struct particleID
{
uint pID; //particleID
uint cellID;
};
К сожалению, это не работает. Кажется, что полученный буфер имеет нормальные идентификаторы ячеек, но идентификаторы pID мерцают при тестировании с фиксированными положениями частиц.
На самом деле у меня нет опыта работы с атомарными функциями, но за несколько шагов до этого, подсчитывая частицы на ячейку, я делаю очень похожую вещь:
Сначала я сбрасываю счетчик на 0:
RWStructuredBuffer<uint> OutputBuffer : BACKBUFFER;
[numthreads(1,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
OutputBuffer[tid.x] = 0;
}
Тогда я так считаю:
StructuredBuffer<particleID> ParticleIDs;
RWStructuredBuffer<uint> OutputBuffer : BACKBUFFER;
[numthreads(64,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
uint oldval;
InterlockedAdd(OutputBuffer[ParticleIDs[tid.x].cellID],1,oldval);
}
Это нормально работает. Я не вижу здесь разницы, кроме того, что я использую 2 буфера, в которые пишу, вместо 1... любая помощь очень ценится!
Спасибо!