0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

chore(ext): update webgpu (#15059)

This commit is contained in:
Dante Issaias 2022-07-20 01:22:26 +01:00 committed by GitHub
parent 649536e266
commit 2b1f145c3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1605 additions and 1867 deletions

57
Cargo.lock generated
View file

@ -102,6 +102,15 @@ dependencies = [
"alloc-no-stdlib", "alloc-no-stdlib",
] ]
[[package]]
name = "android_system_properties"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20ae67ce26261f218e2b3f2f0d01887a9818283ca6fb260fa7c67e253d61c92"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.12.1" version = "0.12.1"
@ -128,9 +137,9 @@ dependencies = [
[[package]] [[package]]
name = "ash" name = "ash"
version = "0.34.0+1.2.203" version = "0.37.0+1.3.209"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" checksum = "006ca68e0f2b03f22d6fa9f2860f85aed430d257fec20f8879b2145e7c7ae1a6"
dependencies = [ dependencies = [
"libloading", "libloading",
] ]
@ -687,9 +696,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]] [[package]]
name = "d3d12" name = "d3d12"
version = "0.4.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" checksum = "827914e1f53b1e0e025ecd3d967a7836b7bcb54520f90e21ef8df7b4d88a2759"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"libloading", "libloading",
@ -2358,6 +2367,7 @@ checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
dependencies = [ dependencies = [
"libc", "libc",
"libloading", "libloading",
"pkg-config",
] ]
[[package]] [[package]]
@ -2625,9 +2635,9 @@ dependencies = [
[[package]] [[package]]
name = "metal" name = "metal"
version = "0.23.1" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"block", "block",
@ -2684,9 +2694,9 @@ dependencies = [
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.8.5" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" checksum = "5f50357e1167a3ab92d6b3c7f4bf5f7fd13fde3f4b28bf0d5ea07b5100fdb6c0"
dependencies = [ dependencies = [
"bit-set", "bit-set",
"bitflags", "bitflags",
@ -2698,7 +2708,9 @@ dependencies = [
"rustc-hash", "rustc-hash",
"serde", "serde",
"spirv", "spirv",
"termcolor",
"thiserror", "thiserror",
"unicode-xid 0.2.3",
] ]
[[package]] [[package]]
@ -3236,7 +3248,7 @@ version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid 0.1.0",
] ]
[[package]] [[package]]
@ -4497,7 +4509,7 @@ checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [ dependencies = [
"proc-macro2 0.4.30", "proc-macro2 0.4.30",
"quote 0.6.13", "quote 0.6.13",
"unicode-xid", "unicode-xid 0.1.0",
] ]
[[package]] [[package]]
@ -5086,6 +5098,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
version = "0.4.1" version = "0.4.1"
@ -5331,11 +5349,12 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-core" name = "wgpu-core"
version = "0.12.2" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" checksum = "266ca6be6004fd1b2a768023b1cb0afbf7af0cbffaba19af25c5792d44e74784"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bit-vec",
"bitflags", "bitflags",
"cfg_aliases", "cfg_aliases",
"codespan-reporting", "codespan-reporting",
@ -5343,22 +5362,24 @@ dependencies = [
"fxhash", "fxhash",
"log 0.4.17", "log 0.4.17",
"naga", "naga",
"parking_lot 0.11.2", "parking_lot 0.12.1",
"profiling", "profiling",
"ron", "ron",
"serde", "serde",
"smallvec", "smallvec",
"thiserror", "thiserror",
"web-sys",
"wgpu-hal", "wgpu-hal",
"wgpu-types", "wgpu-types",
] ]
[[package]] [[package]]
name = "wgpu-hal" name = "wgpu-hal"
version = "0.12.5" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d684ea6a34974a2fc19f1dfd183d11a62e22d75c4f187a574bb1224df8e056c2" checksum = "bef50e48812c7eb958fa52d28a912f8b77c96453ebab21c72b01cdda61d3e65d"
dependencies = [ dependencies = [
"android_system_properties",
"arrayvec", "arrayvec",
"ash", "ash",
"bit-set", "bit-set",
@ -5379,7 +5400,7 @@ dependencies = [
"metal", "metal",
"naga", "naga",
"objc", "objc",
"parking_lot 0.11.2", "parking_lot 0.12.1",
"profiling", "profiling",
"range-alloc", "range-alloc",
"raw-window-handle", "raw-window-handle",
@ -5393,9 +5414,9 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-types" name = "wgpu-types"
version = "0.12.0" version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" checksum = "f48d691b733b9d50ea8cb18f377fd1ed927c90c55ad1ec5b90f68885471977f7"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"bitflags_serde_shim", "bitflags_serde_shim",

View file

@ -5,10 +5,8 @@
/// <reference no-default-lib="true" /> /// <reference no-default-lib="true" />
/// <reference lib="esnext" /> /// <reference lib="esnext" />
// 8cc98b6f10b7f354473a08c3773bb1de839845b9
interface GPUObjectBase { interface GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUObjectDescriptorBase { declare interface GPUObjectDescriptorBase {
@ -64,6 +62,13 @@ declare class GPUSupportedFeatures {
values(): IterableIterator<GPUFeatureName>; values(): IterableIterator<GPUFeatureName>;
} }
declare class GPUAdapterInfo {
readonly vendor: string;
readonly architecture: string;
readonly device: string;
readonly description: string;
}
declare class GPU { declare class GPU {
requestAdapter( requestAdapter(
options?: GPURequestAdapterOptions, options?: GPURequestAdapterOptions,
@ -78,12 +83,12 @@ declare interface GPURequestAdapterOptions {
declare type GPUPowerPreference = "low-power" | "high-performance"; declare type GPUPowerPreference = "low-power" | "high-performance";
declare class GPUAdapter { declare class GPUAdapter {
readonly name: string;
readonly features: GPUSupportedFeatures; readonly features: GPUSupportedFeatures;
readonly limits: GPUSupportedLimits; readonly limits: GPUSupportedLimits;
readonly isFallbackAdapter: boolean; readonly isFallbackAdapter: boolean;
requestDevice(descriptor?: GPUDeviceDescriptor): Promise<GPUDevice>; requestDevice(descriptor?: GPUDeviceDescriptor): Promise<GPUDevice>;
requestAdapterInfo(unmaskHints?: string[]): Promise<GPUAdapterInfo>;
} }
declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase {
@ -101,6 +106,7 @@ declare type GPUFeatureName =
| "texture-compression-astc" | "texture-compression-astc"
| "timestamp-query" | "timestamp-query"
| "indirect-first-instance" | "indirect-first-instance"
| "shader-f16"
// extended from spec // extended from spec
| "mappable-primary-buffers" | "mappable-primary-buffers"
| "sampled-texture-binding-array" | "sampled-texture-binding-array"
@ -116,7 +122,7 @@ declare type GPUFeatureName =
| "vertex-attribute-64bit"; | "vertex-attribute-64bit";
declare class GPUDevice extends EventTarget implements GPUObjectBase { declare class GPUDevice extends EventTarget implements GPUObjectBase {
label: string | null; label: string;
readonly lost: Promise<GPUDeviceLostInfo>; readonly lost: Promise<GPUDeviceLostInfo>;
pushErrorScope(filter: GPUErrorFilter): undefined; pushErrorScope(filter: GPUErrorFilter): undefined;
@ -168,7 +174,7 @@ declare class GPUDevice extends EventTarget implements GPUObjectBase {
} }
declare class GPUBuffer implements GPUObjectBase { declare class GPUBuffer implements GPUObjectBase {
label: string | null; label: string;
mapAsync( mapAsync(
mode: GPUMapModeFlags, mode: GPUMapModeFlags,
@ -208,7 +214,7 @@ declare class GPUMapMode {
} }
declare class GPUTexture implements GPUObjectBase { declare class GPUTexture implements GPUObjectBase {
label: string | null; label: string;
createView(descriptor?: GPUTextureViewDescriptor): GPUTextureView; createView(descriptor?: GPUTextureViewDescriptor): GPUTextureView;
destroy(): undefined; destroy(): undefined;
@ -235,7 +241,7 @@ declare class GPUTextureUsage {
} }
declare class GPUTextureView implements GPUObjectBase { declare class GPUTextureView implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase { declare interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase {
@ -300,6 +306,8 @@ declare type GPUTextureFormat =
| "depth24plus" | "depth24plus"
| "depth24plus-stencil8" | "depth24plus-stencil8"
| "depth32float" | "depth32float"
| "depth24unorm-stencil8"
| "depth32float-stencil8"
| "bc1-rgba-unorm" | "bc1-rgba-unorm"
| "bc1-rgba-unorm-srgb" | "bc1-rgba-unorm-srgb"
| "bc2-rgba-unorm" | "bc2-rgba-unorm"
@ -351,12 +359,10 @@ declare type GPUTextureFormat =
| "astc-12x10-unorm" | "astc-12x10-unorm"
| "astc-12x10-unorm-srgb" | "astc-12x10-unorm-srgb"
| "astc-12x12-unorm" | "astc-12x12-unorm"
| "astc-12x12-unorm-srgb" | "astc-12x12-unorm-srgb";
| "depth24unorm-stencil8"
| "depth32float-stencil8";
declare class GPUSampler implements GPUObjectBase { declare class GPUSampler implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase {
@ -365,7 +371,7 @@ declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase {
addressModeW?: GPUAddressMode; addressModeW?: GPUAddressMode;
magFilter?: GPUFilterMode; magFilter?: GPUFilterMode;
minFilter?: GPUFilterMode; minFilter?: GPUFilterMode;
mipmapFilter?: GPUFilterMode; mipmapFilter?: GPUMipmapFilterMode;
lodMinClamp?: number; lodMinClamp?: number;
lodMaxClamp?: number; lodMaxClamp?: number;
compare?: GPUCompareFunction; compare?: GPUCompareFunction;
@ -376,6 +382,8 @@ declare type GPUAddressMode = "clamp-to-edge" | "repeat" | "mirror-repeat";
declare type GPUFilterMode = "nearest" | "linear"; declare type GPUFilterMode = "nearest" | "linear";
declare type GPUMipmapFilterMode = "nearest" | "linear";
declare type GPUCompareFunction = declare type GPUCompareFunction =
| "never" | "never"
| "less" | "less"
@ -387,7 +395,7 @@ declare type GPUCompareFunction =
| "always"; | "always";
declare class GPUBindGroupLayout implements GPUObjectBase { declare class GPUBindGroupLayout implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase { declare interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase {
@ -450,7 +458,7 @@ declare interface GPUStorageTextureBindingLayout {
} }
declare class GPUBindGroup implements GPUObjectBase { declare class GPUBindGroup implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUBindGroupDescriptor extends GPUObjectDescriptorBase { declare interface GPUBindGroupDescriptor extends GPUObjectDescriptorBase {
@ -475,7 +483,7 @@ declare interface GPUBufferBinding {
} }
declare class GPUPipelineLayout implements GPUObjectBase { declare class GPUPipelineLayout implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase { declare interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase {
@ -496,7 +504,7 @@ declare interface GPUCompilationInfo {
} }
declare class GPUShaderModule implements GPUObjectBase { declare class GPUShaderModule implements GPUObjectBase {
label: string | null; label: string;
compilationInfo(): Promise<GPUCompilationInfo>; compilationInfo(): Promise<GPUCompilationInfo>;
} }
@ -506,8 +514,10 @@ declare interface GPUShaderModuleDescriptor extends GPUObjectDescriptorBase {
sourceMap?: any; sourceMap?: any;
} }
declare type GPUAutoLayoutMode = "auto";
declare interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase { declare interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase {
layout?: GPUPipelineLayout; layout: GPUPipelineLayout | GPUAutoLayoutMode;
} }
declare interface GPUPipelineBase { declare interface GPUPipelineBase {
@ -520,7 +530,7 @@ declare interface GPUProgrammableStage {
} }
declare class GPUComputePipeline implements GPUObjectBase, GPUPipelineBase { declare class GPUComputePipeline implements GPUObjectBase, GPUPipelineBase {
label: string | null; label: string;
getBindGroupLayout(index: number): GPUBindGroupLayout; getBindGroupLayout(index: number): GPUBindGroupLayout;
} }
@ -531,7 +541,7 @@ declare interface GPUComputePipelineDescriptor
} }
declare class GPURenderPipeline implements GPUObjectBase, GPUPipelineBase { declare class GPURenderPipeline implements GPUObjectBase, GPUPipelineBase {
label: string | null; label: string;
getBindGroupLayout(index: number): GPUBindGroupLayout; getBindGroupLayout(index: number): GPUBindGroupLayout;
} }
@ -545,13 +555,6 @@ declare interface GPURenderPipelineDescriptor
fragment?: GPUFragmentState; fragment?: GPUFragmentState;
} }
declare type GPUPrimitiveTopology =
| "point-list"
| "line-list"
| "line-strip"
| "triangle-list"
| "triangle-strip";
declare interface GPUPrimitiveState { declare interface GPUPrimitiveState {
topology?: GPUPrimitiveTopology; topology?: GPUPrimitiveTopology;
stripIndexFormat?: GPUIndexFormat; stripIndexFormat?: GPUIndexFormat;
@ -560,6 +563,13 @@ declare interface GPUPrimitiveState {
unclippedDepth?: boolean; unclippedDepth?: boolean;
} }
declare type GPUPrimitiveTopology =
| "point-list"
| "line-list"
| "line-strip"
| "triangle-list"
| "triangle-strip";
declare type GPUFrontFace = "ccw" | "cw"; declare type GPUFrontFace = "ccw" | "cw";
declare type GPUCullMode = "none" | "front" | "back"; declare type GPUCullMode = "none" | "front" | "back";
@ -571,7 +581,7 @@ declare interface GPUMultisampleState {
} }
declare interface GPUFragmentState extends GPUProgrammableStage { declare interface GPUFragmentState extends GPUProgrammableStage {
targets: GPUColorTargetState[]; targets: (GPUColorTargetState | null)[];
} }
declare interface GPUColorTargetState { declare interface GPUColorTargetState {
@ -710,13 +720,13 @@ declare interface GPUVertexAttribute {
} }
declare class GPUCommandBuffer implements GPUObjectBase { declare class GPUCommandBuffer implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {} declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {}
declare class GPUCommandEncoder implements GPUObjectBase { declare class GPUCommandEncoder implements GPUObjectBase {
label: string | null; label: string;
beginRenderPass(descriptor: GPURenderPassDescriptor): GPURenderPassEncoder; beginRenderPass(descriptor: GPURenderPassDescriptor): GPURenderPassEncoder;
beginComputePass( beginComputePass(
@ -751,8 +761,8 @@ declare class GPUCommandEncoder implements GPUObjectBase {
clearBuffer( clearBuffer(
destination: GPUBuffer, destination: GPUBuffer,
destinationOffset: number, destinationOffset?: number,
size: number, size?: number,
): undefined; ): undefined;
pushDebugGroup(groupLabel: string): undefined; pushDebugGroup(groupLabel: string): undefined;
@ -813,7 +823,7 @@ interface GPUProgrammablePassEncoder {
declare class GPUComputePassEncoder declare class GPUComputePassEncoder
implements GPUObjectBase, GPUProgrammablePassEncoder { implements GPUObjectBase, GPUProgrammablePassEncoder {
label: string | null; label: string;
setBindGroup( setBindGroup(
index: number, index: number,
bindGroup: GPUBindGroup, bindGroup: GPUBindGroup,
@ -830,8 +840,8 @@ declare class GPUComputePassEncoder
popDebugGroup(): undefined; popDebugGroup(): undefined;
insertDebugMarker(markerLabel: string): undefined; insertDebugMarker(markerLabel: string): undefined;
setPipeline(pipeline: GPUComputePipeline): undefined; setPipeline(pipeline: GPUComputePipeline): undefined;
dispatch(x: number, y?: number, z?: number): undefined; dispatchWorkgroups(x: number, y?: number, z?: number): undefined;
dispatchIndirect( dispatchWorkgroupsIndirect(
indirectBuffer: GPUBuffer, indirectBuffer: GPUBuffer,
indirectOffset: number, indirectOffset: number,
): undefined; ): undefined;
@ -844,7 +854,7 @@ declare class GPUComputePassEncoder
writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined; writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined;
endPass(): undefined; end(): undefined;
} }
declare interface GPUComputePassDescriptor extends GPUObjectDescriptorBase {} declare interface GPUComputePassDescriptor extends GPUObjectDescriptorBase {}
@ -888,7 +898,7 @@ interface GPURenderEncoderBase {
declare class GPURenderPassEncoder declare class GPURenderPassEncoder
implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase {
label: string | null; label: string;
setBindGroup( setBindGroup(
index: number, index: number,
bindGroup: GPUBindGroup, bindGroup: GPUBindGroup,
@ -967,11 +977,11 @@ declare class GPURenderPassEncoder
writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined; writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined;
executeBundles(bundles: GPURenderBundle[]): undefined; executeBundles(bundles: GPURenderBundle[]): undefined;
endPass(): undefined; end(): undefined;
} }
declare interface GPURenderPassDescriptor extends GPUObjectDescriptorBase { declare interface GPURenderPassDescriptor extends GPUObjectDescriptorBase {
colorAttachments: GPURenderPassColorAttachment[]; colorAttachments: (GPURenderPassColorAttachment | null)[];
depthStencilAttachment?: GPURenderPassDepthStencilAttachment; depthStencilAttachment?: GPURenderPassDepthStencilAttachment;
occlusionQuerySet?: GPUQuerySet; occlusionQuerySet?: GPUQuerySet;
} }
@ -980,35 +990,38 @@ declare interface GPURenderPassColorAttachment {
view: GPUTextureView; view: GPUTextureView;
resolveTarget?: GPUTextureView; resolveTarget?: GPUTextureView;
loadValue: GPULoadOp | GPUColor; clearValue?: GPUColor;
storeOp?: GPUStoreOp; loadOp: GPULoadOp;
storeOp: GPUStoreOp;
} }
declare interface GPURenderPassDepthStencilAttachment { declare interface GPURenderPassDepthStencilAttachment {
view: GPUTextureView; view: GPUTextureView;
depthLoadValue: GPULoadOp | number; depthClearValue?: number;
depthStoreOp: GPUStoreOp; depthLoadOp?: GPULoadOp;
depthStoreOp?: GPUStoreOp;
depthReadOnly?: boolean; depthReadOnly?: boolean;
stencilLoadValue: GPULoadOp | number; stencilClearValue?: number;
stencilStoreOp: GPUStoreOp; stencilLoadOp?: GPULoadOp;
stencilStoreOp?: GPUStoreOp;
stencilReadOnly?: boolean; stencilReadOnly?: boolean;
} }
declare type GPULoadOp = "load"; declare type GPULoadOp = "load" | "clear";
declare type GPUStoreOp = "store" | "discard"; declare type GPUStoreOp = "store" | "discard";
declare class GPURenderBundle implements GPUObjectBase { declare class GPURenderBundle implements GPUObjectBase {
label: string | null; label: string;
} }
declare interface GPURenderBundleDescriptor extends GPUObjectDescriptorBase {} declare interface GPURenderBundleDescriptor extends GPUObjectDescriptorBase {}
declare class GPURenderBundleEncoder declare class GPURenderBundleEncoder
implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase {
label: string | null; label: string;
draw( draw(
vertexCount: number, vertexCount: number,
instanceCount?: number, instanceCount?: number,
@ -1060,7 +1073,7 @@ declare class GPURenderBundleEncoder
} }
declare interface GPURenderPassLayout extends GPUObjectDescriptorBase { declare interface GPURenderPassLayout extends GPUObjectDescriptorBase {
colorFormats: GPUTextureFormat[]; colorFormats: (GPUTextureFormat | null)[];
depthStencilFormat?: GPUTextureFormat; depthStencilFormat?: GPUTextureFormat;
sampleCount?: number; sampleCount?: number;
} }
@ -1071,7 +1084,7 @@ declare interface GPURenderBundleEncoderDescriptor extends GPURenderPassLayout {
} }
declare class GPUQueue implements GPUObjectBase { declare class GPUQueue implements GPUObjectBase {
label: string | null; label: string;
submit(commandBuffers: GPUCommandBuffer[]): undefined; submit(commandBuffers: GPUCommandBuffer[]): undefined;
@ -1094,7 +1107,7 @@ declare class GPUQueue implements GPUObjectBase {
} }
declare class GPUQuerySet implements GPUObjectBase { declare class GPUQuerySet implements GPUObjectBase {
label: string | null; label: string;
destroy(): undefined; destroy(): undefined;
} }
@ -1121,18 +1134,19 @@ declare interface GPUDeviceLostInfo {
readonly message: string; readonly message: string;
} }
declare type GPUErrorFilter = "out-of-memory" | "validation"; declare class GPUError {
declare class GPUOutOfMemoryError {
constructor();
}
declare class GPUValidationError {
constructor(message: string);
readonly message: string; readonly message: string;
} }
declare type GPUError = GPUOutOfMemoryError | GPUValidationError; declare type GPUErrorFilter = "out-of-memory" | "validation";
declare class GPUOutOfMemoryError extends GPUError {
constructor(message: string);
}
declare class GPUValidationError extends GPUError {
constructor(message: string);
}
declare class GPUUncapturedErrorEvent extends Event { declare class GPUUncapturedErrorEvent extends Event {
constructor( constructor(

View file

@ -1,9 +1,6 @@
struct PrimeIndices { @group(0)
data: [[stride(4)]] array<u32>; @binding(0)
}; // this is used as both input and output for convenience var<storage, read_write> v_indices: array<u32>; // this is used as both input and output for convenience
[[group(0), binding(0)]]
var<storage, read_write> v_indices: PrimeIndices;
// The Collatz Conjecture states that for any integer n: // The Collatz Conjecture states that for any integer n:
// If n is even, n = n/2 // If n is even, n = n/2
@ -34,7 +31,8 @@ fn collatz_iterations(n_base: u32) -> u32{
return i; return i;
} }
[[stage(compute), workgroup_size(1)]] @compute
fn main([[builtin(global_invocation_id)]] global_id: vec3<u32>) { @workgroup_size(1)
v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]); fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
v_indices[global_id.x] = collatz_iterations(v_indices[global_id.x]);
} }

View file

@ -1,10 +1,11 @@
[[stage(vertex)]] @vertex
fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4<f32> { fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
let x = f32(i32(in_vertex_index) - 1); let x = f32(i32(in_vertex_index) - 1);
let y = f32(i32(in_vertex_index & 1u) * 2 - 1); let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
return vec4<f32>(x, y, 0.0, 1.0); return vec4<f32>(x, y, 0.0, 1.0);
} }
[[stage(fragment)]]
fn fs_main() -> [[location(0)]] vec4<f32> { @fragment
fn fs_main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0); return vec4<f32>(1.0, 0.0, 0.0, 1.0);
} }

View file

@ -56,6 +56,7 @@ Deno.test({
storageBuffer.unmap(); storageBuffer.unmap();
const computePipeline = device.createComputePipeline({ const computePipeline = device.createComputePipeline({
layout: "auto",
compute: { compute: {
module: shaderModule, module: shaderModule,
entryPoint: "main", entryPoint: "main",
@ -81,8 +82,8 @@ Deno.test({
computePass.setPipeline(computePipeline); computePass.setPipeline(computePipeline);
computePass.setBindGroup(0, bindGroup); computePass.setBindGroup(0, bindGroup);
computePass.insertDebugMarker("compute collatz iterations"); computePass.insertDebugMarker("compute collatz iterations");
computePass.dispatch(numbers.length); computePass.dispatchWorkgroups(numbers.length);
computePass.endPass(); computePass.end();
encoder.copyBufferToBuffer(storageBuffer, 0, stagingBuffer, 0, size); encoder.copyBufferToBuffer(storageBuffer, 0, stagingBuffer, 0, size);
@ -172,13 +173,14 @@ Deno.test({
{ {
view, view,
storeOp: "store", storeOp: "store",
loadValue: [0, 1, 0, 1], loadOp: "clear",
clearValue: [0, 1, 0, 1],
}, },
], ],
}); });
renderPass.setPipeline(renderPipeline); renderPass.setPipeline(renderPipeline);
renderPass.draw(3, 1); renderPass.draw(3, 1);
renderPass.endPass(); renderPass.end();
encoder.copyTextureToBuffer( encoder.copyTextureToBuffer(
{ {

View file

@ -1,4 +1,4 @@
# Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. # Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
[package] [package]
name = "deno_webgpu" name = "deno_webgpu"
@ -14,5 +14,5 @@ description = "WebGPU implementation for Deno"
deno_core = { version = "0.143.0", path = "../../core" } deno_core = { version = "0.143.0", path = "../../core" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.17", features = ["full"] } tokio = { version = "1.17", features = ["full"] }
wgpu-core = { version = "0.12", features = ["trace", "replay", "serde"] } wgpu-core = { version = "0.13", features = ["trace", "replay", "serde"] }
wgpu-types = { version = "0.12", features = ["trace", "replay", "serde"] } wgpu-types = { version = "0.13", features = ["trace", "replay", "serde"] }

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright 2018-2021 the Deno authors Copyright 2018-2022 the Deno authors
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

File diff suppressed because it is too large Load diff

View file

@ -120,6 +120,7 @@
"texture-compression-astc", "texture-compression-astc",
"timestamp-query", "timestamp-query",
"indirect-first-instance", "indirect-first-instance",
"shader-f16",
// extended from spec // extended from spec
"mappable-primary-buffers", "mappable-primary-buffers",
"texture-binding-array", "texture-binding-array",
@ -341,6 +342,8 @@
"depth24plus", "depth24plus",
"depth24plus-stencil8", "depth24plus-stencil8",
"depth32float", "depth32float",
"depth24unorm-stencil8",
"depth32float-stencil8",
"bc1-rgba-unorm", "bc1-rgba-unorm",
"bc1-rgba-unorm-srgb", "bc1-rgba-unorm-srgb",
"bc2-rgba-unorm", "bc2-rgba-unorm",
@ -393,8 +396,6 @@
"astc-12x10-unorm-srgb", "astc-12x10-unorm-srgb",
"astc-12x12-unorm", "astc-12x12-unorm",
"astc-12x12-unorm-srgb", "astc-12x12-unorm-srgb",
"depth24unorm-stencil8",
"depth32float-stencil8",
], ],
); );
@ -539,6 +540,15 @@
], ],
); );
// ENUM: GPUMipmapFilterMode
webidl.converters["GPUMipmapFilterMode"] = webidl.createEnumConverter(
"GPUMipmapFilterMode",
[
"nearest",
"linear",
],
);
// ENUM: GPUCompareFunction // ENUM: GPUCompareFunction
webidl.converters["GPUCompareFunction"] = webidl.createEnumConverter( webidl.converters["GPUCompareFunction"] = webidl.createEnumConverter(
"GPUCompareFunction", "GPUCompareFunction",
@ -583,7 +593,7 @@
}, },
{ {
key: "mipmapFilter", key: "mipmapFilter",
converter: webidl.converters["GPUFilterMode"], converter: webidl.converters["GPUMipmapFilterMode"],
defaultValue: "nearest", defaultValue: "nearest",
}, },
{ {
@ -935,9 +945,26 @@
// GPUCompilationInfo.prototype, // GPUCompilationInfo.prototype,
// ); // );
webidl.converters["GPUAutoLayoutMode"] = webidl.createEnumConverter(
"GPUAutoLayoutMode",
[
"auto",
],
);
webidl.converters["GPUPipelineLayout or GPUAutoLayoutMode"] = (V, opts) => {
if (typeof V === "object") {
return webidl.converters["GPUPipelineLayout"](V, opts);
}
return webidl.converters["GPUAutoLayoutMode"](V, opts);
};
// DICTIONARY: GPUPipelineDescriptorBase // DICTIONARY: GPUPipelineDescriptorBase
const dictMembersGPUPipelineDescriptorBase = [ const dictMembersGPUPipelineDescriptorBase = [
{ key: "layout", converter: webidl.converters["GPUPipelineLayout"] }, {
key: "layout",
converter: webidl.converters["GPUPipelineLayout or GPUAutoLayoutMode"],
},
]; ];
webidl.converters["GPUPipelineDescriptorBase"] = webidl webidl.converters["GPUPipelineDescriptorBase"] = webidl
.createDictionaryConverter( .createDictionaryConverter(
@ -1427,7 +1454,9 @@
{ {
key: "targets", key: "targets",
converter: webidl.createSequenceConverter( converter: webidl.createSequenceConverter(
webidl.converters["GPUColorTargetState"], webidl.createNullableConverter(
webidl.converters["GPUColorTargetState"],
),
), ),
required: true, required: true,
}, },
@ -1675,6 +1704,7 @@
// ENUM: GPULoadOp // ENUM: GPULoadOp
webidl.converters["GPULoadOp"] = webidl.createEnumConverter("GPULoadOp", [ webidl.converters["GPULoadOp"] = webidl.createEnumConverter("GPULoadOp", [
"load", "load",
"clear",
]); ]);
// DICTIONARY: GPUColorDict // DICTIONARY: GPUColorDict
@ -1724,8 +1754,12 @@
}, },
{ key: "resolveTarget", converter: webidl.converters["GPUTextureView"] }, { key: "resolveTarget", converter: webidl.converters["GPUTextureView"] },
{ {
key: "loadValue", key: "clearValue",
converter: webidl.converters.any, /** put union here! **/ converter: webidl.converters["GPUColor"],
},
{
key: "loadOp",
converter: webidl.converters["GPULoadOp"],
required: true, required: true,
}, },
{ {
@ -1748,14 +1782,17 @@
required: true, required: true,
}, },
{ {
key: "depthLoadValue", key: "depthClearValue",
converter: webidl.converters.any, /** put union here! **/ converter: webidl.converters["float"],
required: true, defaultValue: 0,
},
{
key: "depthLoadOp",
converter: webidl.converters["GPULoadOp"],
}, },
{ {
key: "depthStoreOp", key: "depthStoreOp",
converter: webidl.converters["GPUStoreOp"], converter: webidl.converters["GPUStoreOp"],
required: true,
}, },
{ {
key: "depthReadOnly", key: "depthReadOnly",
@ -1763,14 +1800,17 @@
defaultValue: false, defaultValue: false,
}, },
{ {
key: "stencilLoadValue", key: "stencilClearValue",
converter: webidl.converters.any, /** put union here! **/ converter: webidl.converters["GPUStencilValue"],
required: true, defaultValue: 0,
},
{
key: "stencilLoadOp",
converter: webidl.converters["GPULoadOp"],
}, },
{ {
key: "stencilStoreOp", key: "stencilStoreOp",
converter: webidl.converters["GPUStoreOp"], converter: webidl.converters["GPUStoreOp"],
required: true,
}, },
{ {
key: "stencilReadOnly", key: "stencilReadOnly",
@ -1795,7 +1835,9 @@
{ {
key: "colorAttachments", key: "colorAttachments",
converter: webidl.createSequenceConverter( converter: webidl.createSequenceConverter(
webidl.converters["GPURenderPassColorAttachment"], webidl.createNullableConverter(
webidl.converters["GPURenderPassColorAttachment"],
),
), ),
required: true, required: true,
}, },
@ -1840,7 +1882,7 @@
{ {
key: "colorFormats", key: "colorFormats",
converter: webidl.createSequenceConverter( converter: webidl.createSequenceConverter(
webidl.converters["GPUTextureFormat"], webidl.createNullableConverter(webidl.converters["GPUTextureFormat"]),
), ),
required: true, required: true,
}, },

View file

@ -2,11 +2,11 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use super::error::WebGpuResult; use super::error::WebGpuResult;
@ -122,7 +122,7 @@ impl From<GpuStorageTextureAccess> for wgpu_types::StorageTextureAccess {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuBindGroupLayoutEntry { pub struct GpuBindGroupLayoutEntry {
binding: u32, binding: u32,
visibility: u32, visibility: u32,
#[serde(flatten)] #[serde(flatten)]
@ -138,13 +138,9 @@ enum GpuBindingType {
StorageTexture(GpuStorageTextureBindingLayout), StorageTexture(GpuStorageTextureBindingLayout),
} }
impl TryFrom<GpuBindingType> for wgpu_types::BindingType { impl From<GpuBindingType> for wgpu_types::BindingType {
type Error = AnyError; fn from(binding_type: GpuBindingType) -> wgpu_types::BindingType {
match binding_type {
fn try_from(
binding_type: GpuBindingType,
) -> Result<wgpu_types::BindingType, Self::Error> {
let binding_type = match binding_type {
GpuBindingType::Buffer(buffer) => wgpu_types::BindingType::Buffer { GpuBindingType::Buffer(buffer) => wgpu_types::BindingType::Buffer {
ty: buffer.r#type.into(), ty: buffer.r#type.into(),
has_dynamic_offset: buffer.has_dynamic_offset, has_dynamic_offset: buffer.has_dynamic_offset,
@ -165,44 +161,38 @@ impl TryFrom<GpuBindingType> for wgpu_types::BindingType {
view_dimension: storage_texture.view_dimension, view_dimension: storage_texture.view_dimension,
} }
} }
}; }
Ok(binding_type)
} }
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateBindGroupLayoutArgs {
device_rid: ResourceId,
label: Option<String>,
entries: Vec<GpuBindGroupLayoutEntry>,
}
#[op] #[op]
pub fn op_webgpu_create_bind_group_layout( pub fn op_webgpu_create_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: CreateBindGroupLayoutArgs, device_rid: ResourceId,
label: Option<String>,
entries: Vec<GpuBindGroupLayoutEntry>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let mut entries = vec![]; let entries = entries
.into_iter()
for entry in args.entries { .map(|entry| {
entries.push(wgpu_types::BindGroupLayoutEntry { wgpu_types::BindGroupLayoutEntry {
binding: entry.binding, binding: entry.binding,
visibility: wgpu_types::ShaderStages::from_bits(entry.visibility) visibility: wgpu_types::ShaderStages::from_bits(entry.visibility)
.unwrap(), .unwrap(),
ty: entry.binding_type.try_into()?, ty: entry.binding_type.into(),
count: None, // native-only count: None, // native-only
}); }
} })
.collect::<Vec<_>>();
let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor { let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
entries: Cow::from(entries), entries: Cow::from(entries),
}; };
@ -213,35 +203,30 @@ pub fn op_webgpu_create_bind_group_layout(
) => state, WebGpuBindGroupLayout) ) => state, WebGpuBindGroupLayout)
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatePipelineLayoutArgs {
device_rid: ResourceId,
label: Option<String>,
bind_group_layouts: Vec<u32>,
}
#[op] #[op]
pub fn op_webgpu_create_pipeline_layout( pub fn op_webgpu_create_pipeline_layout(
state: &mut OpState, state: &mut OpState,
args: CreatePipelineLayoutArgs, device_rid: ResourceId,
label: Option<String>,
bind_group_layouts: Vec<u32>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let mut bind_group_layouts = vec![]; let bind_group_layouts = bind_group_layouts
.into_iter()
for rid in &args.bind_group_layouts { .map(|rid| {
let bind_group_layout = let bind_group_layout =
state.resource_table.get::<WebGpuBindGroupLayout>(*rid)?; state.resource_table.get::<WebGpuBindGroupLayout>(rid)?;
bind_group_layouts.push(bind_group_layout.0); Ok(bind_group_layout.0)
} })
.collect::<Result<Vec<_>, AnyError>>()?;
let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor { let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
bind_group_layouts: Cow::from(bind_group_layouts), bind_group_layouts: Cow::from(bind_group_layouts),
push_constant_ranges: Default::default(), push_constant_ranges: Default::default(),
}; };
@ -255,7 +240,7 @@ pub fn op_webgpu_create_pipeline_layout(
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuBindGroupEntry { pub struct GpuBindGroupEntry {
binding: u32, binding: u32,
kind: String, kind: String,
resource: ResourceId, resource: ResourceId,
@ -263,73 +248,68 @@ struct GpuBindGroupEntry {
size: Option<u64>, size: Option<u64>,
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_create_bind_group(
pub struct CreateBindGroupArgs { state: &mut OpState,
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
layout: ResourceId, layout: ResourceId,
entries: Vec<GpuBindGroupEntry>, entries: Vec<GpuBindGroupEntry>,
}
#[op]
pub fn op_webgpu_create_bind_group(
state: &mut OpState,
args: CreateBindGroupArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let mut entries = vec![]; let entries = entries
.into_iter()
.map(|entry| {
Ok(wgpu_core::binding_model::BindGroupEntry {
binding: entry.binding,
resource: match entry.kind.as_str() {
"GPUSampler" => {
let sampler_resource =
state
.resource_table
.get::<super::sampler::WebGpuSampler>(entry.resource)?;
wgpu_core::binding_model::BindingResource::Sampler(
sampler_resource.0,
)
}
"GPUTextureView" => {
let texture_view_resource =
state
.resource_table
.get::<super::texture::WebGpuTextureView>(entry.resource)?;
wgpu_core::binding_model::BindingResource::TextureView(
texture_view_resource.0,
)
}
"GPUBufferBinding" => {
let buffer_resource =
state
.resource_table
.get::<super::buffer::WebGpuBuffer>(entry.resource)?;
wgpu_core::binding_model::BindingResource::Buffer(
wgpu_core::binding_model::BufferBinding {
buffer_id: buffer_resource.0,
offset: entry.offset.unwrap_or(0),
size: std::num::NonZeroU64::new(entry.size.unwrap_or(0)),
},
)
}
_ => unreachable!(),
},
})
})
.collect::<Result<Vec<_>, AnyError>>()?;
for entry in &args.entries { let bind_group_layout =
let e = wgpu_core::binding_model::BindGroupEntry { state.resource_table.get::<WebGpuBindGroupLayout>(layout)?;
binding: entry.binding,
resource: match entry.kind.as_str() {
"GPUSampler" => {
let sampler_resource =
state
.resource_table
.get::<super::sampler::WebGpuSampler>(entry.resource)?;
wgpu_core::binding_model::BindingResource::Sampler(sampler_resource.0)
}
"GPUTextureView" => {
let texture_view_resource =
state
.resource_table
.get::<super::texture::WebGpuTextureView>(entry.resource)?;
wgpu_core::binding_model::BindingResource::TextureView(
texture_view_resource.0,
)
}
"GPUBufferBinding" => {
let buffer_resource =
state
.resource_table
.get::<super::buffer::WebGpuBuffer>(entry.resource)?;
wgpu_core::binding_model::BindingResource::Buffer(
wgpu_core::binding_model::BufferBinding {
buffer_id: buffer_resource.0,
offset: entry.offset.unwrap_or(0),
size: std::num::NonZeroU64::new(entry.size.unwrap_or(0)),
},
)
}
_ => unreachable!(),
},
};
entries.push(e);
}
let bind_group_layout = state
.resource_table
.get::<WebGpuBindGroupLayout>(args.layout)?;
let descriptor = wgpu_core::binding_model::BindGroupDescriptor { let descriptor = wgpu_core::binding_model::BindGroupDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
layout: bind_group_layout.0, layout: bind_group_layout.0,
entries: Cow::from(entries), entries: Cow::from(entries),
}; };

View file

@ -4,14 +4,13 @@ use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::channel::oneshot; use deno_core::futures::channel::oneshot;
use deno_core::op; use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::convert::TryFrom;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
@ -32,33 +31,27 @@ impl Resource for WebGpuBufferMapped {
} }
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_create_buffer(
pub struct CreateBufferArgs { state: &mut OpState,
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
size: u64, size: u64,
usage: u32, usage: u32,
mapped_at_creation: bool, mapped_at_creation: bool,
}
#[op]
pub fn op_webgpu_create_buffer(
state: &mut OpState,
args: CreateBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let descriptor = wgpu_core::resource::BufferDescriptor { let descriptor = wgpu_core::resource::BufferDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
size: args.size, size,
usage: wgpu_types::BufferUsages::from_bits(args.usage) usage: wgpu_types::BufferUsages::from_bits(usage)
.ok_or_else(|| type_error("usage is not valid"))?, .ok_or_else(|| type_error("usage is not valid"))?,
mapped_at_creation: args.mapped_at_creation, mapped_at_creation,
}; };
gfx_put!(device => instance.device_create_buffer( gfx_put!(device => instance.device_create_buffer(
@ -68,20 +61,14 @@ pub fn op_webgpu_create_buffer(
) => state, WebGpuBuffer) ) => state, WebGpuBuffer)
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub async fn op_webgpu_buffer_get_map_async(
pub struct BufferGetMapAsyncArgs { state: Rc<RefCell<OpState>>,
buffer_rid: ResourceId, buffer_rid: ResourceId,
device_rid: ResourceId, device_rid: ResourceId,
mode: u32, mode: u32,
offset: u64, offset: u64,
size: u64, size: u64,
}
#[op]
pub async fn op_webgpu_buffer_get_map_async(
state: Rc<RefCell<OpState>>,
args: BufferGetMapAsyncArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let (sender, receiver) = oneshot::channel::<Result<(), AnyError>>(); let (sender, receiver) = oneshot::channel::<Result<(), AnyError>>();
@ -90,47 +77,36 @@ pub async fn op_webgpu_buffer_get_map_async(
let state_ = state.borrow(); let state_ = state.borrow();
let instance = state_.borrow::<super::Instance>(); let instance = state_.borrow::<super::Instance>();
let buffer_resource = let buffer_resource =
state_.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?; state_.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
let buffer = buffer_resource.0; let buffer = buffer_resource.0;
let device_resource = state_ let device_resource = state_
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
device = device_resource.0; device = device_resource.0;
let boxed_sender = Box::new(sender); let callback = Box::new(move |status| {
let sender_ptr = Box::into_raw(boxed_sender) as *mut u8; sender
extern "C" fn buffer_map_future_wrapper(
status: wgpu_core::resource::BufferMapAsyncStatus,
user_data: *mut u8,
) {
let sender_ptr = user_data as *mut oneshot::Sender<Result<(), AnyError>>;
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)]
let boxed_sender = unsafe { Box::from_raw(sender_ptr) };
boxed_sender
.send(match status { .send(match status {
wgpu_core::resource::BufferMapAsyncStatus::Success => Ok(()), wgpu_core::resource::BufferMapAsyncStatus::Success => Ok(()),
_ => unreachable!(), // TODO _ => unreachable!(), // TODO
}) })
.unwrap(); .unwrap();
} });
// TODO(lucacasonato): error handling // TODO(lucacasonato): error handling
let maybe_err = gfx_select!(buffer => instance.buffer_map_async( let maybe_err = gfx_select!(buffer => instance.buffer_map_async(
buffer, buffer,
args.offset..(args.offset + args.size), offset..(offset + size),
wgpu_core::resource::BufferMapOperation { wgpu_core::resource::BufferMapOperation {
host: match args.mode { host: match mode {
1 => wgpu_core::device::HostMap::Read, 1 => wgpu_core::device::HostMap::Read,
2 => wgpu_core::device::HostMap::Write, 2 => wgpu_core::device::HostMap::Write,
_ => unreachable!(), _ => unreachable!(),
}, },
callback: buffer_map_future_wrapper, callback: wgpu_core::resource::BufferMapCallback::from_rust(callback),
user_data: sender_ptr, }
} ))
)) .err();
.err();
if maybe_err.is_some() { if maybe_err.is_some() {
return Ok(WebGpuResult::maybe_err(maybe_err)); return Ok(WebGpuResult::maybe_err(maybe_err));
@ -144,7 +120,7 @@ pub async fn op_webgpu_buffer_get_map_async(
{ {
let state = state.borrow(); let state = state.borrow();
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
gfx_select!(device => instance.device_poll(device, false)).unwrap() gfx_select!(device => instance.device_poll(device, wgpu_types::Maintain::Wait)).unwrap();
} }
tokio::time::sleep(Duration::from_millis(10)).await; tokio::time::sleep(Duration::from_millis(10)).await;
} }
@ -163,39 +139,32 @@ pub async fn op_webgpu_buffer_get_map_async(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BufferGetMappedRangeArgs {
buffer_rid: ResourceId,
offset: u64,
size: Option<u64>,
}
#[op] #[op]
pub fn op_webgpu_buffer_get_mapped_range( pub fn op_webgpu_buffer_get_mapped_range(
state: &mut OpState, state: &mut OpState,
args: BufferGetMappedRangeArgs, buffer_rid: ResourceId,
mut zero_copy: ZeroCopyBuf, offset: u64,
size: Option<u64>,
mut buf: ZeroCopyBuf,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let buffer_resource = let buffer_resource = state.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
state.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?;
let buffer = buffer_resource.0; let buffer = buffer_resource.0;
let (slice_pointer, range_size) = let (slice_pointer, range_size) =
gfx_select!(buffer => instance.buffer_get_mapped_range( gfx_select!(buffer => instance.buffer_get_mapped_range(
buffer, buffer,
args.offset, offset,
args.size size
)) ))
.map_err(|e| DomExceptionOperationError::new(&e.to_string()))?; .map_err(|e| DomExceptionOperationError::new(&e.to_string()))?;
// TODO(bartlomieju): // TODO(crowlKats):
#[allow(clippy::undocumented_unsafe_blocks)] #[allow(clippy::undocumented_unsafe_blocks)]
let slice = unsafe { let slice = unsafe {
std::slice::from_raw_parts_mut(slice_pointer, range_size as usize) std::slice::from_raw_parts_mut(slice_pointer, range_size as usize)
}; };
zero_copy.copy_from_slice(slice); buf.copy_from_slice(slice);
let rid = state let rid = state
.resource_table .resource_table
@ -204,35 +173,27 @@ pub fn op_webgpu_buffer_get_mapped_range(
Ok(WebGpuResult::rid(rid)) Ok(WebGpuResult::rid(rid))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BufferUnmapArgs {
buffer_rid: ResourceId,
mapped_rid: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_buffer_unmap( pub fn op_webgpu_buffer_unmap(
state: &mut OpState, state: &mut OpState,
args: BufferUnmapArgs, buffer_rid: ResourceId,
zero_copy: Option<ZeroCopyBuf>, mapped_rid: ResourceId,
buf: Option<ZeroCopyBuf>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let mapped_resource = state let mapped_resource = state
.resource_table .resource_table
.take::<WebGpuBufferMapped>(args.mapped_rid)?; .take::<WebGpuBufferMapped>(mapped_rid)?;
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let buffer_resource = let buffer_resource = state.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
state.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?;
let buffer = buffer_resource.0; let buffer = buffer_resource.0;
let slice_pointer = mapped_resource.0; if let Some(buf) = buf {
let size = mapped_resource.1; // TODO(crowlKats):
if let Some(buffer) = zero_copy {
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)] #[allow(clippy::undocumented_unsafe_blocks)]
let slice = unsafe { std::slice::from_raw_parts_mut(slice_pointer, size) }; let slice = unsafe {
slice.copy_from_slice(&buffer); std::slice::from_raw_parts_mut(mapped_resource.0, mapped_resource.1)
};
slice.copy_from_slice(&buf);
} }
gfx_ok!(buffer => instance.buffer_unmap(buffer)) gfx_ok!(buffer => instance.buffer_unmap(buffer))

View file

@ -2,9 +2,10 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
@ -33,7 +34,7 @@ impl Resource for WebGpuRenderBundle {
pub struct CreateRenderBundleEncoderArgs { pub struct CreateRenderBundleEncoderArgs {
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
color_formats: Vec<wgpu_types::TextureFormat>, color_formats: Vec<Option<wgpu_types::TextureFormat>>,
depth_stencil_format: Option<wgpu_types::TextureFormat>, depth_stencil_format: Option<wgpu_types::TextureFormat>,
sample_count: u32, sample_count: u32,
depth_read_only: bool, depth_read_only: bool,
@ -50,25 +51,17 @@ pub fn op_webgpu_create_render_bundle_encoder(
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let mut color_formats = vec![]; let depth_stencil = args.depth_stencil_format.map(|format| {
wgpu_types::RenderBundleDepthStencil {
for format in args.color_formats {
color_formats.push(format);
}
let depth_stencil = if let Some(format) = args.depth_stencil_format {
Some(wgpu_types::RenderBundleDepthStencil {
format, format,
depth_read_only: args.depth_read_only, depth_read_only: args.depth_read_only,
stencil_read_only: args.stencil_read_only, stencil_read_only: args.stencil_read_only,
}) }
} else { });
None
};
let descriptor = wgpu_core::command::RenderBundleEncoderDescriptor { let descriptor = wgpu_core::command::RenderBundleEncoderDescriptor {
label: args.label.map(Cow::from), label: args.label.map(Cow::from),
color_formats: Cow::from(color_formats), color_formats: Cow::from(args.color_formats),
sample_count: args.sample_count, sample_count: args.sample_count,
depth_stencil, depth_stencil,
multiview: None, multiview: None,
@ -93,22 +86,16 @@ pub fn op_webgpu_create_render_bundle_encoder(
Ok(WebGpuResult::rid_err(rid, maybe_err)) Ok(WebGpuResult::rid_err(rid, maybe_err))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderFinishArgs {
render_bundle_encoder_rid: ResourceId,
label: Option<String>,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_finish( pub fn op_webgpu_render_bundle_encoder_finish(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderFinishArgs, render_bundle_encoder_rid: ResourceId,
label: Option<String>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.take::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .take::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
let render_bundle_encoder = Rc::try_unwrap(render_bundle_encoder_resource) let render_bundle_encoder = Rc::try_unwrap(render_bundle_encoder_resource)
.ok() .ok()
.expect("unwrapping render_bundle_encoder_resource should succeed") .expect("unwrapping render_bundle_encoder_resource should succeed")
@ -119,48 +106,42 @@ pub fn op_webgpu_render_bundle_encoder_finish(
gfx_put!(render_bundle_encoder.parent() => instance.render_bundle_encoder_finish( gfx_put!(render_bundle_encoder.parent() => instance.render_bundle_encoder_finish(
render_bundle_encoder, render_bundle_encoder,
&wgpu_core::command::RenderBundleDescriptor { &wgpu_core::command::RenderBundleDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
}, },
std::marker::PhantomData std::marker::PhantomData
) => state, WebGpuRenderBundle) ) => state, WebGpuRenderBundle)
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_bundle_encoder_set_bind_group(
pub struct RenderBundleEncoderSetBindGroupArgs { state: &mut OpState,
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
index: u32, index: u32,
bind_group: ResourceId, bind_group: ResourceId,
dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize, dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
}
#[op]
pub fn op_webgpu_render_bundle_encoder_set_bind_group(
state: &mut OpState,
args: RenderBundleEncoderSetBindGroupArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let bind_group_resource = let bind_group_resource =
state state
.resource_table .resource_table
.get::<super::binding::WebGpuBindGroup>(args.bind_group)?; .get::<super::binding::WebGpuBindGroup>(bind_group)?;
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
// Align the data // Align the data
assert!(args.dynamic_offsets_data.len() % std::mem::size_of::<u32>() == 0); assert!(dynamic_offsets_data.len() % std::mem::size_of::<u32>() == 0);
let (prefix, dynamic_offsets_data, suffix) = let (prefix, dynamic_offsets_data, suffix) =
// SAFETY: A u8 to u32 cast is safe because we asserted that the length is a // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
// multiple of 4. // multiple of 4.
unsafe { args.dynamic_offsets_data.align_to::<u32>() }; unsafe { dynamic_offsets_data.align_to::<u32>() };
assert!(prefix.is_empty()); assert!(prefix.is_empty());
assert!(suffix.is_empty()); assert!(suffix.is_empty());
let start = args.dynamic_offsets_data_start; let start = dynamic_offsets_data_start;
let len = args.dynamic_offsets_data_length; let len = dynamic_offsets_data_length;
// Assert that length and start are both in bounds // Assert that length and start are both in bounds
assert!(start <= dynamic_offsets_data.len()); assert!(start <= dynamic_offsets_data.len());
@ -173,7 +154,7 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group(
unsafe { unsafe {
wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
args.index, index,
bind_group_resource.0, bind_group_resource.0,
dynamic_offsets_data.as_ptr(), dynamic_offsets_data.as_ptr(),
dynamic_offsets_data.len(), dynamic_offsets_data.len(),
@ -183,24 +164,18 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderPushDebugGroupArgs {
render_bundle_encoder_rid: ResourceId,
group_label: String,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_push_debug_group( pub fn op_webgpu_render_bundle_encoder_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderPushDebugGroupArgs, render_bundle_encoder_rid: ResourceId,
group_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
let label = std::ffi::CString::new(args.group_label).unwrap(); let label = std::ffi::CString::new(group_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {
@ -213,21 +188,15 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderPopDebugGroupArgs {
render_bundle_encoder_rid: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_pop_debug_group( pub fn op_webgpu_render_bundle_encoder_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderPopDebugGroupArgs, render_bundle_encoder_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_pop_debug_group( wgpu_core::command::bundle_ffi::wgpu_render_bundle_pop_debug_group(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
@ -236,24 +205,18 @@ pub fn op_webgpu_render_bundle_encoder_pop_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderInsertDebugMarkerArgs {
render_bundle_encoder_rid: ResourceId,
marker_label: String,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_insert_debug_marker( pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderInsertDebugMarkerArgs, render_bundle_encoder_rid: ResourceId,
marker_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
let label = std::ffi::CString::new(args.marker_label).unwrap(); let label = std::ffi::CString::new(marker_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {
@ -266,26 +229,20 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderSetPipelineArgs {
render_bundle_encoder_rid: ResourceId,
pipeline: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_set_pipeline( pub fn op_webgpu_render_bundle_encoder_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderSetPipelineArgs, render_bundle_encoder_rid: ResourceId,
pipeline: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pipeline_resource = let render_pipeline_resource =
state state
.resource_table .resource_table
.get::<super::pipeline::WebGpuRenderPipeline>(args.pipeline)?; .get::<super::pipeline::WebGpuRenderPipeline>(pipeline)?;
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_pipeline( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_pipeline(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
@ -295,165 +252,135 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
pub struct RenderBundleEncoderSetIndexBufferArgs { state: &mut OpState,
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
buffer: ResourceId, buffer: ResourceId,
index_format: wgpu_types::IndexFormat, index_format: wgpu_types::IndexFormat,
offset: u64, offset: u64,
size: u64, size: u64,
}
#[op]
pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
state: &mut OpState,
args: RenderBundleEncoderSetIndexBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.buffer)?; .get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
render_bundle_encoder_resource render_bundle_encoder_resource
.0 .0
.borrow_mut() .borrow_mut()
.set_index_buffer( .set_index_buffer(
buffer_resource.0, buffer_resource.0,
args.index_format, index_format,
args.offset, offset,
std::num::NonZeroU64::new(args.size), std::num::NonZeroU64::new(size),
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer(
pub struct RenderBundleEncoderSetVertexBufferArgs { state: &mut OpState,
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
slot: u32, slot: u32,
buffer: ResourceId, buffer: ResourceId,
offset: u64, offset: u64,
size: u64, size: u64,
}
#[op]
pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer(
state: &mut OpState,
args: RenderBundleEncoderSetVertexBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.buffer)?; .get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_vertex_buffer( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_vertex_buffer(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
args.slot, slot,
buffer_resource.0, buffer_resource.0,
args.offset, offset,
std::num::NonZeroU64::new(args.size), std::num::NonZeroU64::new(size),
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderDrawArgs {
render_bundle_encoder_rid: ResourceId,
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_draw( pub fn op_webgpu_render_bundle_encoder_draw(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderDrawArgs, render_bundle_encoder_rid: ResourceId,
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw( wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
args.vertex_count, vertex_count,
args.instance_count, instance_count,
args.first_vertex, first_vertex,
args.first_instance, first_instance,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_bundle_encoder_draw_indexed(
pub struct RenderBundleEncoderDrawIndexedArgs { state: &mut OpState,
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
index_count: u32, index_count: u32,
instance_count: u32, instance_count: u32,
first_index: u32, first_index: u32,
base_vertex: i32, base_vertex: i32,
first_instance: u32, first_instance: u32,
}
#[op]
pub fn op_webgpu_render_bundle_encoder_draw_indexed(
state: &mut OpState,
args: RenderBundleEncoderDrawIndexedArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indexed( wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indexed(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
args.index_count, index_count,
args.instance_count, instance_count,
args.first_index, first_index,
args.base_vertex, base_vertex,
args.first_instance, first_instance,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderDrawIndirectArgs {
render_bundle_encoder_rid: ResourceId,
indirect_buffer: ResourceId,
indirect_offset: u64,
}
#[op] #[op]
pub fn op_webgpu_render_bundle_encoder_draw_indirect( pub fn op_webgpu_render_bundle_encoder_draw_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderDrawIndirectArgs, render_bundle_encoder_rid: ResourceId,
indirect_buffer: ResourceId,
indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?; .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
let render_bundle_encoder_resource = let render_bundle_encoder_resource =
state state
.resource_table .resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?; .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indirect( wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indirect(
&mut render_bundle_encoder_resource.0.borrow_mut(), &mut render_bundle_encoder_resource.0.borrow_mut(),
buffer_resource.0, buffer_resource.0,
args.indirect_offset, indirect_offset,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())

View file

@ -2,8 +2,9 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
@ -29,27 +30,20 @@ impl Resource for WebGpuCommandBuffer {
} }
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateCommandEncoderArgs {
device_rid: ResourceId,
label: Option<String>,
_measure_execution_time: Option<bool>, // not yet implemented
}
#[op] #[op]
pub fn op_webgpu_create_command_encoder( pub fn op_webgpu_create_command_encoder(
state: &mut OpState, state: &mut OpState,
args: CreateCommandEncoderArgs, device_rid: ResourceId,
label: Option<String>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let descriptor = wgpu_types::CommandEncoderDescriptor { let descriptor = wgpu_types::CommandEncoderDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
}; };
gfx_put!(device => instance.device_create_command_encoder( gfx_put!(device => instance.device_create_command_encoder(
@ -64,134 +58,104 @@ pub fn op_webgpu_create_command_encoder(
pub struct GpuRenderPassColorAttachment { pub struct GpuRenderPassColorAttachment {
view: ResourceId, view: ResourceId,
resolve_target: Option<ResourceId>, resolve_target: Option<ResourceId>,
load_op: GpuLoadOp<wgpu_types::Color>, clear_value: Option<wgpu_types::Color>,
load_op: wgpu_core::command::LoadOp,
store_op: wgpu_core::command::StoreOp, store_op: wgpu_core::command::StoreOp,
} }
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuLoadOp<T> {
Load,
Clear(T),
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuRenderPassDepthStencilAttachment { pub struct GpuRenderPassDepthStencilAttachment {
view: ResourceId, view: ResourceId,
depth_load_op: GpuLoadOp<f32>, depth_clear_value: f32,
depth_load_op: wgpu_core::command::LoadOp,
depth_store_op: wgpu_core::command::StoreOp, depth_store_op: wgpu_core::command::StoreOp,
depth_read_only: bool, depth_read_only: bool,
stencil_load_op: GpuLoadOp<u32>, stencil_clear_value: u32,
stencil_load_op: wgpu_core::command::LoadOp,
stencil_store_op: wgpu_core::command::StoreOp, stencil_store_op: wgpu_core::command::StoreOp,
stencil_read_only: bool, stencil_read_only: bool,
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderBeginRenderPassArgs {
command_encoder_rid: ResourceId,
label: Option<String>,
color_attachments: Vec<GpuRenderPassColorAttachment>,
depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
_occlusion_query_set: Option<u32>, // not yet implemented
}
#[op] #[op]
pub fn op_webgpu_command_encoder_begin_render_pass( pub fn op_webgpu_command_encoder_begin_render_pass(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderBeginRenderPassArgs, command_encoder_rid: ResourceId,
label: Option<String>,
color_attachments: Vec<Option<GpuRenderPassColorAttachment>>,
depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
_occlusion_query_set: Option<u32>, // not yet implemented
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let mut color_attachments = vec![]; let color_attachments = color_attachments
.into_iter()
.map(|color_attachment| {
let rp_at = if let Some(at) = color_attachment.as_ref() {
let texture_view_resource =
state
.resource_table
.get::<super::texture::WebGpuTextureView>(at.view)?;
for color_attachment in args.color_attachments { let resolve_target = at
let texture_view_resource = .resolve_target
state .map(|rid| {
.resource_table state
.get::<super::texture::WebGpuTextureView>(color_attachment.view)?; .resource_table
.get::<super::texture::WebGpuTextureView>(rid)
})
.transpose()?
.map(|texture| texture.0);
let resolve_target = color_attachment Some(wgpu_core::command::RenderPassColorAttachment {
.resolve_target view: texture_view_resource.0,
.map(|rid| { resolve_target,
state channel: wgpu_core::command::PassChannel {
.resource_table load_op: at.load_op,
.get::<super::texture::WebGpuTextureView>(rid) store_op: at.store_op,
}) clear_value: at.clear_value.unwrap_or_default(),
.transpose()? read_only: false,
.map(|texture| texture.0); },
})
} else {
None
};
Ok(rp_at)
})
.collect::<Result<Vec<_>, AnyError>>()?;
let attachment = wgpu_core::command::RenderPassColorAttachment { let mut processed_depth_stencil_attachment = None;
view: texture_view_resource.0,
resolve_target,
channel: match color_attachment.load_op {
GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load,
store_op: color_attachment.store_op,
clear_value: Default::default(),
read_only: false,
},
GpuLoadOp::Clear(color) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear,
store_op: color_attachment.store_op,
clear_value: color,
read_only: false,
},
},
};
color_attachments.push(attachment) if let Some(attachment) = depth_stencil_attachment {
}
let mut depth_stencil_attachment = None;
if let Some(attachment) = args.depth_stencil_attachment {
let texture_view_resource = let texture_view_resource =
state state
.resource_table .resource_table
.get::<super::texture::WebGpuTextureView>(attachment.view)?; .get::<super::texture::WebGpuTextureView>(attachment.view)?;
depth_stencil_attachment = processed_depth_stencil_attachment =
Some(wgpu_core::command::RenderPassDepthStencilAttachment { Some(wgpu_core::command::RenderPassDepthStencilAttachment {
view: texture_view_resource.0, view: texture_view_resource.0,
depth: match attachment.depth_load_op { depth: wgpu_core::command::PassChannel {
GpuLoadOp::Load => wgpu_core::command::PassChannel { load_op: attachment.depth_load_op,
load_op: wgpu_core::command::LoadOp::Load, store_op: attachment.depth_store_op,
store_op: attachment.depth_store_op, clear_value: attachment.depth_clear_value,
clear_value: 0.0, read_only: attachment.depth_read_only,
read_only: attachment.depth_read_only,
},
GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear,
store_op: attachment.depth_store_op,
clear_value: value,
read_only: attachment.depth_read_only,
},
}, },
stencil: match attachment.stencil_load_op { stencil: wgpu_core::command::PassChannel {
GpuLoadOp::Load => wgpu_core::command::PassChannel { load_op: attachment.stencil_load_op,
load_op: wgpu_core::command::LoadOp::Load, store_op: attachment.stencil_store_op,
store_op: attachment.stencil_store_op, clear_value: attachment.stencil_clear_value,
clear_value: 0, read_only: attachment.stencil_read_only,
read_only: attachment.stencil_read_only,
},
GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear,
store_op: attachment.stencil_store_op,
clear_value: value,
read_only: attachment.stencil_read_only,
},
}, },
}); });
} }
let descriptor = wgpu_core::command::RenderPassDescriptor { let descriptor = wgpu_core::command::RenderPassDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
color_attachments: Cow::from(color_attachments), color_attachments: Cow::from(color_attachments),
depth_stencil_attachment: depth_stencil_attachment.as_ref(), depth_stencil_attachment: processed_depth_stencil_attachment.as_ref(),
}; };
let render_pass = wgpu_core::command::RenderPass::new( let render_pass = wgpu_core::command::RenderPass::new(
@ -208,24 +172,18 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
Ok(WebGpuResult::rid(rid)) Ok(WebGpuResult::rid(rid))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderBeginComputePassArgs {
command_encoder_rid: ResourceId,
label: Option<String>,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_begin_compute_pass( pub fn op_webgpu_command_encoder_begin_compute_pass(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderBeginComputePassArgs, command_encoder_rid: ResourceId,
label: Option<String>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let descriptor = wgpu_core::command::ComputePassDescriptor { let descriptor = wgpu_core::command::ComputePassDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
}; };
let compute_pass = wgpu_core::command::ComputePass::new( let compute_pass = wgpu_core::command::ComputePass::new(
@ -242,45 +200,38 @@ pub fn op_webgpu_command_encoder_begin_compute_pass(
Ok(WebGpuResult::rid(rid)) Ok(WebGpuResult::rid(rid))
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_command_encoder_copy_buffer_to_buffer(
pub struct CommandEncoderCopyBufferToBufferArgs { state: &mut OpState,
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
source: ResourceId, source: ResourceId,
source_offset: u64, source_offset: u64,
destination: ResourceId, destination: ResourceId,
destination_offset: u64, destination_offset: u64,
size: u64, size: u64,
}
#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_buffer(
state: &mut OpState,
args: CommandEncoderCopyBufferToBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let source_buffer_resource = let source_buffer_resource = state
state .resource_table
.resource_table .get::<super::buffer::WebGpuBuffer>(source)?;
.get::<super::buffer::WebGpuBuffer>(args.source)?;
let source_buffer = source_buffer_resource.0; let source_buffer = source_buffer_resource.0;
let destination_buffer_resource = let destination_buffer_resource =
state state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.destination)?; .get::<super::buffer::WebGpuBuffer>(destination)?;
let destination_buffer = destination_buffer_resource.0; let destination_buffer = destination_buffer_resource.0;
gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_buffer( gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_buffer(
command_encoder, command_encoder,
source_buffer, source_buffer,
args.source_offset, source_offset,
destination_buffer, destination_buffer,
args.destination_offset, destination_offset,
args.size size
)) ))
} }
@ -302,342 +253,277 @@ pub struct GpuImageCopyTexture {
pub aspect: wgpu_types::TextureAspect, pub aspect: wgpu_types::TextureAspect,
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
pub struct CommandEncoderCopyBufferToTextureArgs { state: &mut OpState,
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
source: GpuImageCopyBuffer, source: GpuImageCopyBuffer,
destination: GpuImageCopyTexture, destination: GpuImageCopyTexture,
copy_size: wgpu_types::Extent3d, copy_size: wgpu_types::Extent3d,
}
#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
state: &mut OpState,
args: CommandEncoderCopyBufferToTextureArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let source_buffer_resource = let source_buffer_resource =
state state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.source.buffer)?; .get::<super::buffer::WebGpuBuffer>(source.buffer)?;
let destination_texture_resource = let destination_texture_resource =
state state
.resource_table .resource_table
.get::<super::texture::WebGpuTexture>(args.destination.texture)?; .get::<super::texture::WebGpuTexture>(destination.texture)?;
let source = wgpu_core::command::ImageCopyBuffer { let source = wgpu_core::command::ImageCopyBuffer {
buffer: source_buffer_resource.0, buffer: source_buffer_resource.0,
layout: wgpu_types::ImageDataLayout { layout: wgpu_types::ImageDataLayout {
offset: args.source.offset, offset: source.offset,
bytes_per_row: NonZeroU32::new(args.source.bytes_per_row.unwrap_or(0)), bytes_per_row: NonZeroU32::new(source.bytes_per_row.unwrap_or(0)),
rows_per_image: NonZeroU32::new(args.source.rows_per_image.unwrap_or(0)), rows_per_image: NonZeroU32::new(source.rows_per_image.unwrap_or(0)),
}, },
}; };
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0, texture: destination_texture_resource.0,
mip_level: args.destination.mip_level, mip_level: destination.mip_level,
origin: args.destination.origin, origin: destination.origin,
aspect: args.destination.aspect, aspect: destination.aspect,
}; };
gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture( gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size &copy_size
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderCopyTextureToBufferArgs {
command_encoder_rid: ResourceId,
source: GpuImageCopyTexture,
destination: GpuImageCopyBuffer,
copy_size: wgpu_types::Extent3d,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_copy_texture_to_buffer( pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyTextureToBufferArgs, command_encoder_rid: ResourceId,
source: GpuImageCopyTexture,
destination: GpuImageCopyBuffer,
copy_size: wgpu_types::Extent3d,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let source_texture_resource = let source_texture_resource =
state state
.resource_table .resource_table
.get::<super::texture::WebGpuTexture>(args.source.texture)?; .get::<super::texture::WebGpuTexture>(source.texture)?;
let destination_buffer_resource = let destination_buffer_resource =
state state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.destination.buffer)?; .get::<super::buffer::WebGpuBuffer>(destination.buffer)?;
let source = wgpu_core::command::ImageCopyTexture { let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0, texture: source_texture_resource.0,
mip_level: args.source.mip_level, mip_level: source.mip_level,
origin: args.source.origin, origin: source.origin,
aspect: args.source.aspect, aspect: source.aspect,
}; };
let destination = wgpu_core::command::ImageCopyBuffer { let destination = wgpu_core::command::ImageCopyBuffer {
buffer: destination_buffer_resource.0, buffer: destination_buffer_resource.0,
layout: wgpu_types::ImageDataLayout { layout: wgpu_types::ImageDataLayout {
offset: args.destination.offset, offset: destination.offset,
bytes_per_row: NonZeroU32::new( bytes_per_row: NonZeroU32::new(destination.bytes_per_row.unwrap_or(0)),
args.destination.bytes_per_row.unwrap_or(0), rows_per_image: NonZeroU32::new(destination.rows_per_image.unwrap_or(0)),
),
rows_per_image: NonZeroU32::new(
args.destination.rows_per_image.unwrap_or(0),
),
}, },
}; };
gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_buffer( gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_buffer(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size &copy_size
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderCopyTextureToTextureArgs {
command_encoder_rid: ResourceId,
source: GpuImageCopyTexture,
destination: GpuImageCopyTexture,
copy_size: wgpu_types::Extent3d,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_copy_texture_to_texture( pub fn op_webgpu_command_encoder_copy_texture_to_texture(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyTextureToTextureArgs, command_encoder_rid: ResourceId,
source: GpuImageCopyTexture,
destination: GpuImageCopyTexture,
copy_size: wgpu_types::Extent3d,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let source_texture_resource = let source_texture_resource =
state state
.resource_table .resource_table
.get::<super::texture::WebGpuTexture>(args.source.texture)?; .get::<super::texture::WebGpuTexture>(source.texture)?;
let destination_texture_resource = let destination_texture_resource =
state state
.resource_table .resource_table
.get::<super::texture::WebGpuTexture>(args.destination.texture)?; .get::<super::texture::WebGpuTexture>(destination.texture)?;
let source = wgpu_core::command::ImageCopyTexture { let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0, texture: source_texture_resource.0,
mip_level: args.source.mip_level, mip_level: source.mip_level,
origin: args.source.origin, origin: source.origin,
aspect: args.source.aspect, aspect: source.aspect,
}; };
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0, texture: destination_texture_resource.0,
mip_level: args.destination.mip_level, mip_level: destination.mip_level,
origin: args.destination.origin, origin: destination.origin,
aspect: args.destination.aspect, aspect: destination.aspect,
}; };
gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture( gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size &copy_size
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderClearBufferArgs {
command_encoder_rid: u32,
destination_rid: u32,
destination_offset: u64,
size: u64,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_clear_buffer( pub fn op_webgpu_command_encoder_clear_buffer(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderClearBufferArgs, command_encoder_rid: u32,
buffer_rid: u32,
offset: u64,
size: u64,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let destination_resource = state let destination_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.destination_rid)?; .get::<super::buffer::WebGpuBuffer>(buffer_rid)?;
gfx_ok!(command_encoder => instance.command_encoder_clear_buffer( gfx_ok!(command_encoder => instance.command_encoder_clear_buffer(
command_encoder, command_encoder,
destination_resource.0, destination_resource.0,
args.destination_offset, offset,
std::num::NonZeroU64::new(args.size) std::num::NonZeroU64::new(size)
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderPushDebugGroupArgs {
command_encoder_rid: ResourceId,
group_label: String,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_push_debug_group( pub fn op_webgpu_command_encoder_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderPushDebugGroupArgs, command_encoder_rid: ResourceId,
group_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
gfx_ok!(command_encoder => instance gfx_ok!(command_encoder => instance.command_encoder_push_debug_group(command_encoder, &group_label))
.command_encoder_push_debug_group(command_encoder, &args.group_label))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderPopDebugGroupArgs {
command_encoder_rid: ResourceId,
} }
#[op] #[op]
pub fn op_webgpu_command_encoder_pop_debug_group( pub fn op_webgpu_command_encoder_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderPopDebugGroupArgs, command_encoder_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
gfx_ok!(command_encoder => instance.command_encoder_pop_debug_group(command_encoder)) gfx_ok!(command_encoder => instance.command_encoder_pop_debug_group(command_encoder))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderInsertDebugMarkerArgs {
command_encoder_rid: ResourceId,
marker_label: String,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_insert_debug_marker( pub fn op_webgpu_command_encoder_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderInsertDebugMarkerArgs, command_encoder_rid: ResourceId,
marker_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
gfx_ok!(command_encoder => instance.command_encoder_insert_debug_marker( gfx_ok!(command_encoder => instance.command_encoder_insert_debug_marker(
command_encoder, command_encoder,
&args.marker_label &marker_label
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderWriteTimestampArgs {
command_encoder_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_write_timestamp( pub fn op_webgpu_command_encoder_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderWriteTimestampArgs, command_encoder_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let query_set_resource = state let query_set_resource = state
.resource_table .resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(query_set)?;
gfx_ok!(command_encoder => instance.command_encoder_write_timestamp( gfx_ok!(command_encoder => instance.command_encoder_write_timestamp(
command_encoder, command_encoder,
query_set_resource.0, query_set_resource.0,
args.query_index query_index
)) ))
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_command_encoder_resolve_query_set(
pub struct CommandEncoderResolveQuerySetArgs { state: &mut OpState,
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
query_set: ResourceId, query_set: ResourceId,
first_query: u32, first_query: u32,
query_count: u32, query_count: u32,
destination: ResourceId, destination: ResourceId,
destination_offset: u64, destination_offset: u64,
}
#[op]
pub fn op_webgpu_command_encoder_resolve_query_set(
state: &mut OpState,
args: CommandEncoderResolveQuerySetArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let query_set_resource = state let query_set_resource = state
.resource_table .resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(query_set)?;
let destination_resource = state let destination_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.destination)?; .get::<super::buffer::WebGpuBuffer>(destination)?;
gfx_ok!(command_encoder => instance.command_encoder_resolve_query_set( gfx_ok!(command_encoder => instance.command_encoder_resolve_query_set(
command_encoder, command_encoder,
query_set_resource.0, query_set_resource.0,
args.first_query, first_query,
args.query_count, query_count,
destination_resource.0, destination_resource.0,
args.destination_offset destination_offset
)) ))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderFinishArgs {
command_encoder_rid: ResourceId,
label: Option<String>,
}
#[op] #[op]
pub fn op_webgpu_command_encoder_finish( pub fn op_webgpu_command_encoder_finish(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderFinishArgs, command_encoder_rid: ResourceId,
label: Option<String>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.take::<WebGpuCommandEncoder>(args.command_encoder_rid)?; .take::<WebGpuCommandEncoder>(command_encoder_rid)?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let descriptor = wgpu_types::CommandBufferDescriptor { let descriptor = wgpu_types::CommandBufferDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
}; };
gfx_put!(command_encoder => instance.command_encoder_finish( gfx_put!(command_encoder => instance.command_encoder_finish(

View file

@ -2,10 +2,10 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
@ -20,25 +20,19 @@ impl Resource for WebGpuComputePass {
} }
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassSetPipelineArgs {
compute_pass_rid: ResourceId,
pipeline: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_compute_pass_set_pipeline( pub fn op_webgpu_compute_pass_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: ComputePassSetPipelineArgs, compute_pass_rid: ResourceId,
pipeline: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pipeline_resource = let compute_pipeline_resource =
state state
.resource_table .resource_table
.get::<super::pipeline::WebGpuComputePipeline>(args.pipeline)?; .get::<super::pipeline::WebGpuComputePipeline>(pipeline)?;
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_set_pipeline( wgpu_core::command::compute_ffi::wgpu_compute_pass_set_pipeline(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
@ -48,106 +42,82 @@ pub fn op_webgpu_compute_pass_set_pipeline(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_compute_pass_dispatch_workgroups(
pub struct ComputePassDispatchArgs { state: &mut OpState,
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
x: u32, x: u32,
y: u32, y: u32,
z: u32, z: u32,
}
#[op]
pub fn op_webgpu_compute_pass_dispatch(
state: &mut OpState,
args: ComputePassDispatchArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch( wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
args.x, x,
args.y, y,
args.z, z,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_compute_pass_dispatch_workgroups_indirect(
pub struct ComputePassDispatchIndirectArgs { state: &mut OpState,
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
indirect_buffer: ResourceId, indirect_buffer: ResourceId,
indirect_offset: u64, indirect_offset: u64,
}
#[op]
pub fn op_webgpu_compute_pass_dispatch_indirect(
state: &mut OpState,
args: ComputePassDispatchIndirectArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?; .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_indirect( wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups_indirect(
&mut compute_pass_resource.0.borrow_mut(),
buffer_resource.0,
args.indirect_offset,
);
Ok(WebGpuResult::empty())
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassBeginPipelineStatisticsQueryArgs {
compute_pass_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
}
#[op]
pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query(
state: &mut OpState,
args: ComputePassBeginPipelineStatisticsQueryArgs,
) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state
.resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?;
let query_set_resource = state
.resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
query_set_resource.0, buffer_resource.0,
args.query_index, indirect_offset,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query(
pub struct ComputePassEndPipelineStatisticsQueryArgs { state: &mut OpState,
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state
.resource_table
.get::<WebGpuComputePass>(compute_pass_rid)?;
let query_set_resource = state
.resource_table
.get::<super::WebGpuQuerySet>(query_set)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query(
&mut compute_pass_resource.0.borrow_mut(),
query_set_resource.0,
query_index,
);
Ok(WebGpuResult::empty())
} }
#[op] #[op]
pub fn op_webgpu_compute_pass_end_pipeline_statistics_query( pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: ComputePassEndPipelineStatisticsQueryArgs, compute_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query( wgpu_core::command::compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
@ -156,56 +126,44 @@ pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassWriteTimestampArgs {
compute_pass_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
}
#[op] #[op]
pub fn op_webgpu_compute_pass_write_timestamp( pub fn op_webgpu_compute_pass_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: ComputePassWriteTimestampArgs, compute_pass_rid: ResourceId,
query_set: ResourceId,
query_index: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
let query_set_resource = state let query_set_resource = state
.resource_table .resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(query_set)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_write_timestamp( wgpu_core::command::compute_ffi::wgpu_compute_pass_write_timestamp(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
query_set_resource.0, query_set_resource.0,
args.query_index, query_index,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_compute_pass_end(
pub struct ComputePassEndPassArgs { state: &mut OpState,
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
}
#[op]
pub fn op_webgpu_compute_pass_end_pass(
state: &mut OpState,
args: ComputePassEndPassArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<super::command_encoder::WebGpuCommandEncoder>( .get::<super::command_encoder::WebGpuCommandEncoder>(
args.command_encoder_rid, command_encoder_rid,
)?; )?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.take::<WebGpuComputePass>(args.compute_pass_rid)?; .take::<WebGpuComputePass>(compute_pass_rid)?;
let compute_pass = &compute_pass_resource.0.borrow(); let compute_pass = &compute_pass_resource.0.borrow();
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
@ -215,41 +173,35 @@ pub fn op_webgpu_compute_pass_end_pass(
)) ))
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_compute_pass_set_bind_group(
pub struct ComputePassSetBindGroupArgs { state: &mut OpState,
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
index: u32, index: u32,
bind_group: ResourceId, bind_group: ResourceId,
dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize, dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
}
#[op]
pub fn op_webgpu_compute_pass_set_bind_group(
state: &mut OpState,
args: ComputePassSetBindGroupArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let bind_group_resource = let bind_group_resource =
state state
.resource_table .resource_table
.get::<super::binding::WebGpuBindGroup>(args.bind_group)?; .get::<super::binding::WebGpuBindGroup>(bind_group)?;
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
// Align the data // Align the data
assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0); assert!(dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0);
let (prefix, dynamic_offsets_data, suffix) = let (prefix, dynamic_offsets_data, suffix) =
// SAFETY: A u8 to u32 cast is safe because we asserted that the length is a // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
// multiple of 4. // multiple of 4.
unsafe { args.dynamic_offsets_data.align_to::<u32>() }; unsafe { dynamic_offsets_data.align_to::<u32>() };
assert!(prefix.is_empty()); assert!(prefix.is_empty());
assert!(suffix.is_empty()); assert!(suffix.is_empty());
let start = args.dynamic_offsets_data_start; let start = dynamic_offsets_data_start;
let len = args.dynamic_offsets_data_length; let len = dynamic_offsets_data_length;
// Assert that length and start are both in bounds // Assert that length and start are both in bounds
assert!(start <= dynamic_offsets_data.len()); assert!(start <= dynamic_offsets_data.len());
@ -262,7 +214,7 @@ pub fn op_webgpu_compute_pass_set_bind_group(
unsafe { unsafe {
wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group( wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
args.index, index,
bind_group_resource.0, bind_group_resource.0,
dynamic_offsets_data.as_ptr(), dynamic_offsets_data.as_ptr(),
dynamic_offsets_data.len(), dynamic_offsets_data.len(),
@ -272,23 +224,17 @@ pub fn op_webgpu_compute_pass_set_bind_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassPushDebugGroupArgs {
compute_pass_rid: ResourceId,
group_label: String,
}
#[op] #[op]
pub fn op_webgpu_compute_pass_push_debug_group( pub fn op_webgpu_compute_pass_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: ComputePassPushDebugGroupArgs, compute_pass_rid: ResourceId,
group_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
let label = std::ffi::CString::new(args.group_label).unwrap(); let label = std::ffi::CString::new(group_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {
@ -302,20 +248,14 @@ pub fn op_webgpu_compute_pass_push_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassPopDebugGroupArgs {
compute_pass_rid: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_compute_pass_pop_debug_group( pub fn op_webgpu_compute_pass_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: ComputePassPopDebugGroupArgs, compute_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_pop_debug_group( wgpu_core::command::compute_ffi::wgpu_compute_pass_pop_debug_group(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
@ -324,23 +264,17 @@ pub fn op_webgpu_compute_pass_pop_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePassInsertDebugMarkerArgs {
compute_pass_rid: ResourceId,
marker_label: String,
}
#[op] #[op]
pub fn op_webgpu_compute_pass_insert_debug_marker( pub fn op_webgpu_compute_pass_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: ComputePassInsertDebugMarkerArgs, compute_pass_rid: ResourceId,
marker_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let compute_pass_resource = state let compute_pass_resource = state
.resource_table .resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(compute_pass_rid)?;
let label = std::ffi::CString::new(args.marker_label).unwrap(); let label = std::ffi::CString::new(marker_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {

View file

@ -3,7 +3,9 @@ use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
use serde::Serialize; use serde::Serialize;
use std::convert::From; use std::convert::From;
use std::error::Error;
use std::fmt; use std::fmt;
use std::fmt::Write;
use wgpu_core::binding_model::CreateBindGroupError; use wgpu_core::binding_model::CreateBindGroupError;
use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreateBindGroupLayoutError;
use wgpu_core::binding_model::CreatePipelineLayoutError; use wgpu_core::binding_model::CreatePipelineLayoutError;
@ -29,6 +31,20 @@ use wgpu_core::resource::CreateSamplerError;
use wgpu_core::resource::CreateTextureError; use wgpu_core::resource::CreateTextureError;
use wgpu_core::resource::CreateTextureViewError; use wgpu_core::resource::CreateTextureViewError;
fn fmt_err(err: &(dyn Error + 'static)) -> String {
let mut output = err.to_string();
let mut e = err.source();
while let Some(source) = e {
// No error possible, unwrap is fine here.
// https://github.com/rust-lang/rust/blob/1.47.0/library/alloc/src/string.rs#L2414-L2427
write!(output, ": {source}").unwrap();
e = source.source();
}
output
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct WebGpuResult { pub struct WebGpuResult {
pub rid: Option<ResourceId>, pub rid: Option<ResourceId>,
@ -49,14 +65,14 @@ impl WebGpuResult {
) -> Self { ) -> Self {
Self { Self {
rid: Some(rid), rid: Some(rid),
err: err.map(|e| e.into()), err: err.map(Into::into),
} }
} }
pub fn maybe_err<T: Into<WebGpuError>>(err: Option<T>) -> Self { pub fn maybe_err<T: Into<WebGpuError>>(err: Option<T>) -> Self {
Self { Self {
rid: None, rid: None,
err: err.map(|e| e.into()), err: err.map(Into::into),
} }
} }
@ -82,7 +98,7 @@ impl From<CreateBufferError> for WebGpuError {
match err { match err {
CreateBufferError::Device(err) => err.into(), CreateBufferError::Device(err) => err.into(),
CreateBufferError::AccessError(err) => err.into(), CreateBufferError::AccessError(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -92,7 +108,7 @@ impl From<DeviceError> for WebGpuError {
match err { match err {
DeviceError::Lost => WebGpuError::Lost, DeviceError::Lost => WebGpuError::Lost,
DeviceError::OutOfMemory => WebGpuError::OutOfMemory, DeviceError::OutOfMemory => WebGpuError::OutOfMemory,
DeviceError::Invalid => WebGpuError::Validation(err.to_string()), DeviceError::Invalid => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -101,7 +117,7 @@ impl From<BufferAccessError> for WebGpuError {
fn from(err: BufferAccessError) -> Self { fn from(err: BufferAccessError) -> Self {
match err { match err {
BufferAccessError::Device(err) => err.into(), BufferAccessError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -110,7 +126,7 @@ impl From<CreateBindGroupLayoutError> for WebGpuError {
fn from(err: CreateBindGroupLayoutError) -> Self { fn from(err: CreateBindGroupLayoutError) -> Self {
match err { match err {
CreateBindGroupLayoutError::Device(err) => err.into(), CreateBindGroupLayoutError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -119,7 +135,7 @@ impl From<CreatePipelineLayoutError> for WebGpuError {
fn from(err: CreatePipelineLayoutError) -> Self { fn from(err: CreatePipelineLayoutError) -> Self {
match err { match err {
CreatePipelineLayoutError::Device(err) => err.into(), CreatePipelineLayoutError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -128,44 +144,44 @@ impl From<CreateBindGroupError> for WebGpuError {
fn from(err: CreateBindGroupError) -> Self { fn from(err: CreateBindGroupError) -> Self {
match err { match err {
CreateBindGroupError::Device(err) => err.into(), CreateBindGroupError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
impl From<RenderBundleError> for WebGpuError { impl From<RenderBundleError> for WebGpuError {
fn from(err: RenderBundleError) -> Self { fn from(err: RenderBundleError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
impl From<CreateRenderBundleError> for WebGpuError { impl From<CreateRenderBundleError> for WebGpuError {
fn from(err: CreateRenderBundleError) -> Self { fn from(err: CreateRenderBundleError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
impl From<CopyError> for WebGpuError { impl From<CopyError> for WebGpuError {
fn from(err: CopyError) -> Self { fn from(err: CopyError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
impl From<CommandEncoderError> for WebGpuError { impl From<CommandEncoderError> for WebGpuError {
fn from(err: CommandEncoderError) -> Self { fn from(err: CommandEncoderError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
impl From<QueryError> for WebGpuError { impl From<QueryError> for WebGpuError {
fn from(err: QueryError) -> Self { fn from(err: QueryError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
impl From<ComputePassError> for WebGpuError { impl From<ComputePassError> for WebGpuError {
fn from(err: ComputePassError) -> Self { fn from(err: ComputePassError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
@ -173,14 +189,14 @@ impl From<CreateComputePipelineError> for WebGpuError {
fn from(err: CreateComputePipelineError) -> Self { fn from(err: CreateComputePipelineError) -> Self {
match err { match err {
CreateComputePipelineError::Device(err) => err.into(), CreateComputePipelineError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
impl From<GetBindGroupLayoutError> for WebGpuError { impl From<GetBindGroupLayoutError> for WebGpuError {
fn from(err: GetBindGroupLayoutError) -> Self { fn from(err: GetBindGroupLayoutError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
@ -188,14 +204,14 @@ impl From<CreateRenderPipelineError> for WebGpuError {
fn from(err: CreateRenderPipelineError) -> Self { fn from(err: CreateRenderPipelineError) -> Self {
match err { match err {
CreateRenderPipelineError::Device(err) => err.into(), CreateRenderPipelineError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
impl From<RenderPassError> for WebGpuError { impl From<RenderPassError> for WebGpuError {
fn from(err: RenderPassError) -> Self { fn from(err: RenderPassError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
@ -203,7 +219,7 @@ impl From<CreateSamplerError> for WebGpuError {
fn from(err: CreateSamplerError) -> Self { fn from(err: CreateSamplerError) -> Self {
match err { match err {
CreateSamplerError::Device(err) => err.into(), CreateSamplerError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -212,7 +228,7 @@ impl From<CreateShaderModuleError> for WebGpuError {
fn from(err: CreateShaderModuleError) -> Self { fn from(err: CreateShaderModuleError) -> Self {
match err { match err {
CreateShaderModuleError::Device(err) => err.into(), CreateShaderModuleError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -221,14 +237,14 @@ impl From<CreateTextureError> for WebGpuError {
fn from(err: CreateTextureError) -> Self { fn from(err: CreateTextureError) -> Self {
match err { match err {
CreateTextureError::Device(err) => err.into(), CreateTextureError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
impl From<CreateTextureViewError> for WebGpuError { impl From<CreateTextureViewError> for WebGpuError {
fn from(err: CreateTextureViewError) -> Self { fn from(err: CreateTextureViewError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }
@ -236,7 +252,7 @@ impl From<CreateQuerySetError> for WebGpuError {
fn from(err: CreateQuerySetError) -> Self { fn from(err: CreateQuerySetError) -> Self {
match err { match err {
CreateQuerySetError::Device(err) => err.into(), CreateQuerySetError::Device(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -245,7 +261,7 @@ impl From<QueueSubmitError> for WebGpuError {
fn from(err: QueueSubmitError) -> Self { fn from(err: QueueSubmitError) -> Self {
match err { match err {
QueueSubmitError::Queue(err) => err.into(), QueueSubmitError::Queue(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
@ -254,14 +270,14 @@ impl From<QueueWriteError> for WebGpuError {
fn from(err: QueueWriteError) -> Self { fn from(err: QueueWriteError) -> Self {
match err { match err {
QueueWriteError::Queue(err) => err.into(), QueueWriteError::Queue(err) => err.into(),
err => WebGpuError::Validation(err.to_string()), err => WebGpuError::Validation(fmt_err(&err)),
} }
} }
} }
impl From<ClearError> for WebGpuError { impl From<ClearError> for WebGpuError {
fn from(err: ClearError) -> Self { fn from(err: ClearError) -> Self {
WebGpuError::Validation(err.to_string()) WebGpuError::Validation(fmt_err(&err))
} }
} }

View file

@ -3,9 +3,7 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpDecl;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -14,10 +12,10 @@ use serde::Serialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryFrom;
use std::rc::Rc; use std::rc::Rc;
pub use wgpu_core; pub use wgpu_core;
pub use wgpu_types; pub use wgpu_types;
use wgpu_types::PowerPreference;
use error::DomExceptionOperationError; use error::DomExceptionOperationError;
use error::WebGpuResult; use error::WebGpuResult;
@ -130,6 +128,12 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL) { if features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL) {
return_features.push("depth-clip-control"); return_features.push("depth-clip-control");
} }
if features.contains(wgpu_types::Features::DEPTH24UNORM_STENCIL8) {
return_features.push("depth24unorm-stencil8");
}
if features.contains(wgpu_types::Features::DEPTH32FLOAT_STENCIL8) {
return_features.push("depth32float-stencil8");
}
if features.contains(wgpu_types::Features::PIPELINE_STATISTICS_QUERY) { if features.contains(wgpu_types::Features::PIPELINE_STATISTICS_QUERY) {
return_features.push("pipeline-statistics-query"); return_features.push("pipeline-statistics-query");
} }
@ -148,6 +152,9 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) { if features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) {
return_features.push("indirect-first-instance"); return_features.push("indirect-first-instance");
} }
if features.contains(wgpu_types::Features::SHADER_FLOAT16) {
return_features.push("shader-f16")
}
// extended from spec // extended from spec
if features.contains(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS) { if features.contains(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS) {
@ -172,18 +179,6 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
) { ) {
return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"); return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing");
} }
if features.contains(wgpu_types::Features::UNSIZED_BINDING_ARRAY) {
return_features.push("unsized-binding-array");
}
if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT) {
return_features.push("multi-draw-indirect");
}
if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT) {
return_features.push("multi-draw-indirect-count");
}
if features.contains(wgpu_types::Features::PUSH_CONSTANTS) {
return_features.push("push-constants");
}
if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) { if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) {
return_features.push("address-mode-clamp-to-border"); return_features.push("address-mode-clamp-to-border");
} }
@ -198,32 +193,22 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT) { if features.contains(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT) {
return_features.push("vertex-attribute-64bit"); return_features.push("vertex-attribute-64bit");
} }
if features.contains(wgpu_types::Features::CONSERVATIVE_RASTERIZATION) {
return_features.push("conservative-rasterization");
}
if features.contains(wgpu_types::Features::VERTEX_WRITABLE_STORAGE) { if features.contains(wgpu_types::Features::VERTEX_WRITABLE_STORAGE) {
return_features.push("vertex-writable-storage"); return_features.push("vertex-writable-storage");
} }
if features.contains(wgpu_types::Features::CLEAR_COMMANDS) { if features.contains(wgpu_types::Features::CLEAR_TEXTURE) {
return_features.push("clear-texture"); return_features.push("clear-texture");
} }
if features.contains(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH) {
return_features.push("spirv-shader-passthrough");
}
if features.contains(wgpu_types::Features::SHADER_PRIMITIVE_INDEX) { if features.contains(wgpu_types::Features::SHADER_PRIMITIVE_INDEX) {
return_features.push("shader-primitive-index"); return_features.push("shader-primitive-index");
} }
if features.contains(wgpu_types::Features::PARTIALLY_BOUND_BINDING_ARRAY) {
return_features.push("shader-primitive-index");
}
return_features return_features
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RequestAdapterArgs {
power_preference: Option<wgpu_types::PowerPreference>,
force_fallback_adapter: bool,
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum GpuAdapterDeviceOrErr { pub enum GpuAdapterDeviceOrErr {
@ -235,7 +220,6 @@ pub enum GpuAdapterDeviceOrErr {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GpuAdapterDevice { pub struct GpuAdapterDevice {
rid: ResourceId, rid: ResourceId,
name: Option<String>,
limits: wgpu_types::Limits, limits: wgpu_types::Limits,
features: Vec<&'static str>, features: Vec<&'static str>,
is_software: bool, is_software: bool,
@ -244,15 +228,15 @@ pub struct GpuAdapterDevice {
#[op] #[op]
pub async fn op_webgpu_request_adapter( pub async fn op_webgpu_request_adapter(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RequestAdapterArgs, power_preference: Option<wgpu_types::PowerPreference>,
force_fallback_adapter: bool,
) -> Result<GpuAdapterDeviceOrErr, AnyError> { ) -> Result<GpuAdapterDeviceOrErr, AnyError> {
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
check_unstable(&state, "navigator.gpu.requestAdapter"); check_unstable(&state, "navigator.gpu.requestAdapter");
let backends = std::env::var("DENO_WEBGPU_BACKEND") let backends = std::env::var("DENO_WEBGPU_BACKEND").map_or_else(
.ok() |_| wgpu_types::Backends::all(),
.map_or_else(wgpu_types::Backends::all, |s| { |s| wgpu_core::instance::parse_backends_from_comma_list(&s),
wgpu_core::instance::parse_backends_from_comma_list(&s) );
});
let instance = if let Some(instance) = state.try_borrow::<Instance>() { let instance = if let Some(instance) = state.try_borrow::<Instance>() {
instance instance
} else { } else {
@ -265,11 +249,8 @@ pub async fn op_webgpu_request_adapter(
}; };
let descriptor = wgpu_core::instance::RequestAdapterOptions { let descriptor = wgpu_core::instance::RequestAdapterOptions {
power_preference: match args.power_preference { power_preference: power_preference.unwrap_or_default(),
Some(power_preference) => power_preference, force_fallback_adapter,
None => PowerPreference::default(),
},
force_fallback_adapter: args.force_fallback_adapter,
compatible_surface: None, // windowless compatible_surface: None, // windowless
}; };
let res = instance.request_adapter( let res = instance.request_adapter(
@ -287,7 +268,6 @@ pub async fn op_webgpu_request_adapter(
}) })
} }
}; };
let name = gfx_select!(adapter => instance.adapter_get_info(adapter))?.name;
let adapter_features = let adapter_features =
gfx_select!(adapter => instance.adapter_features(adapter))?; gfx_select!(adapter => instance.adapter_features(adapter))?;
let features = deserialize_features(&adapter_features); let features = deserialize_features(&adapter_features);
@ -298,22 +278,12 @@ pub async fn op_webgpu_request_adapter(
Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice { Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice {
rid, rid,
name: Some(name),
features, features,
limits: adapter_limits, limits: adapter_limits,
is_software: false, is_software: false,
})) }))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RequestDeviceArgs {
adapter_rid: ResourceId,
label: Option<String>,
required_features: Option<GpuRequiredFeatures>,
required_limits: Option<wgpu_types::Limits>,
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct GpuRequiredFeatures(HashSet<String>); pub struct GpuRequiredFeatures(HashSet<String>);
@ -324,6 +294,14 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
wgpu_types::Features::DEPTH_CLIP_CONTROL, wgpu_types::Features::DEPTH_CLIP_CONTROL,
required_features.0.contains("depth-clip-control"), required_features.0.contains("depth-clip-control"),
); );
features.set(
wgpu_types::Features::DEPTH24UNORM_STENCIL8,
required_features.0.contains("depth24unorm-stencil8"),
);
features.set(
wgpu_types::Features::DEPTH32FLOAT_STENCIL8,
required_features.0.contains("depth32float-stencil8"),
);
features.set( features.set(
wgpu_types::Features::PIPELINE_STATISTICS_QUERY, wgpu_types::Features::PIPELINE_STATISTICS_QUERY,
required_features.0.contains("pipeline-statistics-query"), required_features.0.contains("pipeline-statistics-query"),
@ -348,6 +326,10 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
wgpu_types::Features::INDIRECT_FIRST_INSTANCE, wgpu_types::Features::INDIRECT_FIRST_INSTANCE,
required_features.0.contains("indirect-first-instance"), required_features.0.contains("indirect-first-instance"),
); );
features.set(
wgpu_types::Features::SHADER_FLOAT16,
required_features.0.contains("shader-f16"),
);
// extended from spec // extended from spec
features.set( features.set(
@ -380,22 +362,6 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
.0 .0
.contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"), .contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"),
); );
features.set(
wgpu_types::Features::UNSIZED_BINDING_ARRAY,
required_features.0.contains("unsized-binding-array"),
);
features.set(
wgpu_types::Features::MULTI_DRAW_INDIRECT,
required_features.0.contains("multi-draw-indirect"),
);
features.set(
wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT,
required_features.0.contains("multi-draw-indirect-count"),
);
features.set(
wgpu_types::Features::PUSH_CONSTANTS,
required_features.0.contains("push-constants"),
);
features.set( features.set(
wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
required_features.0.contains("address-mode-clamp-to-border"), required_features.0.contains("address-mode-clamp-to-border"),
@ -414,26 +380,24 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT,
required_features.0.contains("vertex-attribute-64bit"), required_features.0.contains("vertex-attribute-64bit"),
); );
features.set(
wgpu_types::Features::CONSERVATIVE_RASTERIZATION,
required_features.0.contains("conservative-rasterization"),
);
features.set( features.set(
wgpu_types::Features::VERTEX_WRITABLE_STORAGE, wgpu_types::Features::VERTEX_WRITABLE_STORAGE,
required_features.0.contains("vertex-writable-storage"), required_features.0.contains("vertex-writable-storage"),
); );
features.set( features.set(
wgpu_types::Features::CLEAR_COMMANDS, wgpu_types::Features::CLEAR_TEXTURE,
required_features.0.contains("clear-commands"), required_features.0.contains("clear-commands"),
); );
features.set(
wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH,
required_features.0.contains("spirv-shader-passthrough"),
);
features.set( features.set(
wgpu_types::Features::SHADER_PRIMITIVE_INDEX, wgpu_types::Features::SHADER_PRIMITIVE_INDEX,
required_features.0.contains("shader-primitive-index"), required_features.0.contains("shader-primitive-index"),
); );
features.set(
wgpu_types::Features::PARTIALLY_BOUND_BINDING_ARRAY,
required_features
.0
.contains("partially-bound-binding-array"),
);
features features
} }
@ -442,19 +406,21 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
#[op] #[op]
pub async fn op_webgpu_request_device( pub async fn op_webgpu_request_device(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RequestDeviceArgs, adapter_rid: ResourceId,
label: Option<String>,
required_features: Option<GpuRequiredFeatures>,
required_limits: Option<wgpu_types::Limits>,
) -> Result<GpuAdapterDevice, AnyError> { ) -> Result<GpuAdapterDevice, AnyError> {
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
let adapter_resource = state let adapter_resource =
.resource_table state.resource_table.get::<WebGpuAdapter>(adapter_rid)?;
.get::<WebGpuAdapter>(args.adapter_rid)?;
let adapter = adapter_resource.0; let adapter = adapter_resource.0;
let instance = state.borrow::<Instance>(); let instance = state.borrow::<Instance>();
let descriptor = wgpu_types::DeviceDescriptor { let descriptor = wgpu_types::DeviceDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
features: args.required_features.map(Into::into).unwrap_or_default(), features: required_features.map(Into::into).unwrap_or_default(),
limits: args.required_limits.map(Into::into).unwrap_or_default(), limits: required_limits.map(Into::into).unwrap_or_default(),
}; };
let (device, maybe_err) = gfx_select!(adapter => instance.adapter_request_device( let (device, maybe_err) = gfx_select!(adapter => instance.adapter_request_device(
@ -476,7 +442,6 @@ pub async fn op_webgpu_request_device(
Ok(GpuAdapterDevice { Ok(GpuAdapterDevice {
rid, rid,
name: None,
features, features,
limits, limits,
// TODO(lucacasonato): report correctly from wgpu // TODO(lucacasonato): report correctly from wgpu
@ -484,6 +449,36 @@ pub async fn op_webgpu_request_device(
}) })
} }
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GPUAdapterInfo {
vendor: String,
architecture: String,
device: String,
description: String,
}
#[op]
pub async fn op_webgpu_request_adapter_info(
state: Rc<RefCell<OpState>>,
adapter_rid: ResourceId,
) -> Result<GPUAdapterInfo, AnyError> {
let state = state.borrow_mut();
let adapter_resource =
state.resource_table.get::<WebGpuAdapter>(adapter_rid)?;
let adapter = adapter_resource.0;
let instance = state.borrow::<Instance>();
let info = gfx_select!(adapter => instance.adapter_get_info(adapter))?;
Ok(GPUAdapterInfo {
vendor: info.vendor.to_string(),
architecture: String::new(), // TODO(#2170)
device: info.device.to_string(),
description: info.name,
})
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CreateQuerySetArgs { pub struct CreateQuerySetArgs {
@ -562,11 +557,12 @@ pub fn op_webgpu_create_query_set(
) => state, WebGpuQuerySet) ) => state, WebGpuQuerySet)
} }
fn declare_webgpu_ops() -> Vec<OpDecl> { fn declare_webgpu_ops() -> Vec<deno_core::OpDecl> {
vec![ vec![
// Request device/adapter // Request device/adapter
op_webgpu_request_adapter::decl(), op_webgpu_request_adapter::decl(),
op_webgpu_request_device::decl(), op_webgpu_request_device::decl(),
op_webgpu_request_adapter_info::decl(),
// Query Set // Query Set
op_webgpu_create_query_set::decl(), op_webgpu_create_query_set::decl(),
// buffer // buffer
@ -615,7 +611,7 @@ fn declare_webgpu_ops() -> Vec<OpDecl> {
render_pass::op_webgpu_render_pass_end_pipeline_statistics_query::decl(), render_pass::op_webgpu_render_pass_end_pipeline_statistics_query::decl(),
render_pass::op_webgpu_render_pass_write_timestamp::decl(), render_pass::op_webgpu_render_pass_write_timestamp::decl(),
render_pass::op_webgpu_render_pass_execute_bundles::decl(), render_pass::op_webgpu_render_pass_execute_bundles::decl(),
render_pass::op_webgpu_render_pass_end_pass::decl(), render_pass::op_webgpu_render_pass_end::decl(),
render_pass::op_webgpu_render_pass_set_bind_group::decl(), render_pass::op_webgpu_render_pass_set_bind_group::decl(),
render_pass::op_webgpu_render_pass_push_debug_group::decl(), render_pass::op_webgpu_render_pass_push_debug_group::decl(),
render_pass::op_webgpu_render_pass_pop_debug_group::decl(), render_pass::op_webgpu_render_pass_pop_debug_group::decl(),
@ -629,13 +625,13 @@ fn declare_webgpu_ops() -> Vec<OpDecl> {
render_pass::op_webgpu_render_pass_draw_indexed_indirect::decl(), render_pass::op_webgpu_render_pass_draw_indexed_indirect::decl(),
// compute_pass // compute_pass
compute_pass::op_webgpu_compute_pass_set_pipeline::decl(), compute_pass::op_webgpu_compute_pass_set_pipeline::decl(),
compute_pass::op_webgpu_compute_pass_dispatch::decl(), compute_pass::op_webgpu_compute_pass_dispatch_workgroups::decl(),
compute_pass::op_webgpu_compute_pass_dispatch_indirect::decl(), compute_pass::op_webgpu_compute_pass_dispatch_workgroups_indirect::decl(),
compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query::decl( compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query::decl(
), ),
compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query::decl(), compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query::decl(),
compute_pass::op_webgpu_compute_pass_write_timestamp::decl(), compute_pass::op_webgpu_compute_pass_write_timestamp::decl(),
compute_pass::op_webgpu_compute_pass_end_pass::decl(), compute_pass::op_webgpu_compute_pass_end::decl(),
compute_pass::op_webgpu_compute_pass_set_bind_group::decl(), compute_pass::op_webgpu_compute_pass_set_bind_group::decl(),
compute_pass::op_webgpu_compute_pass_push_debug_group::decl(), compute_pass::op_webgpu_compute_pass_push_debug_group::decl(),
compute_pass::op_webgpu_compute_pass_pop_debug_group::decl(), compute_pass::op_webgpu_compute_pass_pop_debug_group::decl(),

View file

@ -2,12 +2,12 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use super::error::WebGpuError; use super::error::WebGpuError;
use super::error::WebGpuResult; use super::error::WebGpuResult;
@ -43,59 +43,69 @@ impl Resource for WebGpuRenderPipeline {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuProgrammableStage { pub enum GPUAutoLayoutMode {
Auto,
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum GPUPipelineLayoutOrGPUAutoLayoutMode {
Layout(ResourceId),
Auto(GPUAutoLayoutMode),
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuProgrammableStage {
module: ResourceId, module: ResourceId,
entry_point: String, entry_point: String,
// constants: HashMap<String, GPUPipelineConstantValue> // constants: HashMap<String, GPUPipelineConstantValue>
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateComputePipelineArgs {
device_rid: ResourceId,
label: Option<String>,
layout: Option<ResourceId>,
compute: GpuProgrammableStage,
}
#[op] #[op]
pub fn op_webgpu_create_compute_pipeline( pub fn op_webgpu_create_compute_pipeline(
state: &mut OpState, state: &mut OpState,
args: CreateComputePipelineArgs, device_rid: ResourceId,
label: Option<String>,
layout: GPUPipelineLayoutOrGPUAutoLayoutMode,
compute: GpuProgrammableStage,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let pipeline_layout = if let Some(rid) = args.layout { let pipeline_layout = match layout {
let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?; GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => {
Some(id.0) let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
} else { Some(id.0)
None }
GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None,
}; };
let compute_shader_module_resource = let compute_shader_module_resource =
state state
.resource_table .resource_table
.get::<super::shader::WebGpuShaderModule>(args.compute.module)?; .get::<super::shader::WebGpuShaderModule>(compute.module)?;
let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor { let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
layout: pipeline_layout, layout: pipeline_layout,
stage: wgpu_core::pipeline::ProgrammableStageDescriptor { stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: compute_shader_module_resource.0, module: compute_shader_module_resource.0,
entry_point: Cow::from(args.compute.entry_point), entry_point: Cow::from(compute.entry_point),
// TODO(lucacasonato): support args.compute.constants // TODO(lucacasonato): support args.compute.constants
}, },
}; };
let implicit_pipelines = match args.layout { let implicit_pipelines = match layout {
Some(_) => None, GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds { GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => {
root_id: std::marker::PhantomData, Some(wgpu_core::device::ImplicitPipelineIds {
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], root_id: std::marker::PhantomData,
}), group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
})
}
}; };
let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline( let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline(
@ -112,13 +122,6 @@ pub fn op_webgpu_create_compute_pipeline(
Ok(WebGpuResult::rid_err(rid, maybe_err)) Ok(WebGpuResult::rid_err(rid, maybe_err))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePipelineGetBindGroupLayoutArgs {
compute_pipeline_rid: ResourceId,
index: u32,
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PipelineLayout { pub struct PipelineLayout {
@ -130,15 +133,16 @@ pub struct PipelineLayout {
#[op] #[op]
pub fn op_webgpu_compute_pipeline_get_bind_group_layout( pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: ComputePipelineGetBindGroupLayoutArgs, compute_pipeline_rid: ResourceId,
index: u32,
) -> Result<PipelineLayout, AnyError> { ) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let compute_pipeline_resource = state let compute_pipeline_resource = state
.resource_table .resource_table
.get::<WebGpuComputePipeline>(args.compute_pipeline_rid)?; .get::<WebGpuComputePipeline>(compute_pipeline_rid)?;
let compute_pipeline = compute_pipeline_resource.0; let compute_pipeline = compute_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, args.index, std::marker::PhantomData)); let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout)); let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));
@ -210,12 +214,9 @@ struct GpuDepthStencilState {
depth_bias_clamp: f32, depth_bias_clamp: f32,
} }
impl TryFrom<GpuDepthStencilState> for wgpu_types::DepthStencilState { impl From<GpuDepthStencilState> for wgpu_types::DepthStencilState {
type Error = AnyError; fn from(state: GpuDepthStencilState) -> wgpu_types::DepthStencilState {
fn try_from( wgpu_types::DepthStencilState {
state: GpuDepthStencilState,
) -> Result<wgpu_types::DepthStencilState, AnyError> {
Ok(wgpu_types::DepthStencilState {
format: state.format, format: state.format,
depth_write_enabled: state.depth_write_enabled, depth_write_enabled: state.depth_write_enabled,
depth_compare: state.depth_compare, depth_compare: state.depth_compare,
@ -230,7 +231,7 @@ impl TryFrom<GpuDepthStencilState> for wgpu_types::DepthStencilState {
slope_scale: state.depth_bias_slope_scale, slope_scale: state.depth_bias_slope_scale,
clamp: state.depth_bias_clamp, clamp: state.depth_bias_clamp,
}, },
}) }
} }
} }
@ -285,7 +286,7 @@ impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuFragmentState { struct GpuFragmentState {
targets: Vec<wgpu_types::ColorTargetState>, targets: Vec<Option<wgpu_types::ColorTargetState>>,
module: u32, module: u32,
entry_point: String, entry_point: String,
// TODO(lucacasonato): constants // TODO(lucacasonato): constants
@ -296,7 +297,7 @@ struct GpuFragmentState {
pub struct CreateRenderPipelineArgs { pub struct CreateRenderPipelineArgs {
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
layout: Option<ResourceId>, layout: GPUPipelineLayoutOrGPUAutoLayoutMode,
vertex: GpuVertexState, vertex: GpuVertexState,
primitive: GpuPrimitiveState, primitive: GpuPrimitiveState,
depth_stencil: Option<GpuDepthStencilState>, depth_stencil: Option<GpuDepthStencilState>,
@ -315,12 +316,13 @@ pub fn op_webgpu_create_render_pipeline(
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let layout = if let Some(rid) = args.layout { let layout = match args.layout {
let pipeline_layout_resource = GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => {
state.resource_table.get::<WebGpuPipelineLayout>(rid)?; let pipeline_layout_resource =
Some(pipeline_layout_resource.0) state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
} else { Some(pipeline_layout_resource.0)
None }
GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None,
}; };
let vertex_shader_module_resource = let vertex_shader_module_resource =
@ -334,18 +336,12 @@ pub fn op_webgpu_create_render_pipeline(
.resource_table .resource_table
.get::<super::shader::WebGpuShaderModule>(fragment.module)?; .get::<super::shader::WebGpuShaderModule>(fragment.module)?;
let mut targets = Vec::with_capacity(fragment.targets.len());
for target in fragment.targets {
targets.push(target);
}
Some(wgpu_core::pipeline::FragmentState { Some(wgpu_core::pipeline::FragmentState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor { stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: fragment_shader_module_resource.0, module: fragment_shader_module_resource.0,
entry_point: Cow::from(fragment.entry_point), entry_point: Cow::from(fragment.entry_point),
}, },
targets: Cow::from(targets), targets: Cow::from(fragment.targets),
}) })
} else { } else {
None None
@ -370,18 +366,20 @@ pub fn op_webgpu_create_render_pipeline(
buffers: Cow::Owned(vertex_buffers), buffers: Cow::Owned(vertex_buffers),
}, },
primitive: args.primitive.into(), primitive: args.primitive.into(),
depth_stencil: args.depth_stencil.map(TryInto::try_into).transpose()?, depth_stencil: args.depth_stencil.map(Into::into),
multisample: args.multisample, multisample: args.multisample,
fragment, fragment,
multiview: None, multiview: None,
}; };
let implicit_pipelines = match args.layout { let implicit_pipelines = match args.layout {
Some(_) => None, GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds { GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => {
root_id: std::marker::PhantomData, Some(wgpu_core::device::ImplicitPipelineIds {
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], root_id: std::marker::PhantomData,
}), group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
})
}
}; };
let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline( let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline(
@ -398,25 +396,19 @@ pub fn op_webgpu_create_render_pipeline(
Ok(WebGpuResult::rid_err(rid, maybe_err)) Ok(WebGpuResult::rid_err(rid, maybe_err))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPipelineGetBindGroupLayoutArgs {
render_pipeline_rid: ResourceId,
index: u32,
}
#[op] #[op]
pub fn op_webgpu_render_pipeline_get_bind_group_layout( pub fn op_webgpu_render_pipeline_get_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: RenderPipelineGetBindGroupLayoutArgs, render_pipeline_rid: ResourceId,
index: u32,
) -> Result<PipelineLayout, AnyError> { ) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let render_pipeline_resource = state let render_pipeline_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPipeline>(args.render_pipeline_rid)?; .get::<WebGpuRenderPipeline>(render_pipeline_rid)?;
let render_pipeline = render_pipeline_resource.0; let render_pipeline = render_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, args.index, std::marker::PhantomData)); let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout)); let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));

View file

@ -13,42 +13,40 @@ use super::error::WebGpuResult;
type WebGpuQueue = super::WebGpuDevice; type WebGpuQueue = super::WebGpuDevice;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QueueSubmitArgs {
queue_rid: ResourceId,
command_buffers: Vec<ResourceId>,
}
#[op] #[op]
pub fn op_webgpu_queue_submit( pub fn op_webgpu_queue_submit(
state: &mut OpState, state: &mut OpState,
args: QueueSubmitArgs, queue_rid: ResourceId,
command_buffers: Vec<ResourceId>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let queue_resource = let queue_resource = state.resource_table.get::<WebGpuQueue>(queue_rid)?;
state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
let queue = queue_resource.0; let queue = queue_resource.0;
let mut ids = vec![]; let ids = command_buffers
.iter()
for rid in args.command_buffers { .map(|rid| {
let buffer_resource = let buffer_resource =
state state
.resource_table .resource_table
.get::<super::command_encoder::WebGpuCommandBuffer>(rid)?; .get::<super::command_encoder::WebGpuCommandBuffer>(*rid)?;
ids.push(buffer_resource.0); Ok(buffer_resource.0)
} })
.collect::<Result<Vec<_>, AnyError>>()?;
let maybe_err = let maybe_err =
gfx_select!(queue => instance.queue_submit(queue, &ids)).err(); gfx_select!(queue => instance.queue_submit(queue, &ids)).err();
for rid in command_buffers {
state.resource_table.close(rid)?;
}
Ok(WebGpuResult::maybe_err(maybe_err)) Ok(WebGpuResult::maybe_err(maybe_err))
} }
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuImageDataLayout { pub struct GpuImageDataLayout {
offset: u64, offset: u64,
bytes_per_row: Option<u32>, bytes_per_row: Option<u32>,
rows_per_image: Option<u32>, rows_per_image: Option<u32>,
@ -64,39 +62,32 @@ impl From<GpuImageDataLayout> for wgpu_types::ImageDataLayout {
} }
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_write_buffer(
pub struct QueueWriteBufferArgs { state: &mut OpState,
queue_rid: ResourceId, queue_rid: ResourceId,
buffer: ResourceId, buffer: ResourceId,
buffer_offset: u64, buffer_offset: u64,
data_offset: usize, data_offset: usize,
size: Option<usize>, size: Option<usize>,
} buf: ZeroCopyBuf,
#[op]
pub fn op_webgpu_write_buffer(
state: &mut OpState,
args: QueueWriteBufferArgs,
zero_copy: ZeroCopyBuf,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.buffer)?; .get::<super::buffer::WebGpuBuffer>(buffer)?;
let buffer = buffer_resource.0; let buffer = buffer_resource.0;
let queue_resource = let queue_resource = state.resource_table.get::<WebGpuQueue>(queue_rid)?;
state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
let queue = queue_resource.0; let queue = queue_resource.0;
let data = match args.size { let data = match size {
Some(size) => &zero_copy[args.data_offset..(args.data_offset + size)], Some(size) => &buf[data_offset..(data_offset + size)],
None => &zero_copy[args.data_offset..], None => &buf[data_offset..],
}; };
let maybe_err = gfx_select!(queue => instance.queue_write_buffer( let maybe_err = gfx_select!(queue => instance.queue_write_buffer(
queue, queue,
buffer, buffer,
args.buffer_offset, buffer_offset,
data data
)) ))
.err(); .err();
@ -104,42 +95,35 @@ pub fn op_webgpu_write_buffer(
Ok(WebGpuResult::maybe_err(maybe_err)) Ok(WebGpuResult::maybe_err(maybe_err))
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_write_texture(
pub struct QueueWriteTextureArgs { state: &mut OpState,
queue_rid: ResourceId, queue_rid: ResourceId,
destination: super::command_encoder::GpuImageCopyTexture, destination: super::command_encoder::GpuImageCopyTexture,
data_layout: GpuImageDataLayout, data_layout: GpuImageDataLayout,
size: wgpu_types::Extent3d, size: wgpu_types::Extent3d,
} buf: ZeroCopyBuf,
#[op]
pub fn op_webgpu_write_texture(
state: &mut OpState,
args: QueueWriteTextureArgs,
zero_copy: ZeroCopyBuf,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let texture_resource = state let texture_resource = state
.resource_table .resource_table
.get::<super::texture::WebGpuTexture>(args.destination.texture)?; .get::<super::texture::WebGpuTexture>(destination.texture)?;
let queue_resource = let queue_resource = state.resource_table.get::<WebGpuQueue>(queue_rid)?;
state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
let queue = queue_resource.0; let queue = queue_resource.0;
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: texture_resource.0, texture: texture_resource.0,
mip_level: args.destination.mip_level, mip_level: destination.mip_level,
origin: args.destination.origin, origin: destination.origin,
aspect: args.destination.aspect, aspect: destination.aspect,
}; };
let data_layout = args.data_layout.into(); let data_layout = data_layout.into();
gfx_ok!(queue => instance.queue_write_texture( gfx_ok!(queue => instance.queue_write_texture(
queue, queue,
&destination, &destination,
&*zero_copy, &*buf,
&data_layout, &data_layout,
&args.size &size
)) ))
} }

View file

@ -3,9 +3,10 @@
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
@ -55,127 +56,97 @@ pub fn op_webgpu_render_pass_set_viewport(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_set_scissor_rect(
pub struct RenderPassSetScissorRectArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
x: u32, x: u32,
y: u32, y: u32,
width: u32, width: u32,
height: u32, height: u32,
}
#[op]
pub fn op_webgpu_render_pass_set_scissor_rect(
state: &mut OpState,
args: RenderPassSetScissorRectArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_scissor_rect( wgpu_core::command::render_ffi::wgpu_render_pass_set_scissor_rect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.x, x,
args.y, y,
args.width, width,
args.height, height,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassSetBlendConstantArgs {
render_pass_rid: ResourceId,
color: wgpu_types::Color,
}
#[op] #[op]
pub fn op_webgpu_render_pass_set_blend_constant( pub fn op_webgpu_render_pass_set_blend_constant(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetBlendConstantArgs, render_pass_rid: ResourceId,
color: wgpu_types::Color,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant( wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
&args.color, &color,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassSetStencilReferenceArgs {
render_pass_rid: ResourceId,
reference: u32,
}
#[op] #[op]
pub fn op_webgpu_render_pass_set_stencil_reference( pub fn op_webgpu_render_pass_set_stencil_reference(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetStencilReferenceArgs, render_pass_rid: ResourceId,
reference: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_stencil_reference( wgpu_core::command::render_ffi::wgpu_render_pass_set_stencil_reference(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.reference, reference,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassBeginPipelineStatisticsQueryArgs {
render_pass_rid: ResourceId,
query_set: u32,
query_index: u32,
}
#[op] #[op]
pub fn op_webgpu_render_pass_begin_pipeline_statistics_query( pub fn op_webgpu_render_pass_begin_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: RenderPassBeginPipelineStatisticsQueryArgs, render_pass_rid: ResourceId,
query_set: u32,
query_index: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let query_set_resource = state let query_set_resource = state
.resource_table .resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(query_set)?;
wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query( wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
query_set_resource.0, query_set_resource.0,
args.query_index, query_index,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassEndPipelineStatisticsQueryArgs {
render_pass_rid: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_render_pass_end_pipeline_statistics_query( pub fn op_webgpu_render_pass_end_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: RenderPassEndPipelineStatisticsQueryArgs, render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_end_pipeline_statistics_query( wgpu_core::command::render_ffi::wgpu_render_pass_end_pipeline_statistics_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
@ -184,136 +155,113 @@ pub fn op_webgpu_render_pass_end_pipeline_statistics_query(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassWriteTimestampArgs {
render_pass_rid: ResourceId,
query_set: u32,
query_index: u32,
}
#[op] #[op]
pub fn op_webgpu_render_pass_write_timestamp( pub fn op_webgpu_render_pass_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: RenderPassWriteTimestampArgs, render_pass_rid: ResourceId,
query_set: u32,
query_index: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let query_set_resource = state let query_set_resource = state
.resource_table .resource_table
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(query_set)?;
wgpu_core::command::render_ffi::wgpu_render_pass_write_timestamp( wgpu_core::command::render_ffi::wgpu_render_pass_write_timestamp(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
query_set_resource.0, query_set_resource.0,
args.query_index, query_index,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassExecuteBundlesArgs {
render_pass_rid: ResourceId,
bundles: Vec<u32>,
}
#[op] #[op]
pub fn op_webgpu_render_pass_execute_bundles( pub fn op_webgpu_render_pass_execute_bundles(
state: &mut OpState, state: &mut OpState,
args: RenderPassExecuteBundlesArgs, render_pass_rid: ResourceId,
bundles: Vec<u32>,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let mut render_bundle_ids = vec![]; let bundles = bundles
.iter()
for rid in &args.bundles { .map(|rid| {
let render_bundle_resource = let render_bundle_resource =
state state
.resource_table .resource_table
.get::<super::bundle::WebGpuRenderBundle>(*rid)?; .get::<super::bundle::WebGpuRenderBundle>(*rid)?;
render_bundle_ids.push(render_bundle_resource.0); Ok(render_bundle_resource.0)
} })
.collect::<Result<Vec<_>, AnyError>>()?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
// SAFETY: the raw pointer and length are of the same slice, and that slice // SAFETY: the raw pointer and length are of the same slice, and that slice
// lives longer than the below function invocation. // lives longer than the below function invocation.
unsafe { unsafe {
wgpu_core::command::render_ffi::wgpu_render_pass_execute_bundles( wgpu_core::command::render_ffi::wgpu_render_pass_execute_bundles(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
render_bundle_ids.as_ptr(), bundles.as_ptr(),
render_bundle_ids.len(), bundles.len(),
); );
} }
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_end(
pub struct RenderPassEndPassArgs { state: &mut OpState,
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
}
#[op]
pub fn op_webgpu_render_pass_end_pass(
state: &mut OpState,
args: RenderPassEndPassArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state let command_encoder_resource = state
.resource_table .resource_table
.get::<super::command_encoder::WebGpuCommandEncoder>( .get::<super::command_encoder::WebGpuCommandEncoder>(
args.command_encoder_rid, command_encoder_rid,
)?; )?;
let command_encoder = command_encoder_resource.0; let command_encoder = command_encoder_resource.0;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.take::<WebGpuRenderPass>(args.render_pass_rid)?; .take::<WebGpuRenderPass>(render_pass_rid)?;
let render_pass = &render_pass_resource.0.borrow(); let render_pass = &render_pass_resource.0.borrow();
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
gfx_ok!(command_encoder => instance.command_encoder_run_render_pass(command_encoder, render_pass)) gfx_ok!(command_encoder => instance.command_encoder_run_render_pass(command_encoder, render_pass))
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_set_bind_group(
pub struct RenderPassSetBindGroupArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
index: u32, index: u32,
bind_group: u32, bind_group: u32,
dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize, dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
}
#[op]
pub fn op_webgpu_render_pass_set_bind_group(
state: &mut OpState,
args: RenderPassSetBindGroupArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let bind_group_resource = let bind_group_resource =
state state
.resource_table .resource_table
.get::<super::binding::WebGpuBindGroup>(args.bind_group)?; .get::<super::binding::WebGpuBindGroup>(bind_group)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
// Align the data // Align the data
assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0); assert_eq!(dynamic_offsets_data_start % std::mem::size_of::<u32>(), 0);
let (prefix, dynamic_offsets_data, suffix) = let (prefix, dynamic_offsets_data, suffix) =
// SAFETY: A u8 to u32 cast is safe because we asserted that the length is a // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
// multiple of 4. // multiple of 4.
unsafe { args.dynamic_offsets_data.align_to::<u32>() }; unsafe { dynamic_offsets_data.align_to::<u32>() };
assert!(prefix.is_empty()); assert!(prefix.is_empty());
assert!(suffix.is_empty()); assert!(suffix.is_empty());
let start = args.dynamic_offsets_data_start; let start = dynamic_offsets_data_start;
let len = args.dynamic_offsets_data_length; let len = dynamic_offsets_data_length;
// Assert that length and start are both in bounds // Assert that length and start are both in bounds
assert!(start <= dynamic_offsets_data.len()); assert!(start <= dynamic_offsets_data.len());
@ -326,7 +274,7 @@ pub fn op_webgpu_render_pass_set_bind_group(
unsafe { unsafe {
wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.index, index,
bind_group_resource.0, bind_group_resource.0,
dynamic_offsets_data.as_ptr(), dynamic_offsets_data.as_ptr(),
dynamic_offsets_data.len(), dynamic_offsets_data.len(),
@ -336,23 +284,17 @@ pub fn op_webgpu_render_pass_set_bind_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassPushDebugGroupArgs {
render_pass_rid: ResourceId,
group_label: String,
}
#[op] #[op]
pub fn op_webgpu_render_pass_push_debug_group( pub fn op_webgpu_render_pass_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderPassPushDebugGroupArgs, render_pass_rid: ResourceId,
group_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let label = std::ffi::CString::new(args.group_label).unwrap(); let label = std::ffi::CString::new(group_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {
@ -366,20 +308,14 @@ pub fn op_webgpu_render_pass_push_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassPopDebugGroupArgs {
render_pass_rid: ResourceId,
}
#[op] #[op]
pub fn op_webgpu_render_pass_pop_debug_group( pub fn op_webgpu_render_pass_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderPassPopDebugGroupArgs, render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_pop_debug_group( wgpu_core::command::render_ffi::wgpu_render_pass_pop_debug_group(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
@ -388,23 +324,17 @@ pub fn op_webgpu_render_pass_pop_debug_group(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassInsertDebugMarkerArgs {
render_pass_rid: ResourceId,
marker_label: String,
}
#[op] #[op]
pub fn op_webgpu_render_pass_insert_debug_marker( pub fn op_webgpu_render_pass_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: RenderPassInsertDebugMarkerArgs, render_pass_rid: ResourceId,
marker_label: String,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let label = std::ffi::CString::new(args.marker_label).unwrap(); let label = std::ffi::CString::new(marker_label).unwrap();
// SAFETY: the string the raw pointer points to lives longer than the below // SAFETY: the string the raw pointer points to lives longer than the below
// function invocation. // function invocation.
unsafe { unsafe {
@ -418,25 +348,19 @@ pub fn op_webgpu_render_pass_insert_debug_marker(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassSetPipelineArgs {
render_pass_rid: ResourceId,
pipeline: u32,
}
#[op] #[op]
pub fn op_webgpu_render_pass_set_pipeline( pub fn op_webgpu_render_pass_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetPipelineArgs, render_pass_rid: ResourceId,
pipeline: u32,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pipeline_resource = let render_pipeline_resource =
state state
.resource_table .resource_table
.get::<super::pipeline::WebGpuRenderPipeline>(args.pipeline)?; .get::<super::pipeline::WebGpuRenderPipeline>(pipeline)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_set_pipeline( wgpu_core::command::render_ffi::wgpu_render_pass_set_pipeline(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
@ -446,29 +370,23 @@ pub fn op_webgpu_render_pass_set_pipeline(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_set_index_buffer(
pub struct RenderPassSetIndexBufferArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
buffer: u32, buffer: u32,
index_format: wgpu_types::IndexFormat, index_format: wgpu_types::IndexFormat,
offset: u64, offset: u64,
size: Option<u64>, size: Option<u64>,
}
#[op]
pub fn op_webgpu_render_pass_set_index_buffer(
state: &mut OpState,
args: RenderPassSetIndexBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.buffer)?; .get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let size = if let Some(size) = args.size { let size = if let Some(size) = size {
Some( Some(
std::num::NonZeroU64::new(size) std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?, .ok_or_else(|| type_error("size must be larger than 0"))?,
@ -479,37 +397,31 @@ pub fn op_webgpu_render_pass_set_index_buffer(
render_pass_resource.0.borrow_mut().set_index_buffer( render_pass_resource.0.borrow_mut().set_index_buffer(
buffer_resource.0, buffer_resource.0,
args.index_format, index_format,
args.offset, offset,
size, size,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_set_vertex_buffer(
pub struct RenderPassSetVertexBufferArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
slot: u32, slot: u32,
buffer: u32, buffer: u32,
offset: u64, offset: u64,
size: Option<u64>, size: Option<u64>,
}
#[op]
pub fn op_webgpu_render_pass_set_vertex_buffer(
state: &mut OpState,
args: RenderPassSetVertexBufferArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.buffer)?; .get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
let size = if let Some(size) = args.size { let size = if let Some(size) = size {
Some( Some(
std::num::NonZeroU64::new(size) std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?, .ok_or_else(|| type_error("size must be larger than 0"))?,
@ -520,130 +432,106 @@ pub fn op_webgpu_render_pass_set_vertex_buffer(
wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer( wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.slot, slot,
buffer_resource.0, buffer_resource.0,
args.offset, offset,
size, size,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_draw(
pub struct RenderPassDrawArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
vertex_count: u32, vertex_count: u32,
instance_count: u32, instance_count: u32,
first_vertex: u32, first_vertex: u32,
first_instance: u32, first_instance: u32,
}
#[op]
pub fn op_webgpu_render_pass_draw(
state: &mut OpState,
args: RenderPassDrawArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw( wgpu_core::command::render_ffi::wgpu_render_pass_draw(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.vertex_count, vertex_count,
args.instance_count, instance_count,
args.first_vertex, first_vertex,
args.first_instance, first_instance,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_render_pass_draw_indexed(
pub struct RenderPassDrawIndexedArgs { state: &mut OpState,
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
index_count: u32, index_count: u32,
instance_count: u32, instance_count: u32,
first_index: u32, first_index: u32,
base_vertex: i32, base_vertex: i32,
first_instance: u32, first_instance: u32,
}
#[op]
pub fn op_webgpu_render_pass_draw_indexed(
state: &mut OpState,
args: RenderPassDrawIndexedArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed( wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
args.index_count, index_count,
args.instance_count, instance_count,
args.first_index, first_index,
args.base_vertex, base_vertex,
args.first_instance, first_instance,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassDrawIndirectArgs {
render_pass_rid: ResourceId,
indirect_buffer: u32,
indirect_offset: u64,
}
#[op] #[op]
pub fn op_webgpu_render_pass_draw_indirect( pub fn op_webgpu_render_pass_draw_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawIndirectArgs, render_pass_rid: ResourceId,
indirect_buffer: u32,
indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?; .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indirect( wgpu_core::command::render_ffi::wgpu_render_pass_draw_indirect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
buffer_resource.0, buffer_resource.0,
args.indirect_offset, indirect_offset,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPassDrawIndexedIndirectArgs {
render_pass_rid: ResourceId,
indirect_buffer: u32,
indirect_offset: u64,
}
#[op] #[op]
pub fn op_webgpu_render_pass_draw_indexed_indirect( pub fn op_webgpu_render_pass_draw_indexed_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawIndexedIndirectArgs, render_pass_rid: ResourceId,
indirect_buffer: u32,
indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let buffer_resource = state let buffer_resource = state
.resource_table .resource_table
.get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?; .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
let render_pass_resource = state let render_pass_resource = state
.resource_table .resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed_indirect( wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed_indirect(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
buffer_resource.0, buffer_resource.0,
args.indirect_offset, indirect_offset,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())

View file

@ -2,8 +2,9 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
@ -26,7 +27,7 @@ pub struct CreateSamplerArgs {
address_mode_w: wgpu_types::AddressMode, address_mode_w: wgpu_types::AddressMode,
mag_filter: wgpu_types::FilterMode, mag_filter: wgpu_types::FilterMode,
min_filter: wgpu_types::FilterMode, min_filter: wgpu_types::FilterMode,
mipmap_filter: wgpu_types::FilterMode, mipmap_filter: wgpu_types::FilterMode, // TODO: GPUMipmapFilterMode
lod_min_clamp: f32, lod_min_clamp: f32,
lod_max_clamp: f32, lod_max_clamp: f32,
compare: Option<wgpu_types::CompareFunction>, compare: Option<wgpu_types::CompareFunction>,

View file

@ -2,9 +2,9 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use super::error::WebGpuResult; use super::error::WebGpuResult;
@ -16,31 +16,24 @@ impl Resource for WebGpuShaderModule {
} }
} }
#[derive(Deserialize)] #[op]
#[serde(rename_all = "camelCase")] pub fn op_webgpu_create_shader_module(
pub struct CreateShaderModuleArgs { state: &mut OpState,
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
code: String, code: String,
_source_map: Option<()>, // not yet implemented _source_map: Option<()>, // not yet implemented
}
#[op]
pub fn op_webgpu_create_shader_module(
state: &mut OpState,
args: CreateShaderModuleArgs,
) -> Result<WebGpuResult, AnyError> { ) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>(); let instance = state.borrow::<super::Instance>();
let device_resource = state let device_resource = state
.resource_table .resource_table
.get::<super::WebGpuDevice>(args.device_rid)?; .get::<super::WebGpuDevice>(device_rid)?;
let device = device_resource.0; let device = device_resource.0;
let source = let source = wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::from(code));
wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::from(args.code));
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor { let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
label: args.label.map(Cow::from), label: label.map(Cow::from),
shader_bound_checks: wgpu_types::ShaderBoundChecks::default(), shader_bound_checks: wgpu_types::ShaderBoundChecks::default(),
}; };

View file

@ -2,8 +2,9 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;

View file

@ -1,5 +1,5 @@
interface mixin GPUObjectBase { interface mixin GPUObjectBase {
attribute USVString? label; attribute USVString label;
}; };
dictionary GPUObjectDescriptorBase { dictionary GPUObjectDescriptorBase {
@ -41,6 +41,14 @@ interface GPUSupportedFeatures {
readonly setlike<DOMString>; readonly setlike<DOMString>;
}; };
[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUAdapterInfo {
readonly attribute DOMString vendor;
readonly attribute DOMString architecture;
readonly attribute DOMString device;
readonly attribute DOMString description;
};
enum GPUPredefinedColorSpace { enum GPUPredefinedColorSpace {
"srgb", "srgb",
}; };
@ -68,12 +76,12 @@ enum GPUPowerPreference {
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUAdapter { interface GPUAdapter {
readonly attribute DOMString name;
[SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits; [SameObject] readonly attribute GPUSupportedLimits limits;
readonly attribute boolean isFallbackAdapter; readonly attribute boolean isFallbackAdapter;
Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {}); Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
Promise<GPUAdapterInfo> requestAdapterInfo(optional sequence<DOMString> unmaskHints = []);
}; };
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
@ -85,12 +93,12 @@ enum GPUFeatureName {
"depth-clip-control", "depth-clip-control",
"depth24unorm-stencil8", "depth24unorm-stencil8",
"depth32float-stencil8", "depth32float-stencil8",
"pipeline-statistics-query",
"texture-compression-bc", "texture-compression-bc",
"texture-compression-etc2", "texture-compression-etc2",
"texture-compression-astc", "texture-compression-astc",
"timestamp-query", "timestamp-query",
"indirect-first-instance", "indirect-first-instance",
"shader-f16",
}; };
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
@ -141,7 +149,7 @@ dictionary GPUBufferDescriptor : GPUObjectDescriptorBase {
typedef [EnforceRange] unsigned long GPUBufferUsageFlags; typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker)]
interface GPUBufferUsage { namespace GPUBufferUsage {
const GPUFlagsConstant MAP_READ = 0x0001; const GPUFlagsConstant MAP_READ = 0x0001;
const GPUFlagsConstant MAP_WRITE = 0x0002; const GPUFlagsConstant MAP_WRITE = 0x0002;
const GPUFlagsConstant COPY_SRC = 0x0004; const GPUFlagsConstant COPY_SRC = 0x0004;
@ -156,7 +164,7 @@ interface GPUBufferUsage {
typedef [EnforceRange] unsigned long GPUMapModeFlags; typedef [EnforceRange] unsigned long GPUMapModeFlags;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker)]
interface GPUMapMode { namespace GPUMapMode {
const GPUFlagsConstant READ = 0x0001; const GPUFlagsConstant READ = 0x0001;
const GPUFlagsConstant WRITE = 0x0002; const GPUFlagsConstant WRITE = 0x0002;
}; };
@ -186,7 +194,7 @@ enum GPUTextureDimension {
typedef [EnforceRange] unsigned long GPUTextureUsageFlags; typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker)]
interface GPUTextureUsage { namespace GPUTextureUsage {
const GPUFlagsConstant COPY_SRC = 0x01; const GPUFlagsConstant COPY_SRC = 0x01;
const GPUFlagsConstant COPY_DST = 0x02; const GPUFlagsConstant COPY_DST = 0x02;
const GPUFlagsConstant TEXTURE_BINDING = 0x04; const GPUFlagsConstant TEXTURE_BINDING = 0x04;
@ -272,13 +280,19 @@ enum GPUTextureFormat {
"rgba32sint", "rgba32sint",
"rgba32float", "rgba32float",
// Depth and stencil formats // Depth/stencil formats
"stencil8", "stencil8",
"depth16unorm", "depth16unorm",
"depth24plus", "depth24plus",
"depth24plus-stencil8", "depth24plus-stencil8",
"depth32float", "depth32float",
// "depth24unorm-stencil8" feature
"depth24unorm-stencil8",
// "depth32float-stencil8" feature
"depth32float-stencil8",
// BC compressed formats usable if "texture-compression-bc" is both // BC compressed formats usable if "texture-compression-bc" is both
// supported by the device/user agent and enabled in requestDevice. // supported by the device/user agent and enabled in requestDevice.
"bc1-rgba-unorm", "bc1-rgba-unorm",
@ -339,12 +353,6 @@ enum GPUTextureFormat {
"astc-12x10-unorm-srgb", "astc-12x10-unorm-srgb",
"astc-12x12-unorm", "astc-12x12-unorm",
"astc-12x12-unorm-srgb", "astc-12x12-unorm-srgb",
// "depth24unorm-stencil8" feature
"depth24unorm-stencil8",
// "depth32float-stencil8" feature
"depth32float-stencil8",
}; };
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
@ -358,7 +366,7 @@ dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
GPUAddressMode addressModeW = "clamp-to-edge"; GPUAddressMode addressModeW = "clamp-to-edge";
GPUFilterMode magFilter = "nearest"; GPUFilterMode magFilter = "nearest";
GPUFilterMode minFilter = "nearest"; GPUFilterMode minFilter = "nearest";
GPUFilterMode mipmapFilter = "nearest"; GPUMipmapFilterMode mipmapFilter = "nearest";
float lodMinClamp = 0; float lodMinClamp = 0;
float lodMaxClamp = 32; float lodMaxClamp = 32;
GPUCompareFunction compare; GPUCompareFunction compare;
@ -376,6 +384,11 @@ enum GPUFilterMode {
"linear", "linear",
}; };
enum GPUMipmapFilterMode {
"nearest",
"linear",
};
enum GPUCompareFunction { enum GPUCompareFunction {
"never", "never",
"less", "less",
@ -396,14 +409,6 @@ dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupLayoutEntry> entries; required sequence<GPUBindGroupLayoutEntry> entries;
}; };
typedef [EnforceRange] unsigned long GPUShaderStageFlags;
[Exposed=(Window, DedicatedWorker)]
interface GPUShaderStage {
const GPUFlagsConstant VERTEX = 0x1;
const GPUFlagsConstant FRAGMENT = 0x2;
const GPUFlagsConstant COMPUTE = 0x4;
};
dictionary GPUBindGroupLayoutEntry { dictionary GPUBindGroupLayoutEntry {
required GPUIndex32 binding; required GPUIndex32 binding;
required GPUShaderStageFlags visibility; required GPUShaderStageFlags visibility;
@ -414,6 +419,14 @@ dictionary GPUBindGroupLayoutEntry {
GPUStorageTextureBindingLayout storageTexture; GPUStorageTextureBindingLayout storageTexture;
}; };
typedef [EnforceRange] unsigned long GPUShaderStageFlags;
[Exposed=(Window, DedicatedWorker)]
namespace GPUShaderStage {
const GPUFlagsConstant VERTEX = 0x1;
const GPUFlagsConstant FRAGMENT = 0x2;
const GPUFlagsConstant COMPUTE = 0x4;
};
enum GPUBufferBindingType { enum GPUBufferBindingType {
"uniform", "uniform",
"storage", "storage",
@ -524,12 +537,16 @@ interface GPUCompilationInfo {
readonly attribute FrozenArray<GPUCompilationMessage> messages; readonly attribute FrozenArray<GPUCompilationMessage> messages;
}; };
enum GPUAutoLayoutMode {
"auto"
};
dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
GPUPipelineLayout layout; required (GPUPipelineLayout or GPUAutoLayoutMode) layout;
}; };
interface mixin GPUPipelineBase { interface mixin GPUPipelineBase {
GPUBindGroupLayout getBindGroupLayout(unsigned long index); [NewObject] GPUBindGroupLayout getBindGroupLayout(unsigned long index);
}; };
dictionary GPUProgrammableStage { dictionary GPUProgrammableStage {
@ -564,14 +581,6 @@ dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
GPUFragmentState fragment; GPUFragmentState fragment;
}; };
enum GPUPrimitiveTopology {
"point-list",
"line-list",
"line-strip",
"triangle-list",
"triangle-strip",
};
dictionary GPUPrimitiveState { dictionary GPUPrimitiveState {
GPUPrimitiveTopology topology = "triangle-list"; GPUPrimitiveTopology topology = "triangle-list";
GPUIndexFormat stripIndexFormat; GPUIndexFormat stripIndexFormat;
@ -582,6 +591,14 @@ dictionary GPUPrimitiveState {
boolean unclippedDepth = false; boolean unclippedDepth = false;
}; };
enum GPUPrimitiveTopology {
"point-list",
"line-list",
"line-strip",
"triangle-list",
"triangle-strip",
};
enum GPUFrontFace { enum GPUFrontFace {
"ccw", "ccw",
"cw", "cw",
@ -600,7 +617,7 @@ dictionary GPUMultisampleState {
}; };
dictionary GPUFragmentState : GPUProgrammableStage { dictionary GPUFragmentState : GPUProgrammableStage {
required sequence<GPUColorTargetState> targets; required sequence<GPUColorTargetState?> targets;
}; };
dictionary GPUColorTargetState { dictionary GPUColorTargetState {
@ -617,7 +634,7 @@ dictionary GPUBlendState {
typedef [EnforceRange] unsigned long GPUColorWriteFlags; typedef [EnforceRange] unsigned long GPUColorWriteFlags;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker)]
interface GPUColorWrite { namespace GPUColorWrite {
const GPUFlagsConstant RED = 0x1; const GPUFlagsConstant RED = 0x1;
const GPUFlagsConstant GREEN = 0x2; const GPUFlagsConstant GREEN = 0x2;
const GPUFlagsConstant BLUE = 0x4; const GPUFlagsConstant BLUE = 0x4;
@ -758,6 +775,9 @@ GPUCommandBuffer includes GPUObjectBase;
dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase { dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
}; };
interface mixin GPUCommandsMixin {
};
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUCommandEncoder { interface GPUCommandEncoder {
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
@ -786,13 +806,9 @@ interface GPUCommandEncoder {
GPUExtent3D copySize); GPUExtent3D copySize);
undefined clearBuffer( undefined clearBuffer(
GPUBuffer destination, GPUBuffer buffer,
GPUSize64 destinationOffset, optional GPUSize64 offset = 0,
GPUSize64 size); optional GPUSize64 size);
undefined pushDebugGroup(USVString groupLabel);
undefined popDebugGroup();
undefined insertDebugMarker(USVString markerLabel);
undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
@ -806,6 +822,8 @@ interface GPUCommandEncoder {
GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {}); GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
}; };
GPUCommandEncoder includes GPUObjectBase; GPUCommandEncoder includes GPUObjectBase;
GPUCommandEncoder includes GPUCommandsMixin;
GPUCommandEncoder includes GPUDebugCommandsMixin;
dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase { dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {
}; };
@ -827,7 +845,7 @@ dictionary GPUImageCopyTexture {
GPUTextureAspect aspect = "all"; GPUTextureAspect aspect = "all";
}; };
interface mixin GPUProgrammablePassEncoder { interface mixin GPUBindingCommandsMixin {
undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup, undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup,
optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []); optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);
@ -835,7 +853,9 @@ interface mixin GPUProgrammablePassEncoder {
Uint32Array dynamicOffsetsData, Uint32Array dynamicOffsetsData,
GPUSize64 dynamicOffsetsDataStart, GPUSize64 dynamicOffsetsDataStart,
GPUSize32 dynamicOffsetsDataLength); GPUSize32 dynamicOffsetsDataLength);
};
interface mixin GPUDebugCommandsMixin {
undefined pushDebugGroup(USVString groupLabel); undefined pushDebugGroup(USVString groupLabel);
undefined popDebugGroup(); undefined popDebugGroup();
undefined insertDebugMarker(USVString markerLabel); undefined insertDebugMarker(USVString markerLabel);
@ -844,39 +864,24 @@ interface mixin GPUProgrammablePassEncoder {
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUComputePassEncoder { interface GPUComputePassEncoder {
undefined setPipeline(GPUComputePipeline pipeline); undefined setPipeline(GPUComputePipeline pipeline);
undefined dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1); undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1);
undefined dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); undefined dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
undefined beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex); undefined beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex);
undefined endPipelineStatisticsQuery(); undefined endPipelineStatisticsQuery();
undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
undefined endPass(); undefined end();
}; };
GPUComputePassEncoder includes GPUObjectBase; GPUComputePassEncoder includes GPUObjectBase;
GPUComputePassEncoder includes GPUProgrammablePassEncoder; GPUComputePassEncoder includes GPUCommandsMixin;
GPUComputePassEncoder includes GPUDebugCommandsMixin;
GPUComputePassEncoder includes GPUBindingCommandsMixin;
dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase { dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase {
}; };
interface mixin GPURenderEncoderBase {
undefined setPipeline(GPURenderPipeline pipeline);
undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size);
undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size);
undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0);
undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstIndex = 0,
optional GPUSignedOffset32 baseVertex = 0,
optional GPUSize32 firstInstance = 0);
undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderPassEncoder { interface GPURenderPassEncoder {
undefined setViewport(float x, float y, undefined setViewport(float x, float y,
@ -898,14 +903,16 @@ interface GPURenderPassEncoder {
undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
undefined executeBundles(sequence<GPURenderBundle> bundles); undefined executeBundles(sequence<GPURenderBundle> bundles);
undefined endPass(); undefined end();
}; };
GPURenderPassEncoder includes GPUObjectBase; GPURenderPassEncoder includes GPUObjectBase;
GPURenderPassEncoder includes GPUProgrammablePassEncoder; GPURenderPassEncoder includes GPUCommandsMixin;
GPURenderPassEncoder includes GPURenderEncoderBase; GPURenderPassEncoder includes GPUDebugCommandsMixin;
GPURenderPassEncoder includes GPUBindingCommandsMixin;
GPURenderPassEncoder includes GPURenderCommandsMixin;
dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase { dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
required sequence<GPURenderPassColorAttachment> colorAttachments; required sequence<GPURenderPassColorAttachment?> colorAttachments;
GPURenderPassDepthStencilAttachment depthStencilAttachment; GPURenderPassDepthStencilAttachment depthStencilAttachment;
GPUQuerySet occlusionQuerySet; GPUQuerySet occlusionQuerySet;
}; };
@ -914,24 +921,28 @@ dictionary GPURenderPassColorAttachment {
required GPUTextureView view; required GPUTextureView view;
GPUTextureView resolveTarget; GPUTextureView resolveTarget;
required (GPULoadOp or GPUColor) loadValue; GPUColor clearValue;
required GPULoadOp loadOp;
required GPUStoreOp storeOp; required GPUStoreOp storeOp;
}; };
dictionary GPURenderPassDepthStencilAttachment { dictionary GPURenderPassDepthStencilAttachment {
required GPUTextureView view; required GPUTextureView view;
required (GPULoadOp or float) depthLoadValue; float depthClearValue = 0;
required GPUStoreOp depthStoreOp; GPULoadOp depthLoadOp;
GPUStoreOp depthStoreOp;
boolean depthReadOnly = false; boolean depthReadOnly = false;
required (GPULoadOp or GPUStencilValue) stencilLoadValue; GPUStencilValue stencilClearValue = 0;
required GPUStoreOp stencilStoreOp; GPULoadOp stencilLoadOp;
GPUStoreOp stencilStoreOp;
boolean stencilReadOnly = false; boolean stencilReadOnly = false;
}; };
enum GPULoadOp { enum GPULoadOp {
"load", "load",
"clear",
}; };
enum GPUStoreOp { enum GPUStoreOp {
@ -940,11 +951,28 @@ enum GPUStoreOp {
}; };
dictionary GPURenderPassLayout: GPUObjectDescriptorBase { dictionary GPURenderPassLayout: GPUObjectDescriptorBase {
required sequence<GPUTextureFormat> colorFormats; required sequence<GPUTextureFormat?> colorFormats;
GPUTextureFormat depthStencilFormat; GPUTextureFormat depthStencilFormat;
GPUSize32 sampleCount = 1; GPUSize32 sampleCount = 1;
}; };
interface mixin GPURenderCommandsMixin {
undefined setPipeline(GPURenderPipeline pipeline);
undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size);
undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size);
undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0);
undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstIndex = 0,
optional GPUSignedOffset32 baseVertex = 0,
optional GPUSize32 firstInstance = 0);
undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderBundle { interface GPURenderBundle {
}; };
@ -958,8 +986,10 @@ interface GPURenderBundleEncoder {
GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {}); GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
}; };
GPURenderBundleEncoder includes GPUObjectBase; GPURenderBundleEncoder includes GPUObjectBase;
GPURenderBundleEncoder includes GPUProgrammablePassEncoder; GPURenderBundleEncoder includes GPUCommandsMixin;
GPURenderBundleEncoder includes GPURenderEncoderBase; GPURenderBundleEncoder includes GPUDebugCommandsMixin;
GPURenderBundleEncoder includes GPUBindingCommandsMixin;
GPURenderBundleEncoder includes GPURenderCommandsMixin;
dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout { dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout {
boolean depthReadOnly = false; boolean depthReadOnly = false;
@ -1033,17 +1063,19 @@ enum GPUErrorFilter {
}; };
[Exposed=(Window, DedicatedWorker), SecureContext] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUOutOfMemoryError { interface GPUError {
constructor();
};
[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUValidationError {
constructor(DOMString message);
readonly attribute DOMString message; readonly attribute DOMString message;
}; };
typedef (GPUOutOfMemoryError or GPUValidationError) GPUError; [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUOutOfMemoryError : GPUError {
constructor(DOMString message);
};
[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUValidationError : GPUError {
constructor(DOMString message);
};
partial interface GPUDevice { partial interface GPUDevice {
undefined pushErrorScope(GPUErrorFilter filter); undefined pushErrorScope(GPUErrorFilter filter);
@ -1056,7 +1088,7 @@ interface GPUUncapturedErrorEvent : Event {
DOMString type, DOMString type,
GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict
); );
[SameObject] readonly attribute GPUError error; readonly attribute GPUError error;
}; };
dictionary GPUUncapturedErrorEventInit : EventInit { dictionary GPUUncapturedErrorEventInit : EventInit {
@ -1108,4 +1140,3 @@ dictionary GPUExtent3DDict {
GPUIntegerCoordinate depthOrArrayLayers = 1; GPUIntegerCoordinate depthOrArrayLayers = 1;
}; };
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D; typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;

View file

@ -3,10 +3,9 @@
import { join, ROOT_PATH, walk } from "./util.js"; import { join, ROOT_PATH, walk } from "./util.js";
// const COMMIT = "c00e471274b6c21acda89b4b13d41742c0285d71"; // Release 12 const COMMIT = "076df1a56812eee01614b7a3a4c88798012e79ab";
const COMMIT = "c4aa3eaed020a640fec06b48f0a5ea93490d41bb"; // tip of PR (needs merge) const REPO = "gfx-rs/wgpu";
const REPO = "kvark/wgpu"; const V_WGPU = "0.13";
const V_WGPU = "0.12";
const TARGET_DIR = join(ROOT_PATH, "ext", "webgpu"); const TARGET_DIR = join(ROOT_PATH, "ext", "webgpu");
async function bash(subcmd, opts = {}) { async function bash(subcmd, opts = {}) {