spirv-cross(1)

๐Ÿ’– spirv-cross(1) ๐Ÿ’–

User Commands โ€ข the manual page, part 1 of 4 โ€ข bestie edition, no cap


โœจ NAME โœจ

spirv-cross โ€” a tool designed for parsing and converting SPIR-V to other shader languages. periodt.

๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

spirv-cross <...>

๐Ÿ’… DESCRIPTION ๐Ÿ’…

๐Ÿ“ Basic ๐Ÿ“

  • [SPIR-V file] (- is stdin) and [--output <output path>] โ€” if the output path isn't provided, it prints output to stdout. slay.
  • [--dump-resources] โ€” prints a basic reflection of the SPIR-V module along with other output. โœจ
  • [--help] โ€” prints this help message.

๐ŸŒˆ Select backend ๐ŸŒˆ

By default, OpenGL-style GLSL is the target, with #version and GLSL/ESSL information inherited from the SPIR-V module if present.

  • --vulkan-semantics or -V โ€” emit Vulkan GLSL instead of plain GLSL. Makes use of Vulkan-only features to match SPIR-V.
  • --msl โ€” emit Metal Shading Language (MSL).
  • --hlsl โ€” emit HLSL.
  • --reflect โ€” emit JSON reflection.
  • --cpp โ€” DEPRECATED. Emits C++ code.

๐Ÿ’– Common options ๐Ÿ’–

  • --entry name โ€” use a specific entry point. By default, the first entry point in the module is used.
  • --stage <stage (vert, frag, geom, tesc, tese comp)> โ€” forces use of a certain shader stage. Can disambiguate the entry point if more than one entry point exists with same name, but different stage.
  • --emit-line-directives โ€” if SPIR-V has OpLine directives, aim to emit those accurately in output code as well.
  • --rename-entry-point <old> <new> <stage> โ€” renames an entry point from what is declared in SPIR-V to code output. Mostly relevant for HLSL or MSL.
  • --rename-interface-variable <in|out> <location> <new_variable_name> โ€” rename an interface variable based on location decoration.
  • --force-zero-initialized-variables โ€” forces temporary variables to be initialized to zero. Can be useful in environments where compilers do not allow potentially uninitialized variables. This usually comes up with Phi temporaries.
  • --fixup-clipspace โ€” fixup Z clip-space at the end of a vertex shader. The behavior is backend-dependent. GLSL: Rewrites [0, w] Z range (D3D/Metal/Vulkan) to GL-style [-w, w]. HLSL/MSL: Rewrites [-w, w] Z range (GL) to D3D/Metal/Vulkan-style [0, w].
  • --flip-vert-y โ€” inverts gl_Position.y (or equivalent) at the end of a vertex shader. This is equivalent to using negative viewport height.

๐ŸŽ€ GLSL options ๐ŸŽ€

  • --es โ€” force ESSL.
  • --no-es โ€” force desktop GLSL.
  • --version <GLSL version> โ€” e.g. --version 450 will emit '#version 450' in shader. Code generation will depend on the version used.
  • --flatten-ubo โ€” emit UBOs as plain uniform arrays which are suitable for use with glUniform4*v(). This can be an optimization on GL implementations where this is faster or works around buggy driver implementations. E.g.: uniform MyUBO { vec4 a; float b, c, d, e; }; will be emitted as uniform vec4 MyUBO[2]; Caveat: You cannot mix and match floating-point and integer in the same UBO with this option. Legacy GLSL/ESSL (where this flattening makes sense) does not support bit-casting, which would have been the obvious workaround.
  • --extension ext โ€” add #extension string of your choosing to GLSL output. Useful if you use variable name remapping to something that requires an extension unknown to SPIRV-Cross.
  • --remove-unused-variables โ€” do not emit interface variables which are not statically accessed by the shader.
  • --separate-shader-objects โ€” redeclare gl_PerVertex blocks to be suitable for desktop GL separate shader objects.
  • --glsl-emit-push-constant-as-ubo โ€” instead of a plain uniform of struct for push constants, emit a UBO block instead.
  • --glsl-emit-ubo-as-plain-uniforms โ€” instead of emitting UBOs, emit them as plain uniform structs.
  • --glsl-remap-ext-framebuffer-fetch input-attachment color-location โ€” remaps an input attachment to use GL_EXT_shader_framebuffer_fetch. gl_LastFragData[location] is read from. The attachment to read from must be declared as an output in the shader.
  • --vulkan-glsl-disable-ext-samplerless-texture-functions โ€” do not allow use of GL_EXT_samperless_texture_functions, even in Vulkan GLSL. Use of texelFetch and similar might have to create dummy samplers to work around it.
  • --combined-samplers-inherit-bindings โ€” inherit binding information from the textures when building combined image samplers from separate textures and samplers.
  • --no-support-nonzero-baseinstance โ€” when using gl_InstanceIndex with desktop GL, assume that base instance is always 0, and do not attempt to fix up gl_InstanceID to match Vulkan semantics.
  • --pls-in format input-name โ€” remaps a subpass input with name into a GL_EXT_pixel_local_storage input. Entry in PLS block is ordered where first --pls-in marks the first entry. Can be called multiple times. Formats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui. Requires ESSL.
  • --pls-out format output-name โ€” remaps a color output with name into a GL_EXT_pixel_local_storage output. Entry in PLS block is ordered where first --pls-output marks the first entry. Can be called multiple times. Formats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui. Requires ESSL.
  • --remap source_name target_name components โ€” remaps a variable to a different name with N components. Main use case is to remap a subpass input to gl_LastFragDepthARM. E.g.: uniform subpassInput uDepth; --remap uDepth gl_LastFragDepthARM 1 --extension GL_ARM_shader_framebuffer_fetch_depth_stencil
  • --no-420pack-extension โ€” do not make use of GL_ARB_shading_language_420pack in older GL targets to support layout(binding).
  • --remap-variable-type <variable_name> <new_variable_type> โ€” remaps a variable type based on name. Primary use case is supporting external samplers in ESSL for video rendering on Android where you could remap a texture to a YUV one.
  • --glsl-force-flattened-io-blocks โ€” always flatten I/O blocks and structs.

