From 5bdb34521d64807bb8b357a502af93397a4320cb Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 11 Jan 2022 20:01:31 +1000 Subject: [PATCH] GS/HW: Add a field for LOD clamp to sampler This way SampleLevel for manual LOD doesn't get clamped. --- pcsx2/GS/Renderers/Common/GSDevice.h | 21 ++++++--------------- pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp | 2 +- pcsx2/GS/Renderers/HW/GSRendererNew.cpp | 4 ++++ pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp | 4 ++-- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h | 2 +- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 4 +++- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index b43457fd32..7d70b32c92 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -269,13 +269,12 @@ struct alignas(16) GSHWDrawConfig { struct { - u8 tau : 1; - u8 tav : 1; - u8 biln : 1; - u8 triln : 3; - u8 aniso : 1; - - u8 _free : 1; + u8 tau : 1; + u8 tav : 1; + u8 biln : 1; + u8 triln : 3; + u8 aniso : 1; + u8 lodclamp : 1; }; u8 key; }; @@ -317,14 +316,6 @@ struct alignas(16) GSHWDrawConfig return (triln == static_cast(GS_MIN_FILTER::Nearest_Mipmap_Linear) || triln == static_cast(GS_MIN_FILTER::Linear_Mipmap_Linear)); } - - /// Returns the maximum LOD for this sampler (0 if mipmapping is disabled). - __fi float GetMaxLOD() const - { - // See https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html#_description - // for the reasoning behind 0.25f here. - return triln >= static_cast(GS_MIN_FILTER::Nearest_Mipmap_Nearest) ? 1000.0f : 0.25f; - } }; struct DepthStencilSelector { diff --git a/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp b/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp index 02e3b7c39e..3c45ad9675 100644 --- a/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp @@ -253,7 +253,7 @@ void GSDevice11::SetupPS(PSSelector sel, const GSHWDrawConfig::PSConstantBuffer* sd.AddressV = ssel.tav ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sd.MinLOD = 0.0f; - sd.MaxLOD = ssel.GetMaxLOD(); + sd.MaxLOD = ssel.lodclamp ? 0.0f : FLT_MAX; sd.MaxAnisotropy = std::clamp(anisotropy, 1, 16); sd.ComparisonFunc = D3D11_COMPARISON_NEVER; diff --git a/pcsx2/GS/Renderers/HW/GSRendererNew.cpp b/pcsx2/GS/Renderers/HW/GSRendererNew.cpp index 001a1f442f..c08327aa1d 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererNew.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererNew.cpp @@ -996,6 +996,10 @@ void GSRendererNew::EmulateTextureSampler(const GSTextureCache::Source* tex) } } + // clamp to base level if we're not providing or generating mipmaps + // manual trilinear causes the chain to be uploaded, auto causes it to be generated + m_conf.sampler.lodclamp = !(trilinear_manual || trilinear_auto); + m_conf.tex = tex->m_texture; m_conf.pal = tex->m_palette; } diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index 01c29f00b6..f849ea4038 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -879,8 +879,8 @@ GLuint GSDeviceOGL::CreateSampler(PSSamplerSelector sel) break; } - //glSamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, 0); - //glSamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, 6); + glSamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, -1000.0f); + glSamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, sel.lodclamp ? 0.0f : 1000.0f); if (sel.tau) glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_REPEAT); diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h index 402369195a..7f27492ec0 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h @@ -288,7 +288,7 @@ private: GLuint timer() { return timer_query[last_query]; } } m_profiler; - GLuint m_ps_ss[1 << 7]; + GLuint m_ps_ss[1 << 8]; GSDepthStencilOGL* m_om_dss[1 << 5]; std::unordered_map m_programs; GL::ShaderCache m_shader_cache; diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index af3d938c62..34c555d657 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -951,6 +951,8 @@ VkSampler GSDeviceVK::GetSampler(GSHWDrawConfig::SamplerSelector ss) const bool aniso = (ss.aniso && GSConfig.MaxAnisotropy > 1); + // See https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html#_description + // for the reasoning behind 0.25f here. const VkSamplerCreateInfo ci = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, nullptr, 0, ss.IsMinFilterLinear() ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, // min @@ -967,7 +969,7 @@ VkSampler GSDeviceVK::GetSampler(GSHWDrawConfig::SamplerSelector ss) VK_FALSE, // compare enable VK_COMPARE_OP_ALWAYS, // compare op 0.0f, // min lod - ss.GetMaxLOD(), // max lod + ss.lodclamp ? 0.25f : VK_LOD_CLAMP_NONE, // max lod VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // border VK_FALSE // unnormalized coordinates };