From 5af8a9fbbcba6e683a8a0a89ff733e548215a3e7 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 16 Oct 2019 23:21:30 +0300 Subject: [PATCH] rsx: Fix decoding of some fixed point texture parameters - Checked envydocs and found the correct format as fixed-point 4.8 with optional sign bit --- rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp | 4 ++-- rpcs3/Emu/RSX/GL/GLTexture.cpp | 8 ++++---- rpcs3/Emu/RSX/RSXTexture.cpp | 24 ++++++++++++------------ rpcs3/Emu/RSX/RSXTexture.h | 12 ++++++------ rpcs3/Emu/RSX/VK/VKGSRender.cpp | 8 ++++---- rpcs3/Emu/RSX/rsx_utils.h | 21 +++++++++++++++++++++ 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index f19a7b6df1..46d353f940 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -49,8 +49,8 @@ D3D12_SAMPLER_DESC get_sampler_desc(const rsx::fragment_texture &texture) samplerDesc.BorderColor[1] = (FLOAT)texture.border_color(); samplerDesc.BorderColor[2] = (FLOAT)texture.border_color(); samplerDesc.BorderColor[3] = (FLOAT)texture.border_color(); - samplerDesc.MinLOD = (FLOAT)(texture.min_lod() >> 8); - samplerDesc.MaxLOD = (FLOAT)(texture.max_lod() >> 8); + samplerDesc.MinLOD = (FLOAT)(texture.min_lod()); + samplerDesc.MaxLOD = (FLOAT)(texture.max_lod()); return samplerDesc; } diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index f97d01ca1f..d9701fccdd 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -259,8 +259,8 @@ namespace gl { set_parameteri(GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter())); set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias()); - set_parameteri(GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); - set_parameteri(GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); + set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod()); + set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod()); } const bool aniso_override = !g_cfg.video.strict_rendering_mode && g_cfg.video.anisotropic_level_override > 0; @@ -307,8 +307,8 @@ namespace gl set_parameteri(GL_TEXTURE_MIN_FILTER, GL_NEAREST); set_parameteri(GL_TEXTURE_MAG_FILTER, GL_NEAREST); set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias()); - set_parameteri(GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); - set_parameteri(GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); + set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod()); + set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod()); set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE); } diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index 63dc42bdeb..5b4762eb01 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -123,14 +123,14 @@ namespace rsx return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1); } - u16 fragment_texture::min_lod() const + f32 fragment_texture::min_lod() const { - return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff); + return rsx::decode_fx13((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff); } - u16 fragment_texture::max_lod() const + f32 fragment_texture::max_lod() const { - return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); + return rsx::decode_fx13((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); } rsx::texture_max_anisotropy fragment_texture::max_aniso() const @@ -211,9 +211,9 @@ namespace rsx return std::make_pair(remap_inputs, remap_lookup); } - float fragment_texture::bias() const + f32 fragment_texture::bias() const { - return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff)); + return rsx::decode_fx13((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); } rsx::texture_minify_filter fragment_texture::min_filter() const @@ -350,19 +350,19 @@ namespace rsx return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1); } - u16 vertex_texture::min_lod() const + f32 vertex_texture::min_lod() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff); + return rsx::decode_fx13((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff); } - u16 vertex_texture::max_lod() const + f32 vertex_texture::max_lod() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); + return rsx::decode_fx13((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); } - u16 vertex_texture::bias() const + f32 vertex_texture::bias() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); + return rsx::decode_fx13((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); } rsx::texture_minify_filter vertex_texture::min_filter() const diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index 0b6f273095..f9a420e722 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -48,8 +48,8 @@ namespace rsx // Control0 bool enabled() const; - u16 min_lod() const; - u16 max_lod() const; + f32 min_lod() const; + f32 max_lod() const; rsx::texture_max_anisotropy max_aniso() const; bool alpha_kill_enabled() const; @@ -65,7 +65,7 @@ namespace rsx std::pair, std::array> decoded_remap() const; // Filter - float bias() const; + f32 bias() const; rsx::texture_minify_filter min_filter() const; rsx::texture_magnify_filter mag_filter() const; u8 convolution_filter() const; @@ -115,11 +115,11 @@ namespace rsx // Control0 bool enabled() const; - u16 min_lod() const; - u16 max_lod() const; + f32 min_lod() const; + f32 max_lod() const; // Filter - u16 bias() const; + f32 bias() const; rsx::texture_minify_filter min_filter() const; rsx::texture_magnify_filter mag_filter() const; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 1a21877465..6c402c9c05 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1348,8 +1348,8 @@ void VKGSRender::end() if (rsx::method_registers.fragment_textures[i].get_exact_mipmap_count() > 1) { - min_lod = (float)(rsx::method_registers.fragment_textures[i].min_lod() >> 8); - max_lod = (float)(rsx::method_registers.fragment_textures[i].max_lod() >> 8); + min_lod = rsx::method_registers.fragment_textures[i].min_lod(); + max_lod = rsx::method_registers.fragment_textures[i].max_lod(); lod_bias = rsx::method_registers.fragment_textures[i].bias(); f32 actual_mipmaps; @@ -1425,8 +1425,8 @@ void VKGSRender::end() bool replace = !vs_sampler_handles[i]; const VkBool32 unnormalized_coords = !!(rsx::method_registers.vertex_textures[i].format() & CELL_GCM_TEXTURE_UN); - const auto min_lod = (f32)rsx::method_registers.vertex_textures[i].min_lod(); - const auto max_lod = (f32)rsx::method_registers.vertex_textures[i].max_lod(); + const auto min_lod = rsx::method_registers.vertex_textures[i].min_lod(); + const auto max_lod = rsx::method_registers.vertex_textures[i].max_lod(); const auto border_color = vk::get_border_color(rsx::method_registers.vertex_textures[i].border_color()); if (vs_sampler_handles[i]) diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 78170b1edc..e77d2b17dc 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -752,6 +752,27 @@ namespace rsx return result; } + static inline f32 decode_fx13(u32 bits) + { + // Classic fixed point, see PGRAPH section of nouveau docs for TEX_FILTER (lod_bias) and TEX_CONTROL (min_lod, max_lod) + // Technically min/max lod are fixed 4.8 but a 5.8 decoder should work just as well since sign bit is 0 + + if ((bits & (1 << 12)) == 0) + { + const auto integral = f32(bits >> 8); + const auto fractional = (bits & 0xff) / 256.f; + return integral + fractional; + } + else + { + // Negative sign bit + bits = (~bits + 1) & 0x1fff; + const auto integral = -f32(bits >> 8); + const auto fractional = (bits & 0xff) / 256.f; + return integral - fractional; + } + } + template void unpack_bitset(std::bitset& block, u64* values) {