stride3d/stride · error · ArgumentOutOfRangeException

BoundingVolumeBufferDownsampleLevel

Error message

BoundingVolumeBufferDownsampleLevel

What it means

LightShafts validates that the bounding-volume buffer downsample level is at least 1 before using it as a divisor for render target dimensions. A value of 0 (or negative) would produce a zero/negative buffer size or division by zero, so the renderer throws ArgumentOutOfRangeException in DrawCore.

Solutions

  1. Set BoundingVolumeBufferDownsampleLevel to 1 (full resolution) or higher
  2. Clamp the value with Math.Max(1, value) when configuring the component
  3. Check any serialized/UI code that can write 0 into this property

Example fix

// before
lightShafts.BoundingVolumeBufferDownsampleLevel = 0;
// after
lightShafts.BoundingVolumeBufferDownsampleLevel = Math.Max(1, requestedLevel);
Defensive patterns

Strategy: validation

Validate before calling

if (lightShafts.BoundingVolumeBufferDownsampleLevel < 1)
    throw new ArgumentException("BoundingVolumeBufferDownsampleLevel must be >= 1");

Prevention

When it happens

Trigger: Setting LightShaftsComponent.BoundingVolumeBufferDownsampleLevel to 0 or a negative value (e.g. defaulting it from a serialized 0 int field) and then rendering a frame with light shafts enabled.

Common situations: A newly added component whose downsample property was never initialized, or a user setting the level to 0 believing it means 'no downsampling' when 1 actually means full resolution.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/Images/LightShafts/LightShafts.cs:139

        {
            base.Destroy();
            minmaxVolumeEffectShader.Dispose();
        }

        public void Collect(RenderContext context)
        {
            lightShafts = context.VisibilityGroup.Tags.Get(CurrentLightShafts);
        }

        protected override void DrawCore(RenderDrawContext context)
        {
            if (lightShafts == null)
                return; // Not collected

            if (LightBufferDownsampleLevel < 1)
                throw new ArgumentOutOfRangeException(nameof(LightBufferDownsampleLevel));
            if (BoundingVolumeBufferDownsampleLevel < 1)
                throw new ArgumentOutOfRangeException(nameof(BoundingVolumeBufferDownsampleLevel));

            var depthInput = GetSafeInput(0);

            // Create a min/max buffer generated from scene bounding volumes
            var targetBoundingBoxBufferSize = new Size2(Math.Max(1, depthInput.Width / BoundingVolumeBufferDownsampleLevel), Math.Max(1, depthInput.Height / BoundingVolumeBufferDownsampleLevel));
            var boundingBoxBuffer = NewScopedRenderTarget2D(targetBoundingBoxBufferSize.Width, targetBoundingBoxBufferSize.Height, PixelFormat.R32G32_Float);

            // Buffer that holds the minimum distance in case of being inside the bounding box
            var backSideRaycastBuffer = NewScopedRenderTarget2D(1, 1, PixelFormat.R32G32_Float);

            // Create a single channel light buffer
            PixelFormat lightBufferPixelFormat = needsColorLightBuffer ? PixelFormat.R16G16B16A16_Float : PixelFormat.R16_Float;
            var targetLightBufferSize = new Size2(Math.Max(1, depthInput.Width / LightBufferDownsampleLevel), Math.Max(1, depthInput.Height / LightBufferDownsampleLevel));
            var lightBuffer = NewScopedRenderTarget2D(targetLightBufferSize.Width, targetLightBufferSize.Height, lightBufferPixelFormat);
            lightShaftsEffectShader.SetOutput(lightBuffer);
            var lightShaftsParameters = lightShaftsEffectShader.Parameters;
            lightShaftsParameters.Set(DepthBaseKeys.DepthStencil, depthInput); // Bind scene depth

View on GitHub (pinned to 96fad776d2)