mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-10-25 07:16:12 -04:00
fix gx worker exit, wrap and frame end
This commit is contained in:
+1
-1
Submodule aurora-main updated: 78850a8d30...ff0b617a92
@@ -134,6 +134,7 @@ inline void ApplyPendingMkwDynamicAspectSurface() {
|
||||
|
||||
void GxWorkerBeginFrame();
|
||||
void GxWorkerEndFrame(AuroraImguiFrame* imgui);
|
||||
void SetAuroraFrameGxBegun(bool begun);
|
||||
|
||||
inline bool BeginAuroraFrame() {
|
||||
if (GxWorker::ShouldDefer()) {
|
||||
@@ -149,6 +150,7 @@ inline bool BeginAuroraFrame() {
|
||||
if (!aurora_begin_frame()) {
|
||||
return false;
|
||||
}
|
||||
SetAuroraFrameGxBegun(true);
|
||||
ApplyPendingMkwDynamicAspectSurface();
|
||||
return true;
|
||||
}
|
||||
@@ -163,6 +165,7 @@ inline void EndAuroraFrame() {
|
||||
return;
|
||||
}
|
||||
aurora_end_frame();
|
||||
SetAuroraFrameGxBegun(false);
|
||||
}
|
||||
|
||||
// Poll Aurora events and update cached window/framebuffer dimensions.
|
||||
|
||||
@@ -28,6 +28,8 @@ void FlushFifo();
|
||||
// Starts the worker unless [video] gx_worker disables it. Call once Aurora is up.
|
||||
void Start();
|
||||
void Stop();
|
||||
// Stops without running queued work; bounded, for fatal exits.
|
||||
void Abandon();
|
||||
|
||||
inline bool Active() noexcept { return detail::g_active.load(std::memory_order_relaxed); }
|
||||
inline bool OnWorker() noexcept { return detail::t_onWorker; }
|
||||
|
||||
@@ -112,26 +112,29 @@ void EnsureAuroraFrameActive() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
// GX worker only.
|
||||
bool g_workerFrameBegun = false;
|
||||
// Whether the GX half of the current frame has begun, on either path. Inline frame calls only run
|
||||
// after a sync, so the ring orders every access.
|
||||
bool g_frameGxBegun = false;
|
||||
}
|
||||
|
||||
void SetAuroraFrameGxBegun(bool begun) { g_frameGxBegun = begun; }
|
||||
|
||||
void GxWorkerBeginFrame() {
|
||||
// gfx::begin_frame can briefly fail to map a staging buffer; retry like the inline path does.
|
||||
const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
|
||||
while (!(g_workerFrameBegun = aurora_begin_frame_gx()) && std::chrono::steady_clock::now() < deadline) {
|
||||
while (!(g_frameGxBegun = aurora_begin_frame_gx()) && std::chrono::steady_clock::now() < deadline) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
if (!g_workerFrameBegun) {
|
||||
if (!g_frameGxBegun) {
|
||||
RT_LOGF(RT_TAG_GX, "GX worker could not begin an aurora frame\n");
|
||||
}
|
||||
}
|
||||
|
||||
void GxWorkerEndFrame(AuroraImguiFrame* imgui) {
|
||||
if (g_workerFrameBegun) {
|
||||
if (g_frameGxBegun) {
|
||||
aurora_end_frame_gx(imgui);
|
||||
} else {
|
||||
aurora_release_imgui_frame(imgui);
|
||||
}
|
||||
g_workerFrameBegun = false;
|
||||
g_frameGxBegun = false;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ std::mutex g_tailMutex;
|
||||
std::condition_variable g_tailCv;
|
||||
void (*g_waitCallback)() = nullptr;
|
||||
std::atomic<bool> g_stop{false};
|
||||
std::atomic<bool> g_abandon{false};
|
||||
std::atomic<bool> g_exited{false};
|
||||
std::thread* g_thread = nullptr;
|
||||
std::vector<uint8_t> g_fifoBytes;
|
||||
|
||||
@@ -139,6 +141,13 @@ void ReplayFifo(void* payload) {
|
||||
|
||||
void WorkerMain() {
|
||||
detail::t_onWorker = true;
|
||||
struct SignalExit {
|
||||
~SignalExit() {
|
||||
std::lock_guard lock{g_tailMutex};
|
||||
g_exited.store(true, std::memory_order_release);
|
||||
g_tailCv.notify_all();
|
||||
}
|
||||
} signalExit;
|
||||
AuroraSetGxProducerThread();
|
||||
#if defined(_WIN32)
|
||||
SetThreadDescription(GetCurrentThread(), L"GX worker");
|
||||
@@ -173,6 +182,9 @@ void WorkerMain() {
|
||||
continue;
|
||||
}
|
||||
while (tail != head) {
|
||||
if (g_abandon.load(std::memory_order_acquire)) {
|
||||
return;
|
||||
}
|
||||
uint8_t* record = g_ring + tail % kCapacity;
|
||||
const Header* header = reinterpret_cast<const Header*>(record);
|
||||
if (header->run != nullptr) {
|
||||
@@ -205,15 +217,16 @@ void* Reserve(size_t payloadSize, void (*run)(void*)) {
|
||||
size_t offset = static_cast<size_t>(g_write % kCapacity);
|
||||
const size_t remaining = kCapacity - offset;
|
||||
if (total > remaining) {
|
||||
WaitForSpace(remaining + total);
|
||||
WaitForSpace(remaining);
|
||||
auto* wrap = reinterpret_cast<Header*>(g_ring + offset);
|
||||
wrap->run = nullptr;
|
||||
wrap->size = static_cast<uint32_t>(remaining);
|
||||
g_write += remaining;
|
||||
// Publish the skip so the worker can drain past it while we wait for the front.
|
||||
Commit();
|
||||
offset = 0;
|
||||
} else {
|
||||
WaitForSpace(total);
|
||||
}
|
||||
WaitForSpace(total);
|
||||
auto* header = reinterpret_cast<Header*>(g_ring + offset);
|
||||
header->run = run;
|
||||
header->size = static_cast<uint32_t>(total);
|
||||
@@ -303,6 +316,8 @@ void Start() {
|
||||
}
|
||||
g_fifoBytes.reserve(kFifoFlushBytes + 4096);
|
||||
g_stop.store(false, std::memory_order_relaxed);
|
||||
g_abandon.store(false, std::memory_order_relaxed);
|
||||
g_exited.store(false, std::memory_order_relaxed);
|
||||
g_thread = new std::thread(WorkerMain);
|
||||
detail::g_active.store(true, std::memory_order_release);
|
||||
RT_LOGF(RT_TAG_GX, "GX worker started\n");
|
||||
@@ -325,4 +340,32 @@ void Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
void Abandon() {
|
||||
if (!Active() || detail::t_onWorker) {
|
||||
return;
|
||||
}
|
||||
detail::g_active.store(false, std::memory_order_release);
|
||||
g_abandon.store(true, std::memory_order_release);
|
||||
g_stop.store(true, std::memory_order_release);
|
||||
{
|
||||
std::lock_guard lock{g_headMutex};
|
||||
g_headCv.notify_one();
|
||||
}
|
||||
bool exited = false;
|
||||
{
|
||||
std::unique_lock lock{g_tailMutex};
|
||||
exited = g_tailCv.wait_for(lock, std::chrono::seconds{2},
|
||||
[] { return g_exited.load(std::memory_order_acquire); });
|
||||
}
|
||||
if (g_thread != nullptr) {
|
||||
if (exited) {
|
||||
g_thread->join();
|
||||
delete g_thread;
|
||||
} else {
|
||||
g_thread->detach();
|
||||
}
|
||||
g_thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GxWorker
|
||||
|
||||
@@ -765,6 +765,8 @@ extern "C" void DumpHostStackTraceForRuntimeHelper() {
|
||||
|
||||
void MarkFatalErrorReported() {
|
||||
g_fatalErrorReported.store(true, std::memory_order_release);
|
||||
// Every caller exits next; keep the worker out of static teardown.
|
||||
GxWorker::Abandon();
|
||||
}
|
||||
|
||||
void ShowRuntimeFatalPopup(std::string_view category, std::string_view details) noexcept {
|
||||
|
||||
Reference in New Issue
Block a user