stride3d/stride · error · NotSupportedException

Only texture cube are currently supported as input of…

Error message

Only texture cube are currently supported as input of 'LambertianPrefilteringSH' effect.

What it means

LambertianPrefilteringSH precomputes spherical-harmonics irradiance by running compute passes over the input; it only supports cubemap inputs. DrawCore throws NotSupportedException when the input texture's ViewDimension is not TextureCube.

Solutions

  1. Convert the environment to a cubemap texture before running LambertianPrefilteringSH.
  2. Verify ViewDimension == TextureDimension.TextureCube before drawing.
  3. Use a dedicated 2D irradiance/SH approximation if cubemap conversion is not possible.

Example fix

// before
shPrefilter.Draw(context, equirectTexture);
// after
var cube = ToCubemap(context, equirectTexture);
shPrefilter.Draw(context, cube);
Defensive patterns

Strategy: validation

Validate before calling

if (inputTexture?.ViewDimension != TextureDimension.TextureCube) throw new ArgumentException("LambertianPrefilteringSH requires a TextureCube input");

Type guard

bool IsCube(Texture t) => t?.ViewDimension == TextureDimension.TextureCube;

Try / catch

try { prefilter.Draw(context, inputTexture); } catch (NotSupportedException ex) { log.Error(ex, "SH prefiltering needs a cubemap input"); }

Prevention

When it happens

Trigger: Calling Draw with inputTexture bound to a 2D/panorama texture instead of a cubemap.

Common situations: Feeding an equirectangular environment map directly into SH prefiltering; migrating code that previously accepted 2D inputs.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/ComputeEffect/LambertianPrefiltering/LambertianPrefilteringSH.cs:71

            firstPassEffect = new ComputeEffectShader(context) { ShaderSourceName = "LambertianPrefilteringSHEffectPass1" };
            secondPassEffect = new ComputeEffectShader(context) { ShaderSourceName = "LambertianPrefilteringSHEffectPass2" };

            HarmonicOrder = 3;
        }

        protected override void DrawCore(RenderDrawContext context)
        {
            var inputTexture = RadianceMap;
            if (inputTexture == null)
                return;

            const int FirstPassBlockSize = 4;
            const int FirstPassSumsCount = FirstPassBlockSize * FirstPassBlockSize;

            var faceCount = inputTexture.ViewDimension == TextureDimension.TextureCube ? 6 : 1;
            if (faceCount == 1)
            {
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringSH' effect.");
            }
            var inputSize = new Int2(inputTexture.Width, inputTexture.Height); // (Note: for cube maps width = height)
            var coefficientsCount = harmonicalOrder * harmonicalOrder;

            var sumsToPerfomRemaining = inputSize.X * inputSize.Y * faceCount / FirstPassSumsCount;
            var partialSumBuffer = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);

            // Project the radiance on the SH basis and sum up the results along the 4x4 blocks
            firstPassEffect.ThreadNumbers = new Int3(FirstPassBlockSize, FirstPassBlockSize, 1);
            firstPassEffect.ThreadGroupCounts = new Int3(inputSize.X / FirstPassBlockSize, inputSize.Y / FirstPassBlockSize, faceCount);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, FirstPassBlockSize);
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.RadianceMap, inputTexture);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.OutputBuffer, partialSumBuffer);
            ((RendererBase)firstPassEffect).Draw(context);

            // Recursively applies the pass2 (sums the coefficients together) as long as needed. Swap input/output buffer at each iteration.
            var secondPassInputBuffer = partialSumBuffer;

View on GitHub (pinned to 96fad776d2)