Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions Assets/PixelSorter.compute
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma kernel CS_VisualizeSpans
#pragma kernel CS_RGBtoSortValue
#pragma kernel CS_PixelSort
#pragma kernel CS_PixelSort2
#pragma kernel CS_Composite

half _LowThreshold, _HighThreshold;
Expand All @@ -25,6 +26,7 @@ Texture2D<half4> _ColorTex;
RWTexture2D<half4> _SortedBuffer;
RWTexture2D<half> _HSLBuffer;
RWTexture2D<half> _SpanBuffer;
Texture2D<half> _SpanBufferRO;

RWTexture2D<half4> _ClearBuffer;

Expand Down Expand Up @@ -304,6 +306,119 @@ void CS_PixelSort(uint3 id : SV_DISPATCHTHREADID) {
}
}

groupshared half gs_PixelSortCache2[2048];
groupshared uint gs_PixelSortIndices2[2048];

void compareAndSwap2(uint2 idx)
{
half c1 = gs_PixelSortCache2[idx.x];
half c2 = gs_PixelSortCache2[idx.y];

bool result = _ReverseSorting ? c1 > c2 : c1 < c2;

if (result)
{
half temp = gs_PixelSortCache2[idx.x];
gs_PixelSortCache2[idx.x] = gs_PixelSortCache2[idx.y];
gs_PixelSortCache2[idx.y] = temp;

uint tempIndex = gs_PixelSortIndices2[idx.x];
gs_PixelSortIndices2[idx.x] = gs_PixelSortIndices2[idx.y];
gs_PixelSortIndices2[idx.y] = tempIndex;
}
}

void flip2(uint h, uint t, uint spanLength)
{
uint q = ((2 * t) / h) * h;
uint half_h = h / 2;
uint2 indices = q + uint2(t % half_h, h - (t % half_h) - 1);

if (indices.y < spanLength)
compareAndSwap2(indices);
}

void disperse2(uint h, uint t, uint spanLength)
{
uint q = ((2 * t) / h) * h;
uint half_h = h / 2;
uint2 indices = q + uint2(t % half_h, (t % half_h) + half_h);

if (indices.y < spanLength)
compareAndSwap2(indices);
}

[numthreads(1024, 1, 1)]
void CS_PixelSort2(uint3 gid : SV_GroupID, uint tid : SV_GroupIndex)
{
const uint spanLength = _SpanBufferRO[gid.xy];

if (spanLength < 1)
return;

const uint2 direction = _HorizontalSorting ? uint2(1, 0) : uint2(0, 1);

const uint2 idx1 = gid.xy + 2 * tid * direction;
const uint2 idx2 = gid.xy + (2 * tid + 1) * direction;

if (2 * tid < spanLength)
{
gs_PixelSortCache2[2 * tid] = _HSLBuffer[idx1];
if (2 * tid + 1 < spanLength)
{
gs_PixelSortCache2[2 * tid + 1] = _HSLBuffer[idx2];
}
else
{
gs_PixelSortCache2[2 * tid + 1] = _ReverseSorting ? 1.0f : 0.0f;
}
}
else
{
gs_PixelSortCache2[2 * tid] = _ReverseSorting ? 1.0f : 0.0f;
}
gs_PixelSortIndices2[2 * tid] = 2 * tid;
gs_PixelSortIndices2[2 * tid + 1] = 2 * tid + 1;

uint n = 2048;
while (n / 2 >= spanLength && n / 2 >= 4)
{
n /= 2;
}

GroupMemoryBarrierWithGroupSync();
flip2(2, tid, spanLength);

[unroll(10)]
for (uint h = 4, cnt = 1; h <= n; h *= 2, cnt += 1)
{
GroupMemoryBarrierWithGroupSync();
flip2(h, tid, spanLength);

[unroll(cnt)]
for (uint hh = h / 2; hh > 1; hh /= 2)
{
GroupMemoryBarrierWithGroupSync();
disperse2(hh, tid, spanLength);
}
}
GroupMemoryBarrierWithGroupSync();

if (2 * tid < spanLength)
{
const uint2 idxSorted1 = gid.xy + gs_PixelSortIndices2[2 * tid] * direction;

_SortedBuffer[idx1] = _ColorBuffer[idxSorted1];

if (2 * tid + 1 < spanLength)
{
const uint2 idxSorted2 = gid.xy + gs_PixelSortIndices2[2 * tid + 1] * direction;

_SortedBuffer[idx2] = _ColorBuffer[idxSorted2];
}
}
}

