Repository navigation
core/nvrhi.ts per C++ ABI: MSVC x64 and Android's Itanium ABI (needs a new tslang) - #38
Merged
Merged
Conversation
The `nvrhi` namespace is now three modules, as tslang's default library is lib.ts and lib.<os>.ts: - core/nvrhi_types.ts: the structs and constants every ABI lays out the same way; - core/nvrhi_abi.win32.ts / core/nvrhi_abi.linux.ts: the @cppvtable classes, libc++'s or the release CRT's std::string and the structs holding one, and the helpers that depend on them. core/nvrhi.ts's import of "./nvrhi_abi" takes the target's file; - core/nvrhi.ts: the functions. The ABI files differ in these ways: - Destructor slots: MSVC has one, the Itanium ABI two. - std::string: 32 bytes in the release CRT, 24 in libc++ (short strings up to 22 characters). - Structs passed by value: clearTextureFloat's TextureSubresourceSet goes as a pointer to a copy under MSVC, and as two u64 registers under Itanium. Struct returns are now declared as tuples (RefCountPtr with @cppnontrivial, NativeObject), with no explicit hidden-pointer parameter. tslang passes the pointer each ABI wants. - Donut_CanCallNvrhiDirectly: also true on Android (libc++, x86-64 or AArch64). - tools/check_nvrhi_slots.py --abi itanium: checks core/nvrhi_abi.linux.ts against NDK clang's vtable dump for x86_64 and aarch64 Android. Both ABIs match. - nvrhi_direct builds on every platform (shaders for all of them), and runs through adb shell on Android. - nvrhi_direct no longer asks Vulkan for a compute queue the device lacks: NVRHI's Vulkan getNativeQueue dereferences it, and the Android emulator has none. Needs a tslang newer than pre-alpha94, for <name>.<os>.ts imports and Itanium struct returns (TypeScriptCompiler PRs 551, 552, 553). Tested with a local tslang built from those three PRs: - Windows: headless.dx12/.vk, headless.donut.dx12/.vk and nvrhi_direct.dx12/.vk pass (6/6, with -debug). headless and nvrhi_direct also pass under the JIT. - Android x86_64 emulator (host GPU, Vulkan): headless takes the direct path and passes, and so does nvrhi_direct, every check included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
core/nvrhi.ts(NVRHI's interfaces called directly through@cppvtableclasses) now works under two C++ ABIs: MSVC x64 on Windows, and Android's Itanium ABI (clang + libc++) on x86-64 and AArch64. I split it the way tslang's default library splitslib.tsandlib.<os>.ts:core/nvrhi_types.tscore/nvrhi_abi.win32.ts@cppvtableclasses with MSVC's slots; the release CRT'sstd::stringand the structs that hold one; helpers that depend on themcore/nvrhi_abi.linux.tscore/nvrhi.tsimport "./nvrhi_abi"picks the target's file (#552)Examples still
import { nvrhi } from "../core/nvrhi". CMake'sNVRHI_TS_SOURCESlists the three modules for the target.What differs between the ABIs
std::string: 32 bytes in the release CRT, 24 in libc++. That makesBufferDesc72 bytes against 80, andTextureDesc104 against 112.stdString(),stdStringSize()andsameShortStdString()are written once per ABI.RefCountPtr, marked@cppnontrivial, andNativeObject), with no explicit hidden-pointer parameter.thisfor MSVC, beforethisassretfor Itanium. On Itanium the 8-byteNativeObjectcomes back in a register.this.clearTextureFloat's 16-byteTextureSubresourceSetis the only one.u64s, and theclearTextureFloathelper moved into the ABI files.Other changes
Donut_CanCallNvrhiDirectly(): now also returns 1 on Android with libc++, x86-64 or AArch64.layoutMatches()still compares the struct sizes at run time.tools/check_nvrhi_slots.py --abi itanium: checksnvrhi_abi.linux.tsagainst NDK clang's-fdump-vtable-layoutsfor bothx86_64-linux-android29andaarch64-linux-android29. Both ABIs match; swapping two slots makes it report both.nvrhi_direct: builds on every platform (donut_compile_shaders_all_platforms) and runs throughadb shellon Android. It now asks Vulkan for a compute queue only if the device has one.getNativeQueuedereferencesm_Queues[queue]without a null check, and the emulator's device has no compute queue.nvrhi_directnow avoids asking for it.<<on au64keeps JavaScript's 32-bit semantics (<u64>3 << 33is 6). The Linux packing multiplies instead.Testing
All runs below used a local tslang built from TypeScriptCompiler #551, #552 and #553:
-debugheadless.dx12/.vk,headless.donut.dx12/.vkandnvrhi_direct.dx12/.vkpass (6/6)run_jit.bat-style)headlessandnvrhi_directpass on D3D12 and Vulkan-gpu host, Vulkan on the RTX 5080)headless -vktakes the direct path and passes, and so doesheadless -vk -donut.nvrhi_direct -vkpasses every check: native objects, ref counts, buffers, debug names, compute, barriers, texture clear and readbacknvrhi.createBuffer's call puts the result pointer in X8 and goes through slot 20Not covered:
-debugon the emulator, which has no Vulkan validation layer.🤖 Generated with Claude Code