apu/vp: Make number of voice workers dynamic

Adds a new config option to control number of workers. If the value of
the option is 0 (default), then the logical CPU count, as reported by
SDL, is used.
This commit is contained in:
Matt Borgerson 2025-06-12 13:34:55 -07:00 committed by mborgerson
parent 8881537de2
commit 7d9739df4c
5 changed files with 21 additions and 8 deletions

View File

@ -214,6 +214,10 @@ display:
default: false
audio:
vp:
num_workers:
type: integer
default: 0 # 0 = auto
use_dsp: bool
hrtf:
type: bool

View File

@ -23,6 +23,8 @@
#include <stdbool.h>
#include <stdint.h>
#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;
};

View File

@ -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])

View File

@ -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;

View File

@ -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);