Magnum::ShaderTools::SpirvToolsConverter class new in Git master

SPIRV-Tools shader converter plugin.

Uses SPIRV-Tools for SPIR-V validation, optimization and converting between SPIR-V binary and assembly text (Format::Spirv, Format::SpirvAssembly).

This plugin provides the SpirvShaderConverter, SpirvAssemblyShaderConverter, SpirvToSpirvAssemblyShaderConverter and SpirvAssemblyToSpirvShaderConverter plugins.

Usage

This plugin depends on the ShaderTools and SPIRV-Tools libraries and is built if WITH_SPIRVTOOLSSHADERCONVERTER is enabled when building Magnum Plugins. To use as a dynamic plugin, load "SpirvToolsShaderConverter" via Corrade::PluginManager::Manager.

Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins, SPIRV-Headers and SPIRV-Tools repositories and do the following. If you want to use system-installed SPIRV-Tools, omit the first part and point CMAKE_PREFIX_PATH to their installation dir if necessary.

# Skip executables, tests and examples
set(SPIRV_SKIP_EXECUTABLES ON CACHE BOOL "" FORCE)
set(SPIRV_SKIP_TESTS ON CACHE BOOL "" FORCE)
set(SPIRV_HEADERS_SKIP_EXAMPLES ON CACHE BOOL "" FORCE)
# assumes SPIRV-Headers is cloned next to SPIRV-Tools
set(SPIRV-Headers_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
add_subdirectory(SPIRV-Tools EXCLUDE_FROM_ALL)

set(WITH_SPIRVTOOLSSHADERCONVERTER ON CACHE BOOL "" FORCE)
add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL)

# So the dynamically loaded plugin gets built implicitly
add_dependencies(your-app MagnumPlugins::SpirvToolsShaderConverter)

To use as a static plugin or as a dependency of another plugin with CMake, put FindMagnumPlugins.cmake and FindSpirvTools.cmake into your modules/ directory, request the SpirvToolsShaderConverter component of the MagnumPlugins package and link to the MagnumPlugins::SpirvToolsShaderConverter target:

find_package(MagnumPlugins REQUIRED SpirvToolsShaderConverter)

# ...
target_link_libraries(your-app PRIVATE MagnumPlugins::SpirvToolsShaderConverter)

See Downloading and building plugins, Plugin usage with CMake and Loading and using plugins for more information.

Conversion between SPIR-V binary and assembly

Use one of the convertDataToData(), convertDataToFile(), convertFileToData() or convertFileToFile() APIs to convert between SPIR-V binary and assembly, similarly to the spirv-as and spirv-dis tools. By default that's the only operation done by the plugin, additionally it can perform optimizations as described below. See Input and output format and version below for details on how to switch between binary and assembly output, see Plugin-specific config for a list of additional options related to the (dis)assembler.

The stage parameter of all conversion APIs is ignored, as SPIR-V has the information embedded (and additionally a single file can contain multiple entrypoints for multiple stages).

On error, the message contains either a line/column (when assembling) or instruction index (when disassemling).

SPIR-V validation

Use validateData() or validateFile() to validate a SPIR-V file. Compared to the spirv-val tool, it accepts a SPIR-V assembly as well, converting it to a SPIR-V binary first (equivalently to doing a conversion first, with the exact same behavior and options recognized). Note that in some cases, such as opening an inaccessible file or an assembly error the validation function can return {false, ""} and print a message to the error output instead.

Validation results are highly dependent on the target version set using setOutputFormat(), see Input and output format and version below for details. Additional validation options can be set through the plugin-specific config.

If the returned validation string contains a numeric identifier, it's always an instruction index, even in case of a SPIR-V assembly on the input.

SPIR-V optimization

Use setOptimizationLevel() to set a level of optimizations performed during convertDataToData(), convertDataToFile(), convertFileToData() or convertFileToFile(). By default no optimizations are done and the APIs just pass-through the data or convert between SPIR-V binary and assembly as described above. Valid optimization levels are:

  • 0 or the empty default performs no optimization
  • 1 optimizes for performance
  • s optimizes for size
  • legalizeHlsl turns SPIR-V originating from a HLSL source to one that can be accepted by Vulkan

Compared to spirv-opt it can work with assembly on both input and output as well, but there's currently no way to directly control particular optimizer stages, only general validation options specified through the plugin-specific config.

Input and output format and version

By default, the converter attempts to detect a SPIR-V binary and if that fails, it'll assume a SPIR-V assembly, parsing it as such. The output format is implicitly a SPIR-V binary. You can override the defaults in the following ways:

  1. Calling setInputFormat() and setOutputFormat() with either Format::Spirv or Format::SpirvAssembly. Format::Unspecified is the default behavior described above.
  2. Loading the plugin through one of the SpirvToSpirvAssemblyShaderConverter, SpirvAssemblyToSpirvShaderConverter, SpirvShaderConverter or SpirvAssemblyShaderConverter, which will set the input and output format accordingly, the last two setting both the input and output format to the same value
  3. Calling convertFileToFile(), in which case the input format is autodetected based on file contents and the output format is a SPIR-V assembly instead of SPIR-V binary (the default) if the output file extension is *.spvasm.

The format passed to setInputFormat() has to be either Format::Unspecified, Format::Spirv or Format::SpirvAssembly. The version parameter is currently reserved for future extensions and has to be always empty.

The format passed to setOutputFormat() has to be either Format::Unspecified, Format::Spirv or Format::SpirvAssembly for conversion and Format::Unspecified for validation. The version string can be one of these. Depending on the version of SPIRV-Tools the plugin is linked against, some choices might not be available or there might be new ones:

  • spv1.0 for SPIR-V 1.0 with no other restrictions
  • spv1.1 for SPIR-V 1.1 with no other restrictions
  • spv1.2 for SPIR-V 1.2 with no other restrictions
  • spv1.3 for SPIR-V 1.3 with no other restrictions
  • spv1.4 for SPIR-V 1.4 with no other restrictions. Available since SPIRV-Tools 2019.3.
  • spv1.5 for SPIR-V 1.5 with no other restrictions. Available since SPIRV-Tools 2019.5.
  • vulkan1.0 for Vulkan 1.0 with SPIR-V 1.0
  • vulkan1.1 for Vulkan 1.1 with SPIR-V 1.3
  • vulkan1.1spv1.4 for Vulkan 1.1 with SPIR-V 1.4. Available since SPIRV-Tools 2019.3.
  • vulkan1.2 for Vulkan 1.1 with SPIR-V 1.5. Available since SPIRV-Tools 2020.1.
  • opencl1.2 for OpenCL Full Profile 1.2 plus cl_khr_il_program
  • opencl1.2embedded for OpenCL Embedded Profile 1.2 plus cl_khr_il_program
  • opencl2.0 for OpenCL Full Profile 2.0 plus cl_khr_il_program
  • opencl2.0embedded for OpenCL Embedded Profile 2.0 plus cl_khr_il_program
  • opencl2.1 for OpenCL Full Profile 2.1
  • opencl2.1embedded for OpenCL Embedded Profile 2.1
  • opencl2.2 for OpenCL Full Profile 2.2
  • opencl2.2embedded for OpenCL Embedded Profile 2.2
  • opengl4.0 for OpenGL 4.0 plus ARB_gl_spirv
  • opengl4.1 for OpenGL 4.1 plus ARB_gl_spirv
  • opengl4.2 for OpenGL 4.2 plus ARB_gl_spirv
  • opengl4.3 for OpenGL 4.3 plus ARB_gl_spirv
  • opengl4.5 for OpenGL 4.5 plus ARB_gl_spirv

Default if no version string is specified is vulkan1.0. There's no variant for OpenGL 4.4.

Plugin-specific config

It's possible to tune various assembler, disassembler and validator options through configuration(). The assembler options are used also during validation in case the input is a SPIR-V assembly. See below for all options and their default values.

[configuration]

# Assembler-related options

# If enabled, numeric IDs in the binary will have the same values as in the
# assembly text. Non-numeric IDs are allocated by filling in the gaps, starting
# with 1 and going up. Implicitly enabled when validating a SPIR-V assembly.
preserveNumericIds=false

# Disassembler-related options

# ANSI-colored disassembly output, useful when printing directly to a terminal
color=false
# Indent the disassembly output
indent=true
# Show byte offset for each disassembled instruction
byteOffset=false
# Output the header as leading comments in the disassembly
header=true
# Use friendly names in the disassembly instead of raw IDs where possible
friendlyNames=true

# Optimizer options, in addition to the preset passed in setOptimizationLevel()

# Run the validator before optimization / after each optimization pass. The
# latter is available since SPIRV-Tools 2019.3, ignored on earlier versions.
validateBeforeOptimization=true
validateAfterEachOptimization=false
# Print resource utilitzation of each pass to the output
optimizerTimeReport=false
# Preserve bindings / specialization constans during optimization. Available
# since SPIRV-Tools 2019.4, ignored on earlier versions.
preserveBindings=false
preserveSpecializationConstants=false

# Validation options

# Maximum allowed number of struct members, struct nesting depth, local
# variables, global variables, branches allowed in switch statements, arguments
# per function, Control Flow nesting depth, indices to use for Access Chain
# instruction and the ID bound. All those default to the Universal Limits
# described in the SPIR-V spec.
maxStructMembers=16383
maxStructDepth=255
maxLocalVariables=524287
maxGlobalVariables=65535
maxSwitchBranches=16383
maxFunctionArgs=255
maxControlFlowNestingDepth=1023
maxAccessChainIndices=255
# Used when optimizing even if validateBeforeOptimization is disabled
maxIdBound=4194303

# Allow allocating an object of a pointer type and returning a pointer value
# from a function in logical addressing mode
relaxLogicalPointer=false

# Enable VK_KHR_relaxed_block_layout when checking standard uniform, storage
# buffer, and push constant layouts. This is the default when targeting Vulkan
# 1.1 or later.
relaxBlockLayout=false

# Enable VK_KHR_uniform_buffer_standard_layout when checking standard uniform
# buffer layouts. Available since SPIRV-Tools 2019.3, ignored on earlier
# versions.
uniformBufferStandardLayout=false

# Enable VK_EXT_scalar_block_layout when checking standard uniform, storage
# buffer, and push constant layouts. Scalar layout rules are more permissive
# than relaxed block layout so in effect this will override the
# relax-block-layout option.
scalarBlockLayout=false

# Skip checking standard uniform/storage buffer layout. Overrides any
# relax-block-layout or scalar-block-layout option.
skipBlockLayout=false

# Allow store from one struct type to a different type with compatible layout
# and members.
relaxStructStore=false

# Allows code patterns that are intended to be fixed by SPIR-V Optimizer's
# legalization passes. Available since SPIRV-Tools 2019.3, ignored on earlier
# versions.
beforeHlslLegalization=false

See Editing plugin-specific configuration for more information and an example showing how to edit the configuration values.

Base classes

class AbstractConverter new in Git master
Base for shader converter plugins.

Constructors, destructors, conversion operators

SpirvToolsConverter(PluginManager::AbstractManager& manager, const std::string& plugin) explicit
Plugin manager constructor.