From de3b8ff54876a2cc7fc7efde90ad68b67012f2d1 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 19 May 2024 19:44:34 +0200 Subject: [PATCH] port: revert multithreaded audio experiments until I can figure out how to fix all the funny concurrency issues that cropped up --- Makefile.port | 4 +-- port/fast3d/gfx_sdl2.cpp | 2 +- port/include/audio.h | 3 +- port/include/system.h | 6 +--- port/include/thread.h | 27 ---------------- port/src/audio.c | 40 +++++++++-------------- port/src/libultra.c | 2 +- port/src/pdmain.c | 2 +- port/src/pdsched.c | 25 +++++++++++++++ port/src/system.c | 11 ++----- port/src/thread.c | 27 ---------------- src/game/chraicommands.c | 10 ++++-- src/game/timing.c | 2 +- src/include/lib/audiomgr.h | 6 +--- src/include/platform.h | 3 -- src/lib/audiomgr.c | 66 -------------------------------------- 16 files changed, 62 insertions(+), 174 deletions(-) delete mode 100644 port/include/thread.h delete mode 100644 port/src/thread.c diff --git a/Makefile.port b/Makefile.port index b3e3b953e..650f02474 100644 --- a/Makefile.port +++ b/Makefile.port @@ -150,7 +150,7 @@ B_DIR := build/$(ROMID)-port G_DIR := src/generated/$(ROMID) ifneq (,$(findstring windows,$(TARGET_PLATFORM))) - TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) -pthread + TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -ldbghelp # on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs TOOLCHAIN ?= i686-w64-mingw32- @@ -161,7 +161,7 @@ ifneq (,$(findstring windows,$(TARGET_PLATFORM))) TARGET_LDFLAGS += -lstdc++ endif else # assume *nix - TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) -pthread + TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz -ldl ifneq (,$(findstring arm,$(TARGET_PLATFORM))$(findstring aarch,$(TARGET_PLATFORM))) # linux on arm or aarch64 diff --git a/port/fast3d/gfx_sdl2.cpp b/port/fast3d/gfx_sdl2.cpp index 537b4c52d..181038d26 100644 --- a/port/fast3d/gfx_sdl2.cpp +++ b/port/fast3d/gfx_sdl2.cpp @@ -261,7 +261,7 @@ static inline void sync_framerate_with_timer(void) { // We want to exit a bit early, so we can busy-wait the rest to never miss the deadline left -= 15000UL; if (left > 0) { - sysFrameLimiterSleep(left); + sysSleep(left); } do { diff --git a/port/include/audio.h b/port/include/audio.h index 8aa5a453c..32fc16cbe 100644 --- a/port/include/audio.h +++ b/port/include/audio.h @@ -6,6 +6,7 @@ s32 audioInit(void); s32 audioGetBytesBuffered(void); s32 audioGetSamplesBuffered(void); -void audioSubmitBuffer(const s16 *buf, u32 size); +void audioSetNextBuffer(const s16 *buf, u32 len); +void audioEndFrame(void); #endif diff --git a/port/include/system.h b/port/include/system.h index b65690b47..84d568382 100644 --- a/port/include/system.h +++ b/port/include/system.h @@ -35,11 +35,7 @@ void *sysMemZeroAlloc(const u32 size); void sysMemFree(void *ptr); // hns is specified in 100ns units -// do not use sysFrameLimiterSleep on any thread other than the main one -void sysFrameLimiterSleep(const s64 hns); - -// us is specified in microseconds -void sysSleep(const s64 us); +void sysSleep(const s64 hns); // yield CPU if supported (e.g. during a busy loop) void sysCpuRelax(void); diff --git a/port/include/thread.h b/port/include/thread.h deleted file mode 100644 index 7a9f6383f..000000000 --- a/port/include/thread.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _IN_THREAD_H -#define _IN_THREAD_H - -#include -#include "platform.h" - -// TODO: backends -#ifndef PLATFORM_USE_PTHREAD -#error "No available thread backend." -#endif - -#include - -#define SYSMUTEX_STATIC_INIT PTHREAD_MUTEX_INITIALIZER - -typedef pthread_t systhread; -typedef pthread_mutex_t sysmutex; - -typedef void *(*systhreadfn)(void *); - -s32 sysThreadCreate(systhread *thread, systhreadfn func, void *arg); -s32 sysThreadJoin(systhread *thread, void **result); - -void sysMutexLock(sysmutex *mtx); -void sysMutexUnlock(sysmutex *mtx); - -#endif // _IN_THREAD_H diff --git a/port/src/audio.c b/port/src/audio.c index f0f172de5..c66cf5912 100644 --- a/port/src/audio.c +++ b/port/src/audio.c @@ -7,13 +7,12 @@ #include "system.h" static SDL_AudioDeviceID dev; +static const s16 *nextBuf; +static u32 nextSize = 0; static s32 bufferSize = 512; static s32 queueLimit = 8192; -static f32 offsetFrames = 0.5f; -static u32 offsetBytes; - s32 audioInit(void) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { @@ -29,8 +28,7 @@ s32 audioInit(void) want.samples = bufferSize; want.callback = NULL; - const f32 spf = (f32)want.freq / (PAL ? 50.f : 60.f); - offsetBytes = offsetFrames * spf * (f32)sizeof(int16_t); + nextBuf = NULL; dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); if (dev == 0) { @@ -45,39 +43,33 @@ s32 audioInit(void) s32 audioGetBytesBuffered(void) { - u32 count = SDL_GetQueuedAudioSize(dev); - - // pd's audio code decides how many samples of audio to produce based on the amount of audio - // currently buffered, so we adjust the reported count to be some number of frames in the future - // to counteract lag; idea shamelessly stolen from mm recomp - if (offsetBytes) { - if (count > offsetBytes) { - count -= offsetBytes; - } else { - count = 0; - } - } - - return count; + return SDL_GetQueuedAudioSize(dev); } s32 audioGetSamplesBuffered(void) { - return audioGetBytesBuffered() / (2 * sizeof(s16)); + return audioGetBytesBuffered() / 4; +} + +void audioSetNextBuffer(const s16 *buf, u32 len) +{ + nextBuf = buf; + nextSize = len; } -void audioSubmitBuffer(const s16 *buf, u32 size) +void audioEndFrame(void) { - if (buf && size) { + if (nextBuf && nextSize) { if (audioGetSamplesBuffered() < queueLimit) { - SDL_QueueAudio(dev, buf, size); + SDL_QueueAudio(dev, nextBuf, nextSize); } + nextBuf = NULL; + nextSize = 0; } } PD_CONSTRUCTOR static void audioConfigInit(void) { configRegisterInt("Audio.BufferSize", &bufferSize, 0, 1 * 1024 * 1024); - configRegisterFloat("Audio.OffsetFrames", &offsetFrames, 0.f, 5.f); configRegisterInt("Audio.QueueLimit", &queueLimit, 0, 1 * 1024 * 1024); } diff --git a/port/src/libultra.c b/port/src/libultra.c index 3d749d211..74edd9782 100644 --- a/port/src/libultra.c +++ b/port/src/libultra.c @@ -166,7 +166,7 @@ u32 osAiGetLength(void) s32 osAiSetNextBuffer(void *bufPtr, u32 size) { - audioSubmitBuffer(bufPtr, size); + audioSetNextBuffer(bufPtr, size); return 0; } diff --git a/port/src/pdmain.c b/port/src/pdmain.c index 7faa21e31..2cd9baffb 100644 --- a/port/src/pdmain.c +++ b/port/src/pdmain.c @@ -501,7 +501,7 @@ void mainLoop(void) schedEndFrame(&g_Sched); } if (g_TickExtraSleep) { - sysFrameLimiterSleep(EXTRA_SLEEP_TIME); + sysSleep(EXTRA_SLEEP_TIME); } } diff --git a/port/src/pdsched.c b/port/src/pdsched.c index a8493d769..1f8800565 100644 --- a/port/src/pdsched.c +++ b/port/src/pdsched.c @@ -242,6 +242,18 @@ void schedStartFrame(OSSched *sc) videoStartFrame(); } +void schedAudioFrame(OSSched *sc) +{ + s32 i; + + if (!g_SndDisabled) { + for (i = 0; i < g_Vars.diffframe60; i++) { + amgrFrame(); + audioEndFrame(); + } + } +} + /** * Handle a retrace (vsync) event. * @@ -260,6 +272,18 @@ void schedEndFrame(OSSched *sc) { sc->frameCount++; +#if PAL + if (!g_Resetting && (sc->frameCount & 1)) { + // osStopTimer(&g_SchedRspTimer); + // osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg); + } +#else + if (!g_Resetting && ((sc->frameCount & 1) || IS4MB())) { + // osStopTimer(&g_SchedRspTimer); + // osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg); + } +#endif + if (!g_Resetting) { viHandleRetrace(); } @@ -271,6 +295,7 @@ void schedEndFrame(OSSched *sc) joy00014238(); sndHandleRetrace(); + schedAudioFrame(sc); schedRenderCrashPeriodically(sc->frameCount); videoEndFrame(); diff --git a/port/src/system.c b/port/src/system.c index 8e06f8ed8..16b689c47 100644 --- a/port/src/system.c +++ b/port/src/system.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include "platform.h" @@ -33,6 +32,8 @@ __attribute__((dllexport)) u32 AmdPowerXpressRequestHighPerformance = 1; #else +#include + // figure out how to yield #if defined(PLATFORM_X86) || defined(PLATFORM_X86_64) // this should work even if the code is not built with SSE enabled, at least on gcc and clang, @@ -292,7 +293,7 @@ void sysMemFree(void *ptr) free(ptr); } -void sysFrameLimiterSleep(const s64 hns) +void sysSleep(const s64 hns) { #ifdef PLATFORM_WIN32 static LARGE_INTEGER li; @@ -305,12 +306,6 @@ void sysFrameLimiterSleep(const s64 hns) #endif } -void sysSleep(const s64 us) -{ - const struct timespec spec = { 0, us * 1000 }; - nanosleep(&spec, NULL); -} - void sysCpuRelax(void) { DO_YIELD(); diff --git a/port/src/thread.c b/port/src/thread.c deleted file mode 100644 index 232c104ac..000000000 --- a/port/src/thread.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "thread.h" - -#ifndef PLATFORM_USE_PTHREAD -#error "No available thread backend." -#endif - -#include - -s32 sysThreadCreate(systhread *thread, systhreadfn func, void *arg) -{ - return pthread_create(thread, NULL, func, arg); -} - -s32 sysThreadJoin(systhread *thread, void **result) -{ - return pthread_join(*thread, result); -} - -void sysMutexLock(sysmutex *mtx) -{ - pthread_mutex_lock(mtx); -} - -void sysMutexUnlock(sysmutex *mtx) -{ - pthread_mutex_unlock(mtx); -} diff --git a/src/game/chraicommands.c b/src/game/chraicommands.c index b25d433ed..9a5517348 100644 --- a/src/game/chraicommands.c +++ b/src/game/chraicommands.c @@ -9840,14 +9840,20 @@ bool aiIfMusicEventQueueIsEmpty(void) { f32 value = (u64)osGetCount() * 64 / 3000; +#ifdef PLATFORM_N64 // will hang forever until the audio thread wakes it up if (g_MusicEventQueueLength) { -#ifndef PLATFORM_N64 - musicTickEvents(); +#else // HACK: will wait 1 frame and get on with it + static bool waited = false; + if (g_MusicEventQueueLength && !waited) { + waited = true; #endif g_Vars.aioffset += 4; } else { u8 *cmd = g_Vars.ailist + g_Vars.aioffset; g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[3]); +#ifndef PLATFORM_N64 + waited = false; +#endif } return false; diff --git a/src/game/timing.c b/src/game/timing.c index 7bf96eb75..747c7ed24 100644 --- a/src/game/timing.c +++ b/src/game/timing.c @@ -47,7 +47,7 @@ void frametimeCalculate(void) #ifndef PLATFORM_N64 if (g_TickExtraSleep) { - sysFrameLimiterSleep(EXTRA_SLEEP_TIME); + sysSleep(EXTRA_SLEEP_TIME); } #endif } while (g_Vars.mininc60 && diffframe60 < g_Vars.mininc60); diff --git a/src/include/lib/audiomgr.h b/src/include/lib/audiomgr.h index 4e6f777bb..ec1d6ba0a 100644 --- a/src/include/lib/audiomgr.h +++ b/src/include/lib/audiomgr.h @@ -17,11 +17,7 @@ OSMesgQueue *amgrGetFrameMesgQueue(void); void amgrStopThread(void); #ifndef PLATFORM_N64 -void amgrLock(void); -void amgrUnlock(void); -#else -#define amgrLock() do {} while(0) -#define amgrUnlock() do {} while(0) +void amgrFrame(void); #endif #endif diff --git a/src/include/platform.h b/src/include/platform.h index 5fc0ceca1..30615f750 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -34,9 +34,6 @@ #error "64-bit platforms are currently not supported." #endif -// threading backend -#define PLATFORM_USE_PTHREAD 1 - // detect endianness #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ diff --git a/src/lib/audiomgr.c b/src/lib/audiomgr.c index 2f4d80021..7791798de 100644 --- a/src/lib/audiomgr.c +++ b/src/lib/audiomgr.c @@ -10,13 +10,6 @@ #include "lib/libc/ll.h" #include "data.h" #include "types.h" -#ifndef PLATFORM_N64 -#include "lib/audiomgr.h" -#include "thread.h" -#include "audio.h" -#include "system.h" -#define AMGR_THREAD_SLEEP_US 2000 -#endif u32 var80091560; u32 var80091564; @@ -50,14 +43,6 @@ void *g_AudioSp; u32 var8005cf90 = 0x00000000; u8 var8005cf94 = 1; -#ifndef PLATFORM_N64 -systhread g_AmgrThread; -sysmutex g_AmgrMutex = SYSMUTEX_STATIC_INIT; -u32 g_AmgrFrame; -u32 g_AmgrFrameTarget; -void *amgrThread(void *arg); -#endif - void amgrHandleDoneMsg(AudioInfo *info); void amgrHandleFrameMsg(AudioInfo *info, AudioInfo *previnfo); void amgrMain(void *arg); @@ -170,9 +155,6 @@ void amgrStartThread(void) { osStartThread(&g_AudioManager.thread); g_AudioIsThreadRunning = true; -#ifndef PLATFORM_N64 - sysThreadCreate(&g_AmgrThread, &amgrThread, NULL); -#endif } OSMesgQueue *amgrGetFrameMesgQueue(void) @@ -189,12 +171,6 @@ void amgrStopThread(void) { if (g_AudioIsThreadRunning) { osStopThread(&g_AudioManager.thread); -#ifndef PLATFORM_N64 - amgrLock(); - g_AudioIsThreadRunning = false; - amgrUnlock(); - sysThreadJoin(&g_AmgrThread, NULL); -#endif } } @@ -345,14 +321,11 @@ void amgrHandleDoneMsg(AudioInfo *info) } #ifndef PLATFORM_N64 - void amgrFrame(void) { static AudioInfo *previnfo = NULL; static s32 count = 0; - amgrLock(); - var80091588 = osGetTime(); AudioInfo *info = g_AudioManager.audioInfo[g_AdmaCurFrame % 3]; @@ -390,8 +363,6 @@ void amgrFrame(void) count++; - amgrUnlock(); - var80091590 = osGetTime(); var80091570 = var80091590 - var80091588; @@ -406,41 +377,4 @@ void amgrFrame(void) var80091568 = var80091590 - var80091588; } } - -void amgrLock(void) -{ - sysMutexLock(&g_AmgrMutex); -} - -void amgrUnlock(void) -{ - sysMutexUnlock(&g_AmgrMutex); -} - -void *amgrThread(void *arg) -{ - const f64 frametime = 1000000.0 / (PAL ? 50.0 : 60.0); - bool running = g_AudioIsThreadRunning; - f64 nexttick = sysGetMicroseconds(); - f64 tick; - - while (running) { - tick = sysGetMicroseconds() + 0.01; - - while (nexttick < tick) { - amgrFrame(); - g_AmgrFrame++; - nexttick += frametime; - } - - sysSleep(AMGR_THREAD_SLEEP_US); - - amgrLock(); - running = g_AudioIsThreadRunning; - amgrUnlock(); - } - - return NULL; -} - #endif