-
-
Notifications
You must be signed in to change notification settings - Fork 20.2k
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
Support passing raw data to multimesh in RenderingServer
#96541
base: master
Are you sure you want to change the base?
Conversation
Your PR is based off of the 4.3 branch for 4.3.x (4.3.1 etc), but your PR is targeting the master branch for 4.x (4.4 etc). |
e048c03
to
d099afb
Compare
Okay rebase finished. Seems to still be working. |
RenderingServer
I tested this PR, and it seems to crash whenever I set the buffer. The stack looks as it would expect for this crash |
d099afb
to
c4d10b8
Compare
Okay, fixed a typo where it was multiplying by sizeof(float) when it shouldn't. Oh and the actual crash was updating a buffer that didn't exist yet. |
I was hoping it wouldn't come to this: it clobbers the data in the end anyway. https://github.com/godotengine/godot/blob/master/drivers/gles3/shaders/scene.glsl#L412-L414 vec4 instance_custom;
instance_custom.xy = unpackHalf2x16(instance_color_custom_data.z);
instance_custom.zw = unpackHalf2x16(instance_color_custom_data.w); So you could modify that section for a custom build and that should do it. |
I probably will end up having to do some build modifications sadly then if I wanna do what I’m trying to do :/ although one last consideration, at this point though this becomes a very specific use case which goes against some of the engine principles unless there is other people who would also support this level of flexibility. |
Actually wait, that might not even be necessary. I could just write my own cast function that "casts" the float32 bits back into the float16 format, and then from there the bits should remain the same as they were input? |
Adding raw variants of uniforms is certainly architecture breaking, so no I won't be attempting that. I have personal interest in the multimesh system so making this PR was a good opportunity to investigate the inner workings while potentially contributing to the engine, no worries there. Yes, maybe it is reversible. Putting INSTANCE_CUSTOM back through packHalf2x16 could potentially reconstruct the data. Edit: Just tried, only partially reversible. If every rgba component is >=4, then it does replicate the original color. But if any component < 4 it goes crazy. This could have different results depending on GPU implementation so not reliable. |
I tried, it does the same thing, but it works for the most part besides the small rgb components, which seems great enough to me. For me it is only the G channel that makes it act all weird. Any clue on why it does this? Edit: Testing further, i noticed it does it for the three values from 129, 130, and 131 as well as 1, 2, and 3 |
Did a little test uniform uint testval;
...
uint v = min(testval, 0xFFFFu);
uint tst = packHalf2x16(unpackHalf2x16(v));
if (v != tst) { COLOR.rgb = vec3(1.0, 0.0, 1.0); } And scrolling through the uniforms I find that 0x83FF is the bitmask of invalid ranges. So we look at this in float toy: The exponent being 0 in float16 means either it's exactly zero, or if the mantissa is non-zero, subnormal (I guess like is_zero_approx() in godot speak). Which the driver apparently responds by normalizing it to 0xFFFF (NaN). Data is lost when the exponent is zero. So let's apply the mask to the whole uint32: 0x83FF83FF. And there is the answer. If (green & 0x7F) < 0x04 and red > 0x00: red and green will = 0xFF |
That's very interesting how that works, thanks for that test |
The data's already lost back when INSTANCE_CUSTOM is unpacked, so it has to be accounted for when creating the multimesh buffer. Two options come to mind
|
Thanks for all that! if ((value == 0) || (value == 1) || (value == 2) || (value == 3)):
bytes[index] = 4
elif ((value == 128) || (value == 129) || (value == 130) || (value == 131)):
bytes[index] = 132 Slightly limits colors but in such a way it doesn't matter at all! I'm very satisified with all this, thanks for all your help! Working with bits and packing stuff into bits is unironically so fun to me |
Any chance on this making it into any of the next 4.4 devs? sorry if this is an annoying question, i'm not exactly sure of how the process goes |
This needs the rendering team to take a look and review it, so when it gets approved depends entirely on their decision, including their opinion on if this is something that should be added, and then their views on the implementation |
Closes godotengine/godot-proposals#10650
and here's a test project with some torus mixing between COLOR and INSTANCE_CUSTOM. (It has a hacky check to determine if it's running OpenGL or Vulkan so keep that in mind.)
testproj.zip