Donner SVG 0.8.0
0.8.0 ยท ebf353960.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::gpu::metal::MetalDevice Class Referencefinal

Metal backend of the Donner GPU runtime. More...

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

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

Classes

struct  SystemCapabilities
 What the system default Metal device supports, which every device Create opens shares. More...
struct  GpuFamilies
 The GPU families a Metal device belongs to, as far as its 2D texture limit depends on them. More...
struct  WriteStats
 Snapshot of upload bookkeeping for tests and performance measurements. More...
struct  NativeTextureUsage
 Native texture access reported by Metal, exposed for allocation-contract tests. More...

Public Types

enum class  MemoryModel : uint8_t {
  Detected ,
  ForceNonUnified
}
 Which memory model the backend builds its resources for. More...

Public Member Functions

ShaderSourceKind shaderSourceKind () const override
 Native shader representation accepted by this device.
bool usesUnifiedMemoryForTest () const
 Whether this device's resources are built for unified memory. Test accessor.
uint64_t hostWritePublishCountForTest () const
 How many buffer writes have published their range to the device copy. Test accessor.
uint64_t deviceWritePublishCountForTest () const
 How many submissions have published the device's changes back to the host copy. Test accessor, for the same reason as above but in the other direction.
WriteStats writeStatsForTest () const
 Current queue-write counters. Does not wait or change device state.
Status pauseSubmissionsForTest ()
 Pauses submitted GPU work at a shared event until resumeSubmissionsForTest is called. A deterministic test seam for writes issued while an earlier submission is in flight. Each command buffer encoded while paused waits for its own turn, numbered from one in encoding order, so releasePausedCommandBuffersForTest can let them run a few at a time.
void releasePausedCommandBuffersForTest (uint64_t count)
 Lets the first count command buffers encoded since pauseSubmissionsForTest run and keeps the rest paused. It only signals a shared event, so another thread may call it while the device's own thread waits, provided that thread does not pause or resume meanwhile. Does nothing when no pause is active.
void resumeSubmissionsForTest ()
 Releases the event installed by pauseSubmissionsForTest. Safe when no pause is active.
void failNextSubmissionForTest (std::optional< size_t > commandBufferIndex=std::nullopt)
 Makes one command buffer of the next submission report an execution error when it completes, as a command buffer the GPU faulted on does, through the same completion path.
void holdNextCompletionForTest ()
 Parks the completion of the next submission when its handler runs, as a GPU that has not finished that work yet looks: the handler records its outcome but publishes nothing until releaseHeldCompletionForTest. Later submissions complete normally meanwhile.
void releaseHeldCompletionForTest ()
 Publishes the completion holdNextCompletionForTest parked, from the calling thread, or lets it publish normally when its handler has not run yet. Safe when nothing is held, and callable from any thread while the device's own thread waits.
void setPresentCompletionTimeoutForTest (std::chrono::milliseconds timeout)
 Bounds how long a present's wait for its frame's work may go without progress, in place of the five seconds it otherwise allows, so a case reaches the bound without spending it, and before the system's own timeout ends a command buffer that makes no progress.
void setSubmissionStallTimeoutForTest (std::chrono::milliseconds timeout)
 Bounds how long a submission waits for room among the command buffers in flight while neither this device nor a device its waiting work depends on completes any, in place of the five seconds it otherwise allows.
void setSubmissionWaitCapForTest (std::chrono::milliseconds timeout)
 Bounds how long one submission waits for room in all, in place of the sixty seconds it otherwise allows, however much progress it sees meanwhile.
uint64_t commandBufferRoomWaitsForTest () const
 How many submissions found too many command buffers in flight and waited for room, whether or not they were then committed. Test accessor, readable from any thread.
uint64_t commandBuffersInFlightForTest () const
 Command buffers committed and not yet completed, as the backstop counts them. Test accessor, readable from any thread.
uint64_t serialWaitLooksForTest () const
 How many times serial waits on this device have looked at its completion state, so a case can tell a wait that looks only when that state changes from one that keeps checking. Test accessor, readable from any thread.
bool waitForCompletionHandlersForTest (uint64_t count, double timeoutSeconds) const
 Waits until count submissions have had all their completion handlers run on this device, parked ones included. Test seam for ordering completions deterministically.
 ~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.
Result< std::vector< uint8_t > > readBackBuffer (const Buffer &buffer)
 Copies the full contents of buffer back to the host and returns the bytes.
Result< NativeTextureUsage > textureUsageForTest (const Texture &texture) const
 Reads native usage after validating the texture's device, liveness, and generation.
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; expires the device-alive token (so handles that outlive the device release nothing) and frees all remaining resources. Backends that submit asynchronously must wait for in-flight submissions in their own destructor before backend state is torn down.
 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.
bool isLost () const
 True once the backend root this device drives has been declared lost, either by the backend's device-lost callback or by a bounded wait giving up on it.
DeviceLossSnapshot deviceLossSnapshot () const
 First-winner loss attribution, once its diagnostic fields have settled.
virtual RcString deviceLostReason () const
 Backend-provided loss reason, when the backend retains one. Empty otherwise.
void markLostAfterWaitTimeout (DeviceLostWaitSite site, std::chrono::milliseconds elapsed, const char *reason) const
 Declares this device's backend root lost because a bounded wait gave up, recording which wait it was and how long it actually ran.
virtual bool supportsFullIndexRange (IndexFormat format) const
 Whether indexed draws through this device honor every value of format. Metal and WebGPU always do; a Vulkan device without fullDrawIndexUint32 caps 32-bit indices below the full range, and RenderPassEncoder::setIndexBuffer refuses that format on it rather than let a driver truncate index values.
Result< Buffer > createBuffer (const BufferDescriptor &descriptor)
 Creates a buffer.
Result< Texture > createTexture (const TextureDescriptor &descriptor)
 Creates a 2D texture.
Result< TextureDescriptor > textureDescriptor (const Texture &texture) const
 Returns the descriptor texture was created with, by value.
Result< TextureView > createTextureView (const Texture &texture, const TextureViewDescriptor &descriptor)
 Creates a view of texture covering the whole texture.
Result< Sampler > createSampler (const SamplerDescriptor &descriptor)
 Creates a sampler.
Result< BindGroupLayout > createBindGroupLayout (const BindGroupLayoutDescriptor &descriptor)
 Creates a bind group layout.
Result< BindGroup > createBindGroup (const BindGroupDescriptor &descriptor)
 Creates a bind group.
Result< PipelineLayout > createPipelineLayout (const PipelineLayoutDescriptor &descriptor)
 Creates a pipeline layout.
Result< ShaderModule > createShaderModule (const ShaderModuleDescriptor &descriptor)
 Creates a shader module from trusted generated source.
Result< RenderPipeline > createRenderPipeline (const RenderPipelineDescriptor &descriptor)
 Creates a render pipeline.
Result< ComputePipeline > createComputePipeline (const ComputePipelineDescriptor &descriptor)
 Creates a compute pipeline.
Status destroyBuffer (Buffer &&buffer)
 Destroys a buffer (see the destroy contract above).
Status destroyTexture (Texture &&texture)
 Destroys a texture (see the destroy contract above).
Status destroyTextureView (TextureView &&textureView)
 Destroys a texture view (see the destroy contract above).
Status destroySampler (Sampler &&sampler)
 Destroys a sampler (see the destroy contract above).
Status destroyBindGroupLayout (BindGroupLayout &&bindGroupLayout)
 Destroys a bind group layout (see the destroy contract above).
Status destroyBindGroup (BindGroup &&bindGroup)
 Destroys a bind group (see the destroy contract above).
Status destroyPipelineLayout (PipelineLayout &&pipelineLayout)
 Destroys a pipeline layout (see the destroy contract above).
Status destroyShaderModule (ShaderModule &&shaderModule)
 Destroys a shader module (see the destroy contract above).
Status destroyRenderPipeline (RenderPipeline &&renderPipeline)
 Destroys a render pipeline (see the destroy contract above).
Status destroyComputePipeline (ComputePipeline &&computePipeline)
 Destroys a compute pipeline (see the destroy contract above).
Status destroyBufferBacking (Buffer &&buffer)
 Destroys buffer and releases its backend allocation at once, rather than leaving the allocation to the backend's own collector.
Status destroyTextureBacking (Texture &&texture)
 Destroys texture and releases its backend allocation at once, the texture counterpart of destroyBufferBacking; a succession of resized render targets is where the deferred release shows up as retained memory.
bool ownsTextureBacking (const Texture &texture) const
 Whether texture names backing this device allocated, rather than memory some other owner holds and this device only named.
Result< TextureExport > exportTexture (const Texture &texture)
 Exports texture so another runtime device over the same backend device can register it.
Result< Texture > registerTexture (const TextureExport &source)
 Registers a texture another runtime device exported, as a read-only texture of this one.
bool waitForTextureSource (const Texture &registration, double timeoutSeconds)
 Waits until work naming registration may be submitted, the budget runs out, or either device is lost, and reports whether it may.
SerialWaitResult waitForTextureSourceUnlessStalled (const Texture &registration, std::chrono::milliseconds stallBound)
 waitForTextureSource for a caller whose bound exists to detect a hung producer: the wait gives up only once the producer has made no progress for stallBound, measured from that progress, rather than giving the producer's whole backlog a fixed budget.
uint64_t sharedTextureTailBytes () const
 Bytes of this device's exported textures that are still held by an export token or a registration after this device released its own handle.
Result< std::unique_ptr< CommandEncoder > > createCommandEncoder ()
 Creates a command encoder recording against this device. The encoder must not outlive the device.
Result< Surface > createSurface (const SurfaceDescriptor &descriptor)
 Creates a surface presenting to a platform object.
Result< SurfaceCapabilities > surfaceCapabilities (const Surface &surface) const
 What surface supports, for choosing a configuration.
Status configureSurface (const Surface &surface, const SurfaceConfiguration &configuration)
 Configures how surface presents, replacing any previous configuration.
Result< SurfaceTexture > acquireCurrentTexture (const Surface &surface)
 Acquires the texture for the next frame of surface.
Result< SurfaceStatus > presentSurface (const Surface &surface)
 Presents the texture acquired from surface and invalidates it.
Status abandonCurrentTexture (const Surface &surface)
 Releases the acquired texture of surface without presenting it, for a frame the caller decided not to show.
Status destroySurface (Surface &&surface)
 Destroys a surface (see the destroy contract above).
Result< BufferMapping > mapBufferAsync (const Buffer &buffer, MapMode mode, uint64_t offsetBytes, uint64_t byteCount)
 Begins mapping a range of buffer for host access, and returns the handle that names the mapping.
Result< MapSliceReport > pollMapping (const BufferMapping &mapping)
 Polls a mapping once without blocking or yielding; ready mappings become readable.
Result< MapWaitReport > waitForMapping (const BufferMapping &mapping, const MapWaitParams &params, const std::function< bool()> &shouldCancel, const MapWaitTestHooks &testHooks={})
 Waits for a pending mapping in slices, until it completes, the caller stops it, the budget runs out, or the device is lost.
Result< std::span< const uint8_t > > mappedBytes (const BufferMapping &mapping) const
 Returns the mapped bytes of a completed mapping.
