Skip to content

nvrhi::IMessageCallback implemented in tslang (needs TypeScriptCompiler #554 released) - #39

Merged
ASDAlexander77 merged 1 commit into
mainfrom
nvrhi-message-callback
Oct 11, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
nvrhi-message-callback

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Merge order: merge this only after ASDAlexander77/TypeScriptCompiler#554 is merged and in a deployed tslang release. tslang releases before it reject a @cppvtable class whose methods have bodies, so nvrhi_direct wouldn't compile.

Summary

NVRHI reports messages through nvrhi::IMessageCallback, an interface the application implements. This PR implements it in tslang: a @cppvtable class extending nvrhi.IMessageCallback whose message() has a body. tslang builds the C++ vtable for it (#554), and NVRHI calls it like a C++ object.

@cppvtable
class MessageLog extends nvrhi.IMessageCallback {
    message(severity: u8, text: string): void { ... }
}

let messageLog = new MessageLog();                  // a global: NVRHI holds a pointer the GC can't see
Donut_SetNvrhiMessageCallback(<Opaque>messageLog);  // before the app is created

Changes

  • Bindings: nvrhi.IMessageCallback in both ABI files:

    • win32: _destructor, message;
    • linux: _completeDestructor, _deletingDestructor, message.

    IDevice::getMessageCallback is bound (slot 71 win32 / 72 linux), and MESSAGE_SEVERITY_* values are added. tools/check_nvrhi_slots.py checks IMessageCallback too: both ABIs match.

  • Donut patch Donut-message-callback-all-apis: DeviceCreationParameters::messageCallback is now used on Vulkan and D3D11, as D3D12 already does. It applies cleanly after the other patches, both on a clean Donut checkout and on the already-patched submodule.

  • Interop:

    • Donut_SetNvrhiMessageCallback(callback): the devices created afterwards get this callback (null restores Donut's).
    • Donut_LogNvrhiMessage(severity, text): Donut's own handling (logs; Fatal ends the program), for a callback that passes messages on.
    • check_interop_types.py: the callback pointer is listed as raw memory, like Donut_GetNvrhiDevice's.
  • nvrhi_direct: MessageLog:

    • checks that device.getMessageCallback() is the object implemented here;
    • with -debug, closes a command list that was never opened. The validation layer reports that as an error and does nothing else, and the test checks NVRHI delivered it to MessageLog;
    • every other message goes on to Donut's log, so CTest still fails on real validation errors.
  • Docs: core/nvrhi.ts header and README.

Testing

All runs used a local tslang built from main plus #554:

Platform Result
Windows, CTest with -debug headless.dx12/.vk, headless.donut.dx12/.vk and nvrhi_direct.dx12/.vk pass. A mutated copy that expects a different message text fails, as it should: the provoked error reached Donut's log, and the check reported NVRHI didn't call MessageLog
Windows, JIT nvrhi_direct passes
Android x86_64 emulator (host GPU) nvrhi_direct and headless pass. That covers getMessageCallback() only: the emulator has no validation layer, so message() isn't provoked there. The C++-to-tslang call under the Itanium ABI is covered by #554's g++ test
Android arm64 builds; not run

🤖 Generated with Claude Code

…rhi_direct

nvrhi.IMessageCallback is bound in both ABI files (one / two destructor slots, checked by check_nvrhi_slots.py), with IDevice::getMessageCallback and the MESSAGE_SEVERITY_* values. A @cppvtable class extending it whose message() has a body is an object NVRHI calls through the vtable tslang makes (a tslang newer than pre-alpha94: TypeScriptCompiler's C++ method implementations).

- Donut_SetNvrhiMessageCallback: the devices made after it get the callback (DeviceCreationParameters::messageCallback, which a Donut patch makes Vulkan and D3D11 use too, as D3D12 does); Donut_LogNvrhiMessage passes a message on to Donut's handling.

- nvrhi_direct's MessageLog: checks the device's getMessageCallback() is it, and with -debug provokes a validation error (closing a command list never opened) that NVRHI reports to it; every other message goes on to Donut's log, so CTest still fails on validation errors.

Tested with a local tslang (main + TypeScriptCompiler #553 + the implementations): Windows CTest headless/nvrhi_direct dx12+vk with -debug pass, a provoked message expected under another text fails the test; JIT too; Android x86_64 emulator nvrhi_direct and headless pass (getMessageCallback only: no validation layer there); arm64 builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant