Skip to content

Commit

Permalink
Make mSampleData an array of floats instead of an array of arrays
Browse files Browse the repository at this point in the history
This helps reduce the amount of unused memory in between the mixing channels'
storage, for better cache utilization.
  • Loading branch information
kcat committed Feb 28, 2024
1 parent 83c66ae commit 7668c35
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 11 deletions.
3 changes: 1 addition & 2 deletions core/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,7 @@ struct DeviceBase {
/* Temp storage used for mixer processing. */
static constexpr size_t MixerLineSize{BufferLineSize + DecoderBase::sMaxPadding};
static constexpr size_t MixerChannelsMax{16};
using MixerBufferLine = std::array<float,MixerLineSize>;
alignas(16) std::array<MixerBufferLine,MixerChannelsMax> mSampleData{};
alignas(16) std::array<float,MixerLineSize*MixerChannelsMax> mSampleData{};
alignas(16) std::array<float,MixerLineSize+MaxResamplerPadding> mResampleData{};

alignas(16) std::array<float,BufferLineSize> FilteredData{};
Expand Down
23 changes: 14 additions & 9 deletions core/voice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ struct NEONTag;
#endif


static_assert(!(sizeof(DeviceBase::MixerBufferLine)&15),
"DeviceBase::MixerBufferLine must be a multiple of 16 bytes");
static_assert(!(DeviceBase::MixerLineSize&3), "MixerLineSize must be a multiple of 4");
static_assert(!(MaxResamplerEdge&3), "MaxResamplerEdge is not a multiple of 4");

static_assert((BufferLineSize-1)/MaxPitch > 0, "MaxPitch is too large for BufferLineSize!");
Expand Down Expand Up @@ -780,10 +779,16 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi
*/
std::array<float*,DeviceBase::MixerChannelsMax> SamplePointers;
const al::span<float*> MixingSamples{SamplePointers.data(), mChans.size()};
auto get_bufferline = [](DeviceBase::MixerBufferLine &bufline) noexcept -> float*
{ return bufline.data(); };
std::transform(Device->mSampleData.end() - mChans.size(), Device->mSampleData.end(),
MixingSamples.begin(), get_bufferline);
{
const uint channelStep{(samplesToLoad+3u)&~3u};
auto base = Device->mSampleData.end() - mChans.size()*channelStep;
std::generate(MixingSamples.begin(), MixingSamples.end(), [&base,channelStep]
{
const auto ret = base;
base += channelStep;
return al::to_address(ret);
});
}

/* UHJ2 and SuperStereo only have 2 buffer channels, but 3 mixing channels
* (3rd channel is generated from decoding).
Expand Down Expand Up @@ -1180,11 +1185,11 @@ void Voice::prepare(DeviceBase *device)
uint num_channels{(mFmtChannels == FmtUHJ2 || mFmtChannels == FmtSuperStereo) ? 3 :
(mFmtChannels == FmtMonoDup) ? 2 :
ChannelsFromFmt(mFmtChannels, std::min(mAmbiOrder, device->mAmbiOrder))};
if(num_channels > device->mSampleData.size()) UNLIKELY
if(num_channels > device->MixerChannelsMax) UNLIKELY
{
ERR("Unexpected channel count: %u (limit: %zu, %d:%d)\n", num_channels,
device->mSampleData.size(), mFmtChannels, mAmbiOrder);
num_channels = static_cast<uint>(device->mSampleData.size());
device->MixerChannelsMax, mFmtChannels, mAmbiOrder);
num_channels = device->MixerChannelsMax;
}
if(mChans.capacity() > 2 && num_channels < mChans.capacity())
{
Expand Down

0 comments on commit 7668c35

Please sign in to comment.