Status unmapBuffer (BufferMapping &&mapping)
 Releases a mapping, invalidating the handle and every copy of it.
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, const Origin2d &destinationOrigin={})
 Writes texel rows from data into the writeSize rectangle of texture whose top-left texel is destinationOrigin, leaving every texel outside that rectangle unchanged.
Result< uint64_t > submit (CommandBuffer commandBuffer)
 Submits a finished command buffer, consuming it, and returns the assigned submission serial.
Result< uint64_t > submit (std::span< CommandBuffer > commandBuffers)
 Submits finished command buffers as one submission, consuming them, and returns the single assigned submission serial.
void poll ()
 Processes deferred destructions: releases the backend object of every destroyed resource whose last referencing submission has completed (completedSerial), and recycles its slot.
void pollCompletionOnce ()
 Drive one nonblocking backend completion iteration even when no resource destroy is pending.
bool hasPendingDestroys () const
 Whether a completed submission can still release a backend object. Owner-thread only.
uint64_t lastSubmittedSerial () const
 Serial assigned to the most recent submission (0 if none yet).
bool waitForSerial (uint64_t serial, double timeoutSeconds)
 Blocks until completedSerial reaches serial, timeoutSeconds elapses, or the backend gives up on the work, and reports whether the submission completed.
SerialWaitResult waitForSerialUnlessStalled (uint64_t serial, std::chrono::milliseconds stallBound)
 Blocks until completedSerial reaches serial, giving up only when the work the serial waits behind stops making progress.
std::optional< std::chrono::steady_clock::time_point > lastProgress ()
 When the work this device's submissions wait behind last made progress, or nothing when the backend has no notion of progress.
Status installObserver (DeviceObserver &observer)
 Installs observer to be notified of the work this device accepts (see DeviceObserver).
void removeObserver (const DeviceObserver &observer)
 Removes observer when it is the installed one and otherwise changes nothing, so an owner can only ever remove its own.
const DeviceObserver * observer () const
 The installed observer, or null when there is none.

Static Public Member Functions

static uint32_t MaxTextureDimension2DFor (GpuFamilies families)
 Largest width or height of a 2D texture a device of families allocates, from Metal's feature set tables: 16,384 for every Mac family and for Apple family 3 onward, and 8,192 for the earlier Apple families.
static std::optional< SystemCapabilities > QuerySystemCapabilities ()
 Asks the system default Metal device, the one Create opens, what it supports without opening a runtime device over it.
static std::unique_ptr< MetalDevice > Create (MemoryModel memoryModel=MemoryModel::Detected, uint64_t uploadStagingByteBudget=kMaxBufferByteSize, std::chrono::milliseconds unalignedWriteTimeout=std::chrono::seconds(5), std::shared_ptr< DeviceLostState > lostState=nullptr)
 Creates a device on the system default Metal device.

Static Public Attributes

static constexpr uint64_t kMaxCommandBuffersInFlight = 512
 Most command buffers a device leaves uncompleted on the GPU at once. A submission that would exceed it first waits for earlier ones to complete. It is a backstop against runaway work rather than a pacing bound: ordinary frames stay far below it, and it is the ceiling the native queue imposed before, now with a wait that is bounded instead of one that is not.
Static Public Attributes inherited from donner::gpu::Device
static constexpr size_t kMaxCommandBuffersPerSubmission = 256
 Most command buffers one submission may carry.
static constexpr double kMaxWaitSeconds = 1.0e6
 Longest a single waitForSerial may block, in seconds. A budget above this is clamped to it; the value is far past any deadline a caller has, and keeps the conversion to the clock's own duration from overflowing on a caller that means "wait indefinitely" and says so with a very large number.

Protected Member Functions

BackendDeviceIdentity backendDeviceIdentity () const override
 Identifies the MTLDevice this device records against, so a sibling device over the same MTLDevice can register its textures.
Result< BackendTextureExport > onExportTexture (uint32_t slotIndex) override
 Exports the texture in slotIndex.
Status onRegisterTexture (uint32_t slotIndex, const ExportedTextureBacking &backing) override
 Names another device's exported texture in slotIndex, refusing one created by a different MTLDevice object, which Metal would not accept in this device's command buffers.
bool onTextureWritePending (uint32_t slotIndex) const override
 Whether the write just accepted for slotIndex was queued for the next submission because earlier work still used the texture.
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.
Status onCreateComputePipeline (uint32_t slotIndex, const ComputePipelineDescriptor &descriptor) override
 Backend hook: a compute pipeline passed validation and occupies slotIndex.
void onRetireBuffer (uint32_t slotIndex) override
 Backend hook: a buffer handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.
void onRetireTexture (uint32_t slotIndex) override
 Backend hook: a texture handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.
void onDestroyResource (std::string_view resourceName, uint32_t slotIndex) override
 Backend hook: a retired resource is no longer used by submitted work and can be released.
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, const Origin2d &destinationOrigin) override
 Backend hook: a validated texture write. The written rectangle is writeSize texels wide and tall with its top-left texel at destinationOrigin; texels outside it keep their contents.
Status onSubmit (uint64_t submissionSerial, std::span< const SubmittedCommandBuffer > commandBuffers) override
 Backend hook: validated command buffers were submitted as one submission.
Status onSubmitAfterSources (uint64_t submissionSerial, std::span< const SubmittedCommandBuffer > commandBuffers, std::span< const SourceWait > waits) override
 Places a GPU wait on each producer's completion event at the start of the submission's first command buffer, one per producer at the latest serial it needs, then submits.
Status onCreateSurface (uint32_t slotIndex, const SurfaceDescriptor &descriptor) override
 Backend hook: create a surface for a platform object.
