KiCad PCB EDA Suite
Loading...
Searching...
No Matches
swapchain_controller.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef RHI_SWAPCHAIN_CONTROLLER_H
21#define RHI_SWAPCHAIN_CONTROLLER_H
22
24
25#include <chrono>
26#include <cstdint>
27
28
29namespace KIGFX
30{
31
32class RENDER_THREAD;
33class FRAME_MAILBOX;
34
35
37{
38 bool shouldLog = false;
39 int phase = -1;
40 uint64_t stalledGenerations = 0;
41 std::chrono::milliseconds stallAge{ 0 };
42};
43
44
46{
47 using CLOCK = std::chrono::steady_clock;
48
49 int observedPhase = -1;
51 CLOCK::time_point phaseStartTime;
52 CLOCK::time_point lastLogTime;
53};
54
55
58 int aPhase,
59 uint64_t aGeneration,
60 RHI_PHASE_STALL_TRACKER::CLOCK::time_point aNow,
61 std::chrono::milliseconds aStallThreshold = std::chrono::milliseconds( 1000 ),
62 uint64_t aGenerationThreshold = 60,
63 std::chrono::milliseconds aRepeatThreshold = std::chrono::milliseconds( 1000 ) )
64{
66 result.phase = aPhase;
67
68 bool firstObservation = aTracker.phaseStartTime.time_since_epoch().count() == 0;
69 bool phaseChanged = aTracker.observedPhase != aPhase;
70 bool generationRewound = aGeneration < aTracker.generationAtPhaseStart;
71
72 if( firstObservation || phaseChanged || generationRewound )
73 {
74 aTracker.observedPhase = aPhase;
75 aTracker.generationAtPhaseStart = aGeneration;
76 aTracker.phaseStartTime = aNow;
77 aTracker.lastLogTime = {};
78 return result;
79 }
80
81 result.stalledGenerations = aGeneration - aTracker.generationAtPhaseStart;
82 result.stallAge = std::chrono::duration_cast<std::chrono::milliseconds>(
83 aNow - aTracker.phaseStartTime );
84
85 if( result.stalledGenerations < aGenerationThreshold
86 || result.stallAge < aStallThreshold )
87 {
88 return result;
89 }
90
91 if( aTracker.lastLogTime.time_since_epoch().count() != 0
92 && std::chrono::duration_cast<std::chrono::milliseconds>(
93 aNow - aTracker.lastLogTime ) < aRepeatThreshold )
94 {
95 return result;
96 }
97
98 result.shouldLog = true;
99 aTracker.lastLogTime = aNow;
100 return result;
101}
102
109{
110public:
111 SWAPCHAIN_CONTROLLER( RENDER_THREAD& aRenderThread, RHI_WINDOW_ID aWindowId );
113
116
123 bool OnPaint( const RHI_NATIVE_WINDOW_HANDLE& aHandle,
124 uint32_t aWidth, uint32_t aHeight, float aDpiScale = 1.0f );
125
129 bool OnResize( uint32_t aWidth, uint32_t aHeight, float aDpiScale = 1.0f );
130
134 bool OnClose();
135
142 bool OnCloseSync(
143 std::chrono::milliseconds aTimeout = std::chrono::milliseconds( 2000 ) );
144
145 void SetFrameMailbox( FRAME_MAILBOX* aMailbox ) { m_frameMailbox = aMailbox; }
146
148 void SetRefreshRate( float aHz ) { m_refreshHz = aHz; }
149
150private:
153 bool m_created = false;
154 uint64_t m_generation = 0;
155 uint32_t m_width = 0;
156 uint32_t m_height = 0;
157 float m_dpiScale = 1.0f;
158 float m_refreshHz = 0.0f;
162};
163
164
165} // namespace KIGFX
166
167
168#endif // RHI_SWAPCHAIN_CONTROLLER_H
Lock-free single-slot mailbox carrying frame state from the main thread to the render thread.
Thread that owns the RHI device.
SWAPCHAIN_CONTROLLER(RENDER_THREAD &aRenderThread, RHI_WINDOW_ID aWindowId)
SWAPCHAIN_CONTROLLER(const SWAPCHAIN_CONTROLLER &)=delete
void SetRefreshRate(float aHz)
Display refresh rate sent with each frame request, 0 when unknown.
RHI_PHASE_STALL_TRACKER m_phaseStallTracker
void SetFrameMailbox(FRAME_MAILBOX *aMailbox)
bool OnResize(uint32_t aWidth, uint32_t aHeight, float aDpiScale=1.0f)
SWAPCHAIN_CONTROLLER & operator=(const SWAPCHAIN_CONTROLLER &)=delete
bool OnCloseSync(std::chrono::milliseconds aTimeout=std::chrono::milliseconds(2000))
Close and wait for the render thread to release the window's GPU resources, so the native window can ...
bool OnPaint(const RHI_NATIVE_WINDOW_HANDLE &aHandle, uint32_t aWidth, uint32_t aHeight, float aDpiScale=1.0f)
The first call creates the swapchain.
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:30
RHI_PHASE_STALL_RESULT EvaluateRenderThreadPhaseStall(RHI_PHASE_STALL_TRACKER &aTracker, int aPhase, uint64_t aGeneration, RHI_PHASE_STALL_TRACKER::CLOCK::time_point aNow, std::chrono::milliseconds aStallThreshold=std::chrono::milliseconds(1000), uint64_t aGenerationThreshold=60, std::chrono::milliseconds aRepeatThreshold=std::chrono::milliseconds(1000))
uint32_t RHI_WINDOW_ID
Routes control commands to a swapchain.
std::chrono::milliseconds stallAge
std::chrono::steady_clock CLOCK
Platform-agnostic wrapper for a native window handle.
Definition rhi_surface.h:45
wxString result
Test unit parsing edge cases and error handling.