123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.CUDA.FFTPlan;
- interface
- uses
- System.Classes,
- System.SysUtils,
- FMX.Dialogs,
-
- CUDA.Import,
- CUDA.FourierTransform,
- GXS.CUDA.API,
- GXS.CUDA.Context,
- Stage.Strings;
- type
- TCUDAFFTransform =
- (
- fftRealToComplex,
- fftComplexToReal,
- fftComplexToComplex,
- fftDoubleToDoubleComplex,
- fftDoubleComplexToDouble,
- fftDoubleComplexToDoubleComplex
- );
- TCUDAFFTdir = (fftdForward, fftdInverse);
- TCUDAFFTPlan = class(TCUDAComponent)
- private
- FHandle: TcufftHandle;
- FWidth: Integer;
- FHeight: Integer;
- FDepth: Integer;
- FBatch: Integer;
- FSize: Integer;
- FPaddedSize: Integer;
- FTransform: TCUDAFFTransform;
- FStatus: TcufftResult;
- procedure SetWidth(Value: Integer);
- procedure SetHeight(Value: Integer);
- procedure SetDepth(Value: Integer);
- procedure SetBatch(Value: Integer);
- procedure SetTransform(Value: TCUDAFFTransform);
- protected
- procedure AllocateHandles; override;
- procedure DestroyHandles; override;
- class procedure CheckLib;
- public
-
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure Execute(ASrc: TCUDAMemData; ADst: TCUDAMemData;
- const ADir: TCUDAFFTdir = fftdForward);
- published
- property Width: Integer read fWidth write SetWidth default 256;
- property Height: Integer read FHeight write SetHeight default 0;
- property Depth: Integer read FDepth write SetDepth default 0;
- property Batch: Integer read FBatch write SetBatch default 1;
- property Transform: TCUDAFFTransform read FTransform write SetTransform
- default fftRealToComplex;
- end;
- implementation //-----------------------------------------
- constructor TCUDAFFTPlan.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FHandle := INVALID_CUFFT_HANDLE;
- fWidth := 256;
- FHeight := 0;
- FDepth := 0;
- FBatch := 1;
- FTransform := fftRealToComplex;
- end;
- destructor TCUDAFFTPlan.Destroy;
- begin
- DestroyHandles;
- inherited;
- end;
- class procedure TCUDAFFTPlan.CheckLib;
- begin
- if not IsCUFFTInitialized then
- if not InitCUFFT then
- begin
- ShowMessage('Can not initialize CUFFT library');
- Abort;
- end;
- end;
- procedure TCUDAFFTPlan.Assign(Source: TPersistent);
- var
- plan: TCUDAFFTPlan;
- begin
- if Source is TCUDAFFTPlan then
- begin
- DestroyHandles;
- plan := TCUDAFFTPlan(Source);
- Width := plan.fWidth;
- Height := plan.FHeight;
- Depth := plan.FDepth;
- Transform := plan.FTransform;
- end;
- inherited Assign(Source);
- end;
- procedure TCUDAFFTPlan.AllocateHandles;
- var
- LType: TcufftType;
- begin
- DestroyHandles;
- case FTransform of
- fftRealToComplex:
- LType := CUFFT_R2C;
- fftComplexToReal:
- LType := CUFFT_C2R;
- fftComplexToComplex:
- LType := CUFFT_C2C;
- fftDoubleToDoubleComplex:
- LType := CUFFT_D2Z;
- fftDoubleComplexToDouble:
- LType := CUFFT_Z2D;
- fftDoubleComplexToDoubleComplex:
- LType := CUFFT_Z2Z;
- else
- begin
- Assert(False, strErrorEx + strUnknownType);
- LType := CUFFT_R2C;
- end;
- end;
- Context.Requires;
- if (FHeight = 0) and (FDepth = 0) then
- begin
- FStatus := cufftPlan1d(FHandle, fWidth, LType, FBatch);
- FSize := FWidth;
- FPaddedSize := FWidth div 2 + 1;
- if FBatch > 0 then
- begin
- FSize := FSize * FBatch;
- FPaddedSize := FPaddedSize * FBatch;
- end;
- end
- else if FDepth = 0 then
- begin
- FStatus := cufftPlan2d(FHandle, fWidth, FHeight, LType);
- FSize := FWidth * FHeight;
- FPaddedSize := FWidth * (FHeight div 2 + 1);
- end
- else
- begin
- FStatus := cufftPlan3d(FHandle, fWidth, FHeight, FDepth, LType);
- FSize := FWidth * FHeight * FDepth;
- FPaddedSize := FWidth * FHeight * (FDepth div 2 + 1);
- end;
- Context.Release;
- if FStatus <> CUFFT_SUCCESS then
- begin
- FHandle := INVALID_CUFFT_HANDLE;
- Abort;
- end;
- Context.Requires;
- FStatus := cufftSetCompatibilityMode(FHandle, CUFFT_COMPATIBILITY_FFTW_PADDING);
- Context.Release;
- fChanges := [];
- inherited;
- end;
- procedure TCUDAFFTPlan.DestroyHandles;
- begin
- inherited;
- CheckLib;
- if FHandle <> INVALID_CUFFT_HANDLE then
- begin
- Context.Requires;
- FStatus := cufftDestroy(FHandle);
- Context.Release;
- if FStatus <> CUFFT_SUCCESS then
- Abort;
- FHandle := 0;
- FPaddedSize := 0;
- end;
- end;
- procedure TCUDAFFTPlan.SetWidth(Value: Integer);
- begin
- if Value < 1 then
- Value := 1;
- if Value <> fWidth then
- begin
- fWidth := Value;
- CuNotifyChange(cuchSize);
- end;
- end;
- procedure TCUDAFFTPlan.SetHeight(Value: Integer);
- begin
- if Value < 0 then
- Value := 0;
- if Value <> FHeight then
- begin
- FHeight := Value;
- if FHeight > 0 then
- FBatch := 1;
- CuNotifyChange(cuchSize);
- end;
- end;
- procedure TCUDAFFTPlan.SetDepth(Value: Integer);
- begin
- if Value < 0 then
- Value := 0;
- if Value <> FDepth then
- begin
- FDepth := Value;
- if FDepth > 0 then
- FBatch := 1;
- CuNotifyChange(cuchSize);
- end;
- end;
- procedure TCUDAFFTPlan.SetBatch(Value: Integer);
- begin
- if Value < 1 then
- Value := 1;
- if Value <> FBatch then
- begin
- FBatch := Value;
- if FBatch > 1 then
- begin
- FHeight := 0;
- FDepth := 0;
- end;
- CuNotifyChange(cuchSize);
- end;
- end;
- procedure TCUDAFFTPlan.SetTransform(Value: TCUDAFFTransform);
- begin
- if Value <> FTransform then
- begin
- FTransform := Value;
- CuNotifyChange(cuchSize);
- end;
- end;
- procedure TCUDAFFTPlan.Execute(ASrc: TCUDAMemData; ADst: TCUDAMemData;
- const ADir: TCUDAFFTdir);
- const
- sFFTdir: array [TCUDAFFTdir] of Integer = (CUFFT_FORWARD, CUFFT_INVERSE);
- cSourceTypeSize: array[TCUDAFFTransform] of Byte = (
- SizeOf(TcufftReal),
- SizeOf(TcufftComplex),
- SizeOf(TcufftComplex),
- SizeOf(TcufftDoubleReal),
- SizeOf(TcufftDoubleComplex),
- SizeOf(TcufftDoubleComplex));
- cDestinationTypeSize: array[TCUDAFFTransform] of Byte = (
- SizeOf(TcufftComplex),
- SizeOf(TcufftReal),
- SizeOf(TcufftComplex),
- SizeOf(TcufftDoubleComplex),
- SizeOf(TcufftDoubleReal),
- SizeOf(TcufftDoubleComplex));
- var
- SrcPtr, DstPtr: Pointer;
- LSrcSize, LDstSize: Integer;
- procedure ForwardCheck;
- begin
- if (LSrcSize * FSize > ASrc.DataSize)
- or (LDstSize * FPaddedSize > ADst.DataSize) then
- begin
- ShowMessage(strBadPlanSize);
- Abort;
- end;
- end;
- procedure InverseCheck;
- begin
- if (LSrcSize * FPaddedSize > ASrc.DataSize)
- or (LDstSize * FSize > ADst.DataSize) then
- begin
- ShowMessage(strBadPlanSize);
- Abort;
- end;
- end;
- begin
- if (FHandle = INVALID_CUFFT_HANDLE) or (fChanges <> []) then
- AllocateHandles;
- if CUDAContextManager.GetCurrentThreadContext <> nil then
- begin
- ShowMessage(strRequireFreeThread);
- Abort;
- end;
- SrcPtr := ASrc.RawData;
- DstPtr := ADst.RawData;
- LSrcSize := cSourceTypeSize[FTransform];
- LDstSize := cDestinationTypeSize[FTransform];
- Context.Requires;
- try
- case FTransform of
- fftRealToComplex:
- begin
- ForwardCheck;
- FStatus := cufftExecR2C(FHandle, SrcPtr, DstPtr);
- end;
- fftComplexToReal:
- begin
- InverseCheck;
- FStatus := cufftExecC2R(FHandle, SrcPtr, DstPtr);
- end;
- fftComplexToComplex:
- begin
- case ADir of
- fftdForward: ForwardCheck;
- fftdInverse: InverseCheck;
- end;
- FStatus := cufftExecC2C(FHandle, SrcPtr, DstPtr, sFFTdir[ADir]);
- end;
- fftDoubleToDoubleComplex:
- begin
- ForwardCheck;
- FStatus := cufftExecD2Z(FHandle, SrcPtr, DstPtr);
- end;
- fftDoubleComplexToDouble:
- begin
- InverseCheck;
- FStatus := cufftExecZ2D(FHandle, SrcPtr, DstPtr);
- end;
- fftDoubleComplexToDoubleComplex:
- begin
- case ADir of
- fftdForward: ForwardCheck;
- fftdInverse: InverseCheck;
- end;
- FStatus := cufftExecZ2Z(FHandle, SrcPtr, DstPtr, sFFTdir[ADir]);
- end
- else
- FStatus := CUFFT_INVALID_VALUE;
- end;
- finally
- Context.Release;
- end;
- if FStatus <> CUFFT_SUCCESS then
- Abort;
- end;
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- RegisterClasses([TCUDAFFTPlan]);
- finalization
- CloseCUFFT;
- end.
|