fenomas Posted March 27, 2015 Share Posted March 27, 2015 Hi, Does BJS do any kind of batching when it draws? For example, if a scene has 1000 meshes that all use material/texture A, and another 1000 meshes that use material/texture B, does it attempt to batch together meshes with a common material? Or just render them in arbitrary order, rebinding textures for every mesh? Also: does scene composition affect this? (e.g. would it depend on whether the meshes had a common parent, or whether they are in the same part of the octree, etc.) Quote Link to comment Share on other sites More sharing options...
jahow Posted March 27, 2015 Share Posted March 27, 2015 AFAIK, no batching is done automatically. Each time the engine renders a mesh, the corresponding material is bound. So if you have 10 different meshes with the same material, you'll have 10 draw calls. Example:http://www.babylonjs-playground.com/#23QH6N The SpriteManager class does batch all its sprites into one buffer though. Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 27, 2015 Author Share Posted March 27, 2015 Yeah, I know there are always separate draw calls for each mesh, but I was wondering if BJS tries to (for example) avoid re-binding textures unnecessarily. Quote Link to comment Share on other sites More sharing options...
jahow Posted March 27, 2015 Share Posted March 27, 2015 Well the StandardMaterial does that here:https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/Materials/babylon.standardMaterial.ts#L440 And the ShaderMaterial here:https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/Materials/babylon.shaderMaterial.ts#L174 As for the order of rendering regarding composition of scene etc., I have no idea. Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 27, 2015 Author Share Posted March 27, 2015 Okay, from doing a simple test it looks like meshes get rendered in the order they were added, regardless of material, parent, etc. So if I understand correctly: * Binding the material is skipped if consecutive meshes happen to share a material * Nothing happens if consecutive meshes use the same texture, it gets re-bound if the material changes * This info isn't useful for optimization unless perhaps you manually reorder 'scene.meshes' If that doesn't sound right please let me know Basically I was looking into whether it would be beneficial to pack small textures into an atlas, but it looks like it's not - that would just mean re-binding a large texture every call, rather than a small one. Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted March 27, 2015 Share Posted March 27, 2015 Wonder if you can effect the order meshes are drawn from outside the frame work by parenting meshes? If so, an application could parent meshes of similar material. Not every app could do this. At the frame work level, perhaps there might be an optimization you could call to "sort" meshes by material. This could be called occasionally by an application thinking they might benefit, but not put any more cpu pressure on, since not attempting to do this in order in the render process. Maybe put in a enhancement request, http://babylonjs.uservoice.com/forums/267546-general, or do it yourself & PR. Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 27, 2015 Author Share Posted March 27, 2015 Wonder if you can effect the order meshes are drawn from outside the frame work by parenting meshes? Nope, like I said they appear to be drawn in the order they appear in scenes.meshes. I didn't test things like submeshes, but parenting doesn't affect this. Either way, unless I'm missing something draw order doesn't affect the case I was hoping to improve (texture atlases). Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 27, 2015 Share Posted March 27, 2015 If 100 meshes has the same material you could think about merging them Batching is done through the cache has the material will be bind just once thanks to the cache But because you have 100 meshes. You need 100 drawcalls Options:- Merging- Instances? Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 28, 2015 Author Share Posted March 28, 2015 If 100 meshes has the same material you could think about merging them I'm asking about the case where the meshes can't be joined, of course. The idea was, if I have 100 meshes with 100 small textures, could I gain performance by stitching the textures into an atlas (thus having 100 meshes that all use the same texture). And it appears the answer is no - this can only hurt performance. If I'm missing anything please let me know... Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 28, 2015 Share Posted March 28, 2015 The only gain will be that texture will remain in the cache Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 28, 2015 Author Share Posted March 28, 2015 BJS rebinds the texture every time the material changes, doesn't it? Or do you mean cache on the GPU, or somesuch? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 28, 2015 Share Posted March 28, 2015 if the texture is the same there is NO rebinding:https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/babylon.engine.ts#L1961 There is cache EVERYWHERE in babylon.js Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted March 28, 2015 Share Posted March 28, 2015 So there might be some utility in sorting meshes, on request, by material. Probably not a lot, unless you have very many though. Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 28, 2015 Author Share Posted March 28, 2015 if the texture is the same there is NO rebinding:https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/babylon.engine.ts#L1961 There is cache EVERYWHERE in babylon.js Ahhhh, so basically everything is cached, but nothing is batched. Got it! Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 30, 2015 Share Posted March 30, 2015 Nothing is batched because there is no good optimization as materials are note the same in your case Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 31, 2015 Author Share Posted March 31, 2015 Nothing is batched because there is no good optimization as materials are note the same in your case Wait, so does that mean that avoiding texture bind calls isn't worthwhile? That is, suppose I have a scene with 1000 meshes and two texture atlases. So every mesh has a different material, but they all use one of the two textures. My assumption was that (due to the caching you described) it would be worthwhile for me to sort "scene.meshes" so as to batch the atlases together. I know it's still 1000 draw calls either way, but batching would allow texture bind calls to be skipped (1000 binds in the worst case, 2 in the best case). Is that not correct? Or are texture bind calls so inexpensive (compared to draws) that it doesn't matter? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 31, 2015 Share Posted March 31, 2015 Sorry I wasn't clear I meant batching materials is not a good optimization if all meshes have differents materials. If they are sharing materials and textures, the cache will do the batching for you by not setting up things that are already set up You are right about the sort.And this is easy to do by just changing objects order in the scene.meshes array Quote Link to comment Share on other sites More sharing options...
fenomas Posted April 1, 2015 Author Share Posted April 1, 2015 ..batching materials is not a good optimization if all meshes have differents materials. If they are sharing materials and textures, the cache will do the batching for you.. Err, could be read both ways. I'm asking about the case for meshes which do not share materials but do share a single texture. Batching should also be beneficial in this case, right? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 1, 2015 Share Posted April 1, 2015 yes sir! fenomas 1 Quote Link to comment Share on other sites More sharing options...
jahow Posted April 7, 2015 Share Posted April 7, 2015 Hey, I'm working on a class that will handle automatic batching of separate meshes into one big mesh with a multimaterial. If batched meshes are removed/added, the buffers of the big mesh will be recomputed (meshes will be sorted by material). Something like this:// BATCHED MESH USAGEthis.batched_mesh = new BatchedMesh( 'ground_static_mesh' );var mesh = meshes_from_file[index];mesh.position.copyFrom(this.position);mesh.position.y += 1.0;this.batched_mesh.injectMesh(mesh);this.batched_mesh.injectMesh(meshes_from_file[index2]);The main use will be to merge meshes that will not move every frame, but will still be changed from time to time. It's mainly a helper to avoid merging meshes manually when needed. Do you guys think this may be useful on this topic? Quote Link to comment Share on other sites More sharing options...
jerome Posted April 7, 2015 Share Posted April 7, 2015 yes ! Quote Link to comment Share on other sites More sharing options...
fenomas Posted April 7, 2015 Author Share Posted April 7, 2015 The main use will be to merge meshes that will not move every frame, but will still be changed from time to time. It's mainly a helper to avoid merging meshes manually when needed. What is the benefit of merging separate meshes into a large mesh with a multimaterial? Quote Link to comment Share on other sites More sharing options...
jahow Posted April 7, 2015 Share Posted April 7, 2015 In the case where all meshes have different materials I'm not sure there's a real benefit, at least according to this thread. I'm doing it mainly because most of my meshes have the same material. At first I was using instances, but it was still running very slow due to the fact that I had a very large mesh list. I also had thousands of draw calls. But since it's not very complicated, I made it so the BatchedMesh class produces one mesh with a multimaterial and submeshes, instead of several meshes with a unique material. I'm thinking it might be interesting to do a simple benchmarking test (case 1: one mesh & multimaterial, case 2: several meshes & single material) , and see what's the best solution... Quote Link to comment Share on other sites More sharing options...
fenomas Posted April 7, 2015 Author Share Posted April 7, 2015 Okay, yeah. I've been doing a lot of testing with that over the past week or two. I'm working on a minecraft-style scene full of terrain split up into chunks. For N discrete chunks, each of which has M different parts that require different materials, I've tried three setups: 1. Naive way: N*M separate chunks and M materials2. Submeshes way: N meshes, each with M submeshes, the whole scene shares 1 multimaterial (with M submaterials)3. Octree way: Like the naive way, but adding in a selection Octree with N octree blocks Unfortunately I wasted about a week working on this because there was a bug in synchronization that greatly affected performance. Now that that's fixed, my profiling results are that 2&3 perform equally, and 1 is significantly slower, mainly due to Scene._evaluateActiveMeshes(). Stuff I've learned:1. Unless you merge meshes that use the same material, the number of draw calls stays the same no matter what - it doesn't matter whether you use submeshes or multimaterials.2. AFAIK the only benefit to using submeshes and multimaterials is that the merged mesh's bounding information is used when determining which objects are visible, very similarly to octrees. This is apparently why my methods 2 & 3 perform the same.3. Basically don't trust the debug layer statistics; they're pretty misleading unless you dig into the source and check how each one is calculated. For example, "Total meshes" and "Total vertices" are not in general related. Total/Active vertices are counting different things as well. It's really confusing. With all that said, my suspicion based on this thread is that overall performance could be sped up by using N*M meshes and manipulating the mesh list to group similar materials together. The number of draw calls won't change but material/texture bind could be skipped, as DK described. My other suspicion is that using submeshes will kill this benefit - because submeshes that use the same material will in general never be rendered consecutively. I haven't tested these suspicions yet, and probably won't until I do more with texture atlases. Quote Link to comment Share on other sites More sharing options...
jahow Posted April 7, 2015 Share Posted April 7, 2015 Wow, thanks for the insight That's impressive work. This probably explains why everytime my scene was killing the FPS, the 'meshes selection' stat in the debug layer was always the highest... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.