Source browser
examples/shaders/fft_butterfly.cpp
Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.
File fingerprint
1// Apply one radix-two FFT stage with precomputed complex phases.
2#ifdef __cplusplus // Include the runtime only in the generated C++ build.
3#include "shdr.h" // Use portable complex values stored as vec2.
4#endif // Keep the shader source valid for a native GLSL compiler.
5layout(local_size_x = 64) in; // Each invocation writes one butterfly result.
6layout(std430, binding = 0) readonly buffer Input { // Read the previous stage.
7 vec2 input_values[]; // Read the previous stage.
8}; // Read the previous stage.
9layout(std430, binding = 1) writeonly buffer Output { // Write the next stage.
10 vec2 output_values[]; // Write the next stage.
11}; // Write the next stage.
12layout(std430, binding = 2) readonly buffer Phases { // Share one phase table between channels.
13 vec2 twiddles[]; // Share one phase table between channels.
14}; // Share one phase table between channels.
15uniform uint block_length; // Number of complex values per transform.
16uniform uint channels; // Number of independent transforms.
17uniform uint span; // Number of values covered by this stage's butterfly groups.
18uniform float direction; // Use +1 for forward phases and -1 for their conjugates.
19uniform float normalization; // Apply 1/N only on the final inverse stage.
20void main() { // Each stage writes independent positions in the next working buffer.
21 uint index = gl_GlobalInvocationID.x; // Select one output value.
22 if (index >= block_length * channels) // Ignore padding in the dispatch.
23 return; // Ignore padding in the dispatch.
24 uint position = index % block_length; // Locate the value within its channel.
25 uint half_span = span / 2u; // Separate the two inputs of a butterfly.
26 uint offset = position % half_span; // Select the phase within this butterfly group.
27 uint base = // Find the group's first input.
28 index - position + (position / span) * span + offset; // Find the group's first input.
29 vec2 first = input_values[base]; // Read the even half of the group.
30 vec2 second = input_values[base + half_span]; // Read the odd half of the group.
31 vec2 phase = twiddles[offset * (block_length / span)]; // Reuse phases from the full-block table.
32 phase.y *= direction; // Conjugation changes a forward FFT into an inverse FFT.
33 vec2 rotated = vec2(second.x * phase.x - second.y * phase.y, // Multiply two complex values.
34 second.x * phase.y + second.y * phase.x); // Multiply two complex values.
35 vec2 value = position % span < half_span // Choose the sum or difference output.
36 ? first + rotated // Choose the sum or difference output.
37 : first - rotated; // Choose the sum or difference output.
38 output_values[index] = value * normalization; // Scale the final inverse result when requested.
39} // A dispatch boundary makes this stage visible to the next stage.