diff options
Diffstat (limited to 'Alc/alu.cpp')
-rw-r--r-- | Alc/alu.cpp | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/Alc/alu.cpp b/Alc/alu.cpp index a6e53f4b..3ea82354 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -1429,8 +1429,10 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray *slots) IncrementRef(&ctx->UpdateCount); } -void ProcessContext(ALCcontext *ctx, ALsizei SamplesToDo) +void ProcessContext(ALCcontext *ctx, const ALsizei SamplesToDo) { + ASSUME(SamplesToDo > 0); + const ALeffectslotArray *auxslots{ctx->ActiveAuxSlots.load(std::memory_order_acquire)}; /* Process pending propery updates for objects on the context. */ @@ -1465,7 +1467,42 @@ void ProcessContext(ALCcontext *ctx, ALsizei SamplesToDo) ); /* Process effects. */ - std::for_each(auxslots->slot, auxslots->slot+auxslots->count, + if(auxslots->count < 1) return; + auto slots = auxslots->slot; + auto slots_end = slots + auxslots->count; + + /* First sort the slots into scratch storage, so that effects come before + * their effect target (or their targets' target). + */ + auto sorted_slots = const_cast<ALeffectslot**>(slots_end); + auto sorted_slots_end = sorted_slots; + auto in_chain = [](const ALeffectslot *slot1, const ALeffectslot *slot2) noexcept -> bool + { + while((slot1=slot1->Params.Target) != nullptr) { + if(slot1 == slot2) return true; + } + return false; + }; + + *sorted_slots_end = *slots; + ++sorted_slots_end; + while(++slots != slots_end) + { + /* If this effect slot targets an effect slot already in the list (i.e. + * slots outputs to something in sorted_slots), directly or indirectly, + * insert it prior to that element. + */ + auto checker = sorted_slots; + do { + if(in_chain(*slots, *checker)) break; + } while(++checker != sorted_slots_end); + + checker = std::move_backward(checker, sorted_slots_end, sorted_slots_end+1); + *--checker = *slots; + ++sorted_slots_end; + } + + std::for_each(sorted_slots, sorted_slots_end, [SamplesToDo](const ALeffectslot *slot) -> void { EffectState *state{slot->Params.mEffectState}; |