Donner SVG Editor & Engine
SVG-native editor and embeddable SVG2 + CSS3 engine in C++20, with GPU (WebGPU) and compact CPU renderers, built for correctness, security, and performance.
Loading...
Searching...
No Matches
donner::gpu::metal::MetalDevice Class Referencefinal

Metal backend of the Donner GPU runtime (design 0053 packet 6, the vertical-slice backend). More...

#include "donner/gpu/metal/MetalDevice.h"

Inheritance diagram for donner::gpu::metal::MetalDevice:
[legend]

Classes

struct  Impl
 Objective-C++ state of a MetalDevice: the Metal device and queue plus per-resource slot tables mirroring the validated slot indices handed to the on* hooks. More...

Public Member Functions

 ~MetalDevice () override
 Destructor; releases all Metal objects still alive.
uint64_t completedSerial () const override
 Serial of the most recent submission whose Metal command buffer has completed on the GPU (0 if none). Updated by completion handlers, which may run on another thread.
bool waitForSerial (uint64_t serial, double timeoutSeconds)
 Blocks until completedSerial reaches serial or timeoutSeconds elapses, by polling the completion counter (the completion handler runs on a Metal-internal thread, so a poll loop with a short sleep is sufficient and keeps this backend free of extra sync primitives).
Result< std::vector< uint8_t > > readBackBuffer (const Buffer &buffer)
 Copies the full contents of buffer back to the host and returns the bytes.
std::string lastErrorForTest () const
 Message of the most recent asynchronous command-buffer execution error captured by a completion handler, or an empty string if none occurred. Test/diagnostic accessor.
Public Member Functions inherited from donner::gpu::Device
virtual ~Device ()
 Destructor; frees all remaining resources.
 Device (const Device &)=delete
Device & operator= (const Device &)=delete
 Device (Device &&)=delete
Device & operator= (Device &&)=delete
uint64_t deviceId () const
 Process-unique identity of this device (starts at 1, never reused). Baked into every handle for cross-device validation.
Result< BuffercreateBuffer (const BufferDescriptor &descriptor)
 Creates a buffer.
Result< TexturecreateTexture (const TextureDescriptor &descriptor)
 Creates a 2D texture.
Result< TextureViewcreateTextureView (const Texture &texture, const TextureViewDescriptor &descriptor)
 Creates a view of texture covering the whole texture.
Result< SamplercreateSampler (const SamplerDescriptor &descriptor)
 Creates a sampler.
Result< BindGroupLayoutcreateBindGroupLayout (const BindGroupLayoutDescriptor &descriptor)
 Creates a bind group layout.
Result< BindGroupcreateBindGroup (const BindGroupDescriptor &descriptor)
 Creates a bind group.
Result< PipelineLayoutcreatePipelineLayout (const PipelineLayoutDescriptor &descriptor)
 Creates a pipeline layout.
Result< ShaderModulecreateShaderModule (const ShaderModuleDescriptor &descriptor)
 Creates a shader module from trusted generated source.
Result< RenderPipelinecreateRenderPipeline (const RenderPipelineDescriptor &descriptor)
 Creates a render pipeline.
Status destroyBuffer (const Buffer &buffer)
 Destroys a buffer; the handle and all references to it become stale.
Status destroyTexture (const Texture &texture)
 Destroys a texture; the handle and all references to it become stale.
Status destroyTextureView (const TextureView &textureView)
 Destroys a texture view; the handle and all references to it become stale.
Status destroySampler (const Sampler &sampler)
 Destroys a sampler; the handle and all references to it become stale.
Status destroyBindGroupLayout (const BindGroupLayout &bindGroupLayout)
 Destroys a bind group layout; the handle and all references to it become stale.
Status destroyBindGroup (const BindGroup &bindGroup)
 Destroys a bind group; the handle and all references to it become stale.
Status destroyPipelineLayout (const PipelineLayout &pipelineLayout)
 Destroys a pipeline layout; the handle and all references to it become stale.
Status destroyShaderModule (const ShaderModule &shaderModule)
 Destroys a shader module; the handle and all references to it become stale.
Status destroyRenderPipeline (const RenderPipeline &renderPipeline)
 Destroys a render pipeline; the handle and all references to it become stale.
Result< std::unique_ptr< CommandEncoder > > createCommandEncoder ()
 Creates a command encoder recording against this device. The encoder must not outlive the device.
Status writeBuffer (const Buffer &buffer, uint64_t offsetBytes, std::span< const uint8_t > data)
 Writes data into buffer at offsetBytes.
Status writeTexture (const Texture &texture, std::span< const uint8_t > data, const TexelCopyBufferLayout &dataLayout, const Extent2d &writeSize)
 Writes texel rows from data into texture starting at texel (0, 0).
Result< uint64_t > submit (CommandBuffer commandBuffer)
 Submits a finished command buffer, consuming it, and returns the assigned submission serial.
uint64_t lastSubmittedSerial () const
 Serial assigned to the most recent submission (0 if none yet).

Static Public Member Functions

static std::unique_ptr< MetalDevice > Create ()
 Creates a device on the system default Metal device.

Protected Member Functions

Status onCreateBuffer (uint32_t slotIndex, const BufferDescriptor &descriptor) override
 Backend hook: a buffer passed validation and occupies slotIndex.
Status onCreateTexture (uint32_t slotIndex, const TextureDescriptor &descriptor) override
 Backend hook: a texture passed validation and occupies slotIndex.
Status onCreateTextureView (uint32_t slotIndex, uint32_t textureSlotIndex, const TextureViewDescriptor &descriptor) override
 Backend hook: a texture view passed validation and occupies slotIndex.
Status onCreateSampler (uint32_t slotIndex, const SamplerDescriptor &descriptor) override
 Backend hook: a sampler passed validation and occupies slotIndex.
Status onCreateBindGroupLayout (uint32_t slotIndex, const BindGroupLayoutDescriptor &descriptor) override
 Backend hook: a bind group layout passed validation and occupies slotIndex.
Status onCreateBindGroup (uint32_t slotIndex, const BindGroupDescriptor &descriptor) override
 Backend hook: a bind group passed validation and occupies slotIndex.
Status onCreatePipelineLayout (uint32_t slotIndex, const PipelineLayoutDescriptor &descriptor) override
 Backend hook: a pipeline layout passed validation and occupies slotIndex.
Status onCreateShaderModule (uint32_t slotIndex, const ShaderModuleDescriptor &descriptor) override
 Backend hook: a shader module passed validation and occupies slotIndex.
Status onCreateRenderPipeline (uint32_t slotIndex, const RenderPipelineDescriptor &descriptor) override
 Backend hook: a render pipeline passed validation and occupies slotIndex.
void onDestroyResource (std::string_view resourceName, uint32_t slotIndex) override
 Backend hook: a validated resource was destroyed.
Status onWriteBuffer (uint32_t slotIndex, uint64_t offsetBytes, std::span< const uint8_t > data) override
 Backend hook: a validated buffer write.
Status onWriteTexture (uint32_t slotIndex, std::span< const uint8_t > data, const TexelCopyBufferLayout &dataLayout, const Extent2d &writeSize) override
 Backend hook: a validated texture write.
Status onSubmit (uint64_t submissionSerial, uint32_t commandBufferSlotIndex, std::span< const Command > commands) override
 Backend hook: a validated command buffer was submitted.
Protected Member Functions inherited from donner::gpu::Device
 Device ()
 Constructor for backends; assigns the process-unique device identity.
Status validateBufferHandleForBackend (const Buffer &buffer) const
 Validates a buffer handle for backend-provided auxiliary entry points (test readback helpers and similar), running the same null/device-identity/generation checks the template-method public API performs before its hooks.

