text: [{"Owner":"fmmoret","Date":"2018-08-17T02:59:03Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tI_t_m getting a little pressed for performance in a game I_t_m working on. With ~6+ characters I_t_m starting to drop below 60fps on medium/low-end computers when my meshes are not very high poly_co_ my animations don_t_t have a very high sample rate and only one animation playing per character_co_ and with no particle effects.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tMy render loop perf breakdown is 4-6ms spent in _animate and 12-20ms in _renderForCameras in the top level render call.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tI_t_m investigating ways to optimize the loop_co_ but it_t_s really difficult to find big chunks that would use_dd_\n_lt_/p_gt_\n\n_lt_p_gt_\n\t1) wasm \n_lt_/p_gt_\n\n_lt_p_gt_\n\ta) where the chunk is easy to black box\n_lt_/p_gt_\n\n_lt_p_gt_\n\tb) where the chunk is big enough that it_t_s worth paying the high bridge-latency-cost of going in and out of a wasm module\n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\tor 2) web workers\n_lt_/p_gt_\n\n_lt_p_gt_\n\ta) where work can be done simultaneously with other stuff  / where order of costly calculations don_t_t matter\n_lt_/p_gt_\n\n_lt_p_gt_\n\tb) where we don_t_t need to serialize / deserialize too much info if we were to send it to a worker &amp_sm_ get a response back\n_lt_/p_gt_\n\n_lt_p_gt_\n\tc) where (like wasm)  the chunk is big enough that it_t_s worth paying the cost of messaging to and from the worker\n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\tWasm to me feels like it_t_ll be an all-or-nothing sort of thing because of how intertwined so many things are in babylon.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tWeb workers might be easier to work in because they can use existing javascript code.\n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\tDo other people have ideas / opinions / specialty knowledge? Do you guys spot some large areas that would be easy to isolate &amp_sm_ either execute asynchronously or just optimize with wasm? \n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"Sebavan","Date":"2018-08-17T10:02:48Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tAbout\n_lt_/p_gt_\n\n_lt_p_gt_\n\t1) yes this would require to rebuild most of the engine in wasm \n_lt_/p_gt_\n\n_lt_p_gt_\n\t2) Unfortunately as long as SharedArrayBuffer are disabled due to Spectre and Meltdown_co_ we won t be able to rely on it as well.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tThere are usually plenty of other tricks that could apply for perf improvment and the community can definitely help addressing some of your issues.\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"fmmoret","Date":"2018-08-17T14:54:02Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tI think SharedArrayBuffers _lt_em_gt_just_lt_/em_gt_ got reenabled for Chrome. I don_t_t know how far other browsers are\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"jerome","Date":"2018-08-17T16:09:58Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\t\\o/  for SAB !\n_lt_/p_gt_\n\n_lt_p_gt_\n\tThat said_co_ the usage of webworkers with SAB is not that simple about their synchronization. Please have a read at this last year experiment _dd_ \n_lt_/p_gt_\n_lt_iframe allowfullscreen_eq__qt__qt_ data-controller_eq__qt_core.front.core.autosizeiframe_qt_ data-embedcontent_eq__qt__qt_ data-embedid_eq__qt_embed1853828541_qt_ scrolling_eq__qt_no_qt_ src_eq__qt_http_dd_//www.html5gamedevs.com/topic/32817-sps-experiments/?tab_eq_comments&amp_sm_do_eq_embed&amp_sm_comment_eq_188167&amp_sm_embedComment_eq_188167&amp_sm_embedDo_eq_findComment#comment-188167_qt_ style_eq__qt_height_dd_292px_sm_max-width_dd_502px_sm__qt__gt__lt_/iframe_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\tAs sebavan said about wasm_co_ the best implementation would be that the major parts of the framework would be ported to wasm AND the user logic would also be coded in wasm to avoid the communication issues (data passing back and forth_co_ multiple wasm calls from js_co_ etc). Note that_co_ they intend_co_ some day_co_ to implement the multi-threading wasm side and the question of the performance gain will then be capital.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tMeanwhile_co_ maybe are there other ways to improve your very own case ? ... reducing the draw call number_co_ reducing the globally the computation required (don_t_t compute what_t_s not visible_co_ what_t_s not pertinent_co_ etc)_co_ reducing the number of loops_co_ iterations_co_ the amount of data ? well_co_ just leads as we don_t_t really know what you_t_re trying to achieve _lt_span_gt__lt_span class_eq__qt_ipsEmoji_qt__gt_😄_lt_/span_gt__lt_/span_gt_\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"fmmoret","Date":"2018-08-19T04:13:51Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tI do all collision / physics server side &amp_sm_ just send state over for babylon to transition to.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tHere_t_s a profile on my game if you_t_re curious_dd_\n_lt_/p_gt_\n\n_lt_p_gt_\n\tClick on the thumbnail to see a clearer version.\n_lt_/p_gt_\n\n_lt_p_gt_\n\t_lt_a class_eq__qt_ipsAttachLink ipsAttachLink_image_qt_ data-fileid_eq__qt_19667_qt_ href_eq__qt_http_dd_//www.html5gamedevs.com/uploads/monthly_2018_08/Untitled3.png.d5b4fb01da91925c30b3e7e7b9bd73c9.png_qt_ rel_eq__qt__qt__gt__lt_img alt_eq__qt_Untitled3.thumb.png.edd4cf25bb5c929d16547aa1809dabee.png_qt_ class_eq__qt_ipsImage ipsImage_thumbnailed_qt_ data-fileid_eq__qt_19667_qt_ src_eq__qt_http_dd_//www.html5gamedevs.com/uploads/monthly_2018_08/Untitled3.thumb.png.edd4cf25bb5c929d16547aa1809dabee.png_qt_ /_gt__lt_/a_gt_\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"Sebavan","Date":"2018-08-19T09:33:51Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tlooks like you have a lot of animations running_co_ maybe some of them could be skeleton animations to defer a bit of load on the GPU ???\n_lt_/p_gt_\n\n_lt_p_gt_\n\tThis really depends on your scene so not sure it could apply in your case.\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"JCPalmer","Date":"2018-08-19T16:21:11Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tLooking at your screen shot_co_ _evaluateActiveMeshes_co_ 26.9% total_co_ is where computeWorldMatrix gets called_co_ 16.7% total_co_ is called.  While this is required if the scaling_co_ location_co_ or rotation changed since the last frame_co_ if you know of meshes that are never going to move_co_ this can be eliminated for them.  No amount of this automated optimization can ever know that.  FreezingWorldMatrix of background meshes is the kind of overhead that can be taken out without sacrificing or redesigning the scene.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tOne other area without sacrifice / redesign is merging meshes of the same material_co_ which also do not move_co_ scale or rotate.  After that_co_ much of the low hanging fruit has been picked.\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"fmmoret","Date":"2018-08-29T00:46:59Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\t_lt_a contenteditable_eq__qt_false_qt_ data-ipshover_eq__qt__qt_ data-ipshover-target_eq__qt_http_dd_//www.html5gamedevs.com/profile/20193-sebavan/?do_eq_hovercard_qt_ data-mentionid_eq__qt_20193_qt_ href_eq__qt_http_dd_//www.html5gamedevs.com/profile/20193-sebavan/_qt_ rel_eq__qt__qt__gt_@Sebavan_lt_/a_gt_ they are skeleton animations in blender.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tDo the shader ones work with weights &amp_sm_ blending?\n_lt_/p_gt_\n\n_lt_p_gt_\n\tI_t_m exporting via the gltf exporter and don_t_t know if that exports a shader for the animations.\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"Deltakosh","Date":"2018-08-29T16:05:33Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tWell so the GPU is already used for bones. I think _lt_a contenteditable_eq__qt_false_qt_ data-ipshover_eq__qt__qt_ data-ipshover-target_eq__qt_http_dd_//www.html5gamedevs.com/profile/8492-jcpalmer/?do_eq_hovercard_qt_ data-mentionid_eq__qt_8492_qt_ href_eq__qt_http_dd_//www.html5gamedevs.com/profile/8492-jcpalmer/_qt_ id_eq__qt_ips_uid_3217_5_qt_ rel_eq__qt__qt__gt_@JCPalmer_lt_/a_gt_ is on something\n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\tDid you read that doc btw? _lt_a href_eq__qt_http_dd_//doc.babylonjs.com/how_to/optimizing_your_scene_qt_ ipsnoembed_eq__qt_true_qt_ rel_eq__qt_external nofollow_qt__gt_http_dd_//doc.babylonjs.com/how_to/optimizing_your_scene_lt_/a_gt_\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"dbawel","Date":"2018-08-30T08:07:09Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\t_lt_a contenteditable_eq__qt_false_qt_ data-ipshover_eq__qt__qt_ data-ipshover-target_eq__qt_http_dd_//www.html5gamedevs.com/profile/8492-jcpalmer/?do_eq_hovercard_qt_ data-mentionid_eq__qt_8492_qt_ href_eq__qt_http_dd_//www.html5gamedevs.com/profile/8492-jcpalmer/_qt_ rel_eq__qt__qt__gt_@JCPalmer_lt_/a_gt_ if you are working on an extension_co_ please let us all know. Otherwise_co_ perhaps this is an extension we need to take on specifically for the BJS framework. I_t_m actually not sure why I_t_m writing this post_co_ as all the info is available in the browser dev tools. But everyone want_t_s the EASY way. I wish I had it so easy in the early days of making console games.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tDB\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"JCPalmer","Date":"2018-08-30T16:05:22Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tI am not working in this area.  MergingMeshes of the same material already works with both meshes &amp_sm_ clones.  One area which might make it easier is optimizing materials.  It is just a loop thru scene.meshes_co_ but why should everyone need to do it.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tMaybe_co_ a method on _lt_strong_gt_Material.mergeMeshes(exclude? _dd_ array&lt_sm_Mesh&gt_sm_) _dd_ void_lt_/strong_gt_.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tIf you had a bunch of tree meshes or clones_co_ call it like_dd_ _lt_strong_gt_scene.getMaterialByName(_qt_tree_material_qt_).mergeMeshes()_sm__lt_/strong_gt_\n_lt_/p_gt_\n\n_lt_p_gt_\n\tIf no one uses it_co_ then it would be more bloat.\n_lt_/p_gt_\n\n_lt_p_gt_\n\tStrawman_co_ not validated_dd_\n_lt_/p_gt_\n\n_lt_pre_gt_\n_lt_code_gt_public mergeMeshes(exclude _dd_ array&lt_sm_Mesh&gt_sm_ _eq_ []) _dd_ void {\n    const selected _eq_ new Array&lt_sm_Mesh&gt_sm_()_sm_\n    for (m in this._scene.meshes) {\n        if (m.material _eq__eq__eq_ this) {\n            let ignore _eq_ false_sm_\n            for (e in exclude) {\n                if (m _eq__eq__eq_ e) {\n                    ignore _eq_ true_sm_\n                    break_sm_\n                }\n            }\n            if (!ignore) selected.push(m)_sm_\n        }\n    }\n    Mesh.MergeMeshes(selected)_sm_\n}_lt_/code_gt__lt_/pre_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n_lt_p_gt_\n\t \n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"},{"Owner":"Deltakosh","Date":"2018-08-30T16:24:52Z","Content":"_lt_div class_eq__qt_mages_qt__gt_\n\t\t\t\n_lt_p_gt_\n\tThis can be done automatically by the SceneOptimizer_dd_ _lt_a href_eq__qt_http_dd_//doc.babylonjs.com/how_to/how_to_use_sceneoptimizer_qt_ ipsnoembed_eq__qt_true_qt_ rel_eq__qt_external nofollow_qt__gt_http_dd_//doc.babylonjs.com/how_to/how_to_use_sceneoptimizer_lt_/a_gt_\n_lt_/p_gt_\n\n\n\t\t\t\n\t\t_lt_/div_gt_\n\n\t\t_lt_div class_eq__qt_ipsI_qt__gt__lt_/div_gt__lt_/div_gt_"}]