stride3d/stride · error · NotSupportedException

Only non-rendertarget unordered access textures are…

Error message

Only non-rendertarget unordered access textures are supported as output

What it means

RadiancePrefilteringGGX.DrawCore throws NotSupportedException when the PrefilteredRadiance texture is not bindable as an unordered access view (IsUnorderedAccess false) or is a render target (IsRenderTarget true). The prefilter runs a compute shader that writes directly into the output mips, which requires UAV binding; render-target textures are rejected.

Solutions

  1. Create the output texture with TextureFlags.UnorderedAccess and without RenderTarget.
  2. Recreate the texture: flags = TextureFlags.ShaderResource | TextureFlags.UnorderedAccess.
  3. Verify no code path enables RenderTarget on the prefiltered radiance texture.

Example fix

// before
var output = Texture.New2D(device, 256, 256, fmt, TextureFlags.RenderTarget | TextureFlags.ShaderResource);
// after
var output = Texture.New2D(device, 256, 256, fmt, TextureFlags.UnorderedAccess | TextureFlags.ShaderResource, arraySize: 6);
Defensive patterns

Strategy: validation

Validate before calling

if (!output.IsUnorderedAccess || output.IsRenderTarget)
    throw new InvalidOperationException("PrefilteredRadiance must be a non-rendertarget UAV texture");

Type guard

bool IsUsableUav(Texture t) => t != null && t.IsUnorderedAccess && !t.IsRenderTarget;

Try / catch

try { prefilter.Render(context); }
catch (NotSupportedException ex) { Log.Error("Prefilter output must be a UAV texture and not a render target.", ex); }

Prevention

When it happens

Trigger: Creating the output texture with only TextureFlags.ShaderResource (no UnorderedAccess), or with flags that make it a render target, then running the prefilter.

Common situations: Reusing a backbuffer/render-target texture as the prefiltered output; forgetting the UnorderedAccess flag when creating the target; graphics device/feature level that restricts simultaneous UAV use.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

            {
                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");

            var roughness = 0f;
            var faceCount = output.ArraySize;
            var levelSize = new Int2(output.Width, output.Height);
            var mipCount = MipmapGenerationCount == 0 ? output.MipLevelCount : MipmapGenerationCount;

            for (int l = 0; l < mipCount; l++)
            {
                if (l == 0 && DoNotFilterHighestLevel && input.Width >= output.Width)
                {
                    var inputLevel = MathUtil.Log2(input.Width / output.Width);
                    for (int f = 0; f < 6; f++)
                    {
                        var inputSubresource = inputLevel + f * input.MipLevelCount;

View on GitHub (pinned to 96fad776d2)