Source code

Revision control

Copy as Markdown

Other Tools

framework = "Metal"
crate = "objc2-metal"
required-crates = ["objc2", "objc2-foundation"]
custom-lib-rs = true
macos = "10.11"
maccatalyst = "13.0"
ios = "8.0"
tvos = "9.0"
visionos = "1.0"
# Duplicated property
class.MTLRasterizationRateLayerDescriptor.methods.sampleCount.skipped = true
# Gets emitted as an out pointer, but the pointer is actually an array.
# Swift also skips this.
class.MTLRasterizationRateMapDescriptor.methods."rasterizationRateMapDescriptorWithScreenSize:layerCount:layers:".skipped = true
# Needs mach / kernel types
protocol.MTLResource.methods."setOwnerWithIdentity:".skipped = true
# Has a union field, but we'd rather have it as just a struct
struct._MTLPackedFloat3.skipped = true
typedef.MTLPackedFloat3.skipped = true
fn.MTLPackedFloat3Make.skipped = true
# Manually defined to allow it to work on older OSes.
fn.MTLCopyAllDevices.skipped = true
# isize referencing usize.
enum.MTLTensorDataType.use-value = true
###
### Safety
###
# SAFETY: Metal is has a _lot_ of low-level functionality since it basically
# has to model the entire GPU, and since it has very tight performance
# constraints, which we must manually mark a lot of things as unsafe.
unsafe-default-safety.documentation-is-reviewed = true
# TODO: Can we rely on Metal being bounds-checked?
# Maybe the various array types are bounds-checked on the CPU side?
# There are also a lot of false positives from this check.
unsafe-default-safety.bounds-checked-internally = false
# TODO(breaking): Figure out whether these are bounds-checked or not?
class.MTLAccelerationStructureGeometryDescriptor.methods."setIntersectionFunctionTableOffset:".unsafe = false
protocol.MTLAccelerationStructureCommandEncoder.methods."buildAccelerationStructure:descriptor:scratchBuffer:scratchBufferOffset:".unsafe = false
protocol.MTLAccelerationStructureCommandEncoder.methods."writeCompactedAccelerationStructureSize:toBuffer:offset:".unsafe = false
protocol.MTLBuffer.methods."didModifyRange:".unsafe = false
protocol.MTLBuffer.methods."newTextureWithDescriptor:offset:bytesPerRow:".unsafe = false
protocol.MTLBuffer.methods."addDebugMarker:range:".unsafe = false
class.MTLAttributeDescriptor.methods."setOffset:".unsafe = false
protocol.MTLRenderCommandEncoder.methods."setVisibilityResultMode:offset:".unsafe = false
protocol.MTLBlitCommandEncoder.methods."fillBuffer:range:value:".unsafe = false
class.MTLArgumentDescriptor.methods."setIndex:".unsafe = false
protocol.MTLIntersectionFunctionTable.methods."setFunction:atIndex:".unsafe = false
protocol.MTLDevice.methods."supportsVertexAmplificationCount:".unsafe = false
class.MTLAccelerationStructureTriangleGeometryDescriptor.methods."setIndexBuffer:".unsafe = false
class.MTLAccelerationStructureTriangleGeometryDescriptor.methods."setTriangleCount:".unsafe = false
class.MTLAccelerationStructureBoundingBoxGeometryDescriptor.methods."setBoundingBoxCount:".unsafe = false
class.MTLInstanceAccelerationStructureDescriptor.methods."setInstanceCount:".unsafe = false
class.MTLIntersectionFunctionTableDescriptor.methods."setFunctionCount:".unsafe = false
protocol.MTLDevice.methods."newCommandQueueWithMaxCommandBufferCount:".unsafe = false
protocol.MTLDevice.methods."supportsTextureSampleCount:".unsafe = false
protocol.MTLDevice.methods.maxArgumentBufferSamplerCount.unsafe = false
class.MTLIndirectCommandBufferDescriptor.methods."setMaxVertexBufferBindCount:".unsafe = false
class.MTLIndirectCommandBufferDescriptor.methods."setMaxFragmentBufferBindCount:".unsafe = false
class.MTLIndirectCommandBufferDescriptor.methods."setMaxKernelBufferBindCount:".unsafe = false
class.MTLRenderPassDescriptor.methods."setDefaultRasterSampleCount:".unsafe = false
class.MTLRenderPipelineDescriptor.methods."setSampleCount:".unsafe = false
class.MTLRenderPipelineDescriptor.methods."setRasterSampleCount:".unsafe = false
class.MTLBufferLayoutDescriptor.methods."setStride:".unsafe = false
class.MTLAccelerationStructureGeometryDescriptor.methods."setPrimitiveDataStride:".unsafe = false
class.MTLAccelerationStructureTriangleGeometryDescriptor.methods."setVertexStride:".unsafe = false
class.MTLHeapDescriptor.methods."setSize:".unsafe = false
class.MTLAccelerationStructureGeometryDescriptor.methods."setPrimitiveDataElementSize:".unsafe = false
protocol.MTLDevice.methods."heapBufferSizeAndAlignWithLength:options:".unsafe = false
protocol.MTLDevice.methods."newAccelerationStructureWithSize:".unsafe = false
protocol.MTLHeap.methods."maxAvailableSizeWithAlignment:".unsafe = false
# SAFETY: The values are checked later:
# > -[MTLDebugDevice newArgumentTableWithDescriptor:error:]:4160: failed assertion `Argument Table Descriptor Validation
# > max texture bind count must not be more than 128.
class.MTL4ArgumentTableDescriptor.methods."setMaxBufferBindCount:".unsafe = false
class.MTL4ArgumentTableDescriptor.methods."setMaxTextureBindCount:".unsafe = false
class.MTL4ArgumentTableDescriptor.methods."setMaxSamplerStateBindCount:".unsafe = false
# TODO(breaking): Mark these as unsafe (they take unsafe functions).
protocol.MTLDevice.methods."newComputePipelineStateWithFunction:error:".unsafe = false
protocol.MTLComputePipelineState.methods."functionHandleWithFunction:".unsafe = false
protocol.MTLComputePipelineState.methods."newComputePipelineStateWithAdditionalBinaryFunctions:error:".unsafe = false
class.MTLComputePipelineDescriptor.methods."setComputeFunction:".unsafe = false
class.MTLRenderPipelineDescriptor.methods."setVertexFunction:".unsafe = false
class.MTLRenderPipelineDescriptor.methods."setFragmentFunction:".unsafe = false
# SAFETY: These do not call the given `MTLFunction`s.
class.MTLLinkedFunctions.methods."setFunctions:".unsafe = false
class.MTLLinkedFunctions.methods."setBinaryFunctions:".unsafe = false
class.MTLLinkedFunctions.methods."setGroups:".unsafe = false
class.MTLLinkedFunctions.methods."setPrivateFunctions:".unsafe = false
# SAFETY: `-ffast-math` is generally frowned upon because it enables
# optimizations that could theoretically optimize math operations away to
# nothing. Metal enables this by default, so we must assume that their
# configuration of it is sound (?), and that we don't need to mark compilation
# as unsafe.
#
# class.MTLCompileOptions.methods."setMathMode:".unsafe = false
# class.MTLCompileOptions.methods."setFastMathEnabled:".unsafe = false
# SAFETY: Mark any accesses to the contents of `MTLResource`s as unsafe.
#
# Reading or writing to resources is unsynchronized and effectively equivalent
# to (non-atomically?) sharing these between threads. The user needs to
# explicitly synchronize accesses to these. (Explicit synchronization could
# maybe in some cases be avoided with `MTLStorageModeShared` and
# `MTLHazardTrackingModeTracked`, but that's dangerous to solely rely on).
#
# In `header-translator`, subprotocols of `MTLResource` is marked as unsafe in
# argument position to ensure that any accesses to these on the GPU side are
# properly synchronized.
#
# Here, we mark all inherent methods that read/write on these as `unsafe` to
# also make things unsafe on the CPU side.
protocol.MTLBuffer.methods.contents.unsafe = false # Raw pointer, unsafe in itself.
protocol.MTLTensor.methods."getBytes:strides:fromSliceOrigin:sliceDimensions:".unsafe = true
protocol.MTLTensor.methods."replaceSliceOrigin:sliceDimensions:withBytes:strides:".unsafe = true
protocol.MTLTexture.methods."getBytes:bytesPerRow:bytesPerImage:fromRegion:mipmapLevel:slice:".unsafe = true
protocol.MTLTexture.methods."getBytes:bytesPerRow:fromRegion:mipmapLevel:".unsafe = true
protocol.MTLTexture.methods."replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:".unsafe = true
protocol.MTLTexture.methods."replaceRegion:mipmapLevel:withBytes:bytesPerRow:".unsafe = true
protocol.MTLAccelerationStructure.unsafe = true
protocol.MTLAccelerationStructure.methods.gpuResourceID.unsafe = false
protocol.MTLAccelerationStructure.methods.size.unsafe = false
protocol.MTLIndirectCommandBuffer.unsafe = true
protocol.MTLIndirectCommandBuffer.methods.gpuResourceID.unsafe = false
protocol.MTLIndirectCommandBuffer.methods.size.unsafe = false
protocol.MTLIntersectionFunctionTable.unsafe = true
protocol.MTLIntersectionFunctionTable.methods.gpuResourceID.unsafe = false
protocol.MTLVisibleFunctionTable.unsafe = true
protocol.MTLVisibleFunctionTable.methods.gpuResourceID.unsafe = false
# TODO(breaking): Mark these as unsafe, they probably require synchronization.
class.MTLRenderPassAttachmentDescriptor.methods."setTexture:".unsafe = false
class.MTLRenderPassAttachmentDescriptor.methods."setResolveTexture:".unsafe = false
class.MTLAccelerationStructureBoundingBoxGeometryDescriptor.methods."setBoundingBoxBuffer:".unsafe = false
class.MTLRenderPassDescriptor.methods."setVisibilityResultBuffer:".unsafe = false
class.MTLInstanceAccelerationStructureDescriptor.methods."setInstanceDescriptorBuffer:".unsafe = false
class.MTLInstanceAccelerationStructureDescriptor.methods."setInstancedAccelerationStructures:".unsafe = false
class.MTLAccelerationStructureGeometryDescriptor.methods."setPrimitiveDataBuffer:".unsafe = false
class.MTLAccelerationStructureTriangleGeometryDescriptor.methods."setVertexBuffer:".unsafe = false
protocol.MTLBlitCommandEncoder.methods."generateMipmapsForTexture:".unsafe = false
protocol.MTLBlitCommandEncoder.methods."optimizeContentsForGPUAccess:".unsafe = false
protocol.MTLAccelerationStructureCommandEncoder.methods."copyAndCompactAccelerationStructure:toAccelerationStructure:".unsafe = false
# SAFETY: Synchronizing a resource is safe, as it:
# - Doesn't need to the resource to be bound.
# - Doesn't access the contents of the resource.
# - Doesn't need the resource to be retained by the user, since it already is
# guaranteed to be since they've used the resource elsewhere.
# TODO(breaking): Is that claim true?
protocol.MTLBlitCommandEncoder.methods."synchronizeResource:".unsafe = false
# SAFETY: We consider resource's bound-ness as safe, the safety is moved to
# command encoding methods such as `setTexture:atIndex:` instead.
#
# Calling this with a resource is safe, since it:
# - Doesn't access the contents of the resource.
# - Doesn't need the resource to be retained by the user, since it already is
# guaranteed to be since they've used the resource elsewhere.
#
# TODO(breaking): Are those claims true?
protocol.MTLAccelerationStructureCommandEncoder.methods."useResource:usage:".unsafe = false
protocol.MTLComputeCommandEncoder.methods."useResource:usage:".unsafe = false
protocol.MTLRenderCommandEncoder.methods."useResource:usage:".unsafe = false
protocol.MTLRenderCommandEncoder.methods."useResource:usage:stages:".unsafe = false
# SAFETY: Resource options are safe to specify:
# - Hazard tracking and storage modes change the required synchronization, but
# we handle that above. Also, we wouldn't really be able to prevent
# untracked resources, these are the only option in Metal 4.
# - The CPU cache mode is safe, it should only affect performance, not
# correctness.
#
# class.*.methods."setResourceOptions:".unsafe = false
# TODO(breaking): Mark these as unsafe, setting `MTLPurgeableState::Volatile)`
# is probably not safe, as you have to lock resources to prevent them from
# being purged while in use.
# TODO: How would you do such locking?
protocol.MTLResource.methods."setPurgeableState:".unsafe = false
protocol.MTLHeap.methods."setPurgeableState:".unsafe = false
# Using the resource's contents in a memory-safe manner is very difficult
# after this is called.
protocol.MTLResource.methods.makeAliasable.unsafe = true
# Modifying residency has similar safety as modifying a resource's bound-ness,
# it does mostly the same thing.
# protocol.MTLResidencySet.methods."addAllocation:".unsafe = false
# Taking a residency set in or out of residency is only a performance knob,
# it's similar to controlling what's in the L1/L2/L3 cache on the CPU.
# protocol.MTLResidencySet.methods.requestResidency.unsafe = false
# protocol.MTLResidencySet.methods.endResidency.unsafe = false
# TODO(breaking): Mark this as unsafe?
class.MTLHeapDescriptor.methods."setType:".unsafe = false
# SAFETY: We could consider marking these as unsafe, since they affect
# lifetime safety, and can cause use-after-free if used incorrectly.
#
# Unretained references are the only option for `MTL4CommandBuffer`s though,
# and we already mark `MTLResource`s as unsafe, so we choose to move the
# unsafety of this to the resources instead.
# class.MTLCommandBufferDescriptor.methods."setRetainedReferences:".unsafe = true
# protocol.MTLCommandQueue.methods.commandBufferWithUnretainedReferences.unsafe = true
# protocol.MTLIOCommandQueue.methods.commandBufferWithUnretainedReferences.unsafe = true
# Must be a multiple of 4.
class.MTLVertexBufferLayoutDescriptor.methods."setStride:".unsafe = true
class.MTLVertexAttributeDescriptor.methods."setOffset:".unsafe = true
# These must be done in lockstep.
class.MTLVertexBufferLayoutDescriptor.methods."setFunction:".unsafe = true
class.MTLVertexBufferLayoutDescriptor.methods."setStepRate:".unsafe = true
# MTLCaptureManager is not documented thread-safe, so +sharedCaptureManager
# is not safe either, since we do interior mutation in it.
class.MTLCaptureManager.methods.sharedCaptureManager.unsafe = true
# TODO: Sizes must be >= 1, unsure if checked?
class.MTLTextureDescriptor.methods."texture2DDescriptorWithPixelFormat:width:height:mipmapped:".unsafe = true
class.MTLTextureDescriptor.methods."textureCubeDescriptorWithPixelFormat:size:mipmapped:".unsafe = true
class.MTLTextureDescriptor.methods."textureBufferDescriptorWithPixelFormat:width:resourceOptions:usage:".unsafe = true
# Call supportsVertexAmplificationCount: on device first.
# TODO: Is this a safety requirement?
class.MTLRenderPipelineDescriptor.methods."setMaxVertexAmplificationCount:".unsafe = true
# Must be specified when layered rendering is enabled.
# TODO: Is this a safety requirement?
class.MTLRenderPipelineDescriptor.methods."setInputPrimitiveTopology:".unsafe = true
# Must be between 16 and 64 and depends on tessellationPartitionMode
class.MTLRenderPipelineDescriptor.methods."setMaxTessellationFactor:".unsafe = true
# Affects maxTessellationFactor above.
class.MTLRenderPipelineDescriptor.methods."setTessellationPartitionMode:".unsafe = true
# Requires specific values when using indexed control points.
class.MTLRenderPipelineDescriptor.methods."setTessellationControlPointIndexType:".unsafe = true
# Takes a MTLGPUAddress
protocol.MTL4ComputeCommandEncoder.methods."dispatchThreadgroupsWithIndirectBuffer:threadsPerThreadgroup:".unsafe = true
# Takes a MTL4BufferRange
class.MTL4InstanceAccelerationStructureDescriptor.methods."setInstanceDescriptorBuffer:".unsafe = true
class.MTL4IndirectInstanceAccelerationStructureDescriptor.methods."setInstanceDescriptorBuffer:".unsafe = true
class.MTL4AccelerationStructureGeometryDescriptor.methods."setPrimitiveDataBuffer:".unsafe = true
class.MTL4AccelerationStructureTriangleGeometryDescriptor.methods."setVertexBuffer:".unsafe = true
# Takes a MTLResourceID, unsure if this allows doing bad things.
protocol.MTL4ArgumentTable.methods."setResource:atBufferIndex:".unsafe = true
protocol.MTL4ArgumentTable.methods."setTexture:atIndex:".unsafe = true
protocol.MTL4ArgumentTable.methods."setSamplerState:atIndex:".unsafe = true
# TODO: Unclear whether changing MTLDataType is safe?
class.MTLArgumentDescriptor.methods."setDataType:".unsafe = false # TODO(breaking)
class.MTLFunctionConstantValues.methods."setConstantValue:type:atIndex:".unsafe = true
class.MTLFunctionConstantValues.methods."setConstantValues:type:withRange:".unsafe = true
class.MTLFunctionConstantValues.methods."setConstantValue:type:withName:".unsafe = true
protocol.MTLAccelerationStructureCommandEncoder.methods."writeCompactedAccelerationStructureSize:toBuffer:offset:sizeDataType:".unsafe = true
# TODO: Triage these.
protocol.MTLBlitCommandEncoder.methods."optimizeContentsForGPUAccess:slice:level:".unsafe = true
class.MTLTextureDescriptor.methods."setWidth:".unsafe = true
class.MTLTextureDescriptor.methods."setHeight:".unsafe = true
class.MTLTextureDescriptor.methods."setDepth:".unsafe = true
class.MTLTextureDescriptor.methods."setMipmapLevelCount:".unsafe = true
class.MTLTextureDescriptor.methods."setSampleCount:".unsafe = true
class.MTLTextureDescriptor.methods."setArrayLength:".unsafe = true
class.MTLComputePipelineDescriptor.methods."setThreadGroupSizeIsMultipleOfThreadExecutionWidth:".unsafe = true
protocol.MTLComputePipelineState.methods."imageblockMemoryLengthForDimensions:".unsafe = true