Skip to content

Instantly share code, notes, and snippets.

@gradbot
Last active September 28, 2020 17:04
Show Gist options
  • Save gradbot/7567a8d1c66fddfd3c7adea1cf03a18c to your computer and use it in GitHub Desktop.
Save gradbot/7567a8d1c66fddfd3c7adea1cf03a18c to your computer and use it in GitHub Desktop.
Algorithm to replace zeros with previous non zero value
// This algorithm replaces zeros with whatever number came before them in an array.
// This code assumes the total data size (c_dataSize) is a multiple of 1024 the modern thread group size limit.
// It's an exercise for the reader to support odd lengths. :)
// What should the behavior be if the very first element in the sequence starts with zero?
// Set lastValue initial value to determine that behavior.
RWTexture2D<float> data;
[numthreads(1024, 1, 1)]
void FirstPass(uint3 dtid : SV_DispatchThreadID)
{
const int chunkSize = c_dataSize / 1024;
const int startOfChunk = chunkSize * dtid.x;
const int endOfChunk = startOfChunk + chunkSize - 1;
int i = endOfChunk;
// Last element already non zero
if (data[i] != 0) return;
i--;
for (; i >= startOfChunk; i--)
{
if (data[i] != 0)
{
data[endOfChunk] = data[i];
return;
}
}
}
[numthreads(1, 1, 1)]
void SecondPass(uint3 dtid : SV_DispatchThreadID)
{
const int chunkSize = c_dataSize / 1024;
int lastValue = 0;
for (int i = chunkSize - 1; i < c_dataSize; i += chunkSize)
{
if (data[i] == 0)
{
data[i] = lastValue;
}
else
{
lastValue = data[i];
}
}
}
[numthreads(1024, 1, 1)]
void ThirdPass(uint3 dtid : SV_DispatchThreadID)
{
const int chunkSize = c_dataSize / 1024;
const int startOfChunk = chunkSize * dtid.x;
const int endOfChunk = startOfChunk + chunkSize - 1;
int lastValue = (dtid.x == 0 ? 0 : data[startOfChunk - 1]);
for (int i = startOfChunk; i <= endOfChunk; i++)
{
if (data[i] == 0)
{
data[i] = lastValue;
}
else
{
lastValue = data[i];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment