SGX Runtime Compiler

The SGX Runtime Compiler is a command line tool that compiles source SGX files into data files that can be consumed by the SGX Runtime API. Since SGX Runtime is built on the established FaceFX Runtime technology, the SGX Runtime Compiler is also capable of compiling source FaceFX files. This article is focused on the SGX-specific details of the SGX Runtime Compiler. Comprehensive documentation for the Runtime Compiler can be found in the manual, located at facefx/doc/pdf/manual.pdf. No matter the source file origin, the Runtime API is the same.

The compiler is an executable file named ffxc.exe and it can be found in the facefx/tools/compiler/bin directory, inside a subdirectory dictated by the OS and build environment. Currently, the SGX Runtime compiler only runs on Windows 64-bit x86_64.

Running the Compiler

To run the compiler, simply run the ffxc executable from the command prompt. When ffxc is not given any arguments, an error is printed along with usage information and a brief description of the valid options. The compiler command line syntax is:

ffxc [ option…] filename…

where option… is a list of command line options and filename… is a list of input files.

In order to compile SGX Character Control Files (.k), a special license file is required. You will have received a license file from Speech Graphics for this purpose, and the compiler will attempt to locate it when requested to compile SGX source files. The compiler will first look for a system environment variable named SGX_RUNTIME_LICENSE which contains a path to the license file. If the system environment variable does not exist, the compiler will attempt to find the license file in the current directory. If no valid license can be found, the compile operation will fail with a licensing error.

Options

The compiler accepts two types of command line options: flags and values. Both types of command line options may have long and short variants, though some options only have a long version. A given command line option may only be specified once on the command line. Specifying the same option more than once on the command line will results in an error. Here we will discuss the command line options relevant to SGX. A complete list can be found in the manual.

Flags

Flags do not accept an accompanying argument. To use a flag, simply add either its long or short form to the command line. For example, suppose there is a flag with long form --flag and short form -f. Usage of this flag would then look like:

ffxc --flag or ffxc -f

Since flags do not accept an accompanying argument, the short form allows multiple flags to be specified simultaneously. To do this, simply specify multiple short form flags after the initial -. For example, suppose there are multiple flags with short forms -1, -2, -3, and -4. Usage of all of these flags could be shortened from:

ffxc -1 -2 -3 -4

to

ffxc -1234

--help, -h

Displays the compiler help screen and exits.

--version

Displays the compiler version information and exits.

Suppresses the compiler’s printed banner during compilation.

--quiet, -q

Suppresses all compiler output. Only errors are printed when this flag is specified.

--nowarnings, -w

Suppresses all warnings.

-Wname

This is a special flag that allows specific warnings to be enabled. To use it, replace name with the name of the warning to be enabled. For example, the following will enable the negative time warning:

ffxc -Wnegative-time

Each warning defines a unique enable flag, so multiple enable warning flags may be specified on the same command line. However, the duplicate option error still applies – attempting to enable the same warning multiple times will result in an error.

For a detailed list of warnings and their meanings, please see the manual.

-Wno-name

This is a special flag that allows specific warnings to be disabled. To use it, replace name with the name of the warning to be disabled. For example, the following will disable the invalid characters detected warning:

ffxc -Wno-invalid-chars

Each warning defines a unique disable flag, so multiple disable warning flags may be specified on the same command line. However, the duplicate option error still applies – attempting to disable the same warning multiple times will result in an error.

--rebuild, -r

Forces a full rebuild of the source content, rather than a minimal build.

--jobs, -j

Tells the compiler how many threads to use during compilation. Note that this is a special flag type as it is the only one that can accept a value in its short form. This is to match other well-known command line tools.

When unspecified, the default value of 0 is used which means use all available hardware threads. This value is clamped to the following range:

[0, num_hardware_threads]

Examples:

ffxc --jobs=16

or

ffxc -j32

When compiling SGX source files, not all available hardware threads are used by default. If a specific number of threads is requested via --jobs, that number will always be used. If no value is specified, the compiler uses half of the available hardware threads to improve overall throughput.

--nothreads

Disables all multithreading in the compiler, and forces compilation on a single thread.

It is an error to specify --nothreads and --jobs simultaneously.

--recurse

Recurses into the specified SGX events directory. May only be used in conjunction with --events-dir, -d. Only valid when compiling SGX source files.

--no-preroll-shift

Do not shift animation key times earlier by the source pre-roll duration. Normally, the compiler shifts keys so that source pre-roll appears at negative time and Runtime audio begins at time 0. Use this option when the input audio already contains leading padding equal to the source pre-roll duration. Only valid when compiling SGX source files.

--stage-import

Emit an import staging area for each processed input, containing only files that require import during this run. The import staging area is used by the Unreal Engine 5 plugin and is a useful construct for any custom engine plugins you may develop yourself. The import staging area will be located parallel to the input file being compiled and is a directory with the name <actor_name>.ffxc.

The import staging area contains only assets that require import during the current run. It is regenerated each run and can be safely deleted after import. The Unreal Engine 5 plugin deletes files from the staging area upon successful import, for example.

When --stage-import is specified, --idmap and --guid are implicitly enabled. More detail on that can be found in the manual.

When compiling SGX source files, --amap=”.” is also implicitly specified and a .facefx file will be created parallel to the <actor_name>.ffxc directory, if one doesn’t already exist. This .facefx file is needed to import the staging area into the Unreal Engine 5 plugin.

More detail on the --amap value can be found in the manual, however, the only valid value when compiling SGX source files is ”.”. With that value specified, the compiler will look for audio files parallel to .event files in the directory specified by --events-dir.

Values

Values do accept an accompanying argument. To use a value, simply specify either its long or short form, followed by =, and then the argument (without any spaces between the components). For example, suppose there is a value option with long form --value and short form -v. Usage of this value would then look like:

ffxc --value=hellowworld

or, for the short form:

ffxc -v=helloworld

If the argument contains spaces, be sure to surround the argument with double quotes ():

ffxc --value=”hello world”

Unless otherwise noted, values accept only one argument.

--logfile, -l

Directs all output to the specified log file. For illustration purposes, this:

ffxc --logfile=./log.txt

produces the same result as this:

ffxc > ./log.txt

--outdir, -o

Changes the output directory to the specified directory. By default, the compiler will use the current directory as its output directory unless directed to do otherwise via the --outdir option. For example,

C:\Game>ffxc

will use the C:\Game directory for output. However,

C:\Game>ffxc --outdir=”C:\My Output Dir”

will use the C:\My Output Dir directory for output.

If the path contains spaces, enclose it in double quotes. Note that on Windows if you use the backslash character (\) you need to escape it by using two backslashes if it is the last character of the path:

C:\Game>ffxc --outdir=”C:\My Output Dir\\”

The best solution is to just not include the trailing backslash character, or even better use the forward slash for all separators:

C:\Game>ffxc --outdir=”C:/My Output Dir/”

--events-dir, -d

Specifies the directory containing SGX Event Files that belong to the SGX Character Control File being compiled. Only valid when compiling SGX source files.

Input

The list of input files can consist of either multiple .facefx or .k files or a single .ffxcproj file. That is, any number of .facefx and .k files can be compiled with a single command, but only a single .ffxcproj file can be compiled with a single command. It is not permitted to mix compilation of .facefx or .k files and .ffxcproj files. Any invalid combination of files will result in an error.

FaceFX Files (.facefx)

.facefx files are created with FaceFX Studio. More details can be found in the manual.

SGX Character Control Files (.k)

.k files are created with SGX Studio. This file contains all the that determines how Speech Graphics animation systems work with the character rig. For more information on .k files, please see the Speech Graphics Knowledge Base.

SGX Event Files (.event)

.event files are created with SGX Production Tools. These files contain SGX animation data targeted to an SGX Character Control File. For more information on .event files, please see the Speech Graphics Knowledge Base.

Project Files (.ffxcproj)

It is possible to define a project file to contain all of the files needed by your game and simply compile that project, rather than compiling a group of source files directly.

It is recommended to use project files when you have a large number of source files in your game or when your game contains a mixture of .facefx and .k files. The project file format is well suited for being automatically generated from your game’s editor or tools. The compiler only accepts one project file at a time for compilation. While you can compile multiple source files simultaneously, e.g.

ffxc Hero1.k Hero2.k

when using a .ffxcproj file you can only list one file on the command line, e.g.

ffxc mygame.ffxcproj

.ffxcproj File Format

Project files are simply YAML files that define what files are included in the project. Project files have the extension .ffxcproj, and they can be created and edited with any text editor. Note, however, that as these files are YAML files, the indentation is very important.

The format is very simple:

YAML
version: <runtime_version>           # integer FX_VERSION from facefx.h, e.g. 40000
items:
    - facefx_file: <facefx_path>     # path to a .facefx file
      mount_files:                   # list of .animset files to mount, or [] if none
        - <animset_path_1>
        - <animset_path_2>
        # ...

    - k_file: <k_file_path>          # path to an SGX Character Control File (.k)
      events_directory: <events_dir> # directory containing SGX Event Files (.event)
      recurse: <true|false>          # whether to recurse into subdirectories
      no_preroll_shift: <true|false> # whether to shift animation keys by pre-roll duration

where <runtime_version> is the Runtime version at the time the project file was created (the value of FX_VERSION from facefx.h, for example 40000 for Runtime version 4.0.0); <facefx_path> is the path to a .facefx file; <animset_path_n> is the path to a .animset file (if there are no .animset files, use [] to signify that fact); <k_file_path> is the path to a .k file; <events_dir> is the path to a directory containing .event files (there can only be one of these directories per .k file); recurse indicates whether the compiler should recurse into subdirectories when searching for .event files; and no_preroll_shfit tells the compiler to not shift animation keys by the source event pre-roll duration. recurse and no_preroll_shift are optional.

You can list multiple source files in items. For example, you could create one by hand for your entire game (e.g. mygame.ffxcproj) and simply list every source file for the whole game; or you could create a tool that will automatically generate the project file prior to compilation.

Here’s an example:

YAML
version: 40000
items:
    - k_file: Hero1.k
     events_directory: C:\Game\Hero1\SGX_Events
     recurse: true

	- k_file: Hero2.k
	  events_directory: C:\Game\Hero2\SGX_Events
	  recurse: true

Output

The compiler outputs several file types upon successful compilation. The files that are required in order for the Runtime API to function are actor files (.ffxactor), bone set files (.ffxbones), and animation files (.ffxanim). Id to string mapping files (.ffxids) and GUID files (.ffxguid) can optionally be output, but are for debugging purposes and are not required by the Runtime API.

Each file that the compiler outputs will contain an embedded GUID (Globally Unique Identifier) code that identifies the source file the produced it. In order for the Runtime API to use a set of files together their embedded GUID codes must match. The Runtime API will enforce this and refuse to allow files with mismatched GUID codes to be used together.

.ffxactor Files

.ffxactor files contain actor data, which in the Runtime consists of data that describes the animation tracks available for use at runtime. It is important to note that the full face graph is not present in the Runtime.

.ffxbones Files

.ffxbones files contain bone set data, which consists of the rest pose and all bone poses defined for the actor. If you are not using bones the compiler will not output a .ffxbones file.

.ffxanim Files

.ffxanim files contain animation data, which consists of animation keys that drive the tracks defined in the .ffxactor file.

.ffxids Files

.ffxids files are optionally output for debugging purposes. They contain a Runtime id-to-string mapping. For more information on .ffxids files, please see the manual.

.ffxatimes Files

.ffxatimes files are optionally output for convenience purposes. They contain a list of all Runtime animations with their corresponding start and end times. For more information on ffxatimes files, please see the manual.

.ffxamap Files

.ffxamap files are optionally output for convenience purposes. They contain a Runtime animation file to audio file mapping. For more information on ffxamap files, please see the manual.

.ffxguid Files

.ffxguid files are optionally output for debugging purposes. They contain the GUID, in text form, that is embedded into all compiler output files for the current source file. For more information on .ffxguid files, please see the manual.

Organization

The compiler will create an output directory structure on a per-source file basis during compilation. The compiler will manage the contents of this directory during subsequent compilations and ensure that it contains a complete representation of the input actor and all its animations. It will re-create any files that have been deleted or moved from its output directory, and it will add and remove files from that directory such that after successful compilation the only files in the directory structure will be files that the compiler has written there. The default output location for the compiler is the current directory, but this can be changed via the --outdir command line option.

For each source file being compiled, the compiler will create a directory with the same file name (without the extension) as the source file. For example, if you are compiling Hero1.k, the compiler will create a directory named Hero1 in the output directory. We will call this the actor directory for the remainder of this discussion.

