TL;DR
In a Vulkan / GLSL ray tracing program, I have several shader files, all accessing the same material buffer of arbitrary data. All materials have an arbitrary layout, e.g. one might be a float, one might contain two vec3s and a float. Can I access a buffer (i.e. an array of uint type) with just an offset within the shader (i.e. the same buffer binding is shared, I cannot use dynamic offsets set on the CPU side) and read out a struct without having to read every member of the struct individually? I am aware of not being able to read a vec3 from a buffer as just 3 values, but that is not my problem. Just assume I only read good data types that don't waste space.
See in the image, I want to access at the given green position with just knowing the size of the struct that will follow at that position.
In C++ it would be something like this:
uint32_t* buffer; //assume this has all the data in it
struct mat2
{
glm::vec3 data1;
float data2;
}
//the following line is what I try to achieve
mat2 matData = *((mat2)(buffer+offset);
Long explanation
I am trying to setup a buffer that contains material parameters. The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.
Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry. I have a shader file per material, so no material is aware of other material structs - it just knows the offset into the array for its own data.
While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:
struct BlinnPhongParams
{
vec3 diffuse;
vec3 specular;
float specIntensity;
};
And the material buffer:
layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer
{
uint[] data;
}uMaterialParamsBuffer;
Currently I am reading every member from the buffer individually:
BlinnPhongParams getMaterialParams(uint offset)
{
BlinnPhongParams bpParams = BlinnPhongParams(
//DiffuseCol
vec3(
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),
//SpecularCol
vec3(
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),
//SpecIntensity
uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])
);
return bpParams;
}
I would like to make reading from this buffer as easy as possible, ideally just say "at this offset, I have a struct that looks like this", e.g. I would like to have something like this:
BlinnPhongParams getMaterialParams(uint offset)
{
// here is the problem
BlinnPhongParams params = BlinnPhongParams(&uMaterialParamsBuffer.data[offset]);
}
Is this possible?