0

I am trying to implement an inverse FFT in a HLSL compute shader and don't understand how the new inversebits function works. The shader is run under Unity3D, but that shouldn't make a difference.

The problem is, that the resulting texture remains black with the exception of the leftmost one or two pixels in every row. It seems to me, as if the reversebits function wouldn't return the correct indexes.

My very simple code is as following:

#pragma kernel BitReverseHorizontal

Texture2D<float4> inTex;
RWTexture2D<float4> outTex;

uint2 getTextureThreadPosition(uint3 groupID, uint3 threadID) {
 uint2 pos;
 
 pos.x = (groupID.x * 16) + threadID.x;
 pos.y = (groupID.y * 16) + threadID.y;
 
 return pos;
}

[numthreads(16,16,1)]
void BitReverseHorizontal (uint3 threadID : SV_GroupThreadID, uint3 groupID : SV_GroupID)
{
    uint2 pos = getTextureThreadPosition(groupID, threadID);
    uint xPos = reversebits(pos.x);
    uint2 revPos = uint2(xPos, pos.y);
    
    float4 values;
    values.x = inTex[pos].x;
    values.y = inTex[pos].y;
    values.z = inTex[revPos].z;
    values.w = 0.0f;
    
    outTex[revPos] = values;
}

I played around with this for quite a while and found out, that if I replace the reversebits line with this one here:

uint xPos = reversebits(pos.x << 23);

it works. Although I have no idea why. Could be just coincidence. Could someone please explain to me, how I have to use the reversebits function correctly?

2 Answers2

0

Are you sure you want to reverse the bits?

x = 0: reversed: x = 0

x = 1: reversed: x = 2,147,483,648

x = 2: reversed: x = 1,073,741,824

etc....

If you fetch texels from a texture using coordinates exceeding the width of the texture then you're going to get black. Unless the texture is > 1 billion texels wide (it isn't) then you're fetching well outside the border.

Adam Miles
  • 3,504
  • 17
  • 15
0

I am doing the same and came to the same problem and these answers actually answered it for me but i'll give you the explanation and a whole solution.

So the solution with variable length buffers in HLSL is:

uint reversedIndx;
uint bits = 32 - log2(xLen); // sizeof(uint) - log2(numberOfIndices);
for (uint j = 0; j < xLen; j ++)
    reversedIndx = reversebits(j << bits);

And what you found/noticed essentially pushes out all the leading 0 of your index so you are just reversing the least significant or rightmost bits up until the max bits we want.

for example:

int length = 8;
int bits = 32 - 3; // because 1 << 3 is 0b1000 and we want the inverse like a mask
int j = 6;

and since the size of an int is generally 32bits in binary j would be

j = 0b00000000000000000000000000000110;

and reversed it would be (AKA reversebits(j);)

j = 0b01100000000000000000000000000000;

Which was our error, so j bit shifted by bits would be

j = 0b11000000000000000000000000000000;

and then reversed and what we want would be

j = 0b00000000000000000000000000000011;