Repository navigation
Conversation
4 of 5 tasks
1 task done
…nction pointers, and add RAM saving option - CPU BC decompression is always enabled on GPUs without native BC support (no build-time or profile options needed) - Eliminate runtime per-texture branch checks by binding specialized function pointers at launch time (g_nvn_bc_unpacked, g_nvn_bc_decode) across 3 concrete paths: 1. Direct BC decompression via GPU (hardware BC) 2. BC -> standard CPU decode (BC6H to RGBA16Float) 3. BC -> RGB9E5 CPU decode (saves 50% RAM on BC6H HDR textures) - Add launch option DM_BC6H_RGB9E5: Label: "Sighly lower texture quality to save RAM" Note: "Try this if game starts crashing in heavy scenes" Hidden on hardware BC GPUs, disabled by default. - Document feature, RAM characteristics, and environment switches in project docs. - Address clang-analyzer nullability, retain count, and scratch allocation findings in nvn_mtl and test suite.
Author
|
The devices that do not support BC textures are the same ones lacking RAM (6GB, with 4GB available for apps, matching Switch total RAM), so would it make sense to always convert BC6H HDR textures into RGB9E5Float? |
Author
|
Closing this in line with upstream's policy from #488 to support only GPUs with native hardware BC sampling. We will continue maintaining this as a fork-only patch in NX2Apple. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Enables games using BC-compressed textures (such as The Legend of Zelda: Tears of the Kingdom,
0100F2C0115B6000) to run on GPUs without native BC compression (pre-A17 Pro iOS devices, such as iPhone 14 Pro / Apple A16 GPU) by decoding BC1–5, BC6H, and BC7 textures on the CPU into uncompressed Metal formats (RGBA8Unorm,RGBA8Unorm_sRGB,R8Unorm,RG8Unorm,RGBA16Float, orRGB9E5Float).All BC texture operations are dispatched via specialized function pointers locked in at launch time across 3 concrete paths with zero runtime branch overhead, and includes an optional launch-time setting (
DM_BC6H_RGB9E5) to halve the RAM footprint of HDR textures.Symptom
When running The Legend of Zelda: Tears of the Kingdom (
0100F2C0115B6000, v1.4.3) on an iPhone 14 Pro (Apple A16 GPU) with CPU BC texture decoding, the game boots and displays the "Nintendo Presents" intro screen, then aborts (SIGABRT) at frame 153 during texture view creation (ser=6059/ser=6074):Earlier in the same frame (
ser=2638,ser=2639,ser=2903), the log also reported[RED]errors whenagl's GPU BC4 block encoder attempted to bind a CPU-decoded BC4 texture as a render target through anRGBA16UI(0x2c) view:Root cause
When running on a GPU without hardware BC texture compression (
!g_dev.supportsBCTextureCompression),tex_desccreates BC1–BC7 / BC6H textures (0x41–0x50) in their unpacked Metal pixel format vianvn_bc_unpacked(RGBA8Unorm70,RGBA8Unorm_sRGB71,R8Unorm10,RG8Unorm30,RGBA16Float115, orRGB9E5Float113). However, several other paths indm/gfx/nvn/nvn_mtl.mstill looked up view formats throughnvn_fmt_to_mtlor checked onlymtl_fmt_block(base.pixelFormat):tex_by_id): When the game registers aview_twith a BC view format (such as0x45RGB_sRGB_DXT1or0x46RGBA_sRGB_DXT1on aDXT1texture whose base Metal texture was unpacked toRGBA8Unorm70orRGBA8Unorm_sRGB71),tex_by_idcallednvn_fmt_to_mtl(r.v.format, &pf, swz)directly. That returnedMTLPixelFormatBC1_RGBA_sRGB(131), which is unsupported on A16 (MTLPixelFormatInvalidin Metal's validator) and not castable fromRGBA8Unorm_sRGB(71), triggeringtex_upgrade_pfvand aborting in[base newTextureViewWithPixelFormat:...].pkg_upload_): Evaluating whether to decode on CPU occurred after the GPU compute deswizzle paths. Non-sparse BC textures therefore took the GPU block-deswizzle path (treating 4x4 texel blocks as 1x1 elements) into an unpackedRGBA8texture instead of reaching the CPUnvn_bc_decodeloop.attach,rt_view_fmt): Because an unpacked BC4 (0x49) texture hasbase.pixelFormat == MTLPixelFormatR8Unorm(10),mtl_fmt_block(base.pixelFormat)was0. When the game bound the BC4 texture as a render target with anRGBA16UI(0x2c) block-encoding view,attachupgraded theR8Unormtexture toMTLTextureUsageRenderTargetinstead of treatingnvn_fmt_bc(t->d.format)as a compressed texture and leaving the attachment unattached (a.texture = nil) whenbcrt_attachdoes not apply.copy_b2t,copy_t2b,mtl_read_texels):copy_b2tblitted raw BC blocks with compressedbytesPerRowdirectly into the unpackedRGBA8texture without decoding vianvn_bc_decode. Similarly,copy_t2band the GPU blit fallback inmtl_read_texelsattempted to blit from an unpackedRGBA8texture using compressed block row strides.fz_p2_draw) andclear_tex: Both resolvedview.formatvianvn_fmt_to_mtlwithout checkingg_bc_cpu && nvn_bc_unpacked(...).The change
Always-enabled CPU BC decompression:
tex_bc_cpufromgame.tsvandgame.py.!supportsBCTextureCompression), CPU BC decompression is enabled automatically for all games.dm/ios/Sources/main.m(front_ios_device_check) so non-BC devices are no longer refused at boot.Launch-time function pointer dispatch (
mtl_set_bc_pathinnvn_mtl.m):g_pkg_upload,g_tex_desc,g_nvn_bc_unpacked,g_nvn_bc_decode) at launch time across 3 concrete paths:BC_PATH_GPU): Hardware direct BC decompression whensupportsBCTextureCompressionis true. CPU scratch buffers and decoding logic are completely bypassed with zero runtime overhead.BC_PATH_CPU_STANDARD): Standard CPU BC decompression. Decodes BC1–5 and BC7 into standard uncompressed Metal formats, and BC6H intoRGBA16Float(8 bytes per pixel).BC_PATH_CPU_RGB9E5): Reduced-RAM CPU BC decompression. Decodes BC6H HDR textures intoRGB9E5Float(4 bytes per pixel) instead ofRGBA16Float, halving memory consumption for HDR environment maps.RAM optimization setting (
DM_BC6H_RGB9E5):DM_BC6H_RGB9E5toggle todm/games/settings.tsv:"Sighly lower texture quality to save RAM""Try this if game starts crashing in heavy scenes"supportsBCTextureCompression == true).LauncherSettings.swift.docs/reference/rendering.md,docs/settings.md, anddocs/env_switches.tsv.Views, uploads, copies, and attachments handling:
tex_by_id,rt_view_fmt,attach,fz_p2_draw, andclear_tex: resolve BC view formats throughg_nvn_bc_unpacked.pkg_upload_: non-sparse uploads route cleanly throughg_pkg_uploadwithout GPU block-deswizzle interference.attach: guardstex_upgradeand compressed-target checks usingnvn_fmt_bc(t->d.format)so CPU-decoded BC textures are not upgraded to uncompressed render targets.copy_b2t,copy_t2b, andmtl_read_texels: CPU decompression incopy_b2tbefore blitting, and skip raw block blits out of unpacked BC textures incopy_t2bandmtl_read_texels.Checked
clang -O2 ... t_bcdec.c nvn_bcdec.c -o /tmp/t_bcdec && /tmp/t_bcdec: BC1 matches independent DXT1 decoder, format map, edge trimming, BC4, BC6H RGB9E5 & RGBA16F - all OK.make -C dm/gfx/tests check_t_view_swizzle GAME=01007EF00011E000(MTL_DEBUG_LAYER=1 ./t_view_swizzle: 393 checks, 0 failed).python3 dm/tools/tests/test_launcher_settings.py: Ran 15 tests, OK.python3 dm/tools/env_switches.py --check: OK (328 switches, 0 without meaning).python3 dm/tools/tests/test_docs.py: Ran 11 tests, OK.0100F2C0115B6000, v1.4.3): progresses past "Nintendo Presents" intro into title sequence and gameplay without crashing on iPhone 14 Pro (Apple A16 GPU, iOS 26.0).supportsBCTextureCompression == true) select Path 1 at launch time: all CPU decoding code and scratch buffers are bypassed completely with zero overhead.Docs
docs/reference/<subsystem>.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)