Use a FlexArray for the context's voices
This commit is contained in:
+49
-96
@@ -2141,18 +2141,37 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
vprops = next;
|
||||
}
|
||||
|
||||
AllocateVoices(context, context->MaxVoices, old_sends);
|
||||
auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
|
||||
std::for_each(context->Voices, voices_end,
|
||||
[device](ALvoice *voice) -> void
|
||||
auto voices = context->Voices.get();
|
||||
auto voices_end = voices->begin() + context->VoiceCount.load(std::memory_order_relaxed);
|
||||
if(device->NumAuxSends < old_sends)
|
||||
{
|
||||
const ALsizei num_sends{device->NumAuxSends};
|
||||
/* Clear extraneous property set sends. */
|
||||
auto clear_sends = [num_sends](ALvoice &voice) -> void
|
||||
{
|
||||
delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
|
||||
std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
|
||||
ALvoiceProps::SendData{});
|
||||
|
||||
std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::SendData{});
|
||||
auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
|
||||
{
|
||||
std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
|
||||
SendParams{});
|
||||
};
|
||||
std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
|
||||
};
|
||||
std::for_each(voices->begin(), voices_end, clear_sends);
|
||||
}
|
||||
std::for_each(voices->begin(), voices_end,
|
||||
[device](ALvoice &voice) -> void
|
||||
{
|
||||
delete voice.mUpdate.exchange(nullptr, std::memory_order_acq_rel);
|
||||
|
||||
/* Force the voice to stopped if it was stopping. */
|
||||
ALvoice::State vstate{ALvoice::Stopping};
|
||||
voice->mPlayState.compare_exchange_strong(vstate, ALvoice::Stopped,
|
||||
voice.mPlayState.compare_exchange_strong(vstate, ALvoice::Stopped,
|
||||
std::memory_order_acquire, std::memory_order_acquire);
|
||||
if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
if(voice.mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
return;
|
||||
|
||||
if(device->AvgSpeakerDist > 0.0f)
|
||||
@@ -2162,7 +2181,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
(device->AvgSpeakerDist * device->Frequency)};
|
||||
auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void
|
||||
{ chandata.mDryParams.NFCtrlFilter.init(w1); };
|
||||
std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels,
|
||||
std::for_each(voice.mChans.begin(), voice.mChans.begin()+voice.mNumChannels,
|
||||
init_nfc);
|
||||
}
|
||||
}
|
||||
@@ -2430,11 +2449,8 @@ ALCcontext::~ALCcontext()
|
||||
}
|
||||
TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
|
||||
|
||||
std::for_each(Voices, Voices + MaxVoices, DeinitVoice);
|
||||
al_free(Voices);
|
||||
Voices = nullptr;
|
||||
VoiceCount.store(0, std::memory_order_relaxed);
|
||||
MaxVoices = 0;
|
||||
|
||||
ALlistenerProps *lprops{Listener.Update.exchange(nullptr, std::memory_order_relaxed)};
|
||||
if(lprops)
|
||||
@@ -2576,109 +2592,46 @@ ContextRef GetContextRef(void)
|
||||
}
|
||||
|
||||
|
||||
void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
|
||||
void AllocateVoices(ALCcontext *context, size_t num_voices)
|
||||
{
|
||||
ALCdevice *device{context->Device};
|
||||
const ALsizei num_sends{device->NumAuxSends};
|
||||
|
||||
if(num_voices == context->MaxVoices && num_sends == old_sends)
|
||||
if(context->Voices && num_voices == context->Voices->size())
|
||||
return;
|
||||
|
||||
/* Allocate the voice pointers, voices, and the voices' stored source
|
||||
* property set (including the dynamically-sized Send[] array) in one
|
||||
* chunk.
|
||||
*/
|
||||
const size_t sizeof_voice{RoundUp(sizeof(ALvoice), 16)};
|
||||
const size_t size{sizeof(ALvoice*) + sizeof_voice};
|
||||
std::unique_ptr<al::FlexArray<ALvoice>> voices;
|
||||
{
|
||||
void *ptr{al_calloc(16, al::FlexArray<ALvoice>::Sizeof(num_voices))};
|
||||
voices.reset(new (ptr) al::FlexArray<ALvoice>{num_voices});
|
||||
}
|
||||
|
||||
auto voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
|
||||
auto voice = reinterpret_cast<ALvoice*>(reinterpret_cast<char*>(voices) + RoundUp(num_voices*sizeof(ALvoice*), 16));
|
||||
|
||||
auto viter = voices;
|
||||
const ALsizei v_count{mini(context->VoiceCount.load(std::memory_order_relaxed), num_voices)};
|
||||
if(context->Voices)
|
||||
{
|
||||
const ALsizei v_count = mini(context->VoiceCount.load(std::memory_order_relaxed),
|
||||
num_voices);
|
||||
const ALsizei s_count = mini(old_sends, num_sends);
|
||||
|
||||
/* Copy the old voice data to the new storage. */
|
||||
auto copy_voice = [&voice,s_count](ALvoice *old_voice) -> ALvoice*
|
||||
auto viter = std::move(context->Voices->begin(), context->Voices->begin()+v_count,
|
||||
voices->begin());
|
||||
|
||||
/* Clear extraneous property set sends. */
|
||||
auto clear_sends = [num_sends](ALvoice &voice) -> void
|
||||
{
|
||||
voice = new (voice) ALvoice{};
|
||||
|
||||
/* Make sure the old voice's Update (if any) is cleared so it
|
||||
* doesn't get deleted on deinit.
|
||||
*/
|
||||
voice->mUpdate.store(old_voice->mUpdate.exchange(nullptr, std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
voice->mSourceID.store(old_voice->mSourceID.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
voice->mPlayState.store(old_voice->mPlayState.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
voice->mProps = old_voice->mProps;
|
||||
/* Clear extraneous property set sends. */
|
||||
std::fill(std::begin(voice->mProps.Send)+s_count, std::end(voice->mProps.Send),
|
||||
std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
|
||||
ALvoiceProps::SendData{});
|
||||
|
||||
voice->mPosition.store(old_voice->mPosition.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
voice->mPositionFrac.store(old_voice->mPositionFrac.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
voice->mCurrentBuffer.store(old_voice->mCurrentBuffer.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
voice->mLoopBuffer.store(old_voice->mLoopBuffer.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
voice->mFrequency = old_voice->mFrequency;
|
||||
voice->mFmtChannels = old_voice->mFmtChannels;
|
||||
voice->mNumChannels = old_voice->mNumChannels;
|
||||
voice->mSampleSize = old_voice->mSampleSize;
|
||||
|
||||
voice->mStep = old_voice->mStep;
|
||||
voice->mResampler = old_voice->mResampler;
|
||||
|
||||
voice->mResampleState = old_voice->mResampleState;
|
||||
|
||||
voice->mFlags = old_voice->mFlags;
|
||||
|
||||
voice->mDirect = old_voice->mDirect;
|
||||
voice->mSend = old_voice->mSend;
|
||||
voice->mChans = old_voice->mChans;
|
||||
|
||||
/* Clear old send data/params. */
|
||||
std::fill(voice->mSend.begin()+s_count, voice->mSend.end(), ALvoice::SendData{});
|
||||
auto clear_chan_sends = [s_count](ALvoice::ChannelData &chandata) -> void
|
||||
std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::SendData{});
|
||||
auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
|
||||
{
|
||||
std::fill(chandata.mWetParams.begin()+s_count, chandata.mWetParams.end(),
|
||||
std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
|
||||
SendParams{});
|
||||
};
|
||||
std::for_each(voice->mChans.begin(), voice->mChans.end(), clear_chan_sends);
|
||||
|
||||
/* Set this voice's reference. */
|
||||
ALvoice *ret{voice++};
|
||||
return ret;
|
||||
std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
|
||||
};
|
||||
viter = std::transform(context->Voices, context->Voices+v_count, viter, copy_voice);
|
||||
|
||||
/* Deinit old voices. */
|
||||
auto voices_end = context->Voices + context->MaxVoices;
|
||||
std::for_each(context->Voices, voices_end, DeinitVoice);
|
||||
std::for_each(voices->begin(), viter, clear_sends);
|
||||
}
|
||||
/* Finish setting the voices and references. */
|
||||
auto init_voice = [&voice]() -> ALvoice*
|
||||
{
|
||||
ALvoice *ret{new (voice++) ALvoice{}};
|
||||
return ret;
|
||||
};
|
||||
std::generate(viter, voices+num_voices, init_voice);
|
||||
|
||||
al_free(context->Voices);
|
||||
context->Voices = voices;
|
||||
context->MaxVoices = num_voices;
|
||||
context->VoiceCount = mini(context->VoiceCount.load(std::memory_order_relaxed), num_voices);
|
||||
context->Voices = std::move(voices);
|
||||
context->VoiceCount.store(v_count, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
|
||||
@@ -3439,7 +3392,7 @@ START_API_FUNC
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
AllocateVoices(context.get(), 256, dev->NumAuxSends);
|
||||
AllocateVoices(context.get(), 256);
|
||||
|
||||
if(DefaultEffect.type != AL_EFFECT_NULL && dev->Type == Playback)
|
||||
{
|
||||
|
||||
+2
-3
@@ -18,6 +18,7 @@
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "alListener.h"
|
||||
#include "alu.h"
|
||||
|
||||
|
||||
struct ALsource;
|
||||
@@ -26,7 +27,6 @@ struct ALcontextProps;
|
||||
struct ALlistenerProps;
|
||||
struct ALvoiceProps;
|
||||
struct ALeffectslotProps;
|
||||
struct ALvoice;
|
||||
struct RingBuffer;
|
||||
|
||||
enum class DistanceModel {
|
||||
@@ -116,9 +116,8 @@ struct ALCcontext {
|
||||
std::atomic<ALvoiceProps*> FreeVoiceProps{nullptr};
|
||||
std::atomic<ALeffectslotProps*> FreeEffectslotProps{nullptr};
|
||||
|
||||
ALvoice **Voices{nullptr};
|
||||
std::unique_ptr<al::FlexArray<ALvoice>> Voices{nullptr};
|
||||
std::atomic<ALsizei> VoiceCount{0};
|
||||
ALsizei MaxVoices{0};
|
||||
|
||||
using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
|
||||
std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
|
||||
|
||||
+19
-23
@@ -177,13 +177,6 @@ void aluInit(void)
|
||||
}
|
||||
|
||||
|
||||
void DeinitVoice(ALvoice *voice) noexcept
|
||||
{
|
||||
delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
|
||||
al::destroy_at(voice);
|
||||
}
|
||||
|
||||
|
||||
void aluSelectPostProcess(ALCdevice *device)
|
||||
{
|
||||
if(device->mHrtf)
|
||||
@@ -1359,11 +1352,12 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray *slots)
|
||||
{ return CalcEffectSlotParams(slot, ctx, cforce) | force; }
|
||||
);
|
||||
|
||||
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
[ctx,force](ALvoice *voice) -> void
|
||||
std::for_each(ctx->Voices->begin(),
|
||||
ctx->Voices->begin() + ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
[ctx,force](ALvoice &voice) -> void
|
||||
{
|
||||
ALuint sid{voice->mSourceID.load(std::memory_order_acquire)};
|
||||
if(sid) CalcSourceParams(voice, ctx, force);
|
||||
ALuint sid{voice.mSourceID.load(std::memory_order_acquire)};
|
||||
if(sid) CalcSourceParams(&voice, ctx, force);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1389,15 +1383,16 @@ void ProcessContext(ALCcontext *ctx, const ALsizei SamplesToDo)
|
||||
);
|
||||
|
||||
/* Process voices that have a playing source. */
|
||||
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
[SamplesToDo,ctx](ALvoice *voice) -> void
|
||||
std::for_each(ctx->Voices->begin(),
|
||||
ctx->Voices->begin() + ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
[SamplesToDo,ctx](ALvoice &voice) -> void
|
||||
{
|
||||
const ALvoice::State vstate{voice->mPlayState.load(std::memory_order_acquire)};
|
||||
const ALvoice::State vstate{voice.mPlayState.load(std::memory_order_acquire)};
|
||||
if(vstate == ALvoice::Stopped) return;
|
||||
const ALuint sid{voice->mSourceID.load(std::memory_order_relaxed)};
|
||||
if(voice->mStep < 1) return;
|
||||
const ALuint sid{voice.mSourceID.load(std::memory_order_relaxed)};
|
||||
if(voice.mStep < 1) return;
|
||||
|
||||
MixVoice(voice, vstate, sid, ctx, SamplesToDo);
|
||||
MixVoice(&voice, vstate, sid, ctx, SamplesToDo);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1788,14 +1783,15 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
|
||||
}
|
||||
}
|
||||
|
||||
auto stop_voice = [](ALvoice *voice) -> void
|
||||
auto stop_voice = [](ALvoice &voice) -> void
|
||||
{
|
||||
voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
|
||||
voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
|
||||
voice->mSourceID.store(0u, std::memory_order_relaxed);
|
||||
voice->mPlayState.store(ALvoice::Stopped, std::memory_order_release);
|
||||
voice.mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
|
||||
voice.mLoopBuffer.store(nullptr, std::memory_order_relaxed);
|
||||
voice.mSourceID.store(0u, std::memory_order_relaxed);
|
||||
voice.mPlayState.store(ALvoice::Stopped, std::memory_order_release);
|
||||
};
|
||||
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
std::for_each(ctx->Voices->begin(),
|
||||
ctx->Voices->begin() + ctx->VoiceCount.load(std::memory_order_acquire),
|
||||
stop_voice);
|
||||
|
||||
ctx = ctx->next.load(std::memory_order_relaxed);
|
||||
|
||||
@@ -532,7 +532,7 @@ struct AsyncEvent {
|
||||
};
|
||||
|
||||
|
||||
void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
|
||||
void AllocateVoices(ALCcontext *context, size_t num_voices);
|
||||
|
||||
|
||||
extern ALint RTPrioLevel;
|
||||
|
||||
+40
-2
@@ -278,10 +278,48 @@ struct ALvoice {
|
||||
|
||||
ALvoice() = default;
|
||||
ALvoice(const ALvoice&) = delete;
|
||||
~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
|
||||
ALvoice& operator=(const ALvoice&) = delete;
|
||||
};
|
||||
ALvoice& operator=(ALvoice&& rhs) noexcept
|
||||
{
|
||||
ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
|
||||
mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
void DeinitVoice(ALvoice *voice) noexcept;
|
||||
mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
|
||||
mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
mProps = rhs.mProps;
|
||||
|
||||
mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
|
||||
mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
|
||||
mFmtChannels = rhs.mFmtChannels;
|
||||
mFrequency = rhs.mFrequency;
|
||||
mNumChannels = rhs.mNumChannels;
|
||||
mSampleSize = rhs.mSampleSize;
|
||||
|
||||
mStep = rhs.mStep;
|
||||
mResampler = rhs.mResampler;
|
||||
|
||||
mResampleState = rhs.mResampleState;
|
||||
|
||||
mFlags = rhs.mFlags;
|
||||
|
||||
mDirect = rhs.mDirect;
|
||||
mSend = rhs.mSend;
|
||||
mChans = rhs.mChans;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
using MixerFunc = void(*)(const ALfloat *data, const al::span<FloatBufferLine> OutBuffer,
|
||||
|
||||
+31
-28
@@ -61,9 +61,9 @@ inline ALvoice *GetSourceVoice(ALsource *source, ALCcontext *context)
|
||||
if(idx >= 0 && idx < context->VoiceCount.load(std::memory_order_relaxed))
|
||||
{
|
||||
ALuint sid{source->id};
|
||||
ALvoice *voice{context->Voices[idx]};
|
||||
if(voice->mSourceID.load(std::memory_order_acquire) == sid)
|
||||
return voice;
|
||||
ALvoice &voice = (*context->Voices)[idx];
|
||||
if(voice.mSourceID.load(std::memory_order_acquire) == sid)
|
||||
return &voice;
|
||||
}
|
||||
source->VoiceIdx = -1;
|
||||
return nullptr;
|
||||
@@ -2777,12 +2777,13 @@ START_API_FUNC
|
||||
}
|
||||
|
||||
/* Count the number of reusable voices. */
|
||||
auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
|
||||
auto free_voices = std::accumulate(context->Voices, voices_end, ALsizei{0},
|
||||
[](const ALsizei count, const ALvoice *voice) noexcept -> ALsizei
|
||||
auto voices_end = context->Voices->begin() +
|
||||
context->VoiceCount.load(std::memory_order_relaxed);
|
||||
auto free_voices = std::accumulate(context->Voices->begin(), voices_end, ALsizei{0},
|
||||
[](const ALsizei count, const ALvoice &voice) noexcept -> ALsizei
|
||||
{
|
||||
if(voice->mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice->mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
if(voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice.mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
return count + 1;
|
||||
return count;
|
||||
}
|
||||
@@ -2790,20 +2791,21 @@ START_API_FUNC
|
||||
if(UNLIKELY(n > free_voices))
|
||||
{
|
||||
/* Increment the number of voices to handle the request. */
|
||||
const ALsizei need_voices{n - free_voices};
|
||||
const ALsizei rem_voices{context->MaxVoices -
|
||||
const ALuint need_voices{static_cast<ALuint>(n) - free_voices};
|
||||
const size_t rem_voices{context->Voices->size() -
|
||||
context->VoiceCount.load(std::memory_order_relaxed)};
|
||||
|
||||
if(UNLIKELY(need_voices > rem_voices))
|
||||
{
|
||||
/* Allocate more voices to get enough. */
|
||||
const ALsizei alloc_count{need_voices - rem_voices};
|
||||
if(UNLIKELY(context->MaxVoices > std::numeric_limits<ALsizei>::max()-alloc_count))
|
||||
const size_t alloc_count{need_voices - rem_voices};
|
||||
if(UNLIKELY(context->Voices->size() > std::numeric_limits<size_t>::max()-alloc_count))
|
||||
SETERR_RETURN(context.get(), AL_OUT_OF_MEMORY,,
|
||||
"Overflow increasing voice count to %d + %d", context->MaxVoices, alloc_count);
|
||||
"Overflow increasing voice count to %zu + %zu", context->Voices->size(),
|
||||
alloc_count);
|
||||
|
||||
const ALsizei newcount{context->MaxVoices + alloc_count};
|
||||
AllocateVoices(context.get(), newcount, device->NumAuxSends);
|
||||
const size_t newcount{context->Voices->size() + alloc_count};
|
||||
AllocateVoices(context.get(), newcount);
|
||||
}
|
||||
|
||||
context->VoiceCount.fetch_add(need_voices, std::memory_order_relaxed);
|
||||
@@ -2862,17 +2864,17 @@ START_API_FUNC
|
||||
}
|
||||
|
||||
/* Look for an unused voice to play this source with. */
|
||||
auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
|
||||
auto voice_iter = std::find_if(context->Voices, voices_end,
|
||||
[](const ALvoice *voice) noexcept -> bool
|
||||
auto voices_end = context->Voices->begin() +
|
||||
context->VoiceCount.load(std::memory_order_relaxed);
|
||||
voice = std::find_if(context->Voices->begin(), voices_end,
|
||||
[](const ALvoice &voice) noexcept -> bool
|
||||
{
|
||||
return voice->mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice->mSourceID.load(std::memory_order_relaxed) == 0u;
|
||||
return voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice.mSourceID.load(std::memory_order_relaxed) == 0u;
|
||||
}
|
||||
);
|
||||
assert(voice_iter != voices_end);
|
||||
auto vidx = static_cast<ALint>(std::distance(context->Voices, voice_iter));
|
||||
voice = *voice_iter;
|
||||
assert(voice != voices_end);
|
||||
auto vidx = static_cast<ALint>(std::distance(context->Voices->begin(), voice));
|
||||
voice->mPlayState.store(ALvoice::Stopped, std::memory_order_release);
|
||||
|
||||
source->PropsClean.test_and_set(std::memory_order_acquire);
|
||||
@@ -3557,14 +3559,15 @@ ALsource::~ALsource()
|
||||
|
||||
void UpdateAllSourceProps(ALCcontext *context)
|
||||
{
|
||||
auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
|
||||
std::for_each(context->Voices, voices_end,
|
||||
[context](ALvoice *voice) -> void
|
||||
auto voices_end = context->Voices->begin() +
|
||||
context->VoiceCount.load(std::memory_order_relaxed);
|
||||
std::for_each(context->Voices->begin(), voices_end,
|
||||
[context](ALvoice &voice) -> void
|
||||
{
|
||||
ALuint sid{voice->mSourceID.load(std::memory_order_acquire)};
|
||||
ALuint sid{voice.mSourceID.load(std::memory_order_acquire)};
|
||||
ALsource *source = sid ? LookupSource(context, sid) : nullptr;
|
||||
if(source && !source->PropsClean.test_and_set(std::memory_order_acq_rel))
|
||||
UpdateSourceProps(source, voice, context);
|
||||
UpdateSourceProps(source, &voice, context);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ struct FlexArray {
|
||||
|
||||
|
||||
const index_type mSize;
|
||||
alignas(alignment) element_type mArray[];
|
||||
alignas(alignment) element_type mArray[0];
|
||||
|
||||
static constexpr index_type Sizeof(index_type count, index_type base=0u) noexcept
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user