SPB Git

spb/forge Public MIT

Forge — LLM training from scratch in pure C++20 + Metal on Apple Silicon.

C++ 61.2% C 23% Python 7.6% TeX 7.2% CMake 1.1%
17.2 KB · 465 lines cpp
Raw Blame History
1//-------------------------------------------------------------------------------------------------------------------------------------------------------------2//3// Metal/MTLCommandBuffer.hpp4//5// Copyright 2020-2025 Apple Inc.6//7// Licensed under the Apache License, Version 2.0 (the "License");8// you may not use this file except in compliance with the License.9// You may obtain a copy of the License at10//11//     http://www.apache.org/licenses/LICENSE-2.012//13// Unless required by applicable law or agreed to in writing, software14// distributed under the License is distributed on an "AS IS" BASIS,15// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.16// See the License for the specific language governing permissions and17// limitations under the License.18//19//-------------------------------------------------------------------------------------------------------------------------------------------------------------2021#pragma once2223#include "../Foundation/Foundation.hpp"24#include "MTLDefines.hpp"25#include "MTLHeaderBridge.hpp"26#include "MTLPrivate.hpp"27#include <CoreFoundation/CoreFoundation.h>28#include <cstdint>2930#include <functional>3132namespace MTL33{34class AccelerationStructureCommandEncoder;35class AccelerationStructurePassDescriptor;36class BlitCommandEncoder;37class BlitPassDescriptor;38class CommandBuffer;39class CommandBufferDescriptor;40class CommandQueue;41class ComputeCommandEncoder;42class ComputePassDescriptor;43class Device;44class Drawable;45class Event;46class LogContainer;47class LogState;48class ParallelRenderCommandEncoder;49class RenderCommandEncoder;50class RenderPassDescriptor;51class ResidencySet;52class ResourceStateCommandEncoder;53class ResourceStatePassDescriptor;54_MTL_ENUM(NS::UInteger, CommandBufferStatus) {55    CommandBufferStatusNotEnqueued = 0,56    CommandBufferStatusEnqueued = 1,57    CommandBufferStatusCommitted = 2,58    CommandBufferStatusScheduled = 3,59    CommandBufferStatusCompleted = 4,60    CommandBufferStatusError = 5,61};6263_MTL_ENUM(NS::UInteger, CommandBufferError) {64    CommandBufferErrorNone = 0,65    CommandBufferErrorInternal = 1,66    CommandBufferErrorTimeout = 2,67    CommandBufferErrorPageFault = 3,68    CommandBufferErrorBlacklisted = 4,69    CommandBufferErrorAccessRevoked = 4,70    CommandBufferErrorNotPermitted = 7,71    CommandBufferErrorOutOfMemory = 8,72    CommandBufferErrorInvalidResource = 9,73    CommandBufferErrorMemoryless = 10,74    CommandBufferErrorDeviceRemoved = 11,75    CommandBufferErrorStackOverflow = 12,76};7778_MTL_ENUM(NS::Integer, CommandEncoderErrorState) {79    CommandEncoderErrorStateUnknown = 0,80    CommandEncoderErrorStateCompleted = 1,81    CommandEncoderErrorStateAffected = 2,82    CommandEncoderErrorStatePending = 3,83    CommandEncoderErrorStateFaulted = 4,84};8586_MTL_ENUM(NS::UInteger, DispatchType) {87    DispatchTypeSerial = 0,88    DispatchTypeConcurrent = 1,89};9091_MTL_OPTIONS(NS::UInteger, CommandBufferErrorOption) {92    CommandBufferErrorOptionNone = 0,93    CommandBufferErrorOptionEncoderExecutionStatus = 1,94};9596using CommandBufferHandler = void (^)(CommandBuffer*);97using HandlerFunction = std::function<void(CommandBuffer*)>;9899class CommandBufferDescriptor : public NS::Copying<CommandBufferDescriptor>100{101public:102    static CommandBufferDescriptor* alloc();103104    CommandBufferErrorOption        errorOptions() const;105106    CommandBufferDescriptor*        init();107108    LogState*                       logState() const;109110    bool                            retainedReferences() const;111112    void                            setErrorOptions(MTL::CommandBufferErrorOption errorOptions);113114    void                            setLogState(const MTL::LogState* logState);115116    void                            setRetainedReferences(bool retainedReferences);117};118class CommandBufferEncoderInfo : public NS::Referencing<CommandBufferEncoderInfo>119{120public:121    NS::Array*               debugSignposts() const;122123    CommandEncoderErrorState errorState() const;124125    NS::String*              label() const;126};127class CommandBuffer : public NS::Referencing<CommandBuffer>128{129public:130    CFTimeInterval                       GPUEndTime() const;131132    CFTimeInterval                       GPUStartTime() const;133134    AccelerationStructureCommandEncoder* accelerationStructureCommandEncoder();135    AccelerationStructureCommandEncoder* accelerationStructureCommandEncoder(const MTL::AccelerationStructurePassDescriptor* descriptor);136137    void                                 addCompletedHandler(const MTL::CommandBufferHandler block);138    void                                 addCompletedHandler(const MTL::HandlerFunction& function);139140    void                                 addScheduledHandler(const MTL::CommandBufferHandler block);141    void                                 addScheduledHandler(const MTL::HandlerFunction& function);142143    BlitCommandEncoder*                  blitCommandEncoder();144    BlitCommandEncoder*                  blitCommandEncoder(const MTL::BlitPassDescriptor* blitPassDescriptor);145146    CommandQueue*                        commandQueue() const;147148    void                                 commit();149150    ComputeCommandEncoder*               computeCommandEncoder(const MTL::ComputePassDescriptor* computePassDescriptor);151    ComputeCommandEncoder*               computeCommandEncoder();152    ComputeCommandEncoder*               computeCommandEncoder(MTL::DispatchType dispatchType);153154    Device*                              device() const;155156    void                                 encodeSignalEvent(const MTL::Event* event, uint64_t value);157158    void                                 encodeWait(const MTL::Event* event, uint64_t value);159160    void                                 enqueue();161162    NS::Error*                           error() const;163    CommandBufferErrorOption             errorOptions() const;164165    CFTimeInterval                       kernelEndTime() const;166167    CFTimeInterval                       kernelStartTime() const;168169    NS::String*                          label() const;170171    LogContainer*                        logs() const;172173    ParallelRenderCommandEncoder*        parallelRenderCommandEncoder(const MTL::RenderPassDescriptor* renderPassDescriptor);174175    void                                 popDebugGroup();176177    void                                 presentDrawable(const MTL::Drawable* drawable);178    void                                 presentDrawableAfterMinimumDuration(const MTL::Drawable* drawable, CFTimeInterval duration);179180    void                                 presentDrawableAtTime(const MTL::Drawable* drawable, CFTimeInterval presentationTime);181182    void                                 pushDebugGroup(const NS::String* string);183184    RenderCommandEncoder*                renderCommandEncoder(const MTL::RenderPassDescriptor* renderPassDescriptor);185186    ResourceStateCommandEncoder*         resourceStateCommandEncoder();187    ResourceStateCommandEncoder*         resourceStateCommandEncoder(const MTL::ResourceStatePassDescriptor* resourceStatePassDescriptor);188189    bool                                 retainedReferences() const;190191    void                                 setLabel(const NS::String* label);192193    CommandBufferStatus                  status() const;194195    void                                 useResidencySet(const MTL::ResidencySet* residencySet);196    void                                 useResidencySets(const MTL::ResidencySet* const residencySets[], NS::UInteger count);197198    void                                 waitUntilCompleted();199200    void                                 waitUntilScheduled();201};202203}204_MTL_INLINE MTL::CommandBufferDescriptor* MTL::CommandBufferDescriptor::alloc()205{206    return NS::Object::alloc<MTL::CommandBufferDescriptor>(_MTL_PRIVATE_CLS(MTLCommandBufferDescriptor));207}208209_MTL_INLINE MTL::CommandBufferErrorOption MTL::CommandBufferDescriptor::errorOptions() const210{211    return Object::sendMessage<MTL::CommandBufferErrorOption>(this, _MTL_PRIVATE_SEL(errorOptions));212}213214_MTL_INLINE MTL::CommandBufferDescriptor* MTL::CommandBufferDescriptor::init()215{216    return NS::Object::init<MTL::CommandBufferDescriptor>();217}218219_MTL_INLINE MTL::LogState* MTL::CommandBufferDescriptor::logState() const220{221    return Object::sendMessage<MTL::LogState*>(this, _MTL_PRIVATE_SEL(logState));222}223224_MTL_INLINE bool MTL::CommandBufferDescriptor::retainedReferences() const225{226    return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(retainedReferences));227}228229_MTL_INLINE void MTL::CommandBufferDescriptor::setErrorOptions(MTL::CommandBufferErrorOption errorOptions)230{231    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setErrorOptions_), errorOptions);232}233234_MTL_INLINE void MTL::CommandBufferDescriptor::setLogState(const MTL::LogState* logState)235{236    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setLogState_), logState);237}238239_MTL_INLINE void MTL::CommandBufferDescriptor::setRetainedReferences(bool retainedReferences)240{241    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setRetainedReferences_), retainedReferences);242}243244_MTL_INLINE NS::Array* MTL::CommandBufferEncoderInfo::debugSignposts() const245{246    return Object::sendMessage<NS::Array*>(this, _MTL_PRIVATE_SEL(debugSignposts));247}248249_MTL_INLINE MTL::CommandEncoderErrorState MTL::CommandBufferEncoderInfo::errorState() const250{251    return Object::sendMessage<MTL::CommandEncoderErrorState>(this, _MTL_PRIVATE_SEL(errorState));252}253254_MTL_INLINE NS::String* MTL::CommandBufferEncoderInfo::label() const255{256    return Object::sendMessage<NS::String*>(this, _MTL_PRIVATE_SEL(label));257}258259_MTL_INLINE CFTimeInterval MTL::CommandBuffer::GPUEndTime() const260{261    return Object::sendMessage<CFTimeInterval>(this, _MTL_PRIVATE_SEL(GPUEndTime));262}263264_MTL_INLINE CFTimeInterval MTL::CommandBuffer::GPUStartTime() const265{266    return Object::sendMessage<CFTimeInterval>(this, _MTL_PRIVATE_SEL(GPUStartTime));267}268269_MTL_INLINE MTL::AccelerationStructureCommandEncoder* MTL::CommandBuffer::accelerationStructureCommandEncoder()270{271    return Object::sendMessage<MTL::AccelerationStructureCommandEncoder*>(this, _MTL_PRIVATE_SEL(accelerationStructureCommandEncoder));272}273274_MTL_INLINE MTL::AccelerationStructureCommandEncoder* MTL::CommandBuffer::accelerationStructureCommandEncoder(const MTL::AccelerationStructurePassDescriptor* descriptor)275{276    return Object::sendMessage<MTL::AccelerationStructureCommandEncoder*>(this, _MTL_PRIVATE_SEL(accelerationStructureCommandEncoderWithDescriptor_), descriptor);277}278279_MTL_INLINE void MTL::CommandBuffer::addCompletedHandler(const MTL::CommandBufferHandler block)280{281    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(addCompletedHandler_), block);282}283284_MTL_INLINE void MTL::CommandBuffer::addCompletedHandler(const MTL::HandlerFunction& function)285{286    __block HandlerFunction blockFunction = function;287    addCompletedHandler(^(MTL::CommandBuffer* pCommandBuffer) { blockFunction(pCommandBuffer); });288}289290_MTL_INLINE void MTL::CommandBuffer::addScheduledHandler(const MTL::CommandBufferHandler block)291{292    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(addScheduledHandler_), block);293}294295_MTL_INLINE void MTL::CommandBuffer::addScheduledHandler(const MTL::HandlerFunction& function)296{297    __block HandlerFunction blockFunction = function;298    addScheduledHandler(^(MTL::CommandBuffer* pCommandBuffer) { blockFunction(pCommandBuffer); });299}300301_MTL_INLINE MTL::BlitCommandEncoder* MTL::CommandBuffer::blitCommandEncoder()302{303    return Object::sendMessage<MTL::BlitCommandEncoder*>(this, _MTL_PRIVATE_SEL(blitCommandEncoder));304}305306_MTL_INLINE MTL::BlitCommandEncoder* MTL::CommandBuffer::blitCommandEncoder(const MTL::BlitPassDescriptor* blitPassDescriptor)307{308    return Object::sendMessage<MTL::BlitCommandEncoder*>(this, _MTL_PRIVATE_SEL(blitCommandEncoderWithDescriptor_), blitPassDescriptor);309}310311_MTL_INLINE MTL::CommandQueue* MTL::CommandBuffer::commandQueue() const312{313    return Object::sendMessage<MTL::CommandQueue*>(this, _MTL_PRIVATE_SEL(commandQueue));314}315316_MTL_INLINE void MTL::CommandBuffer::commit()317{318    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(commit));319}320321_MTL_INLINE MTL::ComputeCommandEncoder* MTL::CommandBuffer::computeCommandEncoder(const MTL::ComputePassDescriptor* computePassDescriptor)322{323    return Object::sendMessage<MTL::ComputeCommandEncoder*>(this, _MTL_PRIVATE_SEL(computeCommandEncoderWithDescriptor_), computePassDescriptor);324}325326_MTL_INLINE MTL::ComputeCommandEncoder* MTL::CommandBuffer::computeCommandEncoder()327{328    return Object::sendMessage<MTL::ComputeCommandEncoder*>(this, _MTL_PRIVATE_SEL(computeCommandEncoder));329}330331_MTL_INLINE MTL::ComputeCommandEncoder* MTL::CommandBuffer::computeCommandEncoder(MTL::DispatchType dispatchType)332{333    return Object::sendMessage<MTL::ComputeCommandEncoder*>(this, _MTL_PRIVATE_SEL(computeCommandEncoderWithDispatchType_), dispatchType);334}335336_MTL_INLINE MTL::Device* MTL::CommandBuffer::device() const337{338    return Object::sendMessage<MTL::Device*>(this, _MTL_PRIVATE_SEL(device));339}340341_MTL_INLINE void MTL::CommandBuffer::encodeSignalEvent(const MTL::Event* event, uint64_t value)342{343    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(encodeSignalEvent_value_), event, value);344}345346_MTL_INLINE void MTL::CommandBuffer::encodeWait(const MTL::Event* event, uint64_t value)347{348    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(encodeWaitForEvent_value_), event, value);349}350351_MTL_INLINE void MTL::CommandBuffer::enqueue()352{353    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(enqueue));354}355356_MTL_INLINE NS::Error* MTL::CommandBuffer::error() const357{358    return Object::sendMessage<NS::Error*>(this, _MTL_PRIVATE_SEL(error));359}360361_MTL_INLINE MTL::CommandBufferErrorOption MTL::CommandBuffer::errorOptions() const362{363    return Object::sendMessage<MTL::CommandBufferErrorOption>(this, _MTL_PRIVATE_SEL(errorOptions));364}365366_MTL_INLINE CFTimeInterval MTL::CommandBuffer::kernelEndTime() const367{368    return Object::sendMessage<CFTimeInterval>(this, _MTL_PRIVATE_SEL(kernelEndTime));369}370371_MTL_INLINE CFTimeInterval MTL::CommandBuffer::kernelStartTime() const372{373    return Object::sendMessage<CFTimeInterval>(this, _MTL_PRIVATE_SEL(kernelStartTime));374}375376_MTL_INLINE NS::String* MTL::CommandBuffer::label() const377{378    return Object::sendMessage<NS::String*>(this, _MTL_PRIVATE_SEL(label));379}380381_MTL_INLINE MTL::LogContainer* MTL::CommandBuffer::logs() const382{383    return Object::sendMessage<MTL::LogContainer*>(this, _MTL_PRIVATE_SEL(logs));384}385386_MTL_INLINE MTL::ParallelRenderCommandEncoder* MTL::CommandBuffer::parallelRenderCommandEncoder(const MTL::RenderPassDescriptor* renderPassDescriptor)387{388    return Object::sendMessage<MTL::ParallelRenderCommandEncoder*>(this, _MTL_PRIVATE_SEL(parallelRenderCommandEncoderWithDescriptor_), renderPassDescriptor);389}390391_MTL_INLINE void MTL::CommandBuffer::popDebugGroup()392{393    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(popDebugGroup));394}395396_MTL_INLINE void MTL::CommandBuffer::presentDrawable(const MTL::Drawable* drawable)397{398    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(presentDrawable_), drawable);399}400401_MTL_INLINE void MTL::CommandBuffer::presentDrawableAfterMinimumDuration(const MTL::Drawable* drawable, CFTimeInterval duration)402{403    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(presentDrawable_afterMinimumDuration_), drawable, duration);404}405406_MTL_INLINE void MTL::CommandBuffer::presentDrawableAtTime(const MTL::Drawable* drawable, CFTimeInterval presentationTime)407{408    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(presentDrawable_atTime_), drawable, presentationTime);409}410411_MTL_INLINE void MTL::CommandBuffer::pushDebugGroup(const NS::String* string)412{413    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(pushDebugGroup_), string);414}415416_MTL_INLINE MTL::RenderCommandEncoder* MTL::CommandBuffer::renderCommandEncoder(const MTL::RenderPassDescriptor* renderPassDescriptor)417{418    return Object::sendMessage<MTL::RenderCommandEncoder*>(this, _MTL_PRIVATE_SEL(renderCommandEncoderWithDescriptor_), renderPassDescriptor);419}420421_MTL_INLINE MTL::ResourceStateCommandEncoder* MTL::CommandBuffer::resourceStateCommandEncoder()422{423    return Object::sendMessage<MTL::ResourceStateCommandEncoder*>(this, _MTL_PRIVATE_SEL(resourceStateCommandEncoder));424}425426_MTL_INLINE MTL::ResourceStateCommandEncoder* MTL::CommandBuffer::resourceStateCommandEncoder(const MTL::ResourceStatePassDescriptor* resourceStatePassDescriptor)427{428    return Object::sendMessage<MTL::ResourceStateCommandEncoder*>(this, _MTL_PRIVATE_SEL(resourceStateCommandEncoderWithDescriptor_), resourceStatePassDescriptor);429}430431_MTL_INLINE bool MTL::CommandBuffer::retainedReferences() const432{433    return Object::sendMessage<bool>(this, _MTL_PRIVATE_SEL(retainedReferences));434}435436_MTL_INLINE void MTL::CommandBuffer::setLabel(const NS::String* label)437{438    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(setLabel_), label);439}440441_MTL_INLINE MTL::CommandBufferStatus MTL::CommandBuffer::status() const442{443    return Object::sendMessage<MTL::CommandBufferStatus>(this, _MTL_PRIVATE_SEL(status));444}445446_MTL_INLINE void MTL::CommandBuffer::useResidencySet(const MTL::ResidencySet* residencySet)447{448    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useResidencySet_), residencySet);449}450451_MTL_INLINE void MTL::CommandBuffer::useResidencySets(const MTL::ResidencySet* const residencySets[], NS::UInteger count)452{453    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(useResidencySets_count_), residencySets, count);454}455456_MTL_INLINE void MTL::CommandBuffer::waitUntilCompleted()457{458    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(waitUntilCompleted));459}460461_MTL_INLINE void MTL::CommandBuffer::waitUntilScheduled()462{463    Object::sendMessage<void>(this, _MTL_PRIVATE_SEL(waitUntilScheduled));464}465