From 1a2ba3b94d247d790240d786213d45a71f49e98e Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+thatcosmonaut@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:12:41 -0700 Subject: [PATCH] GPU: Allow multisample textures to be read (#15838) --- include/SDL3/SDL_gpu.h | 18 ++++++++++++++++++ src/gpu/SDL_gpu.c | 31 ++++++++++++++++++++++++++----- src/gpu/d3d12/SDL_gpu_d3d12.c | 3 +++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h index bdc09c18a0..24f1e4b821 100644 --- a/include/SDL3/SDL_gpu.h +++ b/include/SDL3/SDL_gpu.h @@ -3736,6 +3736,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUIndexBuffer( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, etc.). Multisample textures are not allowed. + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUShader(). * @@ -3762,6 +3765,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, 2DMS, etc.) + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUShader(). * @@ -3809,6 +3815,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageBuffers( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, etc.). Multisample textures are not allowed. + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUShader(). * @@ -3835,6 +3844,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, 2DMS, etc.) + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUShader(). * @@ -4057,6 +4069,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputePipeline( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, etc.). Multisample textures are not allowed. + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUComputePipeline(). * @@ -4083,6 +4098,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ. * + * The textures being bound must have a matching type declared in the shader + * (2D, 3D, 2DMS, etc.) + * * Be sure your shader is set up according to the requirements documented in * SDL_CreateGPUComputePipeline(). * diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c index a63bbaf4a9..527c5c7c73 100644 --- a/src/gpu/SDL_gpu.c +++ b/src/gpu/SDL_gpu.c @@ -1287,11 +1287,8 @@ SDL_GPUTexture *SDL_CreateGPUTexture( failed = true; } if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && - (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER | - SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | - SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ | - SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE))) { - SDL_assert_release(!"For multisample textures: usage cannot contain SAMPLER or STORAGE flags"); + (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE)) { + SDL_assert_release(!"For multisample textures: usage cannot contain COMPUTE_STORAGE_WRITE flag"); failed = true; } if (IsDepthFormat(createinfo->format) && (createinfo->usage & ~(SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER))) { @@ -2102,6 +2099,14 @@ void SDL_BindGPUVertexSamplers( if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation) { CHECK_SAMPLER_TEXTURES + + for (Uint32 i = 0; i < num_bindings; i += 1) { + TextureCommonHeader *texture_header = (TextureCommonHeader *)texture_sampler_bindings[i].texture; + if (texture_header->info.sample_count > SDL_GPU_SAMPLECOUNT_1) + { + SDL_assert_release(!"Multisample textures cannot be bound as samplers!"); + } + } } for (Uint32 i = 0; i < num_bindings; i += 1) { @@ -2215,6 +2220,14 @@ void SDL_BindGPUFragmentSamplers( CHECK_SAMPLER_TEXTURES } + for (Uint32 i = 0; i < num_bindings; i += 1) { + TextureCommonHeader *texture_header = (TextureCommonHeader *)texture_sampler_bindings[i].texture; + if (texture_header->info.sample_count > SDL_GPU_SAMPLECOUNT_1) + { + SDL_assert_release(!"Multisample textures cannot be bound as samplers!"); + } + } + for (Uint32 i = 0; i < num_bindings; i += 1) { ((RenderPass *)render_pass)->fragment_sampler_bound[first_slot + i] = true; } @@ -2576,6 +2589,14 @@ void SDL_BindGPUComputeSamplers( if (COMPUTEPASS_DEVICE->debug_mode) { CHECK_COMPUTEPASS + for (Uint32 i = 0; i < num_bindings; i += 1) { + TextureCommonHeader *texture_header = (TextureCommonHeader *)texture_sampler_bindings[i].texture; + if (texture_header->info.sample_count > SDL_GPU_SAMPLECOUNT_1) + { + SDL_assert_release(!"Multisample textures cannot be bound as samplers!"); + } + } + for (Uint32 i = 0; i < num_bindings; i += 1) { ((ComputePass *)compute_pass)->sampler_bound[first_slot + i] = true; } diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index 2881e9ab59..19ebf09992 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -3535,6 +3535,9 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture( srvDesc.Texture3D.MipLevels = createinfo->num_levels; srvDesc.Texture3D.MostDetailedMip = 0; srvDesc.Texture3D.ResourceMinLODClamp = 0; // default behavior + } else if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2DMS.UnusedField_NothingToDefine = 0; } else { srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = createinfo->num_levels;