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

Can't Set Float Uniform Variable #991

Closed
Voxi0 opened this issue Feb 12, 2024 · 3 comments
Closed

Can't Set Float Uniform Variable #991

Voxi0 opened this issue Feb 12, 2024 · 3 comments

Comments

@Voxi0
Copy link

Voxi0 commented Feb 12, 2024

This is a .glsl shader file that I'm compiling using sokol-shdc I grabbed from the sokol-tools-bin repo. You can see in the fragment shader that I have a uniform block with a float variable called time which I set to '(float)glfwGetTime()'. I am using this variable to just play with the colors. This shader works perfectly fine when embedding this code in the shader desc, but compiling it with sokol-shdc into a header file just does not work. Setting the uniform variable says that the block size does not match and after going through the generated header file, the float variable in the fragment shader is getting converted into a vec4 for whatever reason. And sure enough, it works perfectly when I set a vec4, no block size errors.

This is the first time I've ever reported an issue on GitHub so excuse me if it's not formatted nicely. I'm really loving sokol by the way, it's great. Also I think it would be kinda cool if there was a discord server or something no?

#version 330 core

@ctype mat4 glm::mat4
@ctype vec3 glm::vec3
@ctype vec4 glm::vec4

@vs vs
// Vertex Attributes
layout(location = 0) in vec3 vertexPos;

// Uniform Variables
uniform vsParams {
    mat4 pvm;
};

// Main
void main() {
    gl_Position = pvm * vec4(vertexPos, 1.0f);
}
@end

@fs fs
// Uniform Variables
uniform fsParams {
    float time;
};

// Output
out vec4 fragColor;

// Main
void main() {
    // Set Final Fragment Color
    vec3 color = vec3(abs(sin(time)), 0.0f, 0.0f);
    fragColor = vec4(color, 1.0f);
}
@end

@program testShaders vs fs
@floooh
Copy link
Owner

floooh commented Feb 12, 2024

Do you use the code-generated struct or your own (in the sg_apply_uniforms call)? E.g. in the sokol-shdc output there's the following struct generated:

#pragma pack(push,1)
SOKOL_SHDC_ALIGN(16) typedef struct fsParams_t {
    float time;
    uint8_t _pad_4[12];
} fsParams_t;
#pragma pack(pop

Note how this is padded to a multiple of 16 bytes. This is a side effect of 'flattening' uniform blocks into a vec4 array via SPIRVCross, which allows to update uniforms with a single glUniform4fv() call per uniform-block in the GL backend (instead of one individual glUniform call per uniform block member which is otherwise used).

PS: the #version 330 core at the top of your shader isn't necessary (and might even confuse sokol-shdc in some cases).

PPS: in general, and if possible, you should use the code-generated structs for passing uniforms into sokol-gfx, since the alignment and padding rules for uniform blocks are non-trivial, and very different from vanilla C structs.

PPPS: code example

const fsParams_t fs_params = { .time = (float)glfwGetTime() };
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_fsParams, &SG_RANGE(fs_params));

@Voxi0
Copy link
Author

Voxi0 commented Feb 12, 2024

I know the #version 330 core isn't necessary but I was pretty desperate to get it working. I am using the generated struct yes, I'd rather not make my own or mess with the generated one. And, oh, the code example you provided actually works. I guess that's it, thanks.

By the way, using the '&' before 'SG_RANGE' gives me an error. I've seen it being used every example though. The error is 'Taking address of rvalue [-fpermissive]', the program runs fine regardless of this error. I have all warnings and errors enabled so that must be the case.

@Voxi0 Voxi0 closed this as completed Feb 12, 2024
@floooh
Copy link
Owner

floooh commented Feb 13, 2024

By the way, using the '&' before 'SG_RANGE' gives me an error.

Ah right, that's a C vs C++ thing. In C++ you can do this instead (just drop the '&'):

sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_fsParams, SG_RANGE(fs_params));

...or use the SG_RANGE_REF() macro which does the right thing both in C and C++:

sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_fsParams, SG_RANGE_REF(fs_params));

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