StrangeLoopGames / EcoIssues

131 stars 21 forks source link

New Draw calls from each tree #19684

Open SpiritOfAncientWherewolf opened 3 years ago

SpiritOfAncientWherewolf commented 3 years ago

@keegan-o Tooday i was try to optimize grass and found this. BUG-In-the-forest All eco trees used not optimized render type. Need to use Graphics.DrawMesh But is not supported by type of render. As a result , walking through the forest we create a huge number of DrawCalls and batching. Not using the GPU Instancing function BUG-In-the-forest2

Each tree is extra work for the processor, you can optimize it. Drawing meshes using the GPU will greatly reduce the load. These trees can be duplicated by a video card, up to 1000. https://docs.unity3d.com/Manual/GPUInstancing.html

Realy useful video example, how it can be. https://youtu.be/e5WXx4PQXpU

Full list of objects to rework. SkinRenderListObjects.txt

mirasrael commented 3 years ago

@keegan-o can you review all tree objects if they really need to use SkinnedMeshRenderer? Also @SpiritOfAncientWherewolf analyzed and prepared list of world objects which are using SkinnedMeshRenderer:

AnvilObject ArrastraObject AssemblyLineObject BakeryOvenObject BloomeryObject ButcheryTableObject CarpentryTableObject CompositeBirchDoorObject CompositeCedarDoorObject CompositeCeibaDoorObject CompositeFirDoorObject CompositeOakDoorObject CompositePalmDoorObject CompositeRedwoodDoorObject CompositeSaguaroDoorObject CompositeSpruceDoorObject ComputerLabObject CraneObject CurrencyExchangeObject DoorObject ElectricLatheObject ElectricMachinistTableObject ElectricPlanerObject ElectricStampingPressObject ElectricWaterPumpObject ElectronicsAssemblyObject FrothFloatationCellObject HandPlowObject HardwoodLumberDoorObject InjectionMoldMachineObject JawCrusherObject KilnObject LaboratoryObject LargeWindowedLumberDoorObject LatheObject MachineShopObject MachinistTableObject MechanicalWaterPumpObject MillObject MintObject OilRefineryObject RealEstateDeskObject RegistrarObject ResearchTableObject RoboticAssemblyLineObject RollingMillObject ScreeningMachineObject ScrewPressObject SensorBasedBeltSorterObject ShaperObject SkidSteerObject SmallSinkObject StampMillObject SteamEngineObject SteamTractorObject SteamTruckObject StorageChestObject ToiletObject TruckObject WainwrightTableObject WindTurbineObject WoodenElevatorObject CompositeLumberDoorObject CompositeHardwoodDoorObject LumberDoorObject CompositeJoshuaDoorObject

We should also ensure they really need this Skinned Mesh Renderer and if not then replace it with just Mesh Renderer and enable GPU instancing. It may save lot of draw calls for often occurring objects like chests, doors, chairs etc.

SpiritOfAncientWherewolf commented 3 years ago

New compromise information. Now, dont need change models. Need only change base shaders. This is example how do Skinned Mesh Render to Instancing. 1000 animated skinned meshes and 172 batches.

There is a video instruction. https://youtu.be/_GGVlzAcWgA

There is asset. https://github.com/Unity-Technologies/Animation-Instancing

keegan-o commented 3 years ago

AnvilObject CarpentryTableObject CurrencyExchangeObject All of the Composite Lumber Doors

I went through and edited all those objects to use Mesh Renderer instead of Skinned Mesh Renderer, since they weren't using skinning. Also touched up spacing and sizing and colliders for some, and hooked up LODs for ones that didn't have them, so it'd be good for QA to check my work. All the others in that long list use skinning and thus need to be skinned mesh renderers (and are composed of multiple parts usually, so splitting them would result in more draw calls most likely).

keegan-o commented 3 years ago

Ah, and to your initial question @mirasrael , the trees use the skinning for moving their bones and animating the morph targets I believe.

SpiritOfAncientWherewolf commented 3 years ago

