godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.17k stars 21.2k forks source link

Polygon Drawing Performance Issue in 3.0 #14869

Closed Ron5s closed 6 years ago

Ron5s commented 6 years ago

Godot version:

3.0 Beta 1 and current 3.0 Build

OS/device including version:

Windows 10 x64, Nvidia GTX 770

Issue description:

I had written code in C# to generate a large amount of geometry in Unity. When Godot was released with Mono I tried to change over to it. The code didn't change except for the Godot specific commands to draw the mesh. The code in Godot C# is 99% identical to what I had in Unity. But the low performance (5 fps) and high resource usage (100% video card, 90% of ram, 100% cpu) in Godot is drastically different than in other software. I wrote a script to demonstrate this (see attached) it was run in 2.1.4 and 3.0 Beta 1. 2.1.4 runs it perfectly, 3.0 Beta 1 runs with the low performance as described above.

Steps to reproduce: Run the attached project in 2.1.4 and use the same draw script (DrawTest.gd) in 3.0 Beta 1.

Minimal reproduction project:

TestDraw.zip

groud commented 6 years ago

The difference is probably due to the GLES3 renderer used instead of the GLES2, which is no more available in 3.0. It should be brought back in 3.1.

Ron5s commented 6 years ago

That would be great if that was the issue. Thank you for the help.

reduz commented 6 years ago

If the geometry does not need to be modified on every frame, I suggest you use Mesh isntead of ImmediateGeometry, which is not really meant to draw large amounts of geometry.

On Wed, Dec 20, 2017 at 1:47 PM, Ron notifications@github.com wrote:

That would be great if that was the issue. Thank you for the help.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-353117139, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z2xFya98jAuXKKJbbtCprZWJ_CJryks5tCTomgaJpZM4RIcBj .

Ron5s commented 6 years ago

@reduz Thank you for the reply. I have tried using Mesh also and it behaves the same way. I will make another test case with Mesh and attach it here.

reduz commented 6 years ago

you can create a mesh using SurfaceTool

On Wed, Dec 20, 2017 at 2:19 PM, Ron notifications@github.com wrote:

@reduz https://github.com/reduz Thank you for the reply. I have tried using Mesh also and it behaves the same way. I will make another test case with Mesh and attach it here.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-353126402, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z25Cw4icpzKkgijhqMH2lFPYKuwuAks5tCUG1gaJpZM4RIcBj .

Ron5s commented 6 years ago

@reduz thank you. Attached are two test scenes using surface tool one for Godot 2.1.4 and the other for Godot 3.0 Beta 1. The the only difference in code is the declaration of the Vector3 array. There is a performance drop in 3.0. In 2.1.4 FPS is 60 and there are minimal resourse being used. In 3.0 fps drops to about 25 and there is more usage of the computer resources. Thank you again. MeshDrawTest_3beta1.zip MeshDrawTest_214.zip

endragor commented 6 years ago

So this seems to imply that either GLES2 is superior not only for mobile, but also for PC, or there is some implementation problem in 3.0.

reduz commented 6 years ago

So this seems to imply that either GLES2 is superior also for PC, not only for mobile, or there is some implementation problem in 3.0.

Not really, this test is pretty meaningless. GLES2 will always have better performance for simple tests like this. This test is also not representative of a real-life use case as every mesh is different (if all instances share the same mesh, performance goes back to 60fps).

Keep in mind also that, as Godot 3 needs to do a pre z-pass, it does two geometry passes on PC (on mobile it does not do a pre-depth pass because mobile hardware is optimized for not needing it). Disabling it also raises performance for this test, but it will help improve it on real-life scenarios.

That doesn't mean that it can't be further optimized and profiled, it just means there is a bigger base rendering cost in 3.

On Thu, Dec 21, 2017 at 1:16 AM, Ruslan Mustakov notifications@github.com wrote:

So this seems to imply that either GLES2 is superior also for PC, not only for mobile, or there is some implementation problem in 3.0.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-353254249, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z20e1DTsR82oso7SlJGh5tU3_9CI8ks5tCdulgaJpZM4RIcBj .

reduz commented 6 years ago

In any case, for simple 3D and 2D games, the GLES2 backend will definitely improve these things too.

On Thu, Dec 21, 2017 at 8:11 AM, Juan Linietsky reduzio@gmail.com wrote:

So this seems to imply that either GLES2 is superior also for PC, not only for mobile, or there is some implementation problem in 3.0.

