stride3d/stride · critical · InvalidOperationException

spirv_to_dxil_pipeline failed; SPIR-V dumped to

Error message

spirv_to_dxil_pipeline failed; SPIR-V dumped to {dumpPath}
{diag}

What it means

Spv2DXIL.spirv_to_dxil_pipeline returned false: the dxil-spirv (Mesa SPIRV-to-DXIL) native converter failed to translate the SPIR-V module into DXIL for at least one stage of the pipeline. The compiler dumps the failing SPIR-V bytecode to a temp file and appends all diagnostics collected via the DXILSpirvLogger callback so the offending shader can be reproduced and analyzed.

Solutions

  1. Read the diagnostics appended to the message; they usually name the SPIR-V instruction or feature that failed.
  2. Locate the dumped file in %TEMP% (stride-dxil-fail-<guid>.spv), run spirv-dis on it, and identify the unsupported construct.
  3. Fix the shader source: remove unsupported features (e.g. unusual matrix layouts, extensions) or rewrite the offending effect.
  4. Check for descriptor/register conflicts: resources must live in space 0 since the converter reserves space 31 for runtime data and push constants.
  5. Update Stride or the dxil-spirv native library — newer versions support more SPIR-V features and shader models.
  6. If a shader genuinely needs SM >6.2 features, verify shader_model_max configuration is appropriate.

Example fix

// before: shader uses an extension dxil-spirv can't lower
[[vk::ext_extension("SPV_EXT_descriptor_indexing")]] ...

// after: rewrite using supported constructs (e.g. StructuredBuffer / standard bindings)
Defensive patterns

Strategy: try-catch

Try / catch

try { CompileDxilPipeline(spirv, entryPoints, bytecodes); }
catch (InvalidOperationException ex)
{
    // ex.Message contains the %TEMP% .spv dump path and dxil-spirv diagnostics
    log.Error(ex.Message);
    throw new EffectCompilationException("SPIR-V to DXIL conversion failed; see dumped .spv and diagnostics", ex);
}

Prevention

When it happens

Trigger: Calling the desktop effect compiler on a SPIR-V module that spirv_to_dxil_pipeline rejects: unsupported SPIR-V constructs/extensions, out-of-range descriptor bindings conflicting with the runtime CBV layout (runtime_data_cbv/push_constant_cbv in register space 31), 16-bit types exceeding the configured shader_model_max (SM 6.2), or validator 1.4 rejecting the produced DXIL.

Common situations: Shader feature (e.g. half/Float16 types, unsupported extensions, unusual cbuffer layouts) that dxil-spirv cannot lower; descriptor register/space collisions after custom cbuffer merging; a Stride/D3D12 backend bug on a specific shader; driver-independent since this happens at build/compile time on desktop.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/a1ef58ace37b7820. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/EffectCompiler.cs:627

                            {
                                ShaderStage.Vertex => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_VERTEX,
                                ShaderStage.Hull => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_TESS_CTRL,
                                ShaderStage.Domain => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_TESS_EVAL,
                                ShaderStage.Geometry => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_GEOMETRY,
                                ShaderStage.Pixel => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_FRAGMENT,
                                ShaderStage.Compute => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_COMPUTE,
                                _ => throw new NotSupportedException($"Unsupported shader stage: {entryPoints[i].Stage}"),
                            },
                            entry_point_name = (byte*)nameHandles[i].AddrOfPinnedObject(),
                        };
                    }

                    if (!Spv2DXIL.spirv_to_dxil_pipeline(stages, entryPoints.Count, ValidatorVersion.DXIL_VALIDATOR_1_4, ref runtimeConf, ref logger, outputs))
                    {
                        var dumpPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"stride-dxil-fail-{Guid.NewGuid():N}.spv");
                        System.IO.File.WriteAllBytes(dumpPath, spirvBytecode.ToArray());
                        var diag = _spvLogSink is { Length: > 0 } sb ? sb.ToString().TrimEnd() : "(no diagnostics from spirv_to_dxil)";
                        throw new InvalidOperationException($"spirv_to_dxil_pipeline failed; SPIR-V dumped to {dumpPath}\n{diag}");
                    }

                    for (int i = 0; i < entryPoints.Count; i++)
                    {
                        var dxil = outputs[i];
                        Span<byte> dxilSpan = new(dxil.buffer, (int)dxil.size);
                        fixed (byte* dxilSpanPtr = dxilSpan)
                            DxilHash.ComputeHashRetail(&dxilSpanPtr[20], (uint)(dxilSpan.Length - 20), &dxilSpanPtr[4]);
                        shaderStageBytecodes.Add(new ShaderBytecode(entryPoints[i].Stage, ObjectId.FromBytes(dxilSpan), dxilSpan.ToArray()));
                    }
                }
                finally
                {
                    for (int i = 0; i < entryPoints.Count; i++)
                        if (nameHandles[i].IsAllocated) nameHandles[i].Free();
                }
            }
        }

View on GitHub (pinned to 96fad776d2)