Jump to content

AI, Pathfinding and Performance


Recommended Posts

20 minutes ago, vladislavbelov said:

It's a good tool. I'm using it for a while. But it still misses some good features from RenderDoc, which doesn't support our GL unfortunately.

We mostly use 1 draw call per each GUI element. It'd be good to refactor it and to use only 1-2 draw call per all GUI.

I did indeed try RenderDoc first,  The OpenGL context wasn't created in the way it expected, so I poked around trying to find something similar to a GLFW start function I could modify. I thought I could just pretend the game was OGL3 compatibility profile and trick RenderDoc, but I failed.

 

Also just to be clear: We I write '$number calls' I don't mean only drawcalls, I'm including all OpenGL functions in there.

Edited by theotherhiveking
Link to comment
Share on other sites

Hmmm interesting, thanks for the video link, etc.

On the topic of graphics - I did a quick search thru the code for basically gl_ , and there were quite a few hits in many files. There were a ton in Renderer.cpp (as expected), but also a good few elsewhere.

With that in mind, looking at Renderer.cpp, there's a lot of direct OpenGL calls; this makes me thing that maybe a first step in 'resolving' the issue of updating the renderer, would be to abstract it.

Instead of having the current OpenGL calls directly in Renderer.cpp and friends, the Renderer should be an abstraction or interface, that is then implemented in OpenGL, Vulkan, or whatever else. The benefit to this - is that we'd have one 'set' of functions/calls that we'd have to satisfy whenever it came to supporting a new API.

