void CheckAgainstFFTW() { if (m_FFTW_2D == null) { m_FFTW_2D = new fftwlib.FFT2D(SIGNAL_SIZE_2D, SIGNAL_SIZE_2D); m_test_CPU = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, true, false, null); m_FFTW2D_Output = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null); } // Retrieve input as CPU-accessible m_test_CPU.CopyFrom(m_FFT2D_GPU.Input); PixelsBuffer bufferIn = m_test_CPU.MapRead(0, 0); m_test_CPU.UnMap(bufferIn); float2[,] input_GPU = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D]; using (System.IO.BinaryReader R = bufferIn.OpenStreamRead()) for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++) { for (int X = 0; X < SIGNAL_SIZE_2D; X++) { input_GPU[X, Y].Set(R.ReadSingle(), R.ReadSingle()); } } bufferIn.Dispose(); // Apply FFT m_FFT2D_GPU.FFT_GPUInOut(-1.0f); // Retrieve output as CPU-accessible m_test_CPU.CopyFrom(m_FFT2D_GPU.Output); PixelsBuffer bufferOut = m_test_CPU.MapRead(0, 0); m_test_CPU.UnMap(bufferOut); float2[,] output_GPU = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D]; using (System.IO.BinaryReader R = bufferOut.OpenStreamRead()) for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++) { for (int X = 0; X < SIGNAL_SIZE_2D; X++) { output_GPU[X, Y].Set(R.ReadSingle(), R.ReadSingle()); } } bufferOut.Dispose(); // Process input with FFTW m_FFTW_2D.FillInputSpatial((int _x, int _y, out float _r, out float _i) => { _r = input_GPU[_x, _y].x; _i = input_GPU[_x, _y].y; }); m_FFTW_2D.Execute(fftwlib.FFT2D.Normalization.DIMENSIONS_PRODUCT); float2[,] output_FFTW = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D]; m_FFTW_2D.GetOutput((int _x, int _y, float _r, float _i) => { output_FFTW[_x, _y].Set(_r, _i); }); // Upload FFTW output to GPU bufferOut = m_test_CPU.MapWrite(0, 0); using (System.IO.BinaryWriter W = bufferOut.OpenStreamWrite()) for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++) { for (int X = 0; X < SIGNAL_SIZE_2D; X++) { W.Write(output_FFTW[X, Y].x); W.Write(output_FFTW[X, Y].y); } } m_test_CPU.UnMap(bufferOut); bufferOut.Dispose(); m_FFTW2D_Output.CopyFrom(m_test_CPU); // Compare float sumSqDiffR = 0.0f; float sumSqDiffI = 0.0f; for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++) { for (int X = 0; X < SIGNAL_SIZE_2D; X++) { float2 GPU = output_GPU[X, Y]; float2 FFTW = output_FFTW[X, Y]; float2 diff = GPU - FFTW; sumSqDiffR += diff.x * diff.x; sumSqDiffI += diff.y * diff.y; } } labelDiff2D.Text = "SqDiff = " + sumSqDiffR.ToString("G3") + " , " + sumSqDiffI.ToString("G3"); }
protected unsafe override void OnLoad( EventArgs e ) { base.OnLoad( e ); using ( fftwlib.FFT2D FFT = new fftwlib.FFT2D( 256, 256 ) ) { // Build the source data // FillInput( FFT.Input ); { const double Lx = 400.0; const double Lz = Lx; const double WindAngle = 45.0 * Math.PI / 180.0; const double WindVelocity = 20.0; double Wx = Math.Cos( WindAngle ); double Wz = Math.Sin( WindAngle ); double U1, U2, fX, fZ; Random RNG = new Random( 1 ); FFT.FillInputFrequency( ( int Fx, int Fy, out float r, out float i ) => { double kx = (2.0 * Math.PI / Lx) * Fx; double kz = (2.0 * Math.PI / Lz) * Fy; // Build white gaussian noise // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise) U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fX = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 ); U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fZ = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 ); fX = fZ = 1.0; // Build Phillips spectrum double SqrtPhillips = Math.Sqrt( Phillips( kx, kz, WindVelocity, Wx, Wz ) ); r = (float) (1.0 / Math.Sqrt( 2.0 ) * fX * SqrtPhillips); i = (float) (1.0 / Math.Sqrt( 2.0 ) * fZ * SqrtPhillips); r = (float) (U1);// * Math.Exp( -0.001 * Math.Abs( Fx ) )); i = 0.0f;//(float) U2; // r = 0.0; // for ( int j=1; j < 100; j++ ) // r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j; // i = 0.0; // r = Math.Exp( -0.1 * kx ); // i = Math.Exp( -0.1 * kz ); } ); } // Fill in bitmap outputPanelFrequency.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+0] ))); byte I = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+1] ))); return 0xFF000000 | (uint) ((R << 16) | (I << 8)); } ); // Inverse FFT FFT.InputIsSpatial = false; // We fed frequencies and need an inverse transform FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // DEBUG: Test we get back what we fed! // FFT.SwapInputOutput(); // FFT.InputIsSpatial = false; // FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // Retrieve results outputPanelSpatial.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+0] ))); byte I = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+1] ))); // byte R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) )); // byte I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) )); return 0xFF000000 | (uint) ((R << 16) | (I << 8)); } ); ////////////////////////////////////////////////////////////////////////// // Save the results System.IO.FileInfo F = new System.IO.FileInfo( @".\Water0_256x256.complex" ); System.IO.FileStream S = F.Create(); System.IO.BinaryWriter Writer = new System.IO.BinaryWriter( S ); for ( int Y=0; Y < 256; Y++ ) for ( int X=0; X < 256; X++ ) { Writer.Write( FFT.Output[2*(256*Y+X)+0] ); Writer.Write( FFT.Output[2*(256*Y+X)+1] ); } Writer.Close(); S.Close(); } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); // Quick color picker L*a*b* extension test... (should totally NOT be here! :D) //Nuaj.Cirrus.Utility.ColorPickerForm picker = new Nuaj.Cirrus.Utility.ColorPickerForm(); //picker.ShowDialog( this ); ////////////////////////////////////////////////////////////////////////// // Initialize 1D data try { m_device1D.Init(imagePanel.Handle, false, true); m_FFT1D_GPU = new FFT1D_GPU(m_device1D, SIGNAL_SIZE); m_CB_Main1D = new ConstantBuffer <CB_Main>(m_device1D, 0); m_Shader_GenerateSignal1D = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/GenerateSignal.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_Shader_FilterSignal1D = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/FilterSignal.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_Shader_Display1D = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/Display.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_texSpectrumCopy = new Texture2D(m_device1D, SIGNAL_SIZE, 1, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null); } catch (Exception) { MessageBox.Show("Failed to initialize DirectX device! Can't execute GPU FFT!", "DirectX Error", MessageBoxButtons.OK, MessageBoxIcon.Error); m_device1D = null; } m_image = new ImageFile((uint)imagePanel.Width, (uint)imagePanel.Height, ImageUtility.PIXEL_FORMAT.BGRA8, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB)); try { m_FFTW_1D = new fftwlib.FFT2D(SIGNAL_SIZE, 1); // Allocate on the fly, if the interop fails then it will crash immediately but at least the } catch (Exception _e) { MessageBox.Show("Failed to initialize reference FFTW library! It's not necessary for the unit test unless you need to compare against \"ground truth\".\r\nReason:\r\n" + _e.Message, "FFTW Library Error", MessageBoxButtons.OK, MessageBoxIcon.Error); m_FFTW_1D = null; } imagePanel.SkipPaint = checkBoxGPU.Checked; UpdateGraph1D(); ////////////////////////////////////////////////////////////////////////// // Initialize 2D data try { m_device2D.Init(imagePanel2D.Handle, false, true); m_FFT2D_GPU = new FFT2D_GPU(m_device2D, SIGNAL_SIZE_2D); m_CB_Main2D = new ConstantBuffer <CB_Main>(m_device2D, 0); m_Shader_GenerateSignal2D = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/GenerateSignal2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_Shader_FilterSignal2D = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/FilterSignal2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_Shader_Display2D = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/Display2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_texOriginalSignalCopy2D = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null); m_texSpectrumCopy2D = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null); } catch (Exception _e) { MessageBox.Show("Failed to initialize DirectX device! Can't execute GPU FFT!\r\nReason:\r\n" + _e.Message, "DirectX Error", MessageBoxButtons.OK, MessageBoxIcon.Error); m_device2D = null; } m_image2D = new ImageFile((uint)imagePanel2D.Width, (uint)imagePanel2D.Height, PIXEL_FORMAT.BGRA8, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB)); imagePanel2D.SkipPaint = true; //checkBoxGPU.Checked; radioButtonSignalX_CheckedChanged(null, EventArgs.Empty); radioButtonSignalY_CheckedChanged(null, EventArgs.Empty); Application.Idle += Application_Idle; }
protected unsafe override void OnLoad(EventArgs e) { base.OnLoad(e); using (fftwlib.FFT2D FFT = new fftwlib.FFT2D(256, 256)) { // Build the source data // FillInput( FFT.Input ); { const double Lx = 400.0; const double Lz = Lx; const double WindAngle = 45.0 * Math.PI / 180.0; const double WindVelocity = 20.0; double Wx = Math.Cos(WindAngle); double Wz = Math.Sin(WindAngle); double U1, U2, fX, fZ; Random RNG = new Random(1); FFT.FillInputFrequency((int Fx, int Fy, out float r, out float i) => { double kx = (2.0 * Math.PI / Lx) * Fx; double kz = (2.0 * Math.PI / Lz) * Fy; // Build white gaussian noise // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise) U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fX = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fZ = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); fX = fZ = 1.0; // Build Phillips spectrum double SqrtPhillips = Math.Sqrt(Phillips(kx, kz, WindVelocity, Wx, Wz)); r = (float)(1.0 / Math.Sqrt(2.0) * fX * SqrtPhillips); i = (float)(1.0 / Math.Sqrt(2.0) * fZ * SqrtPhillips); r = (float)(U1); // * Math.Exp( -0.001 * Math.Abs( Fx ) )); i = 0.0f; //(float) U2; // r = 0.0; // for ( int j=1; j < 100; j++ ) // r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j; // i = 0.0; // r = Math.Exp( -0.1 * kx ); // i = Math.Exp( -0.1 * kz ); }); } // Fill in bitmap outputPanelFrequency.FillBitmap((int _X, int _Y, int _Width, int _Height) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 0]))); byte I = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 1]))); return(0xFF000000 | (uint)((R << 16) | (I << 8))); }); // Inverse FFT FFT.InputIsSpatial = false; // We fed frequencies and need an inverse transform FFT.Execute(fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT); // DEBUG: Test we get back what we fed! // FFT.SwapInputOutput(); // FFT.InputIsSpatial = false; // FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // Retrieve results outputPanelSpatial.FillBitmap((int _X, int _Y, int _Width, int _Height) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 0]))); byte I = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 1]))); // byte R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) )); // byte I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) )); return(0xFF000000 | (uint)((R << 16) | (I << 8))); }); ////////////////////////////////////////////////////////////////////////// // Save the results System.IO.FileInfo F = new System.IO.FileInfo(@".\Water0_256x256.complex"); System.IO.FileStream S = F.Create(); System.IO.BinaryWriter Writer = new System.IO.BinaryWriter(S); for (int Y = 0; Y < 256; Y++) { for (int X = 0; X < 256; X++) { Writer.Write(FFT.Output[2 * (256 * Y + X) + 0]); Writer.Write(FFT.Output[2 * (256 * Y + X) + 1]); } } Writer.Close(); S.Close(); } }