stride3d/stride · error · NotSupportedException
Unsupported resource class
Error message
Unsupported resource class {binding.Class} What it means
Thrown by the descriptor-type mapping in VulkanFrameRenderer when an EffectParameterClass (resource kind from the shader bytecode) is not one of the handled classes (CBV, SRV, UAV, etc.). The switch translates HLSL-style binding classes into VkDescriptorType; any unrecognized class falls to the NotSupportedException arm.
Solutions
- Extend the switch to map the missing EffectParameterClass (e.g. Sampler => VkDescriptorType.Sampler) to its VkDescriptorType.
- Log binding.Class and binding.Type at the throw site to identify which resource kind is unmapped, then add the case.
- If the resource is irrelevant to the frame test, skip bindings with unmapped classes instead of throwing.
Example fix
// before
_ => throw new NotSupportedException($"Unsupported resource class {binding.Class}"),
// after
EffectParameterClass.Sampler => VkDescriptorType.CombinedImageSampler,
_ => throw new NotSupportedException($"Unsupported resource class {binding.Class}"), Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<EffectParameterClass> SupportedClasses = new()
{ EffectParameterClass.ConstantBuffer, EffectParameterClass.Texture, EffectParameterClass.UnorderedAccessView };
if (!SupportedClasses.Contains(binding.Class))
throw new InvalidOperationException($"Binding {binding.Name} uses unmapped class {binding.Class}"); Try / catch
try { renderer.RenderFrame(output); }
catch (NotSupportedException ex) when (ex.Message.StartsWith("Unsupported resource class"))
{
// log binding.Class, skip test or update the mapping table
} Prevention
- Keep the class-to-VkDescriptorType mapping in one table and add a unit test enumerating all EffectParameterClass values.
- Log unmapped classes with the shader name to speed up diagnosis.
- Restrict test shaders to resources the renderer explicitly supports.
When it happens
Trigger: A shader whose reflection metadata contains a resource class not covered by the switch (e.g. samplers, acceleraton structures, or an unhandled EffectParameterClass value) reaching SetupDescriptors during descriptor-set layout construction.
Common situations: Tests exercising shaders with sampler or texture arrays beyond the mapped subset; new shader effect kinds added upstream without updating this mapping; typos in effect parameter classification producing unexpected class values.
Related errors
- AHardwareBuffer import requires…
- argumentsBuffer
- Bound render targets
- failed
- Cannot copy data between Buffers and Textures.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/9d1d789529faff34.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Tests/FrameRenderer.Vulkan.cs:575
}
private static VkDescriptorType GetDescriptorType(EffectResourceBindingDescription binding) => binding.Class switch
{
EffectParameterClass.ConstantBuffer => VkDescriptorType.UniformBuffer,
EffectParameterClass.Sampler => VkDescriptorType.Sampler,
EffectParameterClass.ShaderResourceView => binding.Type switch
{
EffectParameterType.Buffer => VkDescriptorType.UniformTexelBuffer,
EffectParameterType.StructuredBuffer or EffectParameterType.ByteAddressBuffer => VkDescriptorType.StorageBuffer,
_ => VkDescriptorType.SampledImage,
},
EffectParameterClass.UnorderedAccessView => binding.Type switch
{
EffectParameterType.RWBuffer => VkDescriptorType.StorageTexelBuffer,
EffectParameterType.RWStructuredBuffer or EffectParameterType.RWByteAddressBuffer => VkDescriptorType.StorageBuffer,
_ => VkDescriptorType.StorageImage,
},
_ => throw new NotSupportedException($"Unsupported resource class {binding.Class}"),
};
public override void RenderFrame(Span<byte> result)
{
SetupDescriptors();
// Quad geometry, same as the D3D11 renderer
ReadOnlySpan<float> vertices =
[
1f, 1f, 0f, 1.0f, 1.0f,
1f, -1f, 0f, 1.0f, 0.0f,
-1f,-1f, 0f, 0.0f, 0.0f,
-1f, 1f, 1f, 0.0f, 1.0f,
];
ReadOnlySpan<uint> indices = [0, 1, 3, 1, 2, 3];
var (vertexBuffer, _) = CreateHostBuffer((ulong)(vertices.Length * sizeof(float)), VkBufferUsageFlags.VertexBuffer, MemoryMarshal.AsBytes(vertices));
var (indexBuffer, _) = CreateHostBuffer((ulong)(indices.Length * sizeof(uint)), VkBufferUsageFlags.IndexBuffer, MemoryMarshal.AsBytes(indices));
View on GitHub (pinned to 96fad776d2)