So for example, the existing code could be reworked into a Renderer interface (IRenderer, following the same convention as everything else [tbh I'm just assuming the I there means interface ... please let me know if otherwise]). Then the current OpenGL code could be implemented as OpenGLRenderer or something, and whatever else in their own implementation.

The benefits of doing it this way would be:

  1. Requirements for the Renderer (thru the interface) would be clear.
  2. OpenGL, Vulkan, and whatever else code would be contained in a single location.
  3. In theory we could package it so that Renderers are easily changeable.
  4. We still have control over the rendering part of the engine.

Downsides would be:

  1. It's a good bit of work

With that in mind, I do see the value in using some other third party rendering stuff - but I think for every third-party dependency added, it provides opportunity for the project to be stuck with no alternative. Say we pick up some library to use for rendering, if that is no longer maintained, then we'd either have to find another, or maintain it ourselves. Which really, only brings us back to the same position. So in my view, I think keeping as much as possible within the project is best - even if a bit more work. Plus we already have a working renderer - even if a little outdated technology-wise.

Those are my thoughts anyway... open to counter-arguments/agreements!

Thanks,

-Crynux

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Those are definitely the pros and con... "Bit more work" is I feel a bit of an understatement though. Modern graphics are complex affairs, and we already don't have much workforce. I don't think we can make an AAA level RTS graphics engine - and that's kinda what we're talking about here.

The dependency problem is a big issue because most "probably won't fail" projects have grown a bit too big. Things like godot or Ogre are complete and modern, but we can't really easily adapt our current code to them. Smaller projects have a more uncertain future, or don't support all of our three platforms, and such.

Regardless, the renderer abstraction is probably something we'll need to do anyways, so it's a good first step.

  • Like 1
Link to comment
Share on other sites

7 hours ago, Crynux said:

Hmmm interesting, thanks for the video link, etc.

On the topic of graphics - I did a quick search thru the code for basically gl_ , and there were quite a few hits in many files. There were a ton in Renderer.cpp (as expected), but also a good few elsewhere.

With that in mind, looking at Renderer.cpp, there's a lot of direct OpenGL calls; this makes me thing that maybe a first step in 'resolving' the issue of updating the renderer, would be to abstract it.

Instead of having the current OpenGL calls directly in Renderer.cpp and friends, the Renderer should be an abstraction or interface, that is then implemented in OpenGL, Vulkan, or whatever else. The benefit to this - is that we'd have one 'set' of functions/calls that we'd have to satisfy whenever it came to supporting a new API.

So for example, the existing code could be reworked into a Renderer interface (IRenderer, following the same convention as everything else [tbh I'm just assuming the I there means interface ... please let me know if otherwise]). Then the current OpenGL code could be implemented as OpenGLRenderer or something, and whatever else in their own implementation.

The benefits of doing it this way would be:

  1. Requirements for the Renderer (thru the interface) would be clear.
  2. OpenGL, Vulkan, and whatever else code would be contained in a single location.
  3. In theory we could package it so that Renderers are easily changeable.
  4. We still have control over the rendering part of the engine.

Downsides would be:

  1. It's a good bit of work

With that in mind, I do see the value in using some other third party rendering stuff - but I think for every third-party dependency added, it provides opportunity for the project to be stuck with no alternative. Say we pick up some library to use for rendering, if that is no longer maintained, then we'd either have to find another, or maintain it ourselves. Which really, only brings us back to the same position. So in my view, I think keeping as much as possible within the project is best - even if a bit more work. Plus we already have a working renderer - even if a little outdated technology-wise.

Those are my thoughts anyway... open to counter-arguments/agreements!

Thanks,

-Crynux

 

I think that is exactly what @vladislavbelov is planning. :)

Maybe he can need some help?

  • Thanks 1
Link to comment
Share on other sites

49 minutes ago, wraitii said:

Those are definitely the pros and con... "Bit more work" is I feel a bit of an understatement though. Modern graphics are complex affairs, and we already don't have much workforce. I don't think we can make an AAA level RTS graphics engine - and that's kinda what we're talking about here.

The dependency problem is a big issue because most "probably won't fail" projects have grown a bit too big. Things like godot or Ogre are complete and modern, but we can't really easily adapt our current code to them. Smaller projects have a more uncertain future, or don't support all of our three platforms, and such.

Regardless, the renderer abstraction is probably something we'll need to do anyways, so it's a good first step.

Yeah that's fair - "a bit more work", is more like "a lot more work" ... either way though, I think it could be done in steps. The first being making it an abstraction, then once we have a 'concrete' interface or whatever, other implementations would be simpler, as there'd be a better idea of what we need to create.

With that being said, there'd need to be some thought into the inputs and outputs of the renderer to some degree (thinking somewhat abstractly here), like building some standard for objects to be passed to the Renderer. That way no matter the implementation - we can provide the same thing and it should be happy. My initial idea was that the renderer implementations could be their own separate thing eventually (maybe thinking too far ahead here). Having for example 'opengl_renderer.so' or 'vulkan_renderer.so', maybe with some version numbers in there as needed. Then the engine could look for the shared objects/dlls/whatever mac uses somehow and load them as-needed, providing a renderer option in the settings (possibly?). I've seen this in other games before... not sure how it was done though... but it's possible lol.

I'm always aware of dependencies ... tbh even not knowing too much about the rendering code here, I think we have a really good base. It'd be a waste in my opinion to move away from it. From how it sounds, it just needs a little TLC.

45 minutes ago, Imarok said:

I think that is exactly what @vladislavbelov is planning. :)

Maybe he can need some help?

Interesting ... I may have to send a message, thanks for the heads-up!

Thanks again!

Crynux

Link to comment
Share on other sites

The renderer isn't bad, it's actually fairly well designed (except for the GUI). It's just quite coupled with OGL2, which isn't the best coupling for 2019 :P.

Also agreed pithing pinging Vlad' on this, he's probably more knowledgeable than I am about the renderer.

  • Like 2
Link to comment
Share on other sites

On 5/22/2019 at 2:44 AM, Crynux said:

Hmmm interesting, thanks for the video link, etc.

On the topic of graphics - I did a quick search thru the code for basically gl_ , and there were quite a few hits in many files. There were a ton in Renderer.cpp (as expected), but also a good few elsewhere.

With that in mind, looking at Renderer.cpp, there's a lot of direct OpenGL calls; this makes me thing that maybe a first step in 'resolving' the issue of updating the renderer, would be to abstract it.

Instead of having the current OpenGL calls directly in Renderer.cpp and friends, the Renderer should be an abstraction or interface, that is then implemented in OpenGL, Vulkan, or whatever else. The benefit to this - is that we'd have one 'set' of functions/calls that we'd have to satisfy whenever it came to supporting a new API.

So for example, the existing code could be reworked into a Renderer interface (IRenderer, following the same convention as everything else [tbh I'm just assuming the I there means interface ... please let me know if otherwise]). Then the current OpenGL code could be implemented as OpenGLRenderer or something, and whatever else in their own implementation.

Yes, that was an origin point. But it's not a silver bullet. Because the another layer of abstraction reduces flexibility, adds limitations and may reduce performance, because of many differences in backend APIs. We can't just add a IRenderer with methods like drawTriangle. Theoretically you can do this, but it would have a significant performance lose.

You may add abstraction structures (like octree for frustum culling) that work for all types of backend. But some backend dependent stuff won't work easily. For ex. shaders, you need to use universal language or use some language converters. Which means another layer of limitations.

So, what we could do (not a full list):

1. Use own graphics engine

a) Use the only one backend API (like Vulkan or GLES) with some third party libraries (like libangle for GLES) that convert these API calls for other platforms (other than supported platforms by this backend).

b) Use multiple backends (like you suggested) with run-time or compile-time backend changing.

2. Use third party graphics engine/library:

a) Use a complete game/graphics engine (like Godot).

b) Use a complete graphics library that has own stable API with own shader language.

 

