Skip to content

MSL: Support SPIR-V Fast Math execution modes and decorations.#2495

Merged
HansKristian-Work merged 2 commits into
KhronosGroup:mainfrom
billhollings:expose-FPFastMathDefault
Jun 23, 2025
Merged

MSL: Support SPIR-V Fast Math execution modes and decorations.#2495
HansKristian-Work merged 2 commits into
KhronosGroup:mainfrom
billhollings:expose-FPFastMathDefault

Conversation

@billhollings

@billhollings billhollings commented Jun 11, 2025

Copy link
Copy Markdown
Contributor
  • Add CompilerMSL::Options::use_fast_math_pragmas to direct whether the MSL should include pragma directives to control floating point compilation options.
  • Add CompilerMSL::get_fp_fast_math_flags() to return a set of FPFastMathModeMask flags that are safe to be applied to all floating-point types, based on FPFastMathDefault and FPFastMathMode decorations on individual operations, or execution modes SignedZeroInfNanPreserve and ContractionOff.
  • Add SPIREntryPoint::fp_fast_math_defaults to track FPFastMathDefault by type ID.
  • Add Decoration::fp_fast_math_mode to support DecorationFPFastMathMode.
  • Use add_pragma_line() for all emitted pragmas, to better control line spacing.
  • Update numerous shader references that were affected by a reordering in emitted pragma lines, due to the consistent use of add_pragma_line().

@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from d216ab8 to 1873a6d Compare June 11, 2025 23:46
Comment thread spirv_parser.cpp Outdated
@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from 1873a6d to c261021 Compare June 13, 2025 02:29
@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from c261021 to 5f70d60 Compare June 13, 2025 03:07
@billhollings billhollings changed the title Expose FPFastMathDefault to API execution mode query. WIP: Expose FPFastMathDefault to API execution mode query. Jun 13, 2025
@billhollings

Copy link
Copy Markdown
Contributor Author

Marked as WIP for now. I'm going to add handling for individual FPFastMathMode op decorations too.

@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from 5f70d60 to f5e64ef Compare June 14, 2025 18:40
@billhollings billhollings changed the title WIP: Expose FPFastMathDefault to API execution mode query. MSL: Expose FPFastMathDefault and FPFastMathMode decorations to API query. Jun 14, 2025
@billhollings

Copy link
Copy Markdown
Contributor Author

Marked as WIP for now. I'm going to add handling for individual FPFastMathMode op decorations too.

Decorations handled now. This is good to be reviewed again.

Comment thread spirv_msl.cpp Outdated
if(p_m.second.decoration.decoration_flags.get(DecorationFPFastMathMode))
accum_flags = and_if_not_zero(accum_flags, p_m.second.decoration.fp_fast_math_mode);

return accum_flags;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking over the SPV_KHR_float_controls2 spec. I'm a little confused about how this deals with a global disable of FP math.

If I understand it, the absence of a global FP math default means the module defaults to normal SPIR-V behavior which is fast-math on by default unless disabled with NoContract. However, if the default behavior is set to 0, I think fast-math is just globally disabled. That also sort of seems to reset the flag tracking.

Also, I'm a little confused why this is queried by MoltenVK. Should SPIRV-Cross not deal with this on its own?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand it, the absence of a global FP math default means the module defaults to normal SPIR-V behavior which is fast-math on by default unless disabled with NoContract. However, if the default behavior is set to 0, I think fast-math is just globally disabled. That also sort of seems to reset the flag tracking.

You are correct. Generally, SPIR-V normally defaults to FastMath, except for spv:: ExecutionModeSignedZeroInfNanPreserve and spv::ExecutionModeContractionOff.

However, SPV_KHR_float_controls2 turns that on its head, and explicitly disables Fast Math, except where enabled via FPFastMathDefault and FPFastMathMode decorations.

The reason MoltenVK is querying this is that Metal has MTLCompileOptions which is used by the Metal compiler, and which has mathMode and mathFloatingPointFunctions properties. Those properties offer similar functionality to what is provided by FPFastMathDefault. Not a perfect match, but it is what it is.

MoltenVK sets these MSL compiler options based on this query, plus the results of querying SPIR-V spv:: ExecutionModeSignedZeroInfNanPreserve and spv::ExecutionModeContractionOff. See here and here for the logic deets of that.

Also, I'm a little confused why this is queried by MoltenVK. Should SPIRV-Cross not deal with this on its own?

Given support in MSL for this, SPRIV-Cross could deal with this by emitting MSL compile pragmas everywhere, but as I mention here, I wasn't prepared to go that far just now.

For now therefore, this PR is just a simple query of the state of SPIR-V fast-path math flags. MoltenVK takes care of the rest of the logic about how to apply it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing to note actually on the last point: assuming I’m reading the spec correctly, you may just be able to use a pragma in the file scope to set the fast math mode for the whole shader, instead of passing through to MoltenVK to set compiler options.

@HansKristian-Work HansKristian-Work Jun 20, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, SPV_KHR_float_controls2 turns that on its head, and explicitly disables Fast Math