@keegan-o @D3nnis3n @johnkslg Срубленные деревья тоже его используют. Касательно анимации с отделением одной части от общей модели, да появляется новый Draw call. Но инстансинг дает массовость. Пример. Сундук с примерно 13 дроу коллами, ему всего то надо перенести крышку в другой объект получаем 15 дроу коллов. Но а если в городе их обычно в каждом доме штабелями по 20 штук это только на сундуках мы получаем только от сундуков 260 батчей. В случае с меш рендером рендерится всего один. То есть 13 и 260+, сами понимаете что лучше. Так вот проблема именно в больших количествах этих предметов. 10 домов это огромные потери производительности. В городах и больше строят. Все мои модифицированные объекты имеют структуру обычного меш рендера. И они анимированы через простые оси чeрез нулевые объекты. Да это добавляет два лишних дроу колла, но я могу их строить тысячами. И игра будет быстро работать.

Google translate: >>> Felled trees also use it. Regarding the animation with the separation of one part from the general model, yes, there is a new Draw call. But instancing gives mass appeal. Example. A chest with about 13 Draw calls, he just needs to move the lid to another object we get 15 drow calls. But if in the city they are usually in each house in stacks of 20 pieces, this is only on chests we get only 260 bathces from chests. In the case of a mesh render, only one is rendered. That is, 15 and 260+, you know what is better. So the problem is precisely in large quantities of these items. 10 houses is a huge loss of productivity. In cities and more are being built. All my modified objects have the structure of a mesh render. And they are animated through a simple axis through the zero object. Yes, it adds two extra drow calls, but I can build thousands of them. And the game will run fast.

I recorded video proofs of how NOT OPTIMISED your skinned mesh render. Specialy for @keegan-o https://yadi.sk/i/mrux7hKJlAGQPg

Old architype of animtion used skinned mesh render. ChestObject>ChestObjectFBX Ich object used new draw calls and new batches. 10 chests its a 130 DC 130 Batches. For the new structure we need do like this. For example. ChestObject>ChestObjectFBX>Axis1(Empty object(Null animator rotation +45° In unity animted.))>ChestTopCapFBX(Animated from the axis1) <Only two draw call and maybe one new batch. In this situation we have 15 draw calls 14 batch but! 10 chests used GPU instancing and it gonna be a 20 draw calls and 20 batches for the 20-2000 chests, dosnt metter. I can fix all this objects in 30-40 days. But its a huge work. I won't do it for free. @D3nnis3n this is not High Priority, is a Extra Critical Priority. Just look video and you understand everything. Game can be optimised to the 100-500 FPS. For the weak video card is critical.

mirasrael commented 3 years ago

@namquang93 can you investigate what we can do to improve number of draw calls and optimize tree rendering?

namquang93 commented 3 years ago

First of all, trees now have GPU Instancing so it's not new draw calls for each tree anymore. For example in this video, multiple Tree_Top are drawn at a time.

ezgif-6-6ce887047aa8

namquang93 commented 3 years ago

But right now, GPU Instancing doesn't work very efficiently. For example, when there're 10 same trees on the screen, because of some reasons, it draws 2 or 3 trees in 1 draw (instanced), and then draws 2-3 trees in another draw... This has been discussed many times on unity forum.

https://forum.unity.com/threads/instanced-gpu-rendering-doesnt-work-reliably.419063/#post-2784746 https://forum.unity.com/threads/gpu-instancing.452320/

So far we can either set different rendering queues for each tree or use Graphics.DrawMeshInstanced/DrawMeshInstancedIndirect. I've tried testing with rendering queue but failed to improve the instancing. So, right now my suggestion is we should improve our indirect rendering system to support all trees (trunk, root, branch, leaf...) and use it to fully instancing all trees. I think indirect rendering almost supports trees, we just need to do a double pass for rendering mesh & rendering shadow. @mirasrael what do you think?

redwyre commented 3 years ago

@mirasrael if we're going to do more work on the indirect renderer can we create a new issue?

mirasrael commented 3 years ago

Not sure if IndirectRenderer will be effective here. Can you test with 100s of trees and check if Unity works good enough with batching?

SpiritOfAncientWherewolf commented 3 years ago

Preparing new trees system. Over 2000 animated trees in render scene have ~900 fps and 13-20 bathces. CPU 2.5ms over 15 millions of vert and almost 25 millions of polys. When it be ready i present it for you. Its not a free work, Because i dont have buisness now, i need money. /