Inside the actor directory you will find the compiler’s output files. The compiler outputs the .ffxactor and .ffxbones files (as well as the optional .ffxids and .ffxguid files) into this directory. The compiler will also create a directory for each group of .event files based on the source events directory structure and will output a .ffxanim file for each .event file that was compiled.

Warnings

When the compiler encounters a non-critical problem with the source data that can be corrected manually by the user (i.e. a problem that does not prevent further compilation), it will issue a warning in its output. Since warnings are non-critical and compilation continues, multiple warnings can be issued during a single compilation.

An exhaustive list of the possible warnings is available in the manual. Warnings relevant to SGX compilation are listed here:

invalid-chars

This warning indicates that invalid characters have been detected in a string that is used in the OS file system. Invalid characters are any characters that cannot be used when naming files or directories in the POSIX standard. The compiler adheres to the POSIX standard for maximum portability between systems. This means that the only valid characters in paths and filenames are 0-9, a-z, A-Z, ., _, -, and <space>; any other characters are replaced by their decimal ASCII code (e.g. : is replaced by _ASCII58_). In addition, fi the path starts or ends with . or there are any instances of .., those instances of . are replaced by _ASCII46_.

Strings used in the OS file system include animation group names (which become directory names) and animation names (which become file names).

To fix this warning, rename problematic names in the source file, or reduce directory nesting.

negative-time

This warning indicates that the animation starts in negative time (has a start time < 0 seconds). Normally, this is completely fine because the character’s mouth needs some small amount of time to move into position before it can emit sound. Because this is normal this warning is disabled by default. There are times, however, where you may wish to enable it explicitly. For example, you may have aggressively cut audio files and your engine expects the sound an animation to start simultaneously. In that case it would be nice to know if there is any negative time in your animation files so that you can cut it out.

To enable this warning pass -Wnegative-time on the compiler command line. To fix this warning simply delete the negative time keys that the compiler indicates as part of this warning message.

zero-bones

  • This warning indicates that there are no bones present. You may see this warning if you do not intend to animate any bones at all (for example, the character only uses blend shapes). If the intent is to not animate bones in the character at all, disable this warning on the command line with the -Wno-zero-bones flag.

unused-bone

This warning indicates that a bone present in the rest pose is never used in any bone pose nodes in the face graph. When the compiler encounters such a bone it is removed from the rest pose for performance reasons.

To fix this warning, make sure that all bones included in the character’s set up are actually used in at least one pose.

zero-bone-poses

This warning indicates that there are bones contained in the character’s rest pose but that there are no bone poses present in the face graph. In this case, it appears that the intention is to animate with bones but no bone animation actually takes place.

There are two possible fixes for this warning:

  • If the intent is to not use bones, remove all bones from the rest pose.

  • If the intent is to use bones, add bone poses to the face graph that animate the rest pose bones (e.g. use bones in at least one pose).

unused-track

This warning indicates that a “target” node in the face graph (e.g. a bone pose node, a morph target node, a material parameter node, or a generic target node) is never animated by any of the animations contains in the actor. In this case, the track is never used in the Runtime and could degrade performance.

To fix this warning, remove the unused node from the face graph.

missing-constraint

This warning indicates that a required constraint is not specified. For example, a morph target does not specify a lower or upper value limit.

invalid-constraint

This warning indicates that a constraint is invalid or inconsistent. For example, a morph target specifies a lower value limit greater than or equal to its upper value limit.

legacy-input-source

This warning indicates that the input file being compiled is in a legacy format. Follow the instructions in the warning message.

Errors

Unlike warnings, the compiler does not emit a stream of errors. Errors during compilation are treated as critical and must be remedied immediately. When the compiler encounters an error, it halts compilation and prints a description of the error it encountered. This does not apply to SGX .event files due to the way they are compiled, however. A stream of errors may be printed before the compilation ends.

When an error occurs, you should not use any data that may have been written to the file system for that particular source file. In that case, it is best to correct the error (adhering to the compiler’s suggestions for correcting the error, if any, then perform a full rebuild for the problematic source file. If you were compiling multiple source files simultaneously, and previous source files were compiled successfully, it is safe to use the data written to the file system for those successfully compiled source files.