• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DemoBytom / DemoEngine / 19463301765

18 Nov 2025 10:46AM UTC coverage: 26.251% (+1.6%) from 24.615%
19463301765

push

coveralls.net

web-flow
Merge pull request #462 from DemoBytom/feature/dx12-arm64

DirectX12 and Windows on Arm migration

530 of 2019 relevant lines covered (26.25%)

0.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.94
/src/Demo.Engine.Core/Services/MainLoopService.cs
1
// Copyright © Michał Dembski and contributors.
2
// Distributed under MIT license. See LICENSE file in the root for more information.
3

4
using System.Diagnostics;
5
using Demo.Engine.Core.Features.StaThread;
6
using Demo.Engine.Core.Interfaces;
7
using Demo.Engine.Core.Interfaces.Rendering;
8
using Demo.Engine.Core.Interfaces.Rendering.Shaders;
9
using Demo.Engine.Core.Requests.Keyboard;
10
using Demo.Engine.Core.ValueObjects;
11
using MediatR;
12
using Microsoft.Extensions.Logging;
13

14
namespace Demo.Engine.Core.Services;
15

16
internal sealed class MainLoopService
17
    : IMainLoopService,
18
      IAsyncDisposable
19
{
20
    private readonly ILogger<MainLoopService> _logger;
21
    private readonly IStaThreadWriter _staThreadWriter;
22
    private readonly IMediator _mediator;
23
    private readonly IShaderAsyncCompiler _shaderCompiler;
24
    private readonly IFpsTimer _fpsTimer;
25
    private readonly IMainLoopLifetime _mainLoopLifetime;
26
    private readonly ILoopJob _loopJob;
27
    private bool _disposedValue;
28

29
    public Task ExecutingTask { get; }
1✔
30

31
    public MainLoopService(
1✔
32
        ILogger<MainLoopService> logger,
1✔
33
        IStaThreadWriter staThreadWriter,
1✔
34
        IMediator mediator,
1✔
35
        IShaderAsyncCompiler shaderCompiler,
1✔
36
        IFpsTimer fpsTimer,
1✔
37
        IRenderingEngine renderingEngine,
1✔
38
        IMainLoopLifetime mainLoopLifetime,
1✔
39
        ILoopJob loopJob)
1✔
40
    {
41
        _logger = logger;
1✔
42
        _staThreadWriter = staThreadWriter;
1✔
43
        _mediator = mediator;
1✔
44
        _shaderCompiler = shaderCompiler;
1✔
45
        _fpsTimer = fpsTimer;
1✔
46
        _mainLoopLifetime = mainLoopLifetime;
1✔
47
        _loopJob = loopJob;
1✔
48
        ExecutingTask = Task.Factory.StartNew(()
1✔
49
            => DoAsync(
1✔
50
                renderingEngine),
1✔
51
            creationOptions: TaskCreationOptions.LongRunning);
1✔
52
    }
1✔
53

54
    private async Task DoAsync(
55
        IRenderingEngine renderingEngine)
56
    {
57
        _ = await _shaderCompiler.CompileShaders(_mainLoopLifetime.Token);
1✔
58

59
        var keyboardHandle = await _mediator.Send(new KeyboardHandleRequest(), CancellationToken.None);
1✔
60
        var keyboardCharCache = await _mediator.Send(new KeyboardCharCacheRequest(), CancellationToken.None);
1✔
61

62
        var surfaces = new RenderingSurfaceId[]
1✔
63
        {
1✔
64
            await _staThreadWriter.CreateSurface(
1✔
65
                _mainLoopLifetime.Token),
1✔
66
            //await _channelWriter.CreateSurface(
1✔
67
            //    _mainLoopLifetime.Token),
1✔
68
        };
1✔
69

70
        var previous = Stopwatch.GetTimestamp();
1✔
71
        var lag = TimeSpan.Zero;
1✔
72

73
        var msPerUpdate = TimeSpan.FromSeconds(1) / 60;
1✔
74

75
        var doEventsOk = true;
1✔
76

77
        while (
1✔
78
            doEventsOk
1✔
79
            //&& IsRunning
1✔
80
            && !_disposedValue
1✔
81
            && !_mainLoopLifetime.Token.IsCancellationRequested)
1✔
82
        {
83
            var current = Stopwatch.GetTimestamp();
1✔
84
            var elapsed = Stopwatch.GetElapsedTime(previous, current);
1✔
85
            previous = current;
1✔
86
            lag += elapsed;
1✔
87

88
            //process input
89
            // TODO!
90

91
            while (lag >= msPerUpdate)
1✔
92
            {
93
                //Update
94
                // TODO - fix the UPS timer.. somehow :D
95
                _fpsTimer.StopUpdateTimer();
1✔
96
                foreach (var renderingSurfaceId in surfaces)
1✔
97
                {
98
                    if (!renderingEngine.TryGetRenderingSurface(
99
                        renderingSurfaceId,
1✔
100
                        out var renderingSurface))
1✔
101
                    {
102
                        _logger.LogCritical(
×
103
                            "Rendering surface {id} not found!",
×
104
                            renderingSurfaceId);
×
105
                        break;
×
106
                    }
107

108
                    await _loopJob.Update(
1✔
109
                          renderingSurface,
1✔
110
                          keyboardHandle,
1✔
111
                          keyboardCharCache);
1✔
112
                }
113
                lag -= msPerUpdate;
1✔
114
                _fpsTimer.StartUpdateTimer();
1✔
115
            }
116

117
            //Render
118
            foreach (var renderingSurfaceId in surfaces)
1✔
119
            {
120
                doEventsOk &= await _staThreadWriter.DoEventsOk(
1✔
121
                    renderingSurfaceId,
1✔
122
                    _mainLoopLifetime.Token);
1✔
123

124
                using var scope = _fpsTimer.StartRenderingTimerScope(
1✔
125
                    renderingSurfaceId);
1✔
126

127
                _loopJob.Render(
1✔
128
                    renderingEngine,
1✔
129
                    renderingSurfaceId);
1✔
130
            }
131
        }
132
        _mainLoopLifetime.Cancel();
1✔
133
    }
1✔
134

135
    private async ValueTask Dispose(bool disposing)
136
    {
137
        if (!_disposedValue)
1✔
138
        {
139
            if (disposing)
1✔
140
            {
141
            }
142

143
            _disposedValue = true;
1✔
144
            //Make sure the loop finishes
145
            await ExecutingTask;
1✔
146
        }
147
    }
1✔
148

149
    public async ValueTask DisposeAsync()
150
    {
151
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
152
        await Dispose(disposing: true);
1✔
153
        GC.SuppressFinalize(this);
1✔
154
    }
1✔
155
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc