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%
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