首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebGPU JsInterop包装器

WebGPU JsInterop包装器
EN

Stack Overflow用户
提问于 2021-11-13 13:04:00
回答 3查看 193关注 0票数 1

我试图使用WebGPU在GWT2.9.0中使用JsInterop,并且在将所有WebGPU接口映射到Java时遇到了一些问题。我所指的定义位于https://www.w3.org/TR/webgpu/#idl-index

1)如何映射未签名的长长度?

例如,在这里使用的是ty胡枝子f:typedef [EnforceRange] unsigned long long GPUSize64;

代码语言:javascript
复制
interface mixin GPURenderEncoderBase { 
    //...other declarations left out...
    undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};

如果我把它包装得像

代码语言:javascript
复制
@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public class GPURenderEncoderBase {
    //...other declarations left out...
    @JsMethod
    public final native void drawIndirect(GPUBuffer indirectBuffer, long indirectOffset);
}

我说错了:

代码语言:javascript
复制
Parameter 'sourceOffset': type 'long' is not safe to access in JSNI code

考虑到我的高级API在这里只公开一个int,以便与其他API兼容,我可能只需要使用int,但是映射GPUSize64的正确解决方案是什么呢?

2)如何包装二叉树?

当我试图翻译以下定义时

代码语言:javascript
复制
dictionary GPUExtent3DDict {
    required GPUIntegerCoordinate width;
    GPUIntegerCoordinate height = 1;
    GPUIntegerCoordinate depthOrArrayLayers = 1;
};
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;

就像这样:

代码语言:javascript
复制
@JsType(isNative = false, namespace = JsPackage.GLOBAL)
public class GPUExtent3D {
    public int width;
    public int height = 1;
    public int depthOrArrayLayers = 1;
}

然后以下列方式使用:

代码语言:javascript
复制
    ...
    GPUExtent3D size = new GPUExtent3D();
    size.width = canvasWidth;
    size.height = canvasHeight;
    GPUCanvasConfiguration config = new GPUCanvasConfiguration();
    config.size = size;
    gpuCanvasContext.configure(config);

我可以很好地编译,但在运行时得到一个错误,例如

代码语言:javascript
复制
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时:

代码语言:javascript
复制
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
}

然后用它就像:

代码语言:javascript
复制
    ...
    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)如何映射枚举?

我还在这里找到了一个可行的解决方案,我想知道,如果有一个枚举声明,这是推荐的,或者可能是不推荐的/旧的方法:

代码语言:javascript
复制
enum GPUPowerPreference {
    "low-power",
    "high-performance"
};

我能不能把它描绘成

代码语言:javascript
复制
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 (我试过了,但在值中使用的破折号有问题)

非常感谢,祝您今天愉快!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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 )。
  • 如何包装字典?作为底层表示形式只是一个javascript对象,有很多很多不同的表示形式。这是不同的,无论您是针对j2cl还是GWT,但是对于GWT,您通常需要如下所示。在我的生成器中,我进一步定义了一个构建器,就像在GPUExtent3DDict中一样(但是请注意,这个源代码是J2CL变量的一个例子,与下面描述的代码有一些细微的差异),这使得字典数据的构造更加容易。即GPUExtent3DDict.width( 10 ).height( 10 ).depthOrArrayLayers( 1 )
代码语言:javascript
复制
@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);
}
  • 如何映射枚举?作为枚举实际上只是字符串值的袋子,一个具有字符串常量的类就足够了。但是,如果您想要更好的可用性(例如,在IDEA(如IntelliJ IDEA)中完成选项卡),那么我通常将它们建模如下。然后用@GPUPowerPreference注释作为枚举类型的参数/返回值。
代码语言:javascript
复制
@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已被证明是一种生命保护程序,特别是因为它目前正在迅速发展,而且当规范发生变化时,编译错误会帮助您定位问题;)祝您好运!

票数 3
EN

Stack Overflow用户

发布于 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

票数 1
EN

Stack Overflow用户

发布于 2021-11-17 14:58:15

添加到其他答案,因为他们遗漏了一个部分,我认为这可能是重要的,至少在一些具体的情况下。

  1. 我如何映射一个未签名的长?

首先,请注意,Java不是等效的,因为虽然long长为64位宽,但它们是签名的。

据我所读到的规范,它是复杂的,但灵活。https://webidl.spec.whatwg.org/#es-unsigned-long-long

通过运行以下算法,将ECMAScript值V转换为无符号长值IDL:

  1. 让X来吧?ConvertToInt(V,64,“未签名”)。
  2. 返回IDL无符号长值,表示与x相同的数值。

将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)生成字符串值。我建议提供本机doubleintString重载,以及一个带有@JsOverlay注释的long方法,该方法随后将委托给字符串重载。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69954515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档