From 7b2c4897f089ab6eee7bc2ce2873c2b11058e04e Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 2 Feb 2015 03:51:40 +0200 Subject: [PATCH] spu: fix some thread safety issues reverb and stuff --- plugins/dfsound/externals.h | 8 +--- plugins/dfsound/freeze.c | 4 +- plugins/dfsound/registers.c | 75 ++++++++++++++------------------- plugins/dfsound/reverb.c | 83 +++++++++++++++++++++---------------- plugins/dfsound/spu.c | 19 ++++----- 5 files changed, 91 insertions(+), 98 deletions(-) diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index f6fc4409..8bbf4e02 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -162,14 +162,8 @@ typedef struct int dirty; // registers changed - // normalized offsets - int nIIR_DEST_A0, nIIR_DEST_A1, nIIR_DEST_B0, nIIR_DEST_B1, - nACC_SRC_A0, nACC_SRC_A1, nACC_SRC_B0, nACC_SRC_B1, - nIIR_SRC_A0, nIIR_SRC_A1, nIIR_SRC_B0, nIIR_SRC_B1, - nACC_SRC_C0, nACC_SRC_C1, nACC_SRC_D0, nACC_SRC_D1, - nMIX_DEST_A0, nMIX_DEST_A1, nMIX_DEST_B0, nMIX_DEST_B1; // MIX_DEST_xx - FB_SRC_x - int nFB_SRC_A0, nFB_SRC_A1, nFB_SRC_B0, nFB_SRC_B1; + int FB_SRC_A0, FB_SRC_A1, FB_SRC_B0, FB_SRC_B1; } REVERBInfo; /////////////////////////////////////////////////////////// diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index 5b4267bf..72c9d22e 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -231,6 +231,8 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, if(!pF) return 0; // first check + do_samples(cycles, 1); + if(ulFreezeMode) // info or save? {//--------------------------------------------------// if(ulFreezeMode==1) @@ -242,8 +244,6 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, if(ulFreezeMode==2) return 1; // info mode? ok, bye // save mode: - do_samples(cycles, 1); - memcpy(pF->cSPURam,spu.spuMem,0x80000); // copy common infos memcpy(pF->cSPUPort,spu.regArea,0x200); diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c index 4588fa7c..91bcaf86 100644 --- a/plugins/dfsound/registers.c +++ b/plugins/dfsound/registers.c @@ -145,17 +145,6 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, break; //-------------------------------------------------// case H_SPUReverbAddr: - if(val==0xFFFF || val<=0x200) - {spu.rvb->StartAddr=spu.rvb->CurrAddr=0;} - else - { - const long iv=(unsigned long)val<<2; - if(spu.rvb->StartAddr!=iv) - { - spu.rvb->StartAddr=(unsigned long)val<<2; - spu.rvb->CurrAddr=spu.rvb->StartAddr; - } - } goto rvbd; //-------------------------------------------------// case H_SPUirqAddr: @@ -246,38 +235,38 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, ReverbOn(16,24,val); break; //-------------------------------------------------// - case H_Reverb+0 : spu.rvb->FB_SRC_A=val*4; goto rvbd; - case H_Reverb+2 : spu.rvb->FB_SRC_B=val*4; goto rvbd; - case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; goto rvbd; - case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; goto rvbd; - case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; goto rvbd; - case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; goto rvbd; - case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; goto rvbd; - case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; goto rvbd; - case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; goto rvbd; - case H_Reverb+18 : spu.rvb->FB_X=(short)val; goto rvbd; - case H_Reverb+20 : spu.rvb->IIR_DEST_A0=val*4; goto rvbd; - case H_Reverb+22 : spu.rvb->IIR_DEST_A1=val*4; goto rvbd; - case H_Reverb+24 : spu.rvb->ACC_SRC_A0=val*4; goto rvbd; - case H_Reverb+26 : spu.rvb->ACC_SRC_A1=val*4; goto rvbd; - case H_Reverb+28 : spu.rvb->ACC_SRC_B0=val*4; goto rvbd; - case H_Reverb+30 : spu.rvb->ACC_SRC_B1=val*4; goto rvbd; - case H_Reverb+32 : spu.rvb->IIR_SRC_A0=val*4; goto rvbd; - case H_Reverb+34 : spu.rvb->IIR_SRC_A1=val*4; goto rvbd; - case H_Reverb+36 : spu.rvb->IIR_DEST_B0=val*4; goto rvbd; - case H_Reverb+38 : spu.rvb->IIR_DEST_B1=val*4; goto rvbd; - case H_Reverb+40 : spu.rvb->ACC_SRC_C0=val*4; goto rvbd; - case H_Reverb+42 : spu.rvb->ACC_SRC_C1=val*4; goto rvbd; - case H_Reverb+44 : spu.rvb->ACC_SRC_D0=val*4; goto rvbd; - case H_Reverb+46 : spu.rvb->ACC_SRC_D1=val*4; goto rvbd; - case H_Reverb+48 : spu.rvb->IIR_SRC_B1=val*4; goto rvbd; - case H_Reverb+50 : spu.rvb->IIR_SRC_B0=val*4; goto rvbd; - case H_Reverb+52 : spu.rvb->MIX_DEST_A0=val*4; goto rvbd; - case H_Reverb+54 : spu.rvb->MIX_DEST_A1=val*4; goto rvbd; - case H_Reverb+56 : spu.rvb->MIX_DEST_B0=val*4; goto rvbd; - case H_Reverb+58 : spu.rvb->MIX_DEST_B1=val*4; goto rvbd; - case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; goto rvbd; - case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; goto rvbd; + case H_Reverb+0 : goto rvbd; + case H_Reverb+2 : goto rvbd; + case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; break; + case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; break; + case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; break; + case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; break; + case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; break; + case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; break; + case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; break; + case H_Reverb+18 : spu.rvb->FB_X=(short)val; break; + case H_Reverb+20 : goto rvbd; + case H_Reverb+22 : goto rvbd; + case H_Reverb+24 : goto rvbd; + case H_Reverb+26 : goto rvbd; + case H_Reverb+28 : goto rvbd; + case H_Reverb+30 : goto rvbd; + case H_Reverb+32 : goto rvbd; + case H_Reverb+34 : goto rvbd; + case H_Reverb+36 : goto rvbd; + case H_Reverb+38 : goto rvbd; + case H_Reverb+40 : goto rvbd; + case H_Reverb+42 : goto rvbd; + case H_Reverb+44 : goto rvbd; + case H_Reverb+46 : goto rvbd; + case H_Reverb+48 : goto rvbd; + case H_Reverb+50 : goto rvbd; + case H_Reverb+52 : goto rvbd; + case H_Reverb+54 : goto rvbd; + case H_Reverb+56 : goto rvbd; + case H_Reverb+58 : goto rvbd; + case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; break; + case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; break; } return; diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c index 2ff6edc8..ec570fb3 100644 --- a/plugins/dfsound/reverb.c +++ b/plugins/dfsound/reverb.c @@ -50,16 +50,16 @@ INLINE int rvb2ram_offs(int curr, int space, int iOff) // get_buffer content helper: takes care about wraps #define g_buffer(var) \ - ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)]) + ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)]) // saturate iVal and store it as var #define s_buffer(var, iVal) \ ssat32_to_16(iVal); \ - spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)] = iVal + spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)] = iVal #define s_buffer1(var, iVal) \ ssat32_to_16(iVal); \ - spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var + 1)] = iVal + spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var + 1)] = iVal //////////////////////////////////////////////////////////////////////// @@ -174,43 +174,54 @@ static void MixREVERB_off(int *SSumLR, int ns_to, int curr_addr) static void REVERBPrep(void) { REVERBInfo *rvb = spu.rvb; - int space = 0x40000 - rvb->StartAddr; - int t; - #define prep_offs(v) \ - t = rvb->v; \ + int space, t; + + t = spu.regArea[(H_SPUReverbAddr - 0xc00) >> 1]; + if (t == 0xFFFF || t <= 0x200) + spu.rvb->StartAddr = spu.rvb->CurrAddr = 0; + else if (spu.rvb->StartAddr != (t << 2)) + spu.rvb->StartAddr = spu.rvb->CurrAddr = t << 2; + + space = 0x40000 - rvb->StartAddr; + + #define prep_offs(v, r) \ + t = spu.regArea[(0x1c0 + r) >> 1] * 4; \ while (t >= space) \ t -= space; \ - rvb->n##v = t - #define prep_offs2(d, v1, v2) \ - t = rvb->v1 - rvb->v2; \ + rvb->v = t + #define prep_offs2(d, r1, r2) \ + t = spu.regArea[(0x1c0 + r1) >> 1] * 4; \ + t -= spu.regArea[(0x1c0 + r2) >> 1] * 4; \ + while (t < 0) \ + t += space; \ while (t >= space) \ t -= space; \ - rvb->n##d = t - - prep_offs(IIR_SRC_A0); - prep_offs(IIR_SRC_A1); - prep_offs(IIR_SRC_B0); - prep_offs(IIR_SRC_B1); - prep_offs(IIR_DEST_A0); - prep_offs(IIR_DEST_A1); - prep_offs(IIR_DEST_B0); - prep_offs(IIR_DEST_B1); - prep_offs(ACC_SRC_A0); - prep_offs(ACC_SRC_A1); - prep_offs(ACC_SRC_B0); - prep_offs(ACC_SRC_B1); - prep_offs(ACC_SRC_C0); - prep_offs(ACC_SRC_C1); - prep_offs(ACC_SRC_D0); - prep_offs(ACC_SRC_D1); - prep_offs(MIX_DEST_A0); - prep_offs(MIX_DEST_A1); - prep_offs(MIX_DEST_B0); - prep_offs(MIX_DEST_B1); - prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A); - prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A); - prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B); - prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B); + rvb->d = t + + prep_offs(IIR_SRC_A0, 32); + prep_offs(IIR_SRC_A1, 34); + prep_offs(IIR_SRC_B0, 36); + prep_offs(IIR_SRC_B1, 38); + prep_offs(IIR_DEST_A0, 20); + prep_offs(IIR_DEST_A1, 22); + prep_offs(IIR_DEST_B0, 36); + prep_offs(IIR_DEST_B1, 38); + prep_offs(ACC_SRC_A0, 24); + prep_offs(ACC_SRC_A1, 26); + prep_offs(ACC_SRC_B0, 28); + prep_offs(ACC_SRC_B1, 30); + prep_offs(ACC_SRC_C0, 40); + prep_offs(ACC_SRC_C1, 42); + prep_offs(ACC_SRC_D0, 44); + prep_offs(ACC_SRC_D1, 46); + prep_offs(MIX_DEST_A0, 52); + prep_offs(MIX_DEST_A1, 54); + prep_offs(MIX_DEST_B0, 56); + prep_offs(MIX_DEST_B1, 58); + prep_offs2(FB_SRC_A0, 52, 0); + prep_offs2(FB_SRC_A1, 54, 0); + prep_offs2(FB_SRC_B0, 56, 2); + prep_offs2(FB_SRC_B1, 58, 2); #undef prep_offs #undef prep_offs2 diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 8681d354..193a5d0d 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -818,12 +818,8 @@ static void do_channels(int ns_to) } if (spu.rvb->StartAddr) { - if (do_rvb) { - if (unlikely(spu.rvb->dirty)) - REVERBPrep(); - + if (do_rvb) REVERBDo(spu.SSumLR, RVB, ns_to, spu.rvb->CurrAddr); - } spu.rvb->CurrAddr += ns_to / 2; while (spu.rvb->CurrAddr >= 0x40000) @@ -970,11 +966,8 @@ static void queue_channel_work(int ns_to, unsigned int silentch) work->rvb_addr = 0; if (spu.rvb->StartAddr) { - if (spu_config.iUseReverb) { - if (unlikely(spu.rvb->dirty)) - REVERBPrep(); + if (spu_config.iUseReverb) work->rvb_addr = spu.rvb->CurrAddr; - } spu.rvb->CurrAddr += ns_to / 2; while (spu.rvb->CurrAddr >= 0x40000) @@ -989,9 +982,9 @@ static void do_channel_work(struct work_item *work) { unsigned int mask; unsigned int decode_dirty_ch = 0; + const SPUCHAN *s_chan; int *SB, sinc, spos, sbpos; int d, ch, ns_to; - SPUCHAN *s_chan; ns_to = work->ns_to; @@ -1057,6 +1050,9 @@ static void sync_worker_thread(int force) struct work_item *work; int done, used_space; + // rvb offsets will change, thread may be using them + force |= spu.rvb->dirty && spu.rvb->StartAddr; + done = thread_get_i_done() - worker->i_reaped; used_space = worker->i_ready - worker->i_reaped; //printf("done: %d use: %d dsp: %u/%u\n", done, used_space, @@ -1150,6 +1146,9 @@ void do_samples(unsigned int cycles_to, int do_direct) } } + if (unlikely(spu.rvb->dirty)) + REVERBPrep(); + if (do_direct || worker == NULL || !spu_config.iUseThread) { do_channels(ns_to); do_samples_finish(spu.SSumLR, ns_to, silentch, spu.decode_pos); -- 2.39.2