compute PSOs fail with E_INVALIDARG on AMD GCN (wave64-only) GPUs

Hi everyone! We’ve encountered a crash in UE 5.7.4. The issue appears to be related to Wave Ops used in the Hair Interpolation PSO. The crash occurs on older AMD GPUs.

We tried disabling Wave Ops entirely for Hair Interpolation, but it didn’t help.

Has anyone encountered a similar issue? How did you solve it?

[Attachment Removed]

Hi,

This crash is likely a regression in 5.7, not a problem with your groom assets. The failing shader is a wave-ops permutation of FHairInterpolationCS. The permutation that fails decodes to PointPerCurve=32 with WaveOps enabled, and those permutations emit WAVESIZE(32) in HairStrandsInterpolation.usf, which becomes a [WaveSize(32)] attribute in the compiled DXIL.

In 5.5 and 5.6, AddHairStrandsInterpolationPass picked the wave-ops permutation only after checking the actual device wave size at runtime:

const bool bWaveOps = GRHISupportsWaveOperations && GRHIMinimumWaveSize <= 32 && GRHIMaximumWaveSize >= 32 && FHairInterpolationCS::DoesSupportsWaveOps(InPlatform, DispatchInfo.PointPerCurve) != ERHIFeatureSupport::Unsupported;

In 5.7, those runtime terms were dropped, leaving only DoesSupportsWaveOps, which checks FDataDrivenShaderPlatformInfo. For Windows SM6, which reports MinimumWaveSize=4 and MaximumWaveSize=128, those are the union of all possible D3D12 devices, rather than the one you are running on. The check is therefore always true on PC, and the wave32 permutation gets selected on every AMD GPU, including the wave64-only ones. This is fixed in 5.8 with the following CLs:

CL 51782802 - “Ensure FHairInterpolationCS’s wave ops path is only picked at runtime if WaveSize 32 is supported”, is the actual fix.

CL 53630446 - “Stop precaching PSOs with wave ops if the GPU doesn’t support the wave size” is a follow-up worth taking at the same time. It gates ShouldPrecachePermutation on the same runtime check, so the PSO precaching system stops queueing pipelines that the device cannot create. Those precache failures are non-fatal, so this is not what is crashing you, but it removes a stream of pointless errors in the log on the same hardware.

One thing to note is that being disabled does not spare you here, which might be worth knowing for the future. The generated cards run the strands interpolation solve first and then FHairCardsDeformationCS on top of the deformed strand positions, so AddHairStrandsInterpolationPass still dispatches even with r.HairStrands.Strands off.

To confirm the hardware theory, can you get us the GPU model and driver version for one of the affected players, along with this line from their log:

LogD3D12RHI: Wave Operations are supported (wave size: min=%d max=%d).

We expect min=64 and max=64 on the machines that crash. Let me know if that helps.

[Attachment Removed]