java - WebGPU JsInterop 包装器
问题描述
我正在尝试使用 JsInterop 在 GWT 2.9.0 中使用 WebGPU,但在尝试将所有 WebGPU 接口映射到 Java 时遇到了一些问题。我所指的定义位于https://www.w3.org/TR/webgpu/#idl-index
1)我如何映射一个无符号长长的?
有一个 typedef: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 or 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枚举(我试过但在值中使用的破折号有问题)
非常感谢,祝您有愉快的一天!
解决方案
首先 - 如果您想要一个现成的 WebGPU(和所有其他浏览器 API)的 jsinterop 绑定,它是通过处理规范中的 webidl 并从 webidl 构建绑定而构建的,那么Akasha在 GWT2.9 和 J2CL 兼容中提供了它变体(Java API 是相同的,但两个变体之间的注解和内部函数略有不同)。最新版本的 GWT akasha 变体的坐标是org.realityforge.akasha:akasha-gwt:jar:0.29
,一个简单的纹理旋转立方体的示例可在Main.java获得
具体问题:
- 您如何表示“无符号长长”?如果值是可选的,则为a
double
或int
... 或 a 。Double
这些表示中没有一个与 API 所期望的完全匹配,但只要这些值被一致地映射并来自外部源(即 gltf 或其他格式),那么就没有明显的惩罚。我将它映射到int
类型不是可选的和Double
可选的时候。有点难看,但在 GWT 领域中效果最好(尽管 J2CL 很快就会有一种方法来代表原生多头 IIRC) - 如何包装字典?由于底层表示只是一个 javascript 对象,因此可能有很多很多不同的表示。无论您是针对 j2cl 还是 GWT,这都会有所不同,但对于 GWT,您通常需要如下所示的内容。在我的生成器中,我更进一步,像在GPUExtent3DDict中一样定义了一个构建器(但请注意,此源是 J2CL 变体的一个示例,与下面描述的代码有一些细微差别),这使得字典数据的构建更加容易。IE
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);
}
- 如何映射枚举?由于枚举实际上只是字符串值的包,因此具有字符串常量的类就足够了。但是,如果您想要更好的可用性(例如 IntelliJ IDEA 等 IDE 中的选项卡完成),那么我通常将它们建模如下。然后注释作为枚举类型的参数/返回值
@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 已被证明是一种救命稻草,尤其是当它正在迅速发展时,当规范发生变化时,编译错误可以帮助您找到问题;)祝您好运!
推荐阅读
- c++ - 为什么下面的代码会抛出错误“Abort signal from abort(3) (SIGABRT)”?
- r - 如何在 get_fit() / hbgd 包中使用 brokenstick
- python - 在保留所有维度的同时减去两个 xarray
- swift - 无法解码 JSON 文件
- r - 如何访问R中的列表元素?
- excel - 取消保护指定路径中的 Excel 工作簿并刷新工作簿连接,然后保护工作簿
- reactjs - getServerSideProps 第一次加载时间太长
- java - 从 SpringBoot 应用程序调用 Strava API
- routes - RouteNotFoundExceptionlaravel
- android - React Native 0.66.* axios 调用 [TypeError: Network request failed] ANDROID