Files
2026-07-13 13:33:03 +08:00

105 lines
3.8 KiB
Plaintext

#version 440 core
layout(std430) buffer;
layout(std430) uniform;
layout(set=0, binding=0, rgba8ui) writeonly restrict highp uniform uimage2D uOutput;
layout(set=0, binding=1) uniform highp usampler2D uInput;
layout(set=0, binding=2) uniform highp usampler2D uKernel;
layout(set=0, binding=3) uniform highp isampler2D uBias;
layout(set=0, binding=4) readonly restrict uniform constBuffer {
ivec4 outputSize;
int kernelZero;
int inputZero;
int outputShiftBefore;
int outputMulti;
int outputShiftAfter;
int outputZero;
int minValue;
int maxValue;
int multiLength;
}uConst;
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main()
{
ivec3 pos = ivec3(gl_GlobalInvocationID);
if (pos.x < uConst.outputSize.x && pos.y < uConst.outputSize.y)
{
int kenerlY = pos.y + pos.z * uConst.outputSize.y;
int srcY = pos.x + pos.z * uConst.outputSize.x;
highp ivec4 bias = texelFetch(uBias, ivec2(pos.y, 0), 0);
highp ivec4 inputZero = ivec4(uConst.inputZero);
highp ivec4 kernelZero = ivec4(uConst.kernelZero);
highp ivec4 outputZero = ivec4(uConst.outputZero);
highp ivec4 outputMin = ivec4(uConst.minValue);
highp ivec4 outputMax = ivec4(uConst.maxValue);
highp ivec4 outputMulti = ivec4(uConst.outputMulti);
highp ivec4 o0 = bias;
highp ivec4 o1 = bias;
highp ivec4 o2 = bias;
highp ivec4 o3 = bias;
for (int k=0; k<uConst.multiLength; ++k)
{
ivec4 k0 = ivec4(texelFetch(uKernel, ivec2(4*k+0, kenerlY), 0)) - kernelZero;
ivec4 k1 = ivec4(texelFetch(uKernel, ivec2(4*k+1, kenerlY), 0)) - kernelZero;
ivec4 k2 = ivec4(texelFetch(uKernel, ivec2(4*k+2, kenerlY), 0)) - kernelZero;
ivec4 k3 = ivec4(texelFetch(uKernel, ivec2(4*k+3, kenerlY), 0)) - kernelZero;
ivec4 s0 = ivec4(texelFetch(uInput, ivec2(4*k+0, srcY), 0)) - inputZero;
ivec4 s1 = ivec4(texelFetch(uInput, ivec2(4*k+1, srcY), 0)) - inputZero;
ivec4 s2 = ivec4(texelFetch(uInput, ivec2(4*k+2, srcY), 0)) - inputZero;
ivec4 s3 = ivec4(texelFetch(uInput, ivec2(4*k+3, srcY), 0)) - inputZero;
o0 += k0 * s0.x;
o0 += k1 * s0.y;
o0 += k2 * s0.z;
o0 += k3 * s0.w;
o1 += k0 * s1.x;
o1 += k1 * s1.y;
o1 += k2 * s1.z;
o1 += k3 * s1.w;
o2 += k0 * s2.x;
o2 += k1 * s2.y;
o2 += k2 * s2.z;
o2 += k3 * s2.w;
o3 += k0 * s3.x;
o3 += k1 * s3.y;
o3 += k2 * s3.z;
o3 += k3 * s3.w;
}
o0 = o0 << uConst.outputShiftBefore;
o1 = o1 << uConst.outputShiftBefore;
o2 = o2 << uConst.outputShiftBefore;
o3 = o3 << uConst.outputShiftBefore;
ivec4 t0, t1, t2, t3;
imulExtended(o0, outputMulti, o0, t0);
o0 = o0 >> uConst.outputShiftAfter;
imulExtended(o1, outputMulti, o1, t1);
o1 = o1 >> uConst.outputShiftAfter;
imulExtended(o2, outputMulti, o2, t2);
o2 = o2 >> uConst.outputShiftAfter;
imulExtended(o3, outputMulti, o3, t3);
o3 = o3 >> uConst.outputShiftAfter;
o0 += outputZero;
o1 += outputZero;
o2 += outputZero;
o3 += outputZero;
o0 = clamp(o0, outputMin, outputMax);
o1 = clamp(o1, outputMin, outputMax);
o2 = clamp(o2, outputMin, outputMax);
o3 = clamp(o3, outputMin, outputMax);
imageStore(uOutput, ivec2(srcY, 4*pos.y+0), uvec4(o0));
imageStore(uOutput, ivec2(srcY, 4*pos.y+1), uvec4(o1));
imageStore(uOutput, ivec2(srcY, 4*pos.y+2), uvec4(o2));
imageStore(uOutput, ivec2(srcY, 4*pos.y+3), uvec4(o3));
}
}