Result< SurfaceCapabilities > onSurfaceCapabilities (uint32_t slotIndex) const override
 Backend hook: what a surface supports.
Status onConfigureSurface (uint32_t slotIndex, const SurfaceConfiguration &configuration) override
 Backend hook: apply a configuration.
Result< SurfaceStatus > onAcquireCurrentTexture (uint32_t slotIndex, uint32_t textureSlotIndex) override
 Backend hook: acquire the next frame's texture and report the surface's state.
Result< SurfaceStatus > onPresentSurface (uint32_t slotIndex) override
 Backend hook: present the acquired texture.
void onAbandonCurrentTexture (uint32_t slotIndex) override
 Backend hook: drop the acquired texture without presenting.
void onDestroySurface (uint32_t slotIndex) override
 Backend hook: release the platform state of a surface that is going away.
Status onMapBufferAsync (uint32_t mappingSlotIndex, uint32_t bufferSlotIndex, MapMode mode, uint64_t offsetBytes, uint64_t byteCount) override
 Backend hook: begin mapping a buffer range.
MapSliceReport onWaitMappingSlice (uint32_t mappingSlotIndex, double sliceSeconds) override
 Backend hook: wait up to sliceSeconds for a pending mapping, and report what it found and how it spent the slice.
bool onWaitForSerial (uint64_t serial, double timeoutSeconds) override
 Sleeps until the completion counter reaches serial, the budget runs out, a completed command buffer reports an execution error (see lastErrorForTest), or the root is declared lost.
SerialWaitResult onWaitForSerialUnlessStalled (uint64_t serial, std::chrono::milliseconds stallBound) override
 Waits for serial on the progress clock the backstop on work in flight uses: the wait gives up once neither this device nor a producer its uncompleted work waits on has made progress for stallBound, measured from that progress.
std::optional< std::chrono::steady_clock::time_point > onLastProgress () override
 The latest progress of this device and of the producers its uncompleted submissions wait on, as the backstop on work in flight measures it.
Result< std::span< const uint8_t > > onMappedBytes (uint32_t mappingSlotIndex) const override
 Backend hook: bytes of a completed mapping.
void onUnmapBuffer (uint32_t mappingSlotIndex) override
 Backend hook: release a mapping.
Protected Member Functions inherited from donner::gpu::Device
 Device ()
 Constructor for backends; assigns the process-unique device identity.
virtual void onPollBackend ()
 One nonblocking backend event iteration before a pending-destroy scan. Native devices report completion directly; callback-driven adapters override this hook.
void adoptLostState (std::shared_ptr< DeviceLostState > state)
 Adopts the sticky loss condition of a backend root this device shares with another device.
uint64_t bufferLastUseSerial (uint32_t slotIndex) const
 Last accepted submission referencing a buffer slot already validated by the caller.
uint64_t textureLastUseSerial (uint32_t slotIndex) const
 Last accepted submission referencing a texture slot already validated by the caller.
virtual void onDestroyBufferBacking (uint32_t slotIndex)
 Backend hook: destroyBufferBacking validated slotIndex and is about to destroy its handle; release the allocation now rather than when the slot is recycled.
virtual void onDestroyTextureBacking (uint32_t slotIndex)
 Backend hook: the texture counterpart of onDestroyBufferBacking, with the same default. A slot whose backing this device does not own keeps its allocation.
virtual bool onOwnsTextureBacking (uint32_t slotIndex) const
 Backend hook: whether slotIndex holds backing this device allocated.
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.
Status validateTextureHandleForBackend (const Texture &texture) const
 Validates a texture handle for backend-provided auxiliary entry points, running the same null/device-identity/generation checks the template-method public API performs.
Status validateTextureViewHandleForBackend (const TextureView &textureView) const
 Validates a texture view handle for backend-provided auxiliary entry points: the view itself plus a re-resolution of its viewed texture, so a view of a destroyed (or slot-recycled) texture fails closed exactly like it does on the normal Device paths.
Status validateBufferMappingHandleForBackend (const BufferMapping &mapping) const
 Validates a buffer-mapping handle for backend-provided auxiliary entry points, running the same null/device-identity/generation checks the template-method public API performs, so a stale handle cannot read state belonging to the slot's new occupant.
uint64_t lastTextureUseSerial (uint32_t textureSlotIndex) const
 Serial of the last submission that referenced the texture at textureSlotIndex, or 0 when nothing has submitted work naming it.
virtual uint64_t onTextureWriteByteCount (std::span< const uint8_t > data) const
 Backend hook: the bytes the write onWriteTexture just accepted handed the backend's queue, which DeviceObserver::onTextureWritten reports.
void notifyObserverOfBackendSubmission () const
 Reports a queue submission the backend made on its own, outside submit, to the installed observer as a submission of no command buffers and no draws.

Detailed Description

Metal backend of the Donner GPU runtime.

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: host-visible buffers and textures, MSL shader modules, render pipelines with up to kMaxVertexBuffers vertex buffer layouts stepped per vertex or per instance, render passes with color attachments, scissors and viewports, non-indexed and indexed (16- and 32-bit) draws with instancing and base vertex, compute pipelines and passes over sampled and storage textures, texture-to-buffer and texture-to-texture copies, queue writes, host buffer mapping, and surface presentation. Resources bind through bind group 0 only; a submission that sets any other group is refused. Bindings follow the deterministic argument-table mapping in donner/gpu/shader/MslBindingMap.h: buffer binding b maps to Metal buffer index 1 + b, and texture and sampler bindings map directly. Vertex buffer layouts take the highest free vertex-stage argument indices at or below 30, in slot order, skipping the length table and every vertex-visible resource buffer; a pipeline whose vertex buffers do not fit is refused at creation.

