sezero / quakespasm

QuakeSpasm -- A modern, cross-platform Quake game engine based on FitzQuake.
https://sourceforge.net/projects/quakespasm/
GNU General Public License v2.0
241 stars 96 forks source link

Increase instruction limit #58

Closed Flecked42 closed 1 year ago

Flecked42 commented 1 year ago

There was some recent discussion about increasing the instruction limit in QS and Ironwail. I figured I'd get the ball rolling.

sezero commented 1 year ago

Can you elaborate?

Boondorl commented 1 year ago

QuakeC's instruction limit is too limiting for modern hardware and can wreak all kinds of havoc in even the most basic scenarios (the example discussed in the mapping Discord was the Thunderbolt's underwater discharge catching too many entities and throwing a runaway loop error). There's a belief that removing this limit (either by increasing it significantly or truly removing it) in Quakespasm will help get the ball rolling for it to be adopted into other ports since it ensures as much mod compatibility as possible across modern ports.

neogeographica commented 1 year ago

Example of hitting the limit I think: https://www.reddit.com/r/quake/comments/13hwwlr/the_pentagram_of_protection_cant_protect_you_from/

Flecked42 commented 1 year ago

I made a test map with 1000 fish.

fish_test.zip

Discharging the LG in the water will crash the map in QuakeSpasm and Ironwail.

It does not crash the map in vkQuake.

sezero commented 1 year ago

I see. It's the runaway loop detection in PR_ExecuteProgram(): https://github.com/sezero/quakespasm/blob/master/Quake/pr_exec.c#L386-L390

vkQuake bumps it from 100000 to 268435456 (0x10000000) which is insane. @andrei-drexler, @temx, @Novum, @Shpoike: What do you guys think?

sezero commented 1 year ago

quakeforge seems to had it bumped to 1000000: doing the same in qs makes it survive that fish_test map, i.e.:

diff --git a/Quake/pr_exec.c b/Quake/pr_exec.c
index 60355d2..ce72138 100644
--- a/Quake/pr_exec.c
+++ b/Quake/pr_exec.c
@@ -383,7 +383,7 @@ void PR_ExecuteProgram (func_t fnum)
     {
    st++;   /* next statement */

-   if (++profile > 100000)
+   if (++profile > 1000000)
    {
        pr_xstatement = st - pr_statements;
        PR_RunError("runaway loop error");

Comments?

Boondorl commented 1 year ago

I don't see any reason to keep the instruction limit as small as possible. Your average CPU nowadays has multiple orders of magnitude more power so I wouldn't let concerns back in 1996 dictate how it should be set in 2023. My biggest concern being constantly needing to expand it as mods get bigger.

Personally, I agree with vkQuake's approach of virtually removing it. I don't think any modder is realistically ever going to need it and it seems to cause more headaches than it does fix things.

sezero commented 1 year ago

I don't see any reason to keep the instruction limit as small as possible. Your average CPU nowadays has multiple orders of magnitude more power so I wouldn't let concerns back in 1996 dictate how it should be set in 2023. My biggest concern being constantly needing to expand it as mods get bigger.

Personally, I agree with vkQuake's approach of virtually removing it. I don't think any modder is realistically ever going to need it and it seems to cause more headaches than it does fix things.

A runaway loop need not happen only because of 1000 fishes being electrocuted in a pool.

Flecked42 commented 1 year ago

1000 fish may be an extreme example but it can happen in real maps these days.

sezero commented 1 year ago

1000 fish may be an extreme example but it can happen in real maps these days.

Yes, and a 1000000 runaway loop limit survives that.

A runaway loop can easily happen because of a badly constructed logic in qc code, a miscompiled progs, and so on. That's why I don't want to bump the limit to insane numbers.

Waiting for others' comments.

Boondorl commented 1 year ago

A runaway loop need not happen only because of 1000 fishes being electrocuted in a pool.

Anything can trigger it because it's not a runaway loop detector, it's a simple instruction limit. This either needs to be fundamentally fixed (much more annoying to implement proper infinite loop detection) or the limit increased significantly to ensure it never gets reached within any reasonable modern usage (which is what vkQuake does). Even at a limit of 0x10000000 a modern CPU will hit that in much less than 1000ms in cases where an actual infinite loop is reached, and ideally devs aren't releasing their mods with infinite loops.

temx commented 1 year ago

100000 is already hit in existing levels: just load Dwell 2's d2m8 and fire the thunderbolt underwater. 0x10000000 is a little too much and causes e.g. trying to start MP in a level without MP starts to hang for several seconds (-game alk1.2 +deathmatch 1 +map start). This was lowered to 0x1000000 in vkQuake 1.30 just to prevent this (the time it takes depends on what the loop is actually doing, but 16M seems reasonable).

sezero commented 1 year ago

Thanks @temx. 1M already seems to handle d2m8, but OK, I'll bump it to 16M shortly.

sezero commented 1 year ago

Fixed in git. Change will be part of 0.96.0 release, whenever that happens.