diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index c129acfe94..2b7f8366e2 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -152,7 +152,7 @@ std::vector get_subresources_layout(const rsx::texture & { case CELL_GCM_TEXTURE_D8R8G8B8: case CELL_GCM_TEXTURE_A8R8G8B8: - return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_D1R5G5B5: case CELL_GCM_TEXTURE_A1R5G5B5: @@ -160,16 +160,16 @@ std::vector get_subresources_layout(const rsx::texture & case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_R5G6B5: case CELL_GCM_TEXTURE_G8B8: - return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: - return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_COMPRESSED_DXT1: - return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT45: - return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_B8: - return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.mipmap(), texture.pitch(), !is_swizzled); + return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); } throw EXCEPTION("Wrong format %d", format); } diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index e638feec05..e46c87638f 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -70,6 +70,16 @@ namespace rsx return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff); } + bool texture::is_compressed_format() const + { + int texture_format = format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + if (texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT1 || + texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT23 || + texture_format == CELL_GCM_TEXTURE_COMPRESSED_DXT45) + return true; + return false; + } + u16 texture::mipmap() const { return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff); @@ -77,7 +87,14 @@ namespace rsx u16 texture::get_exact_mipmap_count() const { - u16 max_mipmap_count = static_cast(floor(log2(std::max(width(), height()))) + 1); + if (is_compressed_format()) + { + // OpenGL considers that highest mipmap level for DXTC format is when either width or height is 1 + // not both. Assume it's the same for others backend. + u16 max_mipmap_count = static_cast(floor(log2(std::min(width() / 4, height() / 4))) + 1); + return std::min(mipmap(), max_mipmap_count); + } + u16 max_mipmap_count = static_cast(floor(log2(std::max(width(), height()))) + 1) - 2; return std::min(mipmap(), max_mipmap_count); } diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index 724caad77a..15dacade91 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -21,6 +21,7 @@ namespace rsx u8 border_type() const; rsx::texture_dimension dimension() const; u8 format() const; + bool is_compressed_format() const; u16 mipmap() const; /** * mipmap() returns value from register which can be higher than the actual number of mipmap level.