From 900c373e0548a4fa21baec94412242acddd292e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 8 Aug 2022 12:07:50 +0200 Subject: [PATCH] Fix feature checks --- Common/GPU/D3D11/thin3d_d3d11.cpp | 1 + Common/GPU/D3D9/thin3d_d3d9.cpp | 1 + Common/GPU/OpenGL/thin3d_gl.cpp | 7 +++++++ Common/GPU/Vulkan/thin3d_vulkan.cpp | 1 + Common/GPU/thin3d.h | 1 + GPU/Common/Draw2D.cpp | 23 +++++++++++++++++++---- GPU/Common/FramebufferManagerCommon.cpp | 13 +++++++++++-- 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 2448d8996e0f..90bec0ecfe93 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -269,6 +269,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.fragmentShaderInt32Supported = true; caps_.anisoSupported = true; caps_.textureNPOTFullySupported = true; + caps_.fragmentShaderDepthWriteSupported = 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 10fa3beb44c9..7b2fa934b030 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -669,6 +669,7 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.framebufferSeparateDepthCopySupported = false; caps_.texture3DSupported = true; caps_.textureNPOTFullySupported = true; + caps_.fragmentShaderDepthWriteSupported = true; if (d3d) { D3DDISPLAYMODE displayMode; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 7a17b3a036e1..3088abc22f05 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -560,6 +560,13 @@ OpenGLContext::OpenGLContext() { gl_extensions.IsCoreContext || gl_extensions.GLES3 || gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot; + if (gl_extensions.IsGLES) { + caps_.fragmentShaderDepthWriteSupported = gl_extensions.GLES3; + // There's also GL_EXT_frag_depth but it's rare along with 2.0. Most chips that support it are simply 3.0 chips. + } else { + caps_.fragmentShaderDepthWriteSupported = true; + } + // Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader): // This will induce a performance penalty on many architectures though so a blanket enable of this // is probably not a good idea. diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index c1d05acb385f..3cceb9c84632 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -793,6 +793,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) caps_.texture3DSupported = true; caps_.fragmentShaderInt32Supported = true; caps_.textureNPOTFullySupported = true; + caps_.fragmentShaderDepthWriteSupported = true; auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties; switch (deviceProps.vendorID) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 6099c198a3c7..cbd5cafef128 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -541,6 +541,7 @@ struct DeviceCaps { bool texture3DSupported; bool fragmentShaderInt32Supported; bool textureNPOTFullySupported; + bool fragmentShaderDepthWriteSupported; std::string deviceName; // The device name to use when creating the thin3d context, to get the same one. }; diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 9c3ac27247e8..d75894999a7f 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -81,10 +81,16 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver GenerateDraw2DVS(vsCode, shaderLanguageDesc); draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); - draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); - _assert_(draw2DFs_ && draw2DVs_ && draw2DFsDepth_); + _assert_(draw2DFs_ && draw2DVs_); + + if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); + _assert_(draw2DFsDepth_); + } else { + draw2DFsDepth_ = nullptr; + } InputLayoutDesc desc = { { @@ -122,8 +128,13 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver { draw2DVs_, draw2DFsDepth_ }, inputLayout, depthWriteAlways, blendDiscard, rasterNoCull, nullptr, }; - draw2DPipelineDepth_ = draw_->CreateGraphicsPipeline(draw2DDepthPipelineDesc); - _assert_(draw2DPipelineDepth_); + + if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + draw2DPipelineDepth_ = draw_->CreateGraphicsPipeline(draw2DDepthPipelineDesc); + _assert_(draw2DPipelineDepth_); + } else { + draw2DPipelineDepth_ = nullptr; + } delete[] fsCode; delete[] vsCode; @@ -152,6 +163,10 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest); } + if (channel == RASTER_DEPTH && !draw2DPipelineDepth_) { + return; + } + draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_); if (tex) { draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 40e133048174..2d171bd08167 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -584,11 +584,16 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir bool useCopy = draw_->GetDeviceCaps().framebufferSeparateDepthCopySupported || (!draw_->GetDeviceCaps().framebufferDepthBlitSupported && draw_->GetDeviceCaps().framebufferCopySupported); bool useBlit = draw_->GetDeviceCaps().framebufferDepthBlitSupported; - // Attempt at optimization - if destination already bound, draw depth using raster + bool useRaster = draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported; + + // Could do an attempt at optimization - if destination already bound, draw depth using raster. + // Let's experiment later, commented out for now. Currently we fall back to raster as a last resort here. + /* if (currentRenderVfb_ == dst) { useCopy = false; useBlit = false; } + */ int w = std::min(src->renderWidth, dst->renderWidth); int h = std::min(src->renderHeight, dst->renderHeight); @@ -603,7 +608,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir // We'll accept whether we get a separate depth blit or not... draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebufferDepth"); RebindFramebuffer("After BlitFramebufferDepth"); - } else { + } else if (useRaster) { BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, RasterChannel::RASTER_DEPTH); } @@ -2688,6 +2693,10 @@ void FramebufferManagerCommon::BlitUsingRaster( bool linearFilter, RasterChannel channel) { + if (channel == RASTER_DEPTH) { + _dbg_assert_(draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported); + } + int destW, destH, srcW, srcH; draw_->GetFramebufferDimensions(src, &srcW, &srcH); draw_->GetFramebufferDimensions(dest, &destW, &destH);