gboisse / gfx

A minimalist and easy to use graphics API.
MIT License
502 stars 36 forks source link

Using RWByteAddressBuffer and ByteAddressBuffer #9

Closed sayan1an closed 3 years ago

sayan1an commented 3 years ago

Host side:

byteBuffer = gfxCreateBuffer<uint32_t>(gfx, (nBytes / sizeof(uint32_t) + 1));
gfxProgramSetParameter(..., .., "byteBufferRW", byteBuffer);
gfxProgramSetParameter(..., .., "byteBuffer", byteBuffer);

Comp Shader:

RWByteAddressBuffer byteBufferRW;
byteBufferRW.Store(idx, value);

ByteAddressBuffer byteBuffer;
loadVal = byteBuffer.Load(idx);

value and loadVal aren't same. Seems like I am creating the byte addressable buffer wrong?

gboisse commented 3 years ago

Not really sure what you are doing here with your idx but addressing of byte buffers must be 4-byte aligned: https://docs.microsoft.com/en-us/windows/win32/direct3d11/direct3d-11-advanced-stages-cs-resources#byte-address-buffer

So potentially in your code you'd want to multiply idx by 4 if what you're doing is simple element addressing.

Alternatively if what you want to do is to manipulate an array of uints, then I would recommend you use structured buffers instead, i.e.:

RWStructuredBuffer<uint> byteBufferRW;
byteBufferRW[idx] = value;

StructuredBuffer<uint> byteBuffer;
loadVal = byteBuffer[idx];

The host code does not need changing.

sayan1an commented 3 years ago

I think I misunderstood what byte address buffer means. I was thinking of accessing a buffer in the shader as an array of uint8(s). As an hypothetical example -

StructuredBuffer<uchar> byteBuffer; 
uchar loadVal = byteBuffer[globalInvocationId.x];

After reading the resource, I am not sure whether this is what ByteAddressBuffer is intended for.

gboisse commented 3 years ago

Indeed, byte address buffers allow for byte-wise addressing (although the index needs to be DWORD-aligned anyway...) rather than reading/writing bytes.

As you can see in the link I sent you:

The contents of a byte address buffer is designed to be a 32-bit unsigned integer.

If you want to read/write bytes, you need to read the whole uint and perform bit masking in your code. I don't believe there is a way in HLSL to "directly" read and/or write bytes.

sayan1an commented 3 years ago

Understood, thanks for clearing that up.