stride3d/stride · error · ArgumentException

The provided value should be a power of 2

Error message

The provided value should be a power of 2

What it means

RadiancePrefilteringGGX.SamplingsCount setter throws ArgumentException when the value is not a power of 2 (checked with MathUtil.IsPow2). The prefiltering shader distributes samples in power-of-2 strides, so any non-power-of-2 sample count is rejected even if <= 1024.

Solutions

  1. Round the value to the nearest power of 2 before assigning (e.g. MathUtil.NextPowerOfTwo).
  2. Use canonical values: 1, 2, 4, 8, ..., 512, 1024.
  3. Add a clamp/round helper at the config-loading boundary so invalid values never reach the setter.

Example fix

// before
prefilter.SamplingsCount = 300;
// after
prefilter.SamplingsCount = 256; // power of 2
// or generic: int v = MathUtil.NextPowerOfTwo(300); prefilter.SamplingsCount = Math.Min(v, 1024);
Defensive patterns

Strategy: validation

Validate before calling

int normalized = MathUtil.NextPowerOfTwo(Math.Max(1, Math.Min(value, 1024)));
prefilter.SamplingsCount = normalized;

Type guard

bool IsPow2(int v) => v > 0 && (v & (v - 1)) == 0;

Try / catch

try { prefilter.SamplingsCount = value; }
catch (ArgumentException ex) { Log.Warning("SamplingsCount must be a power of 2; rounding up"); prefilter.SamplingsCount = MathUtil.NextPowerOfTwo(value); }

Prevention

When it happens

Trigger: Assigning SamplingsCount = 100, 300, 500 or any value that fails MathUtil.IsPow2.

Common situations: Deriving sample count from UI sliders or user config with arbitrary values; computing counts from mip size arithmetic that doesn't yield a power of 2; porting settings from another IBL tool that allowed arbitrary counts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/ComputeEffect/GGXPrefiltering/RadiancePrefilteringGGX.cs:66

            computeShader = new ComputeEffectShader(context) { ShaderSourceName = "RadiancePrefilteringGGXEffect" };
            DoNotFilterHighestLevel = true;
            samplingsCount = 1024;
        }

        /// <summary>
        /// Gets or sets the number of sampling used during the importance sampling
        /// </summary>
        /// <remarks>Should be a power of 2 and maximum value is 1024</remarks>
        public int SamplingsCount
        {
            get { return samplingsCount; }
            set
            {
                if (value > 1024)
                    throw new ArgumentOutOfRangeException("value");

                if (!MathUtil.IsPow2(value))
                    throw new ArgumentException("The provided value should be a power of 2");

                samplingsCount = Math.Max(1, value);
            }
        }

        protected override void DrawCore(RenderDrawContext context)
        {
            var output = PrefilteredRadiance;
            if (output == null || (output.ViewDimension != TextureDimension.Texture2D && output.ViewDimension != TextureDimension.TextureCube) || output.ArraySize != 6)
                throw new NotSupportedException("Only array of 2D textures are currently supported as output");

            if (!output.IsUnorderedAccess || output.IsRenderTarget)
                throw new NotSupportedException("Only non-rendertarget unordered access textures are supported as output");

            var input = RadianceMap;
            if (input == null || input.Dimension != TextureDimension.TextureCube)
                throw new NotSupportedException("Only cubemaps are currently supported as input");

View on GitHub (pinned to 96fad776d2)