From 5ff6e8d522e6b42a27d5a6ccc1dab94bd8b58bce Mon Sep 17 00:00:00 2001
From: Caleb Cornett <[EMAIL REDACTED]>
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 6c5d214129f3a..f3cf36b27a025 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 5a5210112c3e0..073b2ed28fbb6 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 c2ef63408e1fd..ed1238b553f16 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 55ab5c8ba26e3..f78648b4421d3 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 2811904eac2ba..5a8c8d64a14cd 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;