get render threading working in melon

Squashed commit of the following:

commit 6c54b59f5f8f8bbf8698eebbc2a7e39079b0e726
Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date:   Wed Mar 16 19:19:12 2022 -0700

    update submodule

commit 2c65d4375b64d8e729ebc0d35fd34865627bc494
Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date:   Wed Mar 16 19:14:36 2022 -0700

    frontend stuff

commit 4566edcc623061beb6e3a7b2ead5571b42abdf3e
Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date:   Wed Mar 16 18:10:45 2022 -0700

    probably hacky bullshit

commit 1fb9427c56a8d1af60378163cc2cafe6b36149c9
Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date:   Wed Mar 16 00:59:58 2022 -0700

    more mt testing
This commit is contained in:
CasualPokePlayer 2022-03-16 19:19:36 -07:00
parent 57c453ea68
commit 7150a97e07
7 changed files with 36 additions and 45 deletions

Binary file not shown.

View File

@ -132,10 +132,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public abstract IntPtr GetFrameThreadProc(); public abstract IntPtr GetFrameThreadProc();
[UnmanagedFunctionPointer(CC)] [UnmanagedFunctionPointer(CC)]
public delegate void ThreadWaitCallback(); public delegate void ThreadStartCallback();
[BizImport(CC)] [BizImport(CC)]
public abstract void SetThreadWaitCallback(ThreadWaitCallback callback); public abstract void SetThreadStartCallback(ThreadStartCallback callback);
[BizImport(CC)] [BizImport(CC)]
public abstract int GetNANDSize(); public abstract int GetNANDSize();

View File

@ -32,7 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public class NDSSettings public class NDSSettings
{ {
#if false #if true
[DisplayName("Threaded Rendering")] [DisplayName("Threaded Rendering")]
[Description("")] [Description("")]
[DefaultValue(true)] [DefaultValue(true)]

View File

@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
InitMemoryCallbacks(); InitMemoryCallbacks();
_tracecb = MakeTrace; _tracecb = MakeTrace;
_threadwaitcb = ThreadWaitCallback; _threadstartcb = ThreadStartCallback;
_core = PreInit<LibMelonDS>(new WaterboxOptions _core = PreInit<LibMelonDS>(new WaterboxOptions
{ {
@ -66,7 +66,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
MmapHeapSizeKB = 1024 * 1024, MmapHeapSizeKB = 1024 * 1024,
SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
}, new Delegate[] { _readcb, _writecb, _execcb, _tracecb, _threadwaitcb }); }, new Delegate[] { _readcb, _writecb, _execcb, _tracecb, _threadstartcb });
var bios7 = IsDSi || _syncSettings.UseRealBIOS var bios7 = IsDSi || _syncSettings.UseRealBIOS
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7")) ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7"))
@ -112,7 +112,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
loadFlags |= LibMelonDS.LoadFlags.IS_DSI; loadFlags |= LibMelonDS.LoadFlags.IS_DSI;
if (IsDSi && IsDSiWare) if (IsDSi && IsDSiWare)
loadFlags |= LibMelonDS.LoadFlags.LOAD_DSIWARE; loadFlags |= LibMelonDS.LoadFlags.LOAD_DSIWARE;
#if false #if true
if (_settings.ThreadedRendering) if (_settings.ThreadedRendering)
loadFlags |= LibMelonDS.LoadFlags.THREADED_RENDERING; loadFlags |= LibMelonDS.LoadFlags.THREADED_RENDERING;
#endif #endif
@ -209,7 +209,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{ {
Console.WriteLine($"Setting up waterbox thread for 0x{_frameThreadPtr:X16}"); Console.WriteLine($"Setting up waterbox thread for 0x{_frameThreadPtr:X16}");
_frameThreadStart = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer<Action>(_frameThreadPtr); _frameThreadStart = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer<Action>(_frameThreadPtr);
_core.SetThreadWaitCallback(_threadwaitcb); _core.SetThreadStartCallback(_threadstartcb);
} }
_resampler = new SpeexResampler(SpeexResampler.Quality.QUALITY_DEFAULT, 32768, 44100, 32768, 44100, null, this); _resampler = new SpeexResampler(SpeexResampler.Quality.QUALITY_DEFAULT, 32768, 44100, 32768, 44100, null, this);
@ -327,16 +327,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
return b; return b;
} }
private readonly IntPtr _frameThreadPtr;
private readonly Action _frameThreadStart;
private Task _frameThreadProcActive;
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{ {
if (_frameThreadStart != null && render) _render = render;
{
_frameThreadProcActive = Task.Run(_frameThreadStart);
}
_core.SetTraceCallback(Tracer.IsEnabled() ? _tracecb : null); _core.SetTraceCallback(Tracer.IsEnabled() ? _tracecb : null);
return new LibMelonDS.FrameInfo return new LibMelonDS.FrameInfo
{ {
@ -349,9 +342,26 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
}; };
} }
private readonly LibMelonDS.ThreadWaitCallback _threadwaitcb; private readonly IntPtr _frameThreadPtr;
private readonly Action _frameThreadStart;
private readonly LibMelonDS.ThreadStartCallback _threadstartcb;
private void ThreadWaitCallback() private bool _render;
private Task _frameThreadProcActive;
private void ThreadStartCallback()
{
if (_render)
{
if (_frameThreadProcActive != null)
{
throw new InvalidOperationException("Attempted to start render thread twice");
}
_frameThreadProcActive = Task.Run(_frameThreadStart);
}
}
protected override void FrameAdvancePost()
{ {
_frameThreadProcActive?.Wait(); _frameThreadProcActive?.Wait();
_frameThreadProcActive = null; _frameThreadProcActive = null;

View File

@ -72,7 +72,6 @@ typedef struct
} FirmwareSettings; } FirmwareSettings;
extern std::stringstream* NANDFilePtr; extern std::stringstream* NANDFilePtr;
extern bool Stopped;
static bool LoadDSiWare(u8* TmdData) static bool LoadDSiWare(u8* TmdData)
{ {
@ -154,7 +153,6 @@ EXPORT bool Init(LoadFlags loadFlags, LoadData* loadData, FirmwareSettings* fwSe
} }
if (biz_skip_fw) NDS::SetupDirectBoot(""); if (biz_skip_fw) NDS::SetupDirectBoot("");
NDS::Start(); NDS::Start();
Stopped = false;
Config::FirmwareOverrideSettings = false; Config::FirmwareOverrideSettings = false;
return true; return true;
} }
@ -374,7 +372,6 @@ EXPORT void FrameAdvance(MyFrameInfo* f)
NDS::LoadBIOS(); NDS::LoadBIOS();
if (biz_skip_fw) NDS::SetupDirectBoot(""); if (biz_skip_fw) NDS::SetupDirectBoot("");
NDS::Start(); NDS::Start();
Stopped = false;
} }
NDS::SetKeyMask(~f->Keys & 0xFFF); NDS::SetKeyMask(~f->Keys & 0xFFF);
@ -477,7 +474,7 @@ EXPORT void SetTraceCallback(void (*callback)(u32 cpu, u32* regs, u32 opcode))
namespace Platform namespace Platform
{ {
extern uintptr_t FrameThreadProc; extern uintptr_t FrameThreadProc;
extern void (*ThreadWaitCallback)(); extern void (*ThreadStartCallback)();
} }
EXPORT uintptr_t GetFrameThreadProc() EXPORT uintptr_t GetFrameThreadProc()
@ -485,9 +482,9 @@ EXPORT uintptr_t GetFrameThreadProc()
return Platform::FrameThreadProc; return Platform::FrameThreadProc;
} }
EXPORT void SetThreadWaitCallback(void (*callback)()) EXPORT void SetThreadStartCallback(void (*callback)())
{ {
Platform::ThreadWaitCallback = callback; Platform::ThreadStartCallback = callback;
} }
EXPORT u32 GetNANDSize() EXPORT u32 GetNANDSize()

