Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sokol_gfx] Array of struct uniform #1002

Closed
mathewmariani opened this issue Feb 29, 2024 · 2 comments
Closed

[sokol_gfx] Array of struct uniform #1002

mathewmariani opened this issue Feb 29, 2024 · 2 comments

Comments

@mathewmariani
Copy link

I've been looking around for more information on passing an array of structs to my shader, but can't find a lot of information on the subject. I should mention that I'm working with OpenGLES for the time being, and I'm not using the sokol-shdc shader compiler tool.

Here is my structure in both C++ and GLSL.

struct pointlight_t
{
  float radius;
  glm::vec3 color;
  glm::vec3 position;
};
static pointlight_t light_data[MAX_LIGHTS];
struct PointLight {
  float radius;
  vec3 color;
  vec3 position;
};
uniform PointLight[MAX_LIGHTS] lights;

I'm not sure if this is completely correct but this is how I'm describing the uniform block in my sg_shader_desc. At this point, I will add that I have no compile or runtime errors.

// [...]
.uniform_blocks[1] = {
    .layout = SG_UNIFORMLAYOUT_NATIVE,
    .size = sizeof(pointlight_t) * MAX_LIGHTS,
    .uniforms = {
        [0] = {.name = "light.radius", .type = SG_UNIFORMTYPE_FLOAT, .array_count = MAX_LIGHTS},
        [1] = {.name = "light.color", .type = SG_UNIFORMTYPE_FLOAT3, .array_count = MAX_LIGHTS},
        [2] = {.name = "light.position", .type = SG_UNIFORMTYPE_FLOAT3, .array_count = MAX_LIGHTS},
    },
},

// [...]
sg_apply_uniforms(SG_SHADERSTAGE_FS, 1, SG_RANGE(light_data));

I'm not exactly sure what is the proper way to approach this using sokol_gfx. There are no build or runtime errors, yet I don't seem to be getting any data passed to the shader. I wasn't able to find a whole lot of information about this, hopefully, you can clarify my understanding.

@floooh
Copy link
Owner

floooh commented Feb 29, 2024

Hmm... without using the sokol-shdc compiler that's most likely not possible in the GL backend. You would need to convert the struct array into a plain vec4 array.

With the sokol-shdc compiler this conversion happens automatically for the GL backend (e.g. uniform blocks are flattened into a vec4 array), and then something like this could work. TBH I never tried that though.

uniform vs_params {
    PointLight lights[MAX_LIGHTS];
};

PS: maybe it doesn't work though... sokol-shdc has restrictions on what can be declared as an array because that uniform block must also be mapped to a matching C struct, and that's gnarly because of std140 alignment and padding rules, so I'm allowing arrays only for floats, vec2, vec4 and mat4.

I would probably recommend a 'structure of arrays' approach instead:

uniform vs_params {
    float light_radii[MAX_LIGHTS];
    vec4 light_colors[MAX_LIGHTS];
    vec4 light_positions[MAX_LIGHTS];
};

(vec4 instead of vec3 because of the above mentioned alignment restrictions - this is all assuming sokol-shdc though).

Without sokol-shdc this should also work for regular uniforms, but you'd need to experiment..

@floooh
Copy link
Owner

floooh commented May 13, 2024

The recent storage buffer support might make this a little bit less awkward since storage buffer array items have much fewer memory layout restrictions (the restrictions for uniforms need to remain in place however as long as OpenGL is supported).

@floooh floooh closed this as completed May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants