Remove depth-clamping and add depth-clip-control feature

Fixed: dawn:1178
Change-Id: I251a7e05fec9ecef44300d4f948b2d0611888109
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96320
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/dawn.json b/dawn.json
index 23d4c4a..29632dd 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1365,7 +1365,6 @@
             {"value": 6, "name": "texture compression ETC2"},
             {"value": 7, "name": "texture compression ASTC"},
             {"value": 8, "name": "indirect first instance"},
-            {"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]},
             {"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]},
             {"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]},
             {"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]},
@@ -2150,16 +2149,6 @@
         ]
     },
 
-    "primitive depth clamping state": {
-        "category": "structure",
-        "chained": "in",
-        "chain roots": ["primitive state"],
-        "tags": ["dawn", "emscripten"],
-        "members": [
-            {"name": "clamp depth", "type": "bool", "default": "false"}
-        ]
-    },
-
     "primitive depth clip control": {
         "category": "structure",
         "chained": "in",
@@ -2512,7 +2501,6 @@
             {"value": 14, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
             {"value": 15, "name": "render pass descriptor max draw count"},
             {"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
-            {"value": 1001, "name": "primitive depth clamping state", "tags": ["dawn", "emscripten"]},
             {"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]},
             {"value": 1003, "name": "dawn encoder internal usage descriptor", "tags": ["dawn"]},
             {"value": 1004, "name": "dawn instance descriptor", "tags": ["dawn", "native"]},
diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp
index 16b845d..e43da12 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -58,9 +58,6 @@
     {Feature::DepthClipControl,
      {"depth-clip-control", "Disable depth clipping of primitives to the clip volume",
       "https://bugs.chromium.org/p/dawn/issues/detail?id=1178"}},
-    {Feature::DepthClamping,
-     {"depth-clamping", "Clamp depth to [0, 1] in NDC space instead of clipping",
-      "https://bugs.chromium.org/p/dawn/issues/detail?id=716"}},
     {Feature::Depth32FloatStencil8,
      {"depth32float-stencil8", "Support depth32float-stencil8 texture format",
       "https://bugs.chromium.org/p/dawn/issues/detail?id=690"}},
@@ -102,8 +99,6 @@
             return Feature::TextureCompressionASTC;
         case wgpu::FeatureName::DepthClipControl:
             return Feature::DepthClipControl;
-        case wgpu::FeatureName::DepthClamping:
-            return Feature::DepthClamping;
         case wgpu::FeatureName::Depth32FloatStencil8:
             return Feature::Depth32FloatStencil8;
         case wgpu::FeatureName::IndirectFirstInstance:
@@ -136,8 +131,6 @@
             return wgpu::FeatureName::TimestampQuery;
         case Feature::DepthClipControl:
             return wgpu::FeatureName::DepthClipControl;
-        case Feature::DepthClamping:
-            return wgpu::FeatureName::DepthClamping;
         case Feature::Depth32FloatStencil8:
             return wgpu::FeatureName::Depth32FloatStencil8;
         case Feature::IndirectFirstInstance:
diff --git a/src/dawn/native/Features.h b/src/dawn/native/Features.h
index e3913f1..f97fd9d 100644
--- a/src/dawn/native/Features.h
+++ b/src/dawn/native/Features.h
@@ -34,7 +34,6 @@
     PipelineStatisticsQuery,
     TimestampQuery,
     DepthClipControl,
-    DepthClamping,
     Depth32FloatStencil8,
     ChromiumExperimentalDp4a,
     IndirectFirstInstance,
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index 1df3c4c..256cb62 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -153,12 +153,7 @@
 }
 
 MaybeError ValidatePrimitiveState(const DeviceBase* device, const PrimitiveState* descriptor) {
-    DAWN_TRY(ValidateSingleSType(descriptor->nextInChain, wgpu::SType::PrimitiveDepthClampingState,
-                                 wgpu::SType::PrimitiveDepthClipControl));
-    const PrimitiveDepthClampingState* clampInfo = nullptr;
-    FindInChain(descriptor->nextInChain, &clampInfo);
-    DAWN_INVALID_IF(clampInfo && !device->IsFeatureEnabled(Feature::DepthClamping),
-                    "%s is not supported", wgpu::FeatureName::DepthClamping);
+    DAWN_TRY(ValidateSingleSType(descriptor->nextInChain, wgpu::SType::PrimitiveDepthClipControl));
     const PrimitiveDepthClipControl* depthClipControl = nullptr;
     FindInChain(descriptor->nextInChain, &depthClipControl);
     DAWN_INVALID_IF(depthClipControl && !device->IsFeatureEnabled(Feature::DepthClipControl),
@@ -564,11 +559,12 @@
     }
 
     mPrimitive = descriptor->primitive;
-    const PrimitiveDepthClampingState* clampInfo = nullptr;
-    FindInChain(mPrimitive.nextInChain, &clampInfo);
-    if (clampInfo) {
-        mClampDepth = clampInfo->clampDepth;
+    const PrimitiveDepthClipControl* depthClipControl = nullptr;
+    FindInChain(mPrimitive.nextInChain, &depthClipControl);
+    if (depthClipControl) {
+        mUnclippedDepth = depthClipControl->unclippedDepth;
     }
+
     mMultisample = descriptor->multisample;
 
     if (mAttachmentState->HasDepthStencilAttachment()) {
@@ -763,9 +759,9 @@
     return mDepthStencil.depthBiasClamp;
 }
 
-bool RenderPipelineBase::ShouldClampDepth() const {
+bool RenderPipelineBase::HasUnclippedDepth() const {
     ASSERT(!IsError());
-    return mClampDepth;
+    return mUnclippedDepth;
 }
 
 ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments>
@@ -872,7 +868,7 @@
 
     // Record primitive state
     recorder.Record(mPrimitive.topology, mPrimitive.stripIndexFormat, mPrimitive.frontFace,
-                    mPrimitive.cullMode, mClampDepth);
+                    mPrimitive.cullMode, mUnclippedDepth);
 
     // Record multisample state
     // Sample count hashed as part of the attachment state
@@ -989,7 +985,7 @@
         if (stateA.topology != stateB.topology ||
             stateA.stripIndexFormat != stateB.stripIndexFormat ||
             stateA.frontFace != stateB.frontFace || stateA.cullMode != stateB.cullMode ||
-            a->mClampDepth != b->mClampDepth) {
+            a->mUnclippedDepth != b->mUnclippedDepth) {
             return false;
         }
     }
diff --git a/src/dawn/native/RenderPipeline.h b/src/dawn/native/RenderPipeline.h
index f904f8a..afba4a7 100644
--- a/src/dawn/native/RenderPipeline.h
+++ b/src/dawn/native/RenderPipeline.h
@@ -90,7 +90,7 @@
     int32_t GetDepthBias() const;
     float GetDepthBiasSlopeScale() const;
     float GetDepthBiasClamp() const;
-    bool ShouldClampDepth() const;
+    bool HasUnclippedDepth() const;
 
     ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> GetColorAttachmentsMask() const;
     bool HasDepthStencilAttachment() const;
@@ -137,7 +137,7 @@
     PrimitiveState mPrimitive;
     DepthStencilState mDepthStencil;
     MultisampleState mMultisample;
-    bool mClampDepth = false;
+    bool mUnclippedDepth = false;
     bool mWritesDepth = false;
     bool mWritesStencil = false;
 };
diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
index 00fc77b..1ec8e02 100644
--- a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
+++ b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
@@ -389,7 +389,7 @@
     descriptorD3D12.RasterizerState.DepthBias = GetDepthBias();
     descriptorD3D12.RasterizerState.DepthBiasClamp = GetDepthBiasClamp();
     descriptorD3D12.RasterizerState.SlopeScaledDepthBias = GetDepthBiasSlopeScale();
-    descriptorD3D12.RasterizerState.DepthClipEnable = TRUE;
+    descriptorD3D12.RasterizerState.DepthClipEnable = !HasUnclippedDepth();
     descriptorD3D12.RasterizerState.MultisampleEnable = (GetSampleCount() > 1) ? TRUE : FALSE;
     descriptorD3D12.RasterizerState.AntialiasedLineEnable = FALSE;
     descriptorD3D12.RasterizerState.ForcedSampleCount = 0;
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index f9e7b53..ee480a6 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -371,7 +371,7 @@
         }
 
         if (@available(macOS 10.11, iOS 11.0, *)) {
-            mSupportedFeatures.EnableFeature(Feature::DepthClamping);
+            mSupportedFeatures.EnableFeature(Feature::DepthClipControl);
         }
 
         if (@available(macOS 10.11, iOS 9.0, *)) {
diff --git a/src/dawn/native/metal/CommandBufferMTL.mm b/src/dawn/native/metal/CommandBufferMTL.mm
index 04dab40..d32f058 100644
--- a/src/dawn/native/metal/CommandBufferMTL.mm
+++ b/src/dawn/native/metal/CommandBufferMTL.mm
@@ -1242,7 +1242,7 @@
                            slopeScale:newPipeline->GetDepthBiasSlopeScale()
                                 clamp:newPipeline->GetDepthBiasClamp()];
                 if (@available(macOS 10.11, iOS 11.0, *)) {
-                    MTLDepthClipMode clipMode = newPipeline->ShouldClampDepth()
+                    MTLDepthClipMode clipMode = newPipeline->HasUnclippedDepth()
                                                     ? MTLDepthClipModeClamp
                                                     : MTLDepthClipModeClip;
                     [encoder setDepthClipMode:clipMode];
diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp
index 5e399ae..9ccc4d6 100644
--- a/src/dawn/native/vulkan/AdapterVk.cpp
+++ b/src/dawn/native/vulkan/AdapterVk.cpp
@@ -147,10 +147,6 @@
         mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery);
     }
 
-    if (mDeviceInfo.features.depthClamp == VK_TRUE) {
-        mSupportedFeatures.EnableFeature(Feature::DepthClamping);
-    }
-
     if (mDeviceInfo.properties.limits.timestampComputeAndGraphics == VK_TRUE) {
         mSupportedFeatures.EnableFeature(Feature::TimestampQuery);
     }
@@ -171,6 +167,11 @@
         mSupportedFeatures.EnableFeature(Feature::ChromiumExperimentalDp4a);
     }
 
+    if (mDeviceInfo.HasExt(DeviceExt::DepthClipEnable) &&
+        mDeviceInfo.depthClipEnableFeatures.depthClipEnable == VK_TRUE) {
+        mSupportedFeatures.EnableFeature(Feature::DepthClipControl);
+    }
+
 #if defined(DAWN_USE_SYNC_FDS)
     // TODO(chromium:1258986): Precisely enable the feature by querying the device's format
     // features.
diff --git a/src/dawn/native/vulkan/CacheKeyVk.cpp b/src/dawn/native/vulkan/CacheKeyVk.cpp
index d89649e..3a82667 100644
--- a/src/dawn/native/vulkan/CacheKeyVk.cpp
+++ b/src/dawn/native/vulkan/CacheKeyVk.cpp
@@ -58,6 +58,13 @@
 }
 
 template <>
+void CacheKeySerializer<VkPipelineRasterizationDepthClipStateCreateInfoEXT>::Serialize(
+    CacheKey* key,
+    const VkPipelineRasterizationDepthClipStateCreateInfoEXT& t) {
+    key->Record(t.depthClipEnable, t.flags);
+}
+
+template <>
 void CacheKeySerializer<VkSpecializationMapEntry>::Serialize(CacheKey* key,
                                                              const VkSpecializationMapEntry& t) {
     key->Record(t.constantID, t.offset, t.size);
@@ -170,7 +177,7 @@
     key->Record(t.flags, t.depthClampEnable, t.rasterizerDiscardEnable, t.polygonMode, t.cullMode,
                 t.frontFace, t.depthBiasEnable, t.depthBiasConstantFactor, t.depthBiasClamp,
                 t.depthBiasSlopeFactor, t.lineWidth);
-    vulkan::SerializePnext<>(key, &t);
+    vulkan::SerializePnext<VkPipelineRasterizationDepthClipStateCreateInfoEXT>(key, &t);
 }
 
 template <>
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index 3605dc0..05f3a00 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -409,6 +409,16 @@
         usedKnobs.features.pipelineStatisticsQuery = VK_TRUE;
     }
 
