diff --git a/config_spec.yml b/config_spec.yml index 5b86484934..5b2991390c 100644 --- a/config_spec.yml +++ b/config_spec.yml @@ -214,6 +214,10 @@ display: default: false audio: + vp: + num_workers: + type: integer + default: 0 # 0 = auto use_dsp: bool hrtf: type: bool diff --git a/hw/xbox/mcpx/apu/apu_debug.h b/hw/xbox/mcpx/apu/apu_debug.h index a45637adeb..65a00cfa81 100644 --- a/hw/xbox/mcpx/apu/apu_debug.h +++ b/hw/xbox/mcpx/apu/apu_debug.h @@ -23,6 +23,8 @@ #include #include +#define MAX_VOICE_WORKERS 16 + typedef enum McpxApuDebugMonitorPoint { MCPX_APU_DEBUG_MON_AC97, MCPX_APU_DEBUG_MON_VP, @@ -55,10 +57,11 @@ struct McpxApuDebugVoice struct McpxApuDebugVp { struct McpxApuDebugVoice v[256]; + int num_workers; struct { int num_voices; int time_us; - } workers[16]; + } workers[MAX_VOICE_WORKERS]; int total_worker_time_us; }; diff --git a/hw/xbox/mcpx/apu/vp/vp.c b/hw/xbox/mcpx/apu/vp/vp.c index 4bcb8559db..195527052b 100644 --- a/hw/xbox/mcpx/apu/vp/vp.c +++ b/hw/xbox/mcpx/apu/vp/vp.c @@ -1717,7 +1717,7 @@ static void voice_work_schedule(MCPXAPUState *d) if (!group) { next_worker_to_schedule = - (next_worker_to_schedule + 1) % NUM_VOICE_WORKERS; + (next_worker_to_schedule + 1) % vwd->num_workers; } } } @@ -1761,15 +1761,20 @@ static void voice_work_init(MCPXAPUState *d) { VoiceWorkDispatch *vwd = &d->vp.voice_work_dispatch; + int num_workers = g_config.audio.vp.num_workers ?: SDL_GetCPUCount(); + vwd->num_workers = MAX(1, MIN(num_workers, MAX_VOICE_WORKERS)); + vwd->workers = g_malloc0_n(vwd->num_workers, sizeof(VoiceWorker)); vwd->workers_should_exit = false; vwd->workers_pending = 0; vwd->queue_len = 0; + g_dbg.vp.num_workers = vwd->num_workers; + qemu_mutex_init(&vwd->lock); qemu_mutex_lock(&vwd->lock); qemu_cond_init(&vwd->work_pending); qemu_cond_init(&vwd->work_finished); - for (int i = 0; i < NUM_VOICE_WORKERS; i++) { + for (int i = 0; i < vwd->num_workers; i++) { vwd->workers_pending |= 1 << i; qemu_thread_create(&vwd->workers[i].thread, "mcpx.voice_worker", voice_worker_thread, d, QEMU_THREAD_JOINABLE); @@ -1787,9 +1792,11 @@ static void voice_work_finalize(MCPXAPUState *d) vwd->workers_should_exit = true; qemu_cond_broadcast(&vwd->work_pending); qemu_mutex_unlock(&vwd->lock); - for (int i = 0; i < NUM_VOICE_WORKERS; i++) { + for (int i = 0; i < vwd->num_workers; i++) { qemu_thread_join(&vwd->workers[i].thread); } + g_free(vwd->workers); + vwd->workers = NULL; } void mcpx_apu_vp_frame(MCPXAPUState *d, float mixbins[NUM_MIXBINS][NUM_SAMPLES_PER_FRAME]) diff --git a/hw/xbox/mcpx/apu/vp/vp.h b/hw/xbox/mcpx/apu/vp/vp.h index 7dcd16a39c..1f166fc4de 100644 --- a/hw/xbox/mcpx/apu/vp/vp.h +++ b/hw/xbox/mcpx/apu/vp/vp.h @@ -31,8 +31,6 @@ #include "svf.h" #include "hrtf.h" -#define NUM_VOICE_WORKERS 16 - typedef struct MCPXAPUState MCPXAPUState; typedef struct MCPXAPUVPSSLData { @@ -65,7 +63,8 @@ typedef struct VoiceWorker { typedef struct VoiceWorkDispatch { QemuMutex lock; - VoiceWorker workers[NUM_VOICE_WORKERS]; + int num_workers; + VoiceWorker *workers; bool workers_should_exit; QemuCond work_pending; uint64_t workers_pending; diff --git a/ui/xui/debug.cc b/ui/xui/debug.cc index d670625113..52f3fa82b7 100644 --- a/ui/xui/debug.cc +++ b/ui/xui/debug.cc @@ -233,7 +233,7 @@ void DebugApuWindow::Draw() ImGui::Text(" W: # us"); ImGui::SameLine(); ImGui::Text(" W: # us"); - for (int i = 0; i < 16; i++) { + for (int i = 0; i < dbg->vp.num_workers; i++) { if (i % 2) ImGui::SameLine(); ImGui::Text("%2d:%2d %3d", i, dbg->vp.workers[i].num_voices, dbg->vp.workers[i].time_us);