yum/vfft
git clone https://git.yummers.dev/yum/vfft
90039aa
master
1import lib.util; 2 3[[vk::binding(0, 0)]] 4RWStructuredBuffer<float2> input; 5 6[[vk::binding(1, 0)]] 7RWStructuredBuffer<float2> output; 8 9[[vk::binding(2, 0)]] 10StructuredBuffer<float2> twiddles; 11 12[[vk::binding(3, 0)]] 13cbuffer Uniforms { 14 uint input_len; 15 uint n_iter; 16}; 17 18groupshared float2 scratch[4096]; 19 20void fft_v2_stage(uint which_fft, uint id, uint stride, uint big_n) { 21 const uint k = id / stride; 22 const uint start_idx = id % stride; 23 24 // Collect inputs. 25 let i0 = scratch[start_idx + 8 * k * stride]; 26 let i1 = scratch[start_idx + (8 * k + 1) * stride]; 27 let i2 = scratch[start_idx + (8 * k + 2) * stride]; 28 let i3 = scratch[start_idx + (8 * k + 3) * stride]; 29 let i4 = scratch[start_idx + (8 * k + 4) * stride]; 30 let i5 = scratch[start_idx + (8 * k + 5) * stride]; 31 let i6 = scratch[start_idx + (8 * k + 6) * stride]; 32 let i7 = scratch[start_idx + (8 * k + 7) * stride]; 33 34 // Collect relevant twiddles. 35 let ot1 = twiddles[1 * k * stride]; 36 let ot2 = twiddles[2 * k * stride]; 37 let ot3 = twiddles[3 * k * stride]; 38 let ot4 = twiddles[4 * k * stride]; 39 let ot5 = twiddles[5 * k * stride]; 40 let ot6 = twiddles[6 * k * stride]; 41 let ot7 = twiddles[7 * k * stride]; 42 43 let a = i0; 44 let b = cmul(ot1, i1); 45 let c = cmul(ot2, i2); 46 let d = cmul(ot3, i3); 47 let e = cmul(ot4, i4); 48 let f = cmul(ot5, i5); 49 let g = cmul(ot6, i6); 50 let h = cmul(ot7, i7); 51 52 let ae_sum = a + e; 53 let ae_diff = a - e; 54 let bf_sum = b + f; 55 let bf_diff = b - f; 56 let cg_sum = c + g; 57 let cg_diff = c - g; 58 let dh_sum = d + h; 59 let dh_diff = d - h; 60 61 let w00 = ae_sum + cg_sum; 62 let w01 = ae_sum - cg_sum; 63 let w10 = ae_diff + rot_270(cg_diff); 64 let w11 = ae_diff - rot_270(cg_diff); 65 let x00 = bf_sum + dh_sum; 66 let x01 = rot_270(bf_sum) + rot_90(dh_sum); 67 let x10 = rot_45(rot_270(bf_diff) + rot_180(dh_diff)); 68 let x11 = rot_45(rot_180(bf_diff) + rot_270(dh_diff)); 69 70 GroupMemoryBarrierWithGroupSync(); 71 72 scratch[start_idx + k * stride] = w00 + x00; 73 scratch[start_idx + (k + big_n / 8) * stride] = w10 + x10; 74 scratch[start_idx + (k + big_n / 4) * stride] = w01 + x01; 75 scratch[start_idx + (k + 3 * big_n / 8) * stride] = w11 + x11; 76 scratch[start_idx + (k + big_n / 2) * stride] = w00 - x00; 77 scratch[start_idx + (k + 5 * big_n / 8) * stride] = w10 - x10; 78 scratch[start_idx + (k + 3 * big_n / 4) * stride] = w01 - x01; 79 scratch[start_idx + (k + 7 * big_n / 8) * stride] = w11 - x11; 80 81 GroupMemoryBarrierWithGroupSync(); 82} 83 84[shader("compute")] 85[numthreads(64, 8, 1)] 86void fft_v4_radix_8(uint3 globalId : SV_DispatchThreadID, uint id: SV_GroupIndex) 87{ 88 const uint which_fft = globalId.z; 89 90 uint stride = Uniforms.input_len; 91 uint big_n = 1; 92 93 const uint offset = which_fft * Uniforms.input_len; 94 for (uint i = 0; i < 8; i++) { 95 scratch[id + i * 512] = input[offset + id + i * 512]; 96 } 97 AllMemoryBarrierWithGroupSync(); 98 99 for (uint i = 0; i < Uniforms.n_iter; i++) { 100 stride /= 8; 101 big_n *= 8; 102 fft_v2_stage(which_fft, id, stride, big_n); 103 } 104 105 for (uint i = 0; i < 8; i++) { 106 output[offset + id + i * 512] = scratch[id + i * 512]; 107 } 108 AllMemoryBarrierWithGroupSync(); 109}