From 1ae7c0132cecc5d6d0d9e1b440f65ec72330ea1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 Sep 2022 10:02:15 +0200 Subject: [PATCH 1/3] Start unifying setting of the GPU feature flags, now that thin3d has feature detection. --- Common/GPU/D3D11/thin3d_d3d11.cpp | 1 + Common/GPU/D3D9/thin3d_d3d9.cpp | 23 ++++++++++++++++++--- Common/GPU/OpenGL/thin3d_gl.cpp | 2 ++ Common/GPU/Vulkan/thin3d_vulkan.cpp | 2 ++ Common/GPU/thin3d.h | 1 + GPU/D3D11/GPU_D3D11.cpp | 28 +++++-------------------- GPU/D3D11/GPU_D3D11.h | 2 +- GPU/Directx9/GPU_DX9.cpp | 32 +++++------------------------ GPU/Directx9/GPU_DX9.h | 2 +- GPU/GLES/GPU_GLES.cpp | 29 +++++--------------------- GPU/GLES/GPU_GLES.h | 2 +- GPU/GPUCommon.cpp | 27 ++++++++++++++++++++++++ GPU/GPUCommon.h | 2 +- GPU/Software/SoftGpu.h | 2 +- GPU/Vulkan/GPU_Vulkan.cpp | 29 ++++++-------------------- GPU/Vulkan/GPU_Vulkan.h | 2 +- 16 files changed, 80 insertions(+), 106 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index c17bb39919..a808386ce9 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -270,6 +270,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.anisoSupported = true; caps_.textureNPOTFullySupported = true; caps_.fragmentShaderDepthWriteSupported = true; + caps_.blendMinMaxSupported = true; D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options)); diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index a84d42f64e..502d2c06db 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -665,14 +665,24 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.vendor = GPUVendor::VENDOR_UNKNOWN; } - if (!FAILED(device->GetDeviceCaps(&d3dCaps_))) { + D3DCAPS9 caps; + ZeroMemory(&caps, sizeof(caps)); + HRESULT result = 0; + if (deviceEx_) { + result = deviceEx_->GetDeviceCaps(&caps); + } else { + result = device_->GetDeviceCaps(&caps); + } + + if (SUCCEEDED(result)) { sprintf(shadeLangVersion_, "PS: %04x VS: %04x", d3dCaps_.PixelShaderVersion & 0xFFFF, d3dCaps_.VertexShaderVersion & 0xFFFF); } else { + WARN_LOG(G3D, "Direct3D9: Failed to get the device caps!"); strcpy(shadeLangVersion_, "N/A"); } + caps_.deviceID = identifier_.DeviceId; caps_.multiViewport = false; - caps_.anisoSupported = true; caps_.depthRangeMinusOneToOne = false; caps_.preferredDepthBufferFormat = DataFormat::D24_S8; caps_.dualSourceBlend = false; @@ -684,8 +694,15 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.framebufferDepthCopySupported = false; caps_.framebufferSeparateDepthCopySupported = false; caps_.texture3DSupported = true; - caps_.textureNPOTFullySupported = true; caps_.fragmentShaderDepthWriteSupported = true; + caps_.blendMinMaxSupported = true; + + if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) { + caps_.anisoSupported = true; + } + if ((caps.TextureCaps & (D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_POW2)) == 0) { + caps_.textureNPOTFullySupported = true; + } if (d3d) { D3DDISPLAYMODE displayMode; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index b2e6320455..dfe7f95c6f 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -552,6 +552,8 @@ OpenGLContext::OpenGLContext() { caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported; caps_.framebufferStencilBlitSupported = caps_.framebufferBlitSupported; caps_.depthClampSupported = gl_extensions.ARB_depth_clamp; + caps_.blendMinMaxSupported = gl_extensions.EXT_blend_minmax; + if (gl_extensions.IsGLES) { caps_.clipDistanceSupported = gl_extensions.EXT_clip_cull_distance || gl_extensions.APPLE_clip_distance; caps_.cullDistanceSupported = gl_extensions.EXT_clip_cull_distance; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index d64fd7ae7d..34bbdd5efb 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -788,9 +788,11 @@ VKContext::VKContext(VulkanContext *vulkan) caps_.fragmentShaderInt32Supported = true; caps_.textureNPOTFullySupported = true; caps_.fragmentShaderDepthWriteSupported = true; + caps_.blendMinMaxSupported = true; caps_.logicOpSupported = vulkan->GetDeviceFeatures().enabled.logicOp != 0; auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties; + switch (deviceProps.vendorID) { case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break; case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index b4eca9d0bc..0fba6ee6f2 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -547,6 +547,7 @@ struct DeviceCaps { bool textureNPOTFullySupported; bool fragmentShaderDepthWriteSupported; bool textureDepthSupported; + bool blendMinMaxSupported; std::string deviceName; // The device name to use when creating the thin3d context, to get the same one. }; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 3cfe0c4b37..bd4d131e98 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -82,7 +82,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); BuildReportingInfo(); @@ -100,25 +100,15 @@ GPU_D3D11::~GPU_D3D11() { stockD3D11.Destroy(); } -void GPU_D3D11::CheckGPUFeatures() { - u32 features = 0; - - features |= GPU_SUPPORTS_BLEND_MINMAX; +u32 GPU_D3D11::CheckGPUFeatures() const { + u32 features = GPUCommon::CheckGPUFeatures(); // Accurate depth is required because the Direct3D API does not support inverse Z. // So we cannot incorrectly use the viewport transform as the depth range on Direct3D. // TODO: Breaks text in PaRappa for some reason? features |= GPU_SUPPORTS_ACCURATE_DEPTH; -#ifndef _M_ARM - // TODO: Do proper feature detection - features |= GPU_SUPPORTS_ANISOTROPY; -#endif - features |= GPU_SUPPORTS_DEPTH_TEXTURE; - features |= GPU_SUPPORTS_TEXTURE_NPOT; - if (draw_->GetDeviceCaps().dualSourceBlend) - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; if (draw_->GetDeviceCaps().depthClampSupported) features |= GPU_SUPPORTS_DEPTH_CLAMP; if (draw_->GetDeviceCaps().clipDistanceSupported) @@ -146,10 +136,6 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_16BIT_FORMATS; } - if (draw_->GetDeviceCaps().logicOpSupported) { - features |= GPU_SUPPORTS_LOGIC_OP; - } - if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { @@ -164,11 +150,7 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_USE_DEPTH_RANGE_HACK; } - if (PSP_CoreParameter().compat.flags().ClearToRAM) { - features |= GPU_USE_CLEAR_RAM_HACK; - } - - gstate_c.featureFlags = features; + return features; } // Needs to be called on GPU thread, not reporting thread. @@ -206,7 +188,7 @@ void GPU_D3D11::BeginHostFrame() { GPUCommon::BeginHostFrame(); UpdateCmdInfo(); if (resized_) { - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); framebufferManager_->Resized(); drawEngine_.Resized(); textureCache_->NotifyConfigChanged(); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index d1e5287782..e45c1ab79d 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -36,7 +36,7 @@ public: GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_D3D11(); - void CheckGPUFeatures() override; + u32 CheckGPUFeatures() const override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 3e5d0bac57..0ec02a3595 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -81,7 +81,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // No need to flush before the tex scale/offset commands if we are baking // the tex scale/offset into the vertices anyway. UpdateCmdInfo(); - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); BuildReportingInfo(); @@ -155,10 +155,9 @@ static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) { return NV_PRE_KEPLER; } -void GPU_DX9::CheckGPUFeatures() { - u32 features = 0; +u32 GPU_DX9::CheckGPUFeatures() const { + u32 features = GPUCommon::CheckGPUFeatures(); features |= GPU_SUPPORTS_16BIT_FORMATS; - features |= GPU_SUPPORTS_BLEND_MINMAX; features |= GPU_SUPPORTS_DEPTH_TEXTURE; features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; @@ -187,23 +186,6 @@ void GPU_DX9::CheckGPUFeatures() { } } - D3DCAPS9 caps; - ZeroMemory(&caps, sizeof(caps)); - HRESULT result = 0; - if (deviceEx_) { - result = deviceEx_->GetDeviceCaps(&caps); - } else { - result = device_->GetDeviceCaps(&caps); - } - if (FAILED(result)) { - WARN_LOG_REPORT(G3D, "Direct3D9: Failed to get the device caps!"); - } else { - if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) - features |= GPU_SUPPORTS_ANISOTROPY; - if ((caps.TextureCaps & (D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_POW2)) == 0) - features |= GPU_SUPPORTS_TEXTURE_NPOT; - } - if (!g_Config.bHighQualityDepth) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { @@ -213,11 +195,7 @@ void GPU_DX9::CheckGPUFeatures() { features |= GPU_ROUND_DEPTH_TO_16BIT; } - if (PSP_CoreParameter().compat.flags().ClearToRAM) { - features |= GPU_USE_CLEAR_RAM_HACK; - } - - gstate_c.featureFlags = features; + return features; } GPU_DX9::~GPU_DX9() { @@ -261,7 +239,7 @@ void GPU_DX9::BeginHostFrame() { GPUCommon::BeginHostFrame(); UpdateCmdInfo(); if (resized_) { - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); framebufferManager_->Resized(); drawEngine_.Resized(); shaderManagerDX9_->DirtyShader(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 0e313da397..7c6a88d180 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -35,7 +35,7 @@ public: GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_DX9(); - void CheckGPUFeatures() override; + u32 CheckGPUFeatures() const override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 75fd0080b5..7d9ce963a3 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -54,7 +54,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) { UpdateVsyncInterval(true); - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); shaderManagerGL_ = new ShaderManagerGLES(draw); framebufferManagerGL_ = new FramebufferManagerGLES(draw); @@ -148,17 +148,11 @@ GPU_GLES::~GPU_GLES() { // Take the raw GL extension and versioning data and turn into feature flags. // TODO: This should use DrawContext::GetDeviceCaps() more and more, and eventually // this can be shared between all the backends. -void GPU_GLES::CheckGPUFeatures() { - u32 features = 0; +u32 GPU_GLES::CheckGPUFeatures() const { + u32 features = GPUCommon::CheckGPUFeatures(); features |= GPU_SUPPORTS_16BIT_FORMATS; - if (draw_->GetDeviceCaps().dualSourceBlend) { - if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - } - } - if (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch) { // This has caused problems in the past. Let's only enable on GLES3. if (gl_extensions.GLES3) { @@ -169,15 +163,6 @@ void GPU_GLES::CheckGPUFeatures() { if ((gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA) || (gl_extensions.gpuVendor == GPU_VENDOR_AMD)) features |= GPU_PREFER_REVERSE_COLOR_ORDER; - if (draw_->GetDeviceCaps().textureNPOTFullySupported) - features |= GPU_SUPPORTS_TEXTURE_NPOT; - - if (gl_extensions.EXT_blend_minmax) - features |= GPU_SUPPORTS_BLEND_MINMAX; - - if (draw_->GetDeviceCaps().logicOpSupported) - features |= GPU_SUPPORTS_LOGIC_OP; - if (gl_extensions.GLES3 || !gl_extensions.IsGLES) features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; @@ -245,11 +230,7 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_USE_DEPTH_RANGE_HACK; } - if (PSP_CoreParameter().compat.flags().ClearToRAM) { - features |= GPU_USE_CLEAR_RAM_HACK; - } - - gstate_c.featureFlags = features; + return features; } bool GPU_GLES::IsReady() { @@ -321,7 +302,7 @@ void GPU_GLES::BeginHostFrame() { GPUCommon::BeginHostFrame(); UpdateCmdInfo(); if (resized_) { - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); framebufferManager_->Resized(); drawEngine_.Resized(); shaderManagerGL_->DirtyShader(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index cbe6bc00b0..98bb1d9362 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -38,7 +38,7 @@ public: ~GPU_GLES(); // This gets called on startup and when we get back from settings. - void CheckGPUFeatures() override; + u32 CheckGPUFeatures() const override; bool IsReady() override; void CancelReady() override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 6d73d1d532..ea63b7a02b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3153,3 +3153,30 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { vertexAverageCycles ); } + +u32 GPUCommon::CheckGPUFeatures() const { + u32 features = 0; + if (draw_->GetDeviceCaps().logicOpSupported) { + features |= GPU_SUPPORTS_LOGIC_OP; + } + if (draw_->GetDeviceCaps().anisoSupported) { + features |= GPU_SUPPORTS_ANISOTROPY; + } + if (draw_->GetDeviceCaps().textureNPOTFullySupported) { + features |= GPU_SUPPORTS_TEXTURE_NPOT; + } + if (draw_->GetDeviceCaps().dualSourceBlend) { + if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { + features |= GPU_SUPPORTS_DUALSOURCE_BLEND; + } + } + if (draw_->GetDeviceCaps().blendMinMaxSupported) { + features |= GPU_SUPPORTS_BLEND_MINMAX; + } + + if (PSP_CoreParameter().compat.flags().ClearToRAM) { + features |= GPU_USE_CLEAR_RAM_HACK; + } + + return features; +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index cddb1ccdc1..1127e38d91 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -76,7 +76,7 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } - virtual void CheckGPUFeatures() = 0; + virtual u32 CheckGPUFeatures() const; void UpdateCmdInfo(); diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 3ce69dcc18..e90f7c0fb8 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -127,7 +127,7 @@ public: SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~SoftGPU(); - void CheckGPUFeatures() override {} + u32 CheckGPUFeatures() const override { return 0; } void InitClear() override {} void ExecuteOp(u32 op, u32 diff) override; void FinishDeferred() override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index eed7c8b9d5..636f852666 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -52,7 +52,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), drawEngine_(draw) { - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); VulkanContext *vulkan = (VulkanContext *)gfxCtx->GetAPIContext(); @@ -182,8 +182,8 @@ GPU_Vulkan::~GPU_Vulkan() { delete framebufferManagerVulkan_; } -void GPU_Vulkan::CheckGPUFeatures() { - uint32_t features = 0; +u32 GPU_Vulkan::CheckGPUFeatures() const { + uint32_t features = GPUCommon::CheckGPUFeatures(); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); switch (vulkan->GetPhysicalDeviceProperties().properties.vendorID) { @@ -222,8 +222,6 @@ void GPU_Vulkan::CheckGPUFeatures() { // Mandatory features on Vulkan, which may be checked in "centralized" code features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; - features |= GPU_SUPPORTS_BLEND_MINMAX; - features |= GPU_SUPPORTS_TEXTURE_NPOT; features |= GPU_SUPPORTS_INSTANCE_RENDERING; features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH; features |= GPU_SUPPORTS_TEXTURE_FLOAT; @@ -254,17 +252,6 @@ void GPU_Vulkan::CheckGPUFeatures() { features |= GPU_SUPPORTS_VS_RANGE_CULLING; } } - if (enabledFeatures.dualSrcBlend) { - if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - } - } - if (draw_->GetDeviceCaps().logicOpSupported) { - features |= GPU_SUPPORTS_LOGIC_OP; - } - if (draw_->GetDeviceCaps().anisoSupported) { - features |= GPU_SUPPORTS_ANISOTROPY; - } // These are VULKAN_4444_FORMAT and friends. uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16); @@ -280,10 +267,6 @@ void GPU_Vulkan::CheckGPUFeatures() { INFO_LOG(G3D, "Deficient texture format support: 4444: %d 1555: %d 565: %d", fmt4444, fmt1555, fmt565); } - if (PSP_CoreParameter().compat.flags().ClearToRAM) { - features |= GPU_USE_CLEAR_RAM_HACK; - } - if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } @@ -295,7 +278,7 @@ void GPU_Vulkan::CheckGPUFeatures() { features |= GPU_ROUND_DEPTH_TO_16BIT; } - gstate_c.featureFlags = features; + return features; } void GPU_Vulkan::BeginHostFrame() { @@ -303,7 +286,7 @@ void GPU_Vulkan::BeginHostFrame() { UpdateCmdInfo(); if (resized_) { - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); // In case the GPU changed. BuildReportingInfo(); framebufferManager_->Resized(); @@ -542,7 +525,7 @@ void GPU_Vulkan::DeviceRestore() { GPUCommon::DeviceRestore(); InitDeviceObjects(); - CheckGPUFeatures(); + gstate_c.featureFlags = CheckGPUFeatures(); BuildReportingInfo(); UpdateCmdInfo(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 3c13d57621..3fbd329aae 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -38,7 +38,7 @@ public: ~GPU_Vulkan(); // This gets called on startup and when we get back from settings. - void CheckGPUFeatures() override; + u32 CheckGPUFeatures() const override; bool IsReady() override; void CancelReady() override; From 09bcf3ec13064608ff14feb06d404de4ab38e38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 Sep 2022 10:15:04 +0200 Subject: [PATCH 2/3] Unify range culling detection --- Common/GPU/D3D9/thin3d_d3d9.cpp | 72 +++++++++++++++++++++++++++++++ GPU/D3D11/GPU_D3D11.cpp | 13 ------ GPU/Directx9/GPU_DX9.cpp | 75 --------------------------------- GPU/GLES/GPU_GLES.cpp | 16 ------- GPU/GPUCommon.cpp | 18 ++++++++ GPU/Vulkan/GPU_Vulkan.cpp | 16 ------- 6 files changed, 90 insertions(+), 120 deletions(-) diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 502d2c06db..bf33fd34ca 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -646,6 +646,63 @@ void D3D9Context::InvalidateCachedState() { curPipeline_ = nullptr; } +// TODO: Move this detection elsewhere when it's needed elsewhere, not before. It's ugly. +// Source: https://envytools.readthedocs.io/en/latest/hw/pciid.html#gf100 +enum NVIDIAGeneration { + NV_PRE_KEPLER, + NV_KEPLER, + NV_MAXWELL, + NV_PASCAL, + NV_VOLTA, + NV_TURING, // or later +}; + +static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) { + if (deviceID >= 0x1180 && deviceID <= 0x11bf) + return NV_KEPLER; // GK104 + if (deviceID >= 0x11c0 && deviceID <= 0x11fa) + return NV_KEPLER; // GK106 + if (deviceID >= 0x0fc0 && deviceID <= 0x0fff) + return NV_KEPLER; // GK107 + if (deviceID >= 0x1003 && deviceID <= 0x1028) + return NV_KEPLER; // GK110(B) + if (deviceID >= 0x1280 && deviceID <= 0x12ba) + return NV_KEPLER; // GK208 + if (deviceID >= 0x1381 && deviceID <= 0x13b0) + return NV_MAXWELL; // GM107 + if (deviceID >= 0x1340 && deviceID <= 0x134d) + return NV_MAXWELL; // GM108 + if (deviceID >= 0x13c0 && deviceID <= 0x13d9) + return NV_MAXWELL; // GM204 + if (deviceID >= 0x1401 && deviceID <= 0x1427) + return NV_MAXWELL; // GM206 + if (deviceID >= 0x15f7 && deviceID <= 0x15f9) + return NV_PASCAL; // GP100 + if (deviceID >= 0x15f7 && deviceID <= 0x15f9) + return NV_PASCAL; // GP100 + if (deviceID >= 0x1b00 && deviceID <= 0x1b38) + return NV_PASCAL; // GP102 + if (deviceID >= 0x1b80 && deviceID <= 0x1be1) + return NV_PASCAL; // GP104 + if (deviceID >= 0x1c02 && deviceID <= 0x1c62) + return NV_PASCAL; // GP106 + if (deviceID >= 0x1c81 && deviceID <= 0x1c92) + return NV_PASCAL; // GP107 + if (deviceID >= 0x1d01 && deviceID <= 0x1d12) + return NV_PASCAL; // GP108 + if (deviceID >= 0x1d81 && deviceID <= 0x1dba) + return NV_VOLTA; // GV100 + if (deviceID >= 0x1e02 && deviceID <= 0x1e3c) + return NV_TURING; // TU102 + if (deviceID >= 0x1e82 && deviceID <= 0x1ed0) + return NV_TURING; // TU104 + if (deviceID >= 0x1f02 && deviceID <= 0x1f51) + return NV_TURING; // TU104 + if (deviceID >= 0x1e02) + return NV_TURING; // More TU models or later, probably. + return NV_PRE_KEPLER; +} + #define FB_DIV 1 #define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))) @@ -704,6 +761,21 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.textureNPOTFullySupported = true; } + // VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel. + // Also causes problems on old NVIDIA. + switch (caps_.vendor) { + case Draw::GPUVendor::VENDOR_INTEL: + bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL); + break; + case Draw::GPUVendor::VENDOR_NVIDIA: + // Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders. + // No idea if KEPLER is the right cutoff, but let's go with it. + if (NVIDIAGetDeviceGeneration(caps_.deviceID) < NV_KEPLER) { + bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL); + } + break; + } + if (d3d) { D3DDISPLAYMODE displayMode; d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index bd4d131e98..a5a35e3c12 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -111,19 +111,6 @@ u32 GPU_D3D11::CheckGPUFeatures() const { features |= GPU_SUPPORTS_DEPTH_TEXTURE; if (draw_->GetDeviceCaps().depthClampSupported) features |= GPU_SUPPORTS_DEPTH_CLAMP; - if (draw_->GetDeviceCaps().clipDistanceSupported) - features |= GPU_SUPPORTS_CLIP_DISTANCE; - if (draw_->GetDeviceCaps().cullDistanceSupported) - features |= GPU_SUPPORTS_CULL_DISTANCE; - if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { - // Ignore the compat setting if clip and cull are both enabled. - // When supported, we can do the depth side of range culling more correctly. - const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported; - const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling; - if (supported || !disabled) { - features |= GPU_SUPPORTS_VS_RANGE_CULLING; - } - } features |= GPU_SUPPORTS_TEXTURE_FLOAT; features |= GPU_SUPPORTS_INSTANCE_RENDERING; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 0ec02a3595..f11286a29d 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -98,63 +98,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } } -// TODO: Move this detection elsewhere when it's needed elsewhere, not before. It's ugly. -// Source: https://envytools.readthedocs.io/en/latest/hw/pciid.html#gf100 -enum NVIDIAGeneration { - NV_PRE_KEPLER, - NV_KEPLER, - NV_MAXWELL, - NV_PASCAL, - NV_VOLTA, - NV_TURING, // or later -}; - -static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) { - if (deviceID >= 0x1180 && deviceID <= 0x11bf) - return NV_KEPLER; // GK104 - if (deviceID >= 0x11c0 && deviceID <= 0x11fa) - return NV_KEPLER; // GK106 - if (deviceID >= 0x0fc0 && deviceID <= 0x0fff) - return NV_KEPLER; // GK107 - if (deviceID >= 0x1003 && deviceID <= 0x1028) - return NV_KEPLER; // GK110(B) - if (deviceID >= 0x1280 && deviceID <= 0x12ba) - return NV_KEPLER; // GK208 - if (deviceID >= 0x1381 && deviceID <= 0x13b0) - return NV_MAXWELL; // GM107 - if (deviceID >= 0x1340 && deviceID <= 0x134d) - return NV_MAXWELL; // GM108 - if (deviceID >= 0x13c0 && deviceID <= 0x13d9) - return NV_MAXWELL; // GM204 - if (deviceID >= 0x1401 && deviceID <= 0x1427) - return NV_MAXWELL; // GM206 - if (deviceID >= 0x15f7 && deviceID <= 0x15f9) - return NV_PASCAL; // GP100 - if (deviceID >= 0x15f7 && deviceID <= 0x15f9) - return NV_PASCAL; // GP100 - if (deviceID >= 0x1b00 && deviceID <= 0x1b38) - return NV_PASCAL; // GP102 - if (deviceID >= 0x1b80 && deviceID <= 0x1be1) - return NV_PASCAL; // GP104 - if (deviceID >= 0x1c02 && deviceID <= 0x1c62) - return NV_PASCAL; // GP106 - if (deviceID >= 0x1c81 && deviceID <= 0x1c92) - return NV_PASCAL; // GP107 - if (deviceID >= 0x1d01 && deviceID <= 0x1d12) - return NV_PASCAL; // GP108 - if (deviceID >= 0x1d81 && deviceID <= 0x1dba) - return NV_VOLTA; // GV100 - if (deviceID >= 0x1e02 && deviceID <= 0x1e3c) - return NV_TURING; // TU102 - if (deviceID >= 0x1e82 && deviceID <= 0x1ed0) - return NV_TURING; // TU104 - if (deviceID >= 0x1f02 && deviceID <= 0x1f51) - return NV_TURING; // TU104 - if (deviceID >= 0x1e02) - return NV_TURING; // More TU models or later, probably. - return NV_PRE_KEPLER; -} - u32 GPU_DX9::CheckGPUFeatures() const { u32 features = GPUCommon::CheckGPUFeatures(); features |= GPU_SUPPORTS_16BIT_FORMATS; @@ -167,24 +110,6 @@ u32 GPU_DX9::CheckGPUFeatures() const { features |= GPU_SUPPORTS_ACCURATE_DEPTH; auto vendor = draw_->GetDeviceCaps().vendor; - if (!PSP_CoreParameter().compat.flags().DisableRangeCulling) { - // VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel. - // Also causes problems on old NVIDIA. - switch (vendor) { - case Draw::GPUVendor::VENDOR_INTEL: - break; - case Draw::GPUVendor::VENDOR_NVIDIA: - // Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders. - // No idea if KEPLER is the right cutoff, but let's go with it. - if (NVIDIAGetDeviceGeneration(draw_->GetDeviceCaps().deviceID) >= NV_KEPLER) { - features |= GPU_SUPPORTS_VS_RANGE_CULLING; - } - break; - default: - features |= GPU_SUPPORTS_VS_RANGE_CULLING; - break; - } - } if (!g_Config.bHighQualityDepth) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 7d9ce963a3..d394407721 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -166,9 +166,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { if (gl_extensions.GLES3 || !gl_extensions.IsGLES) features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; - if (draw_->GetDeviceCaps().anisoSupported) - features |= GPU_SUPPORTS_ANISOTROPY; - bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced; bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4 || gl_extensions.VersionGEThan(3, 1); bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID); @@ -189,19 +186,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { } if (draw_->GetDeviceCaps().textureDepthSupported) features |= GPU_SUPPORTS_DEPTH_TEXTURE; - if (draw_->GetDeviceCaps().clipDistanceSupported) - features |= GPU_SUPPORTS_CLIP_DISTANCE; - if (draw_->GetDeviceCaps().cullDistanceSupported) - features |= GPU_SUPPORTS_CULL_DISTANCE; - if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { - // Ignore the compat setting if clip and cull are both enabled. - // When supported, we can do the depth side of range culling more correctly. - const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported; - const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling; - if (supported || !disabled) { - features |= GPU_SUPPORTS_VS_RANGE_CULLING; - } - } // If we already have a 16-bit depth buffer, we don't need to round. bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index ea63b7a02b..a3f1d5cd7d 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3174,6 +3174,24 @@ u32 GPUCommon::CheckGPUFeatures() const { features |= GPU_SUPPORTS_BLEND_MINMAX; } + if (draw_->GetDeviceCaps().clipDistanceSupported) { + features |= GPU_SUPPORTS_CLIP_DISTANCE; + } + + if (draw_->GetDeviceCaps().cullDistanceSupported) { + features |= GPU_SUPPORTS_CULL_DISTANCE; + } + + if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { + // Ignore the compat setting if clip and cull are both enabled. + // When supported, we can do the depth side of range culling more correctly. + const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported; + const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling; + if (supported || !disabled) { + features |= GPU_SUPPORTS_VS_RANGE_CULLING; + } + } + if (PSP_CoreParameter().compat.flags().ClearToRAM) { features |= GPU_USE_CLEAR_RAM_HACK; } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 636f852666..1dca91ddcd 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -236,22 +236,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { if (enabledFeatures.depthClamp) { features |= GPU_SUPPORTS_DEPTH_CLAMP; } - if (enabledFeatures.shaderClipDistance) { - features |= GPU_SUPPORTS_CLIP_DISTANCE; - } - if (enabledFeatures.shaderCullDistance) { - // Must support at least 8 if feature supported, so we're fine. - features |= GPU_SUPPORTS_CULL_DISTANCE; - } - if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { - // Ignore the compat setting if clip and cull are both enabled. - // When supported, we can do the depth side of range culling more correctly. - const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported; - const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling; - if (supported || !disabled) { - features |= GPU_SUPPORTS_VS_RANGE_CULLING; - } - } // These are VULKAN_4444_FORMAT and friends. uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16); From aa19712fc3e718f843d7f91402dbb9db27ba5711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 Sep 2022 10:47:49 +0200 Subject: [PATCH 3/3] Unify depth texture and framebuffer fetch checks --- Common/GPU/OpenGL/thin3d_gl.cpp | 4 +++- GPU/D3D11/GPU_D3D11.cpp | 1 - GPU/Directx9/GPU_DX9.cpp | 1 - GPU/GLES/GPU_GLES.cpp | 9 --------- GPU/GPUCommon.cpp | 8 ++++++++ GPU/Vulkan/GPU_Vulkan.cpp | 6 ------ 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index dfe7f95c6f..02decfe05c 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -713,8 +713,10 @@ OpenGLContext::OpenGLContext() { } } - if (gl_extensions.IsGLES) { + // NOTE: We only support framebuffer fetch on ES3 due to past issues.. + if (gl_extensions.IsGLES && gl_extensions.GLES3) { caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch); + if (gl_extensions.EXT_shader_framebuffer_fetch) { shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; shaderLanguageDesc_.lastFragData = gl_extensions.GLES3 ? "fragColor0" : "gl_LastFragData[0]"; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index a5a35e3c12..bfbd12f190 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -108,7 +108,6 @@ u32 GPU_D3D11::CheckGPUFeatures() const { // TODO: Breaks text in PaRappa for some reason? features |= GPU_SUPPORTS_ACCURATE_DEPTH; - features |= GPU_SUPPORTS_DEPTH_TEXTURE; if (draw_->GetDeviceCaps().depthClampSupported) features |= GPU_SUPPORTS_DEPTH_CLAMP; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index f11286a29d..075d89e460 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -101,7 +101,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) u32 GPU_DX9::CheckGPUFeatures() const { u32 features = GPUCommon::CheckGPUFeatures(); features |= GPU_SUPPORTS_16BIT_FORMATS; - features |= GPU_SUPPORTS_DEPTH_TEXTURE; features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; // Accurate depth is required because the Direct3D API does not support inverse Z. diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index d394407721..abae5134f9 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -153,13 +153,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_SUPPORTS_16BIT_FORMATS; - if (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch) { - // This has caused problems in the past. Let's only enable on GLES3. - if (gl_extensions.GLES3) { - features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH; - } - } - if ((gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA) || (gl_extensions.gpuVendor == GPU_VENDOR_AMD)) features |= GPU_PREFER_REVERSE_COLOR_ORDER; @@ -184,8 +177,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { // Our implementation of depth texturing needs simple Z range, so can't // use the extension hacks (yet). } - if (draw_->GetDeviceCaps().textureDepthSupported) - features |= GPU_SUPPORTS_DEPTH_TEXTURE; // If we already have a 16-bit depth buffer, we don't need to round. bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a3f1d5cd7d..3d64bdb1ab 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3182,6 +3182,10 @@ u32 GPUCommon::CheckGPUFeatures() const { features |= GPU_SUPPORTS_CULL_DISTANCE; } + if (draw_->GetDeviceCaps().textureDepthSupported) { + features |= GPU_SUPPORTS_DEPTH_TEXTURE; + } + if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { // Ignore the compat setting if clip and cull are both enabled. // When supported, we can do the depth side of range culling more correctly. @@ -3192,6 +3196,10 @@ u32 GPUCommon::CheckGPUFeatures() const { } } + if (draw_->GetDeviceCaps().framebufferFetchSupported) { + features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH; + } + if (PSP_CoreParameter().compat.flags().ClearToRAM) { features |= GPU_USE_CLEAR_RAM_HACK; } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 1dca91ddcd..b38201c8c5 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -225,12 +225,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { features |= GPU_SUPPORTS_INSTANCE_RENDERING; features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH; features |= GPU_SUPPORTS_TEXTURE_FLOAT; - features |= GPU_SUPPORTS_DEPTH_TEXTURE; - - // through input attachments, when not broken. - if (draw_->GetDeviceCaps().framebufferFetchSupported) { - features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH; - } auto &enabledFeatures = vulkan->GetDeviceFeatures().enabled; if (enabledFeatures.depthClamp) {