diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 19:32:48 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 19:32:48 -0400 |
| commit | 2bd0285a383652b086f51ef779f083f0bce62670 (patch) | |
| tree | be36f7c4d86f893baeebbc3bc542a6009c4b9871 /src/video_core/texture_cache/util.cpp | |
| parent | dcf9ed1b33352a27fceef84c3cf9292424c658db (diff) | |
Texture cache: stop the churn, the per-frame image leak and garbage textures
- Unmapped GPU addresses get a stand-in CPU address fixed by the GPU
address. A fresh one per lookup meant FindImage never found an image
there again: title 1's bloom chain at 0xf0000-0x15b600 was re-created
on every use (~5,400 images per 600 frames), filling VRAM.
- ASTC whose blocks carry no alpha (exact endpoint-mode scan reusing the
decoder's block parsing) is re-compressed to BC1 instead of BC3, half
the size; about 70% of title 1's ASTC qualifies. Copies between BC1
and BC3 hosts are skipped (their guest data is uploaded instead).
EDEN_NX2_ASTC_BC1=0 turns it off.
- Deleting an image cancels every decode still queued for it. An image
re-decoded mid-decode has two; the first to finish cleared IsDecoding,
the second was not cancelled and was uploaded into the next image to
take the slot: garbage textures (the title logo, road patches) and a
staging overrun when that image was smaller.
- Diagnostics: images created and deleted per 600 frames by shape,
collector deletions, async decodes, BC1/BC3 split; collector
thresholds overridable (EDEN_NX2_TC_EXPECTED_MIB/CRITICAL_MIB); GPU
ASTC decode wait timing (EDEN_NX2_ASTC_FLUSH=1 submits without it).
Title 1 attract loop: device memory 4.8-5.1 GB instead of 5.9-6.1 GB, no
decoded textures evicted, ~17 -> 22-23 fps.
Diffstat (limited to 'src/video_core/texture_cache/util.cpp')
| -rw-r--r-- | src/video_core/texture_cache/util.cpp | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index aae2c7e4fd..7a1a1d89c0 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -11,6 +11,7 @@ #include <algorithm> #include <array> +#include <cstring> #include <numeric> #include <optional> #include <span> @@ -603,6 +604,10 @@ u32 CalculateUnswizzledSizeBytes(const ImageInfo& info) noexcept { return NumBlocksPerLayer(info, tile_size) * info.resources.layers * BytesPerBlock(info.format); } +bool AstcDataLooksOpaque(std::span<const u8> data) noexcept { + return Tegra::Texture::ASTC::IsOpaque(data); +} + u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept { if (info.type == ImageType::Buffer) { return info.size.width * BytesPerBlock(info.format); @@ -611,8 +616,10 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept { if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() != Settings::AstcRecompression::Uncompressed) { const u32 bpp_div = - Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2 - : 1; + Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 || + info.astc_opaque + ? 2 + : 1; // NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually. u32 output_size = 0; for (s32 i = 0; i < info.resources.levels; i++) { @@ -955,10 +962,11 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8 } else if (astc) { // BC1 uses 0.5 bytes per texel // BC3 uses 1 byte per texel - const auto compress = recompression_setting == Settings::AstcRecompression::Bc1 - ? Tegra::Texture::BCN::CompressBC1 - : Tegra::Texture::BCN::CompressBC3; - const auto bpp_div = recompression_setting == Settings::AstcRecompression::Bc1 ? 2 : 1; + const bool bc1 = + recompression_setting == Settings::AstcRecompression::Bc1 || info.astc_opaque; + const auto compress = + bc1 ? Tegra::Texture::BCN::CompressBC1 : Tegra::Texture::BCN::CompressBC3; + const auto bpp_div = bc1 ? 2 : 1; const u32 plane_dim = copy.image_extent.width * copy.image_extent.height; const u32 level_size = plane_dim * copy.image_extent.depth * |
