SkSL Binary Format

Background

The SkSL binary format was originally created for internal use, to store our built-in include files in a format which required less processing time than the original text versions.

This improved compiler startup time and memory footprint, but as the format was purpose-built for encoding our include files, it could not encode a normal SkSL program. It only supported the subset of SkSL required by the include files, had no means of referring to external symbols, and had not been tested outside of being used to encode our small handful of include files.

To both improve testability and to support the needs of clients requiring a binary SkSL format, this feature has been extended to support arbitrary SkSL files. Full test coverage is achieved by encoding our entire corpus of SkSL tests to binary, decoding them, and ensuring that the decoded output program matches the unmodified original program.

Design

Overview

A binary SkSL file has the following header:

TypeField Name
uint16version
uint16stringLength
char[stringLength]stringData

The version number is incremented whenever the file format changes. This document describes version 11.

stringLength is the total length of all of the string data in the file, including the length bytes of the strings, but not counting the stringLength field itself. Each string consists of a uint8 length followed by the string’s characters, which are not null terminated.

The header is immediately followed by a sequence of one or more commands encoding the contents. A typical SkSL binary will contain exactly one kProgram_Command.

Types

The following types may appear as data members of commands. All numbers are stored in little endian byte ordering.

NameDescription
int8a signed 8 bit integer
int16a signed 16 bit integer
int32a signed 32 bit integer
uint8an unsigned 8 bit integer
uint16an unsigned 16 bit integer
uint32an unsigned 32 bit integer
floata 32 bit IEEE floating point number
boola single byte with the value either 0 (false) or 1 (true)
Stringa uint8 length, followed by a uint16 offset [^1]
ProgramKinda uint8 mapping to a value in the SkSL::ProgramKind enum
SkSLVersiona uint8 mapping to a value in the SkSL::Version enum
VariableStoragea uint8 mapping to a value in the SkSL::VariableStorage enum
Operatora uint8 mapping to a value in the SkSL::Operator::Kind enum
FieldAccessOwnerKinda uint8 mapping to a value in the SkSL::FieldAccessOwnerKind enum
VariableRefKinda uint8 mapping to a value in the SkSL::VariableRefKind enum
SwizzleComponenta uint8 mapping to a value in the SkSL::SwizzleComponent::Type enum
Symbolan instance of any command in the Symbol category
SymbolIda uint16 ID specified by a Symbol category command [^2]
Expressionan instance of any command in the Expressions category
ProgramElementan instance of any command in the ProgramElements category
Statementan instance of any command in the Statements category
Typean instance of one of the “Type” Symbol commands [^3]
Layoutan instance of the one of the Layout commands [^4]
Modifiersan instance of one of the Modifiers commands [^5]
k*_Commandan instance of the specified command

[^1]: The offset of a String is relative to the beginning of the stringData field of the header.

[^2]: There is one exception to SymbolIds referring to Symbol commands: if a SymbolId is kBuiltin_Symbol, the SymbolId is followed by a String representing the name of the symbol.

[^3]: The Type symbol commands are kArrayType_Command, kStructType_Command, or a kSymbolRef_Command referring to an existing type.

[^4]: The “Layout” commands are kBuiltinLayout_Command, kDefaultLayout_Command, and kLayout_Command.

[^5]: The “Modifiers” commands are kDefaultModifiers_Command, kModifiers8Bit_Command, and kModifiers_Command).

Commands

Each command consists of a single uint8 identifying the command, followed by its data.

General Commands

kBuiltinLayout_Command

TypeField Name
int16builtin

An SkSL::Layout with the specified builtin value, but all other fields left with their default values.


kDefaultLayout_Command

An SkSL::Layout with every field set to its default value.


kDefaultModifiers_Command

An SkSL::Modifiers with every field set to its default value.


kElements_Command

TypeField Name
ProgramElement[]elements
kElementsComplete_Command

The end of the elements array is indicated by the presence of kElementsComplete_Command.


kElementsComplete_Command

Signifies the end of a list of elements.


kLayout_Command

TypeField Name
int32flags
int8location
int16offset
int16binding
int8index
int8set
int16builtin
int8inputAttachmentIndex

Represents an SkSL::Layout with all fields specified.


kModifiers8Bit_Command

TypeField Name
Layoutlayout
uint8flags

A shortened version of Modifiers which only represents the least significant 8 bits of flags, leaving the other bits as zero.


kModifiers_Command

TypeField Name
Layoutlayout
uint32flags

kProgram_Command

TypeField Name
ProgramKindprogramKind
SkSLVersionrequiredVersion
kSymbolTable_CommandsymbolTable
kElements_Commandelements
booluseFlipRTUniform

useFlipRTUniform refers to a field in Program::Inputs.


kSymbolTable_Command

TypeField Name
uint16ownedSymbolCount
Symbol[ownedSymbolCount]ownedSymbols
uint16symbolCount
SymbolID[symbolCount]symbols

The IDs in the symbols array do not relate to indices in ownedSymbols, and instead refer to the IDs specified at the beginning of commands in the Symbol category.


ProgramElement Commands

kFunctionDefinition_Command

TypeField Name
SymbolIddeclaration
Statementbody

Provides the body corresponding to a FunctionDeclaration.


kFunctionPrototype_Command

TypeField Name
uint16declaration

Represents a function declaration appearing in the program as a function prototype.


kInterfaceBlock_Command

TypeField Name
SymbolIdvar
StringtypeName
StringinstanceName
uint8arraySize

An interface block. instanceName may be zero-length to indicate the lack of an instance name. arraySize will be zero if the instance name was not present or was not followed by an array size.


kStructDefinition_Command

TypeField Name
TypestructType

