Store a reference to the effect buffer as an active property

This commit is contained in:
Chris Robinson 2020-08-24 20:34:50 -07:00
parent 1a9fbc1b2f
commit a6bd53c4e1
5 changed files with 33 additions and 3 deletions

View File

@ -702,6 +702,8 @@ ALeffectslot::~ALeffectslot()
if(Params.mEffectState) if(Params.mEffectState)
Params.mEffectState->release(); Params.mEffectState->release();
if(Params.mEffectBuffer)
Params.mEffectBuffer->release();
} }
ALenum ALeffectslot::init() ALenum ALeffectslot::init()
@ -764,6 +766,7 @@ ALenum ALeffectslot::initEffect(ALeffect *effect, ALCcontext *context)
while(props) while(props)
{ {
props->State = nullptr; props->State = nullptr;
props->Buffer = nullptr;
props = props->next.load(std::memory_order_relaxed); props = props->next.load(std::memory_order_relaxed);
} }
@ -792,10 +795,8 @@ void ALeffectslot::updateProps(ALCcontext *context)
props->Type = Effect.Type; props->Type = Effect.Type;
props->Props = Effect.Props; props->Props = Effect.Props;
/* Swap out any stale effect state object there may be in the container, to
* delete it.
*/
props->State = Effect.State; props->State = Effect.State;
props->Buffer = Effect.Buffer;
/* Set the new container for updating internal parameters. */ /* Set the new container for updating internal parameters. */
props = Params.Update.exchange(props, std::memory_order_acq_rel); props = Params.Update.exchange(props, std::memory_order_acq_rel);
@ -805,6 +806,7 @@ void ALeffectslot::updateProps(ALCcontext *context)
* freelist. * freelist.
*/ */
props->State = nullptr; props->State = nullptr;
props->Buffer = nullptr;
AtomicReplaceHead(context->mFreeEffectslotProps, props); AtomicReplaceHead(context->mFreeEffectslotProps, props);
} }
} }

View File

@ -32,6 +32,7 @@ struct ALeffectslotProps {
EffectProps Props; EffectProps Props;
al::intrusive_ptr<EffectState> State; al::intrusive_ptr<EffectState> State;
al::intrusive_ptr<EffectBufferBase> Buffer;
std::atomic<ALeffectslotProps*> next; std::atomic<ALeffectslotProps*> next;
@ -67,6 +68,7 @@ struct ALeffectslot {
ALenum EffectType{AL_EFFECT_NULL}; ALenum EffectType{AL_EFFECT_NULL};
EffectProps mEffectProps{}; EffectProps mEffectProps{};
EffectState *mEffectState{nullptr}; EffectState *mEffectState{nullptr};
EffectBufferBase *mEffectBuffer{nullptr};
float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */ float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */
float DecayTime{0.0f}; float DecayTime{0.0f};

View File

@ -60,6 +60,11 @@ static int EventThread(ALCcontext *context)
evt.u.mEffectState->release(); evt.u.mEffectState->release();
continue; continue;
} }
if(evt.EnumType == EventType_ReleaseEffectBuffer)
{
evt.u.mEffectBuffer->release();
continue;
}
ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_acquire)}; ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_acquire)};
if(!context->mEventCb) continue; if(!context->mEventCb) continue;

View File

@ -6,6 +6,7 @@
#include "almalloc.h" #include "almalloc.h"
struct EffectBufferBase;
struct EffectState; struct EffectState;
@ -23,6 +24,7 @@ enum {
/* Internal events. */ /* Internal events. */
EventType_ReleaseEffectState = 65536, EventType_ReleaseEffectState = 65536,
EventType_ReleaseEffectBuffer,
}; };
struct AsyncEvent { struct AsyncEvent {
@ -44,6 +46,7 @@ struct AsyncEvent {
ALchar msg[232]; ALchar msg[232];
} user; } user;
EffectState *mEffectState; EffectState *mEffectState;
EffectBufferBase *mEffectBuffer;
} u{}; } u{};
AsyncEvent() noexcept = default; AsyncEvent() noexcept = default;

View File

@ -505,6 +505,24 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALeffectslot **sorted_slots, ALCco
} }
} }
EffectBufferBase *buffer{props->Buffer.release()};
EffectBufferBase *oldbuffer{slot->Params.mEffectBuffer};
slot->Params.mEffectBuffer = buffer;
if(oldbuffer && !oldbuffer->releaseIfNoDelete())
{
RingBuffer *ring{context->mAsyncEvents.get()};
auto evt_vec = ring->getWriteVector();
if LIKELY(evt_vec.first.len > 0)
{
AsyncEvent *evt{::new(evt_vec.first.buf) AsyncEvent{EventType_ReleaseEffectBuffer}};
evt->u.mEffectBuffer = oldbuffer;
ring->writeAdvance(1);
}
else
props->Buffer.reset(oldbuffer);
}
AtomicReplaceHead(context->mFreeEffectslotProps, props); AtomicReplaceHead(context->mFreeEffectslotProps, props);
EffectTarget output; EffectTarget output;