Skip to content
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

Polygon Drawing Performance Issue in 3.0 #14869

Closed
Ron5s opened this issue Dec 20, 2017 · 33 comments
Closed

Polygon Drawing Performance Issue in 3.0 #14869

Ron5s opened this issue Dec 20, 2017 · 33 comments

Comments

@Ron5s
Copy link

Ron5s commented Dec 20, 2017

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
Copy link
Member

groud commented Dec 20, 2017

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
Copy link
Author

Ron5s commented Dec 20, 2017

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

@reduz
Copy link
Member

reduz commented Dec 20, 2017 via email

@Ron5s
Copy link
Author

Ron5s commented Dec 20, 2017

@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
Copy link
Member

reduz commented Dec 20, 2017 via email

@Ron5s
Copy link
Author

Ron5s commented Dec 20, 2017

@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
Copy link
Contributor

endragor commented Dec 21, 2017

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
Copy link
Member

reduz commented Dec 21, 2017 via email

@reduz
Copy link
Member

reduz commented Dec 21, 2017 via email

@endragor
Copy link
Contributor

@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
Copy link
Member

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
Copy link
Author

Ron5s commented Dec 21, 2017

@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
Copy link
Member

reduz commented Dec 21, 2017

@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
Copy link
Member

reduz commented Dec 21, 2017

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
Copy link
Member

reduz commented Dec 21, 2017

@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
Copy link
Member

Thanks reduz, that is a little reassuring :)

@endragor
Copy link
Contributor

@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
Copy link
Member

reduz commented Dec 21, 2017

@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
Copy link
Contributor

@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
Copy link
Author

Ron5s commented Dec 22, 2017

@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
Copy link
Member

reduz commented Dec 22, 2017

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

  • Render in HDR by default (16 bits per channel, 2 buffers, 3 if uing effects like SSAO, SSR)
  • Always Render in Linear colorspace (requires a conversion to SRGB pass later)
  • Single material/lighting pass (not deferred) is efficient but expensive, so it requires a pre depth pass
  • MSAA support means it needs to use RenderBuffers to render, which need to be resolved
  • No avoidance for dependent texture reads, means low end / mobile suffer, while PC medium and high end architectures are unaffected.
  • Reflection probes, shadows, etc. are all read from an atlas, so in a single pass you can render dozens of shadows, lights and reflections.

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

  • Always renders in LDR (small buffer, 8 bits per channel, 1 buffer), no bandwidth usage
  • Always renders in SRGB (no conversion needed)
  • Lighting is multi-pass, which means one or two lights are cheap, but many are expensive.
  • Thanks to multi-pass approach, all texture reads can depend from a varying. This makes it able to use texture prefetch on mobile and low end PC, increasing performance a lot.
  • Overdraw may be a problem in this design, but mobile architectures are designed to avoid it, so this is not too bad.
  • Reflections, Shadows, etc. are unique per pass, so not many are allowed per object. Reflection likely limited to 2. Reflection also uses a cubemap (instead of dual paraboloid in GLES3) otherwise prefetch can't be used.

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

@reduz
Copy link
Member

reduz commented Dec 22, 2017

@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
Copy link
Contributor

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
Copy link
Member

reduz commented Dec 22, 2017

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

@volzhs
Copy link
Contributor

volzhs commented Dec 24, 2017

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

@Ron5s
Copy link
Author

Ron5s commented Dec 27, 2017

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
Copy link
Member

reduz commented Dec 27, 2017 via email

@Ron5s
Copy link
Author

Ron5s commented Dec 27, 2017

@ 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
Copy link
Member

reduz commented Dec 27, 2017

@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
Copy link
Member

reduz commented Dec 27, 2017 via email

@Ron5s
Copy link
Author

Ron5s commented Jan 4, 2018

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

@Ron5s
Copy link
Author

Ron5s commented Mar 5, 2018

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
Copy link

ghost commented Mar 5, 2018

Closing as resolved

@ghost ghost closed this as completed Mar 5, 2018
@akien-mga akien-mga added this to the 3.0 milestone Mar 5, 2018
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants