diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index a23eb2059f4a..2a2007f0bda1 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -146,6 +146,8 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_LARGE_VIEWPORTS; if (draw_->GetDeviceCaps().dualSourceBlend) features |= GPU_SUPPORTS_DUALSOURCE_BLEND; + if (draw_->GetDeviceCaps().depthClampSupported) + features |= GPU_SUPPORTS_DEPTH_CLAMP; features |= GPU_SUPPORTS_ANY_COPY_IMAGE; features |= GPU_SUPPORTS_TEXTURE_FLOAT; features |= GPU_SUPPORTS_INSTANCE_RENDERING; diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index c1e669d2686b..f5ff8807dc0f 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -276,12 +276,22 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { keys_.raster.value = 0; - if (gstate.isModeClear()) { + if (gstate.isModeClear() || gstate.isModeThrough()) { keys_.raster.cullMode = D3D11_CULL_NONE; + // TODO: Might happen in clear mode if not through... + keys_.raster.depthClipEnable = 1; } else { // Set cull - bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); + bool wantCull = prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); keys_.raster.cullMode = wantCull ? (gstate.getCullMode() ? D3D11_CULL_FRONT : D3D11_CULL_BACK) : D3D11_CULL_NONE; + if (gstate.getDepthRangeMin() == 0 || gstate.getDepthRangeMax() == 65535) { + // TODO: Still has a bug where we clamp to depth range if one is not the full range. + // But the alternate is not clamping in either direction... + keys_.raster.depthClipEnable = !gstate.isDepthClampEnabled() || !gstate_c.Supports(GPU_SUPPORTS_DEPTH_CLAMP); + } else { + // We just want to clip in this case, the clamp would be clipped anyway. + keys_.raster.depthClipEnable = 1; + } } ID3D11RasterizerState *rs = rasterCache_.Get(keys_.raster.value); if (rs == nullptr) { @@ -290,7 +300,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { desc.FillMode = D3D11_FILL_SOLID; desc.ScissorEnable = TRUE; desc.FrontCounterClockwise = TRUE; - desc.DepthClipEnable = TRUE; + desc.DepthClipEnable = keys_.raster.depthClipEnable; ASSERT_SUCCESS(device_->CreateRasterizerState(&desc, &rs)); rasterCache_.Insert(keys_.raster.value, rs); } diff --git a/GPU/D3D11/StateMappingD3D11.h b/GPU/D3D11/StateMappingD3D11.h index 05f6b51c908d..df6f4a2adf49 100644 --- a/GPU/D3D11/StateMappingD3D11.h +++ b/GPU/D3D11/StateMappingD3D11.h @@ -49,7 +49,8 @@ struct D3D11RasterKey { union { uint32_t value; struct { - unsigned int cullMode : 2; // D3D11_CULL_MODE + unsigned int cullMode : 2; // D3D11_CULL_MODE + unsigned int depthClipEnable : 1; }; }; }; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 73088939fbbc..63be93ce6834 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -487,6 +487,7 @@ struct DeviceCaps { bool multiViewport; bool dualSourceBlend; bool logicOpSupported; + bool depthClampSupported; bool framebufferCopySupported; bool framebufferBlitSupported; bool framebufferDepthCopySupported; diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index f5e0c2da2796..b8618ccfe154 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -227,6 +227,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de // Seems like a fair approximation... caps_.dualSourceBlend = featureLevel_ >= D3D_FEATURE_LEVEL_10_0; + caps_.depthClampSupported = featureLevel_ >= D3D_FEATURE_LEVEL_10_0; caps_.depthRangeMinusOneToOne = false; caps_.framebufferBlitSupported = false; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 43e48283eaaf..37d6497b51bd 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -747,6 +747,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) caps_.tesselationShaderSupported = vulkan->GetFeaturesAvailable().tessellationShader != 0; caps_.multiViewport = vulkan->GetFeaturesAvailable().multiViewport != 0; caps_.dualSourceBlend = vulkan->GetFeaturesAvailable().dualSrcBlend != 0; + caps_.depthClampSupported = vulkan->GetFeaturesAvailable().depthClamp != 0; caps_.framebufferBlitSupported = true; caps_.framebufferCopySupported = true; caps_.framebufferDepthBlitSupported = false; // Can be checked for.