FPS label formatting + odd behaviour?

I’m new to CGE and not a particularly accomplished programmer.

//LabelFps.Caption := 'FPS: ' + Container.Fps.ToString;
    LabelFps.Caption := Format('FPS: %.2f', [Extended(Container.Fps)]);
    OutputDebugString(PChar('FPS raw value: ' + Container.Fps.ToString));

I was messing around to see if there was another way of updating the FPS shown on screen.

But whilst doing so and performing debug output I noticed that my frame rate was increasing.

Normal FPS captioning = 65 FPS seems to be the target CGE ‘tries’ to reach.
Adding debug line = up and down but as high as 85
My broken captioning + debug = can hit 90
Broken captioning alone = unknown

This is not the max FPS which is always many hundreds of FPS, so something is interfering with the ‘normal’ of 65ish?

Does anyone know why my modified caption only ever shows 0.00?

Container.FPS is a class, not a number so you cannot typecast it as extended. I use this

var fps : single;
begin
fps := Container.Fps.RealFps;
FPSLabel.Caption := Format('%2.0ffps', [fps]);  
...
1 Like

As for displaying FPS:

  • You have to watch out for types when using Format. See also " 2.10. Converting to a string" in Modern Object Pascal Introduction for Programmers | Castle Game Engine .

  • As @edj mentioned, Container.Fps is an instance of a class. You cannot typecast it to Extended (it may only compile by accident on platforms where pointer size matches Extended size). You cannot display it using LabelFps.Caption := Format('FPS: %.2f', [Extended(Container.Fps)]);.

  • Just use Container.Fps.ToString. Like shown in “new project” templates:

    LabelFps.Caption := 'FPS: ' + Container.Fps.ToString;
    

    If for some reason you would like to use Format, then use %s. See documentation of Format (Format in FPC, Format in Delphi) to understand how it works. Like

    LabelFps.Caption := Format('FPS: %s', [Container.Fps.ToString]);
    
  • The %f can be used to format floats, like Container.Fps.RealFps.

As for “max” or “target” FPS in CGE and why it changes:

  • Please read “Watch FPS (Frames Per Second)” in Optimization and profiling | Manual | Castle Game Engine – we wrote there various details why FPS are not so obvious to interpret :slight_smile:

  • We don’t have any “target CGE ‘tries’ to reach”. In CGE, we render as far as we can, however

    • We have Application.LimitFps, default 120, to cap this FPS at 120 – because you usually don’t need more, and it would waste the CPU (and thus battery on laptops).
    • Your monitor has usually a refresh rate, like 60, and when “vertical synchronization” is on (it’s a setting of your system), then in practice the FPS are limited by this.
  • Merely displaying a label should definitely not have a visible effect on the FPS :slight_smile: But I’d have to see the exact testcase to judge, is there something more going on.

Thankyou both for the consideration and clarification.

As for the FPS I looked at my screen settings and saw my refresh rate was 165hz, normally the engine was serving me with 64.xx. When I changed screen refresh rate code changes do not affect me FPS of 60 (only render 75ish?) as would be expected.

When on 165hz adding the following code definitely changes the FPS.

OutputDebugString(PChar('FPS raw value: ' + Container.Fps.ToString));

This is in the normal .Update of an otherwise blank project, Uses Windows was added to the interface section. My IDE is Delphi community edition up to date version on Windows 11 64bit.

FPS goes up on average, even approaching 100 (only render many hundreds).

As it is a blank project I cant say much more, but it is a little strange to go from 64ish to up to 80 for adding a debug line.

That is weird indeed, and not something I reproduce. Esp. since OutputDebugString doesn’t even do anything for display – it just sends the message to Windows-specific event log. Doing this should not change the FPS.

And a blank game should just have the same FPS as your graphic card allows. Look into your graphic card setting,

  • is there anything capping FPS, at 80 or such? Maybe at half refresh rate, 165 / 2 = 82.5?
  • Do you have vertical sync enabled or disabled?
  • Does changing ApplicationProperties.LimitFPS := 0 in your ApplicationInitialize (add CastleApplicationProperties to the uses clause to have ApplicationProperties available) change anything?

These are admittedly just “blind guesses, things I would try”. Maybe they will reveal something :slight_smile:

BTW, our WritelnLog also sends message to a Windows OutputDebugString when compiled with Delphi, for Windows, in debug mode. If you do OutputDebugString yourself just to see the message in Delphi event log – you don’t need to do this, just use our WritelnLog and WritelnWarning (see Logging | Manual | Castle Game Engine ) which are cross-platform and will automatically send to event log with Delphi + Windows + debug. See https://github.com/castle-engine/castle-engine/blob/9f7dd80ce0e82635a82ab3b87da5f8bcc7457c48/src/base/castlelog.pas#L23 where this is implemented :slight_smile:

I can confirm the Fps is quite random on Windows. It’s not Delphi-related as it happens on Lazarus/FPC too, on 2 different machines and monitors. However, the Fps goes up to 120 when needed - e.g. in a project that uses fancy graphics. So I don’t think it’s an issue with CGE, or a bug. The Fps just adapts to what’s happening.

Maybe that’s the hint? Sending message (or rather receiving it from a callback when event log is accessed) forces Windows to call WndProc. Otherwise, it seems, Windows allocates time for the app only when it’s worth wasting the energy. From what I remember Linux does multitasking quite differently, equally I think.

But there are also settings like dynamic refresh rate, energy saving and other stuff that can be controlled by GPU or OS. I think I’ve tried them all, having everything on & off, including power saving and game-mode. It’s just Windows :slight_smile:

These things should not matter, as we (by default, when Window.AutoRedisplay:=true) do not tell OS to “wake us up when it’s convenient” :slight_smile: Rather, we do update, render frame, wait for swap buffers, and then go to the next frame (as soon as possible, unless ApplicationProperties.LimitFPS mechanism tells us to wait a bit). We never wait for the windows message to “wake us up”.

The multi-tasking approaches of different OSes should not matter, unless your system is really seriously overloaded with other busy tasks. In normal cases, esp. if we render sthg trivial (like black screen) our process has well enough time to do everything described above, and we mostly spend time in “waiting for swap buffers”, which is OK.

The FPS should match the monitor refresh rate (like 60 on older monitors) if vertical sync is on (which it is, by default), that’s what I observe on systems I have, both Windows and Linux, both Delphi and FPC.

Well, anyhow, obviously I don’t understand something (since I cannot explain why doing OutputDebugString makes a difference), so there may be an error in what I claim above :slight_smile:

Note that everything written above applies to “real FPS”. Interpreting the “only render FPS” is a more tricky business, as documented on Optimization and profiling | Manual | Castle Game Engine , and usually can be ignored.