Skip to content

Commit

Permalink
Metal: track types of buffers (#7796)
Browse files Browse the repository at this point in the history
  • Loading branch information
bejado committed May 6, 2024
1 parent b7eb12b commit dd3b19c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 14 deletions.
62 changes: 51 additions & 11 deletions filament/backend/src/metal/MetalBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,42 @@ namespace filament::backend {

class TrackedMetalBuffer {
public:

enum class Type {
NONE = 0,
GENERIC = 1,
RING = 2,
STAGING = 3,
};
static constexpr size_t TypeCount = 3;

static constexpr auto toIndex(Type t) {
assert_invariant(t != Type::NONE);
switch (t) {
case Type::NONE:
case Type::GENERIC:
return 0;
case Type::RING:
return 1;
case Type::STAGING:
return 2;
}
}

TrackedMetalBuffer() noexcept : mBuffer(nil) {}
TrackedMetalBuffer(id<MTLBuffer> buffer) noexcept : mBuffer(buffer) {
TrackedMetalBuffer(nullptr_t) noexcept : mBuffer(nil) {}
TrackedMetalBuffer(id<MTLBuffer> buffer, Type type) : mBuffer(buffer), mType(type) {
assert_invariant(type != Type::NONE);
if (buffer) {
aliveBuffers++;
aliveBuffers[toIndex(type)]++;
mType = type;
}
}

~TrackedMetalBuffer() {
if (mBuffer) {
aliveBuffers--;
assert_invariant(mType != Type::NONE);
aliveBuffers[toIndex(mType)]--;
}
}

Expand All @@ -57,18 +84,29 @@ class TrackedMetalBuffer {
id<MTLBuffer> get() const noexcept { return mBuffer; }
operator bool() const noexcept { return bool(mBuffer); }

static uint64_t getAliveBuffers() { return aliveBuffers; }
static uint64_t getAliveBuffers() {
uint64_t sum = 0;
for (const auto& v : aliveBuffers) {
sum += v;
}
return sum;
}

static uint64_t getAliveBuffers(Type type) {
assert_invariant(type != Type::NONE);
return aliveBuffers[toIndex(type)];
}

private:
void swap(TrackedMetalBuffer& other) noexcept {
id<MTLBuffer> temp = mBuffer;
mBuffer = other.mBuffer;
other.mBuffer = temp;
std::swap(mBuffer, other.mBuffer);
std::swap(mType, other.mType);
}

id<MTLBuffer> mBuffer;
Type mType = Type::NONE;

static std::atomic<uint64_t> aliveBuffers;
static std::array<uint64_t, TypeCount> aliveBuffers;
};

class MetalBuffer {
Expand Down Expand Up @@ -171,7 +209,8 @@ class MetalRingBuffer {
mBufferOptions(options),
mSlotSizeBytes(computeSlotSize(layout)),
mSlotCount(slotCount) {
mBuffer = [device newBufferWithLength:mSlotSizeBytes * mSlotCount options:mBufferOptions];
mBuffer = { [device newBufferWithLength:mSlotSizeBytes * mSlotCount options:mBufferOptions],
TrackedMetalBuffer::Type::RING };
assert_invariant(mBuffer);
}

Expand All @@ -189,9 +228,10 @@ class MetalRingBuffer {
// If we already have an aux buffer, it will get freed here, unless it has been retained
// by a MTLCommandBuffer. In that case, it will be freed when the command buffer
// finishes executing.
mAuxBuffer = [mDevice newBufferWithLength:mSlotSizeBytes options:mBufferOptions];
mAuxBuffer = { [mDevice newBufferWithLength:mSlotSizeBytes options:mBufferOptions],
TrackedMetalBuffer::Type::RING };
assert_invariant(mAuxBuffer);
return {mAuxBuffer.get(), 0};
return { mAuxBuffer.get(), 0 };
}
mCurrentSlot = (mCurrentSlot + 1) % mSlotCount;
mOccupiedSlots->fetch_add(1, std::memory_order_relaxed);
Expand Down
5 changes: 3 additions & 2 deletions filament/backend/src/metal/MetalBuffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
namespace filament {
namespace backend {

std::atomic<uint64_t> TrackedMetalBuffer::aliveBuffers = 0;
std::array<uint64_t, TrackedMetalBuffer::TypeCount> TrackedMetalBuffer::aliveBuffers = { 0 };

MetalBuffer::MetalBuffer(MetalContext& context, BufferObjectBinding bindingType, BufferUsage usage,
size_t size, bool forceGpuBuffer) : mBufferSize(size), mContext(context) {
Expand All @@ -37,7 +37,8 @@
}

// Otherwise, we allocate a private GPU buffer.
mBuffer = [context.device newBufferWithLength:size options:MTLResourceStorageModePrivate];
mBuffer = { [context.device newBufferWithLength:size options:MTLResourceStorageModePrivate],
TrackedMetalBuffer::Type::GENERIC };
ASSERT_POSTCONDITION(mBuffer, "Could not allocate Metal buffer of size %zu.", size);
}

Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/metal/MetalBufferPool.mm
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
options:MTLResourceStorageModeShared];
ASSERT_POSTCONDITION(buffer, "Could not allocate Metal staging buffer of size %zu.", numBytes);
MetalBufferPoolEntry* stage = new MetalBufferPoolEntry {
.buffer = buffer,
.buffer = { buffer, TrackedMetalBuffer::Type::STAGING },
.capacity = numBytes,
.lastAccessed = mCurrentFrame,
.referenceCount = 1
Expand Down
6 changes: 6 additions & 0 deletions filament/backend/src/metal/MetalDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@
#endif
if (mPlatform.hasDebugUpdateStatFunc()) {
mPlatform.debugUpdateStat("filament.metal.alive_buffers", TrackedMetalBuffer::getAliveBuffers());
mPlatform.debugUpdateStat("filament.metal.alive_buffers.generic",
TrackedMetalBuffer::getAliveBuffers(TrackedMetalBuffer::Type::GENERIC));
mPlatform.debugUpdateStat("filament.metal.alive_buffers.ring",
TrackedMetalBuffer::getAliveBuffers(TrackedMetalBuffer::Type::RING));
mPlatform.debugUpdateStat("filament.metal.alive_buffers.staging",
TrackedMetalBuffer::getAliveBuffers(TrackedMetalBuffer::Type::STAGING));
}
}

Expand Down

0 comments on commit dd3b19c

Please sign in to comment.