๐Ÿฆ‹ MSL options ๐Ÿฆ‹

  • --msl-version <MMmmpp> โ€” uses a specific MSL version, e.g. --msl-version 20100 for MSL 2.1.
  • --msl-capture-output โ€” writes geometry varyings to a buffer instead of as stage-outputs.
  • --msl-swizzle-texture-samples โ€” works around lack of support for VkImageView component swizzles. This has a massive impact on performance and bloat. Do not use this unless you are absolutely forced to. To use this feature, the API side must pass down swizzle buffers. Should only be used by translation layers as a last resort. Recent Metal versions do not require this workaround.
  • --msl-ios โ€” target iOS Metal instead of macOS Metal.
  • --msl-pad-fragment-output โ€” always emit color outputs as 4-component variables. In Metal, the fragment shader must emit at least as many components as the render target format.
  • --msl-domain-lower-left โ€” use a lower-left tessellation domain.
  • --msl-argument-buffers โ€” emit Indirect Argument buffers instead of plain bindings. Requires MSL 2.0 to be enabled.
  • --msl-texture-buffer-native โ€” enable native support for texel buffers. Otherwise, it is emulated as a normal texture.
  • --msl-framebuffer-fetch โ€” implement subpass inputs with frame buffer fetch. Emits [[color(N)]] inputs in fragment stage. Requires an Apple GPU.
  • --msl-emulate-cube-array โ€” emulate cube arrays with 2D array and manual math.
  • --msl-discrete-descriptor-set <index> โ€” when using argument buffers, forces a specific descriptor set to be implemented without argument buffers. Useful for implementing push descriptors in emulation layers. Can be used multiple times for each descriptor set in question.
  • --msl-device-argument-buffer <descriptor set index> โ€” use device address space to hold indirect argument buffers instead of constant. Comes up when trying to support argument buffers which are larger than 64 KiB.
  • --msl-multiview โ€” enable SPV_KHR_multiview emulation.
  • --msl-multiview-no-layered-rendering โ€” don't set [[render_target_array_index]] in multiview shaders. Useful for devices which don't support layered rendering. Only effective when --msl-multiview is enabled.
  • --msl-view-index-from-device-index โ€” treat the view index as the device index instead. For multi-GPU rendering.
  • --msl-dispatch-base โ€” add support for vkCmdDispatchBase() or similar APIs. Offsets the workgroup ID based on a buffer.
  • --msl-dynamic-buffer <set index> <binding> โ€” marks a buffer as having dynamic offset. The offset is applied in the shader with pointer arithmetic. Useful for argument buffers where it is non-trivial to apply dynamic offset otherwise.
  • --msl-inline-uniform-block <set index> <binding> โ€” in argument buffers, mark an UBO as being an inline uniform block which is embedded into the argument buffer itself.
  • --msl-decoration-binding โ€” use SPIR-V bindings directly as MSL bindings. This does not work in the general case as there is no descriptor set support, and combined image samplers are split up. However, if the shader author knows of binding limitations, this option will avoid the need for reflection on Metal side.
  • --msl-force-active-argument-buffer-resources โ€” (bestie, the description for this one is in the next part, hold on to your seat โœจ)