Not really, this test is pretty meaningless. GLES2 will always have better performance for simple tests like this. This test is also not representative of a real-life use case as every mesh is different (if all instances share the same mesh, performance goes back to 60fps).

Keep in mind also that, as Godot 3 needs to do a pre z-pass, it does two geometry passes on PC (on mobile it does not do a pre-depth pass because mobile hardware is optimized for not needing it). Disabling it also raises performance for this test, but it will help improve it on real-life scenarios.

That doesn't mean that it can't be further optimized and profiled, it just means there is a bigger base rendering cost in 3.

On Thu, Dec 21, 2017 at 1:16 AM, Ruslan Mustakov <notifications@github.com

wrote:

So this seems to imply that either GLES2 is superior also for PC, not only for mobile, or there is some implementation problem in 3.0.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-353254249, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z20e1DTsR82oso7SlJGh5tU3_9CI8ks5tCdulgaJpZM4RIcBj .

endragor commented 6 years ago

@Ron5s out of curiosity - have you tried forcing Unity to also use GLES 2.0 and 3.0 backends and comparing the performance there? According to the docs it supports -force-glesXY flag where XY can be 20,30,31.

mhilbrunner commented 6 years ago

I only want to state that there is a difference between "GLES2 will always have better performance for simple tests like this" and having less than half the FPS of the old GLES2 renderer in the new renderer.

Is this really such a pathological test case? Or will real-world performance for the new renderer be in at least the same ballpark, comparatively? The new GLES2 renderer that will be re-added isn't a solution as stated above, as it will not support everything the new backend does... so will not work for all cases.

Ron5s commented 6 years ago

@reduz Thank you for your reply. While the test cases I provided are simple its representative of what I am experiencing with my game. I posted it because it is simple and illustrated the issues I'm having in Godot and not in other software using the same C# code. In my case I can not have all instances share the same mesh since they are unique.

@endragor Good question, I had not until now. I ran Unity in both GLES2 and GLES3, and both ran perfectly. In both cases it ran with lower resource usage than Godot and at 60 FPS.

reduz commented 6 years ago

@mhilbrunner It's not that simple. Performance is not an absolute and universal mesaure, it depends on the test case.

If you ask: Which renderer will have better performance for a cube and a light? GLES2 definitely. If the question is: Which renderer will have better performance for a lot lights, overdraw, post processing effects, probes, complex materials, etc: GLES3 definitely

GLES3 renderer has a considerably bigger base costs in both GPU memory and performance, but scales and looks much better.

There is not a linear scale. This is why a GLES2 renderer is being done. It's considerably less powerful but does simple things more efficiently by using a different approach.

reduz commented 6 years ago

Once GLES2 renderer is complete, I will most definitely make some tests to show the performance and quality in different scenarios, so it's clearer for everyone what are the pros/cons.

reduz commented 6 years ago

@endragor Unity approach for rendering does not change much between GLES2 and GLES3. AFAIK shaders still use regular uniforms and their abstraction is more low level.

In Godot the abstraction is higher level and the approaches used for diferent tasks between GLES2 and GLES3 are considerably different. The difference in performance in different scenarios is more related to how the API is used than the API itself.

I think as API itself, the performance should not change much.

mhilbrunner commented 6 years ago

Thanks reduz, that is a little reassuring :)

endragor commented 6 years ago

@reduz Does that mean Godot's GLES3 backend should have better performance than Unity's in the complex scenarios that you described? If so, it would make sense to create such example(s), and it would also be useful as an advertisement point. So far it's not quite clear what the benefit is from using API in Godot's way, if there is such a significant performance loss for simple scenarios (comparing to Unity's GLES3 backend).

reduz commented 6 years ago

@endragor Depending for what, It's really difficult compare. Godot does look MUCH better than Unity out of the box, though, as the main focus is the ease of use.

endragor commented 6 years ago

@reduz yes, I mean not a generic comparison between Godot and Unity, but the graphics API usage aspect. As I see it, Godot's ease of use comes from its programming and scene structure paradigms. But that stays no matter what backend is used and how it is used underneath. The question is what exactly do we gain in exchange for the performance loss. You earlier said that the loss only applies for simple cases, so it would be nice to have some evidence of that. People trying out Godot will always test simple cases first and such a difference will turn them away.

Ron5s commented 6 years ago

@endragor while the examples I provided are simple they are examples of my application which is not simple. So I am unclear how it being simple hurts performance when it behaves exactly like my non-simple case.

I re-ran the attached test case in 3.0 Beta 2 and there is a performance increase. It now hovers around 50 fps but still stutters. I also added the lines:

func _enter_tree(): OS.set_low_processor_usage_mode(true)

This helped more but still stuttered even when doubling the number of polygons.

My non-simple case is still having considerable performance issues, eating up 92% of my 16gd of ram.

reduz commented 6 years ago

@endragor The loss of base performance in Godot 3 is due to the following: In GLES3:

In comparison, the GLES2 backend that Thomas is doing should be very very fast due to the following:

So that's pretty much it. By becoming less flexible, the GLES2 renderer is fast.

reduz commented 6 years ago

@Ron5s The problem of your case is that you are creating the same mesh over and over again for every single of the 10k instances. If you share the mesh between instances, you'll notice that performance will go up a lot (and memory will go down a lot). If you use hardware instancing (MultiMesh), it will be blazing fast in Godot 3.

It's more about using the right tools for what you want to do.

Zireael07 commented 6 years ago

Wondering about that bit in GLES3 description:

Always Render in Linear colorspace (requires a conversion to SRGB pass later)

Why doesn't it just do srgb?

reduz commented 6 years ago

@Zireael07 Actual lighting math is more correct in linear colorspace, specially if you want to use HDR.

volzhs commented 6 years ago

maybe we could have video something like this. https://www.youtube.com/watch?v=mBfMDlpZRz0 comparison fps and visual quality to other engines. :)

Ron5s commented 6 years ago

For what its worth Ive been experimenting with rendering settings and it seems that the only way to increase FPS and reduce resource usage is to disable MSAA completely.

reduz commented 6 years ago

Your sample so far is not very representative of a real life use case. I explained already how to get better performance..

On Dec 27, 2017 1:58 PM, "Ron" notifications@github.com wrote:

For what its worth Ive been experimenting with rendering settings and it seems that the only way to increase FPS and reduce resource usage is to disable MSAA completely.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-354142709, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z20eoKv1sEZwI7R3W7SFaiwP0vTZnks5tEnchgaJpZM4RIcBj .

Ron5s commented 6 years ago

@ reduz Thank you for the help. None of your suggestions worked on my real world application. Which parses openstreetmap data from an osm file and recreates it with polygons. So each polygon is unique. The example I posted was to illustrate drawing lots of meshes similar to my application. I wrpte the OSM code in C# so the code is nearly identical in Godot as in Unity. Unity's gl2 and 3 renderer runs at 60 fps and low resources, I cant say that about Godot. But if this the best i get out of Godot thats fine, I appreciate all of your hard work and I love Godot. Thank you again. And will continue to use it just not for this project right now.

reduz commented 6 years ago

@Ron5s I think no matter the engine that approach will be inefficient eventually. You can always group polygons per cell or something to minimize drawcalls without that much effort.

reduz commented 6 years ago

Btw, I ran your demo on valgrind and it seems to be completely driver bound, so this may actually be a problem on GLES3 having significantly more driver overhead.. though all it does is bind a VAO and calling draw elements..

On Dec 27, 2017 4:44 PM, "Ron" notifications@github.com wrote:

@ reduz Thank you for the help. None of your suggestions worked on my real world application. Which parses openstreetmap data from an osm file and recreates it with polygons. So each polygon is unique. The example I posted was to illustrate drawing lots of meshes similar to my application. I wrpte the OSM code in C# so the code is nearly identical in Godot as in Unity. Unity's gl2 and 3 renderer runs at 60 fps and low resources, I cant say that about Godot. But if this the best i get out of Godot thats fine, I appreciate all of your hard work and I love Godot. Thank you again. And will continue to use it just not for this project right now.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/14869#issuecomment-354167625, or mute the thread https://github.com/notifications/unsubscribe-auth/AF-Z2zLAHlp_gw00Yx_33Nx4J-jwnuSMks5tEp43gaJpZM4RIcBj .

Ron5s commented 6 years ago

@reduz That's very interesting. Thank you for looking into it further.

Ron5s commented 6 years ago

I just re-ran my project in 3.0.2 Stable and its blazing fast now. I didn't change any code, so something must have happened between the beta and stable release. Before it was consuming 100% of the gpu and large amounts of ram and cpu running at 5fps. Now it is hovering around 15% gpu usage and very little cpu and ram usage running at 60 fps. This can probably be closed now. Thank you for the hard work.

ghost commented 6 years ago

Closing as resolved