View File

@ -7,7 +7,6 @@
bool NdsSaveRamIsDirty = false; bool NdsSaveRamIsDirty = false;
std::stringstream* NANDFilePtr = NULL; std::stringstream* NANDFilePtr = NULL;
bool Stopped = true;
namespace Platform namespace Platform
{ {
@ -22,7 +21,6 @@ void DeInit()
void StopEmu() void StopEmu()
{ {
Stopped = true;
} }
int GetConfigInt(ConfigEntry entry) int GetConfigInt(ConfigEntry entry)
@ -163,11 +161,11 @@ FILE* OpenLocalFile(std::string path, std::string mode)
uintptr_t FrameThreadProc = 0; uintptr_t FrameThreadProc = 0;
std::function<void()> ThreadEntryFunc = nullptr; std::function<void()> ThreadEntryFunc = nullptr;
void (*ThreadWaitCallback)() = nullptr; void (*ThreadStartCallback)() = nullptr;
void ThreadEntry() void ThreadEntry()
{ {
if (!Stopped) ThreadEntryFunc(); ThreadEntryFunc();
} }
Thread* Thread_Create(std::function<void()> func) Thread* Thread_Create(std::function<void()> func)
@ -181,44 +179,30 @@ void Thread_Free(Thread* thread)
{ {
} }
void Thread_Wait(Thread* thread) void Thread_Wait(Thread* thread) // hijacked to act as a thread start, consider this "wait for start of thread"
{ {
ThreadWaitCallback(); ThreadStartCallback();
} }
Semaphore* Semaphore_Create() Semaphore* Semaphore_Create()
{ {
int* s = new int; return nullptr;
*s = 0;
return (Semaphore*)s;
} }
void Semaphore_Free(Semaphore* sema) void Semaphore_Free(Semaphore* sema)
{ {
abort();
} }
void Semaphore_Reset(Semaphore* sema) void Semaphore_Reset(Semaphore* sema)
{ {
__atomic_store_n((int*)sema, 0, __ATOMIC_RELAXED);
} }
void Semaphore_Wait(Semaphore* sema) void Semaphore_Wait(Semaphore* sema)
{ {
int res;
loop:
res = __atomic_load_n((int*)sema, __ATOMIC_RELAXED);
if (!res) goto loop;
__atomic_sub_fetch((int*)sema, 1, __ATOMIC_RELAXED);
if (__atomic_load_n((int*)sema, __ATOMIC_RELAXED) < 0)
{
__atomic_store_n((int*)sema, 0, __ATOMIC_RELAXED);
}
} }
void Semaphore_Post(Semaphore* sema, int count) void Semaphore_Post(Semaphore* sema, int count)
{ {
__atomic_add_fetch((int*)sema, (int)count, __ATOMIC_RELAXED);
} }
Mutex* Mutex_Create() Mutex* Mutex_Create()

@ -1 +1 @@
Subproject commit 7e45e3582be653db468293189d63349c2632c3cb Subproject commit 69d0437b289d87d49c6ec68f81e454cf97c8e7d8