Always emit resources which are part of argument buffers. This makes sure that similar shaders with same resource declarations can share the argument buffer as declaring an argument buffer implies an ABI. ๐Ÿซถ

  • --msl-force-native-arrays โ€” instead of implementing array types as a templated value type ala std::array<T>, use plain, native arrays. It's giving worse code-gen ngl, but it can work around driver bugs on certain driver revisions of certain Intel-based Macbooks where template arrays break. ๐Ÿ˜ญ
  • --msl-disable-frag-depth-builtin โ€” disables FragDepth output. Useful if your pipeline does not enable depth, since pipeline creation might otherwise fail. ๐Ÿ’€
  • --msl-disable-frag-stencil-ref-builtin โ€” disable FragStencilRef output. Useful if your pipeline does not enable stencil output, because pipeline creation might otherwise fail. ๐Ÿ’€
  • --msl-enable-frag-output-mask <mask> โ€” only selectively enable fragment outputs. Useful if your pipeline does not enable fragment output for certain locations, as pipeline creation might otherwise fail. ๐Ÿ™ˆ
  • --msl-no-clip-distance-user-varying โ€” do not emit user varyings to emulate gl_ClipDistance in fragment shaders. โœจ
  • --msl-shader-input <index> <format> <size> โ€” specify the format of the shader input at <index>. <format> can be any32, any16, u16, u8, or other, to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader. Useful if shader stage interfaces don't match up, as pipeline creation might otherwise fail. ๐Ÿ”ฅ
  • --msl-multi-patch-workgroup โ€” use the new style of tessellation control processing, where multiple patches are processed per workgroup. This should increase throughput by ensuring all the GPU's SIMD lanes are occupied, but heads up, it is not compatible with the old style. In addition, this style also passes input variables in buffers directly instead of using vertex attribute processing. In a future version of SPIRV-Cross, this will become the default. ๐Ÿ‘‘
  • --msl-vertex-for-tessellation โ€” when handling a vertex shader, marks it as one that will be used with a new-style tessellation control shader. The vertex shader is output to MSL as a compute kernel which outputs vertices to the buffer in the order they are received, rather than in index order as with --msl-capture-output normally. ๐Ÿฆ‹
  • --msl-additional-fixed-sample-mask <mask> โ€” set an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two. ๐Ÿ’…
  • --msl-arrayed-subpass-input โ€” assume that images of dimension SubpassData have multiple layers. Layered input attachments are accessed relative to BuiltInLayer. This option has no effect if multiview is also enabled. ๐ŸŒธ
  • --msl-r32ui-linear-texture-align <alignment> โ€” the required alignment of linear textures of format MTLPixelFormatR32Uint. This is used to align the row stride for atomic accesses to such images. โญ
  • --msl-r32ui-linear-texture-align-constant-id <id> โ€” the function constant ID to use for the linear texture alignment. On MSL 1.2 or later, you can override the alignment by setting this function constant. ๐ŸŽ€
  • --msl-texture-1d-as-2d โ€” emit Image variables of dimension Dim1D as texture2d. In Metal, 1D textures do not support all features that 2D textures do. Use this option if your code relies on these features. ๐Ÿ’œ
  • --msl-ios-use-simdgroup-functions โ€” use simd_*() functions for subgroup ops instead of quad_*(). Recent Apple GPUs support SIMD-groups larger than a quad. Use this option to take advantage of this support. ๐Ÿ”ฅ
  • --msl-emulate-subgroups โ€” assume subgroups of size 1. Intended for Vulkan Portability implementations where Metal support for SIMD-groups is insufficient for true subgroups. ๐Ÿ˜ญ
  • --msl-fixed-subgroup-size <size> โ€” assign a constant <size> to the SubgroupSize builtin. Intended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled. If 0, assume variable subgroup size as actually exposed by Metal. ๐ŸŒˆ
  • --msl-force-sample-rate-shading โ€” force fragment shaders to run per sample. This adds a [[sample_id]] parameter if none is already present. ๐Ÿ’–

