46 constexpr static std::chrono::duration<double>
min_tick_time{1.0/60};
50 std::unique_ptr<RenderEngine> Renderer;
52 std::unique_ptr<VirtualFilesystem> Resources;
63 virtual void OnFatal(
const std::string_view msg){}
71 virtual bool NeedsAudio()
const {
75 bool GetAudioActive()
const;
78 virtual bool NeedsNetworking()
const {
90 int run(
int argc,
char** argv);
92 constexpr static float evalNormal = 60;
102 const int numcpus = std::thread::hardware_concurrency();
105 tf::Executor executor{
109 std::max<size_t>(std::thread::hardware_concurrency() - 2, 2)
114 NetworkManager networkManager;
116 inline VirtualFilesystem& GetResources(){
117 return *Resources.get();
120 inline RenderEngine& GetRenderEngine(){
121 return *Renderer.get();
125 inline auto& GetAudioPlayer(){
130 inline bool HasRenderEngine(){
132 return static_cast<bool>(Renderer);
151 main_tasks.enqueue(f);
158 float GetCurrentFPSScale()
const{
162 Ref<InputManager> inputManager;
205 std::optional<Ref<World>> GetWorldByName(
const std::string& name);
207 auto GetCurrentRenderWorld() {
214 uint8_t current = 0, inactive = 0, render = 0;
224 static uint8_t RepackAudioBitset(AudioBitsetUnpack values) {
225 uint8_t audioNextBitset = 0;
226 audioNextBitset |= values.current << audioCurrentShift;
227 audioNextBitset |= values.inactive << audioInactiveShift;
228 audioNextBitset |= values.render << audioRenderShift;
230 return audioNextBitset;
233 inline void SwapCurrrentAudioSnapshot(){
235 uint8_t audioCurrentBitset = audioswapbitset.load();
236 uint8_t audioNextBitset = audioCurrentBitset;
238 auto makeNextBitset = [&audioCurrentBitset]{
239 auto indices = UnpackAudioBitset(audioCurrentBitset);
241 std::swap(indices.current, indices.inactive);
243 uint8_t audioNextBitset = RepackAudioBitset(indices);
246 audioNextBitset |= 1 << audioAvailableShift;
248 return audioNextBitset;
250 audioNextBitset = makeNextBitset();
252 while (!audioswapbitset.compare_exchange_weak(audioCurrentBitset, audioNextBitset, std::memory_order_release, std::memory_order_relaxed)){
253 audioNextBitset = makeNextBitset();
256 inline void SwapRenderAudioSnapshotIfNeeded(){
258 auto audioCurrentBitset = audioswapbitset.load();
259 if (NewAudioAvailable(audioCurrentBitset)) {
260 uint8_t audioNextBitset = audioCurrentBitset;
261 auto makeNextBitset = [&audioCurrentBitset] {
262 auto indices = UnpackAudioBitset(audioCurrentBitset);
263 std::swap(indices.inactive, indices.render);
265 uint8_t audioNextBitset = RepackAudioBitset(indices);
266 return audioNextBitset;
268 audioNextBitset = makeNextBitset();
270 while (!audioswapbitset.compare_exchange_weak(audioCurrentBitset, audioNextBitset, std::memory_order_release, std::memory_order_relaxed)){
271 audioNextBitset = makeNextBitset();
275 inline AudioSnapshot* GetCurrentAudioSnapshot(){
276 auto bitset = audioswapbitset.load();
277 auto idx = (bitset & audioCurrentMask) >> audioCurrentShift;
278 auto ptr = &audioSnapshots[idx];
281 inline AudioSnapshot* GetRenderAudioSnapshot(){
282 auto bitset = audioswapbitset.load();
283 auto idx = (bitset & audioRenderMask) >> audioRenderShift;
284 auto ptr = &audioSnapshots[idx];
287 inline static bool NewAudioAvailable(uint8_t currentBitset) {
288 return (currentBitset & audioAvailableMask);
296 float currentScale = 0.01f;
298 Ref<World> renderWorld;
300 ConcurrentQueue<Function<void(
void)>> main_tasks;
302 locked_hashset<Ref<World>,SpinLock> loadedWorlds;
304 Array<AudioSnapshot, 3> audioSnapshots;
306 audioCurrentShift = 0, audioInactiveShift = 2, audioRenderShift = 4, audioAvailableShift = 6,
307 audioCurrentMask = 0b00000011,
308 audioInactiveMask = (audioCurrentMask << audioInactiveShift),
309 audioRenderMask = (audioCurrentMask << audioRenderShift),
310 audioAvailableMask = 1 << audioAvailableShift
313 std::atomic<uint8_t> audioswapbitset = (0 << audioCurrentShift) | (1 << audioInactiveShift) | (2 << audioRenderShift);
318 std::unique_ptr<Window> window;
319 RenderViewCollection mainWindowView;
321 std::vector<RenderViewCollection> xrRenderViewCollections;
324 virtual AppConfig OnConfigure(
int argc,
char** argv) {
return AppConfig{}; }
327 std::unique_ptr<AudioPlayer> player;
342 timePoint lastFrameTime;
343 timeDiff deltaTimeMicroseconds{0};
344 const timeDiff maxTimeStep = std::chrono::milliseconds((
long)1000);
352 const auto& GetMainWindow()
const{