ApplicationLoop

Description

sealed class Tinman.Engine.Application.ApplicationLoop

The ApplicationLoop class implements the main loop of an interactive real-time application.

To run a real-time application, only three steps are necessary:

  1. Create an ApplicationLoop object.

  2. Repeatedly call MainLoop until it returns false.

  3. Dispose the ApplicationLoop loop object.

Proper callbacks to the IApplication object will be made automatically.

The IEventListenerGeneric.NotifyEventGeneric method can be used to manually inject input events to the application loop. The events will be processed the next time MainLoop is called.

Public / Constants

Profile​Application​Cpu​Rate


public static readonly attribute ProfileApplicationCpuRate → (ProfilerValue)

CPU frame rate.

Profile​Application​Cpu​Total


public static readonly attribute ProfileApplicationCpuTotal → (ProfilerValue)

CPU usage of system.

Profile​Application​Cpu​Used


public static readonly attribute ProfileApplicationCpuUsed → (ProfilerValue)

CPU usage of application.

Profile​Application​Gpu​Rate


public static readonly attribute ProfileApplicationGpuRate → (ProfilerValue)

GPU frame rate.

Profile​Application​Gpu​Time


public static readonly attribute ProfileApplicationGpuTime → (ProfilerValue)

GPU time spent for the last frame (see IGraphicsTimer.Result).

Profile​Application​Memory


public static readonly attribute ProfileApplicationMemory → (ProfilerValue)

Relative amount of memory used by application.

Profile​Cpu​Time​Input


public static readonly attribute ProfileCpuTimeInput → (ProfilerValue)

CPU time spent calling IInputConsumer.ConsumeInput, in milliseconds.

Profile​Cpu​Time​Prepare


public static readonly attribute ProfileCpuTimePrepare → (ProfilerValue)

CPU time spent calling IRenderPreparable.RenderPrepare, in milliseconds.

Profile​Cpu​Time​Present


public static readonly attribute ProfileCpuTimePresent → (ProfilerValue)

CPU time spent calling ISwapChain.PresentBegin and ISwapChain.PresentEnd, in milliseconds.

Profile​Cpu​Time​Render


public static readonly attribute ProfileCpuTimeRender → (ProfilerValue)

CPU time spent calling IRenderable.Render, in milliseconds.

Profile​Cpu​Time​Update


public static readonly attribute ProfileCpuTimeUpdate → (ProfilerValue)

CPU time spent calling IUpdateableFrameTime.UpdateFrameTime, in milliseconds.

Profile​Cpu​Time​Wait


public static readonly attribute ProfileCpuTimeWait → (ProfilerValue)

CPU time spent with house-keeping while beginning / ending render cycles with IGraphicsContext (milli-seconds) and with waiting for the GPU via IGraphicsFence.Wait and IGraphicsContext.Wait.

Profile​Memory​Total


public static readonly attribute ProfileMemoryTotal → (ProfilerValue)

Amount of available system memory.

Profile​Memory​Used


public static readonly attribute ProfileMemoryUsed → (ProfilerValue)

Amount of memory used by application.

Public / Constructors

Application​Loop

2 overloads


public constructor ApplicationLoop1 → (3)

application in : IApplication own

[not-null]
The application to run.

window in : IApplicationWindow own

[not-null]
The application window to use.

graphicsContextFactory in : IGraphicsContextFactory

[not-null]
The graphics context factory to use.

Creates a new instance of ApplicationLoop.


public constructor ApplicationLoop2 → (3)

application in : IApplication own

[not-null]
The application to run.

window in : IApplicationWindow own

[not-null]
The application window to use.

graphicsContextFactories in : IVectorConst<IGraphicsContextFactory>

[not-empty]
The graphics context factories to use.

Creates a new instance of ApplicationLoop.

Public / Methods

Invalidate​Frame


public method InvalidateFrame → ()

Forces a new frame to be rendered when MainLoop is called.

This method only needs to be called in special cases. For example, when an application is embedded in a windowing framework that does not use double-buffering and a new paint cycle is triggered (because the most recently rendered frame has been invalidated), while the ApplicationLoop returns ApplicationLoopResult.Idle or ApplicationLoopResult.Limit because it still believes that the most recently rendered frame would still be valid.

Main​Loop


public method MainLoop → (1)

render opt : bool = true

If set to true, MainLoop_Render will be called automatically if necessary. Otherwise, the calling code is responsible for doing so (see return value).

returns → ApplicationLoopResult

The result code. If ApplicationLoopResult.Render is returned and render opt was false, the calling code must call MainLoop_Render once, before calling MainLoop again.

Runs a single iteration of the application main loop.

