Repository: google/filament
File: filament/backend/src/metal/MetalDriver.mm (Objective-C++)

Code before:
    }
}

void MetalDriver::executeAfterCurrentCommandBufferCompletes(utils::Invocable<void()>&& fn) noexcept {
    mDeferredTasks.emplace_back(mContext->pendingCommandBufferId, std::move(fn));
}

void MetalDriver::executeDeferredOps() noexcept {
    for (; !mDeferredTasks.empty(); mDeferredTasks.pop_front()) {
        const auto& task = mDeferredTasks.front();
        if (task.commandBufferId <= mContext->latestCompletedCommandBufferId) {
            task.fn();
        } else {
            break;
        }
    }
}

MemoryMappedBufferHandle MetalDriver::mapBufferS() noexcept {
    return alloc_handle<MetalMemoryMappedBuffer>();
}

void MetalDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
        BufferObjectHandle boh, size_t offset,
        size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) {
    construct_handle<MetalMemoryMappedBuffer>(mmbh, mHandleAllocator, boh, offset, size, access);
    mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag));
}

void MetalDriver::unmapBuffer(MemoryMappedBufferHandle mmbh) {
    if (UTILS_UNLIKELY(!mmbh)) {
        return;
    }

    auto* mmb = handle_cast<MetalMemoryMappedBuffer>(mmbh);
    mmb->unmap(mHandleAllocator);
    destruct_handle<MetalMemoryMappedBuffer>(mmbh);
}

void MetalDriver::copyToMemoryMappedBuffer(MemoryMappedBufferHandle mmbh, size_t offset,
        BufferDescriptor&& data) {
    auto* mmb = handle_cast<MetalMemoryMappedBuffer>(mmbh);
    mmb->copy(*this, offset, std::move(data));
}

// explicit instantiation of the Dispatcher
template class ConcreteDispatcher<MetalDriver>;

} // namespace backend
} // namespace filament


Review comment (suggestion):
You can do the `handle_cast` here and pass in the `MetalBufferObject*` directly, that way we don't need to pass in the whole handle allocator. You can also check that `boh` is a valid handle here first.

Code after:
    }
}

void MetalDriver::executeAfterCurrentCommandBufferCompletes(utils::Invocable<void()>&& fn) noexcept {
    mDeferredTasks.emplace_back(mContext->pendingCommandBufferId, std::move(fn));
}

void MetalDriver::executeDeferredOps() noexcept {
    for (; !mDeferredTasks.empty(); mDeferredTasks.pop_front()) {
        const auto& task = mDeferredTasks.front();
        if (task.commandBufferId <= mContext->latestCompletedCommandBufferId) {
            task.fn();
        } else {
            break;
        }
    }
}

MemoryMappedBufferHandle MetalDriver::mapBufferS() noexcept {
    return alloc_handle<MetalMemoryMappedBuffer>();
}

void MetalDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
        BufferObjectHandle boh, size_t offset,
        size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) {
    assert_invariant(boh);
    MetalBufferObject* bo = mHandleAllocator.handle_cast<MetalBufferObject*>(boh);
    assert_invariant(bo);
    construct_handle<MetalMemoryMappedBuffer>(mmbh, bo, offset, size, access);
    mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag));
}

void MetalDriver::unmapBuffer(MemoryMappedBufferHandle mmbh) {
    if (UTILS_UNLIKELY(!mmbh)) {
        return;
    }

    auto* mmb = handle_cast<MetalMemoryMappedBuffer>(mmbh);
    mmb->unmap();
    destruct_handle<MetalMemoryMappedBuffer>(mmbh);
}

void MetalDriver::copyToMemoryMappedBuffer(MemoryMappedBufferHandle mmbh, size_t offset,
        BufferDescriptor&& data) {
    auto* mmb = handle_cast<MetalMemoryMappedBuffer>(mmbh);
    mmb->copy(*this, offset, std::move(data));
}

// explicit instantiation of the Dispatcher
template class ConcreteDispatcher<MetalDriver>;