It doesn't seem that simple, since this default only applies if you actually set any default mode. I guess to globally disable, you set the FP mode to 0 for e.g. Float32 once.

Otherwise, if the current entry point sets any FPFastMathDefault execution mode then all flags specified for any operand type or for the result type of the operation apply

My main concern here is that it doesn't seem like the code takes this into account, unless I'm missing something.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HansKristian-Work

However, SPV_KHR_float_controls2 turns that on its head, and explicitly disables Fast Math

It doesn't seem that simple, since this default only applies if you actually set any default mode. I guess to globally disable, you set the FP mode to 0 for e.g. Float32 once.

Otherwise, if the current entry point sets any FPFastMathDefault execution mode then all flags specified for any operand type or for the result type of the operation apply

My main concern here is that it doesn't seem like the code takes this into account, unless I'm missing something.

The logic was working, as interpreted in MoltenVK, which was doing the heavy-lifting of combining the various FP flags. But I appreciate that combining both FP Fast Math modes, and then "classic" execution modes makes it easier to interpret, and keeps it self-contained in SPIRV-Cross.

get_fp_fast_math_flags() now combines everything into one set of FP flags, and starts with full Fast Math as the default, then reducing based on FP and execution modes.

@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from f5e64ef to 2f95577 Compare June 22, 2025 20:19
@billhollings billhollings changed the title MSL: Expose FPFastMathDefault and FPFastMathMode decorations to API query. MSL: Support SPIR-V Fast Math execution modes and decorations. Jun 22, 2025
Comment thread spirv_msl.hpp

// Use Fast Math pragmas in MSL code, based on SPIR-V float controls and FP ExecutionModes.
// Requires MSL 3.2 or above, and has no effect with earlier MSL versions.
bool use_fast_math_pragmas = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a scenario where a user wouldn’t want their fast math flags translated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a scenario where a user wouldn’t want their fast math flags translated?

Actually, yes, it turns out.

I could not find any way to actually enable the pragmas over the settings of MTLCompileOptions, which always overrode the pragmas, even when the MTLCompileOptions properties were not explicitly set. That seems bizarre, as one would expect some kind of hierarchy where the pragmas would temporarily override MTLCompileOptions, but I couldn't get it to work. maybe it's a short-term bug with the MSL compiler,

Because of this, MoltenVK will leave use_fast_math_pragmas disabled, and stick with manipulating MTLCompileOptions.

Even though MoltenVK isn't able to use this feature, I've left it in here in case there are other compile scenarios (like offline maybe) where this is operational, or in case whatever is blocking its use in MoltenVK is fixed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, makes sense. Maybe MoltenVK could just skip compiler flags when MSL 3.2 is supported, but I suppose it makes sense to leave this option.

@billhollings billhollings Jun 22, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, makes sense. Maybe MoltenVK could just skip compiler flags when MSL 3.2 is supported, but I suppose it makes sense to leave this option.

I don't think so. I tried that, but even leaving MTLCompileOptions unmodified still used the default values in MTLCompileOptions over the pragmas.

@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from 2f95577 to 96c0932 Compare June 22, 2025 20:56
- Add CompilerMSL::Options::use_fast_math_pragmas to direct whether the MSL
  should include pragma directives to control floating point compilation options.
- Add CompilerMSL::get_fp_fast_math_flags() to return a set of FPFastMathModeMask
  flags that are safe to be applied to all floating-point types, based on
  FPFastMathDefault and FPFastMathMode decorations on individual operations,
  or execution modes SignedZeroInfNanPreserve and ContractionOff.
- Add SPIREntryPoint::fp_fast_math_defaults to track FPFastMathDefault by type ID.
- Add Decoration::fp_fast_math_mode to support DecorationFPFastMathMode.
- Use add_pragma_line() for all emitted pragmas, to better control line spacing.
- Update numerous shader references that were affected by a reordering
  in emitted pragma lines, due to the consistent use of add_pragma_line().
@billhollings billhollings force-pushed the expose-FPFastMathDefault branch from 96c0932 to beb9792 Compare June 22, 2025 21:05
Comment thread spirv_msl.cpp Outdated
Comment thread spirv_msl.cpp
// This particular line can be overridden during compilation, so make it a flag and not a pragma line.
if (suppress_missing_prototypes)
statement("#pragma clang diagnostic ignored \"-Wmissing-prototypes\"");
add_pragma_line("#pragma clang diagnostic ignored \"-Wmissing-prototypes\"");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using add_pragma_line is somewhat questionable here. This will force a recompile, even before we have committed to emitting the header. This is wasteful, and I think this needs to fix add_pragma_line so that it doesn't force a recompile unless it's called after the header is committed. I think all uses of add_pragma happen before we emit the header, so maybe that path can simply be dropped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into cleaning that up.

@HansKristian-Work HansKristian-Work merged commit 94cc87b into KhronosGroup:main Jun 23, 2025
3 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants