stride3d/stride · error · NotSupportedException

ViewSlice.MipBand is not supported for render targets

Error message

ViewSlice.MipBand is not supported for render targets

What it means

Stride's Vulkan Texture.GetImageView creates a VkImageView for shader-resource/unordered-access views. When the caller requests a ViewType.MipBand (a contiguous range of mips) on a texture that is a render target, Stride throws NotSupportedException because Vulkan render-target views cannot express a mip band through this code path. It is an intentional guard against an unsupported combination of view type and binding usage.

Solutions

  1. Use ViewType.Full or ViewType.Single (SingleBand excluded) instead of ViewType.MipBand when the texture is a render target; create one single-mip view per level instead of a band.
  2. Create a separate non-render-target texture (shader-resource only) and copy the needed mip levels into it before viewing them as a MipBand.
  3. Use a Viewport/Scissor or shader-side mip selection to limit sampling to a mip range rather than a MipBand view.
  4. If mip-band views on RTs are essential, extend the Vulkan backend to create a non-attachment image view, accepting it cannot be used as a color attachment.

Example fix

// before
var view = texture.GetView(ViewType.MipBand, 0, 2);
// after
var view = texture.GetView(ViewType.Single, mipIndex: 2, arrayOrDepthSlice: 0); // one mip per view, loop for the band
Defensive patterns

Strategy: validation

Validate before calling

if (viewType == ViewType.MipBand && texture.IsRenderTarget)
    throw new InvalidOperationException("Use ViewType.Single per mip level for render-target textures on Vulkan");

Type guard

bool SupportsMipBandView(Texture t) => !t.IsRenderTarget || t.ViewType != ViewType.MipBand;

Try / catch

try
{
    var view = texture.GetView(ViewType.MipBand, 0, mipIndex);
}
catch (NotSupportedException)
{
    // fall back to per-mip single views
}

Prevention

When it happens

Trigger: Calling Texture.InitializeFromImpl which invokes GetImageView with viewType == ViewType.MipBand while the texture was created with GraphicsResourceUsage/flags marking it as a render target (IsRenderTarget == true). Typical trigger: requesting a texture view over a mip range on a render-target texture.

Common situations: Setting up mip-level-limited views for downsample chains, LOD streaming, or custom bloom pass that reuses a render-target texture with a MipBand view; migrating code from a backend that allowed mip-band RTVs (e.g. D3D11) to Vulkan.

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/a86f962dd2223f4f. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Vulkan/Texture.Vulkan.cs:510

                    || Usage == GraphicsResourceUsage.Default)
                && !IsRenderTarget && !IsDepthStencil)
                return;

            if (ParentTexture == null && GraphicsDevice != null)
            {
                GraphicsDevice.RegisterTextureMemoryUsage(-SizeInBytes);
            }

            InitializeFromImpl();
        }

        private unsafe VkImageView GetImageView(ViewType viewType, int arrayOrDepthSlice, int mipIndex)
        {
            if (!IsShaderResource && !IsUnorderedAccess)
                return VkImageView.Null;

            if (viewType == ViewType.MipBand && IsRenderTarget)
                throw new NotSupportedException("ViewSlice.MipBand is not supported for render targets");

            GetViewSliceBounds(viewType, ref arrayOrDepthSlice, ref mipIndex, out var arrayOrDepthCount, out var mipCount);

            var layerCount = Dimension == TextureDimension.Texture3D ? 1 : arrayOrDepthCount;

            // Narrow view usage to what it's actually bound as (drops ColorAttachment etc.) — avoids MoltenVK's layered-render check on iOS sim.
            var viewUsage = default(VkImageUsageFlags);
            if (IsShaderResource) viewUsage |= VkImageUsageFlags.Sampled;
            if (IsUnorderedAccess) viewUsage |= VkImageUsageFlags.Storage;
            var viewUsageInfo = new VkImageViewUsageCreateInfo
            {
                sType = VkStructureType.ImageViewUsageCreateInfo,
                usage = viewUsage,
            };
            var createInfo = new VkImageViewCreateInfo
            {
                sType = VkStructureType.ImageViewCreateInfo,
                pNext = &viewUsageInfo,

View on GitHub (pinned to 96fad776d2)