我试图使用WebGPU在GWT2.9.0中使用JsInterop,并且在将所有WebGPU接口映射到Java时遇到了一些问题。我所指的定义位于https://www.w3.org/TR/webgpu/#idl-index
1)如何映射未签名的长长度?
例如,在这里使用的是ty胡枝子f:typedef [EnforceRange] unsigned long long GPUSize64;:
interface mixin GPURenderEncoderBase {
//...other declarations left out...
undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};如果我把它包装得像
@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public class GPURenderEncoderBase {
//...other declarations left out...
@JsMethod
public final native void drawIndirect(GPUBuffer indirectBuffer, long indirectOffset);
}我说错了:
Parameter 'sourceOffset': type 'long' is not safe to access in JSNI code考虑到我的高级API在这里只公开一个int,以便与其他API兼容,我可能只需要使用int,但是映射GPUSize64的正确解决方案是什么呢?
2)如何包装二叉树?
当我试图翻译以下定义时
dictionary GPUExtent3DDict {
required GPUIntegerCoordinate width;
GPUIntegerCoordinate height = 1;
GPUIntegerCoordinate depthOrArrayLayers = 1;
};
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;就像这样:
@JsType(isNative = false, namespace = JsPackage.GLOBAL)
public class GPUExtent3D {
public int width;
public int height = 1;
public int depthOrArrayLayers = 1;
}然后以下列方式使用:
...
GPUExtent3D size = new GPUExtent3D();
size.width = canvasWidth;
size.height = canvasHeight;
GPUCanvasConfiguration config = new GPUCanvasConfiguration();
config.size = size;
gpuCanvasContext.configure(config);我可以很好地编译,但在运行时得到一个错误,例如
Uncaught (in promise) TypeError: Failed to execute 'configure' on 'GPUCanvasContext': Failed to read the 'size' property from 'GPUCanvasConfiguration': Failed to read the 'width' property from 'GPUExtent3DDict': Failed to read the 'width' property from 'GPUExtent3DDict': Required member is undefined.让我困惑的是,它说了两次“未能从‘GPUExtent3DDict’中读取'width‘属性”,这暗示了它希望有一些嵌套的东西,并且可能与我所不理解的typedef中关于"sequence或GPUExtent3DDict“的最后一行有关。当我用这种方式定义GPUExtent3D时:
public final class GPUExtent3D extends JavaScriptObject {
public static final native GPUExtent3D createNew() /*-{
return {height: 1, depthOrArrayLayers: 1};
}-*/;
protected GPUExtent3D() {}
public final native void width(int width) /*-{
this["width"] = width;
}-*/;
//...same for height and depthOrArrayLayers
}然后用它就像:
...
GPUExtent3D size = GPUExtent3D.createNew();
size.width(canvasWidth);
size.height(canvasHeight);
size.depthOrArrayLayers(1);
GPUCanvasConfiguration config = new GPUCanvasConfiguration();
config.size = size;
gpuCanvasContext.configure(config);它工作得很好,但是我想用JsInterop的方式来做,而不是用范围JavaScriptObject。我该怎么做?
3)如何映射枚举?
我还在这里找到了一个可行的解决方案,我想知道,如果有一个枚举声明,这是推荐的,或者可能是不推荐的/旧的方法:
enum GPUPowerPreference {
"low-power",
"high-performance"
};我能不能把它描绘成
public final class GPUPowerPreference {
public static final String LOW_POWER = "low-power";
public static final String HIGH_POWER = "high-power";
private GPUPowerPreference() {}
}还是有一种方法可以在@JsEnum中使用java enum (我试过了,但在值中使用的破折号有问题)
非常感谢,祝您今天愉快!
发布于 2021-11-16 06:59:40
首先--如果您希望为WebGPU (以及所有其他浏览器API )准备一个通过处理规范中的webidl并从webidl构建绑定的J烧结API绑定,那么阿卡沙提供了在GWT2.9和J2CL兼容的变体中( Java是相同的,但两个变体之间的注释和innerts略有不同)。最新版本的akasha变体的坐标是org.realityforge.akasha:akasha-gwt:jar:0.29,一个简单的纹理旋转立方体的例子可以在Main.java上找到。
具体问题:
double,要么是int .如果值是可选的,则为Double。这些表示都不完全符合API所期望的,但只要一致地映射值并从外部源(即gltf或其他格式)获取值,就不会有重大的损失。当类型不是可选时,我将它映射到int,当可选时映射到Double。有点丑陋,但在GWT-land中却是最好的(尽管J2CL很快就会有一种方法来表示本机longs )。GPUExtent3DDict.width( 10 ).height( 10 ).depthOrArrayLayers( 1 )@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "?")
public interface GPUExtent3DDict {
@JsProperty(name = "width")
int width();
@JsProperty
void setWidth(int width);
@JsProperty(name = "depthOrArrayLayers")
int depthOrArrayLayers();
@JsProperty
void setDepthOrArrayLayers(int depthOrArrayLayers);
@JsProperty(name = "height")
int height();
@JsProperty
void setHeight(int height);
}@GPUPowerPreference注释作为枚举类型的参数/返回值。@MagicConstant(valuesFromClass = GPUPowerPreference.class)
public @interface GPUPowerPreference {
@Nonnull
String high_performance = "high-performance";
@Nonnull
String low_power = "low-power";
final class Util {
private Util() {
}
@GPUPowerPreference
public static String requireValid(final String value) {
assertValid( value );
return value;
}
public static void assertValid(@Nonnull final String value) {
assert isValid( value );
}
public static boolean isValid(@Nonnull final String value) {
return GPUPowerPreference.high_performance.equals( value ) || GPUPowerPreference.low_power.equals( value );
}
}
}因为它的价值。在java中使用WebGPU已被证明是一种生命保护程序,特别是因为它目前正在迅速发展,而且当规范发生变化时,编译错误会帮助您定位问题;)祝您好运!
发布于 2021-11-15 23:25:40
几个月前,我做了elemental2,就像webgpu包装器一样,基于我手写的外挂. 。
你可以在这里看看:
https://github.com/treblereel/elemental2-experimental/tree/main/java/org/treblereel/gwt/elemental2
简单演示:https://github.com/treblereel/j2cl-tests/blob/webgpu/src/main/java/org/treblereel/App.java
它是基于j2cl的,但是非常接近于如何使用gwt2来实现它。 的主要缺点是,webgpu不稳定,所以很难保持它的最新状态。 更好地从idl生成外部元素:
@peter正在致力于更好地实现Web,但它不是基于elemental2的。https://github.com/akasha/akasha
发布于 2021-11-17 14:58:15
添加到其他答案,因为他们遗漏了一个部分,我认为这可能是重要的,至少在一些具体的情况下。
首先,请注意,Java不是等效的,因为虽然long长为64位宽,但它们是签名的。
据我所读到的规范,它是复杂的,但灵活。https://webidl.spec.whatwg.org/#es-unsigned-long-long
通过运行以下算法,将ECMAScript值V转换为无符号长值IDL:
将IDL无符号长值转换为ECMAScript值的结果是一个数字值,它表示与无符号长最接近的数值,选择具有偶数意义的数值,如果有两个相同的关闭值,则选择这个数值。如果无符号long小于或等于253−1,则该数字将能够表示与无符号long完全相同的值。
好的,那么接下来ConvertToInt是什么?请参阅https://webidl.spec.whatwg.org/#abstract-opdef-converttoint,但是它建立了一些边界(基于64和"unsigned"),然后使用ToNumber,这是ecmascript规范https://tc39.es/ecma262/#sec-tonumber的一个更标准的部分。在其他输入中,这可以通过StringToNumber https://tc39.es/ecma262/#sec-stringtonumber处理字符串。
这样做的最终效果是,您可以向这些API传递带有无符号64位整数值的字符串,并在内部对其进行解释。因此,只要您的值适合于Java long,就可以使用Long.toString(value)生成字符串值。我建议提供本机double、int和String重载,以及一个带有@JsOverlay注释的long方法,该方法随后将委托给字符串重载。
https://stackoverflow.com/questions/69954515
复制相似问题