+    if (IsFeatureEnabled(Feature::DepthClipControl)) {
+        const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
+        ASSERT(deviceInfo.HasExt(DeviceExt::DepthClipEnable) &&
+               deviceInfo.depthClipEnableFeatures.depthClipEnable == VK_TRUE);
+
+        usedKnobs.depthClipEnableFeatures.depthClipEnable = VK_TRUE;
+        featuresChain.Add(&usedKnobs.depthClipEnableFeatures,
+                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT);
+    }
+
     if (IsFeatureEnabled(Feature::ShaderFloat16)) {
         const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
         ASSERT(deviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
@@ -427,11 +437,6 @@
                           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES);
     }
 
-    if (IsFeatureEnabled(Feature::DepthClamping)) {
-        ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.depthClamp == VK_TRUE);
-        usedKnobs.features.depthClamp = VK_TRUE;
-    }
-
     // Find a universal queue family
     {
         // Note that GRAPHICS and COMPUTE imply TRANSFER so we don't need to check for it.
diff --git a/src/dawn/native/vulkan/RenderPipelineVk.cpp b/src/dawn/native/vulkan/RenderPipelineVk.cpp
index 8f30d58..39a24b7 100644
--- a/src/dawn/native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn/native/vulkan/RenderPipelineVk.cpp
@@ -430,7 +430,7 @@
     rasterization.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
     rasterization.pNext = nullptr;
     rasterization.flags = 0;
-    rasterization.depthClampEnable = ShouldClampDepth() ? VK_TRUE : VK_FALSE;
+    rasterization.depthClampEnable = VK_FALSE;
     rasterization.rasterizerDiscardEnable = VK_FALSE;
     rasterization.polygonMode = VK_POLYGON_MODE_FILL;
     rasterization.cullMode = VulkanCullMode(GetCullMode());
@@ -441,6 +441,18 @@
     rasterization.depthBiasSlopeFactor = GetDepthBiasSlopeScale();
     rasterization.lineWidth = 1.0f;
 
+    PNextChainBuilder rasterizationChain(&rasterization);
+    VkPipelineRasterizationDepthClipStateCreateInfoEXT depthClipState;
+    if (HasUnclippedDepth()) {
+        ASSERT(device->IsFeatureEnabled(Feature::DepthClipControl));
+        depthClipState.pNext = nullptr;
+        depthClipState.depthClipEnable = VK_FALSE;
+        depthClipState.flags = 0;
+        rasterizationChain.Add(
+            &depthClipState,
+            VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT);
+    }
+
     VkPipelineMultisampleStateCreateInfo multisample;
     multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
     multisample.pNext = nullptr;
diff --git a/src/dawn/native/vulkan/VulkanExtensions.cpp b/src/dawn/native/vulkan/VulkanExtensions.cpp
index 439e95d..aaf3e65 100644
--- a/src/dawn/native/vulkan/VulkanExtensions.cpp
+++ b/src/dawn/native/vulkan/VulkanExtensions.cpp
@@ -162,6 +162,7 @@
     {DeviceExt::ExternalSemaphoreFD, "VK_KHR_external_semaphore_fd", NeverPromoted},
     {DeviceExt::ExternalSemaphoreZirconHandle, "VK_FUCHSIA_external_semaphore", NeverPromoted},
 
+    {DeviceExt::DepthClipEnable, "VK_EXT_depth_clip_enable", NeverPromoted},
     {DeviceExt::ImageDrmFormatModifier, "VK_EXT_image_drm_format_modifier", NeverPromoted},
     {DeviceExt::Swapchain, "VK_KHR_swapchain", NeverPromoted},
     {DeviceExt::SubgroupSizeControl, "VK_EXT_subgroup_size_control", NeverPromoted},
@@ -283,6 +284,7 @@
                 hasDependencies = icdVersion >= VulkanVersion_1_1;
                 break;
 
+            case DeviceExt::DepthClipEnable:
             case DeviceExt::ShaderIntegerDotProduct:
             case DeviceExt::ZeroInitializeWorkgroupMemory:
                 hasDependencies = HasDep(DeviceExt::GetPhysicalDeviceProperties2);
diff --git a/src/dawn/native/vulkan/VulkanExtensions.h b/src/dawn/native/vulkan/VulkanExtensions.h
index 6912528..eb6ef49 100644
--- a/src/dawn/native/vulkan/VulkanExtensions.h
+++ b/src/dawn/native/vulkan/VulkanExtensions.h
@@ -103,6 +103,7 @@
     ExternalSemaphoreZirconHandle,
 
     // Others
+    DepthClipEnable,
     ImageDrmFormatModifier,
     Swapchain,
     SubgroupSizeControl,
diff --git a/src/dawn/native/vulkan/VulkanInfo.cpp b/src/dawn/native/vulkan/VulkanInfo.cpp
index 116fd72..d033e29 100644
--- a/src/dawn/native/vulkan/VulkanInfo.cpp
+++ b/src/dawn/native/vulkan/VulkanInfo.cpp
@@ -254,6 +254,11 @@
             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR);
     }
 
+    if (info.extensions[DeviceExt::DepthClipEnable]) {
+        featuresChain.Add(&info.depthClipEnableFeatures,
+                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT);
+    }
+
     // If we have DeviceExt::GetPhysicalDeviceProperties2, use features2 and properties2 so
     // that features no covered by VkPhysicalDevice{Features,Properties} can be queried.
     //
diff --git a/src/dawn/native/vulkan/VulkanInfo.h b/src/dawn/native/vulkan/VulkanInfo.h
index 39dd12d..5bb9257 100644
--- a/src/dawn/native/vulkan/VulkanInfo.h
+++ b/src/dawn/native/vulkan/VulkanInfo.h
@@ -53,6 +53,7 @@
     VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroupSizeControlFeatures;
     VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR zeroInitializeWorkgroupMemoryFeatures;
     VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR shaderIntegerDotProductFeatures;
+    VkPhysicalDeviceDepthClipEnableFeaturesEXT depthClipEnableFeatures;
 
     bool HasExt(DeviceExt ext) const;
     DeviceExtSet extensions;
diff --git a/src/dawn/tests/end2end/PrimitiveStateTests.cpp b/src/dawn/tests/end2end/PrimitiveStateTests.cpp
index fc6e5bd..264c42f 100644
--- a/src/dawn/tests/end2end/PrimitiveStateTests.cpp
+++ b/src/dawn/tests/end2end/PrimitiveStateTests.cpp
@@ -21,11 +21,11 @@
 
 constexpr static unsigned int kRTSize = 1;
 
-class DepthClampingTest : public DawnTest {
+class DepthClippingTest : public DawnTest {
   protected:
     void SetUp() override {
         DawnTest::SetUp();
-        DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::DepthClamping}));
+        DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::DepthClipControl}));
 
         wgpu::TextureDescriptor renderTargetDescriptor;
         renderTargetDescriptor.size = {kRTSize, kRTSize};
@@ -70,17 +70,16 @@
 
     std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
         std::vector<wgpu::FeatureName> requiredFeatures = {};
-        if (SupportsFeatures({wgpu::FeatureName::DepthClamping})) {
-            requiredFeatures.push_back(wgpu::FeatureName::DepthClamping);
+        if (SupportsFeatures({wgpu::FeatureName::DepthClipControl})) {
+            requiredFeatures.push_back(wgpu::FeatureName::DepthClipControl);
         }
         return requiredFeatures;
     }
 
     struct TestSpec {
-        wgpu::PrimitiveDepthClampingState* depthClampingState;
+        wgpu::PrimitiveDepthClipControl* depthClipControl;
         RGBA8 color;
         float depth;
-        wgpu::CompareFunction depthCompareFunction;
     };
 
     // Each test param represents a pair of triangles with a color, depth, stencil value, and
@@ -111,13 +110,12 @@
 
             // Create a pipeline for the triangles with the test spec's params.
             utils::ComboRenderPipelineDescriptor descriptor;
-            descriptor.primitive.nextInChain = test.depthClampingState;
+            descriptor.primitive.nextInChain = test.depthClipControl;
             descriptor.primitive.topology = wgpu::PrimitiveTopology::PointList;
             descriptor.vertex.module = vsModule;
             descriptor.cFragment.module = fsModule;
             wgpu::DepthStencilState* depthStencil = descriptor.EnableDepthStencil();
             depthStencil->depthWriteEnabled = true;
-            depthStencil->depthCompare = test.depthCompareFunction;
             depthStencil->format = wgpu::TextureFormat::Depth24PlusStencil8;
 
             wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
@@ -146,150 +144,218 @@
     wgpu::ShaderModule fsModule;
 };
 
-// Test that fragments beyond the far plane are clamped to 1.0 if depth clamping is enabled.
-TEST_P(DepthClampingTest, ClampOnBeyondFarPlane) {
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = true;
+// Test that fragments beyond the far plane are not clipped if unclippedDepth is true
+TEST_P(DepthClippingTest, UnclippedBeyondFarPlane) {
+    wgpu::PrimitiveDepthClipControl depthClipControl;
+    depthClipControl.unclippedDepth = true;
 
     DoTest(
         {
             // Draw a red triangle at depth 1.
             {
-                nullptr,               /* depthClampingState */
+                nullptr,               /* depthClipControl */
                 RGBA8(255, 0, 0, 255), /* color */
                 1.f,                   /* depth */
-                wgpu::CompareFunction::Always,
             },
-            // Draw a green triangle at depth 2 which should get clamped to 1.
+            // Draw a green triangle at depth 2 which should not be clipped.
             {
-                &clampingState,
+                &depthClipControl,     /* depthClipControl */
                 RGBA8(0, 255, 0, 255), /* color */
                 2.f,                   /* depth */
-                wgpu::CompareFunction::Equal,
             },
         },
-        // Since we draw the green triangle with an "equal" depth compare function, the resulting
-        // fragment should be green.
+        // The resulting fragment should be green even though the green triangle is
+        // outside the clip volume.
         RGBA8(0, 255, 0, 255));
 }
 
-// Test that fragments beyond the near plane are clamped to 0.0 if depth clamping is enabled.
-TEST_P(DepthClampingTest, ClampOnBeyondNearPlane) {
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = true;
+// Test that fragments beyond the far plane are clipped if unclippedDepth is false
+TEST_P(DepthClippingTest, ClippedBeyondFarPlane) {
+    wgpu::PrimitiveDepthClipControl depthClipControl;
+    depthClipControl.unclippedDepth = false;
+
+    DoTest(
+        {
+            // Draw a red triangle at depth 1.
+            {
+                nullptr,               /* depthClipControl */
+                RGBA8(255, 0, 0, 255), /* color */
+                1.f,                   /* depth */
+            },
+            // Draw a green triangle at depth 2 which should be clipped.
+            {
+                &depthClipControl,     /* depthClipControl */
+                RGBA8(0, 255, 0, 255), /* color */
+                2.f,                   /* depth */
+            },
+        },
+        // The resulting fragment should be red since the green triangle is
+        // outside the clip volume.
+        RGBA8(255, 0, 0, 255));
+}
+
+// Test that fragments beyond the far plane are clipped if unclippedDepth is not specified
+TEST_P(DepthClippingTest, ClippedBeyondFarPlaneFeatureUnused) {
+    DoTest(
+        {
+            // Draw a red triangle at depth 1.
+            {
+                nullptr,               /* depthClipControl */
+                RGBA8(255, 0, 0, 255), /* color */
+                1.f,                   /* depth */
+            },
+            // Draw a green triangle at depth 2 which should be clipped.
+            {
+                nullptr,               /* depthClipControl */
+                RGBA8(0, 255, 0, 255), /* color */
+                2.f,                   /* depth */
+            },
+        },
+        // The resulting fragment should be red since the green triangle is
+        // outside the clip volume.
+        RGBA8(255, 0, 0, 255));
+}
+
+// Test that fragments beyond the near plane are not clipped if unclippedDepth is true
+TEST_P(DepthClippingTest, UnclippedBeyondNearPlane) {
+    wgpu::PrimitiveDepthClipControl depthClipControl;
+    depthClipControl.unclippedDepth = true;
 
     DoTest(
         {
             // Draw a red triangle at depth 0.
             {
-                nullptr,               /* depthClampingState */
+                nullptr,               /* depthClipControl */
                 RGBA8(255, 0, 0, 255), /* color */
                 0.f,                   /* depth */
-                wgpu::CompareFunction::Always,
             },
-            // Draw a green triangle at depth -1 which should get clamped to 0.
+            // Draw a green triangle at depth -1 which should not be clipped.
             {
-                &clampingState,
+                &depthClipControl,     /* depthClipControl */
                 RGBA8(0, 255, 0, 255), /* color */
                 -1.f,                  /* depth */
-                wgpu::CompareFunction::Equal,
             },
         },
-        // Since we draw the green triangle with an "equal" depth compare function, the resulting
-        // fragment should be green.
+        // The resulting fragment should be green even though the green triangle is
+        // outside the clip volume.
         RGBA8(0, 255, 0, 255));
 }
 
-// Test that fragments inside the view frustum are unaffected by depth clamping.
-TEST_P(DepthClampingTest, ClampOnInsideViewFrustum) {
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = true;
+// Test that fragments beyond the near plane are clipped if unclippedDepth is false
+TEST_P(DepthClippingTest, ClippedBeyondNearPlane) {
+    wgpu::PrimitiveDepthClipControl depthClipControl;
+    depthClipControl.unclippedDepth = false;
 
     DoTest(
         {
+            // Draw a red triangle at depth 0.
             {
-                &clampingState,
-                RGBA8(0, 255, 0, 255), /* color */
-                0.5f,                  /* depth */
-                wgpu::CompareFunction::Always,
+                nullptr,               /* depthClipControl */
+                RGBA8(255, 0, 0, 255), /* color */
+                0.f,                   /* depth */
             },
-        },
-        RGBA8(0, 255, 0, 255));
-}
-
-// Test that fragments outside the view frustum are clipped if depth clamping is disabled.
-TEST_P(DepthClampingTest, ClampOffOutsideViewFrustum) {
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = false;
-
-    DoTest(
-        {
+            // Draw a green triangle at depth -1 which should be clipped.
             {
-                &clampingState,
-                RGBA8(0, 255, 0, 255), /* color */
-                2.f,                   /* depth */
-                wgpu::CompareFunction::Always,
-            },
-            {
-                &clampingState,
+                &depthClipControl,     /* depthClipControl */
                 RGBA8(0, 255, 0, 255), /* color */
                 -1.f,                  /* depth */
-                wgpu::CompareFunction::Always,
             },
         },
-        RGBA8(0, 0, 0, 0));
+        // The resulting fragment should be red because the green triangle is
+        // outside the clip volume.
+        RGBA8(255, 0, 0, 255));
 }
 
-// Test that fragments outside the view frustum are clipped if clampDepth is left unspecified.
-TEST_P(DepthClampingTest, ClampUnspecifiedOutsideViewFrustum) {
+// Test that fragments beyond the near plane are clipped if unclippedDepth is not specified
+TEST_P(DepthClippingTest, ClippedBeyondNearPlaneFeatureUnused) {
     DoTest(
         {
+            // Draw a red triangle at depth 0.
             {
-                nullptr,               /* depthClampingState */
+                nullptr,               /* depthClipControl */
+                RGBA8(255, 0, 0, 255), /* color */
+                0.f,                   /* depth */
+            },
+            // Draw a green triangle at depth -1 which should be clipped.
+            {
+                nullptr,               /* depthClipControl */
                 RGBA8(0, 255, 0, 255), /* color */
                 -1.f,                  /* depth */
-                wgpu::CompareFunction::Always,
-            },
-            {
-                nullptr,               /* depthClampingState */
-                RGBA8(0, 255, 0, 255), /* color */
-                2.f,                   /* depth */
-                wgpu::CompareFunction::Always,
             },
         },
-        RGBA8(0, 0, 0, 0));
+        // The resulting fragment should be red because the green triangle is
+        // outside the clip volume.
+        RGBA8(255, 0, 0, 255));
 }
 
 // Test that fragments are properly clipped or clamped if multiple render pipelines are used
-// within the same render pass with differing clampDepth values.
-TEST_P(DepthClampingTest, MultipleRenderPipelines) {
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = true;
+// within the same render pass with differing unclippedDepth values.
+TEST_P(DepthClippingTest, MultipleRenderPipelines) {
+    wgpu::PrimitiveDepthClipControl depthClipControl1;
+    depthClipControl1.unclippedDepth = true;
 
-    wgpu::PrimitiveDepthClampingState clippingState;
-    clippingState.clampDepth = false;
+    wgpu::PrimitiveDepthClipControl depthClipControl2;
+    depthClipControl2.unclippedDepth = false;
 
     DoTest(
         {
-            // Draw green with clamping
+            // Draw green with no clipping
             {
-                &clampingState,
-                RGBA8(0, 255, 0, 255), /* color */
-                2.f,                   /* depth */
-                wgpu::CompareFunction::Always,
+                &depthClipControl1, RGBA8(0, 255, 0, 255), /* color */
+                2.f,                                       /* depth */
             },
             // Draw red with clipping
             {
-                &clippingState,
-                RGBA8(255, 0, 0, 255), /* color */
-                2.f,                   /* depth */
-                wgpu::CompareFunction::Always,
+                &depthClipControl2, RGBA8(255, 0, 0, 255), /* color */
+                2.f,                                       /* depth */
             },
         },
         RGBA8(0, 255, 0, 255));  // Result should be green
 }
 
-DAWN_INSTANTIATE_TEST(DepthClampingTest,
+// Test that fragments are not clipped if unclippedDepth is true and that their
+// depths are not being clamped instead. In the fragment shader, we should see
+// depth values outside the viewport.
+TEST_P(DepthClippingTest, UnclippedNotClamped) {
+    wgpu::PrimitiveDepthClipControl depthClipControl;
+    depthClipControl.unclippedDepth = true;
+
+    // Create a pipeline to render a point.
+    utils::ComboRenderPipelineDescriptor descriptor;
+    descriptor.primitive.nextInChain = &depthClipControl;
+    descriptor.primitive.topology = wgpu::PrimitiveTopology::PointList;
+    // Draw the point at (0, 0) with depth 2.0.
+    descriptor.vertex.module = utils::CreateShaderModule(device, R"(
+        @vertex fn main() -> @builtin(position) vec4<f32> {
+            return vec4<f32>(0.0, 0.0, 2.0, 1.0);
+        })");
+    // Write frag_pos.z / 4.0 which should be about 0.5 to the red channel.
+    // This is the depth output from the vertex shader which is not clamped to the viewport.
+    descriptor.cFragment.module = utils::CreateShaderModule(device, R"(
+        @fragment fn main(@builtin(position) frag_pos: vec4<f32>) -> @location(0) vec4<f32> {
+            return vec4<f32>(frag_pos.z / 4.0, 0.0, 0.0, 1.0);
+        })");
+    wgpu::DepthStencilState* depthStencil = descriptor.EnableDepthStencil();
+    depthStencil->depthWriteEnabled = true;
+    depthStencil->format = wgpu::TextureFormat::Depth24PlusStencil8;
+
+    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
+
+    // Draw the point.
+    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+    utils::ComboRenderPassDescriptor renderPass({renderTargetView}, depthTextureView);
+    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
+    pass.SetPipeline(pipeline);
+    pass.Draw(1);
+    pass.End();
+    wgpu::CommandBuffer commands = encoder.Finish();
+    queue.Submit(1, &commands);
+
+    EXPECT_PIXEL_RGBA8_BETWEEN(RGBA8(127, 0, 0, 255), RGBA8(128, 0, 0, 255), renderTarget, 0, 0)
+        << "Pixel check failed";
+}
+
+DAWN_INSTANTIATE_TEST(DepthClippingTest,
                       D3D12Backend(),
                       MetalBackend(),
                       OpenGLBackend(),
diff --git a/src/dawn/tests/unittests/ChainUtilsTests.cpp b/src/dawn/tests/unittests/ChainUtilsTests.cpp
index 87d7b46..c1bea5b 100644
--- a/src/dawn/tests/unittests/ChainUtilsTests.cpp
+++ b/src/dawn/tests/unittests/ChainUtilsTests.cpp
@@ -19,7 +19,7 @@
 
 // Checks that we cannot find any structs in an empty chain
 TEST(ChainUtilsTests, FindEmptyChain) {
-    const dawn::native::PrimitiveDepthClampingState* info = nullptr;
+    const dawn::native::PrimitiveDepthClipControl* info = nullptr;
     dawn::native::FindInChain(nullptr, &info);
 
     ASSERT_EQ(nullptr, info);
@@ -27,10 +27,10 @@
 
 // Checks that searching a chain for a present struct returns that struct
 TEST(ChainUtilsTests, FindPresentInChain) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     chain1.nextInChain = &chain2;
-    const dawn::native::PrimitiveDepthClampingState* info1 = nullptr;
+    const dawn::native::PrimitiveDepthClipControl* info1 = nullptr;
     const dawn::native::ShaderModuleSPIRVDescriptor* info2 = nullptr;
     dawn::native::FindInChain(&chain1, &info1);
     dawn::native::FindInChain(&chain1, &info2);
@@ -41,7 +41,7 @@
 
 // Checks that searching a chain for a struct that doesn't exist returns a nullptr
 TEST(ChainUtilsTests, FindMissingInChain) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     chain1.nextInChain = &chain2;
     const dawn::native::SurfaceDescriptorFromMetalLayer* info = nullptr;
@@ -52,9 +52,9 @@
 
 // Checks that validation rejects chains with duplicate STypes
 TEST(ChainUtilsTests, ValidateDuplicateSTypes) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
-    dawn::native::PrimitiveDepthClampingState chain3;
+    dawn::native::PrimitiveDepthClipControl chain3;
     chain1.nextInChain = &chain2;
     chain2.nextInChain = &chain3;
 
@@ -65,7 +65,7 @@
 
 // Checks that validation rejects chains that contain unspecified STypes
 TEST(ChainUtilsTests, ValidateUnspecifiedSTypes) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     dawn::native::ShaderModuleWGSLDescriptor chain3;
     chain1.nextInChain = &chain2;
@@ -73,7 +73,7 @@
 
     dawn::native::MaybeError result =
         dawn::native::ValidateSTypes(&chain1, {
-                                                  {wgpu::SType::PrimitiveDepthClampingState},
+                                                  {wgpu::SType::PrimitiveDepthClipControl},
                                                   {wgpu::SType::ShaderModuleSPIRVDescriptor},
                                               });
     ASSERT_TRUE(result.IsError());
@@ -83,7 +83,7 @@
 // Checks that validation rejects chains that contain multiple STypes from the same oneof
 // constraint.
 TEST(ChainUtilsTests, ValidateOneOfFailure) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     dawn::native::ShaderModuleWGSLDescriptor chain3;
     chain1.nextInChain = &chain2;
@@ -98,7 +98,7 @@
 
 // Checks that validation accepts chains that match the constraints.
 TEST(ChainUtilsTests, ValidateSuccess) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     chain1.nextInChain = &chain2;
 
@@ -106,7 +106,7 @@
         &chain1,
         {
             {wgpu::SType::ShaderModuleSPIRVDescriptor, wgpu::SType::ShaderModuleWGSLDescriptor},
-            {wgpu::SType::PrimitiveDepthClampingState},
+            {wgpu::SType::PrimitiveDepthClipControl},
             {wgpu::SType::SurfaceDescriptorFromMetalLayer},
         });
     ASSERT_TRUE(result.IsSuccess());
@@ -117,7 +117,7 @@
     dawn::native::MaybeError result =
         dawn::native::ValidateSTypes(nullptr, {
                                                   {wgpu::SType::ShaderModuleSPIRVDescriptor},
-                                                  {wgpu::SType::PrimitiveDepthClampingState},
+                                                  {wgpu::SType::PrimitiveDepthClipControl},
                                               });
     ASSERT_TRUE(result.IsSuccess());
 
@@ -132,22 +132,22 @@
     ASSERT_TRUE(result.IsSuccess());
 
     result = dawn::native::ValidateSingleSType(nullptr, wgpu::SType::ShaderModuleSPIRVDescriptor,
-                                               wgpu::SType::PrimitiveDepthClampingState);
+                                               wgpu::SType::PrimitiveDepthClipControl);
     ASSERT_TRUE(result.IsSuccess());
 }
 
 // Checks that singleton validation always fails on chains with multiple children.
 TEST(ChainUtilsTests, ValidateSingleMultiChain) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
     dawn::native::ShaderModuleSPIRVDescriptor chain2;
     chain1.nextInChain = &chain2;
 
     dawn::native::MaybeError result =
-        dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClampingState);
+        dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl);
     ASSERT_TRUE(result.IsError());
     result.AcquireError();
 
-    result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClampingState,
+    result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl,
                                                wgpu::SType::ShaderModuleSPIRVDescriptor);
     ASSERT_TRUE(result.IsError());
     result.AcquireError();
@@ -172,7 +172,7 @@
 
 // Checks that singleton validation passes when the oneof constraint is not met.
 TEST(ChainUtilsTests, ValidateSingleUnsatisfied) {
-    dawn::native::PrimitiveDepthClampingState chain1;
+    dawn::native::PrimitiveDepthClipControl chain1;
 
     dawn::native::MaybeError result =
         dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor);
diff --git a/src/dawn/tests/unittests/validation/DeviceValidationTests.cpp b/src/dawn/tests/unittests/validation/DeviceValidationTests.cpp
index 2ed5916..e1c9e0b 100644
--- a/src/dawn/tests/unittests/validation/DeviceValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/DeviceValidationTests.cpp
@@ -201,9 +201,9 @@
 
 // Test that it is an error to request limits with an invalid chained struct
 TEST_F(RequestDeviceValidationTest, InvalidChainedStruct) {
-    wgpu::PrimitiveDepthClampingState depthClamp = {};
+    wgpu::PrimitiveDepthClipControl depthClipControl = {};
     wgpu::RequiredLimits limits = {};
-    limits.nextInChain = &depthClamp;
+    limits.nextInChain = &depthClipControl;
 
     wgpu::DeviceDescriptor descriptor;
     descriptor.requiredLimits = &limits;
diff --git a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
index c1c36a8..5271228 100644
--- a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
@@ -975,15 +975,15 @@
     }
 }
 
