aboutsummaryrefslogtreecommitdiffstats
path: root/al/buffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'al/buffer.cpp')
-rw-r--r--al/buffer.cpp59
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;
}