diff options
Diffstat (limited to 'al/buffer.cpp')
-rw-r--r-- | al/buffer.cpp | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/al/buffer.cpp b/al/buffer.cpp index 7d043036..b7ed5b32 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -68,6 +68,8 @@ namespace { +using SubListAllocator = typename al::allocator<std::array<ALbuffer,64>>; + std::optional<AmbiLayout> AmbiLayoutFromEnum(ALenum layout) { switch(layout) @@ -178,21 +180,21 @@ bool EnsureBuffers(ALCdevice *device, size_t needed) [](size_t cur, const BufferSubList &sublist) noexcept -> size_t { return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })}; - while(needed > count) - { - if(device->BufferList.size() >= 1<<25) UNLIKELY - return false; - - device->BufferList.emplace_back(); - auto sublist = device->BufferList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Buffers = static_cast<ALbuffer*>(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64)); - if(!sublist->Buffers) UNLIKELY + try { + while(needed > count) { - device->BufferList.pop_back(); - return false; + if(device->BufferList.size() >= 1<<25) UNLIKELY + return false; + + BufferSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Buffers = SubListAllocator{}.allocate(1); + device->BufferList.emplace_back(std::move(sublist)); + count += 64; } - count += 64; + } + catch(...) { + return false; } return true; } @@ -206,7 +208,7 @@ ALbuffer *AllocBuffer(ALCdevice *device) auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALbuffer *buffer{al::construct_at(sublist->Buffers + slidx)}; + ALbuffer *buffer{al::construct_at(al::to_address(sublist->Buffers->begin() + slidx))}; /* Add 1 to avoid buffer ID 0. */ buffer->id = ((lidx<<6) | slidx) + 1; @@ -243,7 +245,7 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) BufferSubList &sublist = device->BufferList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Buffers + slidx; + return al::to_address(sublist.Buffers->begin() + slidx); } @@ -286,7 +288,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, const FmtChannels DstChannels, const FmtType DstType, const std::byte *SrcData, ALbitfieldSOFT access) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", ALBuf->id); @@ -393,7 +395,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, ALBUFFERCALLBACKTYPESOFT callback, void *userptr) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying callback for in-use buffer %u", ALBuf->id); @@ -402,6 +404,10 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const ALuint unpackalign{ALBuf->UnpackAlign}; const ALuint align{SanitizeAlignment(DstType, unpackalign)}; + if(align < 1) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u for %s samples", + unpackalign, NameFromFormat(DstType)); + const ALuint BlockSize{ChannelsFromFmt(DstChannels, ambiorder) * ((DstType == FmtIMA4) ? (align-1)/2 + 4 : (DstType == FmtMSADPCM) ? (align-2)/2 + 7 : @@ -445,7 +451,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, std::byte *sdata, const ALuint sdatalen) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", ALBuf->id); @@ -711,7 +717,7 @@ FORCE_ALIGN void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid); return false; } - if(ReadRef(ALBuf->ref) != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY { context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid); return false; @@ -826,7 +832,8 @@ FORCE_ALIGN void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint else { ALbitfieldSOFT unavailable = (albuf->Access^access) & access; - if(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0 + && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY context->setError(AL_INVALID_OPERATION, "Mapping in-use buffer %u without persistent mapping", buffer); else if(albuf->MappedAccess != 0) UNLIKELY @@ -1042,7 +1049,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, break; case AL_AMBISONIC_LAYOUT_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout", buffer); else if(const auto layout = AmbiLayoutFromEnum(value)) @@ -1052,7 +1059,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, break; case AL_AMBISONIC_SCALING_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling", buffer); else if(const auto scaling = AmbiScalingFromEnum(value)) @@ -1116,7 +1123,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer else switch(param) { case AL_LOOP_POINTS_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points", buffer); else if(values[0] < 0 || values[0] >= values[1] @@ -1366,7 +1373,7 @@ FORCE_ALIGN void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuin else switch(param) { case AL_BUFFER_CALLBACK_FUNCTION_SOFT: - *value = al::bit_cast<void*>(albuf->mCallback); + *value = reinterpret_cast<void*>(albuf->mCallback); break; case AL_BUFFER_CALLBACK_USER_PARAM_SOFT: *value = albuf->mUserData; @@ -1480,11 +1487,11 @@ BufferSubList::~BufferSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - std::destroy_at(Buffers+idx); + std::destroy_at(al::to_address(Buffers->begin() + idx)); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; - al_free(Buffers); + SubListAllocator{}.deallocate(Buffers, 1); Buffers = nullptr; } |