Skip to content

WGPUSync.instanceRequestAdapter returns a broken WGPUAdapter #163

@ShadelessFox

Description

@ShadelessFox

On Windows 11, Temurin 24.0.1+9, the following snippet fails against 0.4.3:

import club.doki7.ffm.library.ILibraryLoader;
import club.doki7.webgpu.WGPU;
import club.doki7.webgpu.WGPUSync;

public class Demo {
    public static void main(String[] args) {
        var wgpu = new WGPU(ILibraryLoader.platformLoader().loadLibrary("..."));
        var instance = wgpu.createInstance(null);
        var adapter = WGPUSync.instanceRequestAdapter(wgpu, instance, null).adapter;
        var device = WGPUSync.adapterRequestDevice(wgpu, adapter, null).device;
    }
}
Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalStateException: Already closed
	at club.doki7.webgpu.WGPU.adapterRequestDevice(WGPU.java:538)
	at club.doki7.webgpu.WGPUSync.adapterRequestDevice(WGPUSync.java:93)
	at sh.adelessfox.demo.Demo.main(Demo.java:12)
Caused by: java.lang.IllegalStateException: Already closed
	at java.base/jdk.internal.foreign.MemorySessionImpl.alreadyClosed(MemorySessionImpl.java:318)
	at java.base/jdk.internal.misc.ScopedMemoryAccess$ScopedAccessError.newRuntimeException(ScopedMemoryAccess.java:114)
	at java.base/jdk.internal.foreign.MemorySessionImpl.checkValidState(MemorySessionImpl.java:217)
	at java.base/jdk.internal.foreign.ConfinedSession.acquire0(ConfinedSession.java:53)
	at club.doki7.webgpu.WGPU.adapterRequestDevice(WGPU.java:531)
	... 2 more

Which is interesting because I didn't encounter the same issue on Linux.

I have discovered that FFM upcalls on Windows use a confined arena for allocating their arguments. When an upcall returns, its arena is closed, and all its MemorySegment arguments become invalid. I haven't investigated why it doesn't happen on Linux, though.

The workaround is to use the raw address of a segment:

MemorySegment.ofAddress(segment.address())

An example patch for WGPUSync#onRequestDeviceFinished (please note that WGPUSync#adapterRequestDevice is affected as well):

    private static void onRequestDeviceFinished(
            ...
    ) {
        @Nullable WGPUDevice deviceHandle = device == MemorySegment.NULL
                ? null
-               : new WGPUDevice(device);
+               : new WGPUDevice(MemorySegment.ofAddress(device.address()));
        @Nullable String messageString = WGPUUtil.readStringView(message);
        saveSlot.value = new RequestDeviceResult(status, deviceHandle, messageString);
    }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions