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);
}
On Windows 11, Temurin 24.0.1+9, the following snippet fails against 0.4.3:
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
MemorySegmentarguments 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:
An example patch for
WGPUSync#onRequestDeviceFinished(please note thatWGPUSync#adapterRequestDeviceis 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); }