-
Notifications
You must be signed in to change notification settings - Fork 316
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
[Android (C) and HTML5 (JS)] GPU skinning "too many uniforms" crash on android Adreno while fine on Mali GPU #2020
Comments
A uniform is like a shader variable that's uniform to all "executions" of that shader in a particular draw call (draw call = tell the GPU it should draw something). It is a bit like a global variable that can be used to pass parameters to a shader. So it is probably caused by a too complex material or world shader. Maybe the only way to find the exact cause is to check all generated .glsl files in To verify your findings you can hide all meshes with that particular material. |
thanks @MoritzBrueckner so I removed one by one any complex elements, materials, etc, from my 3D model and looked at all the GLSL materials and else and tested every time and it turns out it to be the following : An Armory3D project will just stop with a "too many uniforms" error only in specific cases: When you export a 3D model with a complex Armature and lot of Bones it will simply crash with this error on Adreno GPUs but it will work on an old and 70 times slower Mali GPU. I checked other engines, Unreal, Unity and they do have 3D models with complex Armature animation running correctly on Adreno GPU. (Ex: Genshin Impact which is running using Unity). This seems to be a problem with Armory and Adreno GPU while handling Armatures and Bones. For now the best workaround I found is using over simplified Armatures with low bones counts. (so no moving hairs or cloths, etc...) |
Hi @onelsonic, Thanks for the info. Would you be able to do the following checks and see if there are any differences please:
Also, does your "Character" object have more than one sub-meshes ? Best Regards, |
Then this 2013/2014 thread seems similar to what I am experiencing with modern high end Adreno GPU: Issue probably come from this : I guess the same limitations applies to ES 3.0, my Adreno is running on 3.0 #Edit: also my model has only one simple mesh with not much faces but lot of vertex groups for animations but it doesn't seem to be a problem on Mali GPU. |
Hi there, after further investigation and tests. So the way the animation is exported and then loaded on Adreno GPU is probably using too large uniforms that are not supported on these mobile GPUs. Anyone know how animation are stored in Armory, do they use "uniforms"? |
Haven't delved too deep into armory's bone animations, but from what I could gather: If too many uniforms may be tripped probably is because of that uniform. |
thanks @N8n5h, I checked all codes you mentioned and run a few tests and succeed to localise the issue. armory/Shaders/std/skinning.glsl Line 3 in 48952e0
On Adreno GPUs (skinMaxBones * 2) is too high for the hardware. (Or badly supported, not sure...) Hard coding the 'skinMaxBones * 2' value to 245 partially fix the problem as we just limit it to how many uniforms Adreno GPU are supporting. not sure why 245 works, when I think it should technically be 256. Also changing this line here has no effect whatsoever on the GLSL shader: Looking at how Adreno's work :
I read that Adreno GPU's OpenGL was bogus somehow and not sure if it is still the case now... some proposals to fix this for Adreno: compilation crash logs:
|
Not sure, but I guess it's because there are still other uniforms somewhere that add to this count.
Added a fix, this was not related to your changes: #2021 |
Digging into this problem, |
The size of this.skinBuffer = new Float32Array(skinMaxBones * boneSize); so it's weird that reducing the value of Armory seems to be using textures in some places to store data (other than images), maybe the same could be applied to store that skin data instead as an alternative? |
setting skinMaxBones to 1 or 122 in BoneAnimation.hx has no effect, the animation will play correctly on Mali GPU but crash on Adreno. Yes strange, there is probably something overwriting its value when running. You can test the animation and run it with Google Chrome on Android (Adreno and Mali GPU) Solution: armory/Shaders/std/skinning.glsl Line 3 in 48952e0
using either Texture buffer object or Uniform Buffer not sure which one is bigger on Adreno. full adreno OpenGL specs link |
This is what is overwriting the skinMaxBones value.
If set manually to 122 (thanks to @MoritzBrueckner fix #2021 ) --> 122*2 = 244 we get the same as hard coding the value to 244.
Stripping the extra bones. If set to Auto it will default to an automatic calculated value.
Then back to the Adreno skinning problem, I think Texture buffer objects might be the way to fix this. some useful references for this issue: Dual Quaternion Skinning using textures: Edits: |
@onelsonic Thanks for the insights. I am currently working on improving the animation system for Armory3D. Would it help fix this issue if we use So, will going from Vec4 to Mat4 reduce the number of uniforms and maybe fix this issue? |
According to this, the allowed number of uniforms does depend on the size of the used uniforms in OpenGL. So if I understand it correctly, using a 4x4 matrix would take away 4 "components" more than 3 vec4s, but I might be mistaken here and it actually might vary between different platforms and GPUs. The linked page states for example that on some (especially older) GPUs vectors always take 4 components independent of their size. Maybe try to set I think the same holds true for DirectX/HLSL, at least I had some issue with that in the past where data was always aligned in blocks of 4 components which Kha couldn't handle very well. |
What @MoritzBrueckner says then the above issue is Hardware specific on Adreno/qualcomm GPU but also tight to the way bones animations are handle in Armory which uses a too restrictive format : "vertex uniform" not really fit for the Adreno platform. I found this issue occuring on Adreno 200/300/400 and 500 series so far and I have not tested the 600 series yet...
and report on these values:
To overcome this, a solution is to step away from "uniform" all together as being too restrictive on Adreno. Not 100% sure but it seems like Unity has the same issue and fixed it in 2018 : Most reliable workaround is to use unsigned integer variables for array indexing for the bones animations. Also there is another issue which may be fixed by this, |
It's indeed fine on a Mali GPU and Android 10, I can see the animation of a waving Link on a Mali-G72.
I also tested it on a cheap crappy tablet with Android 9 and a PowerVR Rogue GE8100 GPU from Imagination Technologies (never heard of it), and the animation also plays but the arms are very buggy and twisted. Specs:
If you say that using unsigned integers for the array indexing could work, can you try if changing armory/Shaders/std/skinning.glsl Line 7 in 55cfead
ivec4 to uvec4 works already?
|
From what I see this does not address the issue of exceeding the maximum supported uniforms, rather, how to access each uniform properly from an array. I also looked up on texture based animations. Although it is faster and might solve the issues with the limited uniforms, it opens up a host of other issues.
So, if the engine only plays complex animations with many bones and does not require much of real-time modifications to these animations, having a texture based animation makes sense. |
Mobile "uniform" are usually limited from 256 to 1024 Max Vertex Uniform Vectors per shader so far. armory/Shaders/std/skinning.glsl Line 3 in 48952e0
On a 1024 Vertex Uniform Vectors Mali mobile GPU the Skinbones limit is Max =122 Skinbones Available on Mali.... which gives 122 * 2 = 244 elements to handle in the array (Theoretical max is 256 elements in the array but some uniforms used elsewhere are already taken). thus : vec4 * 244 = 976 uniforms max available for Skinbones on a 1024 system which is just enough for complex animation. with 1024 theorical and only 976 available uniforms thus 48 uniforms already taken. On a 256 Vertex Uniform Vectors Adreno mobile GPU Then that's true textures are not realy realtime in our case so the only solution I see is A side not for HTML5 instancing (not sure if this will impact instancing) |
yes, I think using uniform buffers here might be a better option. Not sure how one should link this though. The current linking is defined here armory/blender/arm/material/make_skin.py Line 14 in 55cfead
Should this remain the same even if we use uniform buffers? |
this should help : https://www.geeks3d.com/20140704/gpu-buffers-introduction-to-opengl-3-1-uniform-buffers-objects/ |
Does anyone came across to this error with armory and know what is actually causing this issue?
I suspect my 3d model is too complex and I am searching after some directions in order to run it correctly in Armory and making it more simple.
What is a "uniform" and how does it translate in Blender?
Any input will be much appreciated.
Thanks
The text was updated successfully, but these errors were encountered: