From c545ac089cecc154a86ba80b0b7f0f5558e6bd20 Mon Sep 17 00:00:00 2001 From: Tolmachev Dmitrii Date: Sun, 27 Sep 2020 21:04:34 +0200 Subject: [PATCH] VkFFT update to support big sequences Current system limits: (2^14, 2^15, 2^15) --- README.md | 1 + .../shaders/16384/vkFFT_single_c2c_16384.comp | 610 ++++ .../shaders/16384/vkFFT_single_c2c_16384.spv | Bin 0 -> 68772 bytes .../shaders/16384/vkFFT_single_c2r_16384.comp | 824 +++++ .../shaders/16384/vkFFT_single_c2r_16384.spv | Bin 0 -> 109532 bytes .../shaders/16384/vkFFT_single_r2c_16384.comp | 806 +++++ .../shaders/16384/vkFFT_single_r2c_16384.spv | Bin 0 -> 105604 bytes .../shaders/8192/vkFFT_single_c2c_8192.comp | 89 +- .../shaders/8192/vkFFT_single_c2c_8192.spv | Bin 34432 -> 39004 bytes .../8192/vkFFT_single_c2c_afterR2C.comp | 459 --- ...e_c2c_afterR2C_for_transposition_8192.comp | 824 ----- ...le_c2c_afterR2C_for_transposition_8192.spv | Bin 92948 -> 0 bytes .../8192/vkFFT_single_c2c_beforeC2R.comp | 454 --- ..._c2c_beforeC2R_for_transposition_8192.comp | 801 ----- ...e_c2c_beforeC2R_for_transposition_8192.spv | Bin 91296 -> 0 bytes ...FFT_single_c2c_for_transposition_8192.comp | 849 ----- ...kFFT_single_c2c_for_transposition_8192.spv | Bin 96272 -> 0 bytes .../shaders/8192/vkFFT_single_c2r_8192.comp | 70 +- .../shaders/8192/vkFFT_single_c2r_8192.spv | Bin 61212 -> 62168 bytes ...FFT_single_c2r_for_transposition_8192.comp | 692 ----- ...kFFT_single_c2r_for_transposition_8192.spv | Bin 87156 -> 0 bytes .../shaders/8192/vkFFT_single_r2c_8192.comp | 113 +- .../shaders/8192/vkFFT_single_r2c_8192.spv | Bin 58528 -> 65440 bytes ...FFT_single_r2c_for_transposition_8192.comp | 481 --- ...kFFT_single_r2c_for_transposition_8192.spv | Bin 65224 -> 0 bytes core/thirdparty/VkFFT/shaders/compile.bat | 28 - .../VkFFT/shaders/vkFFT_grouped_c2c.comp | 80 +- .../VkFFT/shaders/vkFFT_grouped_c2c.spv | Bin 54124 -> 49624 bytes .../vkFFT_grouped_convolution_1x1.comp | 73 +- .../shaders/vkFFT_grouped_convolution_1x1.spv | Bin 78032 -> 76360 bytes ..._grouped_convolution_nonsymmetric_2x2.comp | 71 +- ...T_grouped_convolution_nonsymmetric_2x2.spv | Bin 85184 -> 83244 bytes ..._grouped_convolution_nonsymmetric_3x3.comp | 71 +- ...T_grouped_convolution_nonsymmetric_3x3.spv | Bin 93588 -> 91648 bytes ...FFT_grouped_convolution_symmetric_2x2.comp | 73 +- ...kFFT_grouped_convolution_symmetric_2x2.spv | Bin 85088 -> 83148 bytes ...FFT_grouped_convolution_symmetric_3x3.comp | 75 +- ...kFFT_grouped_convolution_symmetric_3x3.spv | Bin 93492 -> 91552 bytes .../VkFFT/shaders/vkFFT_single_c2c.comp | 116 +- .../VkFFT/shaders/vkFFT_single_c2c.spv | Bin 54916 -> 48036 bytes .../shaders/vkFFT_single_c2c_afterR2C.comp | 485 --- .../shaders/vkFFT_single_c2c_afterR2C.spv | Bin 60816 -> 0 bytes .../shaders/vkFFT_single_c2c_beforeC2R.comp | 470 --- .../shaders/vkFFT_single_c2c_beforeC2R.spv | Bin 56716 -> 0 bytes .../shaders/vkFFT_single_c2c_strided.comp | 447 +++ .../shaders/vkFFT_single_c2c_strided.spv | Bin 0 -> 49040 bytes .../VkFFT/shaders/vkFFT_single_c2r.comp | 13 +- .../VkFFT/shaders/vkFFT_single_c2r.spv | Bin 58432 -> 58620 bytes .../shaders/vkFFT_single_convolution_1x1.comp | 129 +- .../shaders/vkFFT_single_convolution_1x1.spv | Bin 86268 -> 74108 bytes ...vkFFT_single_convolution_afterR2C_1x1.comp | 766 ----- .../vkFFT_single_convolution_afterR2C_1x1.spv | Bin 95944 -> 0 bytes ...convolution_afterR2C_nonsymmetric_2x2.comp | 800 ----- ..._convolution_afterR2C_nonsymmetric_2x2.spv | Bin 104468 -> 0 bytes ...convolution_afterR2C_nonsymmetric_3x3.comp | 827 ----- ..._convolution_afterR2C_nonsymmetric_3x3.spv | Bin 112552 -> 0 bytes ...le_convolution_afterR2C_symmetric_2x2.comp | 800 ----- ...gle_convolution_afterR2C_symmetric_2x2.spv | Bin 104372 -> 0 bytes ...le_convolution_afterR2C_symmetric_3x3.comp | 828 ----- ...gle_convolution_afterR2C_symmetric_3x3.spv | Bin 112456 -> 0 bytes ...T_single_convolution_nonsymmetric_2x2.comp | 129 +- ...FT_single_convolution_nonsymmetric_2x2.spv | Bin 88864 -> 80572 bytes ...T_single_convolution_nonsymmetric_3x3.comp | 111 +- ...FT_single_convolution_nonsymmetric_3x3.spv | Bin 96948 -> 88656 bytes ...kFFT_single_convolution_symmetric_2x2.comp | 127 +- ...vkFFT_single_convolution_symmetric_2x2.spv | Bin 88768 -> 80476 bytes ...kFFT_single_convolution_symmetric_3x3.comp | 136 +- ...vkFFT_single_convolution_symmetric_3x3.spv | Bin 96868 -> 88560 bytes .../VkFFT/shaders/vkFFT_single_r2c.comp | 13 +- .../VkFFT/shaders/vkFFT_single_r2c.spv | Bin 58784 -> 58972 bytes core/thirdparty/VkFFT/vkFFT.h | 2745 ++++++++++++----- 71 files changed, 5380 insertions(+), 11106 deletions(-) create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.comp create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.spv create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.comp create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.spv create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.comp create mode 100644 core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.spv delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.spv delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R_for_transposition_8192.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R_for_transposition_8192.spv delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_for_transposition_8192.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_for_transposition_8192.spv delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_for_transposition_8192.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_for_transposition_8192.spv delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_for_transposition_8192.comp delete mode 100644 core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_for_transposition_8192.spv delete mode 100644 core/thirdparty/VkFFT/shaders/compile.bat delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_afterR2C.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_afterR2C.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_beforeC2R.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_beforeC2R.spv create mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_strided.comp create mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_strided.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_1x1.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_1x1.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_2x2.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_2x2.spv delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_3x3.comp delete mode 100644 core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_3x3.spv diff --git a/README.md b/README.md index 4fe555609..c96503eb4 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Currently working:\ -regions with different parameters, periodic/open boundary conditions, freezing spins\ -passing standard problems #1-#4\ -Qt GUI - almost every parameter can be adjusted from there\ +-Max system sizes supported: (2^14, 2^15, 2^15)\ \ Not working yet (compared to current Spirit release version):\ -Methods, other than LLG\ diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.comp b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.comp new file mode 100644 index 000000000..76f69e424 --- /dev/null +++ b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.comp @@ -0,0 +1,610 @@ +#version 450 + +const float M_PI = 3.1415926535897932384626433832795; +const float M_SQRT1_2 = 0.70710678118654752440084436210485; + +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 +layout (constant_id = 4) const uint fft_dim = 2048; +layout (constant_id = 5) const bool inverse = false; +layout (constant_id = 6) const bool zeropad_0 = false; +layout (constant_id = 7) const bool zeropad_1 = false; +layout (constant_id = 8) const uint inputStride_0 = 1; +layout (constant_id = 9) const uint inputStride_1 = 1; +layout (constant_id = 10) const uint inputStride_2 = 1; +layout (constant_id = 11) const uint inputStride_3 = 1; +layout (constant_id = 12) const uint inputStride_4 = 1; +layout (constant_id = 13) const uint outputStride_0 = 1; +layout (constant_id = 14) const uint outputStride_1 = 1; +layout (constant_id = 15) const uint outputStride_2 = 1; +layout (constant_id = 16) const uint outputStride_3 = 1; +layout (constant_id = 17) const uint outputStride_4 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; +layout (constant_id = 21) const uint numStages = 1; +layout (constant_id = 22) const uint stageRadix_0 = 8; +layout (constant_id = 23) const uint stageRadix_1 = 8; +layout (constant_id = 24) const uint ratio_0 = 8; +layout (constant_id = 25) const uint ratio_1 = 8; +layout (constant_id = 26) const bool ratioDirection_0 = false; +layout (constant_id = 27) const bool ratioDirection_1 = true; +layout (constant_id = 28) const uint inputOffset = 0; +layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; + +layout(push_constant) uniform PushConsts +{ + uint coordinate; + uint batchID; +} consts; + + +layout(std430, binding = 0) buffer Data { + vec2 inputs[]; +}; + +layout(std430, binding = 1) buffer Data2 { + vec2 outputs[]; +}; +uint indexInput(uint index) { + return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3 + consts.batchID * inputStride_4; +} +uint indexOutput(uint index) { + return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + consts.coordinate * outputStride_3 + consts.batchID * outputStride_4; +} +uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { + return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); + +} +void radix2(inout vec2 values[2], vec2 w) { + vec2 temp; + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; +} + +void radix4(inout vec2 values[4],inout vec2 w) { + + //DIF 1st stage with double angle + vec2 temp; + temp.x=values[2].x*w.x-values[2].y*w.y; + temp.y=values[2].y*w.x+values[2].x*w.y; + values[2]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[1]-temp; + values[1]=values[1]+temp; + + //DIF 2nd stage with half angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; + + w = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[2]-temp; + values[2]=values[2]+temp; + + temp = values[1]; + values[1]=values[2]; + values[2]=temp; +} + +void radix8(inout vec2 values[8], inout vec2 w) { + //DIF 1st stage with quadruple angle + + vec2 temp; + temp.x=values[4].x*w.x-values[4].y*w.y; + temp.y=values[4].y*w.x+values[4].x*w.y; + values[4]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[5].x*w.x-values[5].y*w.y; + temp.y=values[5].y*w.x+values[5].x*w.y; + values[5]=values[1]-temp; + values[1]=values[1]+temp; + + temp.x=values[6].x*w.x-values[6].y*w.y; + temp.y=values[6].y*w.x+values[6].x*w.y; + values[6]=values[2]-temp; + values[2]=values[2]+temp; + + temp.x=values[7].x*w.x-values[7].y*w.y; + temp.y=values[7].y*w.x+values[7].x*w.y; + values[7]=values[3]-temp; + values[3]=values[3]+temp; + + //DIF 2nd stage with double angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[2].x*w.x-values[2].y*w.y; + temp.y=values[2].y*w.x+values[2].x*w.y; + values[2]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[1]-temp; + values[1]=values[1]+temp; + + vec2 iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[6].x*iw.x-values[6].y*iw.y; + temp.y=values[6].y*iw.x+values[6].x*iw.y; + values[6]=values[4]-temp; + values[4]=values[4]+temp; + + temp.x=values[7].x*iw.x-values[7].y*iw.y; + temp.y=values[7].y*iw.x+values[7].x*iw.y; + values[7]=values[5]-temp; + values[5]=values[5]+temp; + + //DIF 3rd stage with angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; + + iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[3].x*iw.x-values[3].y*iw.y; + temp.y=values[3].y*iw.x+values[3].x*iw.y; + values[3]=values[2]-temp; + values[2]=values[2]+temp; + + iw.x=(inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; + iw.y=(inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; + + temp.x=values[5].x*iw.x-values[5].y*iw.y; + temp.y=values[5].y*iw.x+values[5].x*iw.y; + values[5]=values[4]-temp; + values[4]=values[4]+temp; + + w = (inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); + + temp.x=values[7].x*w.x-values[7].y*w.y; + temp.y=values[7].y*w.x+values[7].x*w.y; + values[7]=values[6]-temp; + values[6]=values[6]+temp; + + temp = values[1]; + values[1]=values[4]; + values[4]=temp; + + temp = values[3]; + values[3]=values[6]; + values[6]=temp; + +} +const uint max_shared_vec2=4096; +const uint ratio = 4;// reg mem/shared mem +const uint tempSize = fft_dim/gl_WorkGroupSize.x; +shared vec2 sdata[max_shared_vec2]; + +void main() { + + vec2 temp0[8]; + vec2 temp1[8]; + vec2 temp2[8]; + vec2 temp3[8]; + uint stageSize=1; + float stageAngle=(inverse) ? -M_PI : M_PI; + if (zeropad_0&&(!inverse)){ + for(uint i = 0; i < 4; ++i){ + temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp2[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp3[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + } + for(uint i = 4; i < 8; ++i){ + temp0[i]=vec2(0,0); + temp1[i]=vec2(0,0); + temp2[i]=vec2(0,0); + temp3[i]=vec2(0,0); + } + }else { + for(uint i = 0; i < 8; ++i){ + temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp2[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp3[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + } + } + + if ((passID>0)&&(!inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp0[i].x*mult.x-temp0[i].y*mult.y, temp0[i].y*mult.x+temp0[i].x*mult.y); + temp0[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp1[i].x*mult.x-temp1[i].y*mult.y, temp1[i].y*mult.x+temp1[i].x*mult.y); + temp1[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp2[i].x*mult.x-temp2[i].y*mult.y, temp2[i].y*mult.x+temp2[i].x*mult.y); + temp2[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp3[i].x*mult.x-temp3[i].y*mult.y, temp3[i].y*mult.x+temp3[i].x*mult.y); + temp3[i]=res; + } + memoryBarrierShared(); + barrier(); + } + for (uint n=0; n < numStages-1; n++){//all stages but last are radix-8 + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + { + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp0, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp1, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp2, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp3, twiddleFactor); + } + memoryBarrierShared(); + barrier(); + + //all stages but last have no shifts larger than shared memory size - no need for swap buffer. Need to serialize thread groups in ratio_over_max amount of batches and exchange data + { + float stageNormalization = (inverse) ? 0.125 : 1.0; + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + uint blockInvocationID = (gl_LocalInvocationID.x) - stageInvocationID; + uint outputIndex = stageInvocationID + blockInvocationID * 8; + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp0[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp0[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp1[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp1[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp2[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp2[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp3[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp3[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + } + + stageSize=stageSize*8; + stageAngle=stageAngle*0.125f; + } + + + //last stage - arbitrary radix + //stageSize=4096; + { + vec2 sort0[8]; + vec2 sort1[8]; + for (uint t=0; t<2; t++){ + sort0[t*4]=temp0[t+4]; + sort0[t*4+1]=temp1[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4]=temp0[t+6]; + sort1[t*4+1]=temp1[t+6]; + } + for (uint t=0; t<2; t++) + sort0[t*4+2]=temp0[t+2]; + + for (uint t=0; t<2; t++) + temp0[t*4]=temp0[t]; + for (uint t=0; t<2; t++){ + temp0[t*4+1]=temp1[t]; + temp0[t*4+2]=temp2[t]; + temp0[t*4+3]=temp3[t]; + } + for (uint t=0; t<2; t++) + temp1[t*4+1]=temp1[t+2]; + for (uint t=0; t<2; t++){ + temp1[t*4]=sort0[t*4+2]; + temp1[t*4+2]=temp2[t+2]; + temp1[t*4+3]=temp3[t+2]; + } + + for (uint t=0; t<2; t++){ + sort0[t*4+2]=temp2[t+4]; + sort0[t*4+3]=temp3[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4+2]=temp2[t+6]; + sort1[t*4+3]=temp3[t+6]; + } + + for (uint t=0; t<8; t++){ + temp2[t]=sort0[t]; + temp3[t]=sort1[t]; + } + + } + + + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + i*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp0[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp0[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+2)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp1[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp1[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp2[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp2[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+6)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp3[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp3[i*4+j]=values[j]; + } + + } + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + + memoryBarrierShared(); + barrier(); + if ((passID>0)&&(inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp0[i].x*mult.x-temp0[i].y*mult.y, temp0[i].y*mult.x+temp0[i].x*mult.y); + temp0[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp1[i].x*mult.x-temp1[i].y*mult.y, temp1[i].y*mult.x+temp1[i].x*mult.y); + temp1[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp2[i].x*mult.x-temp2[i].y*mult.y, temp2[i].y*mult.x+temp2[i].x*mult.y); + temp2[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp3[i].x*mult.x-temp3[i].y*mult.y, temp3[i].y*mult.x+temp3[i].x*mult.y); + temp3[i]=res; + } + memoryBarrierShared(); + barrier(); + } + + if (zeropad_0&&(inverse)){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp0[i]*stageNormalization; + } + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp1[i]*stageNormalization; + } + + } + else{ + + float stageNormalization = (inverse) ? 0.25 : 1.0; + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp0[i]*stageNormalization; + } + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp1[i]*stageNormalization; + } + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp2[i]*stageNormalization; + } + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp3[i]*stageNormalization; + } + + } + +} diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.spv b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2c_16384.spv new file mode 100644 index 0000000000000000000000000000000000000000..ded98c54518432052ebbc5fe952cecc0912d7a68 GIT binary patch literal 68772 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 literal 0 HcmV?d00001 diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.comp b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.comp new file mode 100644 index 000000000..d5b8eb93b --- /dev/null +++ b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.comp @@ -0,0 +1,824 @@ +#version 450 + +const float M_PI = 3.1415926535897932384626433832795; +const float M_SQRT1_2 = 0.70710678118654752440084436210485; + +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 +layout (constant_id = 4) const uint fft_dim = 2048; +layout (constant_id = 5) const bool inverse = false; +layout (constant_id = 6) const bool zeropad_0 = false; +layout (constant_id = 7) const bool zeropad_1 = false; +layout (constant_id = 8) const uint inputStride_0 = 1; +layout (constant_id = 9) const uint inputStride_1 = 1; +layout (constant_id = 10) const uint inputStride_2 = 1; +layout (constant_id = 11) const uint inputStride_3 = 1; +layout (constant_id = 12) const uint inputStride_4 = 1; +layout (constant_id = 13) const uint outputStride_0 = 1; +layout (constant_id = 14) const uint outputStride_1 = 1; +layout (constant_id = 15) const uint outputStride_2 = 1; +layout (constant_id = 16) const uint outputStride_3 = 1; +layout (constant_id = 17) const uint outputStride_4 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; +layout (constant_id = 21) const uint numStages = 1; +layout (constant_id = 22) const uint stageRadix_0 = 8; +layout (constant_id = 23) const uint stageRadix_1 = 8; +layout (constant_id = 24) const uint ratio_0 = 8; +layout (constant_id = 25) const uint ratio_1 = 8; +layout (constant_id = 26) const bool ratioDirection_0 = false; +layout (constant_id = 27) const bool ratioDirection_1 = true; +layout (constant_id = 28) const uint inputOffset = 0; +layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; + +layout(push_constant) uniform PushConsts +{ + uint coordinate; + uint batchID; +} consts; + +layout(std430, binding = 0) buffer Data { + vec2 inputs[]; +}; + +layout(std430, binding = 1) buffer Data2 { + float outputs[]; +}; + +uint indexInput(uint index_x, uint index_y) { + return inputOffset + index_x * inputStride_0 + index_y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3 + consts.batchID * inputStride_4 ; +} +uint indexOutput(uint index) { + return outputOffset + index * outputStride_0 + 2*gl_GlobalInvocationID.y* outputStride_1 + 2*gl_GlobalInvocationID.z * outputStride_2 + 2*consts.coordinate * outputStride_3+ 2*consts.batchID * outputStride_4; +} + +uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { + + return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/4)); + + /*if (ratioDirection) + return ((pos >> ratio)+(pos & (1<>1)); + else + return (((pos)/(fft_dim>>1))+((pos)%(fft_dim>>1))*(1<0) { + for (uint i=0; i<4; i++){ + temp0[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i+4].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp3[i+4].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp0[i].x=(sdata[i*gl_WorkGroupSize.x-1].x-sdata[(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i].y=(sdata[i*gl_WorkGroupSize.x-1].y+sdata[(i+4)*gl_WorkGroupSize.x-1].x); + + } + for (uint i=0; i<4; i++){ + temp3[i+4].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp3[i+4].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp0[4].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp0[4].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + + vec2 temp[2]; + if (zeropad_1){ + temp[0]=inputs[indexInput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]; + temp[1]=inputs[indexInput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]; + } else { + temp[0]=inputs[indexInput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]; + temp[1]=inputs[indexInput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]; + + } + temp0[0].x=(temp[0].x-temp[1].y); + temp0[0].y=(temp[0].y+temp[1].x); + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp0[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp3[i].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp0[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp3[i].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp3[0].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp3[0].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + temp1[0].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp1[0].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp1[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i+4].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp2[i+4].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp1[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i+4].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp2[i+4].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp2[4].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp2[4].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + temp1[4].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp1[4].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + } + + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp1[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp2[i].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp1[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp2[i].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp2[0].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp2[0].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + } + memoryBarrierShared(); + barrier(); + + } + else{ + for (uint i=0; i<4; i++){ + sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sdata[4*gl_WorkGroupSize.x + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0) { + for (uint i=0; i<4; i++){ + temp0[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i+4].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp3[i+4].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp0[i].x=(sdata[i*gl_WorkGroupSize.x-1].x-sdata[(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i].y=(sdata[i*gl_WorkGroupSize.x-1].y+sdata[(i+4)*gl_WorkGroupSize.x-1].x); + + } + for (uint i=0; i<4; i++){ + temp3[i+4].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp3[i+4].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp0[4].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp0[4].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + + vec2 temp[2]; + if (zeropad_1){ + temp[0]=inputs[indexInput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]; + temp[1]=inputs[indexInput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]; + } else { + temp[0]=inputs[indexInput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]; + temp[1]=inputs[indexInput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]; + + } + temp0[0].x=(temp[0].x-temp[1].y); + temp0[0].y=(temp[0].y+temp[1].x); + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sdata[4*gl_WorkGroupSize.x + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+20)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp0[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp3[i].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp0[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp0[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp3[i].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp3[i].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp3[0].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp3[0].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + temp1[0].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp1[0].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sdata[4*gl_WorkGroupSize.x + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp1[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i+4].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp2[i+4].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp1[i].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i+4].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp2[i+4].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp2[4].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp2[4].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + temp1[4].x=(sdata[4*gl_WorkGroupSize.x-1].x-sdata[8*gl_WorkGroupSize.x-1].y); + temp1[4].y=(sdata[4*gl_WorkGroupSize.x-1].y+sdata[8*gl_WorkGroupSize.x-1].x); + + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+12)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sdata[4*gl_WorkGroupSize.x + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+(i+28)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + temp1[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i].x=(sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y); + temp2[i].y=(-sdata[4*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].y+sdata[8*gl_WorkGroupSize.x - (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x) - 1].x); + } + } else{ + for (uint i=1; i<4; i++){ + temp1[i+4].x=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].x-sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].y); + temp1[i+4].y=(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1].y+sdata[gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1].x); + temp2[i].x=(sdata[(4 - i)*gl_WorkGroupSize.x - 1].x+sdata[(8-i)*gl_WorkGroupSize.x - 1].y); + temp2[i].y=(-sdata[(4 - i)*gl_WorkGroupSize.x - 1].y+sdata[(8-i)*gl_WorkGroupSize.x - 1].x); + } + temp2[0].x=(sdata[4*gl_WorkGroupSize.x - 1].x+sdata[8*gl_WorkGroupSize.x - 1].y); + temp2[0].y=(-sdata[4*gl_WorkGroupSize.x - 1].y+sdata[8*gl_WorkGroupSize.x - 1].x); + + } + } + + + memoryBarrierShared(); + barrier(); + + uint stageSize=1; + float stageAngle=(inverse) ? -M_PI : M_PI; + + for (uint n=0; n < numStages-1; n++){//all stages but last are radix-8 + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + { + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp0, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp1, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp2, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp3, twiddleFactor); + } + memoryBarrierShared(); + barrier(); + + //all stages but last have no shifts larger than shared memory size - no need for swap buffer. Need to serialize thread groups in ratio_over_max amount of batches and exchange data + { + float stageNormalization = (inverse) ? 0.125 : 1.0; + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + uint blockInvocationID = (gl_LocalInvocationID.x) - stageInvocationID; + uint outputIndex = stageInvocationID + blockInvocationID * 8; + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp0[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp0[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp1[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp1[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp2[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp2[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp3[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp3[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + } + + stageSize=stageSize*8; + stageAngle=stageAngle*0.125f; + } + + + //last stage - arbitrary radix + //stageSize=4096; + { + vec2 sort0[8]; + vec2 sort1[8]; + for (uint t=0; t<2; t++){ + sort0[t*4]=temp0[t+4]; + sort0[t*4+1]=temp1[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4]=temp0[t+6]; + sort1[t*4+1]=temp1[t+6]; + } + for (uint t=0; t<2; t++) + sort0[t*4+2]=temp0[t+2]; + + for (uint t=0; t<2; t++) + temp0[t*4]=temp0[t]; + for (uint t=0; t<2; t++){ + temp0[t*4+1]=temp1[t]; + temp0[t*4+2]=temp2[t]; + temp0[t*4+3]=temp3[t]; + } + for (uint t=0; t<2; t++) + temp1[t*4+1]=temp1[t+2]; + for (uint t=0; t<2; t++){ + temp1[t*4]=sort0[t*4+2]; + temp1[t*4+2]=temp2[t+2]; + temp1[t*4+3]=temp3[t+2]; + } + + for (uint t=0; t<2; t++){ + sort0[t*4+2]=temp2[t+4]; + sort0[t*4+3]=temp3[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4+2]=temp2[t+6]; + sort1[t*4+3]=temp3[t+6]; + } + + for (uint t=0; t<8; t++){ + temp2[t]=sort0[t]; + temp3[t]=sort1[t]; + } + + } + + + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + i*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp0[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp0[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+2)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp1[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp1[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp2[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp2[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+6)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp3[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp3[i*4+j]=values[j]; + } + + } + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + + memoryBarrierShared(); + barrier(); + + if (zeropad_0){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=temp0[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=temp0[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=temp1[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)+ outputStride_1]=temp1[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + } + else{ + + float stageNormalization = (inverse) ? 0.25 : 1.0; + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=temp0[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=temp0[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=temp1[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)+ outputStride_1]=temp1[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x)]=temp2[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x)+ outputStride_1]=temp2[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x)]=temp3[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x)+ outputStride_1]=temp3[i].y*stageNormalization; + } + memoryBarrierShared(); + barrier(); + } + +} diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.spv b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_c2r_16384.spv new file mode 100644 index 0000000000000000000000000000000000000000..980b9ea23962ee7c08207a7376d98c992bc27f11 GIT binary patch literal 109532 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 K>zk9m9sPf0p$irO literal 0 HcmV?d00001 diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.comp b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.comp new file mode 100644 index 000000000..184b7e90b --- /dev/null +++ b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.comp @@ -0,0 +1,806 @@ +#version 450 + +const float M_PI = 3.1415926535897932384626433832795; +const float M_SQRT1_2 = 0.70710678118654752440084436210485; + +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 +layout (constant_id = 4) const uint fft_dim = 2048; +layout (constant_id = 5) const bool inverse = false; +layout (constant_id = 6) const bool zeropad_0 = false; +layout (constant_id = 7) const bool zeropad_1 = false; +layout (constant_id = 8) const uint inputStride_0 = 1; +layout (constant_id = 9) const uint inputStride_1 = 1; +layout (constant_id = 10) const uint inputStride_2 = 1; +layout (constant_id = 11) const uint inputStride_3 = 1; +layout (constant_id = 12) const uint inputStride_4 = 1; +layout (constant_id = 13) const uint outputStride_0 = 1; +layout (constant_id = 14) const uint outputStride_1 = 1; +layout (constant_id = 15) const uint outputStride_2 = 1; +layout (constant_id = 16) const uint outputStride_3 = 1; +layout (constant_id = 17) const uint outputStride_4 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; +layout (constant_id = 21) const uint numStages = 1; +layout (constant_id = 22) const uint stageRadix_0 = 8; +layout (constant_id = 23) const uint stageRadix_1 = 8; +layout (constant_id = 24) const uint ratio_0 = 8; +layout (constant_id = 25) const uint ratio_1 = 8; +layout (constant_id = 26) const bool ratioDirection_0 = false; +layout (constant_id = 27) const bool ratioDirection_1 = true; +layout (constant_id = 28) const uint inputOffset = 0; +layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; + +layout(push_constant) uniform PushConsts +{ + uint coordinate; + uint batchID; +} consts; + + +layout(std430, binding = 0) buffer Data { + float inputs[]; +}; + +layout(std430, binding = 1) buffer Data2 { + vec2 outputs[]; +}; +uint indexInput(uint index) { + return inputOffset+index * inputStride_0 + 2*gl_GlobalInvocationID.y * inputStride_1 + 2*gl_GlobalInvocationID.z * inputStride_2 + 2*consts.coordinate * inputStride_3 + 2*consts.batchID * inputStride_4 ; +} +uint indexOutput(uint index_x, uint index_y) { + return outputOffset+index_x * outputStride_0 + index_y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + consts.coordinate * outputStride_3+ consts.batchID * outputStride_4; +} +uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { + if (ratioDirection) + return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/4)); + else + return (((pos)/(fft_dim/4))+((pos)%(fft_dim/4))*(ratio)); + +} + +void radix2(inout vec2 values[2], vec2 w) { + vec2 temp; + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; +} + +void radix4(inout vec2 values[4],inout vec2 w) { + + //DIF 1st stage with double angle + vec2 temp; + temp.x=values[2].x*w.x-values[2].y*w.y; + temp.y=values[2].y*w.x+values[2].x*w.y; + values[2]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[1]-temp; + values[1]=values[1]+temp; + + //DIF 2nd stage with half angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; + + w = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[2]-temp; + values[2]=values[2]+temp; + + temp = values[1]; + values[1]=values[2]; + values[2]=temp; +} + +void radix8(inout vec2 values[8], inout vec2 w) { + //DIF 1st stage with quadruple angle + + vec2 temp; + temp.x=values[4].x*w.x-values[4].y*w.y; + temp.y=values[4].y*w.x+values[4].x*w.y; + values[4]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[5].x*w.x-values[5].y*w.y; + temp.y=values[5].y*w.x+values[5].x*w.y; + values[5]=values[1]-temp; + values[1]=values[1]+temp; + + temp.x=values[6].x*w.x-values[6].y*w.y; + temp.y=values[6].y*w.x+values[6].x*w.y; + values[6]=values[2]-temp; + values[2]=values[2]+temp; + + temp.x=values[7].x*w.x-values[7].y*w.y; + temp.y=values[7].y*w.x+values[7].x*w.y; + values[7]=values[3]-temp; + values[3]=values[3]+temp; + + //DIF 2nd stage with double angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[2].x*w.x-values[2].y*w.y; + temp.y=values[2].y*w.x+values[2].x*w.y; + values[2]=values[0]-temp; + values[0]=values[0]+temp; + + temp.x=values[3].x*w.x-values[3].y*w.y; + temp.y=values[3].y*w.x+values[3].x*w.y; + values[3]=values[1]-temp; + values[1]=values[1]+temp; + + vec2 iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[6].x*iw.x-values[6].y*iw.y; + temp.y=values[6].y*iw.x+values[6].x*iw.y; + values[6]=values[4]-temp; + values[4]=values[4]+temp; + + temp.x=values[7].x*iw.x-values[7].y*iw.y; + temp.y=values[7].y*iw.x+values[7].x*iw.y; + values[7]=values[5]-temp; + values[5]=values[5]+temp; + + //DIF 3rd stage with angle + w = normalize(w + vec2(1.0, 0.0)); + + temp.x=values[1].x*w.x-values[1].y*w.y; + temp.y=values[1].y*w.x+values[1].x*w.y; + values[1]=values[0]-temp; + values[0]=values[0]+temp; + + iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); + + temp.x=values[3].x*iw.x-values[3].y*iw.y; + temp.y=values[3].y*iw.x+values[3].x*iw.y; + values[3]=values[2]-temp; + values[2]=values[2]+temp; + + iw.x=(inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; + iw.y=(inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; + + temp.x=values[5].x*iw.x-values[5].y*iw.y; + temp.y=values[5].y*iw.x+values[5].x*iw.y; + values[5]=values[4]-temp; + values[4]=values[4]+temp; + + w = (inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); + + temp.x=values[7].x*w.x-values[7].y*w.y; + temp.y=values[7].y*w.x+values[7].x*w.y; + values[7]=values[6]-temp; + values[6]=values[6]+temp; + + temp = values[1]; + values[1]=values[4]; + values[4]=temp; + + temp = values[3]; + values[3]=values[6]; + values[6]=temp; + +} + +const uint max_shared_vec2=4096; +const uint ratio_over_max = 4;// reg mem/shared mem +const uint tempSize = fft_dim/gl_WorkGroupSize.x; +shared vec2 sdata[max_shared_vec2];// half real half imag + + +void main() { + + vec2 temp0[8]; + vec2 temp1[8]; + vec2 temp2[8]; + vec2 temp3[8]; + uint stageSize=1; + float stageAngle=(inverse) ? -M_PI : M_PI; + if (zeropad_0){ + for(uint j = 0; j < 8; ++j){ + temp0[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)]; + temp0[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)+inputStride_1]; + temp1[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)]; + temp1[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)+inputStride_1]; + } + for(uint j = 0; j < 8; ++j){ + temp2[j]=vec2(0,0); + temp3[j]=vec2(0,0); + } + }else { + for(uint j = 0; j < 8; ++j){ + temp0[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)]; + temp0[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)+inputStride_1]; + temp1[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)]; + temp1[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)+inputStride_1]; + temp2[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j+16)*gl_WorkGroupSize.x)]; + temp2[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j+16)*gl_WorkGroupSize.x)+inputStride_1]; + temp3[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j+24)*gl_WorkGroupSize.x)]; + temp3[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j+24)*gl_WorkGroupSize.x)+inputStride_1]; + } + } + + for (uint n=0; n < numStages-1; n++){//all stages but last are radix-8 + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + { + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp0, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp1, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp2, twiddleFactor); + } + { + uint stageInvocationID = (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + radix8(temp3, twiddleFactor); + } + memoryBarrierShared(); + barrier(); + + //all stages but last have no shifts larger than shared memory size - no need for swap buffer. Need to serialize thread groups in ratio_over_max amount of batches and exchange data + { + float stageNormalization = (inverse) ? 0.125 : 1.0; + uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); + uint blockInvocationID = (gl_LocalInvocationID.x) - stageInvocationID; + uint outputIndex = stageInvocationID + blockInvocationID * 8; + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp0[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp0[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp1[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp1[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp2[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp2[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + for(uint j = 0; j < 8; ++j){ + sdata[outputIndex+stageSize*j]=temp3[j]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + for (uint j=0; j<8; j++){ + temp3[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; + } + + memoryBarrierShared(); + barrier(); + + } + + stageSize=stageSize*8; + stageAngle=stageAngle*0.125f; + } + + + //last stage - arbitrary radix + //stageSize=4096; + { + vec2 sort0[8]; + vec2 sort1[8]; + for (uint t=0; t<2; t++){ + sort0[t*4]=temp0[t+4]; + sort0[t*4+1]=temp1[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4]=temp0[t+6]; + sort1[t*4+1]=temp1[t+6]; + } + for (uint t=0; t<2; t++) + sort0[t*4+2]=temp0[t+2]; + + for (uint t=0; t<2; t++) + temp0[t*4]=temp0[t]; + for (uint t=0; t<2; t++){ + temp0[t*4+1]=temp1[t]; + temp0[t*4+2]=temp2[t]; + temp0[t*4+3]=temp3[t]; + } + for (uint t=0; t<2; t++) + temp1[t*4+1]=temp1[t+2]; + for (uint t=0; t<2; t++){ + temp1[t*4]=sort0[t*4+2]; + temp1[t*4+2]=temp2[t+2]; + temp1[t*4+3]=temp3[t+2]; + } + + for (uint t=0; t<2; t++){ + sort0[t*4+2]=temp2[t+4]; + sort0[t*4+3]=temp3[t+4]; + } + for (uint t=0; t<2; t++){ + sort1[t*4+2]=temp2[t+6]; + sort1[t*4+3]=temp3[t+6]; + } + + for (uint t=0; t<8; t++){ + temp2[t]=sort0[t]; + temp3[t]=sort1[t]; + } + + } + + + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + i*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp0[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp0[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+2)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp1[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp1[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp2[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp2[i*4+j]=values[j]; + } + + } + for (uint i=0; i<2; i++){ + uint stageInvocationID = (gl_LocalInvocationID.x + (i+6)*gl_WorkGroupSize.x ) & (stageSize - 1u); + float angle = stageInvocationID * stageAngle; + vec2 twiddleFactor = vec2(cos(angle), sin(angle)); + vec2 values[4]; + for(uint j = 0; j < 4; ++j){ + values[j] = temp3[i*4+j]; + } + radix4(values, twiddleFactor); + for(uint j = 0; j < 4; ++j){ + temp3[i*4+j]=values[j]; + } + + } + { + vec2 sort0[8]; + vec2 sort1[8]; + for(uint j = 0; j < 2; ++j){ + sort0[j]=temp0[2+4*j]; + sort0[j+2]=temp1[2+4*j]; + + } + for(uint j = 0; j < 2; ++j){ + sort1[j]=temp0[3+4*j]; + sort1[j+2]=temp1[3+4*j]; + + } + for(uint j = 0; j < 2; ++j) + sort0[j+6]=temp0[4*j+1]; + + for(uint j = 0; j < 2; ++j) + temp0[j]=temp0[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+2]=temp1[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+4]=temp2[4*j]; + for(uint j = 0; j < 2; ++j) + temp0[j+6]=temp3[4*j]; + + for(uint j = 0; j < 2; ++j) + temp1[j+2]=temp1[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j]=sort0[j+6]; + for(uint j = 0; j < 2; ++j) + temp1[j+4]=temp2[4*j+1]; + for(uint j = 0; j < 2; ++j) + temp1[j+6]=temp3[4*j+1]; + + for(uint j = 0; j < 2; ++j){ + sort0[j+4]=temp2[2+4*j]; + sort0[j+6]=temp3[2+4*j]; + } + for(uint j = 0; j < 2; ++j){ + sort1[j+4]=temp2[3+4*j]; + sort1[j+6]=temp3[3+4*j]; + } + + for (uint j=0; j<8; j++){ + temp2[j]=sort0[j]; + temp3[j]=sort1[j];} + + } + + + //r2c decomp + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; + sdata[gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x]=temp3[i+4]*stageNormalization; + } + + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0) { + for (uint i=0; i<4; i++){ + temp0[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp0[i].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i+4].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + } else { + vec2 temp[2]; + temp[0].x=sdata[0].x; + temp[0].y=0; + temp[1].x=sdata[0].y; + temp[1].y=0; + if (zeropad_1){ + outputs[indexOutput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]=temp[0]; + outputs[indexOutput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*2*gl_NumWorkGroups.y)]=temp[1]; + } else { + outputs[indexOutput(2*gl_GlobalInvocationID.y, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]=temp[0]; + outputs[indexOutput(2*gl_GlobalInvocationID.y+1, gl_WorkGroupSize.y*gl_NumWorkGroups.y)]=temp[1]; + } + for (uint i=1; i<4; i++){ + temp0[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp0[i].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i+4].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i+4]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x==0) + { + temp0[4].x=0.5*(sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + temp0[4].y=0.5*(sdata[0].y-sdata[4*gl_WorkGroupSize.x].y); + temp3[4].x=0.5*(sdata[0].y+sdata[4*gl_WorkGroupSize.x].y); + temp3[4].y=0.5*(-sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x]=temp3[i]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0) { + for (uint i=0; i<4; i++){ + temp0[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp0[i+4].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + }else { + for (uint i=1; i<4; i++){ + temp0[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp0[i+4].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp3[i].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp1[i]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x==0) + { + temp1[0].x=0.5*(sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + temp1[0].y=0.5*(sdata[0].y-sdata[4*gl_WorkGroupSize.x].y); + temp3[0].x=0.5*(sdata[0].y+sdata[4*gl_WorkGroupSize.x].y); + temp3[0].y=0.5*(-sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x]=temp2[i+4]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0) { + for (uint i=0; i<4; i++){ + temp1[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp1[i].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i+4].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + }else { + for (uint i=1; i<4; i++){ + temp1[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp1[i].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i+4].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp1[i+4]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x==0) + { + temp1[4].x=0.5*(sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + temp1[4].y=0.5*(sdata[0].y-sdata[4*gl_WorkGroupSize.x].y); + temp2[4].x=0.5*(sdata[0].y+sdata[4*gl_WorkGroupSize.x].y); + temp2[4].y=0.5*(-sdata[0].x+sdata[4*gl_WorkGroupSize.x].x); + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<4; i++){ + float stageNormalization = (inverse) ? 0.25 : 1.0; + sdata[gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x]=temp2[i]*stageNormalization; + } + memoryBarrierShared(); + barrier(); + + if (gl_LocalInvocationID.x>0) { + for (uint i=0; i<4; i++){ + temp1[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp1[i+4].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + }else { + for (uint i=1; i<4; i++){ + temp1[i+4].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + temp1[i+4].y=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y-sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); + temp2[i].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); + } + temp0[0].x=(sdata[4*gl_WorkGroupSize.x].x); + temp0[0].y=0; + temp2[0].x=(sdata[4*gl_WorkGroupSize.x].y); + temp2[0].y=0; + } + //r2c save + if (ratioDirection_1){ + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + outputs[indexOutput((gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+12)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+20)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+28)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[i]; + } + } else{ + for (uint i=1; i<4; i++){ + outputs[indexOutput((gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+12)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+20)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[i]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+24)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[i+4]; + outputs[indexOutput((gl_LocalInvocationID.x+(i+28)*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[i]; + } + outputs[indexOutput((4*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[4]; + outputs[indexOutput((8*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[0]; + outputs[indexOutput((12*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp1[4]; + outputs[indexOutput((16*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp0[0]; + outputs[indexOutput((20*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[4]; + outputs[indexOutput((24*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp3[0]; + outputs[indexOutput((28*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[4]; + outputs[indexOutput((32*gl_WorkGroupSize.x-1), gl_GlobalInvocationID.y)]=temp2[0]; + + } + }else{ + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i]; + sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp3[i+4]; + } + } else{ + for (uint i=1; i<4; i++){ + sdata[positionShuffle(i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i]; + sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp3[i+4]; + } + sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp0[4]; + sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp3[4]; + } + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]=sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; + } + + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i+4]; + sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp3[i]; + } + } else{ + for (uint i=1; i<4; i++){ + sdata[positionShuffle((i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i+4]; + sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp3[i]; + } + sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp1[0]; + sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp3[0]; + } + + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+8*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]=sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i]; + sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp2[i+4]; + } + } else{ + for (uint i=1; i<4; i++){ + sdata[positionShuffle((i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i]; + sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp2[i+4]; + } + sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp1[4]; + sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp2[4]; + } + + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+16*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]=sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; + } + memoryBarrierShared(); + barrier(); + if (gl_LocalInvocationID.x>0){ + for (uint i=0; i<4; i++){ + sdata[positionShuffle(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i+4]; + sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp2[i]; + } + } else{ + for (uint i=1; i<4; i++){ + sdata[positionShuffle((i)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i+4]; + sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp2[i]; + } + sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp0[0]; + sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp2[0]; + } + + memoryBarrierShared(); + barrier(); + for (uint i=0; i<8; i++){ + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+24*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]=sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; + } + } +} diff --git a/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.spv b/core/thirdparty/VkFFT/shaders/16384/vkFFT_single_r2c_16384.spv new file mode 100644 index 0000000000000000000000000000000000000000..074fd52d3a145a384479533345ace865ce4e9200 GIT binary patch literal 105604 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 ZHMEUMj!S~e9EUXVY8tO?O#bfZ{{b?ViW~p{ literal 0 HcmV?d00001 diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.comp index 523e504cb..a9c6ff195 100644 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.comp +++ b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.comp @@ -3,10 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -20,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -32,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -199,21 +201,37 @@ void main() { uint stageSize=1; float stageAngle=(inverse) ? -M_PI : M_PI; if (zeropad_0&&(!inverse)){ - for(uint j = 0; j < 4; ++j){ - temp0[j]=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)]; - temp1[j]=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)]; + for(uint i = 0; i < 4; ++i){ + temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; } - for(uint j = 4; j < 8; ++j){ - temp0[j]=vec2(0,0); - temp1[j]=vec2(0,0); + for(uint i = 4; i < 8; ++i){ + temp0[i]=vec2(0,0); + temp1[i]=vec2(0,0); } }else { - for(uint j = 0; j < 8; ++j){ - temp0[j]=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)]; - temp1[j]=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)]; + for(uint i = 0; i < 8; ++i){ + temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; + temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]; } } + if ((passID>0)&&(!inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp0[i].x*mult.x-temp0[i].y*mult.y, temp0[i].y*mult.x+temp0[i].x*mult.y); + temp0[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(temp1[i].x*mult.x-temp1[i].y*mult.y, temp1[i].y*mult.x+temp1[i].x*mult.y); + temp1[i]=res; + } + memoryBarrierShared(); + barrier(); + } for (uint n=0; n < numStages-1; n++){//all stages but last are radix-8 { vec2 sort0[8]; @@ -367,18 +385,27 @@ void main() { memoryBarrierShared(); barrier(); - - if (zeropad_0&&(inverse)){ - float stageNormalization = (inverse) ? 0.5 : 1.0; - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; + if ((passID>0)&&(inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp0[i].x*mult.x-temp0[i].y*mult.y, temp0[i].y*mult.x+temp0[i].x*mult.y); + temp0[i]=res; + } + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x)*(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x))/float(fft_dim_full)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(temp1[i].x*mult.x-temp1[i].y*mult.y, temp1[i].y*mult.x+temp1[i].x*mult.y); + temp1[i]=res; } - memoryBarrierShared(); barrier(); + } + if (zeropad_0&&(inverse)){ + float stageNormalization = (inverse) ? 0.5 : 1.0; for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp0[i]*stageNormalization; } memoryBarrierShared(); barrier(); @@ -388,27 +415,13 @@ void main() { float stageNormalization = (inverse) ? 0.5 : 1.0; for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp0[i]*stageNormalization; } memoryBarrierShared(); barrier(); - - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp1[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x+(gl_WorkGroupID.x)*fft_dim)]=temp1[i]*stageNormalization; } memoryBarrierShared(); barrier(); diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_8192.spv index 1b8fb41491a155c9dadde925f525c4ddb00e69aa..333ed109b114b662f27fe346d67d374e0877291f 100644 GIT binary patch literal 39004 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
    F>zbWNdlHu) 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 literal 34432 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 diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C.comp deleted file mode 100644 index b727f08ac..000000000 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C.comp +++ /dev/null @@ -1,459 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout(push_constant) uniform PushConsts -{ - bool inverse; - bool zeropad[2]; - uint inputStride[5]; - uint outputStride[5]; - uint radixStride[3]; - uint numStages; - uint stageRadix[2]; - uint ratio[2]; - bool ratioDirection[2]; - uint inputOffset; - uint outputOffset; - uint coordinate; - uint batchID; -} consts; - - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; -uint indexInput(uint index) { - return consts.inputOffset+index * consts.inputStride[0] + gl_GlobalInvocationID.y * consts.inputStride[1] + gl_GlobalInvocationID.z * consts.inputStride[2] + consts.coordinate * consts.inputStride[3] + consts.batchID * consts.inputStride[4]; -} -uint indexOutput(uint index) { - return consts.outputOffset+index * consts.outputStride[0] + gl_GlobalInvocationID.y * consts.outputStride[1] + gl_GlobalInvocationID.z * consts.outputStride[2] + consts.coordinate * consts.outputStride[3] + consts.batchID * consts.outputStride[4]; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(consts.inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(consts.inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (consts.inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim]; - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - uint stageSize=1; - float stageAngle=(consts.inverse) ? -M_PI : M_PI; - if (consts.zeropad[0]){ - if (consts.ratioDirection[0]){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0]); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (consts.ratioDirection[0]){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, consts.coordinate)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, consts.coordinate)]; - } - } else{ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, consts.coordinate)]; - } - - } - memoryBarrierShared(); - barrier(); - - for (uint n=0; n < consts.numStages-1; n++){//all stages but last are radix-8 - { - vec2 sort0[8]; - for(uint j = 0; j < 4; ++j){ - sort0[j]=temp0[1+2*j]; - sort0[j+4]=temp1[1+2*j];} - - for(uint j = 0; j < 4; ++j) - temp0[j]=temp0[2*j]; - - for(uint j = 0; j < 4; ++j) - temp0[j+4]=temp1[2*j]; - - for (uint j=0; j<8; j++) - temp1[j]=sort0[j]; - } - { - uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); - float angle = stageInvocationID * stageAngle; - vec2 twiddleFactor = vec2(cos(angle), sin(angle)); - vec2 values[8]; - for(uint j = 0; j < 8; ++j){ - values[j] =temp0[j]; - } - radix8(values, twiddleFactor); - for(uint j = 0; j < 8; ++j){ - temp0[j]=values[j]; - - } - - } - { - - uint stageInvocationID = (gl_LocalInvocationID.+gl_WorkGroupSize.x) & (stageSize - 1u); - float angle = stageInvocationID * stageAngle; - vec2 twiddleFactor = vec2(cos(angle), sin(angle)); - vec2 values[8]; - for(uint j = 0; j < 8; ++j){ - values[j] =temp1[j]; - } - radix8(values, twiddleFactor); - for(uint j = 0; j < 8; ++j){ - temp1[j]=values[j]; - - } - - } - memoryBarrierShared(); - barrier(); - - //all stages but last have no shifts larger than shared memory size - no need for swap buffer. Need to serialize thread groups in ratio amount of batches and exchange data - { - float stageNormalization = (consts.inverse) ? 0.125 : 1.0; - uint stageInvocationID = (gl_LocalInvocationID.x) & (stageSize - 1u); - uint blockInvocationID = (gl_LocalInvocationID.x) - stageInvocationID; - uint outputIndex = stageInvocationID + blockInvocationID * 8; - for(uint j = 0; j < 8; ++j){ - sdata[outputIndex+stageSize*j]=temp0[j]*stageNormalization; - } - memoryBarrierShared(); - barrier(); - - for (uint j=0; j<8; j++){ - temp0[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; - } - - memoryBarrierShared(); - barrier(); - - for(uint j = 0; j < 8; ++j){ - sdata[outputIndex+stageSize*j]=temp1[j]*stageNormalization; - } - memoryBarrierShared(); - barrier(); - - for (uint j=0; j<8; j++){ - temp1[j] = sdata[(gl_LocalInvocationID.x)+gl_WorkGroupSize.x*j]; - } - - memoryBarrierShared(); - barrier(); - - } - - stageSize=stageSize*8; - stageAngle=stageAngle/8.0f; - } - - - //last stage - arbitrary radix - //stageSize=4096; - { - vec2 sort0[8]; - for (uint t=0; t<4; t++){ - sort0[t*2]=temp0[t]; - sort0[t*2+1]=temp1[t]; - } - for (uint t=0; t<4; t++){ - temp0[t]=sort0[t]; - temp1[t]=sort0[t+4]; - } - for (uint t=0; t<4; t++){ - sort0[t*2]=temp0[t+4]; - sort0[t*2+1]=temp1[t+4]; - } - for (uint t=0; t<4; t++) - temp0[t+4]=temp1[t]; - - for (uint t=0; t<8; t++) - temp1[t]=sort0[t]; - - - } - - - for (uint i=0; i<4; i++){ - uint stageInvocationID = (gl_LocalInvocationID.x + i*gl_WorkGroupSize.x ) & (stageSize - 1u); - float angle = stageInvocationID * stageAngle; - vec2 twiddleFactor = vec2(cos(angle), sin(angle)); - - vec2 values[2]; - for(uint j = 0; j < 2; ++j){ - values[j] = temp0[i*2+j]; - } - radix2(values, twiddleFactor); - for(uint j = 0; j < 2; ++j){ - temp0[i*2+j]=values[j]; - } - - } - for (uint i=0; i<4; i++){ - uint stageInvocationID = (gl_LocalInvocationID.x + (i+4)*gl_WorkGroupSize.x ) & (stageSize - 1u); - float angle = stageInvocationID * stageAngle; - vec2 twiddleFactor = vec2(cos(angle), sin(angle)); - vec2 values[2]; - for(uint j = 0; j < 2; ++j){ - values[j] = temp1[i*2+j]; - } - radix2(values, twiddleFactor); - for(uint j = 0; j < 2; ++j){ - temp1[i*2+j]=values[j]; - } - - } - { - vec2 sort0[8]; - for (uint t=0; t<4; t++){ - sort0[t]=temp0[t*2+1]; - sort0[t+4]=temp1[t*2+1]; - } - for (uint t=0; t<4; t++) - temp0[t]=temp0[t*2]; - - for (uint t=0; t<4; t++) - temp0[t+4]=temp1[t*2]; - - for (uint t=0; t<8; t++) - temp1[t]=sort0[t]; - - } - memoryBarrierShared(); - barrier(); - - if (consts.zeropad[0]&&(consts.inverse)){ - float stageNormalization = (consts.inverse) ? 0.5 : 1.0; - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; - } - memoryBarrierShared(); - barrier(); - } - else{ - - float stageNormalization = (consts.inverse) ? 0.5 : 1.0; - - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp1[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; - } - memoryBarrierShared(); - barrier(); - } - -} diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.comp deleted file mode 100644 index 0de250d38..000000000 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.comp +++ /dev/null @@ -1,824 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; -uint indexInput(uint index_x, uint index_y) { - return inputOffset+index_x * inputStride_0 + index_y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3 + consts.batchID * inputStride_4; -} -uint indexOutput(uint index_x, uint index_y) { - return outputOffset+index_x * outputStride_0 + index_y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + consts.coordinate * outputStride_3 + consts.batchID * outputStride_4; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -const uint max_shared_vec2=4096; -const uint last_ratio = 2;// reg mem/shared mem -const uint tempSize = fft_dim/gl_WorkGroupSize.x; -shared vec2 sdata[max_shared_vec2];// half real half imag - -void main() { - vec2 temp0[8]; - vec2 temp1[8]; - - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - vec2 sort0[8]; - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - if (gl_LocalInvocationID.y>0) - return; - for (uint i=0; i<4; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - for (uint i=4; i<8; i++){ - temp0[i]=vec2(0,0); - temp1[i]=vec2(0,0); - - } - } - } else{ - for (uint i=0; i<4; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - for (uint i=4; i<8; i++){ - temp0[i]=vec2(0,0); - temp1[i]=vec2(0,0); - - } - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - vec2 sort0[8]; - for (uint i=0; i<8; i++){ - sort0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - - } - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp0[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - if (gl_LocalInvocationID.y>0) - return; - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - } else{ - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]=temp0[i]; - } - - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=(inverse) ? -M_PI : M_PI; - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (n= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - } - -} diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.spv deleted file mode 100644 index 5c4deee32c05101695cc2fb69df1e157e7711824..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92948 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ɱ)21P!7p93!U$GO<*VY#bg&T>88T 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 RHEz(vt7*KpG5ODq{tpq_c5DCu diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R.comp deleted file mode 100644 index bb5b910ef..000000000 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R.comp +++ /dev/null @@ -1,454 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout(push_constant) uniform PushConsts -{ - bool inverse; - bool zeropad[2]; - uint inputStride[4]; - uint outputStride[4]; - uint radixStride[3]; - uint numStages; - uint stageRadix[2]; - uint ratio[2]; - bool ratioDirection[2]; - uint inputOffset; - uint outputOffset; - uint coordinate; -} consts; - - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; -uint indexInput(uint index, uint coordinate) { - return consts.inputOffset+index * consts.inputStride[0] + gl_GlobalInvocationID.y * consts.inputStride[1] + gl_GlobalInvocationID.z * consts.inputStride[2] + coordinate * consts.inputStride[3]; -} -uint indexOutput(uint index, uint coordinate) { - return consts.outputOffset+index * consts.outputStride[0] + gl_GlobalInvocationID.y * consts.outputStride[1] + gl_GlobalInvocationID.z * consts.outputStride[2] + coordinate * consts.outputStride[3]; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} - -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(consts.inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(consts.inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (consts.inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim]; - -void main() { - - if ((gl_WorkGroupID.y == gl_NumWorkGroups.y-1)&& (gl_LocalInvocationID.y>0)) - return; - - if (consts.ratioDirection[0]){ - for (uint i=0; i<8; i++) - sdata[positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0])]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.coordinate)]; - - }else{ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, consts.coordinate)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, consts.coordinate)]; - } - - - memoryBarrierShared(); - barrier(); - - vec2 temp[8]; - uint stageSize=1; - float stageAngle=(consts.inverse) ? -M_PI : M_PI; - //0-numStages stage - - for (uint n=0; n < consts.numStages; n++){ - uint current_radix = (n0)) - return; - - - vec2 temp0[8]; - vec2 temp1[8]; - - - if (ratioDirection_0){ - vec2 sort0[8]; - for (uint i=0; i<8; i++){ - sort0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - - } - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp0[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]=temp0[i]; - } - - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=(inverse) ? -M_PI : M_PI; - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (n= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<4; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<4; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=temp0[i]; - for (uint i=0; i<4; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]=temp1[i]; - } - - } - } else { - if (ratioDirection_1){ - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=temp0[i]; - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]=temp1[i]; - } - else{ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=temp0[i]; - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]=temp1[i]; - } - - } - } -} diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R_for_transposition_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_beforeC2R_for_transposition_8192.spv deleted file mode 100644 index d4e13a3f12dc962eb8565608d060c1b6e8c42874..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91296 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 taPp~9JMpWP_= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<4; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - for (uint i=0; i<4; i++){ - temp0[i+4]=vec2(0,0); - temp1[i+4]=vec2(0,0); - - } - } - } else { - if (ratioDirection_0){ - vec2 sort0[8]; - for (uint i=0; i<8; i++){ - sort0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - - } - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp0[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]=temp0[i]; - } - - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=(inverse) ? -M_PI : M_PI; - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (n= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<4; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - } - } else { - if (ratioDirection_1){ - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=temp0[i]; - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]=temp1[i]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - } - } - - - -} diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_for_transposition_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2c_for_transposition_8192.spv deleted file mode 100644 index 1b84df799f0173a73bb5495560d8fa7e637e8cd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96272 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 P7EQdG#%mjszdQOLxwHKQ diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.comp index 34fe1a701..85b0a25d9 100644 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.comp +++ b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -55,7 +58,10 @@ uint indexOutput(uint index) { uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/4)); + if (ratioDirection) + return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/2)); + else + return (((pos)/(fft_dim/2))+((pos)%(fft_dim/2))*(ratio)); /*if (ratioDirection) return ((pos >> ratio)+(pos & (1<>1)); @@ -206,8 +212,19 @@ void main() { //c2r regroup if (ratioDirection_0){ + vec2 sort0[8]; + vec2 sort1[8]; for (uint i=0; i<8; i++){ - sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sort0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + sort1[i]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + } + for (uint i=0; i<8; i++){ + uint pos= positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); + if (pos < fft_dim/4) + sdata[pos]=sort0[i]; + pos= positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); + if ((pos >= fft_dim/2)&&(pos < 3*fft_dim/4)) + sdata[pos-fft_dim/4]=sort1[i]; } memoryBarrierShared(); @@ -248,7 +265,13 @@ void main() { memoryBarrierShared(); barrier(); for (uint i=0; i<8; i++){ - sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]; + uint pos= positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); + if ((pos >= fft_dim/4) && (pos < fft_dim/2)) + sdata[pos-fft_dim/4]=sort0[i]; + pos= positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); + if (pos >= 3*fft_dim/4) + sdata[pos-fft_dim/2]=sort1[i]; + } memoryBarrierShared(); @@ -503,16 +526,10 @@ void main() { if (zeropad_0){ float stageNormalization = (inverse) ? 0.5 : 1.0; - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x; - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=temp0[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=temp0[i].y*stageNormalization; } memoryBarrierShared(); barrier(); @@ -521,30 +538,17 @@ void main() { float stageNormalization = (inverse) ? 0.5 : 1.0; - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp0[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x; - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=temp0[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+ outputStride_1]=temp0[i].y*stageNormalization; } memoryBarrierShared(); barrier(); - - for (uint i=0; i<8; i++){ - sdata[gl_LocalInvocationID.x + i*gl_WorkGroupSize.x]=temp1[i]*stageNormalization; - } - - memoryBarrierShared(); - barrier(); for (uint i=0; i<8; i++){ - outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x; - outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)+ outputStride_1]=sdata[(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y; + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)]=temp1[i].x*stageNormalization; + outputs[indexOutput(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x)+ outputStride_1]=temp1[i].y*stageNormalization; } memoryBarrierShared(); barrier(); diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_8192.spv index 9d4adfb624b0a77ac8c320a30437d2443eadb630..e99f37617dc8dd95da001356a9b503cd0f83af3e 100644 GIT binary patch literal 62168 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 OYmwi&V;08{JA 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 UZvmG%-dgz^Q-8TW`Lm<{4-Od&DgXcg diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_for_transposition_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_for_transposition_8192.comp deleted file mode 100644 index 8a54426eb..000000000 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_c2r_for_transposition_8192.comp +++ /dev/null @@ -1,692 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout(push_constant) uniform PushConsts -{ - bool inverse; - bool zeropad[2]; - uint inputStride[5]; - uint outputStride[5]; - uint radixStride[3]; - uint numStages; - uint stageRadix[2]; - uint ratio[2]; - bool ratioDirection[2]; - uint inputOffset; - uint outputOffset; - uint coordinate; - uint batchID; -} consts; - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - float outputs[]; -}; -uint indexInput(uint index_x, uint index_y) { - return consts.inputOffset+index_x * consts.inputStride[0] + index_y * consts.inputStride[1] + gl_GlobalInvocationID.z * consts.inputStride[2] + consts.coordinate * consts.inputStride[3]+ consts.batchID * consts.inputStride[4] ; -} -uint indexOutput(uint index_x, uint index_y) { - return consts.outputOffset+index_x * consts.outputStride[0] + 2*index_y * consts.outputStride[1] + 2*gl_GlobalInvocationID.z * consts.outputStride[2] + 2*consts.coordinate * consts.outputStride[3] + 2*consts.batchID * consts.outputStride[4]; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - if (ratioDirection) - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/2)); - else - return (((pos)/(fft_dim/2))+((pos)%(fft_dim/2))*(ratio)); -} - -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(consts.inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(consts.inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (consts.inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -const uint max_shared_vec2=4096; -const uint last_ratio = 2;// reg mem/shared mem -const uint tempSize = fft_dim/gl_WorkGroupSize.x; -shared vec2 sdata[max_shared_vec2];// half real half imag - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - - //c2r regroup - if (consts.ratioDirection[0]){ - vec2 sort0[8]; - for (uint i=0; i<8; i++){ - sort0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - - } - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0]); - - if (pos < max_shared_vec2) - sdata[pos]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0]); - - if (pos < max_shared_vec2) - sdata[pos]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp0[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0]); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=sort0[i]; - - pos=positionShuffle(max_shared_vec2+8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, consts.ratio[0], consts.ratioDirection[0]); - - if (pos >= max_shared_vec2) - sdata[pos-max_shared_vec2]=temp1[i]; - } - memoryBarrierShared(); - barrier(); - - for (uint i=0; i<8; i++){ - temp1[i]=sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; - } - }else{ - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - - for (uint i=0; i<4; i++){ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + 1+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x=(temp0[i].x-temp0[i+4].y); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + 1+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y=(temp0[i].y+temp0[i+4].x); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + fft_dim-1-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x=(temp0[i].x+temp0[i+4].y); - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + fft_dim-1-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y=(-temp0[i].y+temp0[i+4].x); - } - - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=(consts.inverse) ? -M_PI : M_PI; - - //0-numStages stage - for (uint n=0; n < consts.numStages; n++){ - uint current_radix = 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 P>*CckUfY=bJGK7>1S4zv diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.comp index 38134b89e..84a0dd78b 100644 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.comp +++ b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -208,14 +211,11 @@ void main() { uint stageSize=1; float stageAngle=(inverse) ? -M_PI : M_PI; if (zeropad_0){ - for(uint j = 0; j < 4; ++j){ + for(uint j = 0; j < 8; ++j){ temp0[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)]; temp0[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j)*gl_WorkGroupSize.x)+inputStride_1]; - temp1[j].x=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)]; - temp1[j].y=inputs[indexInput(gl_LocalInvocationID.x+(j+8)*gl_WorkGroupSize.x)+inputStride_1]; } - for(uint j = 4; j < 8; ++j){ - temp0[j]=vec2(0,0); + for(uint j = 0; j < 8; ++j){ temp1[j]=vec2(0,0); } @@ -456,9 +456,9 @@ void main() { temp1[i].x=0.5*(sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].y+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].y); temp1[i].y=0.5*(-sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x].x+sdata[8*gl_WorkGroupSize.x-(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)].x); } - temp1[0].x=0.5*(sdata[4*gl_WorkGroupSize.x].y+sdata[4*gl_WorkGroupSize.x].y); + temp1[0].x=(sdata[4*gl_WorkGroupSize.x].y); temp1[0].y=0; - temp0[0].x=0.5*(sdata[4*gl_WorkGroupSize.x].y+sdata[4*gl_WorkGroupSize.x].y); + temp0[0].x=(sdata[4*gl_WorkGroupSize.x].x); temp0[0].y=0; } @@ -490,16 +490,47 @@ void main() { }else{ if (gl_LocalInvocationID.x>0){ for (uint i=0; i<4; i++){ - sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i]; - sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i+4]; + uint pos=positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[i]; + pos=positionShuffle(gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[i]; } } else{ for (uint i=1; i<4; i++){ - sdata[positionShuffle(i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i]; - sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i+4]; + uint pos=positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[i]; + pos=positionShuffle(gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[i]; } - sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp0[4]; - sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp1[4]; + uint pos=positionShuffle(4*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[4]; + pos=positionShuffle(12*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[4]; + pos=positionShuffle(8*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp0[0]; + pos=positionShuffle(16*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos < max_shared_vec2) + sdata[pos]=temp1[0]; + } memoryBarrierShared(); barrier(); @@ -507,22 +538,54 @@ void main() { outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, gl_GlobalInvocationID.y)]=sdata[gl_LocalInvocationID.x+i*gl_WorkGroupSize.x]; } + memoryBarrierShared(); barrier(); + if (gl_LocalInvocationID.x>0){ for (uint i=0; i<4; i++){ - sdata[positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i+4]; - sdata[positionShuffle(gl_LocalInvocationID.x+(i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i]; + uint pos=positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[i]; + pos=positionShuffle(gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[i]; } } else{ for (uint i=1; i<4; i++){ - sdata[positionShuffle(i*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp0[i+4]; - sdata[positionShuffle((i+8)*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1)]=temp1[i]; + uint pos=positionShuffle(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[i]; + pos=positionShuffle(gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[i+4]; + pos=positionShuffle(max_shared_vec2+gl_LocalInvocationID.x+(i+4)*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[i]; } - sdata[positionShuffle((4*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp0[0]; - sdata[positionShuffle((12*gl_WorkGroupSize.x-1), ratio_1, ratioDirection_1)]=temp1[0]; + uint pos=positionShuffle(4*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[4]; + pos=positionShuffle(12*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[4]; + pos=positionShuffle(8*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp0[0]; + pos=positionShuffle(16*gl_WorkGroupSize.x-1, ratio_1, ratioDirection_1); + if (pos >= max_shared_vec2) + sdata[pos-max_shared_vec2]=temp1[0]; + } - memoryBarrierShared(); barrier(); for (uint i=0; i<8; i++){ diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.spv b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_8192.spv index 7bfcdf3c7cac05891fedb32adaed510fab4e7250..553323f7eb0f42d70f8b519d41a93f8ca985f30f 100644 GIT binary patch literal 65440 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 Xxju=1Ke){CfyUpM`pfmnpB?=_rOzo@ diff --git a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_for_transposition_8192.comp b/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_for_transposition_8192.comp deleted file mode 100644 index 9bd2b43fe..000000000 --- a/core/thirdparty/VkFFT/shaders/8192/vkFFT_single_r2c_for_transposition_8192.comp +++ /dev/null @@ -1,481 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout(push_constant) uniform PushConsts -{ - bool inverse; - bool zeropad[2]; - uint inputStride[5]; - uint outputStride[5]; - uint radixStride[3]; - uint numStages; - uint stageRadix[2]; - uint ratio[2]; - bool ratioDirection[2]; - uint inputOffset; - uint outputOffset; - uint coordinate; - uint batchID; -} consts; - - -layout(std430, binding = 0) buffer Data { - float inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; -uint indexInput(uint index) { - return consts.inputOffset+index * consts.inputStride[0] + 2*gl_GlobalInvocationID.y * consts.inputStride[1] + 2*gl_GlobalInvocationID.z * consts.inputStride[2] + 2*consts.coordinate * consts.inputStride[3] + 2*consts.batchID * consts.inputStride[4] ; -} -uint indexOutput(uint index_x, uint index_y) { - return consts.outputOffset+index_x * consts.outputStride[0] + index_y * consts.outputStride[1] + gl_GlobalInvocationID.z * consts.outputStride[2] + consts.coordinate * consts.outputStride[3]+ consts.batchID * consts.outputStride[4]; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - if (ratioDirection) - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim/2)); - else - return (((pos)/(fft_dim/2))+((pos)%(fft_dim/2))*(ratio)); -} - -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (consts.inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(consts.inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(consts.inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (consts.inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -const uint max_shared_vec2=4096; -const uint last_ratio = 2;// reg mem/shared mem -const uint tempSize = fft_dim/gl_WorkGroupSize.x; -shared vec2 sdata[max_shared_vec2];// half real half imag - -void main() { - vec2 temp0[8]; - vec2 temp1[8]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x].x=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + gl_LocalInvocationID.x].y=inputs[indexInput(gl_LocalInvocationID.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)+consts.inputStride[1]]; - if (consts.zeropad[0]){ - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)].x=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)].y=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)].x=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)].y=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)].x=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)].y=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)].x=0; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)].y=0; - } else { - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)+consts.inputStride[1]]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)].x=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - sdata[8*gl_WorkGroupSize.x*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)].y=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)+consts.inputStride[1]]; - } - if (consts.zeropad[0]){ - for (uint i=0; i<4; i++){ - temp0[i].x=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; - temp0[i].y=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)+consts.inputStride[1]]; - temp1[i].x=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x)]; - temp1[i].y=inputs[indexInput(gl_LocalInvocationID.x+(i+16)*gl_WorkGroupSize.x)+consts.inputStride[1]]; - } - } else{ - for (uint i=0; i<8; i++){ - temp0[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y)]; - temp1[i]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 2*gl_WorkGroupSize.y * gl_WorkGroupID.y + gl_LocalInvocationID.y + gl_WorkGroupSize.y)]; - } - } - memoryBarrierShared(); - barrier(); - - vec2 temp[8]; - uint stageSize=1; - float stageAngle=(consts.inverse) ? -M_PI : M_PI; - - //0-numStages stage - for (uint n=0; n < consts.numStages; n++){ - uint current_radix = (n_nI55 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 + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + float stageAngle=(inverse) ? -M_PI : M_PI; + + //0-numStages stage for (uint n=0; n < numStages; n++){ uint current_radix = (n0)&&(inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } if ((zeropad_0)&&(inverse)){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), stageStartSize*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(stageStartSize*fft_dim))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; } else { - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), stageStartSize*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(stageStartSize*fft_dim))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; } + } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_c2c.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_c2c.spv index c487c48b3cc71465727275236485b06785061fbc..18162ba88ae36e427f3b7ce4bd3f4eef3532bac7 100644 GIT binary patch literal 49624 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 literal 54124 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.comp b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.comp index 55f02cb55..e43611929 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.comp @@ -3,10 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; - layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -20,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -32,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -201,24 +203,28 @@ void main() { vec2 temp0[8]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+gl_WorkGroupSize.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+2*gl_WorkGroupSize.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+3*gl_WorkGroupSize.y)]; if (zeropad_0){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=vec2(0,0); + for (uint i=0; i < 4; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim))]; + for (uint i=4; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=vec2(0,0); } else { - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+4*gl_WorkGroupSize.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+5*gl_WorkGroupSize.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+6*gl_WorkGroupSize.y)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+7*gl_WorkGroupSize.y)]; + for (uint i=0; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim))]; } memoryBarrierShared(); barrier(); - + if ((passID>0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -439,7 +445,8 @@ void main() { vec2 temp0_out[8]; //1x1 convolution for a 1d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInputKernel(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y+i*gl_WorkGroupSize.y, batchID); + uint icellkernel= indexInputKernel(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), batchID); + temp0_out[i].x= kernel[icellkernel ].x * temp0[i].x - kernel[icellkernel ].y * temp0[i].y; temp0_out[i].y= kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel ].y * temp0[i].x; @@ -664,17 +671,23 @@ void main() { memoryBarrierShared(); barrier(); } - - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - if (!zeropad_0){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if (zeropad_0){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } else { + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), batchID)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; } memoryBarrierShared(); barrier(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_1x1.spv index c1c03c202b66397fb610ffc65a16f6e1b1890363..a95fc88b11e7f81367979f2630f2ea1081f32d7e 100644 GIT binary patch literal 76360 zcmaf+1)x>cx`np_Vs|%UcXxMpC#a|>f+BW-V0U+ScXxMpUAwzm-}mjahD_##`_6mo z&hd{w<{Wd)xz^fy9S@yG?%uW48mToZ|M%!vt@h7&t&w3`tub1owA+2?)rGb*$Id-__tmis#~?z+C0~9#4r6n4B7bD;2Ozo-QRa4` z-Wd3L_uaPFUaR!oW%mIy?>^6B{6Czrqs6z?UTu5yf9<`oM{W1j&RuKw0Yj6A=8yev zd`JE`|JvqvX3VYD);$Mov%@OOV~^IFIR5rnR_oQjZ?8Vhh}uQXnIJLEm?r$!?x;D@ zFg3fjx?%V4xoz*g=AC(u?dIKV-YpiRL7=s!!M8`xKD+nYO}kTTTI@YJ)HWM!J8%AW z-uxYT+xc3mBcCGnSYvFdSh3i`LRJGK;Uti8bN8Somp5y7l|E)~B_U^mwuw1{syA5E@M&bYD{Mn{ozy90y?%Q)fFZqsG zmR!gArFFhnZO3)wI=;2Bd%NtKajR8+1KNJ=CDn**_>KPMhYB@*vzkY!e2JRN$zIV-Y;^g;-FURTmRL?=Q1A6Ve3r*X;tg_c<0*3lKwPt1`_GW=Omwni?`}FGH zZ$^Ib5A{SD(Um{4vBY z-w}?2E-h_;+B%x`eq6&jo)f`Mf9$M|F`NgtOV9p2cW&(Shp{`guE6dXZ>QD+|KiTA z4~B{B-1@MxziivP?dF1W-+f!;{tE8dcl$n`Bj>&g7p#nHyWRWrfrjVW1mC{)H1N^LnN+ zT`;4xR)O1Q_x}BR^&PNP``Xa(Yoyk?UTE55Kcln;V7JFKbZgL8=hpu4T9 zuOVGq3&0P5jyty&!&k1QrLl*%mR5uxx|TY(HpedYZduvKSN4gO{di?RS=l4;Kv>rA zG>qM~H8%E$G);)F)HE6P@H9;WUus$tyXqJGA}SNC&FY7M8KW8)i+o|FGaKWF?`Kb=|= z^O>qQ`_TK|)Zn4#s&i`&eeEk+hkp_5@_Aut?2hM!POWW>ZR+#^`yAzU*ykv1e>yb! ze9@`Zx8d6NTX1=<52)+|hp{`gPQ*@Mmk;CX+`6K&udM9*%>DOsMwiz8*m+?*0!y;f#^v z@q;>@+Mh%GoNFI`uF!8?Z9h+FPu19dj?hL%+wbQGZ9lIX-=nepysF)+vBzy}&zJGz zHMXA*v{{nvc%SXHxs|rdjqPUvb33$lZa@3$pQ7;} zjo-eUW9KK&`rWbpaen0Z|8{+!`=@JrhT7c<+s^{_H(?X+^SbubjqNkJ_V|tMv$D3I zz18RQu(qG)wS5lOo}{r)VW30D+qr#D#nqaW!|~^S+Fg<#$1le)+V#A*mgCp%hA;EE z6DM|P{h@odtmi&XJ@;=}PuqHq+3~y2#5|g{ZTFcrk0fo|J*GWDW4pJs)nmSUOFQS& zy`?>Q<99!4dp;*Xg*v)1I>#rTh#KmdmcyTEvF+PKz8fQB3fee)H!R8y!|9uts*Y<~ zj!CHFn6&L@wx%D)r9CCKV=_k0e%;sBk=J%lX&d7>Tq7O19s4acoqLu+yXN$?#>-h_ z23l*#YtPu&j!PXg(OT0u`_rGgbAZ+ESm&g*uAFt|qP4EPb^MHD9r@ImmpJFp>y|&U z7Y2`1*tu>wXG_7GT18u*^W82JgQG%3YX zYXh)rG4@{AT?+e5Z09cid$3(c>FYfP_Cx0dmYT=CgwN}J<|)_u*tyon&b59%dT_mX ztvAOwee=WH_rBnD8b8gy^}QFk;1jn$wsUE`KKH=^w9bJ(*TaFd>XmmrX%B3;tk*%< zNMT=eYI#2~e`>Jz4Q=ZjOY1q2Gf&%liCpw~?{Iv^U)cDprF{vu^H}GeCgzQpUPOK0&BW<62BD0o8zqVZ+z}! zncLOyA4I&o>oaw|zajBo+xwe#^87C55Nywf*Uj+v!{?kL<6r&(_#xQF8k6`JM-cx~ z5pPW5-yK2xdquo4ndjfY4DsLm-$#)DN0V>7G3jqiHqG$#j0Hc0y2cxm_{l~PKY0;v zOyd1sC-d0780Y3qyz^yD;&*6x`z`q!M-YGi2;%(?CjELZN&V4Toa(Y)W5Q3|@b+8s z(>1(fm(RS<36J@2{#;F*d>OYGHvj)`+~Q4~d>OYgw%4bOXO$*Sz8ud(*uy(t4>$4Z zGA4DN8bSQiMZ7VI|6&C3UpDd1k1>h=VFd9%7V*YpzfPb?ZnLpZXxjsqjNREy*lI1A z`rWaIr+0ezoJV64KlcdY=V{^{zcGnlVg&I^Hu0W!V-mmW2;x_3;ywSyBz~h2#Bbch zyAF&={I(;A@72V+9*prC?=yI=@jhE?dyPJg*6X>P*LZE8ujTZg*GxH*;mz}F z@R?_0693@{;y-HQoo8bb|J?}Uzi;B5XJZoo_Xy(uY2w@atcV|jho#|-e@uAC?>rlm z`jd_zezGRsc{V2Nayl^gnfsDI2X=X134bp9@Wyc-eCE-Z#9u#x_#29NV-kPQ2;%Q8 z;*ClCt0Rbit%>(M8I$s61u_ri^?mtK zt%3I@|F{w4pHt;0{^KIPypDcf#FzZv4WH|M>Wt2Zb;q6Sd-#bPKG*Z`(=~j3{k{Z# zcgWUE{C;s9eeQ0U>J~Xzi??hu;&-bCRZI`ZW-+h*T-(ki!-}jcW?Y~E1`<;RB zE92Mpy<}|TeJ>f?&*#3EjBUK{C1V@!d&$`PeJ>eXzwaeu>-W86Z2i8MjBV?C$=K@g zU1V(IeHR&f25jF!mbUL2V;k?g#@N>LU1RJSuzlAU+j!qK#x~w}jj?Tg*BD#B?-yg6 z@B78r&fm9{?fb*{jraXwZ0q^{Ft)Al4@=v3hNV5EvVBKb`h720+P(`cZQlcyw(tH* z`@G8bU0>-XJUZ2i8Qi>=>xbFuaNZZ5X1@8)7Ve&5H% zHs1Gfv1h>cJzQz~9xk@=zK4r#J>SE{HsAMfv5ogVTx{cg4;S0k_i(ZG`|d5a`M!IL z?fLVaTWR~wEw=H#bBk>~-?^2x@7!YB`kt+{eYaNHzE6v7J>R9pw)JH|Y5UHsw0%z& z+kD@V#kTdmSZVt%th9aqRocG$ifujLf5o=-{a0+~!}njMy>wyA`wlFA+x;us_gbaj z_gbaxd#%#;-BxM)ZmYC?x263H_u;Rd#&HC?aXmMhxcIdlEirb9YV}+aJw`< z+n>qlPrDn3Kl%qWe%mGRj{?6t*c#VySNFcZ2UxB z>2SvB%Q(*fTT5U1JF|_49p_na@`p6zJR2+q{Uw?>|>>V$|%j?8S}Gar>R;r5pn}oO|nQ8{^t^ow~kk zGiR59owJPfa`sm22O1s?X=l?!@W45^QZ-_r=w;*Kqiw|JufHo4&6DTO<48 zdNIcwe+diT>B>*oXKQQw1&&(`z!Fzq88{^)7X3jnX zJ7*c|=U}HHemvb>P*joCszB+*&hrV41_PgKC zVENdifPLR~7;8d*SFkbi2RGcP;NPgD&$<5*#+rIssBYlaRw2GUoiR1COrEhKK(mgmi*c$rn&+mKWqIXKLV{k9~?sIC6 zf%Gpwg#7e3P2+Pe{oF7uwzbNbZrJiUkJEw8lTUx$!DWBbW80s6?g#3g0b5`Cn-Oe( zWz0<2^6778uzB)>o3%6x*m3B~7-j{RW0(!wG02zoXUEo;G0Xw3HO~nrpE1k@HcvkN z%?&R5n+Mze4);vF)eEM4eY@Ym}M)QJT$DuFlU?H$`q0e>T_k400 z3 z|La<9Y_7|;*75sE&zacoCVf{gUYd3YygAE&9iOe&>*Z*d=kQ1W3XR`3<6jYMja;u+ z2FtC);eA4TSq^JiTb$fg!Da61*mA3JT+Tl8v%*?n`87D!{T5(3{qE^4!Jeb6-L1gJw0Y`n29`^FPq19Bgeq9`mzUlfvut6@%NyW%ROUzaDC6%0j{3A-f;4{&hH2|S3YyT6S%%d^?{Sm zp4b^|u6*`cU+_TIwm$W_7yE(bjqy8~UBKIM_`IbKZDXQiS8%PPKU}S2H#qr>XLqpN z0FG$e18hBg(Y7bJ*0vX%d}{3tHdj8{_5rI+U$pHDmXEgmz-k-ZXwx>vcz>7hfX1)x z{lVI)H4xl`L*Ie4+CICwPX>Xz(VC+#^$r5dnPb1&8OsoG<~e;F3@4wML%@SMaxS!u ziT_ZrHPn+DhhfVn=5YNS{=S*x&^AWD`}YWNeeRBglg~Ln3Y_PZoP(p`jMHb|?(1X3 z9NFi`g5}D6ejK*B`W%mYS}rw?2bcT&1Z+9|?(-AD_J@>R+;!g&b`}`E_ z>~npIJGF{Ct%-A=>&rer9c&H#j=u-3T;}QwaJ@gygsbQHEI9e(o!#U)w#@N4aK`D& zo;eq6ANq0*&jZ(c=6pE$)Vcs{uDp5PcP|7Fq}AsB>-3ZoBty{o7IP~32tDWn{t>A9to1-uFZUf7i zW53!N%k5w}uLlYab6?zh*j6|nX6<=ngquJ^)gaPq13I@nx!^SmCs0Uk)J zPt9Hr-UQ2MUAzU(`cs>>G12xmxYqU`xLVsgaPk??`(U~E3ho22e7W~O#I_H8(fbj& z*84G>eCmG!Hdj7+KLx8-U-W(kmXF@g!RpOk(l*9;_x_iS-?{h#tesk4gL`o3`-)aO zd;c4-d*2*=srM~d&K&#I&RD(!%awcodu;i{`~V)zaXGcEp>0h3KZ2ttN#WTSMCz{qFr=!1ek36;3|${U=!N4-Wfr@Bby{$lm`OELZORf3VHfXWtvp%B2QF z7-sK}ge|Avy+1N|N#e8jJ7F8s=BejCmrHzSuw3?j7vrhp-q)A7QL4DEO`LmQU-tf} zU~A}i{GNZg?2pmF_5K(guAa{^;N&x(V}s>7ey_RXbJRH4*3*}BGcLH^3**7br`Gsj zbLGu*?@yqgR-c;P`xAoYvo0nAXZ@*7+n8vZ7+hQxW4wERhQ_aNda!nC z%>?ezxnm9Zdp_FP`!j>x`{w9Ny;;C=*0W#jjAd4E=01JQ1}C4G*}?AHr>JcWZDZn} z0~|f6F(;gSV&(!{!~fpI8rsJAUB>$Ge*RyV)_AW4^Wv+|?|g9b_Tj#tUrbK+{Q}r> z<-T7K+dO^t>+eFzrN+Wwx!m&?0n6!k-!BR-_x)nn#jNjBT04Wym5;W*`q8E@+WLXz zqiq+k+HzgfHpckrIhXw#zvpyUuy$$<0J|6U?MACD-ksL}Hg6Gr<7Z^rJ+Nn^HQzY> zslO*!-aN;lo%(x$jn`*C+8OuWVB^c@wSBPV6SFVa>uvU%wlVSV2eyW5Hhu1oEuWYJ z^iw0}UfY=X4+L97e`*ZGmQTzeur=~Mk+w1M9|X3B=O8r(W6LLI2-q5VZfx6)-+RTu z;Cj6s0wa{rQ<}f(p^x3!fl*7gJm3zt&*mC7PSS=er%!>a=lE1O`Q)9}*qYMYb<*~+n9{|d~mJz0=Qc5g>dr8yQs-4^^dJgV}tLNYzIQit=+vJsVa37p;`ZDeZ z!1DKVWDXt#+poUN!9(DB4jzV+PpwD5=E`Rd9@Wnr=*t{D2A0npJPvjayxzJFw2d)- zdblSWzrH8H+Nt$4cySJWPtj_NpP?=9dCy{d&okdR{i**PSl&Fxp`H5AgN@f`KiV1h z3t;2j!-;a z18j|a$Ej^h{BMG-VILXCTiEi6c^hnvd|uKvru@9L9)9D!e!h#ZUZ?ND$=iqbw)e&4 z4ZQp>cq2KX;PAiwa`W?95*&U~}a& z=Rbk#efl$;eD>)tU~}co^Pcsqep-F%^Pcq^SU%_fcks6yu6K248xtLWfNLFp!qqzd zf|Jj9{sGJV%@J)b4(sWQwvpg!Z6m|Ur&cGhx$@E0SwGtJMOzoJe6)=MR-5}!ZQ8~} zTUT(cZB)2g+h}m|8P6DCxsLyqz2m#AF|n+q7`Cwr+6p8BcexT*u!O=+HJjw)ONy z+YI1Z+l+AXsWlVWT={65SwGtJMcXW3`DmLJthRhk(KaU9W&_vSW{0b_%>gH$@yrdD z>-ake9opu>ww}Idn-^Sbn-5MtwdMz#D<5qO=trBrXj>30A8iYP)t38_wlUGRFu2yX z2wbggQ8@XGX9=)e$KP(~(6%JD_4GyCQs7$K(s1&rwG7x?`Dj~KKic#~+j3y}Xj>kv zwtP0!HYVCu0N2`9gsZi!1Sg;ItO}M}g(KI=)xg%%7j3J9Yi(=5$*0zuU~}c8Z7uz1 z(-&=PgXN=b9kAN+44`d{@pE$RT(9wa4P6(komv}!z4z%`AFM6*zlAKH)i%POpIYV{ zr$6;K2Fsi0IJ8rL6R`36>_2@O#EAbtueT$u_c^* zVzvTX!x+b*ZA|<?dtw;_nBxhHEl4c7c;m%&uT-WZh~TQ$D-;o&W#(y-916(i*`3tU|26Pq>!^ zKmInwV#+mc|P7BTdsUQJ^QK9|ATe*QG( zZJs`B4xyFHb@6a;u8XOA1e|fHdnDL6`RF?eTwm{whLca<$AHb1&zd+E?3yUA3CF?7 z8{>2F@!)~9<~wF>V>0Fw!1b6kP2E%DsIioP2bh1y+~&>e4nQeV+}k*UUL^^3i@SSnX`Pf5&qkoN@Z1|9mmy z$=bRATdrKg7h;>M&+)jn!7`qkLx>9eNmK`vvx23)V3YvGK`nz#;ZoP6ftdT_laZh(`| znz#{cuDp5vuIo);*Ti73I{bWhGn~9JuJv2M18L27%-Y6e%(sH;G2aH~m@_xGi|Hq0 zxdYo6`RKY6Y%P7!br-nSbvK-RYTW}iS3bJ#1*@yP2i*rJA6@r@)n&fAw2evM4}j~n z^&p&l`hEl~_b^AaJ}Rc~tfR-U<;r#aIJUX^?AvuDm%g6>*L^<;C!fBb0n0tjk-nb= zTPuA(2R2ULeq5h&iGLn!eC!v%vR1&oP0FD0XA3OJlF7>V9#~=?DQ6#yfLofx4{Ex&3DY&#$?R@0oP-G2d-Sh z?_!s0_&sc6b$tjYA6*}T&6SU?kHP9HpMgGslaH=X!Rj(!UE0Q^ z@6W*XI{F+=K7D@$miv+;>)>lKeP`Dh*q+gy3`T*D)SJ=f*4dnY(~V_d_X!2@Z{cg)(xWXxT_ z^_WM2bIh5WuGr-o9u?ad`RE!AY%P7!H9EM~H3pn~bd3o%S3bJN0;{Wh1|J(vKDx#M ztIK?KX&aL=}AKQQF%$UsG^kBK}%u~+W4A|!Bv!;I|NG|JYMsU5ZW`Z*=b!P?}Cm(&Y zfa^6gE1Z1#o(*iSym{`0*}<-v^7(rXIC*2-3v+@8(wgs>wT;P`=K|Mbo*T|FXKv;Z z(@(}SFSarA(KR2~TKb}EesHa80XX^8S`cimd~_`YR#$nSS{P0~x)uSe%Y1cd8xviN zf@@ui!Iioe$1eBF64>q)`HXK#uzC8Tbt$m*^+oH_;9Bc4aPq0OEZAK6Xk8Ah*7CE) z@^JFex&m0O=BriPm}p%QTx(qkuGG3RcByq0?BD2DKI2;zY@WVoT@7q~ebKr)xYoJ` zoP27n2{uwwj2zFM`7N#E;&?c3`|*5`U~@|lnI!OlndxoQJA z@0hiX$(Z|q>oM;P z=a@4$eZ};XvGl_>Mn1ZB0b5I7bnObRb@hjnPp#d+=E_Ic0I<5s=ak*yhGHD9gT#$+uXE2c)qcO14{cg~yf`s9rF zIqi6G`J8qlw%iHw#OsqQpVRg%p3_djr`GbCc`BTI#&nvPI=S|ojxASS3(vqdPoMps zOe>c;Jquj-b2glO`Z)(|Uivu~Y>d1$&!m-0{P|$xV_yI^CUbWoSZ)sHDd+7XZ1eP4 z^E_I)thI~5^;)|G&bZXQ6l|P)^j!w7*UaT`^6C2uu(|SCGgpFLGv#yIRdDiIGgpHL za*oV*%-Y6e%-4YHF<%Skm@_xmiRmX}xgOgX`RKXVB)n&fAw2g_b+rhQ2JK#!PcVd_O+6fwd%?BV`{3kL>wd7g^3nPLSgqwV>4R|c(fSZrt>&v$+n8v57+h<81g_NjD0Zp! zF>J4K@)_UbVDt1v>l0w>>x;N(;5X|TES(fSNnt>wMzSvdJ1&yT7K5}0Zu+ze*~-5e6?yD6Rkgi zYpp-Sm0EwnF17xOy)s(mGrr%z=IM*p-@(?`7p;GQYps96$*0y|U~}c8^>46R%V&~* z;N+v#m#AtrU#;54hz~(PUoAWq2zMRL*^%!u@b@@y*CY*fE z(O6(}<&!ryxIRbYz{zKPh`kde#Y8w+B6M}0U z6T#IwCWezw-Xu+4`FVI!IOFt1?_^;6&=hbty#e4%17I* z`q8E@+GYdGN89XRwdHqEw2g_jIl#5HIpJz;bHT}HJoAF(=HZC8`M}oG7j5%{Yi$d_ z$*0zWU~}c8Z6W<=(-&!;NhZ7YD~qisd7+VVR)+QvlNO5j@C z%5b%|Rp8_^p4Gu}t8wJKtpT>4zGzz$Tx(kkPCm8P2AeByp4!&YPpdE5)&7h-@Vc{=6~Hw-Isld8Nzw>zSs}!ebLsxJ+~`u ze-3~2@7DNj9f#{-0N5IiV-4)x!K=~^=19yQaPrp?GbuNiJ;CP5`}gUzcj2%<`xiU5 zy=XJGy&IpcW80T@KMsE!+y0H;HvJv|wnq9r5G?2Oiv4Qu!(lD^73W+HYU7UnQ|}-+ z`TTv|!C<-a@0boThI3UuGaL*jpE`$t9aq-fpN$I_}%d>pO*XgC4vdDnM5t+xN|t83y! zu>Vf3`R3_2ZXm6`)HoUJJj6Z&Y|Jv$Ig|D*j?+1O*3su$FxF?wvm1YM&%w5qe;ag0 z{O5w*5AtQ+dD!~$_dL!ATT4E*E&!L~xDY$z(3f-TI4;80pWKVVuSdgMzz*JJC8o*Tf{l25H0!R0t^!p=DKmGy4M)}P#4z~wk@#daL><@j&I)|YYI z4z`y3Ag@2n*&SfVr!Vt*C)jy)?i`2nDrct<)im`uzEd5(fb0neDuBuR1PhYf+46e0xf|F0J z&R}!pqpb^AZRPigqrk~WTUW5!%vYPXG0`?ExYjlrT&-<%IQficEU;Y1zj@j5`DJWu z>* z&*Wgaj(?xCL)#SC*3%blQ-W)4Q^Con*3@8g<)dvHu-eM+3#WyXkG5`LwVAIrZDanw z&m4YFn0u_>0s3!=n(x0)HiTv8{c?J+_e)!!_h+P?iNhcLGdF(Q+>d7gTO-f=vx4PT zq7R?Es&H`L@)XKt{Z|J};`wEpu9;OL}WwTDRGJw2ntU=WRi7y#^M7lTTj@iz$@%q>Et7Ik)*c*o$JDr_b^F zZ@kH+#^PYP{CC|;faUc2th6M!{0?_1eR3Yu^WTVTb4~m**mC*rx|aoefA_!Z)|a}= zRdLHVabppuFaKTl3SevKx4)%n<+6WP0@wRzWw?6oR)LexHEva~x$>Fw)xh;$SshM3 zdu0uvc>k{57L8xs zn}fAeYb&tlRNt1g+WEV7J;2?_H%DLU^#seAW53!N%huq`bNbi@PChZ)g1xroTxc5; ze=l(Kq{en|@`>3VY>j*esBMgX|GTpt!1cN74JV&-z9ZOkUOxZs1ZSK+`}Xs6A91nI zcgB`0_jzAzbM-kd?rFKy=m#$M`7YRU`rYTdg3Ep0AKREVPd)dvT;g{Fm-~DGcJ{fx z#O+?i?a{=!&-G=W?+Lbse#h^ckjq@{1+MqU-f;CC?*k{FynUOza*p?tW2g1o`&kO{cD{r2kmj>yl)#p5TJvay~pY<~soOP;RZDTU-A>dl?!Em+S zL*V3-cW9GW>OBn3IDHxS;b8glx^V=y{p!mc90{)H;3zox)H)h$u6*X;82!wFzRba~ zVEN3!abV|QF!SRaXd7d^*NqbzzrN$a+NpIC*fpZ>L|W}!H%M81Fr{isc|t_F3$p&faUaijkpwCUL!8U zHm1!}Z!xf3;x7lw?LhujCb!p(fFN<$HCgE^%U51ukT4(?d<)h!R~!?^rhZ2 zU^#Q_S36^Q7A#lp{pYad6Z1USeS0~zt)Xp9{4ao`C*yn(PChX&fvu7EPuj-lckjOp zuFvNyaPpb&*THhHaoCT0{|#~Hp?m*LY`JppzlCkCKF7ZRtz2rn4VKH^{|{JBzkB~3 zaJl#2#WtqRQ*SY_T;ksY%VqDs56<4#m$(nAxDT5+_rAXD{g1%b(C_#?|8m(MAA{@t z@d;c#pP$0XXFk6G%YDv~z5gZHdirv1z5>^K;cGbg)cOW&uDp5f{crWt>Ql3O|2wdJ z*2VYWtUtAB8xw6mfNO0(!qwV-f|Jj9eg(_@QgFY4<;%VQJGOo3i{3xLwcbDBWkig!1B@C8hz+qQLnZ!#=G}NZv6WEH@~%0t1~!z-+%vGJA1zi*u8I# zzSJ89EN4CESvzCt3eMc8k5S>|6Ehmveft!(t)Xp9{G)@dF&KYpi~%Q~m@&cD$opAs zWBe{-escZ%KQFEEUJJ&-SD)W;;pFYZeLtSK^U!@iKDOKu`11LG0&Mg2Id=bzbh*@+ z2rQRr32}Roqlfocms1_Wjgg zYv_0U{u}Oc*&EY>>%GwpuAaN;;N-K%yMxV@&zw&WuGjnwaPnF6GlI>PH_tsjlYUx# z>T{3J43^LNp9So{H=oa(+Qvl3tl(P5Y;d)X+2Q0fo;kpBYxB2RqHRuW>*wg9-+wjf-sZ6P@MjAs$B+`=5u zwkX(o`l4+yaII}|IQi6C0&K2)v@NM0ZTg~ZDX@IBEe%%N<&8FNW1?*taII}wxLVtC zaPk??3ShbAIihVvu=Vss+e+YC+sbhAskI8&T={5QRX^JFMcZm%`Dj}mthQX&w2d)- zdi1W<_&uj*-`cd=;&o});K<*>UJvZw1U26{{i(k`Sl&Fxp`H30fQ{E@ zKiV1hhG65%=e3Qn{PG(4QJx zV9O_FORzQaJ(0FC@oxpThUXwPdSJ^ZrYG1Md2ZA;M!)xpt-vUVN>(py; z)=e)sEV!}K!;`Z5QHgXJ>^M}VD!!OV~6T-%svITBpY!BKGa92^ZNpS)w5 zymAhXg)>fH#(g|k{y2`TgA>5^t1okKBDkJ|li=i2>twLG@|lBE^fL$gG6$!E%UE8)N+RaF;cHeV2l@Q|k)wWE}b~ zr_~l;NxKF|?s->%z2}*4oc`3m8Z2*~%rb9 zvc|QIiT?($HT0*(jo9*uxe08I%#XG)@!t%#MtRS>1zSEbw}P#a?>M!MiT^gRHS8nf zxE)(QF?WEikG$6DFu1(8J%Vjao2T9bV7bIU2A0dc?QyXC$oHlC68A(E z_hb|2y-i>4ZBK!%q2KX8N-LMW`V6?<+{U~}a?N6z^R;Ci3F2q&L? z`V!b&dGowyy{w;BpZdIKy#kic`F|DsG>7Y59ooi3$7|qP$LnyljyK@sGoClWa^>H_ zehb@r`l9V^aINh>aPq134%l4zXnR*b+Vn-+dtmu!dmpSe_o3Rfjfu7oz_qpy;c9Ik z!O3SlpMd2)=E!;b6l^_x(e@d**7iA^d}@6GHdj8{zSNI4ebM$6SU%dm2CFUi7;R&s z?Hh2d?OV87+jnsC8P5-3x$ilm?MJZn^hMiG;9A?yaPq133)o!wX!}(^+Vn-+Z(#Xo z`yH&dTpP8GiMBt$wYERuYHfeP$!9$OfaU(?h_==keAkApFWN?etF?^`C!boKz~;(F zTW9@f(-&=B!1B>H3RrFVoT6<^v~>m7+D3(|wT%WRpYeiO(KZ!WKH8=Rt1X`mwT+3kX~4C%Y2j*Z-QeUi zp6+0|={TZoda(8MMcWMETHB0p@~Jfw*j)K&n^`~F^hMh&VEJg96|A;A185s#ynhFK z_QvlubT+VdYRw7u-luO4u(o(E+BM+wtTs2ce+S!q5wJDNXSGG) zL;N%mtB-k3cE@~SS|59LUl)vA)G@N{5mH}HM*B@+MmxGf}%<^DsWS?sr6aNZeYm~pQxgwl=VpalMBl}6)nD|!)TciBF$W`Fv z6SFGV8dHV2!RezpJ`BX7-3Xyp>W71;RLJ;27~8r2gl=imOw^=E5r^YmGBOIo>H zBewzP8kxG=!Woyky}-uFN8fhf`r5ZWoP7G;0c@^()<!Z9r>jOQS2`Z6bV2gAu{JVU_s zcn*d$PG9m40b4)gITUQ1ynVYLm+@T$uGi?raPk@7Wnj5W zIWixYiN3+w~}yzOMq;eP0bHpT4gH%U#QnzOM&cD}CPpHcsAt zT<3C$zY%PF?3=*lUbq=suG|Z^V4J7Unyv-8teIQE^_sa2&bX|H+rh@kNAn%vdOh3; zCm+psfz6dS&%JOr*!568*WCjruP*n(z2I^^+=p$9ymj0Q_k#!0+K0Ndjf<`az_qRi z;nbD+dq~W=&v+lkHby?$9|2oSU$j38uC+e~C!bo6gUywX_9wte4nYy1oL}y1s@}SLW{a{0{stY&k!J7_U#x&qM3b`dMWyT7Cb}o=|*N8EMS_-U}nc$!C0> z#MI2X?~E;1?zt}5=IOH^zHo2J$H6vFpEbvzmCHID7hJEy@!*V0-SNT3$w%J=;ChWs2q&MuCjy%* zpEWiy*fq8~V^oLFU6a7cYrDTD1$*A|S!FV8W8|~OCI=5>+U-MK+QvoK6yRFdlyK_G z{7oh1JZHR9V;dtM?bCp*r7zm21=rfU!O5rAbYOGkqrE#=?d5%TdN}!Lp8;HIpAp*_ z`DmXBtakfQyS8!BJ~O!1J_}r_eOByp56*_|{*#Y}*}>-N%Y4iMw!Xg1$DH7LKIVdx zPp!GZ=E`S2<^ek&=61`OL=xVCTa=oDXf|G9L?q>-ks+uAGmB zvCH{b1lzxXDIX1sg3Z&H`B)5WeSMja#liJ_ECDBmCt-E1$I8lXOX4h77lua&D}o2$?9v}olrp4Gthcvgp#&v@1V*W+0e&NzJ;&st#XXFO|zjgz^ z2R*>GuAXq}%KU9DW<6xQ+h7|bAMM+Mt)(y8dx2~1+ri1F*7jg?<)eKEu-cz0wD*RS zkMi(r_5nK|_ThYJ8<+Xm z7hKQBesJY{?2lc}#{t-0Q{|)KK(KlGG9LrM*4LN$7zD28;~+VX)EX@2kk5P!0XrY% zGws1}@|llAz~y`#ifxR1=HoE1^I;#(hqiH9_lJwo77a&W%XR1c8?R3;eI5xepJ|W6 zmh)NFcztr^Gws^VGwm_(ozaxJIS$*oDX-_p!^vlSCy1$;>*9&na^-dUBy98aIfi3t z<I1REdwEU+<|$Fsq5b1;uN&*xy9r_Y*a z(8^_Po(rzm=6P_&rSAD)<)c>TQuPF~yV z@1@ocwXQ4S)Rp z@|lkZz~y{Ah;58~=Hnr-^I;#(hqiHNVCUnhVtqUdC!hIv4qVR1^Vr77XFgs4J0JGp zd}te&`FIgr&&Nw}<$S!1UCzfV*xebId^EfYHcwyX<2A7L^<_R@2iNoQ2Aq6qy$Lo~ zKJ)Pw*!d_w^SliwpZWL?xSWr7u#J(=e7p;GKJ3H!&^9jf@gBIIkN4rq`S<|4oR1H& z{rm9p(eM%2JbjsukHOa0m-+YvT+hd+aPq138Q5I;%*W?o=c9aH`2tQp^YJCPoR6=t zjgilMd<}L!?8EucHZJq=4Y;0ys;=-~4X!fBlYzu`}_z8Ge6ho3V{Yo$lC~r}44n1~+5VCujcjP5z9u{*K2) z@c#JsswMzW$RTGRV#hi$?GR$jpQQ2G`ggJ>qn(_?AN^A_e%p+1O0YGq<2hzhzA%^y zEH?)^_NzT9hqdfioOLlx8+Y`ddeg$m=kLvS1Iv|v7k4^r*Hih-+Z|3mb*2Y9uB`bP zz^-|})5uz#5zaV$nctbf*3y@_nZb@jUw&767O;HmS;1X6?}s@L^f4Q@G4lEQp|gX3 zV+{J7`>AQ=G9Pn->wPj8oP2c54bI+8-aJiSIUn=F$!9+11DEqLKXyGI3&0ttFY~b= z*joBB9}9sUhrYxu40f#g)HVmLoc%i=i-Ogg-%Vc(?78rF)Ac28@hWbKCXS}1@4%+s zl3;!LUG=5F)|9vZMQG)se;Kf2@^7?G#d%s5JdkrCKZM%pe>rS@&h3ow%Y&^|#;kxX zpYysR*gX04w-UJQZ)I%zlh1i_URJ@@m;P1-+g};88n%4;TODkkeEz=g8eqqvFJo8} zT#jKaY{wv9)?XW2U&gQwxYoQboP5Tx9@sqj^tV2^>~8~X`;#x{Z$oT->2D)&t$AZO z`SiC5*gW|`%^uqn>^Ssg9c%`6F7&w$mZp`<7&iwyMr}WmMvG_S`OR!@$&U|fS zy#7s2>ov?a^|k^}%#nT211vX~+UDz%E3dDUVgG;kf{BQ+FI%tWThsdEHMI}p>xq3r z6C<{-ZD^fm``Whg*?KMCj&^$vfAsIr_-&)5H`p4vmhT9b>rRgSYWL!>mSYn;Z~lH> zzcwCvp1rT`0w;rW*N44_L1J8|V9C%a?!Sd_Qda(C7T`Ppd}p0kry~VIa6~^L%h1SUZ2? zd=Pj%=F5EZ^k=*Wf$Mw1U^w~A#}IIRPdK>A%Rcvf90DhwF&zpn=k+k`dR`BQGfrRT z^$4)F^yQv#q?kir;*J74R(;uDN9$+(>T?|K!DGPkUYjq(cPzLs$Ljc;8|PEbIM=T0 z*!5={Eysb?lD>}z%MGSR_J&-!H(bZs?k(%NpNu_`b_jX;PHKF%?xRy^Pv!7O|7nfi zHe)#*Y>n)rGr)3lkmEkmKAFQ>_AAc$KC_L7U7u&c$!8y(4VEkS(K*=lJ~|gpKI1yi z9FDA;^TGA`z5vcReVNM(!Pe53abDEM!;bS}IQi_OOTcpFKDrcJzT8KbVcUm3=l^nA zHHxpG)gKL4fwPaU1Z!s>T@7|0nQxx{jQ1LFy^pSilh1ry2d?+g^-W&6k8XgI&zNom zm-BiPc0I2*!x^V9^Lh)|TKck&ZUs9IeTlmb>{#_>AKk8>y`s-?xR34t%V!_m3C=!p zZk$g!<6OJ0W7nT;wA=+&OZvVWESG(xPp;e>u4C=&BisM){??ysp?%w??|aDe+@|k) zvE|aYJ~{j9*W~X?`xj4=3v(>Uy{P?pj=As$S8E|O^R+s^zdvo;e+- zz~h3Q)A4CDh7G~SXAB#IBT7&ZZKz@aaBn}V&Kyv@OKn{gy>3$VHRGN)U%@vw8c z6`Xu(^#sfH;7F~l!Pe84Io$?a&*`>s@~O2QSgsdGYHbg;p1$bW0qp!FZ%43PZ;s^c z1U6Tn=R&(Y7ycV4{*>op0_>cN2@5kpPI*Y|GN=IYD27|_PUo{Qb#L!(X$`e`AOaZV7dJ{l6N53Tz#Gk?VO8|!QD9gnVQ4-pOSW(22VvhEr;_z9qnQ* zz5}5>h@&e<{*91>!R8F+7{cNBCZ#=uL!a7bq&<{lT8=X2u!hfPqrr4Hk!P9b-F~?xbr~a{E^W^h+^Ej~m>PxNT!RmCZ-fOgt%a~384{uB-!s|<& zlfct*l$uY*md}_@0h=eE`lo_Zzsx-iUSH~;4xW~y)O-fEeCnSGHcx&K=fZPy7Ki=n zORclPYPOb|wT;v7c|V84G3DAk8Tj0W_nc^-$6*cUR{MMoW6tA9oeRLxW=^8FO{R=UiTcZJvDA%C+Fs z_uOTFTnE;d`qzW4U&h>kEuZ=~g3Xi9{I2Z1Z`#9`ZUuxYC zR4wnp~H!(e0NQ|A$IwAqigaq&Oe_{)ACgOg7` zkAv-JP_sXt02?EpI!}V_$2#_-ZCvK~X|VpMILbMG23wzXW~6X&QsMRMy&)U0h>#`HRPcw>44 zUSI0G39dE21t*^|y$v=`KK1_tPW^ID-+|Yc`tO2k&F{g-Gb%{pw4t z55a2Ay45yLzw7oR4#zZ@BkSkmhL8OTwl%VDKLr~jpE{p`t>b!eZncez|8ubZvY#)o z<_^+U)c6MM+@;13V7c!({LX$d+8;Sa;#h%0zje%! z&$;>uoPNr4^)tLa$K(3{g~Qx3=GTVLx%v&;Jo(iB9h~~*`u_u7U+Vt}wtgA&7q)!r z{|z=zKI{JI;wEk!%Oj#bUt#$`++VGnOiBg5-Uolf9db7wgDjHwIQJo(fg1)Tcj ze07D_m-?fEYt5s<$*2D4VDsb$HS2#2u>I;wtueuBcK+0?ZJd7B|5#whv^q!D(AaSD zvBv>hBkO-$Y-8k8XFPDU*^jny@sHp5%YG(+lTSYrg6(Hev;HT-Hby>mCI)A`_M>f_ zH6|r@67a0Fw>c-^$vEV`gZqW}DZ&2u{hhukIJ$HATqCw0*Y#B3`W#FRC!d&Unwauj zP75cW_gme-a(S;Y9oRbZj^F1cIll{WY>vb6q>t&r^*CmLlTRNrg5{Dk6S!WVGsDSe z9J7GUlg~Kh%5gZJoSRv}j@4LeYiC{02KJmh#Zk`1?C|3RguNBLI9n<9;Sr^O0$;Vy+Y>iwiR>U?&K6O?CN1N+O+qn2wZv16GtH8;p zpH;#3Gl;QyPg@P!82Qv$9h~vnkG65~uhIC+d-9ra^2S?VJMn8Z@#VPIhLcasI!%l< zt)Xp9#=S1sx`|(}iMOWl+Q!tM)8@zT&)gh-PMeE%o(6kv=54UouK75;jx0c%&uQyZ zvuk0`%!j|yo~^PkEo^JPRoOojw*Ak>?bLc%zZ=q@r=mVHwHWQGG-Gv z`K;ef!RE=Q{$}9RFRuxk!|O}^Ex^_)p&;xA0`ckVW*m=w~LEE^D zX>0KC#-r!pEj&Sm+zZ2Lz`9aM! zp%2)8^`+L%U^VBOplzIf&wF36V=C|K{ov%Y=63;GBiDpo!N$m^PJeK;xev6Bi+{Jq zU-mNqPCotY4z`~`%{5^UurczfvnM#?wI6NcGRJ#2{=I0+Io=0bpLJZf`-1CpxF4K+ z=6HXwdGe`$0NDPmU#`gmvGt|?KyZBy2f@jw{y|{#rE8Pnll^W;vMP!oP6qE3^q?b>-G|`{pw4tOTo@d)~&X28PjFp z;f?8XczvmJ1-RCHC7gW5bQRb<`P9D}ociUQUIVW$^{)ljny-VCPyOq`=E)D@T=)!j z1K57`rPhsLHD}#w8>ioOdlT3(mCqnI!^vko-2%2o*6poeW8_okHgL4Lp0tgN|MtdT z_HzfEeEPW)Y(Ik-o6lf(fsK(*ox8yqul;BnmpQ(-@!vyR&hdTN`mE!+y&qhk!w2Bx zGsh2t&67|4hrsr4{c_ztjIA&A9|70r@KHGV)PD?Yo_yBr<6!&Mms(GNotLazZR0Yg zC&9xT(^K&JQs-%Kt@#-^`HbmVuzB*S{~S2=%Q<}>USI0J0IoH^2q&NVFM-XIAJnYd zm%;X{FST9)t2ygd+c^EM+gHJk$Ur4G#z_sRI;p9{QH?Vo~gPQgKJJ^2prPd!{HD~>68>ip(|0mcnmCvt# z!O3S${SCH8*8e|XW8_nZk9GfQb3JJr7yn3&zwBpZIQjI`32Z-un)Tlq+Zg%O=>pDp z?MK_V%<(9V-+fljaaVYK)^XjA3a-!LXmIkGI;wt?|IlOV+KnaT(M2;NgvF0(gC?GaKGzfJ=u zpY=2?xLmj0u#J&Vo$0{Q=6cdLF8=O~zwBpvIQjH51GrqbGh!PfpE@&vGhX}AHqIJ8 zbIk(w`;mM*fDu_MCZ{x%0lg_CDX)=bm%VEtA1rP2I~QVe9w|CDbq4lpdlZoZ= zpMrLrJa@%ZwDX!vuhY==t}wPPJxxas)YA;Ox%kXPw`-mSlc%TIXvfLpKL;KE`h3lW zn~VQEbi3yHFnRnJpdBagb$7)=wDX#a*CKSiD~zo(?_IGNZBI+s=bVcrj^UAbsWJJy z$1NkaMjoH#=&a52WNcmXE4qB0XC+LYc~+t8U9p27pzCOd$<86&vU#H?KpY-k3~Db{`E|5f}4x~ap-mrkB7-K#gk&DoFV|4r!j{p8IsdG_ipXvfLpe>yt;_57a!Hy8gi z(fZe#vtaW0zZLB`dCvda(9UZvUT;U&^KWcjdU^+Xpq|c#n~Tpo(e0Yw1(T(b*2v@YQFQus9%JkD z@H5`W(DgIk$BAWqubdFoa-ylj+4j#N_70| zJ+K>YF8*If>tAcWK`f8|H_?uh=dSn`+Ih{z>)YshR~TEDp1y+~sHgA3&Bfs@gJu{HAe z{0g0ZoyXX^+!en@*Sq33#Iiot=v{FW+JD{^=6=iLuRMH>s-4HX;%0RFdixzro;~;j zTK0P$8TUtY``Z2!OrCLnM#~)6>-O$1X#LE&t{eF)^R;Ww_Gh1&=N5F^->oot=D7_m ztNq$&D>o){>#JXMV)!>LAUGs7fhb@{TnT-&&$2U?elpbOrCM~qh(<${%5X7!sO|Hf3)M| z@qZLL{`EcJ0JypMKN_7r<9{Gb9{7^O9Vd_flhN_7&*{N%bMb!)x?S@jFnRo+iguj5*PV%{p`F)Uyq=D( z?-Rz>nfHC-8EAW|-_f55lly%8z2s1IeV=$1u{HAe9EQ%?JWs~fC4YFAuk#!MlV_f1 zqwD*`bBL{x$7c{a{W_1abvYZ)Mc4c0dBn0l*3tjFA=-cazZ;^T&*LZ_zMj?2;I5|b<&iLXKJN`d%ko)nC|V!6{rms1WWH`+z+d~YpUg1~-S#mYCeIur z(6WpfiEhv5D40Bbj7B?7o<3x?5Btg9j6vJ0wcc08IoD&+?n(Rm%Q(2X^feyc-gQUA zs>L?n*O@Ido~H(-ocY$^7v0dJ5HXvVk+8s&863A=z3QeTbG`u zqX+6~2HaeHW}@3Q&w|O*(`>Zk&$ysEJoXtzYphJEO88v#7m9I``mhWEF-o?9-rmttj+UeY+dpzx_q5y zB}|@qR-x-%v6|Q#d3@HO)35UwTbKOWF29pL<^8@EkKsoC1q=&6UXHSynu Su03w=>h-kV*qZ#`*9QQrE4SbP literal 78032 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 UUyH6auIu8>X}q>E`M0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -452,7 +459,7 @@ void main() { //2x2 nonsymmetric convolution for a 2d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y+i*gl_WorkGroupSize.y, 0); + uint icellkernel= indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(fft_dim), 0); float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; float temp_spin_real1 = kernel[icellkernel+2*inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x - kernel[icellkernel+2*inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y; @@ -697,16 +704,24 @@ void main() { barrier(); } - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - if (!zeropad_0){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - } + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if (zeropad_0){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } else { + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } memoryBarrierShared(); barrier(); } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_2x2.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_2x2.spv index 24befadf490fb151008f897a20de4bdad11af277..3ec2c99d9564b60e68177ee9f8298404974562fc 100644 GIT binary patch literal 83244 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
  1. |N0 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.comp index 6a21b4477..da2afb91b 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.comp @@ -5,7 +5,6 @@ const float M_SQRT1_2 = 0.70710678118654752440084436210485; layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -200,24 +203,30 @@ void main() { vec2 temp2[8]; for(uint coordinate=0; coordinate<3; coordinate++){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+2*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+3*gl_WorkGroupSize.y, coordinate)]; if (zeropad_0){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=vec2(0,0); + for (uint i=0; i < 4; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; + for (uint i=4; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=vec2(0,0); } else { - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+4*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+5*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+6*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+7*gl_WorkGroupSize.y, coordinate)]; + for (uint i=0; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; } memoryBarrierShared(); barrier(); + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + uint stageSize=1; float stageAngle=M_PI; @@ -464,7 +473,7 @@ void main() { //3x3 nonsymmetric convolution for a 3d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y+i*gl_WorkGroupSize.y, 0); + uint icellkernel= indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(fft_dim), 0); float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x + kernel[icellkernel+2*inputStride_3].x * temp2[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y - kernel[icellkernel+2*inputStride_3].y * temp2[i].y; float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].x * temp2[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x + kernel[icellkernel+2*inputStride_3].y * temp2[i].x; float temp_spin_real1 = kernel[icellkernel+3*inputStride_3].x * temp0[i].x + kernel[icellkernel+4*inputStride_3].x * temp1[i].x + kernel[icellkernel+5*inputStride_3].x * temp2[i].x - kernel[icellkernel+3*inputStride_3].y * temp0[i].y - kernel[icellkernel+4*inputStride_3].y * temp1[i].y - kernel[icellkernel+5*inputStride_3].y * temp2[i].y; @@ -723,16 +732,24 @@ void main() { barrier(); } - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - if (!zeropad_0){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - } + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if (zeropad_0){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } else { + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } memoryBarrierShared(); barrier(); } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_nonsymmetric_3x3.spv index f153de28e1a3bf24f2bb0a5c14a67177505a84aa..65f028aa9f216a6c5db00022506b32230a384b4c 100644 GIT binary patch literal 91648 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 literal 93588 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 G>wf_F74_=? diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.comp b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.comp index d948e1377..6ab3157e5 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.comp @@ -5,7 +5,6 @@ const float M_SQRT1_2 = 0.70710678118654752440084436210485; layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -199,24 +202,30 @@ void main() { vec2 temp1[8]; for(uint coordinate=0; coordinate<2; coordinate++){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+2*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+3*gl_WorkGroupSize.y, coordinate)]; if (zeropad_0){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=vec2(0,0); + for (uint i=0; i < 4; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; + for (uint i=4; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=vec2(0,0); } else { - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+4*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+5*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+6*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+7*gl_WorkGroupSize.y, coordinate)]; + for (uint i=0; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; } memoryBarrierShared(); barrier(); + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + uint stageSize=1; float stageAngle=M_PI; @@ -451,7 +460,7 @@ void main() { //2x2 symmetric convolution for a 2d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y+i*gl_WorkGroupSize.y, 0); + uint icellkernel= indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(fft_dim), 0); float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+2*inputStride_3].x * temp1[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+2*inputStride_3].y * temp1[i].y; @@ -695,17 +704,25 @@ void main() { memoryBarrierShared(); barrier(); } - - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - if (!zeropad_0){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - } + + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if (zeropad_0){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } else { + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } memoryBarrierShared(); barrier(); } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_2x2.spv index 47b63b88103b33ce53cac737c21123c1d4a66393..b3acc62791aa5c5eb854a97ebbb75322fd0867a4 100644 GIT binary patch literal 83148 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.comp index 46e352ef8..5a86c0526 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.comp @@ -5,7 +5,6 @@ const float M_SQRT1_2 = 0.70710678118654752440084436210485; layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -197,27 +200,33 @@ void main() { vec2 temp0[8]; vec2 temp1[8]; vec2 temp2[8]; - + for(uint coordinate=0; coordinate<3; coordinate++){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+2*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+3*gl_WorkGroupSize.y, coordinate)]; if (zeropad_0){ - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=vec2(0,0); + for (uint i=0; i < 4; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; + for (uint i=4; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=vec2(0,0); } else { - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+4*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+5*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+6*gl_WorkGroupSize.y, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x, gl_LocalInvocationID.y+7*gl_WorkGroupSize.y, coordinate)]; + for (uint i=0; i < 8; i++) + sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]=inputs[indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]; } memoryBarrierShared(); barrier(); + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; + float stageAngle=M_PI; //0-numStages stage @@ -463,7 +472,7 @@ void main() { //3x3 symmetric convolution for a 3d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y+i*gl_WorkGroupSize.y, 0); + uint icellkernel= indexInput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)%(stageStartSize)+(gl_GlobalInvocationID.x/fft_dim_x/stageStartSize)*(fft_dim), 0); float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x + kernel[icellkernel+2*inputStride_3].x * temp2[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y - kernel[icellkernel+2*inputStride_3].y * temp2[i].y; float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].x * temp2[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x + kernel[icellkernel+2*inputStride_3].y * temp2[i].x; float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x + kernel[icellkernel+4*inputStride_3].x * temp2[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y - kernel[icellkernel+4*inputStride_3].y * temp2[i].y; @@ -636,6 +645,7 @@ void main() { } } + memoryBarrierShared(); barrier(); switch(current_radix){ @@ -721,17 +731,24 @@ void main() { memoryBarrierShared(); barrier(); } - - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+2*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+2*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+3*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+3*gl_WorkGroupSize.y))]; - if (!zeropad_0){ - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+4*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+4*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+5*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+5*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+6*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+6*gl_WorkGroupSize.y))]; - outputs[indexOutput(gl_GlobalInvocationID.x, (gl_LocalInvocationID.y+7*gl_WorkGroupSize.y), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+7*gl_WorkGroupSize.y))]; - } + if (passID>0){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x/fft_dim_x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if (zeropad_0){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } else { + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(fft_dim_x), (gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/fft_dim_x)*(fft_dim), coordinate)]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + } memoryBarrierShared(); barrier(); } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.spv b/core/thirdparty/VkFFT/shaders/vkFFT_grouped_convolution_symmetric_3x3.spv index 716a9c3bdf8d392a0097749cfa2f6ac70a1a9910..a7310a0fac6004246bf655170cd1bd98d2e798b0 100644 GIT binary patch literal 91552 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 LuWd|z_x1k(SzXt_ literal 93492 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®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 + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=(inverse) ? -M_PI : M_PI; //0-numStages stage @@ -435,38 +423,24 @@ void main() { memoryBarrierShared(); barrier(); } - - if ((zeropad_0)&&(inverse)){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)&&(inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)&&(inverse)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c.spv index 7e9a45b5cfa665566b89f01e273397f65d7abb43..e7f1cccf44b14a41e08774563947521ff51f476f 100644 GIT binary patch literal 48036 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 KwT;Q29sPeKz-BW5 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_afterR2C.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_afterR2C.comp deleted file mode 100644 index e0280b115..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_afterR2C.comp +++ /dev/null @@ -1,485 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; -uint indexInput(uint index) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3+ consts.batchID * inputStride_4; -} -uint indexOutput(uint index) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + consts.coordinate * outputStride_3+ consts.batchID * outputStride_4; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim]; - -void main() { - - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - } - - } - memoryBarrierShared(); - barrier(); - - vec2 temp[8]; - uint stageSize=1; - float stageAngle=(inverse) ? -M_PI : M_PI; - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (noCuU-rN6 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 - return; - - if (ratioDirection_0){ - for (uint i=0; i<8; i++) - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; - - }else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - } - - - memoryBarrierShared(); - barrier(); - - vec2 temp[8]; - uint stageSize=1; - float stageAngle=(inverse) ? -M_PI : M_PI; - //0-numStages stage - - for (uint n=0; n < numStages; n++){ - uint current_radix = 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 + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + + float stageAngle=(inverse) ? -M_PI : M_PI; + for (uint n=0; n < numStages; n++){ + uint current_radix = (n0)&&(inverse)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_GlobalInvocationID.x)*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))/float(fft_dim_full)); + uint index=(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)&&(inverse)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(stageStartSize) + stageStartSize*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/stageStartSize)*(stageStartSize*fft_dim))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + + } else { + + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_GlobalInvocationID.x%(stageStartSize) + stageStartSize*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y)+(gl_GlobalInvocationID.x/stageStartSize)*(stageStartSize*fft_dim))]=sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x*(gl_LocalInvocationID.y+i*gl_WorkGroupSize.y))]; + + } +} diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_strided.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2c_strided.spv new file mode 100644 index 0000000000000000000000000000000000000000..496722edd6446efda1752f825c567ede341afe7f GIT binary patch literal 49040 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 literal 0 HcmV?d00001 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.comp index a80453279..855770f95 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_c2r.spv index 72446730f423c471251a40e26baa78f7253de86f..401a81f8cdbd24896c3eb47ca73dfe28cb9ee3f7 100644 GIT binary patch delta 380 zcmX?bg89!$W?p6{Wp)MzMg|Tbtlr2wkvp7?p_Ge(AuX*WJ|#0ZKCLt-hXDv!8Q2)g zfa1j^iRr1qC5c5P!I@R5AaPcPawPQ?V6`j^6+p3~#FEVXctfBHc81Ey8@a{#SQ%It zs(>;DiN(d9E}M^WTQN;G;L8XU0_t)H%7JWP1hR#pe2~c?z6g{LG8M#^gz_t)d}$~j zWHv}%Zu3gMayBj#prhGjqSn}irVjR3P zfy!Z`I-Bo`rE~ZJ1BSr}=r)i+Aon5jLGDB5gWLyH&S1d6%peG)LGFX;1-XrZVRMlD GyCVP%Y&!G+ delta 215 zcmex!lKH?1W?p6{Wp)MzMg|TbEZ@jGkz0d>p_Ge(p(wE=Ge6#tft7)sp$x`%$t+4u z28!naB^WkK@mMiwDzSoeGcX7Nu{#3`!&fL@7|Nf?29Xz;?8}!gCnF!J)y_uK4 zoQ>BAs1c}+0c_ajnWDywa3QdHlOKvD!$rU*ZjKaB=iuW2>M>woW)K9@Wn7#26y6;H E0Lq9WQ2+n{ diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.comp index 16e5f0410..4b238a25c 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -199,45 +202,29 @@ shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, void main() { vec2 temp0[8]; - if (zeropad_0){ - if (ratioDirection_0){ - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -457,7 +444,7 @@ void main() { vec2 temp0_out[8]; //1x1 convolution for a 1d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInputKernel(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, batchID); + uint icellkernel= indexInputKernel(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, batchID); temp0_out[i].x = kernel[icellkernel ].x * temp0[i].x - kernel[icellkernel ].y * temp0[i].y; temp0_out[i].y = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel ].y * temp0[i].x; @@ -681,54 +668,24 @@ void main() { memoryBarrierShared(); barrier(); } - if (zeropad_0){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, batchID)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } - } - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, batchID)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, batchID)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } memoryBarrierShared(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_1x1.spv index c19f750f39ba8a94b16de25f7b97b137606acfe8..aace272d2a1d29f3bf1423593a4ab1ec4750b599 100644 GIT binary patch literal 74108 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

    i)v0Le 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_1x1.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_1x1.comp deleted file mode 100644 index 6e9db7d73..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_1x1.comp +++ /dev/null @@ -1,766 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batch; -} consts; - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; - -layout(std430, binding = 2) readonly buffer Kernel_FFT { - vec2 kernel []; -}; -uint indexInput(uint index) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3; -} -uint indexOutput(uint index, uint batchID) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + consts.coordinate * outputStride_3 + batchID * outputStride_4; -} - -uint indexInputKernel(uint index, uint batchID) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + consts.coordinate * inputStride_3 + batchID * inputStride_4; -} - -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w, float inverse) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse < 0 ) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w, float inverse) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse < 0) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse < 0) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse < 0) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, gl_WorkGroupSize.y - grouped consequential ffts - -void main() { - - vec2 temp0[8]; - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - } - - } - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=M_PI; - - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = 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 Wq{gA>vc`j(cyk)BZA|{`>;D0emv8|9 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.comp deleted file mode 100644 index dead9bf76..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.comp +++ /dev/null @@ -1,800 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; - -layout(std430, binding = 2) readonly buffer Kernel_FFT { - vec2 kernel []; -}; -uint indexInput(uint index, uint coordinate) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + coordinate * inputStride_3; -} -uint indexOutput(uint index, uint coordinate) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + coordinate * outputStride_3; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w, float inverse) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse < 0 ) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w, float inverse) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse < 0) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse < 0) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse < 0) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, gl_WorkGroupSize.y - grouped consequential ffts - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - - for(uint coordinate=0; coordinate<2; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - - } - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=M_PI; - - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = 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�B$=hDKv2-m8rJyjQsIhkV{E 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.comp deleted file mode 100644 index 33269f376..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.comp +++ /dev/null @@ -1,827 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; - -layout(std430, binding = 2) readonly buffer Kernel_FFT { - vec2 kernel []; -}; -uint indexInput(uint index, uint coordinate) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + coordinate * inputStride_3; -} -uint indexOutput(uint index, uint coordinate) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + coordinate * outputStride_3; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w, float inverse) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse < 0 ) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w, float inverse) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse < 0) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse < 0) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse < 0) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, gl_WorkGroupSize.y - grouped consequential ffts - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - vec2 temp2[8]; - - for(uint coordinate=0; coordinate<3; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - - } - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=M_PI; - - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (neS)WGj412Ru}f2*>>pNZ-9ZN*tWy61KVC~i$ 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 b%xMm7V^ZT9=vw2NUA#Gs*ES}9_x1k)8$4&^ diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_2x2.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_2x2.comp deleted file mode 100644 index 2f5f29e57..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_2x2.comp +++ /dev/null @@ -1,800 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; - -layout(std430, binding = 2) readonly buffer Kernel_FFT { - vec2 kernel []; -}; -uint indexInput(uint index, uint coordinate) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + coordinate * inputStride_3; -} -uint indexOutput(uint index, uint coordinate) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + coordinate * outputStride_3; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w, float inverse) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse < 0 ) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w, float inverse) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse < 0) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse < 0) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse < 0) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, gl_WorkGroupSize.y - grouped consequential ffts - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - - for(uint coordinate=0; coordinate<2; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - - } - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=M_PI; - - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (n8y0yI_hP%52g1c*Q7~EY#1Og#}2<`+YI5W7rySux)O>lPxm+yH_dND;! z_Wl3d+tX{UcU9Hf@#`yFzuutDT*BH3#u%UAdTX1RqA5HJriFNQUt#LT_9yDlhpZ)`T z4ehI^8@V;@*Bv&r?7;TpC)Tu|;D6eW-I@|@*Fi)25A8o_;D$R6>(_5U-zJIen>;$T zCL87H$Z2x$;9j^nccJDf!dLD;xNmQJ8I{*89eSVsdoDD`?)?_pa-pr4=0suUH50Mj zdkq-YcZj@GYi9T!99>wSc{mU5MY}~h+AT7wUBAEPWX`JXTz|Fg+?pHQf8g$Y2M_7n z(buBsYl)7&mZoI-;vJkBUbkPrA$^C^f7jNM(KZ}9xPPC%+j`+x zgV)9m1GZglz@Y7W4OnB~?t^+eVFTA#xg*}SwNlk?!A4)b(#_9t)~a;#R9~O-ppIp4 zl4|q~|I+`PnEuUboq^T2u5|`h?^Wvz?D`Er@7HhWwtf2V(!qCw5AD0luADmfsTE&| zYyZFTPOT}~5dB&3F8tq??47?~(_LD<(e~~;c+jrB`ZROet#wwM$d`h>9Ou@zdc$`t%y=+}i#u_{yUwm2~Og=Gfnt1G060 zoP)=I`Y*2fyQJcGSNy(;KU48%D?YN~?^OKTihoz}X?cMw=VOM7FHrFXE51s_SFQLK z72mSrr&s)pil15WvnzgH#jmOOwH3dv;S@Cx&{%*xT zsraWA|GDD7RQ%V9kI9X(T<=a5pQPfGR(!IGPh0WnDn56`=c)L-6t%)_(9ILwoJe zcf1zYuB>nduch`w;l(YTpaJto=xMS$k@^5WURx;)-8d@t-UHYsG*6 z8}HVdV667FOh&A%Wor27YMBwetYv<9S<9&Ro1I&`qnEYpS@FI9#=Eu7f{%WlyR|ML zw*7!Xy?6efHR#g1l-Q{EuWR@TsN;HFhz~vO`dWfmyS|nsR`+$;|Iybq|3_ap{!d?> zThs92%WHSkd;CtVSK<9TuH!DPk>cKc2MpM`@8E%b2XtK9AEA|V`0?L(*Vdx)^v(aK>sRm68i8KF7vE^SW<846vyGz_uVNTjJGYL7m-Bpl#qX>50~PUOq&Z{m=h5 z-mSG1eDv3A=T=W*WlgKVM_1FD=w(g2!^<)EtoYs)f1=_~Rs5O1@oue=@OC+WNUY5H zGx+Fo{sz6wc{RRVD05z;;%okmcWVuVcjU0npuxNJ8qk05j*rNr?pcEp`=9HiTWc7x zcCP_@6RTeXCglr~cH>Nz*l5O?hFH6CW+YaRb9(w3O+9BMHkxtH`#;9Hcr@coJ<y!FRb__6~Cq8 zw^sa#ia%NLkrjWZ;@?&Lhl+Qd`0wk|t>V*EeATmB7Y%ThM8I=J6W%BN|#KNm2U zaKDF?Pu0Zzd4YV|h7WJr+lTod+HikvAU~|(oI3d70NYR9aKDqZZTdeGZf?%!>a2j@ zG5T-TQ78K7)S)TczuzzVeZBv}XC6gIjYntp?|1*k{R}GiyMMW#J>^q2+|P${FA?K@ zW|B|Za6fm*{keki&sa#BH2HS!cn=KisK@+$Pwc-kf3@WAd*L#F`ONq;f8H}4FY`Se z{J-P<_dZ$n@4Ykqd(SNUm)pO6n!ooean{2vQs>Um}|HfQnVxU6v|4*$&rcYF`^nd#H(LmYiFTAG7i zQtHs)Uhi_ppSu~~IhRidcfadVa}4*VW2?(&Xt*Bpn~}3^ z^%+Z_-NDX*ea^;NznXo_&e=ZICqe&^?GziRfg0B8GE zx1R+$+mCwsSqPtV_R{_wo^ zFHCk`Bfj?AMxU|xya#ygE`rZGPBhNhwQ;{i|0lZZZ$IV{{a^6maO1Xd51a~i4;b^> zJB_n*sBXP-f1af_J@evyNB<09?>TbYoz293(%i*@UX|E)Iuw+p`>*W5Y$1kC^c)&5h+=*IgD-SPD6$#`G2@qbc8~<;OzdK{-Nq%E6NnXQgKPG&1`E^1cj!(ayv>yv>ooPQde01%{K_8A!zn-+8 z5bPdF`-$MAYd!9bpB=0hvRqs^u)hn8~;j$Ur+q&xAAY#_+2kO@o(D3 zzggke6Mw%p{v8^BckP^~AqI8~=)p-|In7 z{Qqdj~_if|fukh=M|A;pJBOAZhkDmBPwDBKX`1QnpS{wiA zjlVnj>xuvDHvV%8zn=InZ{xqB@q7K~iT|25{%Z@rp7`%*sK? z(G&j+ZTvG9em(Ke+r~d%-G=y;q>Emt0(?Rc#||b z|D@>g>xqAcHvSn4zn=IPZsT91@q3-?iGTGr{xu4}p7=Lv&g7(`<}Evx$!wK z#-g87v@i9K+W5b({24FbC#Bz|SiH=uvFNKby7N)$>ot0J@+irts{ZZ<> zHM-YzslSgty7m8{@jEYilIQ1b{9hD)J@Jpt7o(%=e;oAT^liO*;-9#Uf0Dwl$9?9$ znjg%+zdmnY+`$iAF7b&*eLuHc`d<`2x_lNxHy`WO6aNZr{3|wo^Vbvq+HL&nH2&`N zuP6S^+xWL={I0K_`1`i;_iOyFyPo)WYvUi>_`M$V#D8KN|4EJC`Oy>q*=_viG=Aqt zPyCm+@n6ySogY2%-`vK3OXGKb^u&LE8~+21-}%uK|I=;!&oqALM~~kj_+4-@&T zuP5W))5d>q<98kP#Q#Ja|C5csJ2mNv|CKiWR~x_Us3-pS+W6mZ{H~*(_`ho7|GM$J zj(XysXuQ$S&&24%n|09>|8#Bq(>H$SM^F57wDHf`_`5TPp7V10uIT3DI_Zgjnl}Dv3%{QDXK&;0QTX-5-?!1-=jHo|T?@Z@ z=6x7?t99T#X@6Ur_77L>;~$qF9A@6j`}`D*ZvCY`bE9`>)KZ_P(Y@|Ueep*3`YQDm z8{O-u)bB9_?;I$$^YRt{znSGp7=j%zO{Pn~?Ya4&}!mlU(dD{5rZT#l1C;lbc z_?ImFdg5Q9jeo_)-<|c+6aU(6{Oc5cJ@IeS#=mLf_q9S#{M)zj_b&W;;@`QAe?a5+ zHAheUd$jTIS@`wDe_$K`L5<(nEc z8~<;O-|I(D{N4CL`1*|L&(r)DeJu3haQ%9sPt?XgapUh!8$Iz)*Tz46;nx%YY;F9r zH-4`lJ@GHt#=lVE*AxFzZTw3&ey<-r@vqv(zgpqf6aTtx{OdJ-uOB_}Z`sDbRpHl@ zpVj)i8NvQuMqYpOI~n2mos1c{-}t*1e4W#Act7e7_am^n_anK#X9P<=Et6AnpAjti0u^7d;yxo-`d6*^78T#J;-^>q zjDkC#J|kH6?=ylWKd<7~RQ%e4+uwBsw;!JoEc^2r!IJxoV96gXxc&KzU>Se5;?Grl zWX0bpxc$9baQpQc!Lom!5iGgS2$uYpg4^G(1=r^@f~DVQ1WWESf+hDE!EpQY8NqPR zJ|kFipAjs%&j^;>X9UCTZ{C8d`;1`Xo_$8JeNM0R`wD;M!lKcEx$$f6E92EL^|OmWB6#`)paseYPyzv(J;2+-Jy2?sH?| zJ@EU?Sh#1O6DzsThLzms!NPms_gS!T&p!WEa-aDsxzBl(+~=}N?sHis_qnW+`&?GZ zeJ-oyt5@9TvdZ|@75BNUGQMBMeIBcf`#e^-?}vOIE8O#G7590pGVb$OCHHx(lKVVX z$$cKH&tsL`=dnue z^H?SKd90HAJXXnl9;@U&k5zJ?$11tcW0l^OzxX)xI?)v*o zR=DT;EABH{W!z`7O71gRCHI-ElKV_n$$ciPG5~f`*0k|=Q2HFJv$a2e}{bsj>#I2 zcm>AnNgq3b`*Zj^Gs$abxOzOhfc;(f(lZdQelY!5%OJ3tp477|+`f#N(_qg2GjC(N zaoogV-eTv}?@KbLLz|dq=X7_@dvN&AIo-2~drt0qf$bwX>ZeN-N9hns>gE(*j(3dJV$`@U1P>O z5>216^mP>2{){_6w&*vTB%a5%@}^nC`{zB6~{g6p|E4^2I7&IgzCbOF4c zrwh^a8OuCf1hy|@*6DX=YU%e<@Rm*N63+4^nJMS$GB9sNJK7jq0rhguS8(`z!-&RX zU;bR{$|h!ASAnnQ@c9Yrb!@pFuUqHJd2xP{%eCOli|w!Hu)VtN<=1hP?d?bIp0Gd9 z>F)-xbC$Wd5!|7XtNj^Mv;9!cws%j+-KX-KIA@)12G@Jz7BuxMsoB@BTfu7X1FwnO z!T$4_Fm@Y7XEcXO6!F75|so$mw7v(68I zU1!@E%Q`;@&N}PKIzI$9mUVs@>^hmFW6Sj<*GIs0J&&TPXWu^tKAgjUS+B?8`i!No zC%|=IPok-(ucyFuUr(dyGiHv@a8}FwJO|GFJPVd*ex3(AKejQJ`FR1H`O%a4c@bF_-b7PRyMKe#-sW)Zk(||1_q*WK z{SH{3y59p^w{482?)Sl|TTkl#0BkIEe+ag2b9ZdHp5*@#xX%A$H1*{FIauv8j=XH5baQ(VG7n(j}nZvokj$thQ&jYUe zpBGI%{m%!k`=1|8pE2w8XK!km>xICXYkv+W&s;AIcCKw>EOWgGICHHhbG<0oSmt^$ zuybuajxE=dnidDwbG-zbdggjbuyd`Rc1wZlxmX%aJ#)AmSZ&!tTOMqG#?n_$aNXAm zXzJ-}Ww4shAzH^OoYgXitAR6ztAgd3!_~pgp>2$14%Yx@4)tUX{{c3ZIb0L$9Gbgh z%k?DxwZQcpu8pRiIa~+q9IB_?y5PF*_0ZH)_l97#4GL`|u>BcJUmJt#zBWNqPhXpZ z)i&d>jx9K=We&FjXAZXn%QJ^tgPlX$7|R@P1I`@k$sBGAHkLWu4(uG7yJO4sB>!IE zdJeZoQ_mds20Mr9Y1ao_*WDLQJ$3I0R@vjvQC{9Fc81qE4nR{+ zj=O-(Q9U^h1lKtZLQ_wUgTZRM71|K6{TWM+L&4@~%pB!qj>F(}j=Q6&C&xX&=BS<= z_XO8D?uDkF9QOsQ?Ney`f$h&&a@-$mj>gPUUgmfJyw34JH1*_o5ZD~mljFhQI>$rM z)RW_3V6{UF?QpRD8B2~wfX&gEIm&bY&i&f6_w&A-y?-Bx$InwobM~K~r}_~)3jPK^ zKh+~nzQ=(36EE-aBhb|2ITk#i@*Ibzp6_&y2dkCe>6`$!FJtC(66fS(>_m=@nw-QL z?__X2_otw#XYT(AcJ9^F?qA?~?oUNi&)lB|wynBzdOBw{@fn2n7%ULaJ@H{wc@Elm4HFyE+8ra5I*5E~O)<93z;3crJtij7**T5Pa zTdpVhzXGn;;8isBtifww*FZh(UI*88zk#Nny59ubRz2Fk!Rl{wn9oSgYT|b|XARy3 zmuv7I+%?dz&vVt$MVd z!0JD8n9t9g)x^JW&Kmp*F4y2UxND$apYi1KJGjo}4>a|RI|lbcHD1a)#`5>&)UpPh z!C3=;cTS!)=mK^PY-22I&=s6D(33Uj1~!&87z^wgSc7%S^(6nX!Sx!9gQlJ}7#Hjs zsHfd{;JWVd(bQA-1Yp~$N1GU|?%&ujAAdJcP3-RlW)1wEz;X>Hhr0&)^%+ktQ-JGS zrbJWExYK~u{97H4j8)I368NpctJz0a9z{au$GlN|N zYjAA2p5#9ZxL$)<(bTgB-NCMbdfLqfuIrv1O+9t@0NYkQ+FW3D{|<@y`1_P;JWVR(bQ9S zPq1y(qpbv1Uy;LnR_3fGUWIekU{!Fr2CKnc1O57pCzsX1buMe5sb}1^z-nu9IM&*n z)v^Zbg0lwefaO_(^}w!yZH#3N)(2+|^kfY-02|91YzTG@tiiG6diGjg&(BB3Hset9^N~0|Z&J%RTY~F(+X_uRo^3|s*%nRR zTDIma&ph@5XCAi$%QKJLgPlj)7|T5N24^1iWFGr~jb$GDf}KZmbZohvS?z> zSZzNJ$3B3wTIxOsoVpJL%TxEkVC%MxvDAGCICbku-NV7gQum=?>o#}Cmg`CWhk@(- z4@Xl^{zrk;j^s$Yqrr8%W6;#o?l`d8u^f(lJZH7keIht@p8%Gp?vudQZ5v~$`($wH z)|0wV0UJx*{{&mNxjVL8PxAj4xX%AnH1*_v23YNMj(5O+D?-1*@II;n?SK zR!iL%fK&JRV0r4k5NzGHF_yY70;g_0srzEEvDAGD*t*T#vE_P_|E1tM|I5(SlmC@q zwJSK%?kaHI?rJpkw7U+hb}ffvU(Z=Bb>9e1-8X>csrx3db=$^R>b@DAy7i>)TfoLr z_pM;-Hh0IC>q-8%f$RKlM^jJ!cY)RJa5pe3(le!-T8%y1ffvwxz9b2v^`9BV>^M3+OJ^4QkR(pyg?VbVG z?Vd$bPrDbuYR_{x_KTd=QuoW?)cq1zp1NNFTeoeDrS4b3sasF#ehq9ab-xa_ZgY2R zxt{WUgYO^YM|1XG{|52Y_a@l-%I`woLQ~IsySKrFoVnAJx%&icEOYlM*ts)L$Cm3! zuAhPHx%nJTJ#+H~*ttRH)#5dWe&duJBG3J{~fsQ|9dp` z^#31l-Tx10`ixockDS#q*FS?Z*FS;fnd@J`&b4ifWv+h(XRh^Ru73j?%Uu5scCM|* zvE_PF(;wh^uKz?+&s_V9XU?^H+Kqu$&&8N%>Y2kXU^V}?UbL=Y`!kllx`FGy#zIq1 zyK%v4{@p$6@Odn?%;5y!%%RU_$uox&f}KO#7|R?^1kN1l$sA4$HkLV@1neA|yJO4s zB>zdl^&C!yrk**R9PAvbr`;6by6!2_)Km8~U^V}KV6ZyBvu$q4(G1>xP`!kll76jLQErh0?c8h}5{QHU4 z;d6aznZqT(nM0rPlV=W>1UrYeF_t-83Yp5Hw zO+9nCJlHu@PrIJry6zRw)KmA$`Z@eNkkM8F+h0elHR|`aSB2Mot%jzacK-mY`8Oi1 zV@=L#nZvcgnZvcf^335nVCT>_#xjTNf-{GDGKcGdjb#qk2Rn!6?$~lYnTrj;^&D=9 zrk*+62<#lHr`^Wjy6#QT)KmB7U^V~NWwb58_Gc`8Z3(XX+6qlQ?Y0H0ZNp(5+i_OQ z9BvQJ9QFdsGl#vw&Y^9LWe)p*GlzOIhke1uGKc-Z&Y`(Gwp>s0-vM0D;f`qPnZy2I z=TJTEb^_OR?~JCNx(9;Qb}6($VEZ$czIFxIeeH&(p1y{H)rN3b$1u)nnZrH6nZw<| z^336$VCT>_#xjR{fis7CGKYJEjb#q^0Xv80?$~lY<@-h7H_G$#cF*tN^*!Uhct^H6 zcRZ8fa~X2`*^jevvCsG((C7zp&hrZgfqg&f+25`1gq^zM*fY!v%qS` zK2}e=%fa>hUV)~by>}(pw(8jvSApFV#;nC0uLi5@@j1+Ez!!7)oP#;b^%r!%o_05Y>zr>yQ%}w}fo-cE?G~{5%^a!YRZSSM0r?wBk)~23zAA;-JK0;GZZ6AYetDf3E0oS#Cil*0C+I|LBFJBKnhg+|) z)cXZkJ@tMGw%)uR$o1&=_2BC!?p%BYmZz_8!LGfrZ#c{Idhi|C*8|%aOMl;k)okOq z^5pU#u$p^4WBdSDkLO3QdpY^a^(6iiIQ68DpV8Fg`2}nr{&$hgL$1eoPsaWgT(8w{ zXzH2oKf!8$a5xU9jt61Oy+4Kz#&VQd__xtNZum?aO^WIoRvonDx2OrvR(#ai32K&b4M8 zay`jsDsWxL)M)CdV;Zn^sHfeu;JS|K(A1Oj^kCbnN1F+(?%%zSHZxeg+|#qbt<6|! zn-#2{+PZ_Y2dqu5N56Y|_9kx3zh@&)Uvq%7r+a|q+0%1^-P5))mj31ftJ$C9%9G37 z;LLNzmhUZ9wh#Z?X7(Z1W4tH*E(osIWg#^6 z%=e;TwM94_hwfU7fy+I;I9#pV(@Vf@Ys|6TziR1YNpQKRmx8MqcTX=3F8A~@a6Rhw z=l)fTe_3$3rY4M^z_wM7_7AZ78XWfJo?a8|b#Ki2+|z4;)%Cci*9PZWvktkQ;Y?&>(TF?-l~Zk+Y&5KU)zAQr?&>nv!}NOyQghqEd6ZhW+c6wKKTf&ja9U<$m4;ZaZU+yCY|{^f3smmV5NBU^V0J=iR{NejcosL*4!ca#o9f zC|E7`=waaOXJhg0UitQDeC}ss+0T1|?Zdd^`8UPXGEaMh>wT~fntJxZzF_x(dfM#= zuIG1uH1%Bb2k7BYx1D?UK(N=hF>7(}9t2j`{mfaeCu1K1u5%uark_?qelkbu_$SypjHQl$fz?yTsbK5KJz1_N z`J4u>>o{FMN9s5OY#r)pcP6;5<194wRw(8N&1*@OKkvh%;TZggKaXwf*bzA_p zj=T=Z_2{3C+%9V3UUL_M<>~7ZuzSbY#hm5hOF56Et&v^R39IS3T z^N^?iE5Q1VIgUJeUkTRleu)1nxOzNSgMEF>o{{TG{2H)*crB)nYvJngTnDy~tg~EC z;@5-i!+83*0j?g;jbQu8_bYNeiQfda57!`l+zeNb=N7PiI9s%2j@mybOna@YT_5OVf zO+EYfaj^SWJ?)+V*X!^kntJx?Q()VwXKkJa*K6|(nqFh}@4ez#uzT8=HG8jk4y>-n zd&To$ucuu1ay`lM1#n&4i)iYp?Ip0asi)n`;JUU~(9~1gt6ot~o-vX{rfm@$Z~R(l+;~Kj8DgZLiOG`u`KGZaedk zr+uzi&Gs4i&g@pJ{-N9ISaC-H7z z`zY^GW1*?XGd9>h@|~YtPvYZ%?W4R$jfm>jH@d(jkNHRIlkrUaMwqN(6|)a}o| z@v9d9G+?#di>3wVUSur3=_=p!jn8|LvD}Mh0NaOg$MbIpt7V>M0@wR_W;FHe=UKq+ zXZ5t36J1lg6yYdrS|ox*qQ_bAbKZ#<|DH^zwCBQ%}zGfo-cEZ2_>l|1G4{u^`wwjHQl+!0M@EVX$>%|H<_v zpGClR9gCu=r;f$I)}fwui-YSrmOxWa&P#%As~&A>u)6=<%G9w8*gA}*j%C5>sbe{? zb>yBP*OPpf2iJA4D}b#-J?&Nm*LAFfrk)0GkJvnaywyk=!t-$JA za-@!}!Pa3cb!-DxPaWHWtt0mZxt`>+9k{Ne7n*wN*dA;h>S@;-T-VVDO+7jH1>06V z+74j#ejKS|N3eAmOC9~e>ZxNVuyy3~lUz^o*%@5dF#t_Hb?gGR4)wGf2(IfGgr=UH zcLm#4J=$Qf`fePlV+hzfjHQmDVD;273~U{_$IA8SpP$_JXyV>Sb_dJT*IwYMIgIVe zSuWn2^GMp}z0f}JMd7yBXFUDy3s$$CdC1fMeqjB^97mqK_Xq1Q-wPc8SC8jFul<$QOhO5VO2-rUIdM?+K_;9d&l<$QOg{#MN7}!4YS}NC*_~BstDBlYm z0auUbNU(k6bxf`&@uR@@;p;=@?`XJsJja0TBd;NHJ&BJ1+lPBIeH;r{kLNhBePsX2 z^(1~g*go7B>Ei^rdORnB?IU|ft|#%6!1m!anLbX2tH*N+*gkUI%Jr1*4gJpg|N1>T z`^M5bm3Bu0{C%@C!T$62&D7<7=X4t9&YVx@%>TE};D7u+T-}^{qMZ${_wG4p>KW@? zaQXi8Jh)o<{_}je?TmTtpT$`%<6H=?$GHeiJ>y&qwq1TN<`S?Tb^E-4vs(O@f%S)9 z4%U;`sw=>1{tjYZbFPHj&X|2(%2_RWUIngS1FuF?PruiIeGOF4*w=#XE8|=T)~BBJ zzaH%Rm;3()G<7|`@4ON0>!0n-Pp&8V-2|@lyBSSA`P~9GKlS8yE4a+>Hn=|Zcy0%~ z&Z*%JxIXpNa3|Or$~}7*ntE!u8*B}>w+6YM)Nl{Dz83C9Q_tt=`@r?*>HE?28B5L& zfXi$1LAY9ZZ9W9ItugcQno&zW4}%v7XDscv{zt_;zli%xL^HWcLZ-C4E-h}H@ zkLN9Lc@4h}*QcHu{tdQ<@}4mgO+7Wd1GWa+TZ3FrYIql1Uo-Easb~Lu2v+-mBl&#< zF0a>*;cDge`U%{&#vI%0LoH)}3a-cg3{5>_e+gFmf+J&p1-7qTn_q+VsXLC>om%|g zfc1xe3oftC@8D|XwfQ~VcE;?}^-@dj{{h!){{xzO*8WGZYpW#}3Q<#(?Wnk7rD9 zd2M!r>r+n+ox#>nz8C3&rk)zQf~~>!)*#oD8oGh&>tif5^;{q0g4M?1NPgpi%WHFd zxLSE_P5`&9F~|1$P|Mg8g6pv-LQ~J!lY-SI;mFvNf$b~T=HzgF>W<@erxyPdVEy4! z!pm!OD!5vCZB7lhoiY1#z0{KXG~jyer$tlG+D`{|?bS2(^x$&sXMpQdw{Ne_8Nse= z`F?pOG<7{*n=^x5SKFJPTu<_w1zhJhE1G)p>kc+Q_2f4jxXf>MxIXoGdVtGoa}KyZ z_0%vY*c!_BxO1VYr-r$~)?j;Ukn71f^MD;E`OXVhbDi`XQ`0{++I-;hd&vdhYV&jG zH>T!$=rdVQ-`}3jIdir!vHE&k1Wi3TEebBL`^DgD<#oR}+;+ws*Z;+u?21MKx-d-Id)Nq+wT z*ZHl9rk?!P0-K+D@>^TXk^I&H>+8_DmPo6$F1)k?7)?DjYy!3h_0+Jbm?Jf82G-Z1H#KYyFZa(DaJBMvZcDgrjis)w zz}8j1Z{HeCJ#}pZwl3RSmt0Tk+7?{bwH=yz>golyF7?#4y_h3)^#<$f(3`sYz{|S& z!qq+@pS0@-x2>_%wFB6?%KPPxXzHn}KiIl#Z(VXdscR>&b(Q}unw`+8^4qh524fS0d1N5b`~r-q}z)=<7TI2uhoH5>!B2HRVMTu*8k0j_H} z7EL`h90#@r_0({@m?Jfu0M^%`H#M9HFZbq2aJBL^=VZ8Tjis(rz}8iM&iW^sdg}TY z*t%?QU2;9C>r`-E*J)_#sq1vGb*ZPWGsGOJ>rAk|4!x=CEO=Sh*>JV;HRl|-ZH=X_ zbHUbCz7IMNO+9s;54JAbTbEo<^1A?Bj(s6qtvhw-H>RfF_dyqd%lAQ-z|}71&~Hqw zd>?d1@jmEsV$Ngv8g~VndUCoF?6`TYxC*XTzII&=x1BM^y^OP3*6UhuJKW&H zukq#ftS9S#3s}wnURl=rR=Dkq+2@U%)sp9J;QG3{9Zfy` z-U0TyQqS0Tg6%8g+y&OBp6laou-8ZVKIk4a^;{qKg1tU$Z+>z;$?raJo!|Xv>dEf` zu=%MczX!o(eh!I#8*E+W zJ>=hL>Zxla*t%?QU2;9C>m6`i*Sl!ysp~zkb*U%k_rYadAHemg$MYe$tm`AVny+`c z4nKz5)>!KL1Z-X9`_@m<)Kk}IVC%BIb;-x-)}@}DzXF$aeGS*A z9?v)6vaWC8YGZW%Z(ZNPZEGxbeGj&-^4|C#H1*W=1K7H3Z(VXdsq05@UDr=&>Z$8z zuyv^?=U>2OUBANhsmJphxUB1UxY}4nU4OuBYbZxlyuyxtqy5xE?_W0m(>J%>cGt`MzdGH1*Un6WF%uS*w}Bu9Y$8z~Aqh z1+1>e&laXg4I*UQef-we(s)->q$OKgX=n$K~qm1%Yv;#J?)kQ z*L5t9rkoAr&)(5Mnjt#)pk>A&l>q$Nvg6ldq zLQ_v28-uMwJ?%CD*L7@)rk*$T9o}BxDZL1z_2e5iSj?}Ru*gA}*j{acv)UgxT zI`Vrfay`jsXK-D|05tW~u?yHb)YEPtxUORmntF2H6>MAeXhXp2gE>;iP_T6vOC7_& z>ZxOQuyy2jXXJYRzwUM3d%V|7#W}g}39f723r#&W?+vzQ^|aduT-UrWntJNn4{TfY z)VDv_`i!N%1HkI3??ABcFLJMu>&e&$f$N+PMpIADhk(slJ?(~r>zog@4M%c53~XEV z+-nX8*Y}zu(DWKhZAXHw%~)zX3ap;mjs{y>?lp2f$?+I)UE2sW_0)DO*xJ<7?l^E= z+wo}XsqF-?ZPlZl3|2phBXyhtwhm*dv&U%E zt|$5239jq73r#(B+zqx4^|ZSOT-R|gntF1+4{TfYXb*zbAK*wG4}q=2Sn7Bfte!d^ z0b57zHF7=4=TUH7$75*fspE05b*QJ^6X3dzC(+cC^HX5ksz-Ykto{r~>Ua)p9mZ0} z^I-MV@dDU7a<7r=`Tu*bnHsO3leT3X?>(L!i!NI)6Z3OYa(o4@me)pOYPR31X}=9; z--Eo0p1+g$8rZ%)`*#xG;QS_s|7`nK6Zf34-v-;qwS2zuzdiqNu$rGg{X2>B*E#IV zzQtLCcfj=;yo;uu{@(-Jf9@gggL4nb`hI|>&sgT*L$G}rv(Aq=tBF76Y|Z{H3g_<= zxPRMHk1;(XIjbj+ufS?6@cHv=&fjo+$>F`#SUxNI8T;ENp0?k?t--&U*@O7^;AuG2 z%Xa^P8_VBE`~hrV>gnr8uz94;pTKHs(Qk758J^sXmt*__H=h1}1(&(~2KPEuFWdbN zHeoVOWwCw~gbL$Lu-qg!>UEs!& zTUW4ssUOnh)(vca#?t>-;Bqd6aOYLM%yUY(vE(@w z*uK=$*VN#04yS>um2)^PJh>S!bDIusJpD}%E_0g!?i{L@xy=YSmfU6n+n0K-$C<(A zY%KlH0xsumR(NtVR*umfZai&g1DCnY4tL(v%bI$?jU~4^!1kq{+~x$EpRx2m7r30u zx#4Q%T+RbezQ)UZ=Y<!qv*$7lS8v<7Ezu!;PoECBS9wOTwLN^|IYkaAV1RX|R2%r>|weWp2yC)t2SR zYv%IcsN^|IYsaAV1LZLoc*=XGfvusIt`|LcOweAkDot;do1 z-2j|?jhEwY2sfVoHUgLVZVY#R)ysC9z>Ou}O~Ll1o_se0o3k;m+l4u+Wvng0W$s(T z)ylcv3ZC4JmutK=+<5xi23+R8E!??QFLU1xZY;U?0^65*`q~~`=GF(U)|(^q+83PM zjF-9fgBwqOJAljFc7!{x>Sb>I;l`5NPGI{|&vm;q*qn`}{{i4K-(BEp@)9^kAbV@Gm$Yh+vjtSpHZxF z1iHBzI~Hu;p8ZU8Jm(WQ{Ac{cChj?7p9Hp#d?q>>tmf|#_?bw49EW|`w>WK20o&G} zd7aAHfBwu%J^Y_wf9CZs&bF7Y!28^uXs3be&%>vqsps?38Q=kU)zj`waQ#{AEHw4Z z;n`r@s@u+=XPpD~8YzD-&e*XgX^3xKvPf77lO@MJ?$<6 z*EwH|rk*LS!u0T^yZC8S=&GyzN*OMHt z0@t-&ji#R3t^r${dfHtJu4}svO+7hZ54Np(w41={H*%zoo59v`T2aR>XzHosRUacf9qMWKD7dcUF*Nn${5aUQ>d~G8t3Sz+I-Ukw z$I8WXz0aVjr;caA)?s_=kn2f4&w=YYo<~zp9WQ{bLp|+Y1lM)Egr=UHUk2M&J=$wv z^;bDk$LnD0@H@urk2lcNQ^%WN>#)6b$n_+jx4?BBZ=x#Lp|+Ag6lfoK~qo8 z?}BZs9_<6L`uiNI<3q4@l)qo{5t@4H_!w**wzm$sp5*fhxUS<dE;_ux-_&eFIkinj>|53$~8(_es7(Q%@b=gRR5%)*;v9z0CWI_Y?0c$?pen zUDuCj>Z$7|uyv`Y-Ou2gO+7hx2HRFW_meK*`hL5>Zxr!@Bm6vPrLEKb!`)%si(FH!M0V8HVIgLVvf`?DcCy7 z`^jWz>ZxOLuyxqpI^=qi&lKRgjw#X9Q^!=`0o0+Mc2k4vI;KHWPtMbVZL1z_2C(|{ z9I0bQuyvI8lbO)eQ^(9;>#)6b$n_+jS-^E2v!bb|j_%+A)S;esvw`b6W=B&`&ON}k zRgX3oSba{8)G;^MI?DUWJZS2vV_vXz*xowidXmq4;JS|a(bQAN0^kAEp`LaNg6ldK zLQ_x93xjQ|9&ItO`l1}EV{x!`l=qV*(9~1Ml3?qwy>-a-B%h_gbsbBisi%%*zyqj5 zJ?)kS*L5t1rkS?zIxUS_7jmin`pttJ0TqXU_dN^Xrza9XOkhde(L)aJ{xWqp4@C0bu7c&q3@0R&#Fi-|-p< zx1BNb?ax^)ee4QW%is0eP29x&u3<3PHOluFL%@2}?QalgHT%;)46K&F>$f}D&#(S> zyo|-SN9EhI@r{qqSpKfxUSRt$?s!8vt7V?{0oQwHUo`dXo&CTA=vO`M_6OJVdjOhx z_Q`=@+p1>|90Ya`7_$~XCmsw|*W>5pL%@4;_`b%R<$5yqaB!XTp=j#K`7rPR+N-DC z;ov&wBhb{7^O0cNsz*BttX}^20FH)Rhq2Ug3|KvNi~w6lzDJSk(LWuz9oNLI@mR1t zeVqVyt&APdS)TtMz=_~lXm1;1>F*@4nr$3co?K1_XHGN5DQN2P{1fbZ;>^2TPvZXq zr=Ik2Dw=vcr-ALm`>T1#^%(C-&ZmRxH8=xJJ?|0E1lR8o&qC8@%&~d-Xq^q-h$H*= z9I#rsf6s;6)|mOYSJl$TdEj#Yo)1?u?tZ)gyfH`i?}cDJ>h|YeRg3>3aJhdkhG+j8 zi|>-kcWL8u{~F8wy$oz0#vRXVLM`)oIk?^nSD>k9FI)*8K)>o~cNMr^hpW-lbKPG9 zwyk>B=2~#QHrJu)HD>>Qk99rR{b9_S-RC!e)%Cc~Zv^L>v^Ke(p`$%dTz|F9-P_=LfBYLwJ^N!McmVyXr`0`}`xY*S#_8bDw_pH$fQ%}xcfo-cE?OU+=H-+{cSiRiS-@~oVSZezZSUt7<0L~t; zHn|@C?&+VJxUnC>^7Qo!*fllwGiQ1B^siv|v~7%~zu&-WwsBl}a`_#sR_^IP;Og=G z33fl8M&I@!*OPdQi_kvG?_I|5!sLi&Ot5|A_YCEFjQ7Oa30$vBXEgP!K{v2kR}O1) zPmcxOh_SP$$A+twdwLwWZH<|~`&TV}j0-OJ^muSJG4!R4Nw0Io;f{@lN6@lOaY z_w+>Y>}g~1O1*l$8-JFGIx`K>%A~JntJxa6yO2$tDbgKg6lb- z3Qaw8J~i03>d~eHt53^eU+(GY!Cv>qtj|3?16W;;dwNE2t~KkB>q$N{f$KVEMpI86 zvw*EbJ?&-%*L8G9Q%}ybfo-cEZ4R({k3yRhtX}Tvx!~4jEVa!IR!?p7fU^gzO|D13 zdwRYmZfst#Jbf(y&YqqhEYF@^5bU0|jj{B%5LnIr99N!P76xaYGsYrl>hUZJc0b-p z-}WKbllWrb)RR6IM^ley39xUCNMP2Dlv&&z_# z{k)tpj&eUQ54W8$b6?6hNBUR+td@K9ieNS4?&p=j<$hinu1DSedU95ae^szrK3}f} z&VDu)-|CfbjmF2RWi0#oA7J}1?s%(kR?9rC1+MqO+Gy(82kU^{2kL3JF1ViG_0ZIF z&94u(t-9^pyBmPLzKvOndv`;yx*qrLM&LC$Mu5#(t|wz}46bwD1Wi3TZwfYN^|adz zT<5$wntF2H0&H9LXj_8S%m3!eR&eVumO8cutEY}_z}AuXr*b{XXIpSx$98DysiPOz zI@Hr{dvIMxZ#4Df+y`u1^=SRT>U}xv%k|g+Y#qi@$Btn2)X^Vo9l0mV^(3F2z;zuv zqp7Ek0buJ;PrF^fbsYoI)RXfdux-_&?FLrgl_PZw23v=*)G-9Co;rqtts}2Pay|O} zZ=~$e#J%Qr2g}pfUSRi*u{}A<#d~ue#_`wR1qaVVU$)n0JpJzrR=1sb$kYFRVEx7% zN1nX*2kRd}zwsXcSC8jFu&_e_6@q@tjQNC|F7_J`AAz=H+I?MGWJ{)Wx#*@dP zaP@c&1KUTwUy+xCZIt2)KGYM}qAm@89HljQ6D7QQ-QzIT}qppOudR*PoR~ zpy@N_*xmz<1()}LYn_ZH+m%OL109A18p-at}BWtY+MMz)9fp9&j>TkGlQ! za>q*|%f$Ms&M^jI|H-N2IJ?(A;*Y)0nrk%A3Cud%ef9jtyEhhw_FcYv+eSn9nKte$%B0$XohljM4m_ub&S-h0s0Q}4ZC>s3#? z`@nU*_oJyN=Lf*HRZqPSg6n!8Lepz3Z65)vKg^MO9|c>lvDEt*SUvSV4z}LhqvU$@ zdyjguiF>U-0hXt)r@^am7<-DdT>K2@VH~+fJqwbCPW=qIpy(wMb)kNFv_p0)l3{0+wlV&*K@ld*pV*E#=&rkRokjZ8^a&Aa?IcS{XXj$6K);GQb#ASdg|y5wvOySxt`?H z1zgwB6-_;LbOT$5dfJTzuIm^ZO+7h}1GcStwDG{|<8s)Sb&L&R=FTu<_u7F^dc9h!RTm>z5$>S;FvxUOSHH1*^>6WF%u(Pjaw&&-iJW(8Y^ zvDDEWte!e%16xPl^UL)lpV`569X-(0Q^y=&>rhX-Il*-ubD^mx=efbQRgX3=SbZLj z)G;5}I*g@``N8U`V*#*rsS;`JvlE1wyk=! zCBW*7bEJ+X!Pa3cbu0x|PaR8xts|eG3q&eAuzi&8g*HS}k7pyWedP6At|#%0!S+$U7up0(J)TX$_L0|8xt_!~ z1KUUWUTAYP^?0@b+eco<;LQb=&aHAg#Br^Ena`$Y!|Tq{CzWZ`IzvXICti}GiQI_YyfA!4_Eiv8pwJ6=I<-^ zB)%)W-p9M4sb}25;PSob5V%_TUUVqjcE%iM5N9>#!Ets6*W>Jgrk-*31luk@Q`-xy zN8LV$aaN0eAF%%LeZhM2y0srzt^7N$`@?N#%s%(#td=|v0N1aF2coH`--E!u9;#>T zgTeNd*SSN$`qXnR3Ory>tv~ zkn2kgM}q4bjzUvU4M&5mK|M7b11@VA0oSJ<&#_>yh17W*T%UUCJRWSFuU!ntHCIOTk`8>KXeoaCseF4%eq{-+otj1=wq( zyr*4>rfxs(g{#2jHF7mvkGlQ17p?(&jW~ui$n~X$Yr%C5*P*GWhU>xBpq?6T0GBn~ z2-l|`&rRTRFWd~*r=B`*0b6HzueudYJ$2p&F6+D;3__ZH+m$*O^+zeh^%b{ScaZ#(os6_6SGDehh41 zxyBy{>r;0euV1zJp8)F*e-d0?<4?iW%4_^-xb2MDr)#Q~+@As0*T=JH>bX9i1ABd_ zXYA*}<@NCbT%WpqdyT&ccJ0geTrZ)i+mF}y%iwbDUxDjUw;!+ZSHZ5mV_1V+Uut*_ zT-WeAntEz@18fcIso_mnz_(y@RHnI^PACb-oAJ zqnihs)UuPepspmTT1g!QkM{4*KTwdd!!PUxZ{ByW%jXAd0nOesF z0$h*%C7OE1{sye}HAlw&7HnU+#=isWQ+FJ%U$ywZ2kQ_24_Hsu@dvP4d5!-Fx1BNj zbWPQg`%mEd`uG`5J^lUy_WDrI*uR3y>*F`LK6U%{8vh;a+LxaR{y{&Z@v-3g z)Kll!VCyX3>yLw`o;t?`mvxQ@*Q1^~#|K-dV_2tLUvilMY%Zy3Lb#git>2hh#+(RT zeuq0TT+R3R`i-gid1Dvm*3SYvH*-8G`o+a(fyv?ZH9iHJdh(kRT<)c*;A-Vwni_69 zW9Bd!XSJ;5wBY|&*ja#URc&inEbJ~YKt&NTP!UuNR8YV~KoDDOF|qr%ySux)ySuv+ zySwYYFK2!COy{$odwI@!);HcU=9puQHTT;8-lC`8XEvBT`^=7ZUA}JSKpP`BXGiX` z#CJv;AA3%;F`46BXjvELn6KBlv0bOnoSnGKQfC)*edgwY$&+_pv}aD9y}P2#m3`(z z8z;|s>W20_l|Kv250jh6ubb{@pHY4mSO9H|Jm+aawCBk^>_OYO^so@R?qOk=JU#S4 z+k-qkEP^h3SQOhhd14krmtQwMv5k|b&&AR9S$+@f1(T=G-srN=C9sW=r_UwP_URt> zscl^PTnb(H*#{<1pG%|dQ=T4{L6?0li*1}dG0UOLugSjHvhp3gJhp4~rS}!k_Fn!R zv?5HN-ut1;-uq)4BTw%uq3wO#9`vqlTzX#_UH3i!CQt7J(e^G+UxUzP@2g-NCr`|( z=(6|Kuw~`{$H?l~uGN>`*Ff8Q`I%r%m^{4?Mwh*>g>8&Hy$?a#yL7*OFiqN>w4CM$y3kz z=(?T_V8-c7JsYCUpLgI!XyfGW-I2R2@f)L!kG%=nn4E!8Xj%CV+!Wh&`poHhkfoo^ z(Dm8c941fREzq7VdG_8CU7oG2u#JABeX1^5@@!VDj{SFuLsh5Nu=Q>HSc&y}O6KYa5r|4@1|z z9}bhJ_ao5uE>B-aqRZZo!ZuExn4{5U@5f-v%6H(g*sj%=-j74ud-<91c$hrBpMWlV zKM~s)d3rwyZSU@3@7l(tzLU{qeWzf{{5m&YpDcTxiY`Aho`x;+v!L<%WaVeZ(amSZ zGvL$EQ|5jawsSAvzh}ebsqY-LHRL^ZF1DDHb$P_pEicx-NW9sjZ5#(pzGeBg~`+V zb7*^)r?2PHW$!Ow8z)c9i|DfVm#}5!`|@RM*Xm2}ub}O{{66_AOrG9fLzlh3j%|!Q zy}w}$y}O6KYa5r|-$d8FzXg-0_qWmZE>B7};kHvPa zzV!Y9+TP2b6+VQ?)B8v0viFa%jghDKPmG~=_poFW!0 z+54B+#>o@&6}s&GYiwD&3IE&sH`uP#m)^fc+k5#L;X9Z-y?>7`d;bC37FvGnhQRw}aWcd)T|Sap`@0blv*|FnM~P5N+@B^feK>?0sTv z^)8n~^-j zvGZ=230s!G$DvQ=`Vr0gk=*?|0JFgTAK-~Z7!H(J|&chJA5Fb|qzIBt!;>@hF8K7(Ch@|?l> z(4$!^&$@2ty0-aY^31I}+O_hWiv`f03w_q@KTlr}E%(1cdj-CQ(4DyaOl95nBQq}h zFO07D?*WtNXZl6Z_0RN+!i>{r-o?1fGQ-8unPE?~c4pWM?F?O`FSYbW*E3uKCeI9) zL_0%y)-8pud*}m`r-!A{bq~wHjMJA{FN<~$eVO%gXlJc2v+j$QXV%N3Gi&>ECNkqv z=L+b$&J|(u?7tFP)}PB9D|44+t^?7T>j1QN<~j)NTwS9t`>ukn=ejCPp1H1ucCPZQ zTOD23y9P|2de=hB1{Z7y+I;#l!=Y$rs4p`dhL&fBYojwmd$E6+aj9uIx~^#iOrDz7 zMaxEVnPWZfvdnM;bY{3dT01k`5bX?Iqc8hzgsx|}F-)ErZi04(@~j($uIt?tCQrRv zpk;U zVDiLlj~-pc>;RMJXVM+fGV@%=&tv|7>+FPWE`7eUcjoRN-|PCua9zk{O=|1ig?s+{ zX}dN)@Ba7GcIUnamw)VM&&KaPweN*CM{3v`E%SS#`)cpTWiIzsr_X)S^>f}2CeL%; zAMJCNXI%?jKj#Br@;v7Q)m-w_dJx)L^PV~wo%dAsI|OE&zT`R-Z9aX@>~QWf^%2|; zYxI%a{od%`1NHmYQRtbu8*iL`*X+YxU+Ov~V`b^%(J&rkYfuFuzrXIk5@GxPbimAPMxuIGLUOm2M_ao5iNm!UJOOVQey z)#YesZamp7VSa+H)k&x~tK3ZP&o$>Hk`^Yvp+s*P(qD`tmHUN6Ygp zZb0W*Shu~(jLZHvqU-%{g30r>c{4g^Fg4u*Gftm*Z{;q_3~xtghPR=$Gs8R3&d@db zQp=s_dWLtwES+f-NXGb)(@fO znf1fy%-a5(iOjgv`3SnM^HG>Q`#*t}Jr-g$%=Hb>U{+*d%0k*qRpo-Gkgv04E1G(ucPIe;T!18&|d6c zW?X7|6J6Kz7EGR+-bKsa;WEd2++~^JSafFiK3Y37`~d9?U867ieu%DT_z_H=8Gej* zhVrcY1YOtrDNLSvzd*}AFW8r8^XbbBzd}1heVO6cXnAJ%4LUQl7yFkPSH2&8PioJ~ z-S?$;?O7W8Tkd{u`<}ah{NC09{TG~jS@$QpuI(?FJkQ{7v}@&=_djUotuOQT!<{_y zZik(DTerQ+jLZJxqwD=AfXVZInh;&TpC*DCr_a0-bC+d?lb|!h_GsOO8Fb&K&eVO&NX!p>USx<*{*7`E*>Cy7c zdIof6ZGX;0W?br=5nb0g6HK1{JD_E=aG9eccUk5-8#;5H6|J4Q&W?7juF;o$=RntU z?F5r&uAR}&Ri1ToqU(C+g2_|wJZM>$g3XIIpT5knE7}?A%M9m3%QM4n=*-Yw>|bVF zYMLKi*VG**PfZJw2N|bVFY8r~JYZ?ZVr=}5T*>Em%tixTF z8Lo@Y3`e51GsE@J&d@dbvhVundWIXoisdrPfY*fKELz_=u zX1F=p8S2Xnw?NA?!!6O7p}p9@%(&FF6}qlzYnVJWZHtzT<}$~2++~^J4(QBqd$e|D zxFgybx<+62-3eXKa12bI8SadBhVrc21zp#>D@>kx_dv^bFW8=F^XbbB_d+{EeVO6j zXnAJ14>~in7yFkPmzws~CQtc$^!;G+)N}w^*5We9f!t-8;lb$4@F28yW_SqN8M;Pa z_B|9`&+ssqJTp8T?F{8vcLchw_ehvL^&W$k9bK?v(dN^a86JmrhWawYpU34N`#Hbyd(ZQ|0Bw%^j_5+PEWdlx zK8MR(?yF9p7oqFtbumny{Fk83pU+yCqVriRXW=rKar*L{FGrh8pM74zU6#C8p>r;; zL~G|y#`&M%WGls)N&o#b1Bcd>(O zz>L$ET(_dlr_bJR<1SO*&i%0F^ZFfVf40f*3h%`BcZJ3qr{5m@9oSuHzaEUSK7R*x zH(H*rhkMZZdT@sBCo|6T<5}_ycu$Y_qU|xY--njvcV7BruFv`OENOeb&F7iUtRFG%lJhOieo!MKry~>Qs{?DW9{a=8|^Y!&2I%h03y#zB(pLt*A zF3SvGMQ4VuptUo@*U-+;HTqJ^>*#uhZ@}c4;hSh@D9^gL&~*=Q!{q7V9dzBpyD;PQ zrLXtU?x8QUejn|u^<~y$(eljt19WC>f6hc^T$OrHHeMaw?nGRJ4!Wtr<2 z=*;zVw07qDCEB^VMql>*3SH0jYnVK9{RZt^=*-Yw>|bVFYMKgN*EBUuo|>jZ%ckWr$MoD~ncZVRy7MbdA33y8ybL;es%EX1EaA z8OpP6VRT(@512glE{2vZTCkpI^XbbB7e_loeVJh|v^+EHjm`}1#r|c+rKTm&bxljc zlv;Nlc%P^ zXxW-v=2(lnEHfO6&J2g3wKKzEXlLjeec5+ybUnl2FnMM;0__atS+@?lu6HC%o_g0u z%hoH{259r?%M3R}J41b$;YMhAX1FmrGqe}`ml;=nUi5RLc78tduAP4d;Qjym`)|kd z_r?6|={>XEgngWCdK-l;%V$}AGWR;BS$`b&zs74f-V$8BID7uHchI;${x@%W(?fgi z{Ob(=tNE*YEHlM!aS_y3~|6X|NS{W@*T?5gw0bI#72yH%nS+@$>KC^B$v}{$btXm!JT77>r zQ|)q&o@M`(bDR=8Go1?UGvsmq@4joHjmf@4(Xt_2*>@OvFqgjczBam^<8YWfxz<6; zMsOw9NVNI%CD*#>dXDSCH-6m++##~u93hi2b&QZIZ zqdyb+XL_#8ZiYh7*l3RScr$T1(^*NPgmwEQ%a$kMPwLjWEt=0FawsEPch3?E%*K`0( zU-BG?wx+V@gRteP>0q?$sx-(Zj(?enUlK(KY`OBUU$CfAm5op)RTTRbLj`Q=o zLGHGv!g!_}GVXfB^|NAAaR$zvafHixs-e>|5l^5i)I-I>eY+(+BE z_)kQ4<|_9&30t0hPDZ;=tJ&uiv@!DJIThWR%RKI*ZCv^N#;<_|xcoC8mtO<(a_`n? z`<}nip5g9XemyM6Jzo!}q1zYsr0xFw^>GG1^PSFBo`W;7^;xgE&*E~gGUn`t=UJYE z?K*kR%DL#|FVDewaDB;tKHB_c%mvu;>$zRUvD!9JnzZzZld<{&V{MVvgCvWjAd?#GT z<-Yoo>w2_3J3o8YHcr3ikGrqg=-^IP0@jcl3%;UMem#cn;_cc5- zz8~9l^5lO2?f&L3&*X#H`jY=4bo~q;hRKuv5wz>%Ik%6Z-B(|7J%)BJ_G8c5#-*mm z(QVcA1YBS8Jc+J*ehMZ}O;4j;Cr|!o(8*uU^jWyRpt4XCC9sHXO|owpk-sZ{O_H2LOtjF{J372cjm`@v?XZ0Dj>*UG*IXd~v^Zx~0U-Ey6Hh&rO6}CM2 zzec-Gp7Z|=+I{sU*SBcrYpwRIZCq;l4&7Ew-^2AK&kyLj=O1D6)btbDb@Jr@8J+y) zyncb}Oa5QcbH8yRW|F`V(!>&d;8;jnnV>|BK6-j^@f4`n%z= z|G_p#&cBDp7Wu8nyd)uBSlP&tOWJJTX%>G3B$I z8YbVbsb?CrY|W;pY0>79Tfd)|Wd2^j+N{HRvd8r3x{euO^6W7qT9!34q3iQGGfbX3 zWXL1);Ig450`cl_y=(?`iVe*{oInb_?Cx0h& z@|W*{&TxInKPS4L)m$)n^3RQSojmV~E@=1Fmt6CpJ&X2Z&)UYNrg_nA)zlTPFL~xe z*FATG$y3w(XxGV;zq@uDGhG0#FZmZl*F7%;lPCYeXxGVGoI}4(dZ67`Uve#iF5eZ} z#_9K6u_)S_PUp(GSPUkQ-4k8DD;CE#MxH#q(CN+DY8w}S@5W#5vjj|@eU?O*?~0|c zjgco$A9U()_0Gq#B7+r*gD9NNaD?&Z&Lx(C#;06&;HH3GTPe9m;o?(&hJ39>*UEl2%Y@p zJ7E>LzT{sOZT>Q5HJCj4S4X=}o_E3;X!q5ZTx+78W8Mkc#-*mg=(cKF3$8DDhM?=7 zhr;BkX&Bmd^5kC|o&4pzhQswG{|I#5^Exnj@{dHjPTp$X3G1TWS6_0ihqhv;!M&XER@nN?w zzQTS6_0CK|7b6TW#Y~)6VF&YTCs$z?<9$&-H{wCm)p=G^X!c3*wTwIAA^b8fYb z)9<<6A8k!zxN?44FnR0)(B{awJrHe-Jb4a6r#H`&wsG+v-1y6V4uQ$D&!K4dX*K8e zFtjo9hqt>obq%_Gond43B}yGvi~?u9GMKacK89e|c_? z$JUqpC!p(Rcp^-m{3oGZC(pS(8STFMlIs+-bIG~YHZC=tif*f>)8P7&=X7-4^BFLC zYC03`I(hP+g--r*rf0+TCI30-y61CY^5j1c?K*j@Ik)Gd-B(|7U4XXdoLg<<^m}eE zL|aq&8RR0EJm=|Rv^jEaFF_k4Po7KB>CN+`ZCw19HU4s+%VF~Da|POcTGZzI_DZxd z^5nS+oqF9z+qlg5n#O-M_j1P9V(T-H=k_{u{S2>%$ur{{(5{mw|BYz(H-C9 z{5PZPXLt)tp8U6>T_?}Ey$$WY`jYE*v~$V1)iy3Q-GOearaR&KlIJdT-Sgcrd1|@` z?K*k#--}NEa;Epe^(FuP=(^_zVDjXD5bZj7i)Yb+Sw4hzUwz5-FxsATZncfm@40;h zZB71+nDg@}Odk6&v^jEaA4eM_Po5{x>CN+`ZCw0MHvV#-r(p8z^EBFhTFtqA25pQy zd7ee5UiZ;9E;*hp*U6LrHFWZq=l^xMzT|%cU7v+FVe;gE3++02&i~tJ_tlqN@1UJ; z&cC*Csp(yGTQ$80*Oxr+qwAi>!sMyx1GMYp$^Rib`OBGp1lO1RAEWD@KY_`U|5LQ< zEm;95U>z*ft$&-IFwCm)p=G;z> zc3*wTH3hmnx7x<(_uNj2wx%&$IX_duo`$uko=^}3I?apv%Q*DUCs-1Gb44%o8yVg7!2Hne}n{kz}jS-Ixs z^7kof_wiiMj;^1<958ueIyEunv+N9$=XbYrqGkEL>|AK`$gSVs%gFq_thHH(^<)1VDjuSFItv0UD2*7>zWTHPaWORu9K$@Sy_kmq}h=qFr0YEQBr3xn3CUI(hQb2pMfxW_8EjO-xaH18zWDiRne)}eYB0sj8|*?S6AnDb+|tB z_%2ujT|dJ$Ve-s)FxqwUw*k6hIU_l$#pooJpbCp>G%8}fwrddXNDtT z@|>xo(B=6*8rv9o@*IOsZ=NS@X4OnSWlkKC1`6kc4qF{IoFq>eJ1tKgO|berLN1-t}W+v1-3lr`bxCx(I{C}@ zz}0Yl$$t&n{AJ9w*z)AR4(&R5-WAuQ-B(|7-GDCN723w7rW?_1)pQeFU-I0Hu6w=( zCQnVbqFpCX{@c*WU(V}xxW44S16}ugCrqCFccEP;Z#D0VyV35eFS+hPm+uN~b;y#!>_WkJcUGV_6G4kYj5S`vUPuj-C|4`#E_jwp5&pwZ!%Xh`2*v80{ z=P`8Zbsufx%;CG@adi2vcmi9Ncg53a|M;%Z_Y~JFTz-wJ-N$#uGwAy3?OB*S&)|8q z>^ZKidjVa4ZNCVUXWdI^nd@53vwInBK7ID}BzKu#yVh)d)|q`?Mc4Jc29sx>*U_@F zzBjPz`rd@ev+gal%ys#CdK+y%eW_1Y)@Pl04)37tA@#nC_Dp;3U9W9S;@?A;&+UC| zS)SX6X#e=!^nJkfC6{wiXP=MIb$=hjyf?_2D;zVBf2tot4{Q}pQJinsz{Il0@FnQ|#9ql@K^8bNO z{_=akpKyK2{}(!SCjZ|sdGh~*cAY%unwG|MUwz5d4px4j&^9hLjgM}trU~Hsl4nA6 z-Sb2+d1{&%?K*k#w?`*`Inznt`jUTAblvl0FnRJ%j&_~A)treb(C(`*xu!&y-zT(< z)9?3*snFKckLT=s{W)Z6m^}70=<@r-wAjYTlV>_~dht`?r zOrDrdO-%VLJHzDpyf-IWmd|o?q0J+=e*Zp}%&%K(vkvRY9$nCN9rM8C*<)U`ENi-= z>+?AuOrAQrp&dg3A8oD1`o7Z6x$chknbg03SpcptbuEal-*pSY0}eOIiAwkCf+oO997HC(a#YvXsezDriZHb$O2E2Gn!=SkbR_y;upa-V@P zdG;BEF5eZaU>hS(o>kGQ*L}2&i+{DoKZZJ!cXgQDc=Kx~evKx+e21+GlP6|y6Jt(u zXd9FKYoX1X_#sWaIgQsgCjOy~zx?Oq!(j5%sGaz=oA`2e!(sBojA&xaX%1~;QsX-4 Svc{23yg7~6HYR`f^?v{nr2PB< diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_3x3.comp deleted file mode 100644 index 41ceb6fdb..000000000 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_afterR2C_symmetric_3x3.comp +++ /dev/null @@ -1,828 +0,0 @@ -#version 450 - -const float M_PI = 3.1415926535897932384626433832795; -const float M_SQRT1_2 = 0.70710678118654752440084436210485; - -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; -layout (constant_id = 4) const uint fft_dim = 2048; - -layout (constant_id = 5) const bool inverse = false; -layout (constant_id = 6) const bool zeropad_0 = false; -layout (constant_id = 7) const bool zeropad_1 = false; -layout (constant_id = 8) const uint inputStride_0 = 1; -layout (constant_id = 9) const uint inputStride_1 = 1; -layout (constant_id = 10) const uint inputStride_2 = 1; -layout (constant_id = 11) const uint inputStride_3 = 1; -layout (constant_id = 12) const uint inputStride_4 = 1; -layout (constant_id = 13) const uint outputStride_0 = 1; -layout (constant_id = 14) const uint outputStride_1 = 1; -layout (constant_id = 15) const uint outputStride_2 = 1; -layout (constant_id = 16) const uint outputStride_3 = 1; -layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; -layout (constant_id = 21) const uint numStages = 1; -layout (constant_id = 22) const uint stageRadix_0 = 8; -layout (constant_id = 23) const uint stageRadix_1 = 8; -layout (constant_id = 24) const uint ratio_0 = 8; -layout (constant_id = 25) const uint ratio_1 = 8; -layout (constant_id = 26) const bool ratioDirection_0 = false; -layout (constant_id = 27) const bool ratioDirection_1 = true; -layout (constant_id = 28) const uint inputOffset = 0; -layout (constant_id = 29) const uint outputOffset = 0; - -layout(push_constant) uniform PushConsts -{ - uint coordinate; - uint batchID; -} consts; - - -layout(std430, binding = 0) buffer Data { - vec2 inputs[]; -}; - -layout(std430, binding = 1) buffer Data2 { - vec2 outputs[]; -}; - -layout(std430, binding = 2) readonly buffer Kernel_FFT { - vec2 kernel []; -}; -uint indexInput(uint index, uint coordinate) { - return inputOffset+index * inputStride_0 + gl_GlobalInvocationID.y * inputStride_1 + gl_GlobalInvocationID.z * inputStride_2 + coordinate * inputStride_3; -} -uint indexOutput(uint index, uint coordinate) { - return outputOffset+index * outputStride_0 + gl_GlobalInvocationID.y * outputStride_1 + gl_GlobalInvocationID.z * outputStride_2 + coordinate * outputStride_3; -} -uint positionShuffle(uint pos, uint ratio, bool ratioDirection ) { - return (((pos)/(ratio))+((pos)%(ratio))*(fft_dim)); -} -void radix2(inout vec2 values[2], vec2 w) { - vec2 temp; - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; -} - -void radix4(inout vec2 values[4],inout vec2 w, float inverse) { - - //DIF 1st stage with double angle - vec2 temp; - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - //DIF 2nd stage with half angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - w = (inverse < 0 ) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - temp = values[1]; - values[1]=values[2]; - values[2]=temp; -} - -void radix8(inout vec2 values[8], inout vec2 w, float inverse) { - //DIF 1st stage with quadruple angle - - vec2 temp; - temp.x=values[4].x*w.x-values[4].y*w.y; - temp.y=values[4].y*w.x+values[4].x*w.y; - values[4]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[5].x*w.x-values[5].y*w.y; - temp.y=values[5].y*w.x+values[5].x*w.y; - values[5]=values[1]-temp; - values[1]=values[1]+temp; - - temp.x=values[6].x*w.x-values[6].y*w.y; - temp.y=values[6].y*w.x+values[6].x*w.y; - values[6]=values[2]-temp; - values[2]=values[2]+temp; - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[3]-temp; - values[3]=values[3]+temp; - - //DIF 2nd stage with double angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[2].x*w.x-values[2].y*w.y; - temp.y=values[2].y*w.x+values[2].x*w.y; - values[2]=values[0]-temp; - values[0]=values[0]+temp; - - temp.x=values[3].x*w.x-values[3].y*w.y; - temp.y=values[3].y*w.x+values[3].x*w.y; - values[3]=values[1]-temp; - values[1]=values[1]+temp; - - vec2 iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[6].x*iw.x-values[6].y*iw.y; - temp.y=values[6].y*iw.x+values[6].x*iw.y; - values[6]=values[4]-temp; - values[4]=values[4]+temp; - - temp.x=values[7].x*iw.x-values[7].y*iw.y; - temp.y=values[7].y*iw.x+values[7].x*iw.y; - values[7]=values[5]-temp; - values[5]=values[5]+temp; - - //DIF 3rd stage with angle - w = normalize(w + vec2(1.0, 0.0)); - - temp.x=values[1].x*w.x-values[1].y*w.y; - temp.y=values[1].y*w.x+values[1].x*w.y; - values[1]=values[0]-temp; - values[0]=values[0]+temp; - - iw = (inverse < 0) ? vec2(w.y, -w.x) : vec2(-w.y, w.x); - - temp.x=values[3].x*iw.x-values[3].y*iw.y; - temp.y=values[3].y*iw.x+values[3].x*iw.y; - values[3]=values[2]-temp; - values[2]=values[2]+temp; - - iw.x=(inverse < 0) ? w.x*M_SQRT1_2+w.y*M_SQRT1_2 : w.x*M_SQRT1_2-w.y*M_SQRT1_2; - iw.y=(inverse < 0) ? w.y*M_SQRT1_2-w.x*M_SQRT1_2 : w.y*M_SQRT1_2+w.x*M_SQRT1_2; - - temp.x=values[5].x*iw.x-values[5].y*iw.y; - temp.y=values[5].y*iw.x+values[5].x*iw.y; - values[5]=values[4]-temp; - values[4]=values[4]+temp; - - w = (inverse < 0) ? vec2(iw.y, -iw.x) : vec2(-iw.y, iw.x); - - temp.x=values[7].x*w.x-values[7].y*w.y; - temp.y=values[7].y*w.x+values[7].x*w.y; - values[7]=values[6]-temp; - values[6]=values[6]+temp; - - temp = values[1]; - values[1]=values[4]; - values[4]=temp; - - temp = values[3]; - values[3]=values[6]; - values[6]=temp; - -} - -shared vec2 sdata[gl_WorkGroupSize.y*fft_dim];// gl_WorkGroupSize.x - fft size, gl_WorkGroupSize.y - grouped consequential ffts - -void main() { - - vec2 temp0[8]; - vec2 temp1[8]; - vec2 temp2[8]; - - for(uint coordinate=0; coordinate<3; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=vec2(0,0); - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=vec2(0,0); - } - } else { - if (ratioDirection_0){ - if (gl_WorkGroupID.y < gl_NumWorkGroups.y-1){ - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, ratio_0, ratioDirection_0)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - }else{ - if (gl_LocalInvocationID.y>0) - return; - sdata[gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - } else{ - sdata[fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x]=inputs[indexInput(gl_LocalInvocationID.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]; - sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]=inputs[indexInput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]; - } - - } - memoryBarrierShared(); - barrier(); - - uint stageSize=1; - float stageAngle=M_PI; - - //0-numStages stage - for (uint n=0; n < numStages; n++){ - uint current_radix = (nDY2@jR@aXG3ahTO>Kuax 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 + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -470,15 +457,15 @@ void main() { //2x2 nonsymmetric convolution for a 2d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 0); - float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; - float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; - float temp_spin_real1 = kernel[icellkernel+2*inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x - kernel[icellkernel+2*inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y; - float temp_spin_imag1 = kernel[icellkernel+2*inputStride_3].x * temp0[i].y + kernel[icellkernel+3*inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].y * temp0[i].x + kernel[icellkernel+3*inputStride_3].y * temp1[i].x; - temp0[i].x= temp_spin_real0; - temp0[i].y= temp_spin_imag0; - temp1[i].x= temp_spin_real1; - temp1[i].y= temp_spin_imag1; + uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, 0); + float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; + float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; + float temp_spin_real1 = kernel[icellkernel+2*inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x - kernel[icellkernel+2*inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y; + float temp_spin_imag1 = kernel[icellkernel+2*inputStride_3].x * temp0[i].y + kernel[icellkernel+3*inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].y * temp0[i].x + kernel[icellkernel+3*inputStride_3].y * temp1[i].x; + temp0[i].x= temp_spin_real0; + temp0[i].y= temp_spin_imag0; + temp1[i].x= temp_spin_real1; + temp1[i].y= temp_spin_imag1; } //ifft @@ -714,38 +701,24 @@ void main() { memoryBarrierShared(); barrier(); } - - if (zeropad_0){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, coordinate)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } memoryBarrierShared(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_2x2.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_2x2.spv index 30d49d85bb11100d29dfb00f1e150c8e33b47fb2..58900aae444b552cf94cbdb856e130ea3f39a97a 100644 GIT binary patch literal 80572 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 literal 88864 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 F{Xg&d`d9z} diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.comp index 117dce41c..bf7d7c846 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -200,43 +203,28 @@ void main() { vec2 temp2[8]; for(uint coordinate=0; coordinate<3; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -483,7 +471,7 @@ void main() { //3x3 nonsymmetric convolution for a 3d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 0); + uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, 0); float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x + kernel[icellkernel+2*inputStride_3].x * temp2[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y - kernel[icellkernel+2*inputStride_3].y * temp2[i].y; float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].x * temp2[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x + kernel[icellkernel+2*inputStride_3].y * temp2[i].x; float temp_spin_real1 = kernel[icellkernel+3*inputStride_3].x * temp0[i].x + kernel[icellkernel+4*inputStride_3].x * temp1[i].x + kernel[icellkernel+5*inputStride_3].x * temp2[i].x - kernel[icellkernel+3*inputStride_3].y * temp0[i].y - kernel[icellkernel+4*inputStride_3].y * temp1[i].y - kernel[icellkernel+5*inputStride_3].y * temp2[i].y; @@ -742,37 +730,24 @@ void main() { barrier(); } - if (zeropad_0){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, coordinate)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } memoryBarrierShared(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_nonsymmetric_3x3.spv index e552239465929834147fdfaefe5b72bc0c4425e0..c1293f7790dce199625000909e7fb502d1e8062f 100644 GIT binary patch literal 88656 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

    lM+<5xy4lZk34emKtFKb&JZY;H}0k$vo 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 R0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -470,15 +458,15 @@ void main() { //2x2 symmetric convolution for a 2d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 0); - float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; - float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; - float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+2*inputStride_3].x * temp1[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+2*inputStride_3].y * temp1[i].y; - float temp_spin_imag1 = kernel[icellkernel+inputStride_3].x * temp0[i].y + kernel[icellkernel+2*inputStride_3].x * temp1[i].y + kernel[icellkernel+inputStride_3].y * temp0[i].x + kernel[icellkernel+2*inputStride_3].y * temp1[i].x; - temp0[i].x= temp_spin_real0; - temp0[i].y= temp_spin_imag0; - temp1[i].x= temp_spin_real1; - temp1[i].y= temp_spin_imag1; + uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, 0); + float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y; + float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x; + float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+2*inputStride_3].x * temp1[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+2*inputStride_3].y * temp1[i].y; + float temp_spin_imag1 = kernel[icellkernel+inputStride_3].x * temp0[i].y + kernel[icellkernel+2*inputStride_3].x * temp1[i].y + kernel[icellkernel+inputStride_3].y * temp0[i].x + kernel[icellkernel+2*inputStride_3].y * temp1[i].x; + temp0[i].x= temp_spin_real0; + temp0[i].y= temp_spin_imag0; + temp1[i].x= temp_spin_real1; + temp1[i].y= temp_spin_imag1; } //ifft @@ -714,37 +702,24 @@ void main() { memoryBarrierShared(); barrier(); } - if (zeropad_0){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, coordinate)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } memoryBarrierShared(); barrier(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_2x2.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_2x2.spv index 8c59e02fc04efca034de7ec8eb3ccde313d5ea52..64aa5110a584da1f3dd1a2f3aa59047fe0e8f51a 100644 GIT binary patch literal 80476 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 Dou_1n literal 88768 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.comp index e587d02c2..09950888f 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.comp @@ -2,11 +2,9 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -const float mult = 1e-7; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -20,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -32,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { @@ -200,43 +202,28 @@ void main() { vec2 temp2[8]; for(uint coordinate=0; coordinate<3; coordinate++){ - if (zeropad_0){ - if (ratioDirection_0){ - for (uint i=0; i<8; i++){ - uint pos=positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_0, ratioDirection_0); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; + } + memoryBarrierShared(); + barrier(); + } uint stageSize=1; float stageAngle=M_PI; @@ -483,19 +470,19 @@ void main() { //3x3 symmetric convolution for a 3d vector for (uint i=0; i<8; i++){ - uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, 0); - float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x + kernel[icellkernel+2*inputStride_3].x * temp2[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y - kernel[icellkernel+2*inputStride_3].y * temp2[i].y; - float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].x * temp2[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x + kernel[icellkernel+2*inputStride_3].y * temp2[i].x; - float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x + kernel[icellkernel+4*inputStride_3].x * temp2[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y - kernel[icellkernel+4*inputStride_3].y * temp2[i].y; - float temp_spin_imag1 = kernel[icellkernel+inputStride_3].x * temp0[i].y + kernel[icellkernel+3*inputStride_3].x * temp1[i].y + kernel[icellkernel+4*inputStride_3].x * temp2[i].y + kernel[icellkernel+inputStride_3].y * temp0[i].x + kernel[icellkernel+3*inputStride_3].y * temp1[i].x + kernel[icellkernel+4*inputStride_3].y * temp2[i].x; - float temp_spin_real2 = kernel[icellkernel+2*inputStride_3].x * temp0[i].x + kernel[icellkernel+4*inputStride_3].x * temp1[i].x + kernel[icellkernel+5*inputStride_3].x * temp2[i].x - kernel[icellkernel+2*inputStride_3].y * temp0[i].y - kernel[icellkernel+4*inputStride_3].y * temp1[i].y - kernel[icellkernel+5*inputStride_3].y * temp2[i].y; - float temp_spin_imag2 = kernel[icellkernel+2*inputStride_3].x * temp0[i].y + kernel[icellkernel+4*inputStride_3].x * temp1[i].y + kernel[icellkernel+5*inputStride_3].x * temp2[i].y + kernel[icellkernel+2*inputStride_3].y * temp0[i].x + kernel[icellkernel+4*inputStride_3].y * temp1[i].x + kernel[icellkernel+5*inputStride_3].y * temp2[i].x; - temp0[i].x= temp_spin_real0; - temp0[i].y= temp_spin_imag0; - temp1[i].x= temp_spin_real1; - temp1[i].y= temp_spin_imag1; - temp2[i].x= temp_spin_real2; - temp2[i].y= temp_spin_imag2; + uint icellkernel= indexInput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, 0); + float temp_spin_real0 = kernel[icellkernel ].x * temp0[i].x + kernel[icellkernel+inputStride_3].x * temp1[i].x + kernel[icellkernel+2*inputStride_3].x * temp2[i].x - kernel[icellkernel ].y * temp0[i].y - kernel[icellkernel+inputStride_3].y * temp1[i].y - kernel[icellkernel+2*inputStride_3].y * temp2[i].y; + float temp_spin_imag0 = kernel[icellkernel ].x * temp0[i].y + kernel[icellkernel+inputStride_3].x * temp1[i].y + kernel[icellkernel+2*inputStride_3].x * temp2[i].y + kernel[icellkernel ].y * temp0[i].x + kernel[icellkernel+inputStride_3].y * temp1[i].x + kernel[icellkernel+2*inputStride_3].y * temp2[i].x; + float temp_spin_real1 = kernel[icellkernel+inputStride_3].x * temp0[i].x + kernel[icellkernel+3*inputStride_3].x * temp1[i].x + kernel[icellkernel+4*inputStride_3].x * temp2[i].x - kernel[icellkernel+inputStride_3].y * temp0[i].y - kernel[icellkernel+3*inputStride_3].y * temp1[i].y - kernel[icellkernel+4*inputStride_3].y * temp2[i].y; + float temp_spin_imag1 = kernel[icellkernel+inputStride_3].x * temp0[i].y + kernel[icellkernel+3*inputStride_3].x * temp1[i].y + kernel[icellkernel+4*inputStride_3].x * temp2[i].y + kernel[icellkernel+inputStride_3].y * temp0[i].x + kernel[icellkernel+3*inputStride_3].y * temp1[i].x + kernel[icellkernel+4*inputStride_3].y * temp2[i].x; + float temp_spin_real2 = kernel[icellkernel+2*inputStride_3].x * temp0[i].x + kernel[icellkernel+4*inputStride_3].x * temp1[i].x + kernel[icellkernel+5*inputStride_3].x * temp2[i].x - kernel[icellkernel+2*inputStride_3].y * temp0[i].y - kernel[icellkernel+4*inputStride_3].y * temp1[i].y - kernel[icellkernel+5*inputStride_3].y * temp2[i].y; + float temp_spin_imag2 = kernel[icellkernel+2*inputStride_3].x * temp0[i].y + kernel[icellkernel+4*inputStride_3].x * temp1[i].y + kernel[icellkernel+5*inputStride_3].x * temp2[i].y + kernel[icellkernel+2*inputStride_3].y * temp0[i].x + kernel[icellkernel+4*inputStride_3].y * temp1[i].x + kernel[icellkernel+5*inputStride_3].y * temp2[i].x; + temp0[i].x= temp_spin_real0; + temp0[i].y= temp_spin_imag0; + temp1[i].x= temp_spin_real1; + temp1[i].y= temp_spin_imag1; + temp2[i].x= temp_spin_real2; + temp2[i].y= temp_spin_imag2; } //ifft @@ -742,37 +729,24 @@ void main() { barrier(); } - if (zeropad_0){ - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - - }else{ - for (uint i=0; i<8; i++){ - uint pos = positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1); - if (pos%fft_dim0)){ + for (uint i=0; i < 8; i++){ + float angle=2*M_PI*(((gl_WorkGroupID.x*gl_WorkGroupSize.y+gl_LocalInvocationID.y)*(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x))/float(fft_dim_full)); + uint index=(fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)); + vec2 mult = vec2(cos(angle),-sin(angle)); + vec2 res=vec2(sdata[index].x*mult.x-sdata[index].y*mult.y,sdata[index].y*mult.x+sdata[index].x*mult.y); + sdata[index]=res; } + memoryBarrierShared(); + barrier(); + } + if ((zeropad_0)){ + for (uint i=0; i < 4; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; + } else { - if (ratioDirection_1){ - outputs[indexOutput(gl_LocalInvocationID.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+2*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+2*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+3*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+3*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+4*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+4*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+5*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+5*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+6*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+6*gl_WorkGroupSize.x)]; - outputs[indexOutput(gl_LocalInvocationID.x+7*gl_WorkGroupSize.x, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+7*gl_WorkGroupSize.x)]; - - }else{ - - for (uint i=0; i<8; i++) - outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, coordinate)]=sdata[positionShuffle(fft_dim*gl_LocalInvocationID.y + gl_LocalInvocationID.x+i*gl_WorkGroupSize.x, ratio_1, ratioDirection_1)]; - - } + for (uint i=0; i < 8; i++) + outputs[indexOutput(gl_LocalInvocationID.x+i*gl_WorkGroupSize.x+gl_LocalInvocationID.y*fft_dim+(gl_WorkGroupID.x)*gl_WorkGroupSize.y*fft_dim, coordinate)]=sdata[fft_dim*gl_LocalInvocationID.y + (gl_LocalInvocationID.x+i*gl_WorkGroupSize.x)]; } memoryBarrierShared(); diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_convolution_symmetric_3x3.spv index 07d3bed6bac3097c7d10be133a09808926a18904..df2f518f5cf995dc4fb7eae7fb3e2609a8440d13 100644 GIT binary patch literal 88560 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 diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.comp b/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.comp index 7a4957a27..37c2c7425 100644 --- a/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.comp +++ b/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.comp @@ -3,9 +3,8 @@ const float M_PI = 3.1415926535897932384626433832795; const float M_SQRT1_2 = 0.70710678118654752440084436210485; -layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in; +layout (local_size_x_id = 1, local_size_y_id = 2, local_size_z_id = 3) in;// 32, fft/8, 1: total <1024 layout (constant_id = 4) const uint fft_dim = 2048; - layout (constant_id = 5) const bool inverse = false; layout (constant_id = 6) const bool zeropad_0 = false; layout (constant_id = 7) const bool zeropad_1 = false; @@ -19,9 +18,9 @@ layout (constant_id = 14) const uint outputStride_1 = 1; layout (constant_id = 15) const uint outputStride_2 = 1; layout (constant_id = 16) const uint outputStride_3 = 1; layout (constant_id = 17) const uint outputStride_4 = 1; -layout (constant_id = 18) const uint radixStride_0 = 1; -layout (constant_id = 19) const uint radixStride_1 = 1; -layout (constant_id = 20) const uint radixStride_2 = 1; +layout (constant_id = 18) const uint fft_dim_full = 2048; +layout (constant_id = 19) const uint stageStartSize = 2048; +layout (constant_id = 20) const uint fft_dim_x = 2048; layout (constant_id = 21) const uint numStages = 1; layout (constant_id = 22) const uint stageRadix_0 = 8; layout (constant_id = 23) const uint stageRadix_1 = 8; @@ -31,6 +30,10 @@ layout (constant_id = 26) const bool ratioDirection_0 = false; layout (constant_id = 27) const bool ratioDirection_1 = true; layout (constant_id = 28) const uint inputOffset = 0; layout (constant_id = 29) const uint outputOffset = 0; +layout (constant_id = 30) const uint passID = 0; +const uint radixStride_0 = fft_dim/2; +const uint radixStride_1 = fft_dim/4; +const uint radixStride_2 = fft_dim/8; layout(push_constant) uniform PushConsts { diff --git a/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.spv b/core/thirdparty/VkFFT/shaders/vkFFT_single_r2c.spv index 319847a30aaf7a013ae6805ddf66f77886137620..b30ffa4bcf2928122d588e810e8b08a19825d93e 100644 GIT binary patch delta 384 zcmZ2*n)%KdW?p6{Wp)MzMg|TboW7A)kUN}>VImg;Lt0u%d`f0+d|GKv4g(OdGO#gB z0*V)xB&MeZmn0UI1ZP&Ig2Y)FCL^h@0IOwTm;w|lN-W9Dk2e6SU}u;**^pbDkClOi zVH!}TAhEdE(`B<8Hy6|72HqKgLO@;aKsk^Nj6k+9ln*i)#210`L8gNE5>WnBC|?T7 z2bm3$m)oq#r_IA<0(3MRkZa32IZjY)bB>e*qbN*F04UK0lxqTFmB|yOli@O3kYsc= zGs+xh@&g7AgAveuAj3dzMCOCsh|CAM5vZKOkb#*&5J-dE2-6F49|ObYOLFIq0RZU% BIGF$d delta 215 zcmca}hIzqhW?p6{Wp)MzMg|TboV<}&kXwU=VImg;Ls4Q$W`4W@11keN!z38rC9^0s z87Q6ylwjCAi<^r{)0P#an}IN{LxVcv5FcTjKP>&%4GlL+Ip2W4ePyXC7 E0B%4b{r~^~ diff --git a/core/thirdparty/VkFFT/vkFFT.h b/core/thirdparty/VkFFT/vkFFT.h index 800e85879..278e7e77d 100644 --- a/core/thirdparty/VkFFT/vkFFT.h +++ b/core/thirdparty/VkFFT/vkFFT.h @@ -12,13 +12,14 @@ typedef struct { uint32_t FFTdim = 1; //FFT dimensionality (1, 2 or 3) uint32_t radix = 8; //FFT radix (2, 4 or 8) bool performZeropadding[3] = { false, false, false }; // perform zeropadding (false - off, true - on) - bool performTranspose[2] = { true, true }; //will be selected automatically + bool performTranspose[2] = { false, false }; //will be selected automatically bool performConvolution = false; //perform convolution in this application (false - off, true - on) bool performR2C = false; //perform R2C/C2R decomposition (false - off, true - on) bool inverse = false; //perform inverse FFT (false - forward, true - inverse) bool symmetricKernel = false; //specify if kernel in 2x2 or 3x3 matrix convolution is symmetric bool isInputFormatted = false; //specify if input buffer is not padded for R2C if out-of-place mode is selected (only if numberBatches==1 and numberKernels==1) - false - padded, true - not padded bool isOutputFormatted = false; //specify if output buffer is not padded for R2C if out-of-place mode is selected (only if numberBatches==1 and numberKernels==1) - false - padded, true - not padded + uint32_t registerBoost = 1; //specify if register file size is bigger than shared memory (on Nvidia 256KB register file can be used instead of 32KB of shared memory, set this constant to 4) char shaderPath[256] = "shaders/"; //path to shaders, can be selected automatically in CMake uint32_t coalescedMemory = 32;//in bits, for Nvidia compute capability >=6.0 is equal to 32, <6.0 and Intel is equal 128. Gonna work regardles, but if specified by user correctly, the performance will be higher. VkDevice* device; @@ -42,13 +43,16 @@ typedef struct { VkBool32 zeropad[2]; uint32_t inputStride[5]; uint32_t outputStride[5]; - uint32_t radixStride[3]; + uint32_t fft_dim_full; + uint32_t stageStartSize; + uint32_t fft_dim_x; uint32_t numStages; uint32_t stageRadix[2] = { 0,0 }; uint32_t ratio[2]; VkBool32 ratioDirection[2]; uint32_t inputOffset; uint32_t outputOffset; + uint32_t passID; } VkFFTSpecializationConstantsLayout; typedef struct { @@ -84,9 +88,10 @@ typedef struct { VkPipeline pipeline; } VkFFTTranspose; typedef struct { - - VkFFTAxis axes[3]; - VkFFTAxis supportAxes[2];//Nx/2+1 for r2c/c2r + uint32_t numAxisUploads[3]; + uint32_t numSupportAxisUploads[2]; + VkFFTAxis axes[3][5]; + VkFFTAxis supportAxes[2][5];//Nx/2+1 for r2c/c2r VkFFTTranspose transpose[2]; } VkFFTPlan; @@ -132,8 +137,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_c2r.spv"); break; case 2: - //printf("vkFFT_single_c2r_zp\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_c2r_zp.spv"); + //printf("vkFFT_single_c2c_strided\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_c2c_strided.spv"); break; case 3: //printf("vkFFT_single_r2c\n"); @@ -164,8 +169,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_1x1.spv"); break; case 10: - //printf("vkFFT_single_convolution_afterR2C_1x1\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_afterR2C_1x1.spv"); + //printf("vkFFT_single_strided_convolution_1x1\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_strided_convolution_1x1.spv"); break; case 11: //printf("vkFFT_grouped_convolution_symmetric_2x2\n"); @@ -176,8 +181,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_symmetric_2x2.spv"); break; case 13: - //printf("vkFFT_single_convolution_afterR2C_symmetric_2x2\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_afterR2C_symmetric_2x2.spv"); + //printf("vkFFT_single_strided_convolution_symmetric_2x2\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_strided_convolution_symmetric_2x2.spv"); break; case 14: //printf("vkFFT_grouped_convolution_nonsymmetric_2x2\n"); @@ -188,8 +193,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_nonsymmetric_2x2.spv"); break; case 16: - //printf("vkFFT_single_convolution_afterR2C_nonsymmetric_2x2\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_afterR2C_nonsymmetric_2x2.spv"); + //printf("vkFFT_single_strided_convolution_nonsymmetric_2x2\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_strided_convolution_nonsymmetric_2x2.spv"); break; case 17: //printf("vkFFT_grouped_convolution_symmetric_3x3\n"); @@ -200,8 +205,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_symmetric_3x3.spv"); break; case 19: - //printf("vkFFT_single_convolution_afterR2C_symmetric_3x3\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_afterR2C_symmetric_3x3.spv"); + //printf("vkFFT_single_strided_convolution_symmetric_3x3\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_strided_convolution_symmetric_3x3.spv"); break; case 20: //printf("vkFFT_grouped_convolution_nonsymmetric_3x3\n"); @@ -212,8 +217,8 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_nonsymmetric_3x3.spv"); break; case 22: - //printf("vkFFT_single_convolution_afterR2C_nonsymmetric_3x3\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_convolution_afterR2C_nonsymmetric_3x3.spv"); + //printf("vkFFT_single_strided_convolution_nonsymmetric_3x3\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_single_strided_convolution_nonsymmetric_3x3.spv"); break; case 23: //printf("vkFFT_single_c2r_8192\n"); @@ -228,26 +233,57 @@ typedef struct VkFFTApplication { sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_c2c_8192.spv"); break; case 26: - //printf("vkFFT_single_c2r_for_transposition_8192\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_c2r_for_transposition_8192.spv"); + //printf("vkFFT_grouped_strided_convolution_1x1\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_grouped_strided_convolution_1x1.spv"); break; case 27: - //printf("vkFFT_single_r2c_for_transposition_8192\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_r2c_for_transposition_8192.spv"); + //printf("vkFFT_grouped_strided_convolution_symmetric_2x2\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_grouped_strided_convolution_symmetric_2x2.spv"); break; case 28: - //printf("vkFFT_single_c2c_for_transposition_8192\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_c2c_for_transposition_8192.spv"); + //printf("vkFFT_grouped_strided_convolution_nonsymmetric_2x2\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_grouped_strided_convolution_nonsymmetric_2x2.spv"); break; case 29: - //printf("vkFFT_single_c2c_afterR2C_for_transposition_8192\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_c2c_afterR2C_for_transposition_8192.spv"); + //printf("vkFFT_grouped_strided_convolution_symmetric_3x3\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_grouped_strided_convolution_symmetric_3x3.spv"); break; case 30: - //printf("vkFFT_single_c2c_beforeC2R_for_transposition_8192\n"); - sprintf(filename, "%s%s", configuration.shaderPath, "8192/vkFFT_single_c2c_beforeC2R_for_transposition_8192.spv"); + //printf("vkFFT_grouped_strided_convolution_nonsymmetric_3x3\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "vkFFT_grouped_strided_convolution_nonsymmetric_3x3.spv"); + break; + case 33: + //printf("vkFFT_single_c2r_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2r_16384.spv"); + break; + case 34: + //printf("vkFFT_single_r2c_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_r2c_16384.spv"); + break; + case 35: + //printf("vkFFT_single_c2c_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2c_16384.spv"); + break; + case 36: + //printf("vkFFT_single_c2r_for_transposition_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2r_for_transposition_16384.spv"); + break; + case 37: + //printf("vkFFT_single_r2c_for_transposition_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_r2c_for_transposition_16384.spv"); + break; + case 38: + //printf("vkFFT_single_c2c_for_transposition_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2c_for_transposition_16384.spv"); + break; + case 39: + //printf("vkFFT_single_c2c_afterR2C_for_transposition_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2c_afterR2C_for_transposition_16384.spv"); + break; + case 40: + //printf("vkFFT_single_c2c_beforeC2R_for_transposition_16384\n"); + sprintf(filename, "%s%s", configuration.shaderPath, "16384/vkFFT_single_c2c_beforeC2R_for_transposition_16384.spv"); break; - } @@ -260,61 +296,410 @@ typedef struct VkFFTApplication { free(code); } - void VkFFTPlanAxis(VkFFTPlan* FFTPlan, uint32_t axis_id, bool inverse) { + void VkFFTPlanAxis(VkFFTPlan* FFTPlan, uint32_t axis_id, uint32_t axis_upload_id, bool inverse) { //get radix stages - VkFFTAxis* axis = &FFTPlan->axes[axis_id]; - //for (uint32_t i; i<3; i++) - // axis->specializationConstants.size[i] = configuration.size[i]; - - //configure radix stages - uint32_t logSize = log2(configuration.size[axis_id]); - switch (configuration.radix) { - case 8: { - uint32_t stage8 = logSize / 3; - uint32_t stage4 = 0; - uint32_t stage2 = 0; - if (logSize % 3 == 2) - stage4 = 1; - if (logSize % 3 == 1) - stage2 = 1; - axis->specializationConstants.numStages = stage8 + stage4 + stage2; - - axis->specializationConstants.stageRadix[0] = 8; - axis->specializationConstants.stageRadix[1] = 8; - if (logSize % 3 == 2) - axis->specializationConstants.stageRadix[1] = 4; - if (logSize % 3 == 1) - axis->specializationConstants.stageRadix[1] = 2; - break; - } - case 4: { - uint32_t stage4 = logSize / 2; - uint32_t stage2 = 0; - if (logSize % 2 == 1) - stage2 = 1; - axis->specializationConstants.numStages = stage4 + stage2; + VkFFTAxis* axis = &FFTPlan->axes[axis_id][axis_upload_id]; + + if (axis_id == 0) { + //configure radix stages + uint32_t logSize = log2(configuration.size[axis_id]); + uint32_t numPasses[8][8];//4096-8k(256KB)-16k(256KB)-32k-64k - find correct strided FFT configuration - x axis | 256-512-1024-2048(256KB)-4096(256KB)-8k(future?)-16k(future?) - find correct strided FFT configuration + for (uint32_t i = 0; i < 8; i++) { + for (uint32_t j = 0; j < 8; j++) { + numPasses[i][j] = 0; + } + } + uint32_t temp = configuration.size[axis_id]; + uint32_t startStage = 4096; + uint32_t continueStage = 256; + uint32_t maxPassId[2] = { 0,0 }; + uint32_t minPassId[2] = { 0,0 }; + maxPassId[0] += log2(configuration.registerBoost); + uint32_t maxSingleSize = 8 * 4096 / configuration.coalescedMemory; + maxPassId[1] = log2(maxSingleSize / 256); + minPassId[1] = (maxSingleSize >= 512) ? 1 : 0; + //maxPassId[1] += log2(configuration.registerBoost);//in development + for (uint32_t i = 0; i < 8; i++) { + for (uint32_t j = 0; j < 8; j++) { + temp /= startStage; + numPasses[i][j]++; + while (temp > 1) + { + temp /= continueStage; + numPasses[i][j]++; + } + continueStage *= 2; + temp = configuration.size[axis_id]; + } + continueStage = 256; + startStage *= 2; + } + uint32_t passId[2] = { minPassId[0], minPassId[1] }; + for (uint32_t i = minPassId[0]; i < maxPassId[0]+1; i++) { + for (uint32_t j = minPassId[1]; j < maxPassId[1]+1; j++) { + if (numPasses[i][j] < numPasses[passId[0]][passId[1]]) { + passId[0] = i; + passId[1] = j; + } + } + } + FFTPlan->numAxisUploads[axis_id] = numPasses[passId[0]][passId[1]]; + if (axis_upload_id >= numPasses[passId[0]][passId[1]]) + return; + if (axis_upload_id == 0) { + //first pass is non-strided, special case + switch (configuration.radix) { + case 8: { + uint32_t logSize0Pass = (12 + passId[0] < logSize) ? 12 + passId[0] : logSize; //4096 + shift + if ((axis_upload_id + 1 == numPasses[passId[0]][passId[1]] - 1) && (logSize - logSize0Pass < 3)) + logSize0Pass -= (3 - (logSize - logSize0Pass)); + uint32_t stage8 = logSize0Pass / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSize0Pass % 3 == 2) + stage4 = 1; + if (logSize0Pass % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + + axis->specializationConstants.numStages = stage8; + axis->specializationConstants.fftDim = pow(8, stage8); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + axis->specializationConstants.stageStartSize = 1; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; - axis->specializationConstants.stageRadix[0] = 4; - axis->specializationConstants.stageRadix[1] = 4; - if (logSize % 2 == 1) - axis->specializationConstants.stageRadix[1] = 2; - break; - } - case 2: { - uint32_t stage2 = logSize; - axis->specializationConstants.numStages = stage2; + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + axis->specializationConstants.numStages = stage2; - axis->specializationConstants.stageRadix[0] = 2; - axis->specializationConstants.stageRadix[1] = 2; - break; - } + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } + } + else { + //passes after first are done similar to strided passes in y and z + uint32_t logSizeLaterPass = (logSize - 12 - passId[0]<3) ? 3 : logSize - 12 - passId[0]; //4096 + shift + switch (configuration.radix) { + case 8: { + uint32_t stage8 = logSizeLaterPass / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSizeLaterPass % 3 == 2) + stage4 = 1; + if (logSizeLaterPass % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + uint32_t locNumStages = 0; + if (passId[1] == minPassId[1]) { + locNumStages = stage8 / (numPasses[passId[0]][passId[1]] - 1); + if (axis_upload_id < stage8 % (numPasses[passId[0]][passId[1]] - 1)) + locNumStages++; + axis->specializationConstants.numStages = locNumStages; + axis->specializationConstants.fftDim = pow(8, locNumStages); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (axis_upload_id == (numPasses[passId[0]][passId[1]] - 1)) { + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + } + axis->specializationConstants.stageStartSize = FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + if (axis_upload_id < numPasses[passId[0]][passId[1]] - 1) { + uint32_t locLogSize = 8 + passId[1]; + if ((axis_upload_id + 1 == numPasses[passId[0]][passId[1]] - 1) && (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2) < 3)) + locLogSize -= (3 - (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2))); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + uint32_t locLogSize = (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2) < 3) ? 3 : logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + } + + + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; + + + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + + axis->specializationConstants.numStages = stage2; + + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } + } + }else{ + //configure radix stages + uint32_t logSize = log2(configuration.size[axis_id]); + uint32_t numPasses[8] = { 0,0,0,0,0,0,0,0 };//256-512-1024-2048(256KB)-4096(256KB)-8k(future?)-16k(future?) - find correct strided FFT configuration + uint32_t temp = configuration.size[axis_id]; + uint32_t startStage = 256; + uint32_t maxSingleSize = 8 * 4096 / configuration.coalescedMemory; + uint32_t maxPassId = log2(maxSingleSize / 256); + uint32_t minPassId = (maxSingleSize >= 512) ? 1 : 0; + //maxPassId += log2(configuration.registerBoost);//in development + for (uint32_t i = 0; i < 8; i++) { + while (temp > 1) + { + temp /= startStage; + numPasses[i]++; + } + temp = configuration.size[axis_id]; + startStage *= 2; + } + uint32_t passId = minPassId; + for (uint32_t i = minPassId; i < maxPassId+1; i++) { + if (numPasses[i] < numPasses[passId]) { + passId = i; + } + } + FFTPlan->numAxisUploads[axis_id] = numPasses[passId]; + if (axis_upload_id >= numPasses[passId]) + return; + switch (configuration.radix) { + case 8: { + uint32_t stage8 = logSize / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSize % 3 == 2) + stage4 = 1; + if (logSize % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + uint32_t locNumStages = 0; + if (passId == minPassId) { + locNumStages = stage8 / numPasses[passId]; + if (axis_upload_id < stage8 % numPasses[passId]) + locNumStages++; + axis->specializationConstants.numStages = locNumStages; + axis->specializationConstants.fftDim = pow(8, locNumStages); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (axis_upload_id == numPasses[passId] - 1) { + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + if (axis_upload_id < numPasses[passId] - 1) { + + uint32_t locLogSize = 8 + passId; + if ((axis_upload_id + 1 == numPasses[passId] - 1) && (logSize - (8 + passId) * (numPasses[passId] - 1) < 3)) + locLogSize -= (3 - (logSize - (8 + passId) * (numPasses[passId] - 1))); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + uint32_t locLogSize = (logSize - (8 + passId)*(numPasses[passId] - 1)<3) ? 3 : logSize - (8 + passId) * (numPasses[passId] - 1); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + } + + + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; + + + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + + axis->specializationConstants.numStages = stage2; + + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } } - if (4096 / configuration.size[1] > configuration.coalescedMemory / 16) { + + //axis->groupedBatch = (4096 / axis->specializationConstants.fftDim >= configuration.coalescedMemory / 8) ? 4096 / axis->specializationConstants.fftDim : configuration.coalescedMemory / 8; + axis->specializationConstants.passID = FFTPlan->numAxisUploads[axis_id] - 1 - axis_upload_id; + axis->specializationConstants.fft_dim_full = configuration.size[axis_id]; + axis->groupedBatch = (4096 / axis->specializationConstants.fftDim >= configuration.coalescedMemory / 8) ? 4096 / axis->specializationConstants.fftDim : configuration.coalescedMemory / 8; + //axis->groupedBatch = ((axis_upload_id > 0) && (axis->groupedBatch > axis->specializationConstants.stageStartSize)) ? axis->specializationConstants.stageStartSize : axis->groupedBatch; + /*if (4096 / configuration.size[1] > configuration.coalescedMemory / 16) { configuration.performTranspose[0] = false; - FFTPlan->axes[1].groupedBatch = 4096 / configuration.size[1]; + FFTPlan->groupedBatch = 4096 / configuration.size[1]; } else { configuration.performTranspose[0] = true; @@ -326,7 +711,7 @@ typedef struct VkFFTApplication { } else { configuration.performTranspose[1] = true; - } + }*/ //configure strides if (configuration.performR2C) { @@ -378,7 +763,7 @@ typedef struct VkFFTApplication { axis->specializationConstants.outputStride[2] = axis->specializationConstants.inputStride[2]; axis->specializationConstants.outputStride[3] = axis->specializationConstants.inputStride[3]; if (axis_id == 0) { - if ((configuration.isInputFormatted) && (!inverse)) { + if ((axis_upload_id==0)&&(configuration.isInputFormatted) && (!inverse)) { if (configuration.performZeropadding[0]) axis->specializationConstants.inputStride[1] = configuration.size[0] / 2; @@ -392,7 +777,7 @@ typedef struct VkFFTApplication { else axis->specializationConstants.inputStride[3] = axis->specializationConstants.inputStride[2] * configuration.size[2]; } - if ((configuration.isOutputFormatted) && ((inverse) || ((configuration.performConvolution) && (configuration.FFTdim == 1)))) { + if ((axis_upload_id == FFTPlan->numAxisUploads[axis_id]-1) && (configuration.isOutputFormatted) && ((inverse) || ((configuration.performConvolution) && (configuration.FFTdim == 1)))) { if (configuration.performZeropadding[0]) axis->specializationConstants.outputStride[1] = configuration.size[0] / 2; @@ -457,7 +842,7 @@ typedef struct VkFFTApplication { axis->specializationConstants.outputStride[2] = axis->specializationConstants.inputStride[2]; axis->specializationConstants.outputStride[3] = axis->specializationConstants.inputStride[3]; if (axis_id == 0) { - if ((configuration.isInputFormatted) && (!inverse)) { + if ((axis_upload_id == 0) && (configuration.isInputFormatted) && (!inverse)) { if (configuration.performZeropadding[0]) axis->specializationConstants.inputStride[1] = configuration.size[0] / 2; @@ -471,7 +856,7 @@ typedef struct VkFFTApplication { else axis->specializationConstants.inputStride[3] = axis->specializationConstants.inputStride[2] * configuration.size[2]; } - if ((configuration.isOutputFormatted) && ((inverse) || ((configuration.performConvolution) && (configuration.FFTdim == 1)))) { + if ((axis_upload_id == FFTPlan->numAxisUploads[axis_id]-1) && (configuration.isOutputFormatted) && ((inverse) || ((configuration.performConvolution) && (configuration.FFTdim == 1)))) { if (configuration.performZeropadding[0]) axis->specializationConstants.outputStride[1] = configuration.size[0] / 2; @@ -489,10 +874,6 @@ typedef struct VkFFTApplication { } axis->specializationConstants.inputStride[4] = axis->specializationConstants.inputStride[3] * configuration.coordinateFeatures; axis->specializationConstants.outputStride[4] = axis->specializationConstants.outputStride[3] * configuration.coordinateFeatures; - for (uint32_t i = 0; i < 3; ++i) { - axis->specializationConstants.radixStride[i] = configuration.size[axis_id] / pow(2, i + 1); - - } axis->specializationConstants.inverse = inverse; axis->specializationConstants.zeropad[0] = configuration.performZeropadding[axis_id]; @@ -500,7 +881,7 @@ typedef struct VkFFTApplication { axis->specializationConstants.zeropad[1] = configuration.performZeropadding[axis_id + 1]; else axis->specializationConstants.zeropad[1] = false; - + //not needed anymore as we don't transpose if (!inverse) { switch (axis_id) { case 0: @@ -698,11 +1079,11 @@ typedef struct VkFFTApplication { VkDescriptorPoolSize descriptorPoolSize = { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER }; descriptorPoolSize.descriptorCount = 2; - if ((axis_id == 0) && (configuration.FFTdim == 1) && (configuration.performConvolution)) + if ((axis_id == 0) && (axis_upload_id == 0) && (configuration.FFTdim == 1) && (configuration.performConvolution)) descriptorPoolSize.descriptorCount = 3; - if ((axis_id == 1) && (configuration.FFTdim == 2) && (configuration.performConvolution)) + if ((axis_id == 1) && (axis_upload_id == 0) && (configuration.FFTdim == 2) && (configuration.performConvolution)) descriptorPoolSize.descriptorCount = 3; - if ((axis_id == 2) && (configuration.FFTdim == 3) && (configuration.performConvolution)) + if ((axis_id == 2) && (axis_upload_id == 0) && (configuration.FFTdim == 3) && (configuration.performConvolution)) descriptorPoolSize.descriptorCount = 3; VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; @@ -736,15 +1117,15 @@ typedef struct VkFFTApplication { VkDescriptorBufferInfo descriptorBufferInfo = {}; if (i == 0) { - if (configuration.isInputFormatted && ( - ((axis_id == 0) && (!inverse)) - || ((axis_id == configuration.FFTdim-1) && (inverse))) + if ((axis_upload_id == FFTPlan->numAxisUploads[axis_id]-1) && (configuration.isInputFormatted) && ( + ((axis_id == 0) && (!inverse) ) + || ((axis_id == configuration.FFTdim-1) && (inverse) && (!configuration.performConvolution))) ) { descriptorBufferInfo.buffer = configuration.inputBuffer[0]; descriptorBufferInfo.range = configuration.inputBufferSize[0]; } else { - if ((configuration.numberKernels > 1) && (inverse)) { + if ((axis_upload_id == 0) && (configuration.numberKernels > 1) && (inverse) && (!configuration.performConvolution)) { descriptorBufferInfo.buffer = configuration.outputBuffer[0]; descriptorBufferInfo.range = configuration.outputBufferSize[0]; } @@ -756,7 +1137,7 @@ typedef struct VkFFTApplication { descriptorBufferInfo.offset = 0; } if (i == 1) { - if ((configuration.isOutputFormatted && ( + if ((axis_upload_id == 0) && (configuration.isOutputFormatted && ( ((axis_id == 0) && (inverse)) || ((axis_id == configuration.FFTdim-1) && (!inverse) && (!configuration.performConvolution)) || ((axis_id == 0) && (configuration.performConvolution) && (configuration.FFTdim == 1))) @@ -805,143 +1186,172 @@ typedef struct VkFFTApplication { vkCreatePipelineLayout(configuration.device[0], &pipelineLayoutCreateInfo, NULL, &axis->pipelineLayout); if (!inverse) { if (axis_id == 0) { - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - if (FFTPlan->axes[axis_id].axisBlock[0] > 512) FFTPlan->axes[axis_id].axisBlock[0] = 512; - if (configuration.performR2C) - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[1]) ? 1 : FFTPlan->axes[axis_id].specializationConstants.ratio[1] / 2; - else - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[1]) ? 1 : FFTPlan->axes[axis_id].specializationConstants.ratio[1]; + + if (axis_upload_id == 0) { + axis->axisBlock[0] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + if (axis->axisBlock[0] > 512) axis->axisBlock[0] = 512; + + axis->axisBlock[1] = 1; + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } + else { + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + axis->axisBlock[0] = (axis->specializationConstants.stageStartSize > axis->groupedBatch) ? axis->groupedBatch : axis->specializationConstants.stageStartSize; + + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; } if (axis_id == 1) { - if (configuration.performTranspose[0]) { - VkFFTPlanTranspose(FFTPlan, 0, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - if (FFTPlan->axes[axis_id].axisBlock[0] > 512) FFTPlan->axes[axis_id].axisBlock[0] = 512; - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[0]) ? FFTPlan->axes[axis_id].specializationConstants.ratio[0] : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + if (configuration.performR2C) { + if (axis_upload_id == 0) { + for (uint32_t i = 0; i < 8; i++) + VkFFTPlanSupportAxis(FFTPlan, 1, i, inverse); + } + axis->axisBlock[0] = (configuration.size[0] / 2 > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0] / 2; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0]/2 > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0]/2;*/ } else { - if (configuration.performR2C) { - VkFFTPlanSupportAxis(FFTPlan, 1, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] / 2 > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0] / 2; - } - else - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + axis->axisBlock[0] = (configuration.size[0] > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0]; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0];*/ } + + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } if (axis_id == 2) { - if (configuration.performTranspose[1]) { - VkFFTPlanTranspose(FFTPlan, 1, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[0]) ? FFTPlan->axes[axis_id].specializationConstants.ratio[0] : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + if (configuration.performR2C) { + if (axis_upload_id == 0) { + for (uint32_t i = 0; i < 8; i++) + VkFFTPlanSupportAxis(FFTPlan, 2, i, inverse); + } + axis->axisBlock[0] = (configuration.size[0] / 2 > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0] / 2; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] / 2 > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0] / 2;*/ } else { - if (configuration.performTranspose[0]) { - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[1] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[1]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; - } - else { - if (configuration.performR2C) { - VkFFTPlanSupportAxis(FFTPlan, 2, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] / 2 > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0] / 2; - } + axis->axisBlock[0] = (configuration.size[0] > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0]; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; else - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; - } + axis->axisBlock[0] = configuration.size[0];*/ } + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; } } else { if (axis_id == 0) { - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - if (FFTPlan->axes[axis_id].axisBlock[0] > 512) FFTPlan->axes[axis_id].axisBlock[0] = 512; - if (configuration.performR2C) - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[0]) ? FFTPlan->axes[axis_id].specializationConstants.ratio[0] / 2 : 1; - else - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[0]) ? FFTPlan->axes[axis_id].specializationConstants.ratio[0] : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + if (axis_upload_id == 0) { + axis->axisBlock[0] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + if (axis->axisBlock[0] > 512) axis->axisBlock[0] = 512; + + axis->axisBlock[1] = 1; + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } + else { + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + axis->axisBlock[0] = (axis->specializationConstants.stageStartSize > axis->groupedBatch) ? axis->groupedBatch : axis->specializationConstants.stageStartSize; + + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } } if (axis_id == 1) { - if (configuration.performTranspose[0]) { - VkFFTPlanTranspose(FFTPlan, 0, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - if (FFTPlan->axes[axis_id].axisBlock[0] > 512) FFTPlan->axes[axis_id].axisBlock[0] = 512; - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[1]) ? 1 : FFTPlan->axes[axis_id].specializationConstants.ratio[1]; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + if (configuration.performR2C) { + if (axis_upload_id == 0) { + for (uint32_t i = 0; i < 8; i++) + VkFFTPlanSupportAxis(FFTPlan, 1, i, inverse); + } + axis->axisBlock[0] = (configuration.size[0] / 2 > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0] / 2; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] / 2 > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0] / 2;*/ } else { - if (configuration.performR2C) { - VkFFTPlanSupportAxis(FFTPlan, 1, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] / 2 > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0] / 2; - } - else - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + axis->axisBlock[0] = (configuration.size[0] > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0]; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0];*/ } + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } if (axis_id == 2) { - if (configuration.performTranspose[1]) { - VkFFTPlanTranspose(FFTPlan, 1, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[1] = (FFTPlan->axes[axis_id].specializationConstants.ratioDirection[1]) ? 1 : FFTPlan->axes[axis_id].specializationConstants.ratio[1]; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; + + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + if (configuration.performR2C) { + if (axis_upload_id == 0) { + for (uint32_t i = 0; i < 8; i++) + VkFFTPlanSupportAxis(FFTPlan, 2, i, inverse); + } + axis->axisBlock[0] = (configuration.size[0] / 2 > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0] / 2; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] / 2 > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0] / 2;*/ } else { - if (configuration.performTranspose[0]) { - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[1] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[1]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; - } - else { - if (configuration.performR2C) { - VkFFTPlanSupportAxis(FFTPlan, 2, inverse); - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] / 2 > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0] / 2; - } + axis->axisBlock[0] = (configuration.size[0] > axis->groupedBatch) ? axis->groupedBatch : configuration.size[0]; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[0] > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; else - FFTPlan->axes[axis_id].axisBlock[0] = (configuration.size[0] > FFTPlan->axes[axis_id].groupedBatch) ? FFTPlan->axes[axis_id].groupedBatch : configuration.size[0]; - FFTPlan->axes[axis_id].axisBlock[1] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->axes[axis_id].axisBlock[2] = 1; - FFTPlan->axes[axis_id].axisBlock[3] = configuration.size[axis_id]; - } + axis->axisBlock[0] = configuration.size[0];*/ } + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } } - VkSpecializationMapEntry specializationMapEntries[29] = { {} }; - for (uint32_t i = 0; i < 29; i++) { + VkSpecializationMapEntry specializationMapEntries[30] = { {} }; + for (uint32_t i = 0; i < 30; i++) { specializationMapEntries[i].constantID = i + 1; specializationMapEntries[i].size = sizeof(uint32_t); specializationMapEntries[i].offset = i * sizeof(uint32_t); } VkSpecializationInfo specializationInfo = {}; - specializationInfo.dataSize = 29 * sizeof(uint32_t); - specializationInfo.mapEntryCount = 29; + specializationInfo.dataSize = 30 * sizeof(uint32_t); + specializationInfo.mapEntryCount = 30; specializationInfo.pMapEntries = specializationMapEntries; - FFTPlan->axes[axis_id].specializationConstants.localSize[0] = FFTPlan->axes[axis_id].axisBlock[0]; - FFTPlan->axes[axis_id].specializationConstants.localSize[1] = FFTPlan->axes[axis_id].axisBlock[1]; - FFTPlan->axes[axis_id].specializationConstants.localSize[2] = FFTPlan->axes[axis_id].axisBlock[2]; - FFTPlan->axes[axis_id].specializationConstants.fftDim = FFTPlan->axes[axis_id].axisBlock[3]; - specializationInfo.pData = &FFTPlan->axes[axis_id].specializationConstants; + axis->specializationConstants.localSize[0] = axis->axisBlock[0]; + axis->specializationConstants.localSize[1] = axis->axisBlock[1]; + axis->specializationConstants.localSize[2] = axis->axisBlock[2]; + specializationInfo.pData = &axis->specializationConstants; VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; VkComputePipelineCreateInfo computePipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; @@ -951,14 +1361,32 @@ typedef struct VkFFTApplication { if (configuration.performR2C) { if (axis_id == 0) { if (inverse) { - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(23, &pipelineShaderStageCreateInfo.module); + switch (configuration.registerBoost) { + case 1: + { + VkFFTInitShader(1, &pipelineShaderStageCreateInfo.module); break; - default: - switch (configuration.size[axis_id+1]) { + } + case 2: + { + switch (axis->specializationConstants.fftDim) { + case 8192: + VkFFTInitShader(23, &pipelineShaderStageCreateInfo.module); + break; + default: + VkFFTInitShader(1, &pipelineShaderStageCreateInfo.module); + break; + } + break; + } + case 4: + { + switch (axis->specializationConstants.fftDim) { case 8192: - VkFFTInitShader(26, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(23, &pipelineShaderStageCreateInfo.module); + break; + case 16384: + VkFFTInitShader(33, &pipelineShaderStageCreateInfo.module); break; default: VkFFTInitShader(1, &pipelineShaderStageCreateInfo.module); @@ -966,16 +1394,35 @@ typedef struct VkFFTApplication { } break; } + } } else { - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(24, &pipelineShaderStageCreateInfo.module); + switch (configuration.registerBoost) { + case 1: + { + VkFFTInitShader(3, &pipelineShaderStageCreateInfo.module); break; - default: - switch (configuration.size[axis_id + 1]) { + } + case 2: + { + switch (axis->specializationConstants.fftDim) { + case 8192: + VkFFTInitShader(24, &pipelineShaderStageCreateInfo.module); + break; + default: + VkFFTInitShader(3, &pipelineShaderStageCreateInfo.module); + break; + } + break; + } + case 4: + { + switch (axis->specializationConstants.fftDim) { case 8192: - VkFFTInitShader(27, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(24, &pipelineShaderStageCreateInfo.module); + break; + case 16384: + VkFFTInitShader(34, &pipelineShaderStageCreateInfo.module); break; default: VkFFTInitShader(3, &pipelineShaderStageCreateInfo.module); @@ -983,31 +1430,43 @@ typedef struct VkFFTApplication { } break; } + } } } if (axis_id == 1) { - if ((configuration.FFTdim == 2) && (configuration.performConvolution)) { - if (configuration.performTranspose[0]) + if ((configuration.FFTdim == 2) && (configuration.performConvolution)&&(axis_upload_id == 0)) { + + switch (configuration.matrixConvolution) { case 1: - VkFFTInitShader(10, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); break; case 2: if (configuration.symmetricKernel) - VkFFTInitShader(13, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(11, &pipelineShaderStageCreateInfo.module); else - VkFFTInitShader(16, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(14, &pipelineShaderStageCreateInfo.module); break; case 3: if (configuration.symmetricKernel) - VkFFTInitShader(19, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(17, &pipelineShaderStageCreateInfo.module); else - VkFFTInitShader(22, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); break; } - else + + } + else { + VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); + } + + } + + if (axis_id == 2) { + if ((configuration.FFTdim == 3) && (configuration.performConvolution)&&(axis_upload_id == 0)) { + switch (configuration.matrixConvolution) { case 1: VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); @@ -1025,48 +1484,18 @@ typedef struct VkFFTApplication { VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); break; } - + } else { - if (configuration.performTranspose[0]) { - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); - break; - default: - if (inverse) - VkFFTInitShader(6, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(5, &pipelineShaderStageCreateInfo.module); - break; - /*switch (configuration.size[axis_id - 1]) { - case 8192: - if (inverse) - VkFFTInitShader(30, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(29, &pipelineShaderStageCreateInfo.module); - break; - default: - if (inverse) - VkFFTInitShader(6, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(5, &pipelineShaderStageCreateInfo.module); - break; - } - break;*/ - } - - } - else { + VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); - } } - } - - if (axis_id == 2) { - if ((configuration.FFTdim == 3) && (configuration.performConvolution)) { - if (configuration.performTranspose[1]) + } + else { + if (axis_id == 0) { + if ((configuration.FFTdim == 1) && (configuration.performConvolution) && (axis_upload_id == 0)) { + if (axis_upload_id == 0) { switch (configuration.matrixConvolution) { case 1: VkFFTInitShader(9, &pipelineShaderStageCreateInfo.module); @@ -1084,114 +1513,77 @@ typedef struct VkFFTApplication { VkFFTInitShader(21, &pipelineShaderStageCreateInfo.module); break; } - else + } + else { switch (configuration.matrixConvolution) { case 1: - VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(10, &pipelineShaderStageCreateInfo.module); break; case 2: if (configuration.symmetricKernel) - VkFFTInitShader(11, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(13, &pipelineShaderStageCreateInfo.module); else - VkFFTInitShader(14, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(16, &pipelineShaderStageCreateInfo.module); break; case 3: if (configuration.symmetricKernel) - VkFFTInitShader(17, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(19, &pipelineShaderStageCreateInfo.module); else - VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(22, &pipelineShaderStageCreateInfo.module); break; } - + } } else { - if (configuration.performTranspose[1]) { - - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); - break; + switch (configuration.registerBoost) { + case 1: + { + if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); + break; + } + case 2: + { + switch (axis->specializationConstants.fftDim) { + case 8192: + VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); + break; default: - switch (configuration.size[axis_id - 1]) { - case 8192: - VkFFTInitShader(28, &pipelineShaderStageCreateInfo.module); - break; - default: + if (axis_upload_id == 0) VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); - break; - } + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); break; } - - } - else - VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); - } - } - } - else { - if (axis_id == 0) { - if ((configuration.FFTdim == 1) && (configuration.performConvolution)) { - - switch (configuration.matrixConvolution) { - case 1: - VkFFTInitShader(9, &pipelineShaderStageCreateInfo.module); - break; - case 2: - if (configuration.symmetricKernel) - VkFFTInitShader(12, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(15, &pipelineShaderStageCreateInfo.module); - break; - case 3: - if (configuration.symmetricKernel) - VkFFTInitShader(18, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(21, &pipelineShaderStageCreateInfo.module); break; } - } - else { - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); - break; - default: - switch (configuration.size[axis_id + 1]) { + case 4: + { + switch (axis->specializationConstants.fftDim) { case 8192: - VkFFTInitShader(28, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); + break; + case 16384: + VkFFTInitShader(35, &pipelineShaderStageCreateInfo.module); break; default: - VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); break; } break; } - + } } } if (axis_id == 1) { - if ((configuration.FFTdim == 2) && (configuration.performConvolution)) { - if (configuration.performTranspose[0]) - switch (configuration.matrixConvolution) { - case 1: - VkFFTInitShader(10, &pipelineShaderStageCreateInfo.module); - break; - case 2: - if (configuration.symmetricKernel) - VkFFTInitShader(13, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(16, &pipelineShaderStageCreateInfo.module); - break; - case 3: - if (configuration.symmetricKernel) - VkFFTInitShader(19, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(22, &pipelineShaderStageCreateInfo.module); - break; - } - else + if ((configuration.FFTdim == 2) && (configuration.performConvolution) && (axis_upload_id == 0)) { + switch (configuration.matrixConvolution) { case 1: VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); @@ -1209,53 +1601,18 @@ typedef struct VkFFTApplication { VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); break; } + } else { - if (configuration.performTranspose[0]) { - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); - break; - default: - switch (configuration.size[axis_id - 1]) { - case 8192: - VkFFTInitShader(28, &pipelineShaderStageCreateInfo.module); - break; - default: - VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); - break; - } - break; - } - } - else { VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); - } + } } if (axis_id == 2) { - if ((configuration.FFTdim == 3) && (configuration.performConvolution)) { - if (configuration.performTranspose[1]) - switch (configuration.matrixConvolution) { - case 1: - VkFFTInitShader(9, &pipelineShaderStageCreateInfo.module); - break; - case 2: - if (configuration.symmetricKernel) - VkFFTInitShader(12, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(15, &pipelineShaderStageCreateInfo.module); - break; - case 3: - if (configuration.symmetricKernel) - VkFFTInitShader(18, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(21, &pipelineShaderStageCreateInfo.module); - break; - } - else + if ((configuration.FFTdim == 3) && (configuration.performConvolution) && (axis_upload_id == 0)) { + switch (configuration.matrixConvolution) { case 1: VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); @@ -1273,26 +1630,10 @@ typedef struct VkFFTApplication { VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); break; } + } else { - if (configuration.performTranspose[1]) - switch (configuration.size[axis_id]) { - case 8192: - VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); - break; - default: - switch (configuration.size[axis_id - 1]) { - case 8192: - VkFFTInitShader(28, &pipelineShaderStageCreateInfo.module); - break; - default: - VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); - break; - } - break; - } - else - VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); + VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); } } } @@ -1310,60 +1651,399 @@ typedef struct VkFFTApplication { } - void VkFFTPlanSupportAxis(VkFFTPlan* FFTPlan, uint32_t axis_id, bool inverse) { + void VkFFTPlanSupportAxis(VkFFTPlan* FFTPlan, uint32_t axis_id, uint32_t axis_upload_id, bool inverse) { //get radix stages - VkFFTAxis* axis = &FFTPlan->supportAxes[axis_id - 1]; - //for (uint32_t i; i<3; i++) - // axis->specializationConstants.size[i] = configuration.size[i]; - - //configure radix stages - uint32_t logSize = log2(configuration.size[axis_id]); - - switch (configuration.radix) { - case 8: { - uint32_t stage8 = logSize / 3; - uint32_t stage4 = 0; - uint32_t stage2 = 0; - if (logSize % 3 == 2) - stage4 = 1; - if (logSize % 3 == 1) - stage2 = 1; - axis->specializationConstants.numStages = stage8 + stage4 + stage2; - - axis->specializationConstants.stageRadix[0] = 8; - axis->specializationConstants.stageRadix[1] = 8; - if (logSize % 3 == 2) - axis->specializationConstants.stageRadix[1] = 4; - if (logSize % 3 == 1) - axis->specializationConstants.stageRadix[1] = 2; - break; - } - case 4: { - uint32_t stage4 = logSize / 2; - uint32_t stage2 = 0; - if (logSize % 2 == 1) - stage2 = 1; - axis->specializationConstants.numStages = stage4 + stage2; + VkFFTAxis* axis = &FFTPlan->supportAxes[axis_id - 1][axis_upload_id]; + if (axis_id == 1) { + //configure radix stages + uint32_t logSize = log2(configuration.size[axis_id]); + uint32_t numPasses[8][8];//4096-8k(256KB)-16k(256KB)-32k-64k - find correct strided FFT configuration - x axis | 256-512-1024-2048(256KB)-4096(256KB)-8k(future?)-16k(future?) - find correct strided FFT configuration + for (uint32_t i = 0; i < 8; i++) { + for (uint32_t j = 0; j < 8; j++) { + numPasses[i][j] = 0; + } + } + uint32_t temp = configuration.size[axis_id]; + uint32_t startStage = 4096; + uint32_t continueStage = 256; + uint32_t maxPassId[2] = { 0,0 }; + uint32_t minPassId[2] = { 0,0 }; + maxPassId[0] += log2(configuration.registerBoost); + uint32_t maxSingleSize = 8 * 4096 / configuration.coalescedMemory; + maxPassId[1] = log2(maxSingleSize / 256); + minPassId[1] = (maxSingleSize >= 512) ? 1 : 0; + //maxPassId[1] += log2(configuration.registerBoost);//in development + for (uint32_t i = 0; i < 8; i++) { + for (uint32_t j = 0; j < 8; j++) { + temp /= startStage; + numPasses[i][j]++; + while (temp > 1) + { + temp /= continueStage; + numPasses[i][j]++; + } + continueStage *= 2; + temp = configuration.size[axis_id]; + } + continueStage = 256; + startStage *= 2; + } + uint32_t passId[2] = { minPassId[0], minPassId[1] }; + for (uint32_t i = minPassId[0]; i < maxPassId[0]+1; i++) { + for (uint32_t j = minPassId[1]; j < maxPassId[1]+1; j++) { + if (numPasses[i][j] < numPasses[passId[0]][passId[1]]) { + passId[0] = i; + passId[1] = j; + } + } + } + FFTPlan->numSupportAxisUploads[axis_id - 1] = numPasses[passId[0]][passId[1]]; + if (axis_upload_id >= numPasses[passId[0]][passId[1]]) + return; + if (axis_upload_id == 0) { + //first pass is non-strided, special case + switch (configuration.radix) { + case 8: { + uint32_t logSize0Pass = (12 + passId[0] < logSize) ? 12 + passId[0] : logSize; //4096 + shift + if ((axis_upload_id + 1 == numPasses[passId[0]][passId[1]] - 1) && (logSize - logSize0Pass < 3)) + logSize0Pass -= (3 - (logSize - logSize0Pass)); + uint32_t stage8 = logSize0Pass / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSize0Pass % 3 == 2) + stage4 = 1; + if (logSize0Pass % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + + axis->specializationConstants.numStages = stage8; + axis->specializationConstants.fftDim = pow(8, stage8); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + axis->specializationConstants.stageStartSize = 1; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; - axis->specializationConstants.stageRadix[0] = 4; - axis->specializationConstants.stageRadix[1] = 4; - if (logSize % 2 == 1) - axis->specializationConstants.stageRadix[1] = 2; - break; - } - case 2: { - uint32_t stage2 = logSize; - axis->specializationConstants.numStages = stage2; + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + axis->specializationConstants.numStages = stage2; - axis->specializationConstants.stageRadix[0] = 2; - axis->specializationConstants.stageRadix[1] = 2; - break; - } + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } + } + else { + //passes after first are done similar to strided passes in y and z + uint32_t logSizeLaterPass = (logSize - 12 - passId[0] < 3) ? 3 : logSize - 12 - passId[0]; //4096 + shift + switch (configuration.radix) { + case 8: { + uint32_t stage8 = logSizeLaterPass / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSizeLaterPass % 3 == 2) + stage4 = 1; + if (logSizeLaterPass % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + uint32_t locNumStages = 0; + if (passId[1] == minPassId[1]) { + locNumStages = stage8 / (numPasses[passId[0]][passId[1]] - 1); + if (axis_upload_id < stage8 % (numPasses[passId[0]][passId[1]] - 1)) + locNumStages++; + axis->specializationConstants.numStages = locNumStages; + axis->specializationConstants.fftDim = pow(8, locNumStages); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (axis_upload_id == (numPasses[passId[0]][passId[1]] - 1)) { + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + } + axis->specializationConstants.stageStartSize = FFTPlan->supportAxes[axis_id-1][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.fftDim; + axis->specializationConstants.fft_dim_x = configuration.size[1]; + } + else { + if (axis_upload_id < numPasses[passId[0]][passId[1]] - 1) { + uint32_t locLogSize = 8 + passId[1]; + if ((axis_upload_id + 1 == numPasses[passId[0]][passId[1]] - 1) && (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2) < 3)) + locLogSize -= (3 - (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2))); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + uint32_t locLogSize = (logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2) < 3) ? 3 : logSizeLaterPass - (8 + passId[1]) * (numPasses[passId[0]][passId[1]] - 2); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + } + + + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; + + + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + + axis->specializationConstants.numStages = stage2; + + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } + } } + else { + //configure radix stages + uint32_t logSize = log2(configuration.size[axis_id]); + uint32_t numPasses[8] = { 0,0,0,0,0,0,0,0 };//256-512-1024-2048(256KB)-4096(256KB)-8k(future?)-16k(future?) - find correct strided FFT configuration + uint32_t temp = configuration.size[axis_id]; + uint32_t startStage = 256; + uint32_t maxSingleSize = 8 * 4096 / configuration.coalescedMemory; + uint32_t maxPassId = log2(maxSingleSize / 256); + uint32_t minPassId = (maxSingleSize >= 512) ? 1 : 0; + //maxPassId += log2(configuration.registerBoost); //in development + for (uint32_t i = 0; i < 8; i++) { + while (temp > 1) + { + temp /= startStage; + numPasses[i]++; + } + temp = configuration.size[axis_id]; + startStage *= 2; + } + uint32_t passId = minPassId; + for (uint32_t i = minPassId; i < maxPassId+1; i++) { + if (numPasses[i] < numPasses[passId]) { + passId = i; + } + } + FFTPlan->numSupportAxisUploads[axis_id-1] = numPasses[passId]; + if (axis_upload_id >= numPasses[passId]) + return; + switch (configuration.radix) { + case 8: { + uint32_t stage8 = logSize / 3; + uint32_t stage4 = 0; + uint32_t stage2 = 0; + if (logSize % 3 == 2) + stage4 = 1; + if (logSize % 3 == 1) + stage2 = 1; + uint32_t totNumStages = stage8 + stage4 + stage2; + uint32_t locNumStages = 0; + if (passId == minPassId) { + locNumStages = stage8 / numPasses[passId]; + if (axis_upload_id < stage8 % numPasses[passId]) + locNumStages++; + axis->specializationConstants.numStages = locNumStages; + axis->specializationConstants.fftDim = pow(8, locNumStages); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (axis_upload_id == numPasses[passId] - 1) { + if (stage4 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 4; + axis->specializationConstants.fftDim *= 4; + } + if (stage2 == 1) { + axis->specializationConstants.numStages++; + axis->specializationConstants.stageRadix[1] = 2; + axis->specializationConstants.fftDim *= 2; + } + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->supportAxes[axis_id - 1][axis_upload_id - 1].specializationConstants.fftDim; + axis->specializationConstants.fft_dim_x = configuration.size[1]; + } + else { + if (axis_upload_id < numPasses[passId] - 1) { + + uint32_t locLogSize = 8 + passId; + if ((axis_upload_id + 1 == numPasses[passId] - 1) && (logSize - (8 + passId) * (numPasses[passId] - 1) < 3)) + locLogSize -= (3 - (logSize - (8 + passId) * (numPasses[passId] - 1))); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + else { + uint32_t locLogSize = (logSize - (8 + passId) * (numPasses[passId] - 1) < 3) ? 3 : logSize - (8 + passId) * (numPasses[passId] - 1); + uint32_t locStage8 = locLogSize / 3; + uint32_t locStage4 = 0; + uint32_t locStage2 = 0; + if (locLogSize % 3 == 2) + locStage4 = 1; + if (locLogSize % 3 == 1) + locStage2 = 1; + axis->specializationConstants.numStages = locStage8 + locStage4 + locStage2; + axis->specializationConstants.fftDim = pow(2, locLogSize); + axis->specializationConstants.stageRadix[0] = 8; + axis->specializationConstants.stageRadix[1] = 8; + + if (locStage4 == 1) { + axis->specializationConstants.stageRadix[1] = 4; + } + if (locStage2 == 1) { + axis->specializationConstants.stageRadix[1] = 2; + } + axis->specializationConstants.stageStartSize = (axis_upload_id == 0) ? 1 : FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.stageStartSize * FFTPlan->axes[axis_id][axis_upload_id - 1].specializationConstants.fftDim; + if (configuration.performR2C) + axis->specializationConstants.fft_dim_x = configuration.size[0] / 2; + else + axis->specializationConstants.fft_dim_x = configuration.size[0]; + } + } + + + break; + } + case 4: { + uint32_t stage4 = logSize / 2; + uint32_t stage2 = 0; + if (logSize % 2 == 1) + stage2 = 1; + axis->specializationConstants.numStages = stage4 + stage2; + + axis->specializationConstants.stageRadix[0] = 4; + axis->specializationConstants.stageRadix[1] = 4; + if (logSize % 2 == 1) + axis->specializationConstants.stageRadix[1] = 2; + break; + } + case 2: { + uint32_t stage2 = logSize; + + axis->specializationConstants.numStages = stage2; + + + axis->specializationConstants.stageRadix[0] = 2; + axis->specializationConstants.stageRadix[1] = 2; + break; + } + } + } + axis->specializationConstants.passID = FFTPlan->numSupportAxisUploads[axis_id - 1] - 1 - axis_upload_id; + axis->specializationConstants.fft_dim_full = configuration.size[axis_id]; + axis->groupedBatch = (4096 / axis->specializationConstants.fftDim >= configuration.coalescedMemory / 8) ? 4096 / axis->specializationConstants.fftDim : configuration.coalescedMemory / 8; + //axis->groupedBatch = ((axis_upload_id>0)&&(axis->groupedBatch > axis->specializationConstants.stageStartSize)) ? axis->specializationConstants.stageStartSize : axis->groupedBatch; //configure strides //perform r2c axis->specializationConstants.inputStride[0] = 1; @@ -1394,11 +2074,6 @@ typedef struct VkFFTApplication { axis->specializationConstants.inputStride[4] = axis->specializationConstants.inputStride[3] * configuration.coordinateFeatures; axis->specializationConstants.outputStride[4] = axis->specializationConstants.outputStride[3] * configuration.coordinateFeatures; - for (uint32_t i = 0; i < 3; ++i) { - axis->specializationConstants.radixStride[i] = configuration.size[axis_id] / pow(2, i + 1); - - } - axis->specializationConstants.inverse = inverse; axis->specializationConstants.zeropad[0] = configuration.performZeropadding[axis_id]; axis->specializationConstants.zeropad[1] = false; @@ -1411,9 +2086,9 @@ typedef struct VkFFTApplication { VkDescriptorPoolSize descriptorPoolSize = { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER }; descriptorPoolSize.descriptorCount = 2; - if ((axis_id == 1) && (configuration.FFTdim == 2) && (configuration.performConvolution)) + if ((axis_id == 1) && (axis_upload_id == 0) && (configuration.FFTdim == 2) && (configuration.performConvolution)) descriptorPoolSize.descriptorCount = 3; - if ((axis_id == 2) && (configuration.FFTdim == 3) && (configuration.performConvolution)) + if ((axis_id == 2) && (axis_upload_id == 0) && (configuration.FFTdim == 3) && (configuration.performConvolution)) descriptorPoolSize.descriptorCount = 3; VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; @@ -1447,7 +2122,9 @@ typedef struct VkFFTApplication { VkDescriptorBufferInfo descriptorBufferInfo = {}; if (i == 0) { - if (configuration.isInputFormatted && ( + descriptorBufferInfo.buffer = configuration.buffer[0]; + descriptorBufferInfo.range = configuration.bufferSize[0]; + /*if (configuration.isInputFormatted && ( ((axis_id == 0) && (!inverse)) || ((axis_id == configuration.FFTdim-1) && (inverse))) ) { @@ -1463,11 +2140,13 @@ typedef struct VkFFTApplication { descriptorBufferInfo.buffer = configuration.buffer[0]; descriptorBufferInfo.range = configuration.bufferSize[0]; } - } + }*/ descriptorBufferInfo.offset = 0; } if (i == 1) { - if ((configuration.isOutputFormatted && ( + descriptorBufferInfo.buffer = configuration.buffer[0]; + descriptorBufferInfo.range = configuration.bufferSize[0]; + /*if ((configuration.isOutputFormatted && ( ((axis_id == 0) && (inverse)) || ((axis_id == configuration.FFTdim-1) && (!inverse) && (!configuration.performConvolution)) || ((axis_id == 0) && (configuration.performConvolution) && (configuration.FFTdim == 1))) @@ -1482,7 +2161,7 @@ typedef struct VkFFTApplication { else { descriptorBufferInfo.buffer = configuration.buffer[0]; descriptorBufferInfo.range = configuration.bufferSize[0]; - } + }*/ descriptorBufferInfo.offset = 0; } if (i == 2) { @@ -1516,33 +2195,50 @@ typedef struct VkFFTApplication { vkCreatePipelineLayout(configuration.device[0], &pipelineLayoutCreateInfo, NULL, &axis->pipelineLayout); if (axis_id == 1) { - FFTPlan->supportAxes[0].axisBlock[0] = (configuration.size[axis_id] / 8 > 1) ? configuration.size[axis_id] / 8 : 1; - FFTPlan->supportAxes[0].axisBlock[1] = 1; - FFTPlan->supportAxes[0].axisBlock[2] = 1; - FFTPlan->supportAxes[0].axisBlock[3] = configuration.size[1]; + if (axis_upload_id == 0) { + axis->axisBlock[0] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + if (axis->axisBlock[0] > 512) axis->axisBlock[0] = 512; + axis->axisBlock[1] = 1; + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } + else { + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + axis->axisBlock[0] = (axis->specializationConstants.stageStartSize > axis->groupedBatch) ? axis->groupedBatch : axis->specializationConstants.stageStartSize; + + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; + } } if (axis_id == 2) { - FFTPlan->supportAxes[1].axisBlock[0] = (configuration.size[1] > FFTPlan->supportAxes[1].groupedBatch) ? FFTPlan->supportAxes[1].groupedBatch : configuration.size[1]; - FFTPlan->supportAxes[1].axisBlock[1] = (configuration.size[2] / 8 > 1) ? configuration.size[2] / 8 : 1; - FFTPlan->supportAxes[1].axisBlock[2] = 1; - FFTPlan->supportAxes[1].axisBlock[3] = configuration.size[2]; + axis->axisBlock[1] = (axis->specializationConstants.fftDim / 8 > 1) ? axis->specializationConstants.fftDim / 8 : 1; + + axis->axisBlock[0] = (configuration.size[1] > axis->groupedBatch) ? axis->groupedBatch : configuration.size[1]; + /*if (axis->axisBlock[0] * axis->axisBlock[1] < 64) + if (configuration.size[1] > 64 / axis->axisBlock[1]) + axis->axisBlock[0] = 64 / axis->axisBlock[1]; + else + axis->axisBlock[0] = configuration.size[0];*/ + axis->axisBlock[2] = 1; + axis->axisBlock[3] = axis->specializationConstants.fftDim; } - VkSpecializationMapEntry specializationMapEntries[29] = { {} }; - for (uint32_t i = 0; i < 29; i++) { + VkSpecializationMapEntry specializationMapEntries[30] = { {} }; + for (uint32_t i = 0; i < 30; i++) { specializationMapEntries[i].constantID = i + 1; specializationMapEntries[i].size = sizeof(uint32_t); specializationMapEntries[i].offset = i * sizeof(uint32_t); } VkSpecializationInfo specializationInfo = {}; - specializationInfo.dataSize = 29 * sizeof(uint32_t); - specializationInfo.mapEntryCount = 29; + specializationInfo.dataSize = 30 * sizeof(uint32_t); + specializationInfo.mapEntryCount = 30; specializationInfo.pMapEntries = specializationMapEntries; - FFTPlan->supportAxes[axis_id-1].specializationConstants.localSize[0] = FFTPlan->supportAxes[axis_id-1].axisBlock[0]; - FFTPlan->supportAxes[axis_id-1].specializationConstants.localSize[1] = FFTPlan->supportAxes[axis_id-1].axisBlock[1]; - FFTPlan->supportAxes[axis_id-1].specializationConstants.localSize[2] = FFTPlan->supportAxes[axis_id-1].axisBlock[2]; - FFTPlan->supportAxes[axis_id-1].specializationConstants.fftDim = FFTPlan->supportAxes[axis_id-1].axisBlock[3]; - specializationInfo.pData = &FFTPlan->supportAxes[axis_id-1].specializationConstants; + axis->specializationConstants.localSize[0] = axis->axisBlock[0]; + axis->specializationConstants.localSize[1] = axis->axisBlock[1]; + axis->specializationConstants.localSize[2] = axis->axisBlock[2]; + axis->specializationConstants.fftDim = axis->axisBlock[3]; + specializationInfo.pData = &axis->specializationConstants; VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; VkComputePipelineCreateInfo computePipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; @@ -1552,52 +2248,119 @@ typedef struct VkFFTApplication { if (axis_id == 1) { - if ((configuration.FFTdim == 2) && (configuration.performConvolution)) { - switch (configuration.matrixConvolution) { + if ((configuration.FFTdim == 2) && (configuration.performConvolution) && (axis_upload_id == 0)) { + if (axis_upload_id == 0) { + switch (configuration.matrixConvolution) { + case 1: + VkFFTInitShader(9, &pipelineShaderStageCreateInfo.module); + break; + case 2: + if (configuration.symmetricKernel) + VkFFTInitShader(12, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(15, &pipelineShaderStageCreateInfo.module); + break; + case 3: + if (configuration.symmetricKernel) + VkFFTInitShader(18, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(21, &pipelineShaderStageCreateInfo.module); + break; + } + } + else { + switch (configuration.matrixConvolution) { + case 1: + VkFFTInitShader(10, &pipelineShaderStageCreateInfo.module); + break; + case 2: + if (configuration.symmetricKernel) + VkFFTInitShader(13, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(16, &pipelineShaderStageCreateInfo.module); + break; + case 3: + if (configuration.symmetricKernel) + VkFFTInitShader(19, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(22, &pipelineShaderStageCreateInfo.module); + break; + } + } + + } + else { + /*if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module);*/ + switch (configuration.registerBoost) { case 1: - VkFFTInitShader(9, &pipelineShaderStageCreateInfo.module); + { + if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); break; + } case 2: - if (configuration.symmetricKernel) - VkFFTInitShader(12, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(15, &pipelineShaderStageCreateInfo.module); + { + switch (axis->specializationConstants.fftDim) { + case 8192: + VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); + break; + default: + if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); + break; + } break; - case 3: - if (configuration.symmetricKernel) - VkFFTInitShader(18, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(21, &pipelineShaderStageCreateInfo.module); + } + case 4: + { + switch (axis->specializationConstants.fftDim){ + case 8192: + VkFFTInitShader(25, &pipelineShaderStageCreateInfo.module); + break; + case 16384: + VkFFTInitShader(35, &pipelineShaderStageCreateInfo.module); + break; + default: + if (axis_upload_id == 0) + VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(2, &pipelineShaderStageCreateInfo.module); + break; + } break; } - - } - else { - - VkFFTInitShader(0, &pipelineShaderStageCreateInfo.module); + } } } if (axis_id == 2) { - if ((configuration.FFTdim == 3) && (configuration.performConvolution)) { - switch (configuration.matrixConvolution) { - case 1: - VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); - break; - case 2: - if (configuration.symmetricKernel) - VkFFTInitShader(11, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(14, &pipelineShaderStageCreateInfo.module); - break; - case 3: - if (configuration.symmetricKernel) - VkFFTInitShader(17, &pipelineShaderStageCreateInfo.module); - else - VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); - break; - } + if ((configuration.FFTdim == 3) && (configuration.performConvolution) && (axis_upload_id == 0)) { + switch (configuration.matrixConvolution) { + case 1: + VkFFTInitShader(8, &pipelineShaderStageCreateInfo.module); + break; + case 2: + if (configuration.symmetricKernel) + VkFFTInitShader(11, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(14, &pipelineShaderStageCreateInfo.module); + break; + case 3: + if (configuration.symmetricKernel) + VkFFTInitShader(17, &pipelineShaderStageCreateInfo.module); + else + VkFFTInitShader(20, &pipelineShaderStageCreateInfo.module); + break; + } + } else { VkFFTInitShader(7, &pipelineShaderStageCreateInfo.module); @@ -1750,8 +2513,8 @@ typedef struct VkFFTApplication { VkComputePipelineCreateInfo computePipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; uint32_t max_dim = 1; - if (FFTPlan->axes[axis_id].axisBlock[1] * configuration.size[axis_id] < pow(2, floor(log2(sqrt(1024 * FFTPlan->transpose[axis_id].specializationConstants.ratio))))) - max_dim = FFTPlan->axes[axis_id].axisBlock[1] * configuration.size[axis_id]; + if (FFTPlan->axes[axis_id][0].axisBlock[1] * configuration.size[axis_id] < pow(2, floor(log2(sqrt(1024 * FFTPlan->transpose[axis_id].specializationConstants.ratio))))) + max_dim = FFTPlan->axes[axis_id][0].axisBlock[1] * configuration.size[axis_id]; else max_dim = pow(2, floor(log2(sqrt(1024 * FFTPlan->transpose[axis_id].specializationConstants.ratio)))); FFTPlan->transpose[axis_id].transposeBlock[0] = max_dim; @@ -1819,13 +2582,17 @@ typedef struct VkFFTApplication { if (configuration.matrixConvolution > 1) configuration.coordinateFeatures = configuration.matrixConvolution; if (configuration.performConvolution) { + configuration.inverse = false; for (uint32_t i = 0; i < configuration.FFTdim; i++) { - VkFFTPlanAxis(&localFFTPlan_inverse_convolution, i, true); + for (uint32_t j =0; j<8; j++) + VkFFTPlanAxis(&localFFTPlan_inverse_convolution, i, j, true); } + } for (uint32_t i = 0; i < configuration.FFTdim; i++) { - VkFFTPlanAxis(&localFFTPlan, i, configuration.inverse); + for (uint32_t j = 0; j < 8; j++) + VkFFTPlanAxis(&localFFTPlan, i, j, configuration.inverse); } } @@ -1839,50 +2606,85 @@ typedef struct VkFFTApplication { if (!configuration.inverse) { //FFT axis 0 for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[0].pushConstants.batch = j; - uint32_t maxCoordinate = ((configuration.matrixConvolution) > 1 && (configuration.performConvolution) && (configuration.FFTdim == 1)) ? 1 : configuration.coordinateFeatures; - for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.axes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[0].pipelineLayout, 0, 1, &localFFTPlan.axes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[1]) { - if (configuration.performZeropadding[2]) { + for (int l = localFFTPlan.numAxisUploads[0]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[0][l]; + axis->pushConstants.batch = j; + uint32_t maxCoordinate = ((configuration.matrixConvolution) > 1 && (configuration.performConvolution) && (configuration.FFTdim == 1)) ? 1 : configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - } - else { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - } - } - else { - if (configuration.performZeropadding[2]) { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0) , configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0) , ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1] , ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0) , configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1], configuration.size[2]); + } + } } else { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { + + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2] ); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0) , ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1] , ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0) , configuration.size[2] ); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1] , configuration.size[2]); + } + } } } - + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - + if (configuration.FFTdim > 1) { //transpose 0-1, if needed - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.transpose[0].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -1908,11 +2710,11 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - } + }*/ //FFT axis 1 if ((configuration.FFTdim == 2) && (configuration.performConvolution)) { - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { uint32_t maxCoordinate = (configuration.matrixConvolution > 1 ) ? 1 : configuration.coordinateFeatures; for (uint32_t i = 0; i < maxCoordinate; i++) { localFFTPlan.axes[1].pushConstants.coordinate = i; @@ -1937,50 +2739,75 @@ typedef struct VkFFTApplication { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } - else { - if (configuration.performR2C == true) { - uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; + else {*/ + if (configuration.performR2C == true) { + for (int l = localFFTPlan.numSupportAxisUploads[0]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[0][l]; + uint32_t maxCoordinate = ((configuration.matrixConvolution > 1)&&(l == 0)) ? 1 : configuration.coordinateFeatures; for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.supportAxes[0].pushConstants.coordinate = i; - localFFTPlan.supportAxes[0].pushConstants.batch = configuration.numberKernels; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[2]) { - vkCmdDispatch(commandBuffer, 1, 1, ceil(configuration.size[2] / 2.0)); + axis->pushConstants.coordinate = i; + + axis->pushConstants.batch = ((l == 0)&& (configuration.matrixConvolution == 1)) ? configuration.numberKernels : 0; + + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + } } - else { - vkCmdDispatch(commandBuffer, 1, 1, configuration.size[2]); + else{ + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, configuration.size[2]); + } } } + if (l >0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } - uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; + + } + + for (int l = localFFTPlan.numAxisUploads[1]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[1][l]; + uint32_t maxCoordinate = ((configuration.matrixConvolution > 1) && (l == 0)) ? 1 : configuration.coordinateFeatures; for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.axes[1].pushConstants.coordinate = i; - localFFTPlan.axes[1].pushConstants.batch = configuration.numberKernels; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipelineLayout, 0, 1, &localFFTPlan.axes[1].descriptorSet, 0, NULL); + + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = ((l == 0) && (configuration.matrixConvolution == 1)) ? configuration.numberKernels : 0; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); if (configuration.performZeropadding[2]) { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0]* configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0]* configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); } else { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0]* configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2] ); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0]* configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2] ); } } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } + + //} } else { - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.axes[1].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2008,55 +2835,75 @@ typedef struct VkFFTApplication { } else { - - if (configuration.performR2C == true) { - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.supportAxes[0].pushConstants.batch = j; + */ + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numSupportAxisUploads[0]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[0][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.supportAxes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[2]) { - vkCmdDispatch(commandBuffer, 1, 1, ceil(configuration.size[2] / 2.0)); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil (configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + } } else { - vkCmdDispatch(commandBuffer, 1, 1, configuration.size[2]); + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, configuration.size[2]); + } } } + if (l >=0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[1].pushConstants.batch = j; + } + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numAxisUploads[1]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[1][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.axes[1].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipelineLayout, 0, 1, &localFFTPlan.axes[1].descriptorSet, 0, NULL); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); if (configuration.performZeropadding[2]) { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); } else { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); } } - } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } + + //} } } //FFT axis 2 if (configuration.FFTdim > 2) { //transpose 1-2, after 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.transpose[1].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2082,11 +2929,11 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - } + }*/ if ((configuration.FFTdim == 3) && (configuration.performConvolution)) { //transposed 1-2, transposed 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; for (uint32_t i = 0; i < maxCoordinate; i++) { localFFTPlan.axes[2].pushConstants.coordinate = i; @@ -2103,55 +2950,71 @@ typedef struct VkFFTApplication { } else { - if (configuration.performTranspose[0]) { - //transposed 0-1, didn't transpose 1-2 - uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; - for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.axes[2].pushConstants.coordinate = i; - localFFTPlan.axes[2].pushConstants.batch = configuration.numberKernels; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[2].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[2].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0] / 2 + 1); - else - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0]); - } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + if (configuration.performTranspose[0]) { + //transposed 0-1, didn't transpose 1-2 + uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + localFFTPlan.axes[2].pushConstants.coordinate = i; + localFFTPlan.axes[2].pushConstants.batch = configuration.numberKernels; + vkCmdPushConstants(commandBuffer, localFFTPlan.axes[2].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[2].pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0] / 2 + 1); + else + vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0]); } - else { - //didn't transpose 0-1, didn't transpose 1-2 - if (configuration.performR2C == true) { - uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; - for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.supportAxes[1].pushConstants.coordinate = i; - localFFTPlan.supportAxes[1].pushConstants.batch = configuration.numberKernels; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[1].descriptorSet, 0, NULL); - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.supportAxes[1].axisBlock[0], 1, 1); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } + else {*/ + //didn't transpose 0-1, didn't transpose 1-2 + if (configuration.performR2C == true) { - } - } - uint32_t maxCoordinate = (configuration.matrixConvolution > 1) ? 1 : configuration.coordinateFeatures; + for (int l = localFFTPlan.numSupportAxisUploads[1]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[1][l]; + uint32_t maxCoordinate = ((configuration.matrixConvolution > 1) && (l == 0)) ? 1 : configuration.coordinateFeatures; for (uint32_t i = 0; i < maxCoordinate; i++) { - localFFTPlan.axes[2].pushConstants.coordinate = i; - localFFTPlan.axes[2].pushConstants.batch = configuration.numberKernels; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[2].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[2].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); - else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); + axis->pushConstants.coordinate = i; + + axis->pushConstants.batch = ((l == 0) && (configuration.matrixConvolution == 1)) ? configuration.numberKernels : 0; + + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->axisBlock[0]* configuration.size[2] / axis->specializationConstants.fftDim, 1, 1); + } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + if (l >=0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } + + for (int l= localFFTPlan.numAxisUploads[2]-1; l >=0; l--) { + + VkFFTAxis* axis = &localFFTPlan.axes[2][l]; + uint32_t maxCoordinate = ((configuration.matrixConvolution > 1) && (l == 0)) ? 1 : configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = ((l == 0) && (configuration.matrixConvolution == 1)) ? configuration.numberKernels : 0; + + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + //} + //} } else { //transposed 1-2, transposed 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.axes[2].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2168,39 +3031,9 @@ typedef struct VkFFTApplication { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } - else { - if (configuration.performTranspose[0]) { - //transposed 0-1, didn't transpose 1-2 - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[2].pushConstants.batch = j; - for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.axes[2].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[2].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[2].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0] / 2 + 1); - else - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0]); - } - } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - - } - else { - //didn't transpose 0-1, didn't transpose 1-2 - if (configuration.performR2C == true) { - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.supportAxes[1].pushConstants.batch = j; - for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.supportAxes[1].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[1].descriptorSet, 0, NULL); - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.supportAxes[1].axisBlock[0], 1, 1); - } - } - } + else { + if (configuration.performTranspose[0]) { + //transposed 0-1, didn't transpose 1-2 for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.axes[2].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2209,23 +3042,66 @@ typedef struct VkFFTApplication { vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); + vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0] / 2 + 1); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); + vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[0]); + } + } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + else {*/ + //didn't transpose 0-1, didn't transpose 1-2 + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numSupportAxisUploads[1]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[1][l]; + axis->pushConstants.batch = j; + for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { + axis->pushConstants.coordinate = i; + + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, 1); + } + if (l >= 0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + } + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numAxisUploads[2]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[2][l]; + axis->pushConstants.batch = j; + for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } } + + //} + //} } } } if (configuration.performConvolution) { if (configuration.FFTdim > 2) { + //transpose 1-2, after 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { for (uint32_t j = 0; j < configuration.numberKernels; j++) { localFFTPlan_inverse_convolution.transpose[1].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2278,51 +3154,112 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } - else { - + else {*/ + //multiple upload ifft leftovers + if (configuration.FFTdim == 3) { if (configuration.performR2C == true) { for (uint32_t j = 0; j < configuration.numberKernels; j++) { - localFFTPlan_inverse_convolution.supportAxes[0].pushConstants.batch = j; + for (int l = 1; l< localFFTPlan_inverse_convolution.numSupportAxisUploads[1]; l++) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.supportAxes[1][l]; + uint32_t maxCoordinate = configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = j; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, 1); + + } + if (l > 0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + } + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = 1; l < localFFTPlan_inverse_convolution.numAxisUploads[2]; l++) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.axes[2][l]; + uint32_t maxCoordinate = configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = j; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + } + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = localFFTPlan_inverse_convolution.numSupportAxisUploads[0]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.supportAxes[0][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan_inverse_convolution.supportAxes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan_inverse_convolution.supportAxes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan_inverse_convolution.supportAxes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.supportAxes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.supportAxes[0].pipelineLayout, 0, 1, &localFFTPlan_inverse_convolution.supportAxes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[2]) { - vkCmdDispatch(commandBuffer, 1, 1, ceil(configuration.size[2] / 2.0)); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + } } else { - vkCmdDispatch(commandBuffer, 1, 1, configuration.size[2]); + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, configuration.size[2]); + } } } + if (l >= 0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } - for (uint32_t j = 0; j < configuration.numberKernels; j++) { - localFFTPlan_inverse_convolution.axes[1].pushConstants.batch = j; + } + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = localFFTPlan_inverse_convolution.numAxisUploads[1]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.axes[1][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan_inverse_convolution.axes[1].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan_inverse_convolution.axes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan_inverse_convolution.axes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.axes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.axes[1].pipelineLayout, 0, 1, &localFFTPlan_inverse_convolution.axes[1].descriptorSet, 0, NULL); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); if (configuration.performZeropadding[2]) { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan_inverse_convolution.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan_inverse_convolution.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); } else { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan_inverse_convolution.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan_inverse_convolution.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2] ); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan_inverse_convolution.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan_inverse_convolution.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2] ); } } - } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } + + //} @@ -2330,7 +3267,7 @@ typedef struct VkFFTApplication { } if (configuration.FFTdim > 1) { // transpose 0 - 1, if needed - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { for (uint32_t j = 0; j < configuration.numberKernels; j++) { localFFTPlan_inverse_convolution.transpose[0].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2356,50 +3293,183 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + }*/ + if (configuration.FFTdim == 2) { + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = 1; l< localFFTPlan_inverse_convolution.numSupportAxisUploads[0]; l++) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.supportAxes[0][l]; + uint32_t maxCoordinate = configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = j; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, configuration.size[2]); + } + } + } + if (l > 0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + + } + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = 1; l< localFFTPlan_inverse_convolution.numAxisUploads[1]; l++) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.axes[1][l]; + uint32_t maxCoordinate = configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = j; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + + } + } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } } for (uint32_t j = 0; j < configuration.numberKernels; j++) { - localFFTPlan_inverse_convolution.axes[0].pushConstants.batch = j; - for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan_inverse_convolution.axes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan_inverse_convolution.axes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan_inverse_convolution.axes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.axes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan_inverse_convolution.axes[0].pipelineLayout, 0, 1, &localFFTPlan_inverse_convolution.axes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[1]) { - if (configuration.performZeropadding[2]) { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[2])); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[2])); + for (int l = localFFTPlan_inverse_convolution.numAxisUploads[0]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.axes[0][l]; + axis->pushConstants.batch = j; + for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { + + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1], ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1], configuration.size[2]); + } + } } else { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan_inverse_convolution.axes[0].axisBlock[2]); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan_inverse_convolution.axes[0].axisBlock[2]); + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1], ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1], configuration.size[2]); + } + } } + } - else { + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + + + } + if (configuration.FFTdim == 1) { + for (uint32_t j = 0; j < configuration.numberKernels; j++) { + for (int l = 1; l < localFFTPlan_inverse_convolution.numAxisUploads[0]; l++) { + VkFFTAxis* axis = &localFFTPlan_inverse_convolution.axes[0][l]; + uint32_t maxCoordinate = configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + + axis->pushConstants.coordinate = i; + axis->pushConstants.batch = j; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); if (configuration.performZeropadding[2]) { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[2])); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan_inverse_convolution.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan_inverse_convolution.axes[0].axisBlock[2])); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); } else { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan_inverse_convolution.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan_inverse_convolution.axes[0].axisBlock[2]); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan_inverse_convolution.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan_inverse_convolution.axes[0].axisBlock[2]); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); } } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - - } } @@ -2408,7 +3478,7 @@ typedef struct VkFFTApplication { //FFT axis 2 if (configuration.FFTdim > 2) { //transposed 1-2, transposed 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.axes[2].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2444,39 +3514,52 @@ typedef struct VkFFTApplication { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } - else { + else {*/ //didn't transpose 0-1, didn't transpose 1-2 - if (configuration.performR2C == true) { - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.supportAxes[1].pushConstants.batch = j; - for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.supportAxes[1].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[1].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[1].descriptorSet, 0, NULL); - vkCmdDispatch(commandBuffer, configuration.size[1] / localFFTPlan.supportAxes[1].axisBlock[0], 1, 1); - } - } - } - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[2].pushConstants.batch = j; + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numSupportAxisUploads[1]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[1][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.axes[2].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[2].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[2].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[2].pipelineLayout, 0, 1, &localFFTPlan.axes[2].descriptorSet, 0, NULL); - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); - else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[2].axisBlock[0], 1, configuration.size[1]); + axis->pushConstants.coordinate = i; + + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, 1); + } + if (l >0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + + } + } + } + + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numAxisUploads[2]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[2][l]; + axis->pushConstants.batch = j; + for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[2] / axis->specializationConstants.fftDim, 1, configuration.size[1]); } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } } + + //} + //} //transpose 1-2, after 0-1 - if (configuration.performTranspose[1]) { + /*if (configuration.performTranspose[1]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.transpose[1].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2502,13 +3585,13 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - } + }*/ } if (configuration.FFTdim > 1) { //FFT axis 1 - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.axes[1].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2526,54 +3609,72 @@ typedef struct VkFFTApplication { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } - else { - - if (configuration.performR2C == true) { - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.supportAxes[0].pushConstants.batch = j; + else {*/ + + if (configuration.performR2C == true) { + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numSupportAxisUploads[0]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan.supportAxes[0][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - - localFFTPlan.supportAxes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.supportAxes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.supportAxes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.supportAxes[0].pipelineLayout, 0, 1, &localFFTPlan.supportAxes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[2]) { - vkCmdDispatch(commandBuffer, 1, 1, ceil(configuration.size[2] / 2.0)); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); + } } else { - vkCmdDispatch(commandBuffer, 1, 1, configuration.size[2]); + if (configuration.performZeropadding[2]) { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, ceil(configuration.size[2] / 2.0)); + } + else { + vkCmdDispatch(commandBuffer, configuration.size[1] / axis->specializationConstants.fftDim / axis->axisBlock[0], 1, configuration.size[2]); + } } } + if (l >= 0) + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } - for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[1].pushConstants.batch = j; + } + for (uint32_t j = 0; j < configuration.numberBatches; j++) { + for (int l = localFFTPlan.numAxisUploads[1]-1; l >= 0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[1][l]; + axis->pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.axes[1].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[1].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[1].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[1].pipelineLayout, 0, 1, &localFFTPlan.axes[1].descriptorSet, 0, NULL); + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); if (configuration.performZeropadding[2]) { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[1].axisBlock[2])); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, ceil(configuration.size[2] / 2.0)); } else { if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, configuration.size[0] / 2 / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, ceil(configuration.size[0] / 2.0) / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); else - vkCmdDispatch(commandBuffer, configuration.size[0] / localFFTPlan.axes[1].axisBlock[0], 1, configuration.size[2] / localFFTPlan.axes[1].axisBlock[2]); + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->axisBlock[0] * configuration.size[1] / axis->specializationConstants.fftDim, 1, configuration.size[2]); } } - } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); + } } + //} // transpose 0 - 1, if needed - if (configuration.performTranspose[0]) { + /*if (configuration.performTranspose[0]) { for (uint32_t j = 0; j < configuration.numberBatches; j++) { localFFTPlan.transpose[0].pushConstants.batch = j; for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { @@ -2599,74 +3700,118 @@ typedef struct VkFFTApplication { } vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - } + }*/ } //FFT axis 0 for (uint32_t j = 0; j < configuration.numberBatches; j++) { - localFFTPlan.axes[0].pushConstants.batch = j; - for (uint32_t i = 0; i < configuration.coordinateFeatures; i++) { - localFFTPlan.axes[0].pushConstants.coordinate = i; - vkCmdPushConstants(commandBuffer, localFFTPlan.axes[0].pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &localFFTPlan.axes[0].pushConstants); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[0].pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, localFFTPlan.axes[0].pipelineLayout, 0, 1, &localFFTPlan.axes[0].descriptorSet, 0, NULL); - if (configuration.performZeropadding[1]) { - if (configuration.performZeropadding[2]) { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan.axes[0].axisBlock[1]), ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - } - else { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / 2.0 / localFFTPlan.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - else - vkCmdDispatch(commandBuffer, 1, ceil(configuration.size[1] / 2.0 / localFFTPlan.axes[0].axisBlock[1]), configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - } - } - else { - if (configuration.performZeropadding[2]) { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); - else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan.axes[0].axisBlock[1], ceil(configuration.size[2] / 2.0 / localFFTPlan.axes[0].axisBlock[2])); + for (int l = localFFTPlan.numAxisUploads[0]-1; l >=0; l--) { + VkFFTAxis* axis = &localFFTPlan.axes[0][l]; + axis->pushConstants.batch = j; + uint32_t maxCoordinate = ((configuration.matrixConvolution) > 1 && (configuration.performConvolution) && (configuration.FFTdim == 1)) ? 1 : configuration.coordinateFeatures; + for (uint32_t i = 0; i < maxCoordinate; i++) { + axis->pushConstants.coordinate = i; + vkCmdPushConstants(commandBuffer, axis->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkFFTPushConstantsLayout), &axis->pushConstants); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, axis->pipelineLayout, 0, 1, &axis->descriptorSet, 0, NULL); + if (l == 0) { + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { + + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1], ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, ceil(configuration.size[1] / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim, configuration.size[1], configuration.size[2]); + } + } } else { - if (configuration.performR2C == true) - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / 2 / localFFTPlan.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); - else - vkCmdDispatch(commandBuffer, 1, configuration.size[1] / localFFTPlan.axes[0].axisBlock[1], configuration.size[2] / localFFTPlan.axes[0].axisBlock[2]); + if (configuration.performZeropadding[1]) { + if (configuration.performZeropadding[2]) { + + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0 / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), configuration.size[2]); + } + } + else { + if (configuration.performZeropadding[2]) { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), ceil(configuration.size[2] / 2.0)); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1], ceil(configuration.size[2] / 2.0)); + } + else { + if (configuration.performR2C == true) + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], ceil(configuration.size[1] / 2.0), configuration.size[2]); + else + vkCmdDispatch(commandBuffer, configuration.size[0] / axis->specializationConstants.fftDim / axis->axisBlock[0], configuration.size[1], configuration.size[2]); + } + } } } + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); } } - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL); - + } } void deleteVulkanFFT() { for (uint32_t i = 0; i < configuration.FFTdim; i++) { - deleteAxis(&localFFTPlan.axes[i]); + for (uint32_t j = 0; j < localFFTPlan.numAxisUploads[i]; j++) + deleteAxis(&localFFTPlan.axes[i][j]); } - for (uint32_t i = 0; i < 2; i++) { + for (uint32_t i = 0; i < configuration.FFTdim-1; i++) { if (configuration.performTranspose[i]) deleteTranspose(&localFFTPlan.transpose[i]); - else - deleteAxis(&localFFTPlan.supportAxes[i]); + else { + for (uint32_t j = 0; j < localFFTPlan.numSupportAxisUploads[i]; j++) + deleteAxis(&localFFTPlan.supportAxes[i][j]); + } } if (configuration.performConvolution) { for (uint32_t i = 0; i < configuration.FFTdim; i++) { - deleteAxis(&localFFTPlan_inverse_convolution.axes[i]); + for (uint32_t j = 0; j < localFFTPlan_inverse_convolution.numAxisUploads[i]; j++) + deleteAxis(&localFFTPlan_inverse_convolution.axes[i][j]); } for (uint32_t i = 0; i < configuration.FFTdim - 1; i++) { if (configuration.performTranspose[i]) deleteTranspose(&localFFTPlan_inverse_convolution.transpose[i]); - else - deleteAxis(&localFFTPlan_inverse_convolution.supportAxes[i]); + else { + for (uint32_t j = 0; j < localFFTPlan_inverse_convolution.numSupportAxisUploads[i]; j++) + deleteAxis(&localFFTPlan_inverse_convolution.supportAxes[i][j]); + } } } }