MSL: Support SPIR-V Fast Math execution modes and decorations.#2495
Conversation
d216ab8 to
1873a6d
Compare
1873a6d to
c261021
Compare
c261021 to
5f70d60
Compare
|
Marked as WIP for now. I'm going to add handling for individual |
5f70d60 to
f5e64ef
Compare
Decorations handled now. This is good to be reviewed again. |
| 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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
f5e64ef to
2f95577
Compare
|
|
||
| // 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; |
There was a problem hiding this comment.
Is there a scenario where a user wouldn’t want their fast math flags translated?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
2f95577 to
96c0932
Compare
- 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().
96c0932 to
beb9792
Compare
| // 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\""); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I'll look into cleaning that up.
CompilerMSL::Options::use_fast_math_pragmasto direct whether the MSL should include pragma directives to control floating point compilation options.CompilerMSL::get_fp_fast_math_flags()to return a set ofFPFastMathModeMaskflags that are safe to be applied to all floating-point types, based onFPFastMathDefaultandFPFastMathModedecorations on individual operations, or execution modesSignedZeroInfNanPreserveandContractionOff.SPIREntryPoint::fp_fast_math_defaultsto trackFPFastMathDefaultby type ID.Decoration::fp_fast_math_modeto supportDecorationFPFastMathMode.add_pragma_line()for all emitted pragmas, to better control line spacing.add_pragma_line().