CitiesSkylinesMods / TMPE

Cities: Skylines Traffic Manager: President Edition
https://steamcommunity.com/sharedfiles/filedetails/?id=1637663252
MIT License
571 stars 85 forks source link

Extraocular framerate boosting #737

Open originalfoo opened 4 years ago

originalfoo commented 4 years ago

Some of the most fps heavy features of TMPE are around junctions - priority signs, traffic lights, junction restrictions (enter blocked junction), etc.

Vehicle AIs need to use collision detection at junctions just like anywhere else. Which means they are also using vehicle grid.

Could we create a OcularGrid which is like vehicle grid but just contains flag per cell as to whether that bit of the map is in camera view? (Is there already something like this in vanilla game?) The existing vehicle grid "coordinate" could then be used to check against the ocular grid, minimising grid inspection overheads.

An 'outer rim' region could be defined where stuff that's just out of camera view is treated as in camera view so that if the camera pans a little things on the periphery look more correct.

The OcularGrid would be recalculated whenever camera moves/tilts/zooms/etc, but would otherwise remain static.

We could then basically skip collision detection and all sorts of other stuff for junctions that are outside camera view. Vehicles would ignore (or just use significantly more basic computations for...) priority signs, traffic lights, junction restrictions and collision detection, and anything else that eats up CPU, when not in camera view.

To retain some sort of reality in terms of traffic congestion reporting, noise pollution, etc., the segments at those junctions would be heavily speed nerfed (in such a way to avoid affecting pathfinder) to compensate for the ignored computations at the junction. We already have speed nerfing architecture as part of priority signs tool (and possibly traffic light tool, especially if #666 is implemented) so it would just hook in to that.

The feature would be optional, via mod options setting, as some users would prefer to keep things as realistic as possible. But for people who want max fps with "good enough" simulation, extraocular framerate boosting could help.

EDIT: We also have simulation accuracy setting (currently missing from mod options) - that too could be greatly reduced for stuff outside of camera view.

DaEgi01 commented 4 years ago

there is already what you call the occular grid. it is used for camera frustum culling in the rendering process. its even a two step process where the games first makes a more primitive check to get an approximation, and later a more evolved check to determine what should be rendered. i made a mini mod in order to visualize if CO did it right because the code looked fishy. I can give you my mod to get started, even though I'd rather not have this feature implemented because in that case i prefer "realism" or rather consistency in the simulation. I don't want the traffic patterns to change just because i moved my camera. if i'd play for visuals only I'd not use tm:pe.

originalfoo commented 4 years ago

I'd rather not have this feature implemented because...

It would be optional, a setting in mod options, something like:

[x] Enable extraocular simulation culling

The same ocular grid (or whatever it is called in vanilla game) could also be used for improved caching when rendering TMPE overlays.

krzychu124 commented 4 years ago

@DaEgi01 I tried that mod but doesn't seem to do anything or maybe I hit wrong buttons xD Anyways I am going to use that approach to make rendering all visible overlays in one loop instead of loop through every segment/node for each overlay. We have to think what resolution should it have for that.

originalfoo commented 4 years ago

I can give you my mod to get started

If it's already in a repository, could it be added to the CitiesSkylinesMods github org?

originalfoo commented 4 years ago

Fire Controllers' vehicle grid visualiser mod might be useful for testing stuff: https://github.com/FireController1847/Cities-Skylines-Grid-Drawer

DaEgi01 commented 4 years ago

done, its actually pretty primitive :) https://github.com/CitiesSkylinesMods/RenderGridVisualizer

for the actual logic how the game does it check out RenderManager.LateUpdate(). the part with the m_cameraInfo.m_bounds is the first pass, so that it iterates only through the stuff the is really necessary, and the part inside renderGroup.Render(this.m_cameraInfo)) cameraInfo.Intersect(this.m_bounds) does the fine tuning. in the end all rendergroups that are part of RenderManager.instance.m_renderedGroups are the ones that are being rerendered. there is some dirty checking going on .. no idea how that works.

maybe the code in RenderManager.CameraInfo.Intersect is all you need though.

DaEgi01 commented 4 years ago

I'd rather not have this feature implemented because...

It would be optional, a setting in mod options, something like:

[x] Enable extraocular simulation culling

The same ocular grid (or whatever it is called in vanilla game) could also be used for improved caching when rendering TMPE overlays.

opportunity costs :P I'd rather see a IMO more important feature, more optimization, less bugs or cleaner code.

originalfoo commented 4 years ago

we could always use an extra set of hands :)

matfax commented 3 years ago

Simple framerate boosts would certainly be appreciated by the community as DLCs and mods seem to accumulate more and more fps drag, especially in large cities. There are still users who hesitate using TMPE because of fps. If there was a way to get at least 30 fps, this would be sufficient for the next years, without the necessity for a pathfinding overhaul.

So I had another idea that could enable a smoother visual representation without adding too much complexity. It's a simple interpolated approximation of the coordinates of moving objects - not sacrificing accuracy, but instead, 3D latency and some memory. My first hope was that NVidia would provide an AI-based frame boost by using their existing pre-rendered frames. But at the moment, their DLSS is focused on upscaling and anti-aliasing. They in fact offer such a feature for graphical applications and video rendering, though. So it might only be a matter of time until they release GPU fps boosts for CPU-bound games.

