Jump to content
  • Advertisement
Sign in to follow this  
360GAMZ

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

This topic is 2595 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 :)

Share this post


Link to post
Share on other sites
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"

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
Yeah, but that's pretty exactly how structured buffers work under the hood.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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)...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!