From 632af8d723ad4125ad5fbc6b576fbac4478a1ad3 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 8 Jul 2020 23:47:40 +0300 Subject: [PATCH] rsx: Support partial texture descriptors - It is safe to declare w > pitch and it works as long as sampling inside the legal 2D area is obeyed. --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 33 ++++++++++++++++++------ rpcs3/Emu/RSX/Common/texture_cache.h | 36 ++++++++++++++++----------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 81cab0e735..e96579880d 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -457,7 +457,8 @@ std::vector get_subresources_layout_impl(const RsxTextur std::tie(h, depth, layer) = get_height_depth_layer(texture); - int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + const auto format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + const auto pitch = texture.pitch(); const u32 texaddr = rsx::get_address(texture.offset(), texture.location(), HERE); auto pixels = vm::_ptr(texaddr); @@ -465,10 +466,26 @@ std::vector get_subresources_layout_impl(const RsxTextur const bool is_swizzled = !(texture.format() & CELL_GCM_TEXTURE_LN); const bool has_border = !texture.border_type(); + if (!is_swizzled) + { + if (pitch) [[likely]] + { + if (pitch < get_format_packed_pitch(format, w, has_border, false)) + { + const u32 real_width_in_block = pitch / get_format_block_size_in_bytes(format); + w = std::max(real_width_in_block * get_format_block_size_in_texel(format), 1); + } + } + else + { + w = h = depth = 1; + } + } + switch (format) { case CELL_GCM_TEXTURE_B8: - return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, has_border); + return get_subresources_layout_impl<1, u8>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, has_border); case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: case CELL_GCM_TEXTURE_COMPRESSED_HILO8: @@ -483,7 +500,7 @@ std::vector get_subresources_layout_impl(const RsxTextur case CELL_GCM_TEXTURE_R6G5B5: case CELL_GCM_TEXTURE_G8B8: case CELL_GCM_TEXTURE_X16: - return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, has_border); + return get_subresources_layout_impl<1, u16>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, has_border); case CELL_GCM_TEXTURE_DEPTH24_D8: // Untested case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // Untested case CELL_GCM_TEXTURE_D8R8G8B8: @@ -491,16 +508,16 @@ std::vector get_subresources_layout_impl(const RsxTextur case CELL_GCM_TEXTURE_Y16_X16: case CELL_GCM_TEXTURE_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_X32_FLOAT: - return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, has_border); + return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, has_border); case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: - return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, has_border); + return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, has_border); case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: - return get_subresources_layout_impl<1, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, has_border); + return get_subresources_layout_impl<1, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, has_border); case CELL_GCM_TEXTURE_COMPRESSED_DXT1: - return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, false); + return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, false); 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.get_exact_mipmap_count(), texture.pitch(), !is_swizzled, false); + return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), pitch, !is_swizzled, false); } fmt::throw_exception("Wrong format 0x%x" HERE, format); } diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 679986d4e6..d87ef4aa65 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -1731,17 +1731,36 @@ namespace rsx u8 subsurface_count; size2f scale{ 1.f, 1.f }; + if (is_unnormalized) + { + if (extended_dimension <= rsx::texture_dimension_extended::texture_dimension_2d) + { + scale.width /= attributes.width; + scale.height /= attributes.height; + } + else + { + rsx_log.error("Unimplemented unnormalized sampling for texture type %d", static_cast(extended_dimension)); + } + } + + const auto packed_pitch = get_format_packed_pitch(attributes.gcm_format, attributes.width, !tex.border_type(), is_swizzled); if (!is_swizzled) [[likely]] { if (attributes.pitch = tex.pitch(); !attributes.pitch) { - attributes.pitch = get_format_packed_pitch(attributes.gcm_format, attributes.width, !tex.border_type(), false); + attributes.pitch = packed_pitch; scale = { 0.f, 0.f }; } + else if (packed_pitch > attributes.pitch && !options.is_compressed_format) + { + scale.width *= f32(packed_pitch) / attributes.pitch; + attributes.width = attributes.pitch / attributes.bpp; + } } else { - attributes.pitch = get_format_packed_pitch(attributes.gcm_format, attributes.width, !tex.border_type(), true); + attributes.pitch = packed_pitch; } switch (extended_dimension) @@ -1774,19 +1793,6 @@ namespace rsx break; } - if (is_unnormalized) - { - if (extended_dimension <= rsx::texture_dimension_extended::texture_dimension_2d) - { - scale.width /= attributes.width; - scale.height /= attributes.height; - } - else - { - rsx_log.error("Unimplemented unnormalized sampling for texture type %d", static_cast(extended_dimension)); - } - } - if (options.is_compressed_format) { // Compressed textures cannot be 1D in some APIs