Skip to content

Commit 9058726

Browse files
committed
Do SDL3 gamepad init async.
It is too slow to do synchronous.
1 parent c3e250d commit 9058726

File tree

1 file changed

+59
-7
lines changed

1 file changed

+59
-7
lines changed

application/platforms/application_sdl3.cpp

+59-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <SDL3/SDL.h>
2424
#include <SDL3/SDL_vulkan.h>
25+
#include <atomic>
2526

2627
#include "application.hpp"
2728
#include "application_wsi.hpp"
@@ -102,6 +103,49 @@ struct WSIPlatformSDL : GraniteWSIPlatform
102103
{
103104
}
104105

106+
void run_gamepad_init()
107+
{
108+
Util::Timer tmp_timer;
109+
tmp_timer.start();
110+
111+
if (SDL_Init(SDL_INIT_GAMEPAD) < 0)
112+
{
113+
LOGE("Failed to init gamepad.\n");
114+
return;
115+
}
116+
117+
LOGI("SDL_Init(GAMEPAD) took %.3f seconds async.\n", tmp_timer.end());
118+
119+
push_task_to_main_thread([this]() {
120+
if (!pad.init(get_input_tracker(), [](std::function<void ()> func) { func(); }))
121+
LOGE("Failed to init gamepad tracker.\n");
122+
123+
gamepad_init_async.store(true, std::memory_order_release);
124+
});
125+
}
126+
127+
void kick_gamepad_init()
128+
{
129+
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
130+
// Adding gamepad events will make main loop spin without waiting.
131+
SDL_SetHint(SDL_HINT_AUTO_UPDATE_JOYSTICKS, "0");
132+
133+
// Enumerating gamepads can be extremely slow in some cases. Do this async.
134+
// Gamepad interface is very async friendly.
135+
136+
gamepad_init_async = false;
137+
138+
if (auto *tg = GRANITE_THREAD_GROUP())
139+
{
140+
gamepad_init_task = tg->create_task([this]() { run_gamepad_init(); });
141+
gamepad_init_task->set_desc("SDL init gamepad");
142+
gamepad_init_task->set_task_class(TaskClass::Background);
143+
gamepad_init_task->flush();
144+
}
145+
else
146+
run_gamepad_init();
147+
}
148+
105149
bool init(const std::string &name, unsigned width_, unsigned height_)
106150
{
107151
request_tear_down.store(false);
@@ -126,16 +170,15 @@ struct WSIPlatformSDL : GraniteWSIPlatform
126170

127171
Util::Timer tmp_timer;
128172
tmp_timer.start();
129-
if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_GAMEPAD | SDL_INIT_VIDEO) < 0)
173+
if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO) < 0)
130174
{
131175
LOGE("Failed to init SDL.\n");
132176
return false;
133177
}
134178
LOGI("SDL_Init took %.3f seconds.\n", tmp_timer.end());
135179

136-
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
137-
// Adding gamepad events will make main loop spin without waiting.
138-
SDL_SetHint(SDL_HINT_AUTO_UPDATE_JOYSTICKS, "0");
180+
kick_gamepad_init();
181+
139182
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_FALSE);
140183
SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_FALSE);
141184

@@ -174,7 +217,7 @@ struct WSIPlatformSDL : GraniteWSIPlatform
174217
application.info.pApplicationName = application.name.empty() ? "Granite" : application.name.c_str();
175218
application.info.apiVersion = VK_API_VERSION_1_1;
176219

177-
return pad.init(get_input_tracker(), [](std::function<void ()> func) { func(); });
220+
return true;
178221
}
179222

180223
const VkApplicationInfo *get_application_info() override
@@ -268,7 +311,9 @@ struct WSIPlatformSDL : GraniteWSIPlatform
268311
std::lock_guard<std::mutex> holder{get_input_tracker().get_lock()};
269312
flush_deferred_input_events();
270313
process_events_async_thread();
271-
pad.update(get_input_tracker());
314+
315+
if (gamepad_init_async.load(std::memory_order_acquire))
316+
pad.update(get_input_tracker());
272317
get_input_tracker().dispatch_current_state(get_frame_timer().get_frame_time());
273318
}
274319

@@ -278,7 +323,8 @@ struct WSIPlatformSDL : GraniteWSIPlatform
278323
begin_async_input_handling();
279324
{
280325
process_events_async_thread();
281-
pad.update(get_input_tracker());
326+
if (gamepad_init_async.load(std::memory_order_acquire))
327+
pad.update(get_input_tracker());
282328
}
283329
end_async_input_handling();
284330
get_input_tracker().dispatch_current_state(0.0, override_handler);
@@ -316,8 +362,12 @@ struct WSIPlatformSDL : GraniteWSIPlatform
316362

317363
~WSIPlatformSDL()
318364
{
365+
if (gamepad_init_task)
366+
gamepad_init_task->wait();
367+
319368
if (window)
320369
SDL_DestroyWindow(window);
370+
321371
pad.close();
322372
SDL_Quit();
323373
}
@@ -656,6 +706,8 @@ struct WSIPlatformSDL : GraniteWSIPlatform
656706
uint32_t wake_event_type = 0;
657707
Options options;
658708
std::string clipboard;
709+
TaskGroupHandle gamepad_init_task;
710+
std::atomic<bool> gamepad_init_async;
659711

660712
struct
661713
{

0 commit comments

Comments
 (0)