[numthreads(8, 8, 1)]
void CS_Composite(uint3 id : SV_DISPATCHTHREADID) {
if (_Mask[id.xy] == 1) {
Expand Down
29 changes: 21 additions & 8 deletions Assets/PixelSorter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class PixelSorter : MonoBehaviour {

public bool visualizeSpans = false;

[Range(0, 1080)]
[Range(0, 2048)]
public int maxSpanLength = 1080;

[Range(0, 512)]
Expand All @@ -60,10 +60,13 @@ public enum SortMode {

public bool reverseSorting = false;

public bool improvedSorting = false;

private float animatedLowThreshold = 0.5f;
private float animatedHighThreshold = 0.5f;

private int createMaskPass, testSelectionSortPass, testBitonicSortPass, testCustomSortPass, clearBufferPass, indentifySpansPass, visualizeSpansPass, rgbToHslPass, pixelSortPass, compositePass;
private int createMaskPass, testSelectionSortPass, testBitonicSortPass, testCustomSortPass;
private int clearBufferPass, indentifySpansPass, visualizeSpansPass, rgbToHslPass, pixelSortPass, pixelSort2Pass, compositePass;

private RenderTexture maskTex, spanTex, colorTex, hslTex, sortedTex;

Expand Down Expand Up @@ -103,6 +106,7 @@ void OnEnable() {
visualizeSpansPass = pixelSorter.FindKernel("CS_VisualizeSpans");
rgbToHslPass = pixelSorter.FindKernel("CS_RGBtoSortValue");
pixelSortPass = pixelSorter.FindKernel("CS_PixelSort");
pixelSort2Pass = pixelSorter.FindKernel("CS_PixelSort2");
compositePass = pixelSorter.FindKernel("CS_Composite");

/*
Expand Down Expand Up @@ -198,12 +202,21 @@ private void OnRenderImage(RenderTexture source, RenderTexture destination) {

pixelSorter.Dispatch(rgbToHslPass, Mathf.CeilToInt(Screen.width / 8.0f), Mathf.CeilToInt(Screen.height / 8.0f), 1);

pixelSorter.SetTexture(pixelSortPass, "_HSLBuffer", hslTex);
pixelSorter.SetTexture(pixelSortPass, "_ColorBuffer", colorTex);
pixelSorter.SetTexture(pixelSortPass, "_SortedBuffer", sortedTex);
pixelSorter.SetTexture(pixelSortPass, "_SpanBuffer", spanTex);

pixelSorter.Dispatch(pixelSortPass, Screen.width, Screen.height, 1);
if (improvedSorting) {
pixelSorter.SetTexture(pixelSort2Pass, "_HSLBuffer", hslTex);
pixelSorter.SetTexture(pixelSort2Pass, "_ColorBuffer", colorTex);
pixelSorter.SetTexture(pixelSort2Pass, "_SortedBuffer", sortedTex);
pixelSorter.SetTexture(pixelSort2Pass, "_SpanBufferRO", spanTex);

pixelSorter.Dispatch(pixelSort2Pass, Screen.width, Screen.height, 1);
} else {
pixelSorter.SetTexture(pixelSortPass, "_HSLBuffer", hslTex);
pixelSorter.SetTexture(pixelSortPass, "_ColorBuffer", colorTex);
pixelSorter.SetTexture(pixelSortPass, "_SortedBuffer", sortedTex);
pixelSorter.SetTexture(pixelSortPass, "_SpanBuffer", spanTex);

pixelSorter.Dispatch(pixelSortPass, Screen.width, Screen.height, 1);
}

pixelSorter.SetTexture(compositePass, "_Mask", maskTex);
pixelSorter.SetTexture(compositePass, "_ColorBuffer", colorTex);
Expand Down