Regardless, in a fixed setup like a map, this could be simplified by using interpolation, without AI usage, since there's no moving camera for fixed coordinates. Interpolation should be significantly less complex than the accurate calculation of all objects. It's also a process that could be multi-threaded or performed on the GPU without an effort (depends on Unity engine's internal handling and the question if vehicle object values or solely vector objects are interpolated). By only interpolating one inter-frame, 50 to 80 percent fps gain would be possible - at least for the vehicle calculation.

Memory overhead would be required for the caching of the next accurate state (NEXT) and the last accurate state (LAST).

The workflow would look like this:

  1. Calculate next state accurately (1 frame) 1.1 Store state in NEXT but don't update the source values 1.2 Update source values from LAST instead (only if LAST is already filled)
  2. Approximate next source (1 frame) 2.1 Update source values by interpolating NEXT and LAST 2.2 Switch pointers of NEXT and LAST
  3. (Optionally repeat 2. for more interpolation and more fast frames)

This is for a 50% interpolation. It could be extended to a two-frame interpolation (i.e. ~50% + ~75%), sacrificing the latency of another frame, but increasing fps twice the factor. It's a bit more challenging though because the interpolation factor would have to be derived from the lag since the last frame, which differs significantly between accurate calculation and approximation. Time.deltaTime could be used to determine the difference. Optionally, the approximation could also be limited to the OutsideGrid but I think it would add more complexity than necessary to have different latencies inside and outside the OcularGrid. The latency shouldn't be notable at all because (1) it doesn't affect the mouse pointer and UI itself, and (2) NVidia uses/used 3 frames for pre-rendering which is only disruptive for FPS shooters.

What's your opinion?

krzychu124 commented 3 years ago

@matfax I'm working on FPS Booster mod so there will be solution for fps problems. Game has fps problems because UI is very slow and bottlenecks CPU = main thread. Depends on PC configuration, FPS can be >80% higher than without the mod (have you ever seen more than 100fps in this game? I did, even >200) 😃

Regards to FPS, TM:PE doesn't affect it at all (if you don't use any of its overlays 😅) TM:PE can only slow down simulation due to more realistic vehicle behaviour, but simulation is running on different thread and is more or less independent from FPS(besides sim-main thread sync issues), it has own fixedTime clock 60 frames/second, IIRC.

This particular issue is related with a way how the mod is rendering those overlays (it's slow, old and frametime consuming code). Basically, currently each overlay layer(can show different things) iterates over all objects(nodes/segments) to render itself - there are multiple layers which can be enabled simultaneously.

My idea, already discussed, is to create manager which could collect all visible objects within camera frustum and based on that "cache" render specific layer/layers. Single iteration, plus if no layers visible we could even stop caching these objects to save some frame time (needs to run on main thread 😕). Your idea is nice but game already does that thing for vehicles and citizens. It simulates about 4 frames each second for each entity(citizen/vehicle) (every step it fills 2 frames) and movement is interpolated, based on positions from those two frames.

matfax commented 3 years ago

@krzychu124 Thank you for clarifying this. I observed that traffic load also induced fps load, so I suspected the traffic simulation was causing this. I'm playing on a machine with 64GB, 6 CPU cores, and a GTX 1080. My test map has 0 population and only low outside traffic. But I'm using high-res assets (~ 4500 total) and a lot of mods (including your Mini FPS Booster). If it isn't the traffic simulation, then I assume it's just the rendering of the moving assets that make my fps drop to 5 when zoomed in. It's so laggy, sometimes I have to click multiple times on the UI to respond. Neither GPU nor CPU load is reaching any limit, except GPU memory (8GB total) and CPU main thread.

I'm looking forward to your "Big" FPS booster and I see its potential. Actually, I'm really eager to test it - in case you're still looking for beta testers 😅. However, I don't see how the overlays could be affected by asset rendering. I speculate that even if I hide the whole overlay and your mod completely skips the overlay rendering, I will see low fps due to my assets. But there is no logical reason for it. If I don't move the camera and pause the game, nothing is moving and the assets could theoretically be cached somehow and fps could go up. But it won't. That's why I suspected that assets are inefficiently rendered. If you're already doing traffic simulation on a separate thread and the game already interpolates moving asset objects, then I assume it's related to vector calculations and rendering. I know that the Unity engine isn't very efficient but is it really possible that there isn't a bottleneck in the asset logic as well? Or are my assets simply overloading my GPU memory?

Regardless, I know that this is getting a little bit off-topic and it's not your responsibility to fix what the base game is supposed to deliver, for that people actually have paid. It's a pity that Steam still doesn't provide a method to monetize community contributions. The work of all of you who regularly contribute to this game's modding community is really appreciated.

krzychu124 commented 3 years ago

Test to check if simulation bottleneck fps is pretty simple and you already did it. Move camera to location with nothing to render but still not too far from moving objects (citizens/vehicles). If you stop simulation you should see fps boost, sometimes is little sometimes is significant. I noticed two issues. If you have big city with a lot of moving instances:

A bit more off-topic: I did few experiments trying to figure out if we can add few more PF threads. Here the conclusions:

Summarizing, vanilla game needs 6 fast threads (1 render, 1 sim, 4 PF) and 2 for other less important stuff (audio, water sim, file monitor etc.)

p.s. contact me on Steam or TM:PE discord