Generated runtime-array reads use the exact declared binding sizes in a fixed length table. Metal buffer index 0 is reserved for that table, so raw MSL this backend accepts must leave index 0 free. Each immutable bind group caches the table; when the bound group changes it is uploaded to every stage the active encoder has, deliberately without consulting the layout, because the generated code's need for the table follows from the shader IR rather than from a layout's binding types or visibility. Repeated draws and dispatches reuse that binding, and each new pass binds it again. MSL modules must supply buffer interface metadata before native compilation, including an explicitly empty list when no entry point uses buffers. Pipeline creation checks the supplied facts against the layout's binding types and stage visibility.

Presentation goes through a Core Animation Metal layer the embedder supplies and continues to own: configuring sets the layer's pixel format, drawable extent, pacing and alpha compositing, and each acquired frame is one of that layer's drawables, handed out only while it matches the configured extent. Presenting waits for the frame's own submission to complete and then hands the drawable over, because a drawable presented from a command buffer is shown when that buffer is scheduled rather than when it completes, which would show a frame the GPU is still drawing. A frame whose work cannot finish because the root is lost is abandoned, and the present reports SurfaceStatus::DeviceLost; so does an acquire on a lost root, which hands out no frame. The layer hands out a small fixed number of drawables, so a frame that is neither presented nor abandoned stalls the next acquisition until the layer gives up waiting.

Queue writes update idle resources directly. Writes to resources an earlier submission still uses are copied into bounded host storage and uploaded at the beginning of the next ordinary submission. Repeated writes of the same resource range are coalesced. A batch adds one staging allocation and no queue submission; Metal retains the staging buffer and destinations until completion. Queued and in-flight uploads share a configurable byte budget, defaulting to kMaxBufferByteSize; at most 16,384 writes may await submission. Excess writes return LimitExceeded without changing the batch. The budget counts logical upload bytes, excluding row and alignment padding. Combined queued and in-flight packed staging also stays within the larger of this budget and kMaxBufferByteSize. Packing temporarily retains both the host payload and native staging buffer. Managed resources may have separate host and device backing, so physical RAM/VRAM usage also includes those copies and driver overhead. Destroyed destinations drop unsubmitted writes; completion returns the in-flight byte reservation.

macOS buffer blits require four-byte-aligned offsets and sizes. An unaligned update instead waits for that buffer's last use for as long as the work ahead of it keeps making progress. It returns an error if this device has failed work, its root is lost, or that work makes no progress for the unalignedWriteTimeout given to Create (five seconds by default); it never waits for unrelated later submissions.

Memory model: unified-memory resources use MTLStorageModeShared; other devices use MTLStorageModeManaged. Managed CPU writes publish their ranges, and every submission synchronizes its GPU-written buffers before reporting completion to host readers. Textures reach the CPU through readback buffers, so unrelated buffers and textures need no scan.

Threading: single-threaded use, matching donner::gpu::Device's thread affinity. The thread needs no autorelease pool of its own: every call drains the Objective-C objects it autoreleased before it returns, so a plain worker thread keeps no frame's resources resident after the call that used them. The one exception to single-threaded use is command-buffer completion handlers, which Metal invokes on an internal queue; they touch only atomics, mutex-protected completion state (the error string and the ordered completion watermark), and the root's shared loss condition, observable through completedSerial, Device::waitForSerial, Device::isLost, and lastErrorForTest. A handler that saw work fail also writes one diagnostic line to stderr, after it has published everything a waiter reads.

Every command buffer of a submission reports its outcome, and the submission completes once all of them have. When any of them failed on the GPU, the submission failed: the root is declared lost, with no wait site because the backend reported it, before the submission's serial is reported complete. The completed serial advances only in serial order, so a serial seen complete carries the outcome of every submission through it, whatever order their handlers ran in. Mappings answer loss before readiness and serial waits give up at once, whichever device over the root declared the loss, so teardown after a hang does not wait it out.

Work in flight is bounded in command buffers: a submission that would leave more than kMaxCommandBuffersInFlight committed and uncompleted waits for room before it acquires any native buffer, so acquisition never blocks inside Metal. The wait is bounded. It gives up when no progress has been seen for five seconds, measured from the last progress rather than from the start of the wait; progress is a command buffer of this device completing, or a completion on another device while an uncompleted submission of this one still waits for that device's work. Once that work completes, the other device's later completions no longer count. The wait also gives up after sixty seconds in all. Either way the root is declared lost, attributed to the queue wait, and the submission is refused without consuming a serial. Ordinary frames stay far below the backstop and never wait. Another device's progress is sampled one hop deep: when that device's own work in turn waits on a third device, the third device's completions do not count, so a chain that progresses only at its far end for longer than the stall bound declares the loss.

Every other wait that exists to detect a hung GPU judges a stall on that same progress clock rather than giving the whole backlog a fixed budget: Device::waitForSerialUnlessStalled, the drain at teardown, a present's wait for its frame's work and an unaligned write's wait for its busy buffer. A slow device that keeps completing work is never cut off, however long its backlog, and a device that stops completing it is caught within the bound.

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::SystemCapabilities

struct donner::gpu::metal::MetalDevice::SystemCapabilities

What the system default Metal device supports, which every device Create opens shares.

Class Members
uint32_t maxTextureDimension2D = 0 Largest width or height of a 2D texture the device allocates, from its GPU family and capped at kMaxTextureDimension, the largest extent the runtime accepts.

◆ donner::gpu::metal::MetalDevice::GpuFamilies

struct donner::gpu::metal::MetalDevice::GpuFamilies

The GPU families a Metal device belongs to, as far as its 2D texture limit depends on them.

Class Members
bool apple3OrLater = false Apple family 3 or later.
bool mac = false Any Mac family. Every Metal device on macOS is in one, Apple silicon included.

◆ donner::gpu::metal::MetalDevice::WriteStats

struct donner::gpu::metal::MetalDevice::WriteStats

Snapshot of upload bookkeeping for tests and performance measurements.

Class Members
uint64_t inFlightStagingBytes = 0 Packed staging bytes retained until GPU completion.
uint64_t pendingStagingBytes = 0 Packed staging bytes reserved for those writes.
size_t pendingWrites = 0 Coalesced writes awaiting a normal submission.
uint64_t stagingAllocations = 0 Native upload staging allocations attempted.
uint64_t submittedUploadBatches = 0 Ordinary submissions containing queued writes.
uint64_t unalignedWriteWaits = 0 Resource waits needed by unaligned buffer writes.

◆ donner::gpu::metal::MetalDevice::NativeTextureUsage

struct donner::gpu::metal::MetalDevice::NativeTextureUsage

Native texture access reported by Metal, exposed for allocation-contract tests.

Class Members
bool renderTarget = false Native render-target usage.
bool shaderRead = false Native shader-read usage.
bool shaderWrite = false Native shader-write usage.

Member Enumeration Documentation

◆ MemoryModel

enum class donner::gpu::metal::MetalDevice::MemoryModel : uint8_t
strong

Which memory model the backend builds its resources for.

Enumerator
Detected 

Take the model the Metal device reports. Production always uses this.

ForceNonUnified 

Build for a device without unified memory whatever it reports, so the host-coherency steps that model needs are exercised on hardware that would otherwise never take them.

Member Function Documentation

◆ backendDeviceIdentity()

BackendDeviceIdentity donner::gpu::metal::MetalDevice::backendDeviceIdentity ( ) const
overrideprotectedvirtual

Identifies the MTLDevice this device records against, so a sibling device over the same MTLDevice can register its textures.

Reimplemented from donner::gpu::Device.

◆ 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 ( MemoryModel memoryModel = MemoryModel::Detected,
uint64_t uploadStagingByteBudget = kMaxBufferByteSize,
std::chrono::milliseconds unalignedWriteTimeout = std::chrono::seconds(5),
std::shared_ptr< DeviceLostState > lostState = nullptr )
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).

Parameters
memoryModelWhich memory model to build resources for; production leaves this detected, and a test forces the non-unified path to cover it on unified hardware.
uploadStagingByteBudgetMaximum combined queued and in-flight logical payload bytes. Zero is invalid and returns nullptr. Each individual batch also fits kMaxBufferByteSize.
unalignedWriteTimeoutLongest an unaligned write to a busy buffer waits while the work ahead of it makes no progress. Must be between zero and five seconds; invalid bounds return nullptr.
lostStateLoss condition to share with every other device selected over the same backend, or null for a private one only this device can set. The device reports it through Device::isLost; the loss is declared by whoever observes it, such as a failed command buffer of this device or a context's bounded wait.

◆ failNextSubmissionForTest()

void donner::gpu::metal::MetalDevice::failNextSubmissionForTest ( std::optional< size_t > commandBufferIndex = std::nullopt)

Makes one command buffer of the next submission report an execution error when it completes, as a command buffer the GPU faulted on does, through the same completion path.

A deterministic test seam: a real fault cannot be produced on demand without hanging or corrupting the GPU.

Parameters
commandBufferIndexIndex of the failing buffer within the submission; its last buffer when absent or past the end.

◆ hostWritePublishCountForTest()

uint64_t donner::gpu::metal::MetalDevice::hostWritePublishCountForTest ( ) const
nodiscard

How many buffer writes have published their range to the device copy. Test accessor.

Counts CPU-written buffer ranges, including packed staging for buffer or texture uploads. Direct texture writes publish through replaceRegion and need no buffer-range publication.

On unified memory nothing is published and this stays zero. The count exists because hardware that addresses one copy produces correct results whether or not the publication happened, so the results cannot show whether it did.

◆ MaxTextureDimension2DFor()

uint32_t donner::gpu::metal::MetalDevice::MaxTextureDimension2DFor ( GpuFamilies families)
static

Largest width or height of a 2D texture a device of families allocates, from Metal's feature set tables: 16,384 for every Mac family and for Apple family 3 onward, and 8,192 for the earlier Apple families.

Capped at kMaxTextureDimension.

Parameters
familiesFamilies the device belongs to.

◆ onAbandonCurrentTexture()

void donner::gpu::metal::MetalDevice::onAbandonCurrentTexture ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: drop the acquired texture without presenting.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onAcquireCurrentTexture()

Result< SurfaceStatus > donner::gpu::metal::MetalDevice::onAcquireCurrentTexture ( uint32_t slotIndex,
uint32_t textureSlotIndex )
overrideprotectedvirtual

Backend hook: acquire the next frame's texture and report the surface's state.

Parameters
slotIndexSlot of the surface.
textureSlotIndexSlot the runtime allocated for the acquired texture.

Reimplemented from donner::gpu::Device.

◆ onConfigureSurface()

Status donner::gpu::metal::MetalDevice::onConfigureSurface ( uint32_t slotIndex,
const SurfaceConfiguration & configuration )
overrideprotectedvirtual

Backend hook: apply a configuration.

Parameters
slotIndexSlot of the surface.
configurationConfiguration to apply.

Reimplemented from donner::gpu::Device.

◆ 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.

◆ onCreateComputePipeline()

