Use RAII when handling the mixer's FPU state
This commit is contained in:
parent
8f43f737ba
commit
9f2a77f788
@ -2241,7 +2241,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
* allocated with the appropriate size.
|
||||
*/
|
||||
update_failed = AL_FALSE;
|
||||
START_MIXER_MODE();
|
||||
FPUCtl mixer_mode{};
|
||||
context = device->ContextList.load();
|
||||
while(context)
|
||||
{
|
||||
@ -2354,7 +2354,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
|
||||
context = context->next.load(std::memory_order_relaxed);
|
||||
}
|
||||
END_MIXER_MODE();
|
||||
mixer_mode.leave();
|
||||
if(update_failed)
|
||||
return ALC_INVALID_DEVICE;
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
|
||||
ALCcontext *ctx;
|
||||
ALsizei i, c;
|
||||
|
||||
START_MIXER_MODE();
|
||||
FPUCtl mixer_mode{};
|
||||
for(SamplesDone = 0;SamplesDone < NumSamples;)
|
||||
{
|
||||
SamplesToDo = mini(NumSamples-SamplesDone, BUFFERSIZE);
|
||||
@ -1815,7 +1815,6 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
|
||||
|
||||
SamplesDone += SamplesToDo;
|
||||
}
|
||||
END_MIXER_MODE();
|
||||
}
|
||||
|
||||
|
||||
|
@ -154,7 +154,7 @@ SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType
|
||||
converter->mFracOffset = 0;
|
||||
|
||||
/* Have to set the mixer FPU mode since that's what the resampler code expects. */
|
||||
START_MIXER_MODE();
|
||||
FPUCtl mixer_mode{};
|
||||
step = (ALsizei)mind(((ALdouble)srcRate/dstRate*FRACTIONONE) + 0.5,
|
||||
MAX_PITCH * FRACTIONONE);
|
||||
converter->mIncrement = maxi(step, 1);
|
||||
@ -166,7 +166,6 @@ SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType
|
||||
BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc12);
|
||||
converter->mResample = SelectResampler(BSinc12Resampler);
|
||||
}
|
||||
END_MIXER_MODE();
|
||||
|
||||
return converter;
|
||||
}
|
||||
@ -227,7 +226,7 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
|
||||
const ALsizei increment = converter->mIncrement;
|
||||
ALsizei pos = 0;
|
||||
|
||||
START_MIXER_MODE();
|
||||
FPUCtl mixer_mode{};
|
||||
while(pos < dstframes && *srcframes > 0)
|
||||
{
|
||||
ALfloat *RESTRICT SrcData = converter->mSrcSamples;
|
||||
@ -339,7 +338,6 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
|
||||
dst = (ALbyte*)dst + DstFrameSize*DstSize;
|
||||
pos += DstSize;
|
||||
}
|
||||
END_MIXER_MODE();
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -1,41 +1,25 @@
|
||||
#ifndef FPU_MODES_H
|
||||
#define FPU_MODES_H
|
||||
|
||||
#ifdef HAVE_FENV_H
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct FPUCtl {
|
||||
class FPUCtl {
|
||||
#if defined(__GNUC__) && defined(HAVE_SSE)
|
||||
unsigned int sse_state;
|
||||
unsigned int sse_state{};
|
||||
#elif defined(HAVE___CONTROL87_2)
|
||||
unsigned int state;
|
||||
unsigned int sse_state;
|
||||
unsigned int state{};
|
||||
unsigned int sse_state{};
|
||||
#elif defined(HAVE__CONTROLFP)
|
||||
unsigned int state;
|
||||
unsigned int state{};
|
||||
#endif
|
||||
} FPUCtl;
|
||||
void SetMixerFPUMode(FPUCtl *ctl);
|
||||
void RestoreFPUMode(const FPUCtl *ctl);
|
||||
bool in_mode{};
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Use an alternate macro set with GCC to avoid accidental continue or break
|
||||
* statements within the mixer mode.
|
||||
*/
|
||||
#define START_MIXER_MODE() __extension__({ FPUCtl _oldMode; SetMixerFPUMode(&_oldMode)
|
||||
#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); })
|
||||
#else
|
||||
#define START_MIXER_MODE() do { FPUCtl _oldMode; SetMixerFPUMode(&_oldMode)
|
||||
#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); } while(0)
|
||||
#endif
|
||||
#define LEAVE_MIXER_MODE() RestoreFPUMode(&_oldMode)
|
||||
public:
|
||||
FPUCtl() noexcept;
|
||||
~FPUCtl() { leave(); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
FPUCtl(const FPUCtl&) = delete;
|
||||
FPUCtl& operator=(const FPUCtl&) = delete;
|
||||
|
||||
void leave() noexcept;
|
||||
};
|
||||
|
||||
#endif /* FPU_MODES_H */
|
||||
|
@ -260,13 +260,13 @@ void FillCPUCaps(int capfilter)
|
||||
}
|
||||
|
||||
|
||||
void SetMixerFPUMode(FPUCtl *ctl)
|
||||
FPUCtl::FPUCtl() noexcept
|
||||
{
|
||||
#if defined(__GNUC__) && defined(HAVE_SSE)
|
||||
if((CPUCapFlags&CPU_CAP_SSE))
|
||||
{
|
||||
__asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state));
|
||||
unsigned int sseState = ctl->sse_state;
|
||||
__asm__ __volatile__("stmxcsr %0" : "=m" (*&this->sse_state));
|
||||
unsigned int sseState = this->sse_state;
|
||||
sseState |= 0x8000; /* set flush-to-zero */
|
||||
if((CPUCapFlags&CPU_CAP_SSE2))
|
||||
sseState |= 0x0040; /* set denormals-are-zero */
|
||||
@ -275,32 +275,37 @@ void SetMixerFPUMode(FPUCtl *ctl)
|
||||
|
||||
#elif defined(HAVE___CONTROL87_2)
|
||||
|
||||
__control87_2(0, 0, &ctl->state, &ctl->sse_state);
|
||||
__control87_2(0, 0, &this->state, &this->sse_state);
|
||||
_control87(_DN_FLUSH, _MCW_DN);
|
||||
|
||||
#elif defined(HAVE__CONTROLFP)
|
||||
|
||||
ctl->state = _controlfp(0, 0);
|
||||
this->state = _controlfp(0, 0);
|
||||
_controlfp(_DN_FLUSH, _MCW_DN);
|
||||
#endif
|
||||
|
||||
this->in_mode = true;
|
||||
}
|
||||
|
||||
void RestoreFPUMode(const FPUCtl *ctl)
|
||||
void FPUCtl::leave() noexcept
|
||||
{
|
||||
if(!this->in_mode) return;
|
||||
|
||||
#if defined(__GNUC__) && defined(HAVE_SSE)
|
||||
if((CPUCapFlags&CPU_CAP_SSE))
|
||||
__asm__ __volatile__("ldmxcsr %0" : : "m" (*&ctl->sse_state));
|
||||
__asm__ __volatile__("ldmxcsr %0" : : "m" (*&this->sse_state));
|
||||
|
||||
#elif defined(HAVE___CONTROL87_2)
|
||||
|
||||
unsigned int mode;
|
||||
__control87_2(ctl->state, _MCW_DN, &mode, nullptr);
|
||||
__control87_2(ctl->sse_state, _MCW_DN, nullptr, &mode);
|
||||
__control87_2(this->state, _MCW_DN, &mode, nullptr);
|
||||
__control87_2(this->sse_state, _MCW_DN, nullptr, &mode);
|
||||
|
||||
#elif defined(HAVE__CONTROLFP)
|
||||
|
||||
_controlfp(ctl->state, _MCW_DN);
|
||||
_controlfp(this->state, _MCW_DN);
|
||||
#endif
|
||||
this->in_mode = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -514,19 +514,19 @@ ALenum InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect
|
||||
EffectState *State{factory->create()};
|
||||
if(!State) return AL_OUT_OF_MEMORY;
|
||||
|
||||
START_MIXER_MODE(); {
|
||||
ALCdevice *Device{Context->Device};
|
||||
std::unique_lock<almtx_t> backlock{Device->BackendLock};
|
||||
State->mOutBuffer = Device->Dry.Buffer;
|
||||
State->mOutChannels = Device->Dry.NumChannels;
|
||||
if(State->deviceUpdate(Device) == AL_FALSE)
|
||||
{
|
||||
backlock.unlock();
|
||||
LEAVE_MIXER_MODE();
|
||||
State->DecRef();
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
} END_MIXER_MODE();
|
||||
FPUCtl mixer_mode{};
|
||||
ALCdevice *Device{Context->Device};
|
||||
std::unique_lock<almtx_t> backlock{Device->BackendLock};
|
||||
State->mOutBuffer = Device->Dry.Buffer;
|
||||
State->mOutChannels = Device->Dry.NumChannels;
|
||||
if(State->deviceUpdate(Device) == AL_FALSE)
|
||||
{
|
||||
backlock.unlock();
|
||||
mixer_mode.leave();
|
||||
State->DecRef();
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
mixer_mode.leave();
|
||||
|
||||
if(!effect)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user