-// Test that specifying a clampDepth value is an error if the feature is not enabled.
-TEST_F(RenderPipelineValidationTest, ClampDepthWithoutFeature) {
+// Test that specifying a unclippedDepth value is an error if the feature is not enabled.
+TEST_F(RenderPipelineValidationTest, UnclippedDepthWithoutFeature) {
     {
         utils::ComboRenderPipelineDescriptor descriptor;
         descriptor.vertex.module = vsModule;
         descriptor.cFragment.module = fsModule;
-        wgpu::PrimitiveDepthClampingState clampingState;
-        clampingState.clampDepth = true;
-        descriptor.primitive.nextInChain = &clampingState;
+        wgpu::PrimitiveDepthClipControl depthClipControl;
+        depthClipControl.unclippedDepth = true;
+        descriptor.primitive.nextInChain = &depthClipControl;
         ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
                             testing::HasSubstr("not supported"));
     }
@@ -991,9 +991,9 @@
         utils::ComboRenderPipelineDescriptor descriptor;
         descriptor.vertex.module = vsModule;
         descriptor.cFragment.module = fsModule;
-        wgpu::PrimitiveDepthClampingState clampingState;
-        clampingState.clampDepth = false;
-        descriptor.primitive.nextInChain = &clampingState;
+        wgpu::PrimitiveDepthClipControl depthClipControl;
+        depthClipControl.unclippedDepth = false;
+        descriptor.primitive.nextInChain = &depthClipControl;
         ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
                             testing::HasSubstr("not supported"));
     }
@@ -1023,24 +1023,6 @@
     }
 }
 
-// Test that using both DepthClipControl and DepthClamp features is invalid.
-TEST_F(RenderPipelineValidationTest, DepthClipControlAndDepthClampInvalid) {
-    utils::ComboRenderPipelineDescriptor descriptor;
-    descriptor.vertex.module = vsModule;
-    descriptor.cFragment.module = fsModule;
-
-    wgpu::PrimitiveDepthClipControl depthClipControl;
-    depthClipControl.unclippedDepth = false;
-    descriptor.primitive.nextInChain = &depthClipControl;
-
-    wgpu::PrimitiveDepthClampingState clampingState;
-    clampingState.clampDepth = false;
-    depthClipControl.nextInChain = &clampingState;
-
-    ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
-                        testing::HasSubstr("only contain a single chained struct"));
-}
-
 // Test that depthStencil.depthCompare must not be undefiend.
 TEST_F(RenderPipelineValidationTest, DepthCompareUndefinedIsError) {
     utils::ComboRenderPipelineDescriptor descriptor;
@@ -1359,35 +1341,35 @@
     ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
 }
 
-class DepthClampingValidationTest : public RenderPipelineValidationTest {
+class DepthClipControlValidationTest : public RenderPipelineValidationTest {
   protected:
     WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter) override {
         wgpu::DeviceDescriptor descriptor;
-        wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::DepthClamping};
+        wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::DepthClipControl};
         descriptor.requiredFeatures = requiredFeatures;
         descriptor.requiredFeaturesCount = 1;
         return dawnAdapter.CreateDevice(&descriptor);
     }
 };
 
-// Tests that specifying a clampDepth value succeeds if the feature is enabled.
-TEST_F(DepthClampingValidationTest, Success) {
+// Tests that specifying a unclippedDepth value succeeds if the feature is enabled.
+TEST_F(DepthClipControlValidationTest, Success) {
     {
         utils::ComboRenderPipelineDescriptor descriptor;
         descriptor.vertex.module = vsModule;
         descriptor.cFragment.module = fsModule;
-        wgpu::PrimitiveDepthClampingState clampingState;
-        clampingState.clampDepth = true;
-        descriptor.primitive.nextInChain = &clampingState;
+        wgpu::PrimitiveDepthClipControl depthClipControl;
+        depthClipControl.unclippedDepth = true;
+        descriptor.primitive.nextInChain = &depthClipControl;
         device.CreateRenderPipeline(&descriptor);
     }
     {
         utils::ComboRenderPipelineDescriptor descriptor;
         descriptor.vertex.module = vsModule;
         descriptor.cFragment.module = fsModule;
-        wgpu::PrimitiveDepthClampingState clampingState;
-        clampingState.clampDepth = false;
-        descriptor.primitive.nextInChain = &clampingState;
+        wgpu::PrimitiveDepthClipControl depthClipControl;
+        depthClipControl.unclippedDepth = false;
+        descriptor.primitive.nextInChain = &depthClipControl;
         device.CreateRenderPipeline(&descriptor);
     }
 }
diff --git a/src/dawn/tests/unittests/wire/WireExtensionTests.cpp b/src/dawn/tests/unittests/wire/WireExtensionTests.cpp
index 6060ce5..b36e244 100644
--- a/src/dawn/tests/unittests/wire/WireExtensionTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireExtensionTests.cpp
@@ -36,10 +36,10 @@
     EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiShaderModule));
     FlushClient();
 
-    WGPUPrimitiveDepthClampingState clientExt = {};
-    clientExt.chain.sType = WGPUSType_PrimitiveDepthClampingState;
+    WGPUPrimitiveDepthClipControl clientExt = {};
+    clientExt.chain.sType = WGPUSType_PrimitiveDepthClipControl;
     clientExt.chain.next = nullptr;
-    clientExt.clampDepth = true;
+    clientExt.unclippedDepth = true;
 
     WGPURenderPipelineDescriptor renderPipelineDesc = {};
     renderPipelineDesc.vertex.module = shaderModule;
