Skip to content

Metallib file format

Teodor Tanasoaia edited this page Jun 21, 2023 · 15 revisions

Compiling Shader Code into a Library with Metal’s Command-Line Tools

Generating and Loading a Metal Library Symbol File (metallibsym)

Metallibs are very simple files, however there is no documentation on them and it's unlikely there ever will be. Hopefully, Naga will be able to produce these files directly without having to pass through a text representation and then be compiled for a second time. These files do have some optimizations applied to them (there is at least some inlining), however it is currently unknown exactly what is done.

In some bastardised rust notation this is the file format (all numbers little endian):

struct Value {
   /// Length of the following data
   length: u16,
   data: [u8],
}

struct Metallib {
    magic_number = b"MTLB",
    /// Seen [0x01, 0x80, 0x02, 0x00], [0x01, 0x00, 0x02, 0x00]
    unknown: [u8; 4],
    /// File format version, 3 is documented here.
    /// WARNING version 2 exists in the wild.
    format_version: u64,

    /// Total length including what has come before
    file_size: u64,

    /// Address of num_entries
    headers_start: u64,
    headers_len: u64,

    types_start: u64,
    types_length: u64,

    empties_start: u64,
    empties_length: u64,

    bitcode_start: u64,
    total_bitcode_length: u64,

    num_entries: u32,
    headers: [Header; num_entries],
    endt_tag = b"ENDT", // Exists in version 3 but not version 2??

    // These are related and possibly to do with the input and output
    // types of the entry points.
    types: [Empty | Type; num_entries],
    empties: [Empty; num_entries],

    /// Code!
    bitcode: [LLVMBitcode; num_entries],
}

struct Header {
    /// Total length of this header, including this field
    length: u32,

    name_tag = b"NAME",
    /// Name of the entry point, null terminated
    name: Value,

    type_tag = b"TYPE",
    /// 0 for vertex shaders, 1 for fragment shaders, seems to always be 1 byte
    type: Value,

    hash_tag = b"HASH",
    /// The SHA256 hash of this entrypoint's bitcode
    hash: Value,

    mdsz_tag = b"MDSZ",
    /// Size of this entry point's LLVM bitcode, seems to always be 8 bytes long
    mdsz: Value,

    offt_tag = b"OFFT",
    /// No idea, seems to be [u64; 3], seen [0,0,0],[0x24,0x8,0xA60],[0x2C,0x10,0x1490]
    offt: Value, 

    vers_ tag = b"VERS",
    /// No idea, seems to be [2,2,2,2]: [u16; 4]
    vers: Value, 

    endt_ tag = b"ENDT",
}

struct Type {
    // Length of this type, NOT including this field
    length: u32,
    vatt_tag = b"VATT",
    /// No idea, seen [0x0001, b"position\0", 0x8000]
    vatt: Value,
    vaty_tag = b"VATY",
    /// No clue, seen [0x01, 0x00, 0x06]
    vaty: Value,
    endt_tag = b"ENDT",
}

/// Related to Type with some fields missing
struct Empty {
    /// Always 4 for obvious reasons
    length: u32 = 4,
    endt_tag = b"ENDT",
}
Clone this wiki locally