153 lines
4.3 KiB
Plaintext
153 lines
4.3 KiB
Plaintext
#version 440 core
|
|
|
|
layout(std430) buffer;
|
|
|
|
layout(set=0, binding=0) writeonly uniform image2D uOutValue;
|
|
layout(set=0, binding=1) writeonly uniform iimage2D uOutIndex;
|
|
layout(set=0, binding=2) uniform sampler2D uInput;
|
|
|
|
layout(set=0, binding=3) uniform constBuffer {
|
|
int rowSize;
|
|
int k;
|
|
int numRows;
|
|
int C4; // UP_DIV(rowSize, 4)
|
|
} uConst;
|
|
|
|
#define THREAD_NUMBER 128
|
|
#define LOCAL_K 8
|
|
#define CANDIDATE_NUMBER 1024
|
|
|
|
shared float sharedValue[CANDIDATE_NUMBER];
|
|
shared int sharedIndex[CANDIDATE_NUMBER];
|
|
|
|
layout(local_size_x = THREAD_NUMBER, local_size_y = 1, local_size_z = 1) in;
|
|
|
|
float readValue(int row, int idx) {
|
|
int c4 = idx >> 2;
|
|
int c = idx & 3;
|
|
vec4 v = texelFetch(uInput, ivec2(c4, row), 0);
|
|
if (c == 0) return v.x;
|
|
if (c == 1) return v.y;
|
|
if (c == 2) return v.z;
|
|
return v.w;
|
|
}
|
|
|
|
bool afterAsc(float aValue, int aIndex, float bValue, int bIndex) {
|
|
if (aValue > bValue) return true;
|
|
if (aValue < bValue) return false;
|
|
return aIndex > bIndex;
|
|
}
|
|
|
|
bool better(float aValue, int aIndex, float bValue, int bIndex) {
|
|
if (bIndex < 0) return true;
|
|
if (aIndex < 0) return false;
|
|
#ifdef SORT_DESC
|
|
if (aValue > bValue) return true;
|
|
if (aValue < bValue) return false;
|
|
#else
|
|
if (aValue < bValue) return true;
|
|
if (aValue > bValue) return false;
|
|
#endif
|
|
return aIndex < bIndex;
|
|
}
|
|
|
|
void main() {
|
|
int tid = int(gl_LocalInvocationID.x);
|
|
int row = int(gl_WorkGroupID.y);
|
|
|
|
if (tid >= THREAD_NUMBER || row >= uConst.numRows) {
|
|
return;
|
|
}
|
|
|
|
int rowSize = uConst.rowSize;
|
|
int k = uConst.k;
|
|
|
|
float initWorst = 3.402823466e+38;
|
|
float initBestWorst = -3.402823466e+38;
|
|
|
|
float localValue[LOCAL_K];
|
|
int localIndex[LOCAL_K];
|
|
#ifdef SORT_DESC
|
|
for (int i = 0; i < LOCAL_K; ++i) {
|
|
localValue[i] = initBestWorst;
|
|
localIndex[i] = -1;
|
|
}
|
|
#else
|
|
for (int i = 0; i < LOCAL_K; ++i) {
|
|
localValue[i] = initWorst;
|
|
localIndex[i] = -1;
|
|
}
|
|
#endif
|
|
|
|
for (int i = tid; i < rowSize; i += THREAD_NUMBER) {
|
|
float value = readValue(row, i);
|
|
if (!better(value, i, localValue[LOCAL_K - 1], localIndex[LOCAL_K - 1])) {
|
|
continue;
|
|
}
|
|
|
|
int insertPos = LOCAL_K;
|
|
for (int j = 0; j < LOCAL_K; ++j) {
|
|
if (better(value, i, localValue[j], localIndex[j])) {
|
|
insertPos = j;
|
|
break;
|
|
}
|
|
}
|
|
if (insertPos >= LOCAL_K) {
|
|
continue;
|
|
}
|
|
for (int j = LOCAL_K - 1; j > insertPos; --j) {
|
|
localValue[j] = localValue[j - 1];
|
|
localIndex[j] = localIndex[j - 1];
|
|
}
|
|
localValue[insertPos] = value;
|
|
localIndex[insertPos] = i;
|
|
}
|
|
|
|
int base = tid * LOCAL_K;
|
|
for (int i = 0; i < LOCAL_K; ++i) {
|
|
sharedValue[base + i] = localValue[i];
|
|
sharedIndex[base + i] = localIndex[i];
|
|
}
|
|
barrier();
|
|
|
|
for (int size = 2; size <= CANDIDATE_NUMBER; size <<= 1) {
|
|
for (int stride = size >> 1; stride > 0; stride >>= 1) {
|
|
for (int idx = tid; idx < CANDIDATE_NUMBER; idx += THREAD_NUMBER) {
|
|
int ixj = idx ^ stride;
|
|
if (ixj <= idx) {
|
|
continue;
|
|
}
|
|
bool up = ((idx & size) == 0);
|
|
#ifdef SORT_DESC
|
|
up = !up;
|
|
#endif
|
|
|
|
bool after = afterAsc(sharedValue[idx], sharedIndex[idx], sharedValue[ixj], sharedIndex[ixj]);
|
|
if (up == after) {
|
|
float tValue = sharedValue[idx];
|
|
sharedValue[idx] = sharedValue[ixj];
|
|
sharedValue[ixj] = tValue;
|
|
int tIndex = sharedIndex[idx];
|
|
sharedIndex[idx] = sharedIndex[ixj];
|
|
sharedIndex[ixj] = tIndex;
|
|
}
|
|
}
|
|
barrier();
|
|
}
|
|
}
|
|
|
|
if (tid == 0) {
|
|
int realK = min(k, rowSize);
|
|
for (int i = 0; i < realK; i += 4) {
|
|
vec4 values = vec4(0.0);
|
|
ivec4 indices = ivec4(0);
|
|
int count = min(4, realK - i);
|
|
for (int j = 0; j < count; ++j) {
|
|
values[j] = sharedValue[i + j];
|
|
indices[j] = sharedIndex[i + j];
|
|
}
|
|
imageStore(uOutValue, ivec2(i >> 2, row), values);
|
|
imageStore(uOutIndex, ivec2(i >> 2, row), indices);
|
|
}
|
|
}
|
|
} |