Repeatedly calling the MainLoop method according to the returned ApplicationLoopResult values will establish the following CPU/GPU timelines:

     frame #0         frame #1         frame #2         frame #3
CPU: [I U RP R F P] Q [I U RP R F P] Q [I U RP R F P] Q [I U RP R F P] Q ...
                _____sync_____/  _____sync_____/  _____sync_____/
               /                /                /
GPU:          [R   F   P  ]    [R   F   P  ]    [R   F   P  ] ...
              frame #0         frame #1         frame #2

where the mnemonic have the following meaning:

The CPU and GPU timelines are allowed to progress independently on each other. When using GpuUpdateFlag.NoOverwrite to update GPU resources, it may be necessary to synchronize with the GPU, using IGraphicsFence objects (see sync in the above figure).

Main​Loop_​Initialize


public method MainLoop_Initialize → ()

returns → ApplicationLoopResult

The status of the graphics subsystem:
ApplicationLoopResult.Idle : no graphics context yet, the application is inactive.
ApplicationLoopResult.Headless : graphics context is unavailable (bad configuration, runtime error, etc.)
ApplicationLoopResult.Render : graphics context is ready, see CurrentContext.

Initializes the graphics context, if necessary.

This method is called automatically from MainLoop and does not need to be called explicitly. It may be called to force creation of the graphics context. Calling this method more than once is allowed but has no effect.

Main​Loop_​Render


public method MainLoop_Render → ()

returns → bool

true if the necessary render cycle has been performed,
false if no render cycle has been performed, either because none was necessary or the graphics context has become invalid.

Performs a render cycle, if necessary.

This method is usually called automatically from MainLoop and does not need to be called explicitly. Calling this method when no render cycle needs to be performed is allowed but has no effect.

Run


[OwnerThis]
public method Run → (1)

sleepOnIdle in : bool

Honour ApplicationLoopResult.Idle by sleeping for a short time?

Runs the application loop until the application terminates.

This ApplicationLoop object will have been disposed when this method returns. To replace this method with an own loop, the following code fragment can be used:

ApplicationLoop applicationLoop; // [!]

applicationLoop = ...;
try
{
  while (true)
  {
    switch (applicationLoop.MainLoop())
    {
      case ApplicationLoopResult.Idle:
        Thread.Sleep(sleepOnIdle ? 1 : 0);
        break;

      case ApplicationLoopResult.Headless:
        // Log message: "Lost graphics context."
        return;

      case ApplicationLoopResult.Quit:
        return;
    }
  }
}
finally
{
  applicationLoop.Dispose();
}

Public / Attributes

Context​Factories


public attribute ContextFactories → (set)

value : IVectorConst<IGraphicsContextFactory>

[not-null]
The list of graphics context factories.

Specifies the graphics context factories to use.

Setting this property will also reset CurrentContextIndex to -1.

Context​Factory


public attribute ContextFactory → (set)

value : IGraphicsContextFactory

[not-null]
The graphics context factory.

Specifies the graphics context factory to use.

Setting this property will also reset CurrentContextIndex to -1.

Current​Context


public attribute CurrentContext → (get)

value : IGraphicsContext

The current graphics context or null.

The current graphics context.

Current​Context​Index


public attribute CurrentContextIndex → (get,set)

value : int32

The graphics context factory index. If negative, a suitable graphics context factory will be chosen from ContextFactories automatically, by using IGraphicsContextFactory.CanCreateGraphicsContext and IGraphicsContextFactory.CanCreateSwapChain.

The current graphics context factory index.

Setting this property will also trigger a graphics context reset. While in headless state, this property will return -1. After the MainLoop method has created a graphics context, this property will return the corresponding factory index.

Frame​Index


public attribute FrameIndex → (get)

value : int32

[>=0]
The frame index.

Returns the current frame index.

The frame index counts the number of calls to ISwapChain.PresentBegin that have been made from inside the MainLoop. Frames that do not require rendering are counted, too.

Is​Headless


public attribute IsHeadless → (get)

value : bool

true if the application loop is in the headless state,
false if it is not.

Is this application loop in the headless state?

The application loop will be in the headless state as long as there is no graphics context. The transition to the headless state is indicated by the MainLoop returning the ApplicationLoopResult.Headless value. While headless, the application will be suspended, i.e. no callbacks will be performed. To get out of the headless state, one of the following actions must be taken:

Time​Index


public attribute TimeIndex → (get)

value : float64

[>=0]
The running time, in seconds.

Returns the current time index.

The time index is the update time that has been accumulated in the MainLoop. This value correlates to the calls to IUpdateableFrameTime.UpdateFrameTime.

Logging

Logger


public static readonly attribute Logger → (ILogger)

The logger object of this class.