Documentation
¶
Overview ¶
Package msl implements Metal Shading Language (MSL) code generation for naga.
MSL is Apple's shader language for the Metal graphics API. It is based on C++14 with extensions for GPU programming, including explicit address spaces, attribute-based parameter binding, and a metal:: namespace for standard library functions.
Usage ¶
To compile a WGSL shader to MSL:
module, err := wgsl.Parse(source)
if err != nil {
return err
}
options := msl.Options{
LangVersion: msl.Version{Major: 2, Minor: 1},
}
mslCode, err := msl.Compile(module, options)
if err != nil {
return err
}
MSL Language Versions ¶
Options.LangVersion is the version the output is written for (zero: 2.1). The backend never raises it: a shader that needs a newer MSL is refused with a *backend.VersionError, as Rust naga refuses it. The versions some features need:
- MSL 1.2: @builtin(instance_index), @blend_src, reverseBits, extractBits, insertBits, writable storage buffers in fragment shaders, writable storage textures in vertex and fragment shaders, read-write storage textures
- MSL 2.0: binding arrays of samplers, textures and read-only or write-only storage textures
- MSL 2.1: @invariant
- MSL 2.2: @builtin(view_index)
- MSL 2.3: @builtin(primitive_index), @builtin(barycentric)
- MSL 2.4: ray queries
- MSL 3.0: binding arrays of read-write storage textures, mesh shaders
- MSL 3.1: 64-bit storage textures (r64uint, r64sint)
- MSL 4.0: @interpolate(per_vertex)
Type Mapping ¶
WGSL types map to MSL as follows:
WGSL MSL ---- --- bool bool i32 int u32 uint f32 float f16 half vec2<T> metal::T2 vec3<T> metal::T3 vec4<T> metal::T4 mat4x4<f32> metal::float4x4 array<T, N> array<T, N> (wrapped in struct) texture_2d metal::texture2d<float> sampler metal::sampler
Address Spaces ¶
WGSL address spaces map to MSL as:
uniform -> constant storage -> device private -> thread workgroup -> threadgroup function -> thread (stack)
Entry Points ¶
Entry points are generated with appropriate stage keywords:
- vertex: Vertex shaders with [[stage_in]], [[vertex_id]], etc.
- fragment: Fragment shaders with [[position]], [[color(N)]], etc.
- kernel: Compute shaders with [[thread_position_in_grid]], etc.
Helper Functions ¶
Some WGSL operations require polyfill functions in MSL:
- naga_div: Safe integer division (typed overloads, handles zero and INT_MIN/-1)
- naga_mod: Safe integer modulo (typed overloads, handles zero and INT_MIN/-1)
- naga_modf: modf with WGSL-compatible result struct
- naga_frexp: frexp with WGSL-compatible result struct
- _mslBufferSizes: Struct for runtime-sized array buffer sizes
Concurrency ¶
Every exported function is safe for concurrent use. Compile never modifies its input module, so one module can be compiled for several targets at once.
Index ¶
- Variables
- type AttributeMapping
- type BindExternalTextureTarget
- type BindSamplerTarget
- type BindTarget
- type EntryPointResources
- type InlineSampler
- type Options
- type SamplerAddress
- type SamplerBorderColor
- type SamplerCompareFunc
- type SamplerCoord
- type SamplerFilter
- type TranslationInfo
- type Version
- type VertexBufferMapping
- type VertexBufferStepMode
- type VertexFormat
- type VertexPullingOptions
Constants ¶
This section is empty.
Variables ¶
var ( Version1_0 = Version{Major: 1, Minor: 0} Version1_2 = Version{Major: 1, Minor: 2} Version2_0 = Version{Major: 2, Minor: 0} Version2_1 = Version{Major: 2, Minor: 1} Version2_3 = Version{Major: 2, Minor: 3} Version2_4 = Version{Major: 2, Minor: 4} Version3_0 = Version{Major: 3, Minor: 0} Version3_1 = Version{Major: 3, Minor: 1} )
Common MSL versions.
Functions ¶
This section is empty.
Types ¶
type AttributeMapping ¶ added in v0.15.0
type AttributeMapping struct {
ShaderLocation uint32
Offset uint32
Format VertexFormat
}
AttributeMapping maps a vertex attribute to a shader location.
type BindExternalTextureTarget ¶ added in v0.15.0
BindExternalTextureTarget specifies the Metal binding slots for an external texture global variable. External textures are lowered to 3 texture planes and a constant buffer of NagaExternalTextureParams.
type BindSamplerTarget ¶ added in v0.15.0
type BindSamplerTarget struct {
// IsInline indicates the sampler is an inline (constexpr) sampler.
IsInline bool
// Slot is the binding slot (for resource samplers) or index into
// Options.InlineSamplers (for inline samplers).
Slot uint8
}
BindSamplerTarget specifies how a sampler is bound.
type BindTarget ¶
type BindTarget struct {
// Buffer is the buffer binding slot. Nil if not bound as buffer.
Buffer *uint8
// Texture is the texture binding slot. Nil if not bound as texture.
Texture *uint8
// Sampler is the sampler binding slot. Nil if not bound as sampler.
Sampler *BindSamplerTarget
// ExternalTexture is the binding for external texture planes + params.
ExternalTexture *BindExternalTextureTarget
// Mutable indicates if this is a read-write resource.
Mutable bool
}
BindTarget specifies the Metal binding slots for a resource.
type EntryPointResources ¶
type EntryPointResources struct {
// Resources maps (group, binding) pairs to Metal bind targets.
Resources map[ir.ResourceBinding]BindTarget
// SizesBuffer is the buffer slot for runtime array sizes.
// Required when using runtime-sized arrays.
SizesBuffer *uint8
// ImmediatesBuffer is the buffer slot for immediate data.
// Nil if immediate data is not used.
ImmediatesBuffer *uint8
}
EntryPointResources maps WGSL resource bindings to Metal binding slots.
type InlineSampler ¶ added in v0.15.0
type InlineSampler struct {
Coord SamplerCoord
Address [3]SamplerAddress
BorderColor SamplerBorderColor
MagFilter SamplerFilter
MinFilter SamplerFilter
MipFilter *SamplerFilter // nil if not set
CompareFunc SamplerCompareFunc
}
InlineSampler defines an inline (constexpr) sampler in Metal.
type Options ¶
type Options struct {
// LangVersion is the MSL version written in the header and the
// highest one the output may use; the zero value is 2.1 (Rust naga's
// default is 1.0). The backend never raises it: a feature of a newer
// MSL is an error, a *backend.VersionError in backend.VersionMSL that
// names the feature and the version it needs, as Rust naga refuses it.
// Pass the device's highest supported version.
LangVersion Version
// PerEntryPointMap maps entry point names to their resource bindings.
// If nil, bindings are auto-generated: the module's resource globals,
// sorted by (group, binding), get consecutive buffer, texture and sampler
// slots. These slots depend on which globals the module has, so
// naga.ProcessOverrides with an EntryPoint, which removes unused globals,
// can move them. Pass a map for stable slots (Rust naga requires one).
// A non-nil map, empty too, must give every resource an entry point uses
// a slot of its kind in that entry point's entry, and the sizes and
// immediates buffers it needs; an entry point without an entry has none.
// Otherwise Compile fails with an error wrapping
// backend.ErrMissingBinding, unless FakeMissingBindings is set.
PerEntryPointMap map[string]EntryPointResources
// InlineSamplers defines constexpr samplers to be inlined into the code.
// Referenced by BindSamplerTarget.Slot when IsInline is true.
InlineSamplers []InlineSampler
// BoundsCheckPolicies selects how out-of-bounds indices and image loads
// are handled. The zero value is backend.BoundsCheckRestrict everywhere,
// which WebGPU requires; Rust naga's default is Unchecked, and wgpu-hal's
// Metal backend passes Restrict for Index, Buffer and ImageLoad (Unchecked
// when its runtime bounds checks are off) and Unchecked for BindingArray.
// Every field honors every policy, as Rust naga's MSL writer does:
// Restrict with metal::min on the index (a runtime-sized array takes its
// length from the sizes buffer) and on image coordinates,
// ReadZeroSkipWrite with a ternary or an if around the access,
// Unchecked with no code.
BoundsCheckPolicies backend.BoundsCheckPolicies
// ZeroInitializeWorkgroupMemory is how compute entry points zero the
// threadgroup variables they use, as WebGPU requires. The zero value,
// backend.ZeroInitWorkgroupPolyfill, stores zero to them from the first
// invocation and adds a threadgroup barrier, as Rust naga's default
// zero_initialize_workgroup_memory: true does. ZeroInitWorkgroupNone
// leaves them as they are; ZeroInitWorkgroupNative is an error, Metal
// has no way to ask for it.
ZeroInitializeWorkgroupMemory backend.ZeroInitializeWorkgroupMemoryMode
// SkipLoopBounding leaves loops as they are. By default every loop gets
// a decrementing 64-bit counter that breaks out of it, so an infinite
// loop, undefined behavior that can hang the device, ends. Rust naga's
// force_loop_bounding defaults to true, and wgpu-hal passes true.
SkipLoopBounding bool
// FakeMissingBindings writes a placeholder attribute, [[user(fake0)]],
// for a resource a non-nil PerEntryPointMap gives no slot, instead of
// failing. Rust naga's fake_missing_bindings defaults to true; wgpu-hal
// passes false, the zero value here.
FakeMissingBindings bool
// EntryPoint selects the one entry point to write, as Rust naga's
// msl::PipelineOptions::entry_point; nil writes every entry point. One
// the module does not have is an error wrapping
// backend.ErrEntryPointNotFound.
EntryPoint *backend.EntryPointSelector
// AllowAndForcePointSize forces point size output for vertex shaders.
AllowAndForcePointSize bool
// VertexPulling, when set, makes vertex entry points read their inputs
// from vertex buffers instead of stage_in (Rust naga's
// vertex_pulling_transform with its vertex_buffer_mappings).
VertexPulling *VertexPullingOptions
// ClampFragDepth, when set, clamps the depth a fragment entry point
// writes to the range in two f32, min then max, at byte offset
// ClampFragDepth.Offset of the entry point's immediates buffer
// (EntryPointResources.ImmediatesBuffer), which it then needs. WebGPU
// clamps frag_depth to the viewport's depth range; the caller puts the
// viewport's minDepth and maxDepth there, where Dawn's ClampFragDepth
// transform reads them on Metal, and as the spirv option of the same
// name reads them from push constants. An entry point with immediate
// data of its own finds the range in the same buffer, so Offset has to
// be past that data. Rust naga has no such option.
ClampFragDepth *backend.ClampFragDepth
// FixedSampleMask, when set, is the render pipeline's sample mask, which
// a fragment entry point applies itself: it ANDs it into the sample_mask
// it returns, or returns it as a [[sample_mask]] output when it returns
// none. Metal has no pipeline sample mask; Dawn folds it into the shader
// the same way. Leave it nil for a mask of all ones. Rust naga has no
// such option.
FixedSampleMask *uint32
}
Options configures MSL code generation.
func DefaultOptions ¶
func DefaultOptions() Options
DefaultOptions returns the zero Options, the safe defaults: MSL 2.1, Restrict bounds checks, bounded loops.
type SamplerAddress ¶ added in v0.15.0
type SamplerAddress int
SamplerAddress specifies the addressing mode for an inline sampler.
const ( SamplerAddressRepeat SamplerAddress = iota SamplerAddressMirroredRepeat SamplerAddressClampToEdge SamplerAddressClampToZero SamplerAddressClampToBorder )
type SamplerBorderColor ¶ added in v0.15.0
type SamplerBorderColor int
SamplerBorderColor specifies the border color for an inline sampler.
const ( SamplerBorderColorTransparentBlack SamplerBorderColor = iota SamplerBorderColorOpaqueBlack SamplerBorderColorOpaqueWhite )
type SamplerCompareFunc ¶ added in v0.15.0
type SamplerCompareFunc int
SamplerCompareFunc specifies the comparison function for an inline sampler.
const ( SamplerCompareFuncNever SamplerCompareFunc = iota SamplerCompareFuncLess SamplerCompareFuncLessEqual SamplerCompareFuncGreater SamplerCompareFuncGreaterEqual SamplerCompareFuncEqual SamplerCompareFuncNotEqual SamplerCompareFuncAlways )
type SamplerCoord ¶ added in v0.15.0
type SamplerCoord int
SamplerCoord specifies the coordinate system for an inline sampler.
const ( SamplerCoordNormalized SamplerCoord = iota SamplerCoordPixel )
type SamplerFilter ¶ added in v0.15.0
type SamplerFilter int
SamplerFilter specifies the filtering mode for an inline sampler.
const ( SamplerFilterNearest SamplerFilter = iota SamplerFilterLinear )
type TranslationInfo ¶
type TranslationInfo struct {
// EntryPointNames maps original entry point names to generated MSL names.
EntryPointNames map[string]string
// RequiresSizesBuffer indicates if a sizes buffer is needed for
// runtime-sized arrays.
RequiresSizesBuffer bool
}
TranslationInfo contains information about the compiled MSL output.
type Version ¶
Version represents an MSL language version.
type VertexBufferMapping ¶ added in v0.15.0
type VertexBufferMapping struct {
ID uint32
Stride uint32
StepMode VertexBufferStepMode
Attributes []AttributeMapping
}
VertexBufferMapping describes a vertex buffer and its attributes.
type VertexBufferStepMode ¶ added in v0.15.0
type VertexBufferStepMode int
VertexBufferStepMode defines how to advance the data in vertex buffers.
const ( VertexStepModeConstant VertexBufferStepMode = 0 VertexStepModeByVertex VertexBufferStepMode = 1 VertexStepModeByInstance VertexBufferStepMode = 2 )
type VertexFormat ¶ added in v0.15.0
type VertexFormat int
VertexFormat describes the format of a vertex attribute.
const ( VertexFormatUint8 VertexFormat = 0 VertexFormatUint8x2 VertexFormat = 1 VertexFormatUint8x4 VertexFormat = 2 VertexFormatSint8 VertexFormat = 3 VertexFormatSint8x2 VertexFormat = 4 VertexFormatSint8x4 VertexFormat = 5 VertexFormatUnorm8 VertexFormat = 6 VertexFormatUnorm8x2 VertexFormat = 7 VertexFormatUnorm8x4 VertexFormat = 8 VertexFormatSnorm8 VertexFormat = 9 VertexFormatSnorm8x2 VertexFormat = 10 VertexFormatSnorm8x4 VertexFormat = 11 VertexFormatUint16 VertexFormat = 12 VertexFormatUint16x2 VertexFormat = 13 VertexFormatUint16x4 VertexFormat = 14 VertexFormatSint16 VertexFormat = 15 VertexFormatSint16x2 VertexFormat = 16 VertexFormatSint16x4 VertexFormat = 17 VertexFormatUnorm16 VertexFormat = 18 VertexFormatUnorm16x2 VertexFormat = 19 VertexFormatUnorm16x4 VertexFormat = 20 VertexFormatSnorm16 VertexFormat = 21 VertexFormatSnorm16x2 VertexFormat = 22 VertexFormatSnorm16x4 VertexFormat = 23 VertexFormatFloat16 VertexFormat = 24 VertexFormatFloat16x2 VertexFormat = 25 VertexFormatFloat16x4 VertexFormat = 26 VertexFormatFloat32 VertexFormat = 27 VertexFormatFloat32x2 VertexFormat = 28 VertexFormatFloat32x3 VertexFormat = 29 VertexFormatFloat32x4 VertexFormat = 30 VertexFormatUint32 VertexFormat = 31 VertexFormatUint32x2 VertexFormat = 32 VertexFormatUint32x3 VertexFormat = 33 VertexFormatUint32x4 VertexFormat = 34 VertexFormatSint32 VertexFormat = 35 VertexFormatSint32x2 VertexFormat = 36 VertexFormatSint32x3 VertexFormat = 37 VertexFormatSint32x4 VertexFormat = 38 VertexFormatUnorm10_10_10_2 VertexFormat = 43 VertexFormatUnorm8x4Bgra VertexFormat = 44 VertexFormatSnorm10_10_10_2 VertexFormat = 45 )
type VertexPullingOptions ¶ added in v0.21.0
type VertexPullingOptions struct {
// VertexBuffers describes the vertex buffers and their attributes.
VertexBuffers []VertexBufferMapping
}
VertexPullingOptions configures vertex pulling: the vertex buffers vertex entry points read their inputs from.