I'm writing a game with SDL_gpu and noticed MSAA was disabled on my Windows laptop under D3D12.
I pick a sample count by checking all my attachment formats support it:
SDL_GPUSampleCount msaa_counts[] = {SDL_GPU_SAMPLECOUNT_4, SDL_GPU_SAMPLECOUNT_2};
SDL_GPUTextureFormat msaa_formats[] = {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, SDL_GPU_TEXTUREFORMAT_R16_FLOAT, depth_stencil_format};
for (SDL_GPUSampleCount *c = msaa_counts; c < msaa_counts + SDL_arraysize(msaa_counts); c++) {
bool supported = true;
for (SDL_GPUTextureFormat *f = msaa_formats; f < msaa_formats + SDL_arraysize(msaa_formats); f++) supported &= SDL_GPUTextureSupportsSampleCount(device, *f, *c);
if (supported) { msaa_sample_count = *c; msaa_enabled = true; break; }
}
Both colour formats come back true. D24_UNORM_S8_UINT comes back false at 2x, 4x and 8x.
What I think is happening
SDL_gpu_d3d12.c has two format tables, and for depth they hold different things:
line 338 DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM_S8_UINT (SDLToD3D12_TextureFormat)
line 447 DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT (SDLToD3D12_DepthFormat)
The depth one is what actually ends up in the pipeline at line 3231 (psoDesc.DSVFormat). But both feature checks use the other table:
line 8250 DXGI_FORMAT dxgiFormat = SDLToD3D12_TextureFormat[format]; (D3D12_SupportsTextureFormat)
line 8334 featureData.Format = SDLToD3D12_TextureFormat[format]; (D3D12_SupportsSampleCount)
So it ends up asking the driver about R24_UNORM_X8_TYPELESS rather than D24_UNORM_S8_UINT.
D3D12_SupportsTextureFormat also takes a usage argument and doesn't look at it when picking the format, so a DEPTH_STENCIL_TARGET query has the same issue.
Vulkan and Metal don't seem affected. They use one format for both, so it doesn't occur.
I tried it
I patched both lines locally to use the depth table for depth formats and rebuilt SDL.
It correctly enabled MSAA at 4x for D3D12.
The image is the same apart from the MSAA — I dumped the same frame as raw RGBA8 and got 27 differing bytes, by a delta of 1 RGB value.
Machine
Intel Iris Xe (device 0x46A6), driver 32.0.101.7077, Windows 11
My depth texture is DEPTH_STENCIL_TARGET usage only, I never sample it.
Notes
Might date back to #12701, which moved depth textures to typeless resources with separate views but didn't change these two queries.
Disclaimer: I used Claude to help diagnose this.
I'm writing a game with SDL_gpu and noticed MSAA was disabled on my Windows laptop under D3D12.
I pick a sample count by checking all my attachment formats support it:
Both colour formats come back true.
D24_UNORM_S8_UINTcomes back false at 2x, 4x and 8x.What I think is happening
SDL_gpu_d3d12.chas two format tables, and for depth they hold different things:The depth one is what actually ends up in the pipeline at line 3231 (
psoDesc.DSVFormat). But both feature checks use the other table:So it ends up asking the driver about
R24_UNORM_X8_TYPELESSrather thanD24_UNORM_S8_UINT.D3D12_SupportsTextureFormatalso takes ausageargument and doesn't look at it when picking the format, so aDEPTH_STENCIL_TARGETquery has the same issue.Vulkan and Metal don't seem affected. They use one format for both, so it doesn't occur.
I tried it
I patched both lines locally to use the depth table for depth formats and rebuilt SDL.
It correctly enabled MSAA at 4x for D3D12.
The image is the same apart from the MSAA — I dumped the same frame as raw RGBA8 and got 27 differing bytes, by a delta of 1 RGB value.
Machine
Intel Iris Xe (device 0x46A6), driver 32.0.101.7077, Windows 11
My depth texture is
DEPTH_STENCIL_TARGETusage only, I never sample it.Notes
Might date back to #12701, which moved depth textures to typeless resources with separate views but didn't change these two queries.
Disclaimer: I used Claude to help diagnose this.