[DX11]: Is it possible to "cast" from byte address buffer to a structure in HLSL?

Started by
8 comments, last by AlexandreMutel 12 years, 5 months ago
In HLSL, is there a way to "cast" a byte address buffer location to a structure? For example, if I know that a defined structure of data begins at 100 bytes into my byte address buffer, it would be helpful if I could cast (or whatever the HLSL equivalent would be) that location to a struct defined in the HLSL code and then access the structure's data members per the usual syntax for structures. Any clever ideas on how to possibly do this? Hacks welcome :)
Advertisement

In HLSL, is there a way to "cast" a byte address buffer location to a structure? For example, if I know that a defined structure of data begins at 100 bytes into my byte address buffer, it would be helpful if I could cast (or whatever the HLSL equivalent would be) that location to a struct defined in the HLSL code and then access the structure's data members per the usual syntax for structures. Any clever ideas on how to possibly do this? Hacks welcome :)

If you mean mapping a structure to a HLSL constant buffer (declared as cbuffer) in Direct3D11, you don't need to cast them as they can be uploaded as structure. Meaning that a cbuffer in HLSL =~ a struct in C++ (at the condition that the struct members are correctly aligned to the HLSL cbuffer aligned rules).

You can have a look at any Direct3D11 samples from DirectX SDK, you will see that C++ struct are mapped to cbuffer directly.
If you are more familiar with c#, you can read this article "Marshalling C# structures into Direct3D 11 cbuffers using SharpDX"
I'm pretty sure there's no way to cast (since there's no concept of pointers), so you'll have to manually read in the memory you need, cast each value to floats or integers, and then fill in the members of your struct.
Hm, well it depends on where you need your data. If you want to access the byteaddressbuffer in a struct-like fashion in a compute shader, no idea comes to my mind. (so, as MJP said, you have to copy the data manually.)

If you access your data in a vertex shader you can build your byte address buffer with the vertex buffer binding flag and simply feed it in via the input assembler. Your input layout will specify the struct layout and your vertex shader will receive the data in the usual struct-manner. This, of course, only works if you don't plan to access the buffer multiple times at arbitrary positions.
Thank you for the replies. I need access to the data in the VS and PS. I suspect MJP is right in that I need to manually do the copying. Too bad you can't simply do something like this:

struct MyStruct {
uint a;
float b;
float2 c;
};

ByteAddressBuffer MyBAB;

...

(shader code)

MyStruct Test = MyStruct( MyBAB[100] );

uint a = Test.a;
float b = Test.b;
float2 c = Test.c;
Yeah, but that's pretty exactly how structured buffers work under the hood.
I'm using structured buffers where I can, but in this one case it's not possible.

Thank you for the replies. I need access to the data in the VS and PS. I suspect MJP is right in that I need to manually do the copying. Too bad you can't simply do something like this:

struct MyStruct {
uint a;
float b;
float2 c;
};

ByteAddressBuffer MyBAB;

...

(shader code)

MyStruct Test = MyStruct( MyBAB[100] );

uint a = Test.a;
float b = Test.b;
float2 c = Test.c;

Still, I don't really understand your usecase.
Do you want to access the ByteAddressBuffer directly in your shader like this:
[source]
MyBAB[5] = 4;
[/source]
And at the same time, using it through a struct? If yes, This is MJP suggestion.

But if you are going to only use the ByteAddressBuffer through a struct, you could do that with a constant buffer like this:
[source]
struct MyStruct {
uint a;
float b;
float2 c;
};

cbuffer MyBuffer {
MyStruct Test;
};
...
(shader code)
uint a = Test.a;
float b = Test.b;
float2 c = Test.c;
[/source]
And you would be able to update the cbuffer directly from a C++ pointer, or from the equivalent C++ struct.
xoofx, the amount of data in my buffer can exceed the maximum cbuffer size of 4096 elements, which is why I'm using a byte address buffer. The data in my buffer is not an array of structures and so I can't use a structured buffer. My only option, I believe, is to use a byte address buffer. But I know that at offset 100, for example, the data starting there represents a known struct. Instead of having to call Load() for each element and then store it in a structure, it would be useful if I could just cast the data at offset 100 to a structure and then access it as I would a structured buffer. This is all read-only, BTW - the shaders are not writing to the buffer.

xoofx, the amount of data in my buffer can exceed the maximum cbuffer size of 4096 elements, which is why I'm using a byte address buffer. The data in my buffer is not an array of structures and so I can't use a structured buffer. My only option, I believe, is to use a byte address buffer. But I know that at offset 100, for example, the data starting there represents a known struct. Instead of having to call Load() for each element and then store it in a structure, it would be useful if I could just cast the data at offset 100 to a structure and then access it as I would a structured buffer. This is all read-only, BTW - the shaders are not writing to the buffer.

Thanks for the clarification.
If your structure is less than 4096 float4s, you could use new upcoming Direct3D11.1 "Bind a subrange of a constant buffer to a shader". This feature is supported on downlevel hardware. But the offset will have to be a multiple of 16 bytes (a float4)...

This topic is closed to new replies.

Advertisement