Browse Source

GPU: Add enable_depth_clip to RasterizerState (#10964)

Caleb Cornett 6 months ago
parent
commit
5ff6e8d522

+ 6 - 1
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;
 
 /**

+ 1 - 1
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

+ 1 - 1
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;

+ 11 - 0
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)

+ 3 - 1
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;