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
- Read the diagnostics appended to the message; they usually name the SPIR-V instruction or feature that failed.
- Locate the dumped file in %TEMP% (stride-dxil-fail-<guid>.spv), run spirv-dis on it, and identify the unsupported construct.
- Fix the shader source: remove unsupported features (e.g. unusual matrix layouts, extensions) or rewrite the offending effect.
- Check for descriptor/register conflicts: resources must live in space 0 since the converter reserves space 31 for runtime data and push constants.
- Update Stride or the dxil-spirv native library — newer versions support more SPIR-V features and shader models.
- 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
- Avoid shader features known to be unsupported by dxil-spirv (uncommon extensions, exotic layouts).
- Keep all resources in register space 0; the converter reserves space 31 for runtime data and push constants.
- Pin the dxil-spirv native library and Stride versions; test shader content in CI on desktop D3D12.
- Keep the dumped .spv from the temp folder when reporting — it reproduces the failure exactly.
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
- Unsupported shader stage
- Can't OpLoad with cbuffer
- : Could not create spirv context
- : Could not parse spirv
- : could not create compiler
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)