@@ -50,10 +50,10 @@
     EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
         .WillOnce(Invoke(
             [&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
-                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
+                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(
                     serverDesc->primitive.nextInChain);
                 EXPECT_EQ(ext->chain.sType, clientExt.chain.sType);
-                EXPECT_EQ(ext->clampDepth, true);
+                EXPECT_EQ(ext->unclippedDepth, true);
                 EXPECT_EQ(ext->chain.next, nullptr);
 
                 return api.GetNewRenderPipeline();
@@ -69,15 +69,15 @@
     EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiShaderModule));
     FlushClient();
 
-    WGPUPrimitiveDepthClampingState clientExt2 = {};
-    clientExt2.chain.sType = WGPUSType_PrimitiveDepthClampingState;
+    WGPUPrimitiveDepthClipControl clientExt2 = {};
+    clientExt2.chain.sType = WGPUSType_PrimitiveDepthClipControl;
     clientExt2.chain.next = nullptr;
-    clientExt2.clampDepth = false;
+    clientExt2.unclippedDepth = false;
 
-    WGPUPrimitiveDepthClampingState clientExt1 = {};
-    clientExt1.chain.sType = WGPUSType_PrimitiveDepthClampingState;
+    WGPUPrimitiveDepthClipControl clientExt1 = {};
+    clientExt1.chain.sType = WGPUSType_PrimitiveDepthClipControl;
     clientExt1.chain.next = &clientExt2.chain;
-    clientExt1.clampDepth = true;
+    clientExt1.unclippedDepth = true;
 
     WGPURenderPipelineDescriptor renderPipelineDesc = {};
     renderPipelineDesc.vertex.module = shaderModule;
@@ -88,15 +88,15 @@
     EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
         .WillOnce(Invoke(
             [&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
-                const auto* ext1 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
+                const auto* ext1 = reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(
                     serverDesc->primitive.nextInChain);
                 EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
-                EXPECT_EQ(ext1->clampDepth, true);
+                EXPECT_EQ(ext1->unclippedDepth, true);
 
                 const auto* ext2 =
-                    reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(ext1->chain.next);
+                    reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(ext1->chain.next);
                 EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
-                EXPECT_EQ(ext2->clampDepth, false);
+                EXPECT_EQ(ext2->unclippedDepth, false);
                 EXPECT_EQ(ext2->chain.next, nullptr);
 
                 return api.GetNewRenderPipeline();
@@ -112,15 +112,15 @@
     EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
         .WillOnce(Invoke(
             [&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
-                const auto* ext2 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
+                const auto* ext2 = reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(
                     serverDesc->primitive.nextInChain);
                 EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
-                EXPECT_EQ(ext2->clampDepth, false);
+                EXPECT_EQ(ext2->unclippedDepth, false);
 
                 const auto* ext1 =
-                    reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(ext2->chain.next);
+                    reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(ext2->chain.next);
                 EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
-                EXPECT_EQ(ext1->clampDepth, true);
+                EXPECT_EQ(ext1->unclippedDepth, true);
                 EXPECT_EQ(ext1->chain.next, nullptr);
 
                 return api.GetNewRenderPipeline();
@@ -136,7 +136,7 @@
     EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiShaderModule));
     FlushClient();
 
-    WGPUPrimitiveDepthClampingState clientExt = {};
+    WGPUPrimitiveDepthClipControl clientExt = {};
     clientExt.chain.sType = WGPUSType_Invalid;
     clientExt.chain.next = nullptr;
 
@@ -164,7 +164,7 @@
     EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiShaderModule));
     FlushClient();
 
-    WGPUPrimitiveDepthClampingState clientExt = {};
+    WGPUPrimitiveDepthClipControl clientExt = {};
     clientExt.chain.sType = static_cast<WGPUSType>(-1);
     clientExt.chain.next = nullptr;
 
@@ -193,14 +193,14 @@
     EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiShaderModule));
     FlushClient();
 
-    WGPUPrimitiveDepthClampingState clientExt2 = {};
+    WGPUPrimitiveDepthClipControl clientExt2 = {};
     clientExt2.chain.sType = WGPUSType_Invalid;
     clientExt2.chain.next = nullptr;
 
-    WGPUPrimitiveDepthClampingState clientExt1 = {};
-    clientExt1.chain.sType = WGPUSType_PrimitiveDepthClampingState;
+    WGPUPrimitiveDepthClipControl clientExt1 = {};
+    clientExt1.chain.sType = WGPUSType_PrimitiveDepthClipControl;
     clientExt1.chain.next = &clientExt2.chain;
-    clientExt1.clampDepth = true;
+    clientExt1.unclippedDepth = true;
 
     WGPURenderPipelineDescriptor renderPipelineDesc = {};
     renderPipelineDesc.vertex.module = shaderModule;
@@ -211,10 +211,10 @@
     EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
         .WillOnce(Invoke(
             [&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
-                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
+                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(
                     serverDesc->primitive.nextInChain);
                 EXPECT_EQ(ext->chain.sType, clientExt1.chain.sType);
-                EXPECT_EQ(ext->clampDepth, true);
+                EXPECT_EQ(ext->unclippedDepth, true);
 
                 EXPECT_EQ(ext->chain.next->sType, WGPUSType_Invalid);
                 EXPECT_EQ(ext->chain.next->next, nullptr);
@@ -233,10 +233,10 @@
             [&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
                 EXPECT_EQ(serverDesc->primitive.nextInChain->sType, WGPUSType_Invalid);
 
-                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
+                const auto* ext = reinterpret_cast<const WGPUPrimitiveDepthClipControl*>(
                     serverDesc->primitive.nextInChain->next);
                 EXPECT_EQ(ext->chain.sType, clientExt1.chain.sType);
-                EXPECT_EQ(ext->clampDepth, true);
+                EXPECT_EQ(ext->unclippedDepth, true);
                 EXPECT_EQ(ext->chain.next, nullptr);
 
                 return api.GetNewRenderPipeline();
diff --git a/src/dawn/wire/SupportedFeatures.cpp b/src/dawn/wire/SupportedFeatures.cpp
index 3deb1a7..aca064f 100644
--- a/src/dawn/wire/SupportedFeatures.cpp
+++ b/src/dawn/wire/SupportedFeatures.cpp
@@ -32,7 +32,6 @@
         case WGPUFeatureName_TextureCompressionASTC:
         case WGPUFeatureName_IndirectFirstInstance:
         case WGPUFeatureName_DepthClipControl:
-        case WGPUFeatureName_DepthClamping:
         case WGPUFeatureName_DawnShaderFloat16:
         case WGPUFeatureName_DawnInternalUsages:
         case WGPUFeatureName_DawnMultiPlanarFormats:
diff --git a/webgpu-cts/expectations.txt b/webgpu-cts/expectations.txt
index cc2759c..fc18769 100644
--- a/webgpu-cts/expectations.txt
+++ b/webgpu-cts/expectations.txt
@@ -246,10 +246,9 @@
 
 ################################################################################
 # depth_clip_clamp failures
-# KEEP
 ################################################################################
-crbug.com/dawn/0000 webgpu:api,operation,rendering,depth_clip_clamp:depth_clamp_and_clip:* [ Failure ]
-crbug.com/dawn/0000 webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:* [ Failure ]
+crbug.com/dawn/1125 [ linux ] webgpu:api,operation,rendering,depth_clip_clamp:depth_clamp_and_clip:* [ Failure ]
+crbug.com/dawn/1125 [ linux ] webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:* [ Failure ]
 
 ################################################################################
 # compilation_info failures