From 4a367148e6e97f3a47f1393671995ff2515e914b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Nov 2022 08:04:47 -0800 Subject: [PATCH] GPU: Centralize more GPU_USE flags, like depth. --- Common/GPU/D3D11/thin3d_d3d11.cpp | 1 + GPU/D3D11/GPU_D3D11.cpp | 14 +---------- GPU/Directx9/GPU_DX9.cpp | 14 +---------- GPU/GLES/GPU_GLES.cpp | 40 +++++++++---------------------- GPU/GPUCommon.cpp | 29 ++++++++++++++++++++++ GPU/GPUCommon.h | 3 +++ GPU/Vulkan/GPU_Vulkan.cpp | 31 +++++------------------- 7 files changed, 52 insertions(+), 80 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 428e86fdb3..46713b53f3 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -261,6 +261,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.framebufferStencilBlitSupported = false; caps_.framebufferDepthCopySupported = true; caps_.framebufferSeparateDepthCopySupported = false; // Though could be emulated with a draw. + caps_.preferredDepthBufferFormat = DataFormat::D24_S8; caps_.textureDepthSupported = true; caps_.texture3DSupported = true; caps_.fragmentShaderInt32Supported = true; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 90fb480155..93793165ac 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -105,12 +105,8 @@ u32 GPU_D3D11::CheckGPUFeatures() const { // 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_USE_ACCURATE_DEPTH; - if (draw_->GetDeviceCaps().depthClampSupported) - features |= GPU_USE_DEPTH_CLAMP; - features |= GPU_USE_TEXTURE_FLOAT; features |= GPU_USE_INSTANCE_RENDERING; features |= GPU_USE_TEXTURE_LOD_CONTROL; @@ -122,20 +118,12 @@ u32 GPU_D3D11::CheckGPUFeatures() const { features |= GPU_USE_16BIT_FORMATS; } - if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - // The Phantasy Star hack :( if (PSP_CoreParameter().compat.flags().DepthRangeHack && (features & GPU_USE_ACCURATE_DEPTH) == 0) { features |= GPU_USE_DEPTH_RANGE_HACK; } - return features; + return CheckGPUFeaturesLate(features); } // Needs to be called on GPU thread, not reporting thread. diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index beb701796a..6d8926e0fe 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -105,21 +105,9 @@ u32 GPU_DX9::CheckGPUFeatures() const { // 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_USE_ACCURATE_DEPTH; - auto vendor = draw_->GetDeviceCaps().vendor; - - if (!g_Config.bHighQualityDepth) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - // Assume we always have a 24-bit depth buffer. - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - - return features; + return CheckGPUFeaturesLate(features); } GPU_DX9::~GPU_DX9() { diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8b71b2dce1..018cd0b6c5 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -173,35 +173,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { if (gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float) features |= GPU_USE_TEXTURE_FLOAT; - if (draw_->GetDeviceCaps().depthClampSupported) { - features |= GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH; - // Our implementation of depth texturing needs simple Z range, so can't - // use the extension hacks (yet). - } - - // If we already have a 16-bit depth buffer, we don't need to round. - bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; - bool prefer16 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D16; - if (!prefer16) { - if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - if (prefer24 && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - // Here we can simulate a 16 bit depth buffer by scaling. - // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (!gl_extensions.IsGLES || gl_extensions.GLES3) { - // Use fragment rounding on desktop and GLES3, most accurate. - features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; - } else { - // At least do vertex rounding if nothing else. - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - } - // The Phantasy Star hack :( if (PSP_CoreParameter().compat.flags().DepthRangeHack && (features & GPU_USE_ACCURATE_DEPTH) == 0) { features |= GPU_USE_DEPTH_RANGE_HACK; @@ -218,6 +189,17 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_USE_SINGLE_PASS_STEREO; } + features = CheckGPUFeaturesLate(features); + + // This is a bit ugly, but lets us reuse most of the depth logic in GPUCommon. + if (features & GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT) { + if (gl_extensions.IsGLES && !gl_extensions.GLES3) { + // Unsupported, switch to GPU_ROUND_DEPTH_TO_16BIT instead. + features &= ~GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; + features |= GPU_ROUND_DEPTH_TO_16BIT; + } + } + return features; } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 17de04fc52..67bd4566dc 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3336,6 +3336,11 @@ u32 GPUCommon::CheckGPUFeatures() const { features |= GPU_USE_DEPTH_TEXTURE; } + if (draw_->GetDeviceCaps().depthClampSupported) { + // Some backends always do GPU_USE_ACCURATE_DEPTH, but it's required for depth clamp. + features |= GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH; + } + bool canClipOrCull = draw_->GetDeviceCaps().clipDistanceSupported || draw_->GetDeviceCaps().cullDistanceSupported; bool canDiscardVertex = draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL); if (canClipOrCull || canDiscardVertex) { @@ -3357,3 +3362,27 @@ u32 GPUCommon::CheckGPUFeatures() const { return features; } + +u32 GPUCommon::CheckGPUFeaturesLate(u32 features) const { + // If we already have a 16-bit depth buffer, we don't need to round. + bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; + bool prefer16 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D16; + if (!prefer16) { + if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { + features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { + if (prefer24 && (features & GPU_USE_ACCURATE_DEPTH) != 0) { + // Here we can simulate a 16 bit depth buffer by scaling. + // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. + features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + } else { + // Use fragment rounding on where available otherwise. + features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; + } + } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { + features |= GPU_ROUND_DEPTH_TO_16BIT; + } + } + + return features; +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8823a52715..39519495c8 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -262,6 +262,9 @@ protected: void DeviceLost() override; void DeviceRestore() override; + // Add additional common features dependent on other features, which may be backend-determined. + u32 CheckGPUFeaturesLate(u32 features) const; + inline bool IsTrianglePrim(GEPrimitiveType prim) const { return prim != GE_PRIM_RECTANGLES && prim > GE_PRIM_LINE_STRIP; } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 17387c3e8b..4232e3f526 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -207,12 +207,16 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || driverTooOld) { features |= GPU_USE_ACCURATE_DEPTH; + } else { + features &= ~GPU_USE_ACCURATE_DEPTH; } break; } default: if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth) { features |= GPU_USE_ACCURATE_DEPTH; + } else { + features &= ~GPU_USE_ACCURATE_DEPTH; } break; } @@ -227,13 +231,8 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { features |= GPU_USE_VERTEX_TEXTURE_FETCH; features |= GPU_USE_TEXTURE_FLOAT; - auto &enabledFeatures = vulkan->GetDeviceFeatures().enabled.standard; - if (enabledFeatures.depthClamp) { - features |= GPU_USE_DEPTH_CLAMP; - } - // Fall back to geometry shader culling if we can't do vertex range culling. - if (enabledFeatures.geometryShader) { + if (draw_->GetDeviceCaps().geometryShaderSupported) { const bool useGeometry = g_Config.bUseGeometryShader && !draw_->GetBugs().Has(Draw::Bugs::GEOMETRY_SHADERS_SLOW_OR_BROKEN); const bool vertexSupported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported; if (useGeometry && (!vertexSupported || (features & GPU_USE_VS_RANGE_CULLING) == 0)) { @@ -257,24 +256,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { INFO_LOG(G3D, "Deficient texture format support: 4444: %d 1555: %d 565: %d", fmt4444, fmt1555, fmt565); } - bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; - bool prefer16 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D16; - if (!prefer16) { - if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - if (prefer24 && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - // Here we can simulate a 16 bit depth buffer by scaling. - // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else { - features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; - } - } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - } - if (g_Config.bStereoRendering && draw_->GetDeviceCaps().multiViewSupported) { features |= GPU_USE_SINGLE_PASS_STEREO; features |= GPU_USE_SIMPLE_STEREO_PERSPECTIVE; @@ -287,7 +268,7 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { } } - return features; + return CheckGPUFeaturesLate(features); } void GPU_Vulkan::BeginHostFrame() {