-
Notifications
You must be signed in to change notification settings - Fork 63
Fix material system uniform SSBO struct packing #1777
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
Conversation
Explicitly writing the padding seems pointless and the way the padding is calculated looks suspicious.
Use DAEMON_ASSERT_xyz instead of ASSERT_xyz in headers, so that the headers are compatible with Googletest. Also document this requirement in Assert.h and provide a non-shorthand version of ASSERT_UNREACHABLE.
If the uniform size is divisible by 16 it wrongly thought that 16 bytes of padding (instead of 0) were needed. Add a unit test demonstrating the case that was broken.
The point is that I can copy it from shader source to buffer view in Nsight and immediately see the values read by the shader. |
I don't get it, why would adding dummy fields at the end make this more effective? |
Because otherwise I'd need to add them manually. |
OK I found that in the documentation:
Does the latest commit work? I would try it but the last time I tried to update the software, it broke - it can no longer establish the socket connection. The original code seemed strange since it could only add padding at the end. I assume you need to add it anywhere else there are holes too? That's what I did. |
Thx, I'll try that in a bit. Yeah, the original code might be wrong on that. |
That does work, yes. The change in struct packing does, however, break when the material uniforms add up to less than 4 components/16 bytes. In that case the size is calculated as if they're tightly packed, when in the actual buffer interface they're rounded up to a Also, I believe the implementation in this pr doesn't calculate the size for arrays correctly as the component count is never taken into account. |
Fix some bugs and add more unit tests.
It's actually std140 not std430, so fix comment and GLShader member names to reflect that. (GLUniform still has the old _std430XXX names though.) Since it cannot handle arrays, add an assert that the uniforms are not arrays. Also delete WriteToBuffer implementations that assume std430 layout for arrays.
I didn't realize it actually uses std140, not std430. Fixed. I renamed some of the variable/function names in GLShader to reflect this.
The code was not prepared to handle arrays anyway since the |
I have it working fine in #1684 for The change to |
OK I added pack support for 4-aligned arrays.
It's not strictly related to lack of array support, but I deleted it in passing since it also looks wrong. It only writes 1 byte out of 4 and even if you can get away with that, it's definitely not endian-aware. |
Does this fix the edge case where if you add a uniform that is 4 byte aligned, it messes up the alignment of the struct and causes view corruption? I hit that in some of my testing.. I hacked it like this:
(which is probably wrong, but it fixed my corruption) |
Yes. The |
if ( uniforms[i]->_std430Size <= alignment ) { | ||
return i; | ||
static auto FindUniformForOffset( std::vector<GLUniform*>& uniforms, const GLuint baseOffset ) { | ||
for ( auto it = uniforms.begin(); it != uniforms.end(); ++it ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just do it : uniforms
if you're making it an iterator instead of an index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how - you just get a reference to the element that way, not an iterator.
src/engine/renderer/gl_shader.cpp
Outdated
} else { | ||
( *iterNext )->_std430Size = ( *iterNext )->_std430BaseSize; | ||
if ( ( *iterNext )->_components ) { | ||
ASSERT_GE( ( *iterNext )->_std430Alignment, 4 ); // aligment less than 4 not compatible with std130 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*std140
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarified the comment.
I see. #1685 should fix that once merged, and will get rid of the |
Fix the code for laying out the std430 struct containing the uniforms for material system GLSL shaders. There is no functional change given the exact sets of uniforms we have on our GLSL shaders right now, but adding a new one could cause things to blow up as demonstrated at #1696 (comment).
I'm not attempting to run the added unit tests on CI for now as the client test does full client initialization including opening a window. So it wouldn't easily run in a headless environment.