Status donner::gpu::metal::MetalDevice::onCreateComputePipeline ( uint32_t slotIndex,
const ComputePipelineDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a compute pipeline 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.

◆ onCreateSurface()

Status donner::gpu::metal::MetalDevice::onCreateSurface ( uint32_t slotIndex,
const SurfaceDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: create a surface for a platform object.

Defaults to reporting presentation as unsupported, so a backend that cannot present needs no implementation.

Parameters
slotIndexSlot the surface occupies.
descriptorLabel and platform object.

Reimplemented from 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 retired resource is no longer used by submitted work and can be released.

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

Implements donner::gpu::Device.

◆ onDestroySurface()

void donner::gpu::metal::MetalDevice::onDestroySurface ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: release the platform state of a surface that is going away.

Runs once per surface, when it is destroyed or when its last handle is dropped, after any frame it still held has been handed back through onAbandonCurrentTexture. The slot is reused by the next surface, so a backend that keeps per-surface state clears it here rather than leaving the next surface to find its predecessor's.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onExportTexture()

Result< BackendTextureExport > donner::gpu::metal::MetalDevice::onExportTexture ( uint32_t slotIndex)
overrideprotectedvirtual

Exports the texture in slotIndex.

Every device over the system device submits to its own command queue, so registrations are ordered by waiting for this device's work to complete; the export carries the completion counter and error flag the command-buffer handlers set.

Parameters
slotIndexValidated live texture slot.

Reimplemented from donner::gpu::Device.

◆ onLastProgress()

std::optional< std::chrono::steady_clock::time_point > donner::gpu::metal::MetalDevice::onLastProgress ( )
overrideprotectedvirtual

The latest progress of this device and of the producers its uncompleted submissions wait on, as the backstop on work in flight measures it.

Reimplemented from donner::gpu::Device.

◆ onMapBufferAsync()

Status donner::gpu::metal::MetalDevice::onMapBufferAsync ( uint32_t mappingSlotIndex,
uint32_t bufferSlotIndex,
MapMode mode,
uint64_t offsetBytes,
uint64_t byteCount )
overrideprotectedvirtual

Backend hook: begin mapping a buffer range.

Defaults to reporting the capability as unsupported, so a backend without host mapping needs no implementation and callers get a clean unsupported result rather than a missing symbol.

Parameters
mappingSlotIndexSlot the mapping occupies.
bufferSlotIndexSlot of the buffer being mapped.
modeHow the host will access the range.
offsetBytesByte offset of the mapped range.
byteCountLength of the mapped range.

Reimplemented from donner::gpu::Device.

◆ onMappedBytes()

Result< std::span< const uint8_t > > donner::gpu::metal::MetalDevice::onMappedBytes ( uint32_t mappingSlotIndex) const
overrideprotectedvirtual

Backend hook: bytes of a completed mapping.

Parameters
mappingSlotIndexSlot of the mapping.

Reimplemented from donner::gpu::Device.

◆ onPresentSurface()

Result< SurfaceStatus > donner::gpu::metal::MetalDevice::onPresentSurface ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: present the acquired texture.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onRegisterTexture()

Status donner::gpu::metal::MetalDevice::onRegisterTexture ( uint32_t slotIndex,
const ExportedTextureBacking & backing )
overrideprotectedvirtual

Names another device's exported texture in slotIndex, refusing one created by a different MTLDevice object, which Metal would not accept in this device's command buffers.

Parameters
slotIndexSlot the registration occupies.
backingThe producer's export.

Reimplemented from donner::gpu::Device.

◆ onRetireBuffer()

void donner::gpu::metal::MetalDevice::onRetireBuffer ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: a buffer handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.

Parameters
slotIndexRetired buffer slot.

Reimplemented from donner::gpu::Device.

◆ onRetireTexture()

void donner::gpu::metal::MetalDevice::onRetireTexture ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: a texture handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.

Parameters
slotIndexRetired texture slot.

Reimplemented from donner::gpu::Device.

◆ onSubmit()

Status donner::gpu::metal::MetalDevice::onSubmit ( uint64_t submissionSerial,
std::span< const SubmittedCommandBuffer > commandBuffers )
overrideprotectedvirtual

Backend hook: validated command buffers were submitted as one submission.

The span holds at least one buffer and they execute in the order given. The backend owes the caller one completion for the whole span: whatever native objects it splits the work across, completedSerial reaches submissionSerial only once all of them have finished, and a backend that reports the submission accepted has accepted all of it.

Parameters
submissionSerialSerial assigned to this submission.
commandBuffersCommand buffers of this submission, in execution order.

Implements donner::gpu::Device.

◆ onSubmitAfterSources()

Status donner::gpu::metal::MetalDevice::onSubmitAfterSources ( uint64_t submissionSerial,
std::span< const SubmittedCommandBuffer > commandBuffers,
std::span< const SourceWait > waits )
overrideprotectedvirtual

Places a GPU wait on each producer's completion event at the start of the submission's first command buffer, one per producer at the latest serial it needs, then submits.

Reimplemented from donner::gpu::Device.

◆ onSurfaceCapabilities()

Result< SurfaceCapabilities > donner::gpu::metal::MetalDevice::onSurfaceCapabilities ( uint32_t slotIndex) const
overrideprotectedvirtual

Backend hook: what a surface supports.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onTextureWritePending()

bool donner::gpu::metal::MetalDevice::onTextureWritePending ( uint32_t slotIndex) const
overrideprotectedvirtual

Whether the write just accepted for slotIndex was queued for the next submission because earlier work still used the texture.

Parameters
slotIndexValidated live texture slot.

Reimplemented from donner::gpu::Device.

◆ onUnmapBuffer()

void donner::gpu::metal::MetalDevice::onUnmapBuffer ( uint32_t mappingSlotIndex)
overrideprotectedvirtual

Backend hook: release a mapping.

Parameters
mappingSlotIndexSlot of the mapping.

Reimplemented from donner::gpu::Device.

◆ onWaitForSerial()

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

Sleeps until the completion counter reaches serial, the budget runs out, a completed command buffer reports an execution error (see lastErrorForTest), or the root is declared lost.

Completion handlers run on a Metal-internal thread and wake the wait each time a command buffer completes or a serial is published, so it returns as soon as the work does.

Parameters
serialSubmission serial to wait for.
timeoutSecondsLongest to wait, in seconds.

Reimplemented from donner::gpu::Device.

◆ onWaitForSerialUnlessStalled()

SerialWaitResult donner::gpu::metal::MetalDevice::onWaitForSerialUnlessStalled ( uint64_t serial,
std::chrono::milliseconds stallBound )
overrideprotectedvirtual

Waits for serial on the progress clock the backstop on work in flight uses: the wait gives up once neither this device nor a producer its uncompleted work waits on has made progress for stallBound, measured from that progress.

Woken by every command buffer that completes, every serial published and a declared loss.

Parameters
serialSubmission serial to wait for.
stallBoundLongest the work may go without progress.

Reimplemented from donner::gpu::Device.

◆ onWaitMappingSlice()

MapSliceReport donner::gpu::metal::MetalDevice::onWaitMappingSlice ( uint32_t mappingSlotIndex,
double sliceSeconds )
overrideprotectedvirtual

Backend hook: wait up to sliceSeconds for a pending mapping, and report what it found and how it spent the slice.

The runtime owns the deadline and the caller's cancellation; this reports only the mapping.

Parameters
mappingSlotIndexSlot of the pending mapping.
sliceSecondsLongest this call may block.

Reimplemented from 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,
const Origin2d & destinationOrigin )
overrideprotectedvirtual

Backend hook: a validated texture write. The written rectangle is writeSize texels wide and tall with its top-left texel at destinationOrigin; texels outside it keep their contents.

Parameters
slotIndexDestination texture slot.
dataPayload bytes.
dataLayoutRow layout of data.
writeSizeExtent written in texels.
destinationOriginTop-left texel of the written rectangle.

Implements donner::gpu::Device.

◆ QuerySystemCapabilities()

std::optional< SystemCapabilities > donner::gpu::metal::MetalDevice::QuerySystemCapabilities ( )
static

Asks the system default Metal device, the one Create opens, what it supports without opening a runtime device over it.

A backend root is selected before any device over it exists, and its limits have to be the device's own rather than a portable fallback.

Returns
The capabilities, or empty when no Metal device is available.

◆ 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.

Synchronous test and diagnostic readback, outside the asynchronous mapping API (donner::gpu::Device::mapBufferAsync): it validates device identity, slot liveness, and the handle generation, then reads the shared-storage Metal buffer contents directly. Callers must ensure relevant GPU work has completed first (see Device::waitForSerial). Queued writes become visible after a subsequent ordinary submission completes; this accessor does not submit them.

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

◆ releasePausedCommandBuffersForTest()

void donner::gpu::metal::MetalDevice::releasePausedCommandBuffersForTest ( uint64_t count)

Lets the first count command buffers encoded since pauseSubmissionsForTest run and keeps the rest paused. It only signals a shared event, so another thread may call it while the device's own thread waits, provided that thread does not pause or resume meanwhile. Does nothing when no pause is active.

Parameters
countCommand buffers to release, counted from the first one encoded while paused.

◆ setPresentCompletionTimeoutForTest()

void donner::gpu::metal::MetalDevice::setPresentCompletionTimeoutForTest ( std::chrono::milliseconds timeout)

Bounds how long a present's wait for its frame's work may go without progress, in place of the five seconds it otherwise allows, so a case reaches the bound without spending it, and before the system's own timeout ends a command buffer that makes no progress.

Parameters
timeoutLongest the wait sees no progress; zero or less restores the default.

◆ setSubmissionStallTimeoutForTest()

void donner::gpu::metal::MetalDevice::setSubmissionStallTimeoutForTest ( std::chrono::milliseconds timeout)

Bounds how long a submission waits for room among the command buffers in flight while neither this device nor a device its waiting work depends on completes any, in place of the five seconds it otherwise allows.

Parameters
timeoutLongest a wait sees no progress; zero or less restores the default.

◆ setSubmissionWaitCapForTest()

void donner::gpu::metal::MetalDevice::setSubmissionWaitCapForTest ( std::chrono::milliseconds timeout)

Bounds how long one submission waits for room in all, in place of the sixty seconds it otherwise allows, however much progress it sees meanwhile.

Parameters
timeoutLongest a wait lasts; zero or less restores the default.

◆ shaderSourceKind()

ShaderSourceKind donner::gpu::metal::MetalDevice::shaderSourceKind ( ) const
inlineoverridevirtual

Native shader representation accepted by this device.

Reimplemented from donner::gpu::Device.

◆ textureUsageForTest()

Result< NativeTextureUsage > donner::gpu::metal::MetalDevice::textureUsageForTest ( const Texture & texture) const

Reads native usage after validating the texture's device, liveness, and generation.

Parameters
textureA live texture owned by this device.

◆ waitForCompletionHandlersForTest()

bool donner::gpu::metal::MetalDevice::waitForCompletionHandlersForTest ( uint64_t count,
double timeoutSeconds ) const
nodiscard

Waits until count submissions have had all their completion handlers run on this device, parked ones included. Test seam for ordering completions deterministically.

Parameters
countSubmissions to wait for.
timeoutSecondsLongest to wait.
Returns
True once that many have.

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