From 5ff6e8d522e6b42a27d5a6ccc1dab94bd8b58bce Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 27 Sep 2024 11:18:54 -0500 Subject: [PATCH] GPU: Add enable_depth_clip to RasterizerState (#10964) --- include/SDL3/SDL_gpu.h | 7 ++++++- src/gpu/d3d11/SDL_gpu_d3d11.c | 2 +- src/gpu/d3d12/SDL_gpu_d3d12.c | 2 +- src/gpu/metal/SDL_gpu_metal.m | 11 +++++++++++ src/gpu/vulkan/SDL_gpu_vulkan.c | 4 +++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h index 6c5d214129..f3cf36b27a 100644 --- a/include/SDL3/SDL_gpu.h +++ b/include/SDL3/SDL_gpu.h @@ -1355,6 +1355,11 @@ typedef struct SDL_GPUTransferBufferCreateInfo * A structure specifying the parameters of the graphics pipeline rasterizer * state. * + * NOTE: Some backend APIs (D3D11/12) will enable depth clamping even if + * enable_depth_clip is true. If you rely on this clamp+clip behavior, + * consider enabling depth clip and then manually clamping depth in your + * fragment shaders on Metal and Vulkan. + * * \since This struct is available since SDL 3.0.0 * * \sa SDL_GPUGraphicsPipelineCreateInfo @@ -1368,9 +1373,9 @@ typedef struct SDL_GPURasterizerState float depth_bias_clamp; /**< The maximum depth bias of a fragment. */ float depth_bias_slope_factor; /**< A scalar factor applied to a fragment's slope in depth calculations. */ bool enable_depth_bias; /**< true to bias fragment depth values. */ + bool enable_depth_clip; /**< true to enable depth clip, false to enable depth clamp. */ Uint8 padding1; Uint8 padding2; - Uint8 padding3; } SDL_GPURasterizerState; /** diff --git a/src/gpu/d3d11/SDL_gpu_d3d11.c b/src/gpu/d3d11/SDL_gpu_d3d11.c index 5a5210112c..073b2ed28f 100644 --- a/src/gpu/d3d11/SDL_gpu_d3d11.c +++ b/src/gpu/d3d11/SDL_gpu_d3d11.c @@ -1356,7 +1356,7 @@ static ID3D11RasterizerState *D3D11_INTERNAL_FetchRasterizerState( rasterizerDesc.CullMode = SDLToD3D11_CullMode[rasterizerState.cull_mode]; rasterizerDesc.DepthBias = SDL_lroundf(rasterizerState.depth_bias_constant_factor); rasterizerDesc.DepthBiasClamp = rasterizerState.depth_bias_clamp; - rasterizerDesc.DepthClipEnable = TRUE; + rasterizerDesc.DepthClipEnable = rasterizerState.enable_depth_clip; rasterizerDesc.FillMode = (rasterizerState.fill_mode == SDL_GPU_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME; rasterizerDesc.FrontCounterClockwise = (rasterizerState.front_face == SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE); rasterizerDesc.MultisampleEnable = TRUE; // only applies to MSAA render targets diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index c2ef63408e..ed1238b553 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -2447,7 +2447,7 @@ static bool D3D12_INTERNAL_ConvertRasterizerState(SDL_GPURasterizerState rasteri desc->SlopeScaledDepthBias = 0.0f; } - desc->DepthClipEnable = TRUE; + desc->DepthClipEnable = rasterizerState.enable_depth_clip; desc->MultisampleEnable = FALSE; desc->AntialiasedLineEnable = FALSE; desc->ForcedSampleCount = 0; diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m index 55ab5c8ba2..f78648b442 100644 --- a/src/gpu/metal/SDL_gpu_metal.m +++ b/src/gpu/metal/SDL_gpu_metal.m @@ -368,6 +368,16 @@ static MTLColorWriteMask SDLToMetal_ColorWriteMask( return result; } +static MTLDepthClipMode SDLToMetal_DepthClipMode( + bool enableDepthClip +) { + if (enableDepthClip) { + return MTLDepthClipModeClip; + } else { + return MTLDepthClipModeClamp; + } +} + // Structs typedef struct MetalTexture @@ -2311,6 +2321,7 @@ static void METAL_BindGraphicsPipeline( [metalCommandBuffer->renderEncoder setTriangleFillMode:SDLToMetal_PolygonMode[metalGraphicsPipeline->rasterizerState.fill_mode]]; [metalCommandBuffer->renderEncoder setCullMode:SDLToMetal_CullMode[metalGraphicsPipeline->rasterizerState.cull_mode]]; [metalCommandBuffer->renderEncoder setFrontFacingWinding:SDLToMetal_FrontFace[metalGraphicsPipeline->rasterizerState.front_face]]; + [metalCommandBuffer->renderEncoder setDepthClipMode:SDLToMetal_DepthClipMode(metalGraphicsPipeline->rasterizerState.enable_depth_clip)]; [metalCommandBuffer->renderEncoder setDepthBias:((rast->enable_depth_bias) ? rast->depth_bias_constant_factor : 0) slopeScale:((rast->enable_depth_bias) ? rast->depth_bias_slope_factor : 0) diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 2811904eac..5a8c8d64a1 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -6175,7 +6175,7 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline( rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizationStateCreateInfo.pNext = NULL; rasterizationStateCreateInfo.flags = 0; - rasterizationStateCreateInfo.depthClampEnable = VK_FALSE; + rasterizationStateCreateInfo.depthClampEnable = !createinfo->rasterizer_state.enable_depth_clip; rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE; rasterizationStateCreateInfo.polygonMode = SDLToVK_PolygonMode( renderer, @@ -11030,6 +11030,8 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice( desiredDeviceFeatures.independentBlend = VK_TRUE; desiredDeviceFeatures.samplerAnisotropy = VK_TRUE; desiredDeviceFeatures.imageCubeArray = VK_TRUE; + desiredDeviceFeatures.depthClamp = VK_TRUE; + desiredDeviceFeatures.shaderClipDistance = VK_TRUE; if (haveDeviceFeatures.fillModeNonSolid) { desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;