aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alSource.cpp
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-03-09 15:04:51 -0800
committerChris Robinson <[email protected]>2019-03-09 15:04:51 -0800
commitcde4500e24a8f5067d87711bf778cde99f26d990 (patch)
tree07fa77b29d6e344121e9b5dcdc2918feb8740435 /OpenAL32/alSource.cpp
parentd39cfcc7bb4f7c7ad6686bfc455785438d6b22ae (diff)
Increment the active voice count ahead of playing the sources
Diffstat (limited to 'OpenAL32/alSource.cpp')
-rw-r--r--OpenAL32/alSource.cpp34
1 files changed, 27 insertions, 7 deletions
diff --git a/OpenAL32/alSource.cpp b/OpenAL32/alSource.cpp
index 9b0e5672..e014a388 100644
--- a/OpenAL32/alSource.cpp
+++ b/OpenAL32/alSource.cpp
@@ -27,6 +27,7 @@
#include <cmath>
#include <thread>
#include <limits>
+#include <numeric>
#include <algorithm>
#include <functional>
@@ -2719,13 +2720,32 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
return;
}
- while(n > context->MaxVoices-context->VoiceCount.load(std::memory_order_relaxed))
+ /* 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
+ { return (voice->SourceID.load(std::memory_order_relaxed) == 0u) ? count+1 : count; }
+ );
+ if(UNLIKELY(n > free_voices))
{
- if(UNLIKELY(context->MaxVoices > std::numeric_limits<ALsizei>::max()>>1))
- SETERR_RETURN(context.get(), AL_OUT_OF_MEMORY,,
- "Overflow increasing voice count from %d", context->MaxVoices);
- ALsizei newcount = context->MaxVoices << 1;
- AllocateVoices(context.get(), newcount, device->NumAuxSends);
+ /* Increment the number of voices to handle the request. */
+ const ALsizei need_voices{n - free_voices};
+ const ALsizei rem_voices{context->MaxVoices -
+ 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))
+ SETERR_RETURN(context.get(), AL_OUT_OF_MEMORY,,
+ "Overflow increasing voice count to %d + %d", context->MaxVoices, alloc_count);
+
+ const ALsizei newcount{context->MaxVoices + alloc_count};
+ AllocateVoices(context.get(), newcount, device->NumAuxSends);
+ }
+
+ context->VoiceCount.fetch_add(need_voices, std::memory_order_relaxed);
}
auto start_source = [&context,device](ALuint sid) -> void
@@ -2786,10 +2806,10 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
[](const ALvoice *voice) noexcept -> bool
{ return voice->SourceID.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;
voice->Playing.store(false, std::memory_order_release);
- if(voice_iter == voices_end) context->VoiceCount.fetch_add(1, std::memory_order_acq_rel);
source->PropsClean.test_and_set(std::memory_order_acquire);
UpdateSourceProps(source, voice, context.get());