stride3d/stride · error · Exception

: could not create compiler

Error message

{cross.ContextCreateCompiler(context, backend, ir, CaptureMode.Copy, &compiler)} : could not create compiler

What it means

SpirvTranslator.GetEntryPoints throws this when the native spirv-cross call ContextCreateCompiler fails to instantiate a compiler object for the requested backend after successfully creating a context and parsing the SPIR-V. The exception message embeds the non-success Result code returned by the native library. It means the parsed IR could not be handed to a backend compiler (HLSL/GLSL/etc.).

Solutions

  1. Verify the Backend argument is a value supported by the bundled spirv-cross (Hlsl, Glsl, Msl) and matches how the SPIR-V was produced
  2. Check the error callback log lines emitted just before the throw — spirv-cross usually logs the concrete reason via ContextSetErrorCallback
  3. Validate the SPIR-V module with spirv-val to rule out corrupt/invalid IR
  4. Ensure the preloaded 'spirv-cross' native library matches the Silk.NET.SPIRV.Cross API version (NativeLibraryHelper.PreloadLibrary in the static constructor)
  5. Retry with the default Backend.Hlsl to isolate backend-specific failures

Example fix

// before
var entryPoints = translator.GetEntryPoints((Backend)42);
// after
if (!Enum.IsDefined(backend)) throw new ArgumentException($"Unsupported backend {backend}");
var entryPoints = translator.GetEntryPoints(backend);
Defensive patterns

Strategy: validation

Validate before calling

if (!Enum.IsDefined(typeof(Backend), backend)) throw new ArgumentOutOfRangeException(nameof(backend), $"Unsupported spirv-cross backend: {backend}");

Try / catch

try { var eps = translator.GetEntryPoints(backend); } catch (Exception ex) when (ex.Message.Contains("could not create compiler")) { Log.Error($"spirv-cross backend {backend} failed: {ex.Message}"); throw; }

Prevention

When it happens

Trigger: Calling GetEntryPoints(backend) when spirv-cross rejects ContextCreateCompiler: invalid/unsupported Backend enum value for the loaded spirv-cross build, corrupt or feature-inappropriate parsed IR, or the context/IR was in an invalid state (e.g. empty or zero-length Words parsed into a degenerate IR).

Common situations: Using a Backend value not compiled into the bundled spirv-cross native library; a mismatched spirv-cross native binary that rejects the capture mode or IR; passing SPIR-V whose parse produced a degenerate module; running on a platform where the preloaded spirv-cross native lib is an incompatible version.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/SpirvTranslator.cs:45

    {
        Context* context = null;
        ParsedIr* ir = null;
        Compiler* compiler = null;
        if (cross.ContextCreate(&context) != Result.Success)
            throw new Exception($"{cross.ContextCreate(&context)} : Could not create spirv context");
        fixed (uint* w = Words.Span)
            if (cross.ContextParseSpirv(context, w, (nuint)Words.Length, &ir) != Result.Success)
                throw new Exception($"{cross.ContextParseSpirv(context, w, (nuint)Words.Length, &ir)} : Could not parse spirv");

        cross.ContextSetErrorCallback(context, new((void* userData, byte* errorData) =>
        {
            var error = Marshal.PtrToStringAnsi((IntPtr)errorData);
            if (error != null)
                Log.Error(error);
        }), null);

        if (cross.ContextCreateCompiler(context, backend, ir, CaptureMode.Copy, &compiler) != Result.Success)
            throw new Exception($"{cross.ContextCreateCompiler(context, backend, ir, CaptureMode.Copy, &compiler)} : could not create compiler");

        var result = new List<(string RealName, string TranslatedName, ExecutionModel ExecutionModel)>();
        EntryPoint* entry_points = null;
        nuint num_entry_points = 0;
        cross.CompilerGetEntryPoints(compiler, &entry_points, &num_entry_points);
        for (int i = 0; i < (int)num_entry_points; ++i)
        {
            var entryPointModel = entry_points[i].ExecutionModel;
            var entryPointName = Marshal.PtrToStringAnsi((IntPtr)entry_points[i].Name)!;
            result.Add((entryPointName, "main", entryPointModel));
        }

        cross.ContextReleaseAllocations(context);
        cross.ContextDestroy(context);

        return result;
    }

View on GitHub (pinned to 96fad776d2)