Files
2026-07-13 13:13:17 +08:00

98 lines
2.6 KiB
HLSL

cbuffer IntParams : register(b0)
{
uint2 TexSize;
uint BufferSize;
uint TotalSteps;
uint IsInverse;
uint Direction;
uint Normalization;
}
cbuffer CallParams : register(b1)
{
int CallIndex;
}
float2 cmul(float2 a,float2 b){return float2(a.x*b.x-a.y*b.y,a.y*b.x+a.x*b.y);}
float2 cexp(float2 z){return float2(cos(z.y),sin(z.y))*exp(z.x);}
Texture2D<float4> Image : register(t0);
RWStructuredBuffer<float4> DataBuffer : register(u0);
#define IFFT (IsInverse==1)
[numthreads(64,1,1)]
void main_fft(uint3 DTid : SV_DispatchThreadID)
{
uint numStructs, stride;
DataBuffer.GetDimensions(numStructs, stride);
// buffer 2x size of input texture
if(DTid.x>= numStructs/2)return;
// bool Vertical=(Direction==1);
// uint StepCount=TotalSteps;
// uint ipass=uint(CallIndex);
uint2 StepsXY=uint2(log2(TexSize.xy));
//Direction: 0=horizontal, 1=vertical, 2=horizontal+vertical
bool Vertical=(Direction==1) || CallIndex>=StepsXY.x;
uint StepCount=Vertical?StepsXY.y:StepsXY.x;
uint ipass=(CallIndex>=StepsXY.x)?uint(CallIndex-StepsXY.x):uint(CallIndex);
uint WriteOffset=((CallIndex%2)==1)*(TexSize.x*TexSize.y);
uint ReadOffset=((CallIndex%2)==0)*(TexSize.x*TexSize.y);
int2 ip=int2(DTid.x%TexSize.x,(DTid.x/TexSize.x)%TexSize.y);
uint blocksize=1<<StepCount;
if(Vertical)ip=ip.yx;
int xblock=ip.x/blocksize;
uint ix=ip.x%blocksize;
uint iy=ip.y;
uint n=2<<(ipass);
uint oddg=(ix/(n/2))%2;
uint2 xx=uint2(
(ix/(n))*n+(ix%(n/2)),
(ix/(n))*n+(ix%(n/2))+n/2
);
// input scrambler
if(ipass==0){
xx.x=reversebits(xx.x)>>(32-StepCount);
xx.y=reversebits(xx.y)>>(32-StepCount);
}
xx+=blocksize*xblock;
int2 ipe=int2(xx.x,iy);
int2 ipo=int2(xx.y,iy);
if(Vertical){
ipe=int2(iy,xx.x);
ipo=int2(iy,xx.y);
}
float4 pe=0;
float4 po=0;
if(CallIndex==0){
pe=Image.Load(int3(ipe,0));
po=Image.Load(int3(ipo,0));
}else{
pe=DataBuffer[ipe.x+ipe.y*TexSize.x+ReadOffset];
po=DataBuffer[ipo.x+ipo.y*TexSize.x+ReadOffset];
}
float2 w=cexp(float2(0,(IFFT?1:-1)*acos(-1.0)*2.0*float(ix%(n))/float(n)));
float4 c=float4(pe.xy+cmul(po.xy,w.xy),pe.zw+cmul(po.zw,w.xy));
if(ipass==StepCount-1){
//float k=1./sqrt(float(n));
float k=Normalization==0
?1./sqrt(float(n))//ortho normalization
:((IsInverse==1)^(Normalization==2))?1./float(n):1.0;//backward or forward normalization
c*=k;
}
DataBuffer[DTid.x+WriteOffset]=c;
}