Detailed Description

Metal backend of the Donner GPU runtime (design 0053 packet 6, the vertical-slice backend).

Inherits every fail-closed validation check from donner::gpu::Device; the on* hooks receive only validated input and translate it to Metal objects. Any Metal-side failure (nil object, compile error, encoder failure) fails closed with a donner::gpu::GpuError; the backend never crashes on such failures.

Scope is exactly the solid-fill vertical slice: shared-storage buffers and textures, MSL shader modules, one render pipeline family with a single vertex buffer layout at slot 0 and bind group 0 only, render passes with color attachments, and texture-to-buffer readback copies. Bindings follow the deterministic argument-table mapping in donner/gpu/shader/MslBindingMap.h: buffer binding b maps to Metal buffer index 1 + b, texture and sampler bindings map directly, and stage-in vertex data occupies vertex buffer index 30.

Resources use MTLStorageModeShared: this backend targets Apple Silicon's unified memory, so shared storage keeps queue writes (memcpy / replaceRegion) and buffer readback simple with no staging copies.

Threading: single-threaded use, matching donner::gpu::Device's thread affinity. The one exception is command-buffer completion handlers, which Metal invokes on an internal queue; they touch only atomics and a mutex-protected error string, observable through completedSerial, waitForSerial, and lastErrorForTest.

The header is pure C++ (Objective-C state lives behind a pimpl) so it is includable from C++ tests; the implementation is Objective-C++.


Class Documentation

◆ donner::gpu::metal::MetalDevice::Impl

struct donner::gpu::metal::MetalDevice::Impl

Objective-C++ state of a MetalDevice: the Metal device and queue plus per-resource slot tables mirroring the validated slot indices handed to the on* hooks.

Class Members
vector< optional< BindGroupLayoutDescriptor > > bindGroupLayouts Layout slots.
vector< optional< BindGroupRecord > > bindGroups Bind group slots.
vector< id< MTLBuffer > > buffers Buffer slots.
id< MTLCommandQueue > commandQueue = nil Lazily created on first submit.
shared_ptr< CompletionState > completionState Shared with completion handlers.
id< MTLDevice > device = nil The Metal device; set by Create.
vector< optional< PipelineLayoutDescriptor > > pipelineLayouts Pipeline layouts.
vector< optional< RenderPipelineRecord > > renderPipelines Render pipeline slots.
vector< id< MTLSamplerState > > samplers Sampler slots.
vector< id< MTLLibrary > > shaderLibraries Shader module slots.
vector< id< MTLTexture > > textures Texture slots.
vector< optional< uint32_t > > textureViewToTexture View slot -> texture slot.

Member Function Documentation

◆ completedSerial()

uint64_t donner::gpu::metal::MetalDevice::completedSerial ( ) const
overridevirtual

Serial of the most recent submission whose Metal command buffer has completed on the GPU (0 if none). Updated by completion handlers, which may run on another thread.

Implements donner::gpu::Device.

◆ Create()

std::unique_ptr< MetalDevice > donner::gpu::metal::MetalDevice::Create ( )
static

Creates a device on the system default Metal device.

Returns nullptr if no Metal device is available (for example on a CI host without a GPU).

◆ onCreateBindGroup()

