FakeFishGames / Barotrauma

A 2D online multiplayer game taking place in a submarine travelling through the icy depths of Jupiter's moon Europa.
http://www.barotraumagame.com/
1.77k stars 409 forks source link

Destructible level walls are never culled #12986

Closed BlackMoons closed 5 months ago

BlackMoons commented 1 year ago

Disclaimers

What happened?

Hi. I tried loading the game into renderdoc today... Had some interesting results.

For one, large sections of the level are rendered even if not remotely visible. Not the worst thing because they are at least well batched... but some things are not. Several hundred draw calls of 12 and 18 vertices in color pass #4 don't actually appear anywhere on screen.

They appear to be using these textures: image

image

All of these objects are quite far off screen and drawn in individual draw calls, so should be cullable.

image

Shows just how far offscreen some of these objects are. (the white box is the screen area, the blue box is the thing being rendered by that draw call)

Infact here is the whole pass, showing objects being rendered insanely far off screen: image

For reference, the sub is inside that tiny little yellow 'cave' at the top left, and the sub couldn't even see any of the cave from the rendering. The cave shown is several times bigger then the sub, many times bigger then the viewable scene.

Here is the actual scene as rendered, note its entirely just showing inside of the sub and no cave walls whatsoever. Position was just seconds after leaving the 1st station: image

None of the cave is even visible in that scene, yet stuff miles outside the cave is being rendered in color pass #4

Here is a photoshop with a green dot that shows the area that is actually on screen:

image

Upon further inspection, I believe they are ice spires...

Reproduction steps

Start renderdoc attached to barotrauma, stable release.

Start single player campaign

Leave first station

Capture frame.

Bug prevalence

Happens every time I play

Single player or multiplayer?

Single player

-

No response

Version

v1.1.19.3 (Treacherous Tides Hotfix 2)

-

No response

Which operating system did you encounter this bug on?

Windows

Relevant error messages and crash reports

No response

Regalis11 commented 1 year ago

Thank you for the report!

I would like to repeat what I said in the previous ticket: it's not really that useful to do optimization by searching for problematic parts "blind" like this - we can actually measure what the heavy parts of the logic and rendering are and spend our time focusing on those (and very often those parts turn out to be something completely different than what we would've expected).

In this case, I highly doubt rendering these destructible walls has any noticeable performance impact, and I wouldn't even be surprised if the overhead of culling them would be larger than just always rendering them. I also gave this a quick test, and I couldn't measure any performance impact by disabling the rendering of these walls completely.

Also, this isn't overdraw: overdraw in the context of games means that things are being drawn in front of each other, meaning you're rendering things unnecessarily when it's going to get obstructed by the stuff in front of it, which doesn't seem to be the case here.

BlackMoons commented 1 year ago

Some mods add more destructible ice spires, like dynamic europa and make the levels way bigger. Especially in the 1st/4th biome.

Maybe you could at least consider changing them to be batchable draw calls? (And set the two textures used to slightly different depths so they batch properly?)

Also, I suspect that if your computer isn't already draw call stressed, your not going to see any performance benefit from reducing draw calls like people who are draw call stressed (complex subs, with complex mods, later in the campaign)

Video card drivers tend to buffer draw calls until you overrun the buffer, then things go to a grinding halt.

BlackMoons commented 1 year ago

Thank you for the report!

In this case, I highly doubt rendering these destructible walls has any noticeable performance impact, and I wouldn't even be surprised if the overhead of culling them would be larger than just always rendering them. I also gave this a quick test, and I couldn't measure any performance impact by disabling the rendering of these walls completely.

Renderdoc says rendering those destructible walls are responsible for about 1000 out of the 9000 events in that scene. If you didn't see any improvement it likely means that your particular computer isn't draw call limited in the scene you tested.

Regalis11 commented 1 year ago

Maybe you could at least consider changing them to be batchable draw calls? (And set the two textures used to slightly different depths so they batch properly?)

They aren't rendered using SpriteBatch, we'd need to construct the vertex buffer manually (which isn't a huge task, but not entirely trivial either). Sprite depth isn't a concern in this cases because they're not sprites nor sorted by depth.

But anyhow, I think I'll look into this and see if there's some performance gains to be had here. But before that, we need to measure whether this is actually a problem worth addressing. Modern graphics cards and APIs can handle millions of draw calls per second, so a thousand extra draw calls might be practically nothing, and the degraded performance experienced on less powerful hardware might have nothing to do with these deconstructible walls.

BlackMoons commented 1 year ago

Thank you for looking into it further.

Modern video cards can only handle millions of draw calls with careful DX12 programming/vulcan. DX11 is generally limited to 3000~20000 per frame in immediate mode, depending on your hardware, drivers, programming and how much your CPU is being used.

Source: https://docs.nvidia.com/gameworks/content/gameworkslibrary/graphicssamples/d3d_samples/images/image003.jpg

https://docs.nvidia.com/gameworks/content/gameworkslibrary/graphicssamples/d3d_samples/d3d11deferredcontextssample.htm

Can I suggest you use the mod dynamic europa when profiling it? https://steamcommunity.com/workshop/filedetails/?id=2532991202

It has larger levels and more ice spires that will cause any performance loss to stand out much better. Its also an incredibly popular mod with 127,000 subscribers.

I feel like you could go either way to improve this: Construct your own vertex buffer so the entire levels destructible walls can all be rendered in one draw call (Since its only a few 1000 vertices), or do a visibility check (sphere, the size of the furthest vertex from center of wall vs viewing frustum would be fine) and only render those walls within range (would only render like 1~4 even with a very basic visibility test, with mods that greatly increase spire count)

Regalis11 commented 1 year ago

Gave this a test with dynamic europa, and I did notice an increase in performance (not drastic though, about 5% higher FPS, but it the results could be more noticeable on more low-end hardware).

Implemented culling the walls in https://github.com/Regalis11/Barotrauma-development/commit/5f216b88534c21931548a8812f57f22bf2f5fcb6

Jasontti commented 5 months ago

Tested the fix in: https://github.com/FakeFishGames/Barotrauma-development/pull/4667/commits/777dff41a228b3d2dd87378e61cb3b643e4bb50b

Tested that there is no pop in in regular gameplay. Looked that sonar to see that spires were visible there. Flew around in freecam and debugmode to see if there are issues with invisible spires, ice chunks or destructible cave chunks. Gave renderdoc a go and noted differences, camera position is at top left (start outpost): image

No issues found, closing ticket as completed