Represents a struct definition appearing at top-level scope.


kSharedFunction_Command

TypeField Name
uint8parameterCount
Variable[parameterCount]parameters
FunctionDeclarationdecl
FunctionDefinitiondefn

Represents a function from Program.fSharedElements.


kGlobalVar_Command

TypeField Name
kVarDeclaration_Commanddecl

A VarDeclaration appearing in global scope.


Symbol Commands

kArrayType_Command

TypeField Name
uint16id
TypecomponentType
uint8count

kField_Command

TypeField Name
SymbolIdownerId
uint8index

Symbol referring to a particular field of a StructType. Unlike other symbols, Field does not have its own ID; references to a Field are compiled in terms of the owner’s ID.


kFunctionDeclaration_Command

TypeField Name
uint16id
Modifiersmodifiers
Stringname
uint8parameterCount
Symbol[parameterCount]parameters
TypereturnType

If a function is overloaded, the overloads will by dehydrated in the same order that they appear in the code. SkSL will prefer the first overload when a function call is ambiguous, so maintaining the overload order is important.


kStructType_Command

TypeField Name
uint16id
Stringname
uint8fieldCount
Field[fieldCount]fields

The Field type referenced in this command is:

struct Field {
    Modifiers modifiers;
    String name;
    Type type;
};

kSymbolRef_Command

TypeField Name
SymbolIdid

Refers to a Symbol which has already been written by another command.


kVariable_Command

TypeField Name
uint16id
Modifiersmodifiers
Stringname
Typetype
VariableStoragestorage

Expression Commands

kBinary_Command

TypeField Name
Expressionleft
Operatorop
Expressionright
Typetype

Represents a binary operator applied to two expressions.


kBoolLiteral_Command

TypeField Name
boolvalue

Represents a literal true or false value.


kConstructorArray_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorArray.


kConstructorArrayCast_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorArrayCast.


kConstructorCompound_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorCompound.


kConstructorCompoundCast_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorCompoundCast.


kConstructorDiagonalMatrix_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorDiagonalMatrix.


kConstructorMatrixResize_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorMatrixResize.


kConstructorScalarCast_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorScalarCast.


kConstructorSplat_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorSplat.


kConstructorStruct_Command

TypeField Name
Typetype
uint8argCount
Expression[argCount]arguments

Represents an instance of SkSL::ConstructorStruct.


kFieldAccess_Command

TypeField Name
Expressionbase
uint8index
FieldAccessOwnerKindownerKind

A reference to the index’th field of the base struct.


kFloatLiteral_Command

TypeField Name
floatvalue

Represents a floating point literal.


kFunctionCall_Command

TypeField Name
Typetype
SymbolIdfunction
uint8argCount
Expression[argCount]arguments

Represents a call to function(arguments...).


kIndex_Command

TypeField Name
Expressionbase
Expressionindex

Represents the expression base[index].


kIntLiteral_Command

TypeField Name
int32value

Represents an integer literal.


kPostfix_Command

TypeField Name
Operatorop
Expressionoperand

Represents applying the postfix operator op to operand.


kPrefix_Command

TypeField Name
Operatorop
Expressionoperand

Represents applying the prefix operator op to operand.


kSetting_Command

TypeField Name
Stringname

Represents a field of sk_Caps, such as “integerSupport”.


kSwizzle_Command

TypeField Name
Expressionbase
uint8componentCount
SwizzleComponent[componentCount]components

Represents the swizzle base.components.


kTernary_Command

TypeField Name
Expressiontest
ExpressionifTrue
ExpressionifFalse

Represents the ternary expression test ? ifTrue : ifFalse.


kVariableReference_Command

TypeField Name
SymbolIDvar
VariableRefKindrefKind

Represents a reference to the variable var.


Statement Commands

kBlock_Command

TypeField Name
kSymbolTable_CommandsymbolTable
uint8statementCount
Statement[statementCount]statements
uint8blockKind

A block of statements.


kBreak_Command

A break statement.


kContinue_Command

A continue statement.


kDiscard_Command

A discard statement.


kDo_Command

TypeField Name
Statementstmt
Expressiontest

Represents do stmt; while(test);.


kExpressionStatement_Command

TypeField Name
Expressionexpression

Represents the statement expression;.


kFor_Command

TypeField Name
Statementinitializer
Expressiontest
Expressionnext
Statementbody
SymbolTablesymbols

Represents for (initializer; test; next) body;. test, next, and body may all be kVoid_Command to represent their absence.


kIf_Command

TypeField Name
boolisStatic
Expressiontest
StatementifTrue
StatementifFalse

Represents if (test) ifTrue; else ifFalse; (or @if, if isStatic is true). ifFalse may be kVoid_Command to represent the absence of an else statement.


kNop_Command

Represents an empty statement (a bare semicolon).


kReturn_Command

TypeField Name
Expressionvalue

Represents the statement return value;. value may be kVoid_Command to represent the absence of a return value.


kSwitch_Command

TypeField Name
boolisStatic
kSymbolTable_Commandsymbols
Expressionvalue
uint8caseCount
Case[caseCount]cases

The Case type referenced in this command is:

struct Case {
    bool isDefault;
    (when !isDefault) Expression value;
    uint8 statementCount;
    Statement statements[statementCount];
};

Represents a switch or @switch statement on value. Each case begins with a bool identifying whether or not it is the default case; the default case does not contain the value field.


kVarDeclaration_Command

TypeField Name
SymbolIdvar
TypebaseType
uint8arraySize
Expressionvalue

Represents the variable declaration statement baseType var[arraySize] = value;. An arraySize of zero omits the array declaration. A value of kVoid_Command omits the initializer.


kVoid_Command

A marker indicating that a node is not present.