Status donner::gpu::metal::MetalDevice::onCreateBindGroup ( uint32_t slotIndex,
const BindGroupDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a bind group passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateBindGroupLayout()

Status donner::gpu::metal::MetalDevice::onCreateBindGroupLayout ( uint32_t slotIndex,
const BindGroupLayoutDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a bind group layout passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateBuffer()

Status donner::gpu::metal::MetalDevice::onCreateBuffer ( uint32_t slotIndex,
const BufferDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a buffer passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreatePipelineLayout()

Status donner::gpu::metal::MetalDevice::onCreatePipelineLayout ( uint32_t slotIndex,
const PipelineLayoutDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a pipeline layout passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateRenderPipeline()

Status donner::gpu::metal::MetalDevice::onCreateRenderPipeline ( uint32_t slotIndex,
const RenderPipelineDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a render pipeline passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateSampler()

Status donner::gpu::metal::MetalDevice::onCreateSampler ( uint32_t slotIndex,
const SamplerDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a sampler passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateShaderModule()

Status donner::gpu::metal::MetalDevice::onCreateShaderModule ( uint32_t slotIndex,
const ShaderModuleDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a shader module passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateTexture()

Status donner::gpu::metal::MetalDevice::onCreateTexture ( uint32_t slotIndex,
const TextureDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a texture passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateTextureView()

Status donner::gpu::metal::MetalDevice::onCreateTextureView ( uint32_t slotIndex,
uint32_t textureSlotIndex,
const TextureViewDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a texture view passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
textureSlotIndexSlot index of the viewed texture.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onDestroyResource()

void donner::gpu::metal::MetalDevice::onDestroyResource ( std::string_view resourceName,
uint32_t slotIndex )
overrideprotectedvirtual

Backend hook: a validated resource was destroyed.

Parameters
resourceNameResource type name, e.g. "buffer".
slotIndexSlot index of the destroyed resource.

Implements donner::gpu::Device.

◆ onSubmit()

Status donner::gpu::metal::MetalDevice::onSubmit ( uint64_t submissionSerial,
uint32_t commandBufferSlotIndex,
std::span< const Command > commands )
overrideprotectedvirtual

Backend hook: a validated command buffer was submitted.

Parameters
submissionSerialSerial assigned to this submission.
commandBufferSlotIndexSlot the command buffer occupied before being consumed.
commandsValidated commands, in recording order.

Implements donner::gpu::Device.

◆ onWriteBuffer()

Status donner::gpu::metal::MetalDevice::onWriteBuffer ( uint32_t slotIndex,
uint64_t offsetBytes,
std::span< const uint8_t > data )
overrideprotectedvirtual

Backend hook: a validated buffer write.

Parameters
slotIndexDestination buffer slot.
offsetBytesDestination byte offset.
dataPayload bytes.

Implements donner::gpu::Device.

◆ onWriteTexture()

Status donner::gpu::metal::MetalDevice::onWriteTexture ( uint32_t slotIndex,
std::span< const uint8_t > data,
const TexelCopyBufferLayout & dataLayout,
const Extent2d & writeSize )
overrideprotectedvirtual

Backend hook: a validated texture write.

Parameters
slotIndexDestination texture slot.
dataPayload bytes.
dataLayoutRow layout of data.
writeSizeExtent written in texels.

Implements donner::gpu::Device.

◆ readBackBuffer()

Result< std::vector< uint8_t > > donner::gpu::metal::MetalDevice::readBackBuffer ( const Buffer & buffer)

Copies the full contents of buffer back to the host and returns the bytes.

Test/readback convenience for the vertical slice, pending the packet-7 buffer mapping API: it validates only device identity and slot liveness (not the handle generation), then reads the shared-storage Metal buffer contents directly. Callers must ensure relevant GPU work has completed first (see waitForSerial).

Parameters
bufferBuffer to read back; must be a live buffer of this device.

◆ waitForSerial()

bool donner::gpu::metal::MetalDevice::waitForSerial ( uint64_t serial,
double timeoutSeconds )

Blocks until completedSerial reaches serial or timeoutSeconds elapses, by polling the completion counter (the completion handler runs on a Metal-internal thread, so a poll loop with a short sleep is sufficient and keeps this backend free of extra sync primitives).

Returns false on timeout, and also returns false if any completed command buffer reported an execution error (see lastErrorForTest).

Parameters
serialSubmission serial to wait for.
timeoutSecondsMaximum time to wait, in seconds.

The documentation for this class was generated from the following files: