#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.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)); } }