๐Ÿ”ฅ HLSL OPTIONS ๐Ÿ”ฅ

  • --shader-model โ€” enables a specific shader model, e.g. --shader-model 50 for SM 5.0. ๐Ÿ‘‘
  • --hlsl-enable-compat โ€” allow point size and point coord to be used, even if they won't work as expected. PointSize is ignored, and PointCoord returns (0.5, 0.5). ๐Ÿ’€
  • --hlsl-support-nonzero-basevertex-baseinstance โ€” support base vertex and base instance by emitting a special cbuffer declared as:
cbuffer SPIRV_Cross_VertexInfo
{
    int SPIRV_Cross_BaseVertex;
    int SPIRV_Cross_BaseInstance;
};
  • --hlsl-auto-binding (push, cbv, srv, uav, sampler, all) โ€” do not emit any : register(#) bindings for specific resource types, and rely on the HLSL compiler to assign something. ๐ŸŽ€
  • --hlsl-force-storage-buffer-as-uav โ€” always emit SSBOs as UAVs, even when marked as read-only. Normally, SSBOs marked with NonWritable will be emitted as SRVs. ๐Ÿ’…
  • --hlsl-nonwritable-uav-texture-as-srv โ€” emit NonWritable storage images as SRV textures instead of UAV. Using this option messes with the type system. SPIRV-Cross cannot guarantee that this will work. One major problem area with this feature is function arguments, where we won't know if we're seeing a UAV or SRV. Shader must ensure that read/write state is consistent at all call sites. ๐Ÿ˜ญ
  • --set-hlsl-vertex-input-semantic <location> <semantic> โ€” emits a specific vertex input semantic for a given location. Otherwise, TEXCOORD# is used as semantics, where # is location. โœจ
  • --hlsl-enable-16bit-types โ€” enables native use of half/int16_t/uint16_t and ByteAddressBuffer interaction with these types. Requires SM 6.2. ๐Ÿฆ‹
  • --hlsl-flatten-matrix-vertex-input-semantics โ€” emits matrix vertex inputs with input semantics as if they were independent vectors, e.g. TEXCOORD{2,3,4} rather than matrix form TEXCOORD2_{0,1,2}. ๐ŸŒธ

๐Ÿ’€ OBSCURE OPTIONS ๐Ÿ’€

These options are not meant to be used on a regular basis. They have some occasional uses in the test suite. ๐Ÿ™ˆ

  • --force-temporary โ€” aggressively emit temporary expressions instead of forwarding expressions. Very rarely used and under-tested. ๐Ÿ’€
  • --revision โ€” prints build timestamp and Git commit information (updated when cmake is configured). โญ
  • --iterations iter โ€” recompiles the same shader over and over, benchmarking related. ๐Ÿ”
  • --disable-storage-image-qualifier-deduction โ€” if storage images are received without any nonwritable or nonreadable information, do not attempt to analyze usage, and always emit read/write state. ๐Ÿ‘‘
  • --flatten-multidimensional-arrays โ€” do not support multi-dimensional arrays and flatten them to one dimension. ๐Ÿงš
  • --cpp-interface-name <name> โ€” emit a specific class name in C++ codegen. ๐Ÿ’œ

๐Ÿซถ USAGE ๐Ÿซถ

Usage: spirv-cross <...>

๐ŸŒธ Basic ๐ŸŒธ

  • [SPIR-V file] (- is stdin) [--output <output path>] โ€” if not provided, prints output to stdout. ๐Ÿ’–
  • [--dump-resources] โ€” prints a basic reflection of the SPIR-V module along with other output. โœจ
  • [--help] โ€” prints this help message. ๐ŸŽ€

๐Ÿ‘‘ Select backend ๐Ÿ‘‘

By default, OpenGL-style GLSL is the target, with #version and GLSL/ESSL information inherited from the SPIR-V module if present. ๐ŸŒˆ

  • --vulkan-semantics, -V โ€” emit Vulkan GLSL instead of plain GLSL. Makes use of Vulkan-only features to match SPIR-V. ๐Ÿ”ฅ
  • --msl โ€” emit Metal Shading Language (MSL). ๐Ÿ’…
  • --hlsl โ€” emit HLSL. โญ
  • --reflect โ€” emit JSON reflection. ๐Ÿฆ‹
  • --cpp โ€” DEPRECATED. Emits C++ code. ๐Ÿ’€

๐Ÿ’– Common options ๐Ÿ’–

  • --entry name โ€” use a specific entry point. By default, the first entry point in the module is used. ๐Ÿ‘‘
  • --stage <stage (vert, frag, geom, tesc, tese comp)> โ€” forces use of a certain shader stage. Can disambiguate the entry point if more than one entry point exists with same name, but different stage. ๐ŸŒธ
  • --emit-line-directives โ€” if SPIR-V has OpLine directives, aim to emit those accurately in output code as well. โœจ
  • --rename-entry-point <old> <new> <stage> โ€” renames an entry point from what is declared in SPIR-V to code output. Mostly relevant for HLSL or MSL. ๐ŸŽ€
  • --rename-interface-variable <in|out> <location> <new_variable_name> โ€” rename an interface variable based on location decoration. ๐Ÿ’œ
  • --force-zero-initialized-variables โ€” forces temporary variables to be initialized to zero. Can be useful in environments where compilers do not allow potentially uninitialized variables. This usually comes up with Phi temporaries. ๐Ÿ”ฅ
  • --fixup-clipspace โ€” fixup Z clip-space at the end of a vertex shader. The behavior is backend-dependent. GLSL: rewrites [0, w] Z range (D3D/Metal/Vulkan) to GL-style [-w, w]. HLSL/MSL: rewrites [-w, w] Z range (GL) to D3D/Metal/Vulkan-style [0, w]. ๐Ÿฆ‹
  • --flip-vert-y โ€” inverts gl_Position.y (or equivalent) at the end of a vertex shader. This is equivalent to using negative viewport height. โญ

๐ŸŽ€ GLSL options ๐ŸŽ€

  • --es โ€” force ESSL. ๐Ÿ’–
  • --no-es โ€” force desktop GLSL. ๐Ÿ’…
  • --version <GLSL version> โ€” e.g. --version 450 will emit '#version 450' in shader. Code generation will depend on the version used. ๐Ÿ‘‘
  • --flatten-ubo โ€”

okay so this one's the tail end of the flatten-the-UBOs situation ๐Ÿ’… โ€” it spits your UBOs out as plain uniform arrays, the kind that play nice with glUniform4*v(). It can be a real optimization on GL implementations where that path is faster, and it also dodges some genuinely cursed buggy driver behaviour. Like, look at this glow-up:

uniform MyUBO { vec4 a; float b, c, d, e; };

gets emitted as

uniform vec4 MyUBO[2];
โš ๏ธ Caveat bestie, no cap: you literally cannot mix floating-point and integer in the same UBO with this on. Legacy GLSL/ESSL (the only place this flattening even makes sense) doesn't support bit-casting, which would've been the obvious workaround. So it's giving "pick a lane." ๐Ÿ˜ญ
  • --extension ext โ€” drops an #extension string of your choosing straight into the GLSL output. Super useful when you're using variable name remapping to something that needs an extension SPIRV-Cross has never heard of. โœจ
  • --remove-unused-variables โ€” don't emit interface variables that the shader never statically accesses. If nobody's reading it, it's not invited to the party. ๐Ÿ™ˆ
  • --separate-shader-objects โ€” redeclares gl_PerVertex blocks so they're suitable for desktop GL separate shader objects. Desktop GL girlies, this one's for you. ๐Ÿซถ
  • --glsl-emit-push-constant-as-ubo โ€” instead of a plain uniform of struct for push constants, emit a UBO block instead. Switching up the fit. ๐Ÿ‘‘
  • --glsl-emit-ubo-as-plain-uniforms โ€” instead of emitting UBOs, emit them as plain uniform structs. The reverse slay. ๐Ÿ’…
  • --glsl-remap-ext-framebuffer-fetch input-attachment color-location โ€” remaps an input attachment to use GL_EXT_shader_framebuffer_fetch. gl_LastFragData[location] is what gets read from. Heads up: the attachment you're reading from must be declared as an output in the shader, periodt.
  • --vulkan-glsl-disable-ext-samplerless-texture-functions โ€” don't allow use of GL_EXT_samperless_texture_functions, even in Vulkan GLSL. Using texelFetch and friends might force you to create dummy samplers to work around it. ๐Ÿ˜ญ
  • --combined-samplers-inherit-bindings โ€” inherit binding info from the textures when building combined image samplers out of separate textures and samplers. Sharing is caring. ๐Ÿ’–
  • --no-support-nonzero-baseinstance โ€” when using gl_InstanceIndex with desktop GL, assume the base instance is always 0, and don't bother trying to fix up gl_InstanceID to match Vulkan semantics. No extra work, no extra stress. ๐ŸŒธ
  • --pls-in format input-name โ€” remaps a subpass input with name into a GL_EXT_pixel_local_storage input. The entry's position in the PLS block is ordered so that the first --pls-in marks the first entry. Can be called multiple times. Formats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui. Requires ESSL. ๐ŸŽ€
  • --pls-out format output-name โ€” remaps a color output with name into a GL_EXT_pixel_local_storage output. Same ordering rules: the first --pls-output marks the first entry. Can be called multiple times. Formats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui. Requires ESSL. ๐ŸŽ€
  • --remap source_name target_name components โ€” remaps a variable to a different name with N components. The main character use case here is remapping a subpass input to gl_LastFragDepthARM. E.g.:
uniform subpassInput uDepth; --remap uDepth gl_LastFragDepthARM 1 --extension GL_ARM_shader_framebuffer_fetch_depth_stencil
  • --no-420pack-extension โ€” do not make use of GL_ARB_shading_language_420pack in older GL targets just to support layout(binding). Living without it, we can do it. ๐Ÿ’ช
  • --remap-variable-type <variable_name> <new_variable_type> โ€” remaps a variable type based on its name. Primary use case: supporting external samplers in ESSL for video rendering on Android, where you could remap a texture to a YUV one. Android girlies rise. ๐ŸŒˆ
  • --glsl-force-flattened-io-blocks โ€” always flatten I/O blocks and structs. Flatten everything, bestie. ๐Ÿฆ‹

๐ŸŽ MSL options ๐ŸŽ

  • --msl-version <MMmmpp> โ€” uses a specific MSL version, e.g. --msl-version 20100 for MSL 2.1. Set the vibe, choose your version. โญ
  • --msl-capture-output โ€” writes geometry varyings to a buffer instead of as stage-outputs. Rerouting the mail. ๐Ÿ“ฆ
  • --msl-swizzle-texture-samples โ€” works around the lack of support for VkImageView component swizzles.
๐Ÿšจ Bestie this one has a massive impact on performance and bloat. Do not use this unless you are absolutely, genuinely forced to. To use it, the API side must pass down swizzle buffers. It should only ever be used by translation layers as a last resort. Recent Metal versions do not require this workaround, so likeโ€ฆ check first. ๐Ÿ’€
  • --msl-ios โ€” target iOS Metal instead of macOS Metal. ๐Ÿ“ฑ
  • --msl-pad-fragment-output โ€” always emit color outputs as 4-component variables. In Metal, the fragment shader must emit at least as many components as the render target format. Pad it out. โœจ
  • --msl-domain-lower-left โ€” use a lower-left tessellation domain. ๐Ÿฆ‹
  • --msl-argument-buffers โ€” emit Indirect Argument buffers instead of plain bindings. Requires MSL 2.0 to be enabled. ๐Ÿ‘‘
  • --msl-texture-buffer-native โ€” enable native support for texel buffers. Otherwise, it gets emulated as a normal texture. Fake it till you make it. ๐ŸŽ€
  • --msl-framebuffer-fetch โ€” implement subpass inputs with frame buffer fetch. Emits [[color(N)]] inputs in the fragment stage. Requires an Apple GPU. ๐ŸŽ
  • --msl-emulate-cube-array โ€” emulate cube arrays with a 2D array and manual math. Doing the math ourselves because we're capable like that. ๐Ÿงฎ
  • --msl-discrete-descriptor-set <index> โ€” when using argument buffers, forces a specific descriptor set to be implemented without argument buffers. Super useful for implementing push descriptors in emulation layers. Can be used multiple times, once for each descriptor set in question. ๐Ÿ”
  • --msl-device-argument-buffer <descriptor set index> โ€” use the device address space to hold indirect argument buffers instead of constant. Comes up when you're trying to support argument buffers larger than 64 KiB. Big buffer energy. ๐Ÿ”ฅ
  • --msl-multiview โ€” enable SPV_KHR_multiview emulation. ๐Ÿ‘€
  • --msl-multiview-no-layered-rendering โ€” don't set [[render_target_array_index]] in multiview shaders. Useful for devices that don't support layered rendering. Only effective when --msl-multiview is enabled. โš ๏ธ
  • --msl-view-index-from-device-index โ€” treat the view index as the device index instead. For multi-GPU rendering. Teamwork. ๐Ÿซถ
  • --msl-dispatch-base โ€” add support for vkCmdDispatchBase() or similar APIs. Offsets the workgroup ID based on a buffer. ๐Ÿ“
  • --msl-dynamic-buffer <set index> <binding> โ€” marks a buffer as having a dynamic offset. The offset gets applied in the shader with pointer arithmetic. Useful for argument buffers where applying a dynamic offset is otherwise non-trivial. ๐Ÿง 
  • --msl-inline-uniform-block <set index> <binding> โ€” in argument buffers, mark a UBO as being an inline uniform block which is embedded into the argument buffer itself. Nesting era. ๐Ÿช†
  • --msl-decoration-binding โ€” use SPIR-V bindings directly as MSL bindings. This does not work in the general case, because there's no descriptor set support and combined image samplers get split up. However, if the shader author knows about the binding limitations, this option will avoid the need for reflection on the Metal side. YMMV, iykyk. ๐Ÿ’…
  • --msl-force-active-argument-buffer-resources โ€” always emit resources which are part of argument buffers. This makes sure similar shaders with the same resource declarations can share the argument buffer, since declaring an argument buffer implies an ABI. ๐Ÿค
  • --msl-force-native-arrays โ€” rather than implementing array types as a templated value type ala std::array<T>, use plain, native arrays. This leads to worse code-gen, but it can work around driver bugs on certain driver revisions of certain Intel-based Macbooks where template arrays break. Fixing the laptop, not the code. ๐Ÿ’ป
  • --msl-disable-frag-depth-builtin โ€” disables FragDepth output. Useful if the pipeline does not enable depth, since pipeline creation might otherwise fail. ๐Ÿ™…
  • --msl-disable-frag-stencil-ref-builtin โ€” disable FragStencilRef output. Useful if the pipeline does not enable stencil output, since pipeline creation might otherwise fail. ๐Ÿ™…
  • --msl-enable-frag-output-mask <mask> โ€” only selectively enable fragment outputs. Useful if the pipeline does not enable fragment output for certain locations, since pipeline creation might otherwise fail. ๐ŸŽฏ
  • --msl-no-clip-distance-user-varying โ€” do not emit user varyings to emulate gl_ClipDistance in fragment shaders. โœ‚๏ธ
  • --msl-shader-input <index> <format> <size> โ€” specify the format of the shader input at <index>. <format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader. Useful if shader stage interfaces don't match up, since pipeline creation might otherwise fail. ๐Ÿงฉ
  • --msl-multi-patch-workgroup โ€” use the new style of tessellation control processing, where multiple patches are processed per workgroup. This should increase throughput by ensuring all the GPU's SIMD lanes are occupied, but it is not compatible with the old style. In addition, this style also passes input variables in buffers directly instead of using vertex attribute processing. In a future version of SPIRV-Cross, this will become the default. Future is now-ish. ๐Ÿ”ฎ
  • --msl-vertex-for-tessellation โ€” when handling a vertex shader, marks it as one that will be used with a new-style tessellation control shader. The vertex shader is output to MSL as a compute kernel which outputs vertices to the buffer in the order they are received, rather than in index order as with --msl-capture-output normally. Order matters, bestie. ๐Ÿ“‹
  • --msl-additional-fixed-sample-mask <mask> โ€” set an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two. ๐Ÿ”—
  • --msl-arrayed-subpass-input

Also, quick note on the option from literally one second ago (the layered-attachment one, you know the one ๐Ÿ’…): Assume that images of dimension SubpassData have multiple layers. Layered input attachments are accessed relative to BuiltInLayer. And heads up bestie โ€” this option has no effect if multiview is also enabled. It's giving "mutually exclusive," fr fr.

  • --msl-r32ui-linear-texture-align <alignment> โ€” the required alignment of linear textures of format MTLPixelFormatR32Uint. It's used to align the row stride for atomic accesses to those images. Alignment matters, no cap ๐ŸŽ€
  • --msl-r32ui-linear-texture-align-constant-id <id> โ€” the function constant ID you use for that linear texture alignment. On MSL 1.2 or later, you can override the alignment by setting this function constant. Override era โœจ
  • --msl-texture-1d-as-2d โ€” emit Image variables of dimension Dim1D as texture2d. In Metal, 1D textures do not support all features that 2D textures do. Use this option if your code relies on those features. Fake it till you make it ๐Ÿ’…
  • --msl-ios-use-simdgroup-functions โ€” use simd_*() functions for subgroup ops instead of quad_*(). Recent Apple GPUs support SIMD-groups larger than a quad, so flip this on to actually take advantage of that. Bigger groups, bigger slay ๐Ÿ”ฅ
  • --msl-emulate-subgroups โ€” assume subgroups of size 1. Intended for Vulkan Portability implementations where Metal's support for SIMD-groups is just not enough for true subgroups. Pretend era, but on purpose ๐Ÿ™ˆ
  • --msl-fixed-subgroup-size <size> โ€” assign a constant <size> to the SubgroupSize builtin. Intended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled. If 0, assume variable subgroup size as actually exposed by Metal. Pick your fighter ๐ŸŒธ
  • --msl-force-sample-rate-shading โ€” force fragment shaders to run per sample. This adds a [[sample_id]] parameter if none is already present. Per sample, per moment, main character energy ๐Ÿ‘‘

๐Ÿ”ฅ HLSL options ๐Ÿ”ฅ

  • --shader-model โ€” enables a specific shader model, e.g. --shader-model 50 for SM 5.0.
  • --hlsl-enable-compat โ€” allow point size and point coord to be used, even if they won't work as expected. PointSize is ignored, and PointCoord returns (0.5, 0.5). So likeโ€ฆ it compiles. That's the vibe ๐Ÿ˜ญ
  • --hlsl-support-nonzero-basevertex-baseinstance โ€” support base vertex and base instance by emitting a special cbuffer declared as:
cbuffer SPIRV_Cross_VertexInfo
{
    int SPIRV_Cross_BaseVertex;
    int SPIRV_Cross_BaseInstance;
};
  • --hlsl-auto-binding (push, cbv, srv, uav, sampler, all) โ€” do not emit any : register(#) bindings for specific resource types, and rely on the HLSL compiler to assign something. Delegate era, we love a handoff ๐Ÿซถ
  • --hlsl-force-storage-buffer-as-uav โ€” always emit SSBOs as UAVs, even when they're marked as read-only. Normally, SSBOs marked with NonWritable get emitted as SRVs. No read-only privilege here, they're all UAVs now ๐Ÿ’…
  • --hlsl-nonwritable-uav-texture-as-srv โ€” emit NonWritable storage images as SRV textures instead of UAV.
โš ๏ธ Using this option messes with the type system. SPIRV-Cross cannot guarantee that this will work. One major problem area with this feature is function arguments, where we won't know if we're seeing a UAV or SRV. Shader must ensure that read/write state is consistent at all call sites. Bestie. Be careful. This one is genuinely unhinged ๐Ÿ’€
  • --set-hlsl-vertex-input-semantic <location> <semantic> โ€” emits a specific vertex input semantic for a given location. Otherwise, TEXCOORD# is used as semantics, where # is location. Custom naming rights, iconic ๐ŸŽ€
  • --hlsl-enable-16bit-types โ€” enables native use of half/int16_t/uint16_t and ByteAddressBuffer interaction with these types. Requires SM 6.2. Gatekeeping, but respectfully โœจ
  • --hlsl-flatten-matrix-vertex-input-semantics โ€” emits matrix vertex inputs with input semantics as if they were independent vectors, e.g. TEXCOORD{2,3,4} rather than matrix form TEXCOORD2_{0,1,2}. Un-matrix-ify the whole situation ๐ŸŒˆ

๐Ÿซฃ Obscure options ๐Ÿซฃ

These options are not meant to be used on a regular basis. They have some occasional uses in the test suite. So like, not your everyday thing. You've been warned, bestie ๐Ÿ™ˆ

  • --force-temporary โ€” aggressively emit temporary expressions instead of forwarding expressions. Very rarely used and under-tested. Under-tested fr fr, tread lightly ๐Ÿ’€
  • --revision โ€” prints build timestamp and Git commit information (updated when cmake is configured). Receipts, literally ๐Ÿงพ
  • --iterations iter โ€” recompiles the same shader over and over, benchmarking related. Over and over and over, it's giving treadmill energy ๐Ÿƒโ€โ™€๏ธ
  • --disable-storage-image-qualifier-deduction โ€” if storage images are received without any nonwritable or nonreadable information, do not attempt to analyze usage, and always emit read/write state. No detective work today, we assume the most permissive โœจ
  • --flatten-multidimensional-arrays โ€” do not support multi-dimensional arrays and flatten them to one dimension. One dimension only, we keep it simple ๐ŸŽ€
  • --cpp-interface-name <name> โ€” emit a specific class name in C++ codegen. Name it, own it ๐Ÿ’…

and that's the whole page, bestie, we made it to the end ๐Ÿฅน

This gorgeous little manual is for spirv-cross, and it was dated June 2021 โ€” the page identifies itself as spirv-cross(1), so that's the source/version-and-date energy right there. Go forth and cross some SPIR-V, you absolute icon ๐Ÿ‘‘๐Ÿ’–