ID:2103825
 
Problem description:
Hey guys I'm toying around with a project that uses the KEEP_TOGETHER flag on an object with lots of overlays, many of these objects in fact, and when using them with a plane master within your screen this actually gives terrible performance even when you can't see any of these objects in your view. (Which may in itself be considered a sort of 'bug'.)

Do you guys know any code tricks to replicate or approximate the effect of KEEP_TOGETHER manually? Possibly not a 100% replication, just a close approximation of how it works.
Can you give me a rough idea of how this is laid out? Or even better, maybe a test project demonstrating the phenomenon?

Both KEEP_TOGETHER and PLANE_MASTER create temporary render target textures. (Also maptext now does that too.) There's really no reason I can think of that using them together should cause a major performance drag.
Hmm yes I can give you a rough description. I know how you don't like debugging SS13 code in general but what I'm toying with right now is an experimental lighting system using shadowcasting, a dark plane, and a clientside plane master. I expect in the future it will supplant most other lighting systems due to it's great modularity, appearance, and performance (other than cilentside performance).

It's done here (this is an unfinished stripped down codebase)
https://github.com/Yonaguni/EuropaStation

Essentially
1. Plane master screen image
2. Dark plane screen image
3. Light objects on the map, first overlay being a light falloff and the rest of the overlays are shadows cast by the walls and opaque objects it touches

Now the problem with has been that it gives particularly poor clientside performance (though perhaps it is affecting server performance and this just isn't profiled by the profiler or world.cpu which hovers around 0)

In the past I have tested the code and removing all light objects within the client's view did not help, but setting all light objects to not have the KEEP_TOGETHER flag improved performance immensely, (though obviously it broke all lights that relied upon it).

I'm fairly sure it's built from Nadrew's lighting demo? Though I can't be sure without asking around.
Where in that codebase will I find the lighting code?
It's under code/modules/planar_lighting. It should be all be self contained within.
Hmm, I'll see if I can separate it into it's own demo at some point.

The problem is that even in it's current state I feel like it is inconsistent. I had a friend compile the same code and send it to me and it seemed like it had noticeably different performance than mine. Though that could have been a result of the fact it randomly generates some areas which might have more or less lights.

And even earlier it was cripplingly slow (2 second delay between a movement and keypress), which rather inexplicably stopped being THAT slow at some point, With no change to the code.
Ah I think it was because I was 'seeing' shadows which means I was seeing the entire icon despite none of the actual light icon being in view, just another reason I want to try to remove KEEP_TOGETHER from it.

If I removed KEEP_TOGETHER, I could set the shadows to be TILE_BOUND so that they aren't inappropriately being shown unless you can see the actual light itself.

But unfortunately I'm not sure how to replicate it's multiplicative effect. What is it that keep together actually does to render the icon as one (and kill my client?)
I wouldn't use TILE_BOUND because even if you can't see the light source, you'd expect to be able to see the lights and shadows it casts. The only time you wouldn't want to include a light would be if it was totally occluded, and you couldn't see any of its rays at all.

All KEEP_TOGETHER does is create a temporary texture for rendering, and it draws the icon and all its overlays/underlays grouped with it on that same temporary texture. From what I can figure out of your lighting system, it does look like that's what you need.

Based on what I'm seeing, I can't help but wonder if the issue is that all of these shadows/rays would be better served by drawing to an entire plane at once than an arbitrarily-sized texture.
Ah yeah it's possible you could be in a scenario where you could see the light but not the shadows.

It's seems really weird to me that the cost of keep together + plane master combo has such an unexpectedly high toll clientside. Because I've used some hundreds/thousands of overlays in a screen with a plane master normally and there's been little issue even on low end machines.

Can you give any rough example of how the shadows/rays would draw to an entire plane at once? I didn't get quite what you were suggesting there.
The difference between drawing to a plane vs. using KEEP_TOGETHER would be largely semantic; mainly it would impact things like not needing to calculate a large bounding box for the KEEP_TOGETHER temporary texture, and instead simply drawing to a plane which always has the same size as the map.

In KEEP_TOGETHER's case, there's also the fact that the grouping operation does another layer sort on the icons it's grouping, but that should be fairly quick; I doubt it would impact performance.

What I do think would potentially impact performance is if the shadows and/or lights stretch outside of the map area, because then KEEP_TOGETHER has to build a temporary texture that's larger than the map, and is drawing pixels nobody cares about.
The difference between drawing to a plane vs. using KEEP_TOGETHER would be largely semantic; mainly it would impact things like not needing to calculate a large bounding box for the KEEP_TOGETHER temporary texture, and instead simply drawing to a plane which always has the same size as the map.

Yes that would work, but wouldn't the system you are describing require nested planes? And in effect we are using keep_together as a nested plane in this instance. Because the darkness plane needs to be in the same plane as the light it is being illuminated by, I can't imagine how it would work for a lighting system.

In KEEP_TOGETHER's case, there's also the fact that the grouping operation does another layer sort on the icons it's grouping, but that should be fairly quick; I doubt it would impact performance.

That's strange, because in our case here if you remove KEEP_TOGETHER from everything at once, the game will go from chugging (even on my rather powerful home gtx 970 desktop computer) to 100% performant even for low end machines. And that is even when you compare with an equal number of sprites (by expanding your view size for example).

Now you say here
What I do think would potentially impact performance is if the shadows and/or lights stretch outside of the map area, because then KEEP_TOGETHER has to build a temporary texture that's larger than the map, and is drawing pixels nobody cares about.

When you say 'map area' I assume you mean the entire map from 1 to maxx and maxy. But would the same thing apply to a plane master? If a sprite is about the size of 1x your client.view, and many the different objects are just barely inside your client.view then surely the plane master is being stretched ~9x the size to render all the objects, and that is why KEEP_TOGETHER is performing so poorly in this case?
By "map area" I'm referring to the screen dimensions. E.g., whatever's in view and drawn. The KEEP_TOGETHER texture may exceed that size in your case.

And yes, drawing the shadows/lights to a plane and putting them within a lighting plane would require nested planes. It's not currently possible, but I see value in thinking up ways to make it happen.
Ah yeah, so we're very much on the same page on all of this then.
One thing that occurs to me is that in a case where KEEP_TOGETHER would create a massive texture but that texture is not being transformed, I could probably handle that specially at the rendering level to draw to a map-sized plane.
In response to Lummox JR
What about a new appearance_flag "KEEP_CROPPED" that would exclude that child icon from the bounding box calculation for the temporary texture?

Then for our lighting systems, we would just give the shadow overlays the KEEP_CROPPED flag, and the parent's KEEP_TOGETHER temporary texture would just be sized to the much smaller light source's icon.

It's not as auto-magical as your solution, but would give some finer control (and there might be some other cool hacks we could do with it).
In response to DarkCampainger
Huh. That's an interesting notion.

I kind of hate going too far overboard with new appearance flags; at some point it gets to be excessive. But I'll give it some thought.