In only my opinion I'd prefer the 1a or 1b but with not more than 2 different backends, like OpenGL + Vulkan. Because they're Open-Source and present mostly for all platforms (through third-party libraries). Because it's most interesting for a graphics programmer: you don't need to support a lot of backends and you have enough power of the backends.

But! It means that we need to handle some low-level stuff by ourselves. Like GPU blacklists, driver specific bugs (like our Intel crashes), and so on. That's harder to support. Complete engines have own problems too, they have less flexibility/performance or small number of supported platforms (some engines already dropped <= GL2). They may change their license or stop support it.

Actually it's not the easy question. That's why I suggested to not rush inside rewriting all graphics stuff (while we somehow support most platforms) and refactor all related stuff first.

I think the main task now is to collect and isolate most of GL code in some specific place (not just call them through simple proxy functions). That'd be useful for any way that we'd choose.

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

20 hours ago, vladislavbelov said:

Yes, that was an origin point. But it's not a silver bullet. Because the another layer of abstraction reduces flexibility, adds limitations and may reduce performance, because of many differences in backend APIs. We can't just add a IRenderer with methods like drawTriangle. Theoretically you can do this, but it would have a significant performance lose.

You may add abstraction structures (like octree for frustum culling) that work for all types of backend. But some backend dependent stuff won't work easily. For ex. shaders, you need to use universal language or use some language converters. Which means another layer of limitations.

So, what we could do (not a full list):

1. Use own graphics engine

a) Use the only one backend API (like Vulkan or GLES) with some third party libraries (like libangle for GLES) that convert these API calls for other platforms (other than supported platforms by this backend).

b) Use multiple backends (like you suggested) with run-time or compile-time backend changing.

2. Use third party graphics engine/library:

a) Use a complete game/graphics engine (like Godot).

b) Use a complete graphics library that has own stable API with own shader language.

 

In only my opinion I'd prefer the 1a or 1b but with not more than 2 different backends, like OpenGL + Vulkan. Because they're Open-Source and present mostly for all platforms (through third-party libraries). Because it's most interesting for a graphics programmer: you don't need to support a lot of backends and you have enough power of the backends.

But! It means that we need to handle some low-level stuff by ourselves. Like GPU blacklists, driver specific bugs (like our Intel crashes), and so on. That's harder to support. Complete engines have own problems too, they have less flexibility/performance or small number of supported platforms (some engines already dropped <= GL2). They may change their license or stop support it.

Actually it's not the easy question. That's why I suggested to not rush inside rewriting all graphics stuff (while we somehow support most platforms) and refactor all related stuff first.

I think the main task now is to collect and isolate most of GL code in some specific place (not just call them through simple proxy functions). That'd be useful for any way that we'd choose.

Hello! Thank you for the detailed response.

I understand the concerns with an abstraction possibly introducing slowdown, but I do think if done right that slowdown could be minimal to none. Rather than creating an abstraction that forces Vulkan, OpenGL, or whatever else, to conform to it. It'd be best to create the abstraction "conforming" to our 2 or so favorable APIs.

So, for example, It'd be created with Vulkan and OpenGL implementations in mind - minimizing the need to create workarounds in each. Where differences exist, some compromises may need to be made. But I think the benefit would be that even with this OpenGL/Vulkan abstraction, anyone else who comes along and would like to develop an implementation of it for some other graphics api, can then just conform to the abstraction spec - and not have to necessarily deal with how to build it into the game engine. If they satisfy the abstraction, then it should work.

Either way, I do think some layer between whatever graphics APIs that will be used, and the engine, is important. For one, if we have a standardized interface, with that interface, unittests or function/feature-based performance benchmarks could be possible. So then technically, it would be possible to create a small separate application, that would for example, test one of the implementations in areas such as - rendering 500 units. Or testing the FPS impacts of effects. With these benchmarks you could actually see were each API struggles. In addition, it may provide an opportunity to add some kind of option to the game graphics menu, where it could choose the 'optimal api' for your machine, based on a series of small real-time performance tests (even if just a FPS comparison of a minute or to of each running a similar complex scene). Almost like a benchmark that determines your graphics settings.

But with that being said, I do agree that 1a or 1b would be best. Relying on a 3rd party has more risks, even if it may be 'easier' (although sometimes it isn't, because then there's learning that 3rd party api).

I also agree that an initial refactor would help greatly. As you say, if we get all the GL code in one spot - then that'll make replacing it simpler.

Thanks!

-Crynux

Link to comment
Share on other sites

3 hours ago, wraitii said:

I think we should consider OpenGL deprecated going forward, too. Mac OS has done so, so the only useful thing is OGL 2 for legacy systems support. Vulkan / Vulkan+MoltenVK are probably the systems of the future for us.

+1

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...