CNA-BUG-094: SDL_GPU claims compute and SPIR-V shader intake on every device, including Direct3D 12 and Metal drivers that cannot take raw SPIR-V
Evidence basis: source-verified at the pinned commit; inferred from the source (the behaviour was not run); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
SupportsComputeShadersEXT() and SupportsShaderLanguageEXT(SpirV) answer true whenever a device exists, but compute pipelines and ShaderEffect SPIR-V payloads reach SDL_gpu as raw SPIR-V, which its Direct3D 12 and Metal drivers reject.
- Identifier
CNA-BUG-094- Category
- Bug
- Subsystem
- Graphics & renderers
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Inferred (strong): follows from the code, but the behaviour was not run
- Tests touching this area
- Yes: see Current tests
- Affected contract
- GraphicsDevice::SupportsCapability(GraphicsCapability::ComputeShaders), GraphicsDevice::SupportsShaderLanguageEXT and CNA::Graphics::ComputeShader on SDL_GPU
Expected behaviour
IGraphicsRenderer::SupportsComputeShadersEXT() answers "whether this renderer really implements compute", and SupportsShaderLanguageEXT is true "only when the implemented shader intake consumes that exact pair". GraphicsDevice::SupportsCapability(ComputeShaders) is derived from the former precisely so that compute is never claimed by default.
Actual behaviour at TARGET
SdlGpuRenderer::SupportsComputeShadersEXT() returns device_ != nullptr, and SdlGpuRenderer::SupportsShaderLanguageEXT accepts SpirV for vertex and fragment whenever a device exists (compute follows SupportsComputeShadersEXT). Stock shaders reach a non-SPIR-V driver through CreateSdlGpuShaderEXT, which chooses SDL_shadercross when the device does not accept SPIR-V. The other two intakes do not: SdlGpuComputeShaderRenderer::CompileProgram creates the compute pipeline with SDL_GPU_SHADERFORMAT_SPIRV, and the ShaderEffect SPIR-V route (SdlGpuEffectRenderer::CompileProgram to CreateShaderFromRemappedSpirvEXT) does the same. With CNA_SDL_GPU_SHADERCROSS=ON, the default on Windows and macOS, the device may be created on SDL_gpu's Direct3D 12 or Metal driver; there the capability is true and creation fails, so CNA::Graphics::ComputeShader throws ShaderCompilationExceptionEXT carrying SDL's error instead of the NotSupportedException a false capability would give, and a shader package that prefers its SPIR-V variant selects a payload the device cannot load.
Source locations
modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp— SdlGpuRenderer::SupportsComputeShadersEXT and SdlGpuRenderer::SupportsShaderLanguageEXTmodules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp— CreateSdlGpuShaderEXT and SelectSdlGpuShaderCreationRouteEXT (the stock-shader shadercross route)modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp— CreateShaderFromRemappedSpirvEXT and SdlGpuEffectRenderer::CompileProgram (raw SPIR-V ShaderEffect intake)modules/renderers/sdl-gpu/src/SdlGpuModern.cpp— SdlGpuComputeShaderRenderer::CompileProgram passes SDL_GPU_SHADERFORMAT_SPIRVcmake/RendererSelection.cmake— CNA_SDL_GPU_SHADERCROSS defaults ON on WIN32 and APPLE; D3D12 and Metal need translated shadersmodules/renderers/sdl-gpu/CMakeLists.txt— comment: D3D12 and Metal cannot consume ShaderEffect's raw SPIR-V pathmodules/graphics-ext/src/ComputeShader.cpp— ComputeShader::compile: capability check, then ShaderCompilationExceptionEXT on an invalid program
Evidence
Checked by reading at 009d40f5; not executed; no Direct3D 12 or Metal run exists for this entry. That SDL_gpu's Direct3D 12 and Metal drivers need translated shaders is CNA's own statement in cmake/RendererSelection.cmake, in modules/renderers/sdl-gpu/CMakeLists.txt and in the constructor's refusal when no driver accepts SPIR-V. On Linux SDL_gpu offers only its Vulkan driver, where both answers are correct and sdlgpu_smoke_test.cpp asserts them. Which driver SDL picks on a Windows host that has both Vulkan and Direct3D 12 was not established; on macOS the device is Metal. Engine-layer consumers mostly survive the claim: ClusteredLightCompute catches the failure and uses its CPU path, and the passes that also require CustomEffects are off because that capability is false on Windows and Apple builds.
Focused reproduction
// Illustrative; not compiled or run for this entry. SDL_GPU build with CNA_SDL_GPU_SHADERCROSS=ON,
// on macOS (SDL_gpu's Metal driver) or on Windows with SDL_GPU_DRIVER=direct3d12.
using namespace Microsoft::Xna::Framework::Graphics;
GraphicsDevice device;
bool claimed = device.SupportsCapability(CNA::GraphicsCapability::ComputeShaders); // true
CNA::Graphics::ComputeShader shader(device, spirvComputeSource);
// Expected with a truthful capability: NotSupportedException before any creation.
// Actual: ShaderCompilationExceptionEXT carrying "SDL_CreateGPUComputePipeline failed: ...".
Current tests
sdlgpu_smoke_test.cpp asserts that the device-level ComputeShaders and IndirectDraw answers equal the renderer's and are true, on Vulkan. SdlGpu_HeadlessGraphicsDevice and SdlGpu_BackbufferFormat are portable to a headless Direct3D 12 run through CNA's isolated Wine/vkd3d launcher, but neither creates a compute pipeline or a SPIR-V ShaderEffect. No test runs either intake on a non-SPIR-V driver.
Regression test
Make both answers depend on SDL_GetGPUShaderFormats(device_) including SDL_GPU_SHADERFORMAT_SPIRV (or route both intakes through SDL_shadercross), and extend the Direct3D 12 probe run to assert that SupportsCapability(ComputeShaders) equals whether a trivial compute pipeline can be created.
Blast radius
SDL_GPU on a Direct3D 12 or Metal driver only (a shadercross build, the default on Windows and macOS): CNAEXT ComputeShader, storage-buffer compute work and shader packages that select a SPIR-V variant. Vulkan-driver SDL_GPU (every Linux build) and stock drawing are unaffected.
Workaround
On Windows, select SDL_gpu's Vulkan driver (SDL_GPU_DRIVER=vulkan) where one is installed; on macOS, use another renderer for CNAEXT compute.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- SDL_gpu renderer internals: shaders
- Known issues
- Bug index