ApplicationLoop
Description
- Derived from
-
Disposable abstract
IEventListenerGeneric<InputEvent>
The ApplicationLoop class implements the main loop of an interactive real-time application.
To run a real-time application, only three steps are necessary:
-
Create an ApplicationLoop object.
-
Repeatedly call MainLoop until it returns
false
. -
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
ProfileApplication
A profiler value that groups common application-level values.
- See also
-
ApplicationLoop.ProfileApplicationCpuRate
ApplicationLoop.ProfileApplicationCpuTime
ApplicationLoop.ProfileApplicationCpuTotal
ApplicationLoop.ProfileApplicationCpuUsed
ApplicationLoop.ProfileApplicationGpuRate
ApplicationLoop.ProfileApplicationGpuTime
ApplicationLoop.ProfileApplicationMemory
ProfileApplicationCpuTime
The frame time that has been passed to IUpdateableFrameTime.UpdateFrameTime.
ProfileCpuTimePresent
CPU time spent calling ISwapChain.PresentBegin and ISwapChain.PresentEnd, in milliseconds.
ProfileCpuTimeUpdate
CPU time spent calling IUpdateableFrameTime.UpdateFrameTime, in milliseconds.
ProfileCpuTimeWait
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.
- See also
Public / Constructors
ApplicationLoop
2 overloads
Creates a new instance of ApplicationLoop.
Creates a new instance of ApplicationLoop.
Public / Methods
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.
MainLoop
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:
-
I
: IInputConsumer.ConsumeInput
U
: IUpdateableFrameTime.UpdateFrameTime / IApplicationWindow.ProcessSystemMessages
The application consumes external stimuli and updates its internal state accordingly. Usually, a new frame will only be rendered if the application state has changed. -
RP
: IRenderPreparable.RenderPrepare
The application performs all pre-rendering work that does not require GPU interaction. -
R
: IRenderable.Render
The application renders the current frame by issuing render commands, which are processed asynchronously by the GPU. -
F
: IRenderTarget.Finish
The application finishes rendering to the render target of its swap chain for the current frame. The GPU may now prepare presentation of the current frame asynchronously, for example by resolving a multi-sampled render target into a backbuffer. -
P
: ISwapChain.PresentBegin
Q
: ISwapChain.PresentEnd
The current frame is ready and may be presented. Presentation will be performed asynchronously, for example by flipping back buffers after waiting for vertical synchronization.
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).
MainLoop_Initialize
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.
MainLoop_Render
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
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
ContextFactories
Specifies the graphics context factories to use.
Setting this property will also reset CurrentContextIndex to -1
.
ContextFactory
Specifies the graphics context factory to use.
Setting this property will also reset CurrentContextIndex to -1
.
CurrentContextIndex
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.
- See also
FrameIndex
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.
IsHeadless
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:
-
Set the ContextFactories property.
-
Set the ContextFactory property.
-
Set the CurrentContextIndex property.
TimeIndex
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.