summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/webgpu/01_webgpu.js122
-rw-r--r--ext/webgpu/02_idl_types.js2
-rw-r--r--ext/webgpu/binding.rs258
-rw-r--r--ext/webgpu/buffer.rs4
-rw-r--r--ext/webgpu/bundle.rs125
-rw-r--r--ext/webgpu/command_encoder.rs278
-rw-r--r--ext/webgpu/compute_pass.rs56
-rw-r--r--ext/webgpu/lib.rs241
-rw-r--r--ext/webgpu/pipeline.rs645
-rw-r--r--ext/webgpu/queue.rs48
-rw-r--r--ext/webgpu/render_pass.rs83
-rw-r--r--ext/webgpu/sampler.rs134
-rw-r--r--ext/webgpu/texture.rs461
-rw-r--r--ext/webidl/00_webidl.js4
14 files changed, 1384 insertions, 1077 deletions
diff --git a/ext/webgpu/01_webgpu.js b/ext/webgpu/01_webgpu.js
index f7ad6caa7..3954a93b7 100644
--- a/ext/webgpu/01_webgpu.js
+++ b/ext/webgpu/01_webgpu.js
@@ -2646,9 +2646,9 @@
depthStencilAttachment.depthLoadOp =
descriptor.depthStencilAttachment.depthLoadValue;
} else {
- depthStencilAttachment.depthLoadOp = "clear";
- depthStencilAttachment.depthLoadValue =
- descriptor.depthStencilAttachment.depthLoadValue;
+ depthStencilAttachment.depthLoadOp = {
+ clear: descriptor.depthStencilAttachment.depthLoadValue,
+ };
}
if (
@@ -2656,11 +2656,10 @@
) {
depthStencilAttachment.stencilLoadOp =
descriptor.depthStencilAttachment.stencilLoadValue;
- depthStencilAttachment.stencilLoadValue = undefined;
} else {
- depthStencilAttachment.stencilLoadOp = "clear";
- depthStencilAttachment.stencilLoadValue =
- descriptor.depthStencilAttachment.stencilLoadValue;
+ depthStencilAttachment.stencilLoadOp = {
+ clear: descriptor.depthStencilAttachment.stencilLoadValue,
+ };
}
}
const colorAttachments = ArrayPrototypeMap(
@@ -2717,10 +2716,9 @@
if (typeof colorAttachment.loadValue === "string") {
attachment.loadOp = colorAttachment.loadValue;
} else {
- attachment.loadOp = "clear";
- attachment.loadValue = normalizeGPUColor(
- colorAttachment.loadValue,
- );
+ attachment.loadOp = {
+ clear: normalizeGPUColor(colorAttachment.loadValue),
+ };
}
return attachment;
@@ -3674,29 +3672,19 @@
resourceContext: "Argument 2",
selfContext: "this",
});
- if (dynamicOffsetsData instanceof Uint32Array) {
- core.opSync(
- "op_webgpu_render_pass_set_bind_group",
- {
- renderPassRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsDataStart,
- dynamicOffsetsDataLength,
- },
- dynamicOffsetsData,
- );
- } else {
- dynamicOffsetsData ??= [];
- core.opSync("op_webgpu_render_pass_set_bind_group", {
- renderPassRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsData,
- dynamicOffsetsDataStart: 0,
- dynamicOffsetsDataLength: dynamicOffsetsData.length,
- });
+ if (!(dynamicOffsetsData instanceof Uint32Array)) {
+ dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
+ dynamicOffsetsDataStart = 0;
+ dynamicOffsetsDataLength = dynamicOffsetsData.length;
}
+ core.opSync("op_webgpu_render_pass_set_bind_group", {
+ renderPassRid,
+ index,
+ bindGroup: bindGroupRid,
+ dynamicOffsetsData,
+ dynamicOffsetsDataStart,
+ dynamicOffsetsDataLength,
+ });
}
/**
@@ -4410,29 +4398,19 @@
resourceContext: "Argument 2",
selfContext: "this",
});
- if (dynamicOffsetsData instanceof Uint32Array) {
- core.opSync(
- "op_webgpu_compute_pass_set_bind_group",
- {
- computePassRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsDataStart,
- dynamicOffsetsDataLength,
- },
- dynamicOffsetsData,
- );
- } else {
- dynamicOffsetsData ??= [];
- core.opSync("op_webgpu_compute_pass_set_bind_group", {
- computePassRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsData,
- dynamicOffsetsDataStart: 0,
- dynamicOffsetsDataLength: dynamicOffsetsData.length,
- });
+ if (!(dynamicOffsetsData instanceof Uint32Array)) {
+ dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
+ dynamicOffsetsDataStart = 0;
+ dynamicOffsetsDataLength = dynamicOffsetsData.length;
}
+ core.opSync("op_webgpu_compute_pass_set_bind_group", {
+ computePassRid,
+ index,
+ bindGroup: bindGroupRid,
+ dynamicOffsetsData,
+ dynamicOffsetsDataStart,
+ dynamicOffsetsDataLength,
+ });
}
/**
@@ -4659,29 +4637,19 @@
resourceContext: "Argument 2",
selfContext: "this",
});
- if (dynamicOffsetsData instanceof Uint32Array) {
- core.opSync(
- "op_webgpu_render_bundle_encoder_set_bind_group",
- {
- renderBundleEncoderRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsDataStart,
- dynamicOffsetsDataLength,
- },
- dynamicOffsetsData,
- );
- } else {
- dynamicOffsetsData ??= [];
- core.opSync("op_webgpu_render_bundle_encoder_set_bind_group", {
- renderBundleEncoderRid,
- index,
- bindGroup: bindGroupRid,
- dynamicOffsetsData,
- dynamicOffsetsDataStart: 0,
- dynamicOffsetsDataLength: dynamicOffsetsData.length,
- });
+ if (!(dynamicOffsetsData instanceof Uint32Array)) {
+ dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
+ dynamicOffsetsDataStart = 0;
+ dynamicOffsetsDataLength = dynamicOffsetsData.length;
}
+ core.opSync("op_webgpu_render_bundle_encoder_set_bind_group", {
+ renderBundleEncoderRid,
+ index,
+ bindGroup: bindGroupRid,
+ dynamicOffsetsData,
+ dynamicOffsetsDataStart,
+ dynamicOffsetsDataLength,
+ });
}
/**
diff --git a/ext/webgpu/02_idl_types.js b/ext/webgpu/02_idl_types.js
index 364a39747..6f871a4ff 100644
--- a/ext/webgpu/02_idl_types.js
+++ b/ext/webgpu/02_idl_types.js
@@ -950,6 +950,7 @@
webidl.converters["GPUComputePipelineDescriptor"] = webidl
.createDictionaryConverter(
"GPUComputePipelineDescriptor",
+ dictMembersGPUObjectDescriptorBase,
dictMembersGPUPipelineDescriptorBase,
dictMembersGPUComputePipelineDescriptor,
);
@@ -1422,6 +1423,7 @@
webidl.converters["GPURenderPipelineDescriptor"] = webidl
.createDictionaryConverter(
"GPURenderPipelineDescriptor",
+ dictMembersGPUObjectDescriptorBase,
dictMembersGPUPipelineDescriptorBase,
dictMembersGPURenderPipelineDescriptor,
);
diff --git a/ext/webgpu/binding.rs b/ext/webgpu/binding.rs
index c1b98fcef..c2dbcf455 100644
--- a/ext/webgpu/binding.rs
+++ b/ext/webgpu/binding.rs
@@ -5,6 +5,9 @@ use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
+use std::convert::{TryFrom, TryInto};
+
+use crate::texture::{GpuTextureFormat, GpuTextureViewDimension};
use super::error::WebGpuResult;
@@ -27,33 +30,122 @@ impl Resource for WebGpuBindGroup {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuBufferBindingLayout {
- #[serde(rename = "type")]
- kind: Option<String>,
- has_dynamic_offset: Option<bool>,
- min_binding_size: Option<u64>,
+ r#type: GpuBufferBindingType,
+ has_dynamic_offset: bool,
+ min_binding_size: u64,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuBufferBindingType {
+ Uniform,
+ Storage,
+ ReadOnlyStorage,
+}
+
+impl From<GpuBufferBindingType> for wgpu_types::BufferBindingType {
+ fn from(binding_type: GpuBufferBindingType) -> Self {
+ match binding_type {
+ GpuBufferBindingType::Uniform => wgpu_types::BufferBindingType::Uniform,
+ GpuBufferBindingType::Storage => {
+ wgpu_types::BufferBindingType::Storage { read_only: false }
+ }
+ GpuBufferBindingType::ReadOnlyStorage => {
+ wgpu_types::BufferBindingType::Storage { read_only: true }
+ }
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuSamplerBindingLayout {
- #[serde(rename = "type")]
- kind: Option<String>,
+ r#type: GpuSamplerBindingType,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuSamplerBindingType {
+ Filtering,
+ NonFiltering,
+ Comparison,
+}
+
+impl From<GpuSamplerBindingType> for wgpu_types::BindingType {
+ fn from(binding_type: GpuSamplerBindingType) -> Self {
+ match binding_type {
+ GpuSamplerBindingType::Filtering => wgpu_types::BindingType::Sampler {
+ filtering: true,
+ comparison: false,
+ },
+ GpuSamplerBindingType::NonFiltering => wgpu_types::BindingType::Sampler {
+ filtering: false,
+ comparison: false,
+ },
+ GpuSamplerBindingType::Comparison => wgpu_types::BindingType::Sampler {
+ filtering: true,
+ comparison: true,
+ },
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuTextureBindingLayout {
- sample_type: Option<String>,
- view_dimension: Option<String>,
- multisampled: Option<bool>,
+ sample_type: GpuTextureSampleType,
+ view_dimension: GpuTextureViewDimension,
+ multisampled: bool,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuTextureSampleType {
+ Float,
+ UnfilterableFloat,
+ Depth,
+ Sint,
+ Uint,
+}
+
+impl From<GpuTextureSampleType> for wgpu_types::TextureSampleType {
+ fn from(sample_type: GpuTextureSampleType) -> Self {
+ match sample_type {
+ GpuTextureSampleType::Float => {
+ wgpu_types::TextureSampleType::Float { filterable: true }
+ }
+ GpuTextureSampleType::UnfilterableFloat => {
+ wgpu_types::TextureSampleType::Float { filterable: false }
+ }
+ GpuTextureSampleType::Depth => wgpu_types::TextureSampleType::Depth,
+ GpuTextureSampleType::Sint => wgpu_types::TextureSampleType::Sint,
+ GpuTextureSampleType::Uint => wgpu_types::TextureSampleType::Uint,
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuStorageTextureBindingLayout {
- access: String,
- format: String,
- view_dimension: Option<String>,
+ access: GpuStorageTextureAccess,
+ format: GpuTextureFormat,
+ view_dimension: GpuTextureViewDimension,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuStorageTextureAccess {
+ WriteOnly,
+}
+
+impl From<GpuStorageTextureAccess> for wgpu_types::StorageTextureAccess {
+ fn from(access: GpuStorageTextureAccess) -> Self {
+ match access {
+ GpuStorageTextureAccess::WriteOnly => {
+ wgpu_types::StorageTextureAccess::WriteOnly
+ }
+ }
+ }
}
#[derive(Deserialize)]
@@ -61,10 +153,47 @@ struct GpuStorageTextureBindingLayout {
struct GpuBindGroupLayoutEntry {
binding: u32,
visibility: u32,
- buffer: Option<GpuBufferBindingLayout>,
- sampler: Option<GpuSamplerBindingLayout>,
- texture: Option<GpuTextureBindingLayout>,
- storage_texture: Option<GpuStorageTextureBindingLayout>,
+ #[serde(flatten)]
+ binding_type: GpuBindingType,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+enum GpuBindingType {
+ Buffer(GpuBufferBindingLayout),
+ Sampler(GpuSamplerBindingLayout),
+ Texture(GpuTextureBindingLayout),
+ StorageTexture(GpuStorageTextureBindingLayout),
+}
+
+impl TryFrom<GpuBindingType> for wgpu_types::BindingType {
+ type Error = AnyError;
+
+ 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 {
+ ty: buffer.r#type.into(),
+ has_dynamic_offset: buffer.has_dynamic_offset,
+ min_binding_size: std::num::NonZeroU64::new(buffer.min_binding_size),
+ },
+ GpuBindingType::Sampler(sampler) => sampler.r#type.into(),
+ GpuBindingType::Texture(texture) => wgpu_types::BindingType::Texture {
+ sample_type: texture.sample_type.into(),
+ view_dimension: texture.view_dimension.into(),
+ multisampled: texture.multisampled,
+ },
+ GpuBindingType::StorageTexture(storage_texture) => {
+ wgpu_types::BindingType::StorageTexture {
+ access: storage_texture.access.into(),
+ format: storage_texture.format.try_into()?,
+ view_dimension: storage_texture.view_dimension.into(),
+ }
+ }
+ };
+ Ok(binding_type)
+ }
}
#[derive(Deserialize)]
@@ -88,101 +217,12 @@ pub fn op_webgpu_create_bind_group_layout(
let mut entries = vec![];
- for entry in &args.entries {
+ for entry in args.entries {
entries.push(wgpu_types::BindGroupLayoutEntry {
binding: entry.binding,
visibility: wgpu_types::ShaderStages::from_bits(entry.visibility)
.unwrap(),
- ty: if let Some(buffer) = &entry.buffer {
- wgpu_types::BindingType::Buffer {
- ty: match &buffer.kind {
- Some(kind) => match kind.as_str() {
- "uniform" => wgpu_types::BufferBindingType::Uniform,
- "storage" => {
- wgpu_types::BufferBindingType::Storage { read_only: false }
- }
- "read-only-storage" => {
- wgpu_types::BufferBindingType::Storage { read_only: true }
- }
- _ => unreachable!(),
- },
- None => wgpu_types::BufferBindingType::Uniform,
- },
- has_dynamic_offset: buffer.has_dynamic_offset.unwrap_or(false),
- min_binding_size: if let Some(min_binding_size) =
- buffer.min_binding_size
- {
- std::num::NonZeroU64::new(min_binding_size)
- } else {
- None
- },
- }
- } else if let Some(sampler) = &entry.sampler {
- match &sampler.kind {
- Some(kind) => match kind.as_str() {
- "filtering" => wgpu_types::BindingType::Sampler {
- filtering: true,
- comparison: false,
- },
- "non-filtering" => wgpu_types::BindingType::Sampler {
- filtering: false,
- comparison: false,
- },
- "comparison" => wgpu_types::BindingType::Sampler {
- filtering: true,
- comparison: true,
- },
- _ => unreachable!(),
- },
- None => wgpu_types::BindingType::Sampler {
- filtering: true,
- comparison: false,
- },
- }
- } else if let Some(texture) = &entry.texture {
- wgpu_types::BindingType::Texture {
- sample_type: match &texture.sample_type {
- Some(sample_type) => match sample_type.as_str() {
- "float" => {
- wgpu_types::TextureSampleType::Float { filterable: true }
- }
- "unfilterable-float" => {
- wgpu_types::TextureSampleType::Float { filterable: false }
- }
- "depth" => wgpu_types::TextureSampleType::Depth,
- "sint" => wgpu_types::TextureSampleType::Sint,
- "uint" => wgpu_types::TextureSampleType::Uint,
- _ => unreachable!(),
- },
- None => wgpu_types::TextureSampleType::Float { filterable: true },
- },
- view_dimension: match &texture.view_dimension {
- Some(view_dimension) => {
- super::texture::serialize_dimension(view_dimension)
- }
- None => wgpu_types::TextureViewDimension::D2,
- },
- multisampled: texture.multisampled.unwrap_or(false),
- }
- } else if let Some(storage_texture) = &entry.storage_texture {
- wgpu_types::BindingType::StorageTexture {
- access: match storage_texture.access.as_str() {
- "write-only" => wgpu_types::StorageTextureAccess::WriteOnly,
- _ => unreachable!(),
- },
- format: super::texture::serialize_texture_format(
- &storage_texture.format,
- )?,
- view_dimension: match &storage_texture.view_dimension {
- Some(view_dimension) => {
- super::texture::serialize_dimension(view_dimension)
- }
- None => wgpu_types::TextureViewDimension::D2,
- },
- }
- } else {
- unreachable!()
- },
+ ty: entry.binding_type.try_into()?,
count: None, // native-only
});
}
@@ -244,7 +284,7 @@ pub fn op_webgpu_create_pipeline_layout(
struct GpuBindGroupEntry {
binding: u32,
kind: String,
- resource: u32,
+ resource: ResourceId,
offset: Option<u64>,
size: Option<u64>,
}
@@ -254,7 +294,7 @@ struct GpuBindGroupEntry {
pub struct CreateBindGroupArgs {
device_rid: ResourceId,
label: Option<String>,
- layout: u32,
+ layout: ResourceId,
entries: Vec<GpuBindGroupEntry>,
}
diff --git a/ext/webgpu/buffer.rs b/ext/webgpu/buffer.rs
index b87982aec..92afd2ef9 100644
--- a/ext/webgpu/buffer.rs
+++ b/ext/webgpu/buffer.rs
@@ -38,7 +38,7 @@ pub struct CreateBufferArgs {
label: Option<String>,
size: u64,
usage: u32,
- mapped_at_creation: Option<bool>,
+ mapped_at_creation: bool,
}
pub fn op_webgpu_create_buffer(
@@ -57,7 +57,7 @@ pub fn op_webgpu_create_buffer(
size: args.size,
usage: wgpu_types::BufferUsages::from_bits(args.usage)
.ok_or_else(|| type_error("usage is not valid"))?,
- mapped_at_creation: args.mapped_at_creation.unwrap_or(false),
+ mapped_at_creation: args.mapped_at_creation,
};
gfx_put!(device => instance.device_create_buffer(
diff --git a/ext/webgpu/bundle.rs b/ext/webgpu/bundle.rs
index 3a228ba62..df91104f5 100644
--- a/ext/webgpu/bundle.rs
+++ b/ext/webgpu/bundle.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::null_opbuf;
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
@@ -8,10 +7,13 @@ use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use std::cell::RefCell;
+use std::convert::TryInto;
use std::rc::Rc;
+use crate::pipeline::GpuIndexFormat;
+use crate::texture::GpuTextureFormat;
+
use super::error::WebGpuResult;
-use super::texture::serialize_texture_format;
struct WebGpuRenderBundleEncoder(
RefCell<wgpu_core::command::RenderBundleEncoder>,
@@ -34,9 +36,9 @@ impl Resource for WebGpuRenderBundle {
pub struct CreateRenderBundleEncoderArgs {
device_rid: ResourceId,
label: Option<String>,
- color_formats: Vec<String>,
- depth_stencil_format: Option<String>,
- sample_count: Option<u32>,
+ color_formats: Vec<GpuTextureFormat>,
+ depth_stencil_format: Option<GpuTextureFormat>,
+ sample_count: u32,
depth_read_only: bool,
stencil_read_only: bool,
}
@@ -53,24 +55,25 @@ pub fn op_webgpu_create_render_bundle_encoder(
let mut color_formats = vec![];
- for format in &args.color_formats {
- color_formats.push(serialize_texture_format(format)?);
+ for format in args.color_formats {
+ color_formats.push(format.try_into()?);
}
+ let depth_stencil = if let Some(format) = args.depth_stencil_format {
+ Some(wgpu_types::RenderBundleDepthStencil {
+ format: format.try_into()?,
+ depth_read_only: args.depth_read_only,
+ stencil_read_only: args.stencil_read_only,
+ })
+ } else {
+ None
+ };
+
let descriptor = wgpu_core::command::RenderBundleEncoderDescriptor {
label: args.label.map(Cow::from),
color_formats: Cow::from(color_formats),
- sample_count: args.sample_count.unwrap_or(1),
- depth_stencil: if let Some(depth_stencil_format) = args.depth_stencil_format
- {
- Some(wgpu_types::RenderBundleDepthStencil {
- format: serialize_texture_format(&depth_stencil_format)?,
- depth_read_only: args.depth_read_only,
- stencil_read_only: args.stencil_read_only,
- })
- } else {
- None
- },
+ sample_count: args.sample_count,
+ depth_stencil,
};
let res =
@@ -129,8 +132,8 @@ pub fn op_webgpu_render_bundle_encoder_finish(
pub struct RenderBundleEncoderSetBindGroupArgs {
render_bundle_encoder_rid: ResourceId,
index: u32,
- bind_group: u32,
- dynamic_offsets_data: Option<Vec<u32>>,
+ bind_group: ResourceId,
+ dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize,
}
@@ -138,7 +141,7 @@ pub struct RenderBundleEncoderSetBindGroupArgs {
pub fn op_webgpu_render_bundle_encoder_set_bind_group(
state: &mut OpState,
args: RenderBundleEncoderSetBindGroupArgs,
- zero_copy: Option<ZeroCopyBuf>,
+ _: (),
) -> Result<WebGpuResult, AnyError> {
let bind_group_resource =
state
@@ -149,37 +152,35 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group(
.resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
- // I know this might look like it can be easily deduplicated, but it can not
- // be due to the lifetime of the args.dynamic_offsets_data slice. Because we
- // need to use a raw pointer here the slice can be freed before the pointer
- // is used in wgpu_render_pass_set_bind_group. See
- // https://matrix.to/#/!XFRnMvAfptAHthwBCx:matrix.org/$HgrlhD-Me1DwsGb8UdMu2Hqubgks8s7ILwWRwigOUAg
- match args.dynamic_offsets_data {
- Some(data) => unsafe {
- wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group(
- &mut render_bundle_encoder_resource.0.borrow_mut(),
- args.index,
- bind_group_resource.0,
- data.as_slice().as_ptr(),
- args.dynamic_offsets_data_length,
- );
- },
- None => {
- let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
- let (prefix, data, suffix) = unsafe { zero_copy.align_to::<u32>() };
- assert!(prefix.is_empty());
- assert!(suffix.is_empty());
- unsafe {
- wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group(
- &mut render_bundle_encoder_resource.0.borrow_mut(),
- args.index,
- bind_group_resource.0,
- data[args.dynamic_offsets_data_start..].as_ptr(),
- args.dynamic_offsets_data_length,
- );
- }
- }
- };
+ // Align the data
+ assert!(args.dynamic_offsets_data.len() % std::mem::size_of::<u32>() == 0);
+ // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
+ // multiple of 4.
+ let (prefix, dynamic_offsets_data, suffix) =
+ unsafe { args.dynamic_offsets_data.align_to::<u32>() };
+ assert!(prefix.is_empty());
+ assert!(suffix.is_empty());
+
+ let start = args.dynamic_offsets_data_start;
+ let len = args.dynamic_offsets_data_length;
+
+ // Assert that length and start are both in bounds
+ assert!(start <= dynamic_offsets_data.len());
+ assert!(len <= dynamic_offsets_data.len() - start);
+
+ let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len];
+
+ // SAFETY: the raw pointer and length are of the same slice, and that slice
+ // lives longer than the below function invocation.
+ unsafe {
+ wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group(
+ &mut render_bundle_encoder_resource.0.borrow_mut(),
+ args.index,
+ bind_group_resource.0,
+ dynamic_offsets_data.as_ptr(),
+ dynamic_offsets_data.len(),
+ );
+ }
Ok(WebGpuResult::empty())
}
@@ -201,8 +202,10 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group(
.resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+ let label = std::ffi::CString::new(args.group_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.group_label).unwrap();
wgpu_core::command::bundle_ffi::wgpu_render_bundle_push_debug_group(
&mut render_bundle_encoder_resource.0.borrow_mut(),
label.as_ptr(),
@@ -252,8 +255,10 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
.resource_table
.get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+ let label = std::ffi::CString::new(args.marker_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.marker_label).unwrap();
wgpu_core::command::bundle_ffi::wgpu_render_bundle_insert_debug_marker(
&mut render_bundle_encoder_resource.0.borrow_mut(),
label.as_ptr(),
@@ -267,7 +272,7 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderSetPipelineArgs {
render_bundle_encoder_rid: ResourceId,
- pipeline: u32,
+ pipeline: ResourceId,
}
pub fn op_webgpu_render_bundle_encoder_set_pipeline(
@@ -296,8 +301,8 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline(
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderSetIndexBufferArgs {
render_bundle_encoder_rid: ResourceId,
- buffer: u32,
- index_format: String,
+ buffer: ResourceId,
+ index_format: GpuIndexFormat,
offset: u64,
size: u64,
}
@@ -320,7 +325,7 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
.borrow_mut()
.set_index_buffer(
buffer_resource.0,
- super::pipeline::serialize_index_format(args.index_format),
+ args.index_format.into(),
args.offset,
std::num::NonZeroU64::new(args.size),
);
@@ -333,7 +338,7 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
pub struct RenderBundleEncoderSetVertexBufferArgs {
render_bundle_encoder_rid: ResourceId,
slot: u32,
- buffer: u32,
+ buffer: ResourceId,
offset: u64,
size: u64,
}
@@ -430,7 +435,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indexed(
#[serde(rename_all = "camelCase")]
pub struct RenderBundleEncoderDrawIndirectArgs {
render_bundle_encoder_rid: ResourceId,
- indirect_buffer: u32,
+ indirect_buffer: ResourceId,
indirect_offset: u64,
}
diff --git a/ext/webgpu/command_encoder.rs b/ext/webgpu/command_encoder.rs
index b68bab7bd..afffe77a0 100644
--- a/ext/webgpu/command_encoder.rs
+++ b/ext/webgpu/command_encoder.rs
@@ -8,6 +8,8 @@ use std::borrow::Cow;
use std::cell::RefCell;
use std::num::NonZeroU32;
+use crate::texture::GpuTextureAspect;
+
use super::error::WebGpuResult;
pub(crate) struct WebGpuCommandEncoder(
@@ -28,14 +30,6 @@ impl Resource for WebGpuCommandBuffer {
}
}
-fn serialize_store_op(store_op: String) -> wgpu_core::command::StoreOp {
- match store_op.as_str() {
- "store" => wgpu_core::command::StoreOp::Store,
- "discard" => wgpu_core::command::StoreOp::Discard,
- _ => unreachable!(),
- }
-}
-
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateCommandEncoderArgs {
@@ -69,25 +63,45 @@ pub fn op_webgpu_create_command_encoder(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuRenderPassColorAttachment {
- view: u32,
- resolve_target: Option<u32>,
- load_op: String,
- load_value: Option<super::render_pass::GpuColor>,
- store_op: Option<String>,
+ view: ResourceId,
+ resolve_target: Option<ResourceId>,
+ load_op: GpuLoadOp<super::render_pass::GpuColor>,
+ store_op: GpuStoreOp,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuLoadOp<T> {
+ Load,
+ Clear(T),
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuStoreOp {
+ Store,
+ Discard,
+}
+
+impl From<GpuStoreOp> for wgpu_core::command::StoreOp {
+ fn from(value: GpuStoreOp) -> wgpu_core::command::StoreOp {
+ match value {
+ GpuStoreOp::Store => wgpu_core::command::StoreOp::Store,
+ GpuStoreOp::Discard => wgpu_core::command::StoreOp::Discard,
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuRenderPassDepthStencilAttachment {
- view: u32,
- depth_load_op: String,
- depth_load_value: Option<f32>,
- depth_store_op: String,
- depth_read_only: Option<bool>,
- stencil_load_op: String,
- stencil_load_value: Option<u32>,
- stencil_store_op: String,
- stencil_read_only: Option<bool>,
+ view: ResourceId,
+ depth_load_op: GpuLoadOp<f32>,
+ depth_store_op: GpuStoreOp,
+ depth_read_only: bool,
+ stencil_load_op: GpuLoadOp<u32>,
+ stencil_store_op: GpuStoreOp,
+ stencil_read_only: bool,
}
#[derive(Deserialize)]
@@ -117,43 +131,37 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
.resource_table
.get::<super::texture::WebGpuTextureView>(color_attachment.view)?;
+ let resolve_target = color_attachment
+ .resolve_target
+ .map(|rid| {
+ state
+ .resource_table
+ .get::<super::texture::WebGpuTextureView>(rid)
+ })
+ .transpose()?
+ .map(|texture| texture.0);
+
let attachment = wgpu_core::command::RenderPassColorAttachment {
view: texture_view_resource.0,
- resolve_target: color_attachment
- .resolve_target
- .map(|rid| {
- state
- .resource_table
- .get::<super::texture::WebGpuTextureView>(rid)
- })
- .transpose()?
- .map(|texture| texture.0),
- channel: match color_attachment.load_op.as_str() {
- "load" => wgpu_core::command::PassChannel {
+ 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
- .map_or(wgpu_core::command::StoreOp::Store, serialize_store_op),
+ store_op: color_attachment.store_op.into(),
clear_value: Default::default(),
read_only: false,
},
- "clear" => {
- let color = color_attachment.load_value.unwrap();
- wgpu_core::command::PassChannel {
- load_op: wgpu_core::command::LoadOp::Clear,
- store_op: color_attachment
- .store_op
- .map_or(wgpu_core::command::StoreOp::Store, serialize_store_op),
- clear_value: wgpu_types::Color {
- r: color.r,
- g: color.g,
- b: color.b,
- a: color.a,
- },
- read_only: false,
- }
- }
- _ => unreachable!(),
+ GpuLoadOp::Clear(color) => wgpu_core::command::PassChannel {
+ load_op: wgpu_core::command::LoadOp::Clear,
+ store_op: color_attachment.store_op.into(),
+ clear_value: wgpu_types::Color {
+ r: color.r,
+ g: color.g,
+ b: color.b,
+ a: color.a,
+ },
+ read_only: false,
+ },
},
};
@@ -171,35 +179,33 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
depth_stencil_attachment =
Some(wgpu_core::command::RenderPassDepthStencilAttachment {
view: texture_view_resource.0,
- depth: match attachment.depth_load_op.as_str() {
- "load" => wgpu_core::command::PassChannel {
+ depth: match attachment.depth_load_op {
+ GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load,
- store_op: serialize_store_op(attachment.depth_store_op),
+ store_op: attachment.depth_store_op.into(),
clear_value: 0.0,
- read_only: attachment.depth_read_only.unwrap_or(false),
+ read_only: attachment.depth_read_only,
},
- "clear" => wgpu_core::command::PassChannel {
+ GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear,
- store_op: serialize_store_op(attachment.depth_store_op),
- clear_value: attachment.depth_load_value.unwrap(),
- read_only: attachment.depth_read_only.unwrap_or(false),
+ store_op: attachment.depth_store_op.into(),
+ clear_value: value,
+ read_only: attachment.depth_read_only,
},
- _ => unreachable!(),
},
- stencil: match attachment.stencil_load_op.as_str() {
- "load" => wgpu_core::command::PassChannel {
+ stencil: match attachment.stencil_load_op {
+ GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load,
- store_op: serialize_store_op(attachment.stencil_store_op),
+ store_op: attachment.stencil_store_op.into(),
clear_value: 0,
- read_only: attachment.stencil_read_only.unwrap_or(false),
+ read_only: attachment.stencil_read_only,
},
- "clear" => wgpu_core::command::PassChannel {
+ GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear,
- store_op: serialize_store_op(attachment.stencil_store_op),
- clear_value: attachment.stencil_load_value.unwrap(),
- read_only: attachment.stencil_read_only.unwrap_or(false),
+ store_op: attachment.stencil_store_op.into(),
+ clear_value: value,
+ read_only: attachment.stencil_read_only,
},
- _ => unreachable!(),
},
});
}
@@ -262,9 +268,9 @@ pub fn op_webgpu_command_encoder_begin_compute_pass(
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderCopyBufferToBufferArgs {
command_encoder_rid: ResourceId,
- source: u32,
+ source: ResourceId,
source_offset: u64,
- destination: u32,
+ destination: ResourceId,
destination_offset: u64,
size: u64,
}
@@ -303,8 +309,8 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_buffer(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuImageCopyBuffer {
- buffer: u32,
- offset: Option<u64>,
+ buffer: ResourceId,
+ offset: u64,
bytes_per_row: Option<u32>,
rows_per_image: Option<u32>,
}
@@ -312,18 +318,28 @@ pub struct GpuImageCopyBuffer {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuOrigin3D {
- pub x: Option<u32>,
- pub y: Option<u32>,
- pub z: Option<u32>,
+ pub x: u32,
+ pub y: u32,
+ pub z: u32,
+}
+
+impl From<GpuOrigin3D> for wgpu_types::Origin3d {
+ fn from(origin: GpuOrigin3D) -> wgpu_types::Origin3d {
+ wgpu_types::Origin3d {
+ x: origin.x,
+ y: origin.y,
+ z: origin.z,
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuImageCopyTexture {
- pub texture: u32,
- pub mip_level: Option<u32>,
- pub origin: Option<GpuOrigin3D>,
- pub aspect: String,
+ pub texture: ResourceId,
+ pub mip_level: u32,
+ pub origin: GpuOrigin3D,
+ pub aspect: GpuTextureAspect,
}
#[derive(Deserialize)]
@@ -357,38 +373,22 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
let source = wgpu_core::command::ImageCopyBuffer {
buffer: source_buffer_resource.0,
layout: wgpu_types::ImageDataLayout {
- offset: args.source.offset.unwrap_or(0),
+ offset: args.source.offset,
bytes_per_row: NonZeroU32::new(args.source.bytes_per_row.unwrap_or(0)),
rows_per_image: NonZeroU32::new(args.source.rows_per_image.unwrap_or(0)),
},
};
let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0,
- mip_level: args.destination.mip_level.unwrap_or(0),
- origin: args
- .destination
- .origin
- .map_or(Default::default(), |origin| wgpu_types::Origin3d {
- x: origin.x.unwrap_or(0),
- y: origin.y.unwrap_or(0),
- z: origin.z.unwrap_or(0),
- }),
- aspect: match args.destination.aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
+ mip_level: args.destination.mip_level,
+ origin: args.destination.origin.into(),
+ aspect: args.destination.aspect.into(),
};
gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture(
command_encoder,
&source,
&destination,
- &wgpu_types::Extent3d {
- width: args.copy_size.width.unwrap_or(1),
- height: args.copy_size.height.unwrap_or(1),
- depth_or_array_layers: args.copy_size.depth_or_array_layers.unwrap_or(1),
- }
+ &args.copy_size.into()
))
}
@@ -422,25 +422,14 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0,
- mip_level: args.source.mip_level.unwrap_or(0),
- origin: args.source.origin.map_or(Default::default(), |origin| {
- wgpu_types::Origin3d {
- x: origin.x.unwrap_or(0),
- y: origin.y.unwrap_or(0),
- z: origin.z.unwrap_or(0),
- }
- }),
- aspect: match args.source.aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
+ mip_level: args.source.mip_level,
+ origin: args.source.origin.into(),
+ aspect: args.source.aspect.into(),
};
let destination = wgpu_core::command::ImageCopyBuffer {
buffer: destination_buffer_resource.0,
layout: wgpu_types::ImageDataLayout {
- offset: args.destination.offset.unwrap_or(0),
+ offset: args.destination.offset,
bytes_per_row: NonZeroU32::new(
args.destination.bytes_per_row.unwrap_or(0),
),
@@ -453,11 +442,7 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
command_encoder,
&source,
&destination,
- &wgpu_types::Extent3d {
- width: args.copy_size.width.unwrap_or(1),
- height: args.copy_size.height.unwrap_or(1),
- depth_or_array_layers: args.copy_size.depth_or_array_layers.unwrap_or(1),
- }
+ &args.copy_size.into()
))
}
@@ -491,48 +476,21 @@ pub fn op_webgpu_command_encoder_copy_texture_to_texture(
let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0,
- mip_level: args.source.mip_level.unwrap_or(0),
- origin: args.source.origin.map_or(Default::default(), |origin| {
- wgpu_types::Origin3d {
- x: origin.x.unwrap_or(0),
- y: origin.y.unwrap_or(0),
- z: origin.z.unwrap_or(0),
- }
- }),
- aspect: match args.source.aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
+ mip_level: args.source.mip_level,
+ origin: args.source.origin.into(),
+ aspect: args.source.aspect.into(),
};
let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0,
- mip_level: args.destination.mip_level.unwrap_or(0),
- origin: args
- .destination
- .origin
- .map_or(Default::default(), |origin| wgpu_types::Origin3d {
- x: origin.x.unwrap_or(0),
- y: origin.y.unwrap_or(0),
- z: origin.z.unwrap_or(0),
- }),
- aspect: match args.destination.aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
+ mip_level: args.destination.mip_level,
+ origin: args.destination.origin.into(),
+ aspect: args.destination.aspect.into(),
};
gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture(
command_encoder,
&source,
&destination,
- &wgpu_types::Extent3d {
- width: args.copy_size.width.unwrap_or(1),
- height: args.copy_size.height.unwrap_or(1),
- depth_or_array_layers: args.copy_size.depth_or_array_layers.unwrap_or(1),
- }
+ &args.copy_size.into()
))
}
@@ -606,7 +564,7 @@ pub fn op_webgpu_command_encoder_insert_debug_marker(
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderWriteTimestampArgs {
command_encoder_rid: ResourceId,
- query_set: u32,
+ query_set: ResourceId,
query_index: u32,
}
@@ -635,10 +593,10 @@ pub fn op_webgpu_command_encoder_write_timestamp(
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderResolveQuerySetArgs {
command_encoder_rid: ResourceId,
- query_set: u32,
+ query_set: ResourceId,
first_query: u32,
query_count: u32,
- destination: u32,
+ destination: ResourceId,
destination_offset: u64,
}
diff --git a/ext/webgpu/compute_pass.rs b/ext/webgpu/compute_pass.rs
index 4fc0af538..fe1186c4e 100644
--- a/ext/webgpu/compute_pass.rs
+++ b/ext/webgpu/compute_pass.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::null_opbuf;
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
@@ -24,7 +23,7 @@ impl Resource for WebGpuComputePass {
#[serde(rename_all = "camelCase")]
pub struct ComputePassSetPipelineArgs {
compute_pass_rid: ResourceId,
- pipeline: u32,
+ pipeline: ResourceId,
}
pub fn op_webgpu_compute_pass_set_pipeline(
@@ -80,7 +79,7 @@ pub fn op_webgpu_compute_pass_dispatch(
#[serde(rename_all = "camelCase")]
pub struct ComputePassDispatchIndirectArgs {
compute_pass_rid: ResourceId,
- indirect_buffer: u32,
+ indirect_buffer: ResourceId,
indirect_offset: u64,
}
@@ -109,7 +108,7 @@ pub fn op_webgpu_compute_pass_dispatch_indirect(
#[serde(rename_all = "camelCase")]
pub struct ComputePassBeginPipelineStatisticsQueryArgs {
compute_pass_rid: ResourceId,
- query_set: u32,
+ query_set: ResourceId,
query_index: u32,
}
@@ -160,7 +159,7 @@ pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
#[serde(rename_all = "camelCase")]
pub struct ComputePassWriteTimestampArgs {
compute_pass_rid: ResourceId,
- query_set: u32,
+ query_set: ResourceId,
query_index: u32,
}
@@ -220,8 +219,8 @@ pub fn op_webgpu_compute_pass_end_pass(
pub struct ComputePassSetBindGroupArgs {
compute_pass_rid: ResourceId,
index: u32,
- bind_group: u32,
- dynamic_offsets_data: Option<Vec<u32>>,
+ bind_group: ResourceId,
+ dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize,
}
@@ -229,7 +228,7 @@ pub struct ComputePassSetBindGroupArgs {
pub fn op_webgpu_compute_pass_set_bind_group(
state: &mut OpState,
args: ComputePassSetBindGroupArgs,
- zero_copy: Option<ZeroCopyBuf>,
+ _: (),
) -> Result<WebGpuResult, AnyError> {
let bind_group_resource =
state
@@ -239,22 +238,33 @@ pub fn op_webgpu_compute_pass_set_bind_group(
.resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?;
+ // Align the data
+ assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0);
+ // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
+ // multiple of 4.
+ let (prefix, dynamic_offsets_data, suffix) =
+ unsafe { args.dynamic_offsets_data.align_to::<u32>() };
+ assert!(prefix.is_empty());
+ assert!(suffix.is_empty());
+
+ let start = args.dynamic_offsets_data_start;
+ let len = args.dynamic_offsets_data_length;
+
+ // Assert that length and start are both in bounds
+ assert!(start <= dynamic_offsets_data.len());
+ assert!(len <= dynamic_offsets_data.len() - start);
+
+ let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len];
+
+ // SAFETY: the raw pointer and length are of the same slice, and that slice
+ // lives longer than the below function invocation.
unsafe {
wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group(
&mut compute_pass_resource.0.borrow_mut(),
args.index,
bind_group_resource.0,
- match args.dynamic_offsets_data {
- Some(data) => data.as_ptr(),
- None => {
- let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
- let (prefix, data, suffix) = zero_copy.align_to::<u32>();
- assert!(prefix.is_empty());
- assert!(suffix.is_empty());
- data[args.dynamic_offsets_data_start..].as_ptr()
- }
- },
- args.dynamic_offsets_data_length,
+ dynamic_offsets_data.as_ptr(),
+ dynamic_offsets_data.len(),
);
}
@@ -277,8 +287,10 @@ pub fn op_webgpu_compute_pass_push_debug_group(
.resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?;
+ let label = std::ffi::CString::new(args.group_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.group_label).unwrap();
wgpu_core::command::compute_ffi::wgpu_compute_pass_push_debug_group(
&mut compute_pass_resource.0.borrow_mut(),
label.as_ptr(),
@@ -327,8 +339,10 @@ pub fn op_webgpu_compute_pass_insert_debug_marker(
.resource_table
.get::<WebGpuComputePass>(args.compute_pass_rid)?;
+ let label = std::ffi::CString::new(args.marker_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.marker_label).unwrap();
wgpu_core::command::compute_ffi::wgpu_compute_pass_insert_debug_marker(
&mut compute_pass_resource.0.borrow_mut(),
label.as_ptr(),
diff --git a/ext/webgpu/lib.rs b/ext/webgpu/lib.rs
index d2b0a239b..0fdd30dd3 100644
--- a/ext/webgpu/lib.rs
+++ b/ext/webgpu/lib.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::not_supported;
use deno_core::error::AnyError;
use deno_core::include_js_files;
use deno_core::op_async;
@@ -14,10 +13,12 @@ use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::cell::RefCell;
+use std::collections::HashSet;
use std::path::PathBuf;
use std::rc::Rc;
pub use wgpu_core;
pub use wgpu_types;
+use wgpu_types::PowerPreference;
use error::DomExceptionOperationError;
use error::WebGpuResult;
@@ -218,9 +219,27 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
}
#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuPowerPreference {
+ LowPower,
+ HighPerformance,
+}
+
+impl From<GpuPowerPreference> for wgpu_types::PowerPreference {
+ fn from(value: GpuPowerPreference) -> wgpu_types::PowerPreference {
+ match value {
+ GpuPowerPreference::LowPower => wgpu_types::PowerPreference::LowPower,
+ GpuPowerPreference::HighPerformance => {
+ wgpu_types::PowerPreference::HighPerformance
+ }
+ }
+ }
+}
+
+#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RequestAdapterArgs {
- power_preference: Option<String>,
+ power_preference: Option<GpuPowerPreference>,
}
#[derive(Serialize)]
@@ -260,12 +279,8 @@ pub async fn op_webgpu_request_adapter(
let descriptor = wgpu_core::instance::RequestAdapterOptions {
power_preference: match args.power_preference {
- Some(power_preference) => match power_preference.as_str() {
- "low-power" => wgpu_types::PowerPreference::LowPower,
- "high-performance" => wgpu_types::PowerPreference::HighPerformance,
- _ => unreachable!(),
- },
- None => Default::default(),
+ Some(power_preference) => power_preference.into(),
+ None => PowerPreference::default(),
},
// TODO(lucacasonato): respect forceFallbackAdapter
compatible_surface: None, // windowless
@@ -412,124 +427,132 @@ impl From<GpuLimits> for wgpu_types::Limits {
pub struct RequestDeviceArgs {
adapter_rid: ResourceId,
label: Option<String>,
- required_features: Option<Vec<String>>,
+ required_features: Option<GpuRequiredFeatures>,
required_limits: Option<GpuLimits>,
}
-pub async fn op_webgpu_request_device(
- state: Rc<RefCell<OpState>>,
- args: RequestDeviceArgs,
- _: (),
-) -> Result<GpuAdapterDevice, AnyError> {
- let mut state = state.borrow_mut();
- let adapter_resource = state
- .resource_table
- .get::<WebGpuAdapter>(args.adapter_rid)?;
- let adapter = adapter_resource.0;
- let instance = state.borrow::<Instance>();
+#[derive(Deserialize)]
+pub struct GpuRequiredFeatures(HashSet<String>);
- let mut features: wgpu_types::Features = wgpu_types::Features::empty();
+impl From<GpuRequiredFeatures> for wgpu_types::Features {
+ fn from(required_features: GpuRequiredFeatures) -> wgpu_types::Features {
+ let mut features: wgpu_types::Features = wgpu_types::Features::empty();
- if let Some(passed_features) = args.required_features {
- if passed_features.contains(&"depth-clamping".to_string()) {
+ if required_features.0.contains("depth-clamping") {
features.set(wgpu_types::Features::DEPTH_CLAMPING, true);
}
- if passed_features.contains(&"pipeline-statistics-query".to_string()) {
+ if required_features.0.contains("pipeline-statistics-query") {
features.set(wgpu_types::Features::PIPELINE_STATISTICS_QUERY, true);
}
- if passed_features.contains(&"texture-compression-bc".to_string()) {
+ if required_features.0.contains("texture-compression-bc") {
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_BC, true);
}
- if passed_features.contains(&"timestamp-query".to_string()) {
+ if required_features.0.contains("timestamp-query") {
features.set(wgpu_types::Features::TIMESTAMP_QUERY, true);
}
// extended from spec
- if passed_features.contains(&"mappable-primary-buffers".to_string()) {
+ if required_features.0.contains("mappable-primary-buffers") {
features.set(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS, true);
}
- if passed_features.contains(&"texture-binding-array".to_string()) {
+ if required_features.0.contains("texture-binding-array") {
features.set(wgpu_types::Features::TEXTURE_BINDING_ARRAY, true);
}
- if passed_features.contains(&"buffer-binding-array".to_string()) {
+ if required_features.0.contains("buffer-binding-array") {
features.set(wgpu_types::Features::BUFFER_BINDING_ARRAY, true);
}
- if passed_features.contains(&"storage-resource-binding-array".to_string()) {
+ if required_features
+ .0
+ .contains("storage-resource-binding-array")
+ {
features.set(wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY, true);
}
- if passed_features.contains(
- &"sampled-texture-and-storage-buffer-array-non-uniform-indexing"
- .to_string(),
- ) {
+ if required_features
+ .0
+ .contains("sampled-texture-and-storage-buffer-array-non-uniform-indexing")
+ {
features.set(wgpu_types::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, true);
}
- if passed_features.contains(
- &"uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"
- .to_string(),
+ if required_features.0.contains(
+ "uniform-buffer-and-storage-buffer-texture-non-uniform-indexing",
) {
features.set(wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, true);
}
- if passed_features.contains(&"unsized-binding-array".to_string()) {
+ if required_features.0.contains("unsized-binding-array") {
features.set(wgpu_types::Features::UNSIZED_BINDING_ARRAY, true);
}
- if passed_features.contains(&"multi-draw-indirect".to_string()) {
+ if required_features.0.contains("multi-draw-indirect") {
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT, true);
}
- if passed_features.contains(&"multi-draw-indirect-count".to_string()) {
+ if required_features.0.contains("multi-draw-indirect-count") {
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT, true);
}
- if passed_features.contains(&"push-constants".to_string()) {
+ if required_features.0.contains("push-constants") {
features.set(wgpu_types::Features::PUSH_CONSTANTS, true);
}
- if passed_features.contains(&"address-mode-clamp-to-border".to_string()) {
+ if required_features.0.contains("address-mode-clamp-to-border") {
features.set(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, true);
}
- if passed_features.contains(&"non-fill-polygon-mode".to_string()) {
+ if required_features.0.contains("non-fill-polygon-mode") {
features.set(wgpu_types::Features::NON_FILL_POLYGON_MODE, true);
}
- if passed_features.contains(&"texture-compression-etc2".to_string()) {
+ if required_features.0.contains("texture-compression-etc2") {
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2, true);
}
- if passed_features.contains(&"texture-compression-astc-ldr".to_string()) {
+ if required_features.0.contains("texture-compression-astc-ldr") {
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR, true);
}
- if passed_features
- .contains(&"texture-adapter-specific-format-features".to_string())
+ if required_features
+ .0
+ .contains("texture-adapter-specific-format-features")
{
features.set(
wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
true,
);
}
- if passed_features.contains(&"shader-float64".to_string()) {
+ if required_features.0.contains("shader-float64") {
features.set(wgpu_types::Features::SHADER_FLOAT64, true);
}
- if passed_features.contains(&"vertex-attribute-64bit".to_string()) {
+ if required_features.0.contains("vertex-attribute-64bit") {
features.set(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, true);
}
- if passed_features.contains(&"conservative-rasterization".to_string()) {
+ if required_features.0.contains("conservative-rasterization") {
features.set(wgpu_types::Features::CONSERVATIVE_RASTERIZATION, true);
}
- if passed_features.contains(&"vertex-writable-storage".to_string()) {
+ if required_features.0.contains("vertex-writable-storage") {
features.set(wgpu_types::Features::VERTEX_WRITABLE_STORAGE, true);
}
- if passed_features.contains(&"clear-commands".to_string()) {
+ if required_features.0.contains("clear-commands") {
features.set(wgpu_types::Features::CLEAR_COMMANDS, true);
}
- if passed_features.contains(&"spirv-shader-passthrough".to_string()) {
+ if required_features.0.contains("spirv-shader-passthrough") {
features.set(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH, true);
}
- if passed_features.contains(&"shader-primitive-index".to_string()) {
+ if required_features.0.contains("shader-primitive-index") {
features.set(wgpu_types::Features::SHADER_PRIMITIVE_INDEX, true);
}
+
+ features
}
+}
+
+pub async fn op_webgpu_request_device(
+ state: Rc<RefCell<OpState>>,
+ args: RequestDeviceArgs,
+ _: (),
+) -> Result<GpuAdapterDevice, AnyError> {
+ let mut state = state.borrow_mut();
+ let adapter_resource = state
+ .resource_table
+ .get::<WebGpuAdapter>(args.adapter_rid)?;
+ let adapter = adapter_resource.0;
+ let instance = state.borrow::<Instance>();
let descriptor = wgpu_types::DeviceDescriptor {
label: args.label.map(Cow::from),
- features,
- limits: args
- .required_limits
- .map_or(wgpu_types::Limits::default(), Into::into),
+ features: args.required_features.map(Into::into).unwrap_or_default(),
+ limits: args.required_limits.map(Into::into).unwrap_or_default(),
};
let (device, maybe_err) = gfx_select!(adapter => instance.adapter_request_device(
@@ -564,10 +587,54 @@ pub async fn op_webgpu_request_device(
pub struct CreateQuerySetArgs {
device_rid: ResourceId,
label: Option<String>,
- #[serde(rename = "type")]
- kind: String,
+ #[serde(flatten)]
+ r#type: GpuQueryType,
count: u32,
- pipeline_statistics: Option<Vec<String>>,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case", tag = "type")]
+enum GpuQueryType {
+ Occlusion,
+ #[serde(rename_all = "camelCase")]
+ PipelineStatistics {
+ pipeline_statistics: HashSet<String>,
+ },
+ Timestamp,
+}
+
+impl From<GpuQueryType> for wgpu_types::QueryType {
+ fn from(query_type: GpuQueryType) -> Self {
+ match query_type {
+ GpuQueryType::Occlusion => wgpu_types::QueryType::Occlusion,
+ GpuQueryType::PipelineStatistics {
+ pipeline_statistics,
+ } => {
+ use wgpu_types::PipelineStatisticsTypes;
+
+ let mut types = PipelineStatisticsTypes::empty();
+
+ if pipeline_statistics.contains("vertex-shader-invocations") {
+ types.set(PipelineStatisticsTypes::VERTEX_SHADER_INVOCATIONS, true);
+ }
+ if pipeline_statistics.contains("clipper-invocations") {
+ types.set(PipelineStatisticsTypes::CLIPPER_INVOCATIONS, true);
+ }
+ if pipeline_statistics.contains("clipper-primitives-out") {
+ types.set(PipelineStatisticsTypes::CLIPPER_PRIMITIVES_OUT, true);
+ }
+ if pipeline_statistics.contains("fragment-shader-invocations") {
+ types.set(PipelineStatisticsTypes::FRAGMENT_SHADER_INVOCATIONS, true);
+ }
+ if pipeline_statistics.contains("compute-shader-invocations") {
+ types.set(PipelineStatisticsTypes::COMPUTE_SHADER_INVOCATIONS, true);
+ }
+
+ wgpu_types::QueryType::PipelineStatistics(types)
+ }
+ GpuQueryType::Timestamp => wgpu_types::QueryType::Timestamp,
+ }
+ }
}
pub fn op_webgpu_create_query_set(
@@ -582,57 +649,7 @@ pub fn op_webgpu_create_query_set(
let descriptor = wgpu_types::QuerySetDescriptor {
label: args.label.map(Cow::from),
- ty: match args.kind.as_str() {
- "pipeline-statistics" => {
- let mut pipeline_statistics_names =
- wgpu_types::PipelineStatisticsTypes::empty();
-
- if let Some(pipeline_statistics) = args.pipeline_statistics {
- if pipeline_statistics
- .contains(&"vertex-shader-invocations".to_string())
- {
- pipeline_statistics_names.set(
- wgpu_types::PipelineStatisticsTypes::VERTEX_SHADER_INVOCATIONS,
- true,
- );
- }
- if pipeline_statistics.contains(&"clipper-invocations".to_string()) {
- pipeline_statistics_names.set(
- wgpu_types::PipelineStatisticsTypes::CLIPPER_INVOCATIONS,
- true,
- );
- }
- if pipeline_statistics.contains(&"clipper-primitives-out".to_string())
- {
- pipeline_statistics_names.set(
- wgpu_types::PipelineStatisticsTypes::CLIPPER_PRIMITIVES_OUT,
- true,
- );
- }
- if pipeline_statistics
- .contains(&"fragment-shader-invocations".to_string())
- {
- pipeline_statistics_names.set(
- wgpu_types::PipelineStatisticsTypes::FRAGMENT_SHADER_INVOCATIONS,
- true,
- );
- }
- if pipeline_statistics
- .contains(&"compute-shader-invocations".to_string())
- {
- pipeline_statistics_names.set(
- wgpu_types::PipelineStatisticsTypes::COMPUTE_SHADER_INVOCATIONS,
- true,
- );
- }
- };
-
- wgpu_types::QueryType::PipelineStatistics(pipeline_statistics_names)
- }
- "occlusion" => return Err(not_supported()),
- "timestamp" => wgpu_types::QueryType::Timestamp,
- _ => unreachable!(),
- },
+ ty: args.r#type.into(),
count: args.count,
};
diff --git a/ext/webgpu/pipeline.rs b/ext/webgpu/pipeline.rs
index 877143f94..77edcadfb 100644
--- a/ext/webgpu/pipeline.rs
+++ b/ext/webgpu/pipeline.rs
@@ -6,6 +6,10 @@ use deno_core::{OpState, Resource};
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
+use std::convert::{TryFrom, TryInto};
+
+use crate::sampler::GpuCompareFunction;
+use crate::texture::GpuTextureFormat;
use super::error::{WebGpuError, WebGpuResult};
@@ -38,121 +42,196 @@ impl Resource for WebGpuRenderPipeline {
}
}
-pub fn serialize_index_format(format: String) -> wgpu_types::IndexFormat {
- match format.as_str() {
- "uint16" => wgpu_types::IndexFormat::Uint16,
- "uint32" => wgpu_types::IndexFormat::Uint32,
- _ => unreachable!(),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuIndexFormat {
+ Uint16,
+ Uint32,
+}
+
+impl From<GpuIndexFormat> for wgpu_types::IndexFormat {
+ fn from(value: GpuIndexFormat) -> wgpu_types::IndexFormat {
+ match value {
+ GpuIndexFormat::Uint16 => wgpu_types::IndexFormat::Uint16,
+ GpuIndexFormat::Uint32 => wgpu_types::IndexFormat::Uint32,
+ }
}
}
-fn serialize_stencil_operation(
- operation: &str,
-) -> wgpu_types::StencilOperation {
- match operation {
- "keep" => wgpu_types::StencilOperation::Keep,
- "zero" => wgpu_types::StencilOperation::Zero,
- "replace" => wgpu_types::StencilOperation::Replace,
- "invert" => wgpu_types::StencilOperation::Invert,
- "increment-clamp" => wgpu_types::StencilOperation::IncrementClamp,
- "decrement-clamp" => wgpu_types::StencilOperation::DecrementClamp,
- "increment-wrap" => wgpu_types::StencilOperation::IncrementWrap,
- "decrement-wrap" => wgpu_types::StencilOperation::DecrementWrap,
- _ => unreachable!(),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GPUStencilOperation {
+ Keep,
+ Zero,
+ Replace,
+ Invert,
+ IncrementClamp,
+ DecrementClamp,
+ IncrementWrap,
+ DecrementWrap,
+}
+
+impl From<GPUStencilOperation> for wgpu_types::StencilOperation {
+ fn from(value: GPUStencilOperation) -> wgpu_types::StencilOperation {
+ match value {
+ GPUStencilOperation::Keep => wgpu_types::StencilOperation::Keep,
+ GPUStencilOperation::Zero => wgpu_types::StencilOperation::Zero,
+ GPUStencilOperation::Replace => wgpu_types::StencilOperation::Replace,
+ GPUStencilOperation::Invert => wgpu_types::StencilOperation::Invert,
+ GPUStencilOperation::IncrementClamp => {
+ wgpu_types::StencilOperation::IncrementClamp
+ }
+ GPUStencilOperation::DecrementClamp => {
+ wgpu_types::StencilOperation::DecrementClamp
+ }
+ GPUStencilOperation::IncrementWrap => {
+ wgpu_types::StencilOperation::IncrementWrap
+ }
+ GPUStencilOperation::DecrementWrap => {
+ wgpu_types::StencilOperation::DecrementWrap
+ }
+ }
}
}
-fn serialize_stencil_face_state(
- state: GpuStencilFaceState,
-) -> wgpu_types::StencilFaceState {
- wgpu_types::StencilFaceState {
- compare: state
- .compare
- .as_ref()
- .map_or(wgpu_types::CompareFunction::Always, |op| {
- super::sampler::serialize_compare_function(op)
- }),
- fail_op: state
- .fail_op
- .as_ref()
- .map_or(wgpu_types::StencilOperation::Keep, |op| {
- serialize_stencil_operation(op)
- }),
- depth_fail_op: state
- .depth_fail_op
- .as_ref()
- .map_or(wgpu_types::StencilOperation::Keep, |op| {
- serialize_stencil_operation(op)
- }),
- pass_op: state
- .pass_op
- .as_ref()
- .map_or(wgpu_types::StencilOperation::Keep, |op| {
- serialize_stencil_operation(op)
- }),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuBlendFactor {
+ Zero,
+ One,
+ Src,
+ OneMinusSrc,
+ SrcAlpha,
+ OneMinusSrcAlpha,
+ Dst,
+ OneMinusDst,
+ DstAlpha,
+ OneMinusDstAlpha,
+ SrcAlphaSaturated,
+ Constant,
+ OneMinusConstant,
+}
+
+impl From<GpuBlendFactor> for wgpu_types::BlendFactor {
+ fn from(value: GpuBlendFactor) -> wgpu_types::BlendFactor {
+ match value {
+ GpuBlendFactor::Zero => wgpu_types::BlendFactor::Zero,
+ GpuBlendFactor::One => wgpu_types::BlendFactor::One,
+ GpuBlendFactor::Src => wgpu_types::BlendFactor::Src,
+ GpuBlendFactor::OneMinusSrc => wgpu_types::BlendFactor::OneMinusSrc,
+ GpuBlendFactor::SrcAlpha => wgpu_types::BlendFactor::SrcAlpha,
+ GpuBlendFactor::OneMinusSrcAlpha => {
+ wgpu_types::BlendFactor::OneMinusSrcAlpha
+ }
+ GpuBlendFactor::Dst => wgpu_types::BlendFactor::Dst,
+ GpuBlendFactor::OneMinusDst => wgpu_types::BlendFactor::OneMinusDst,
+ GpuBlendFactor::DstAlpha => wgpu_types::BlendFactor::DstAlpha,
+ GpuBlendFactor::OneMinusDstAlpha => {
+ wgpu_types::BlendFactor::OneMinusDstAlpha
+ }
+ GpuBlendFactor::SrcAlphaSaturated => {
+ wgpu_types::BlendFactor::SrcAlphaSaturated
+ }
+ GpuBlendFactor::Constant => wgpu_types::BlendFactor::Constant,
+ GpuBlendFactor::OneMinusConstant => {
+ wgpu_types::BlendFactor::OneMinusConstant
+ }
+ }
}
}
-fn serialize_blend_factor(blend_factor: &str) -> wgpu_types::BlendFactor {
- match blend_factor {
- "zero" => wgpu_types::BlendFactor::Zero,
- "one" => wgpu_types::BlendFactor::One,
- "src" => wgpu_types::BlendFactor::Src,
- "one-minus-src" => wgpu_types::BlendFactor::OneMinusSrc,
- "src-alpha" => wgpu_types::BlendFactor::SrcAlpha,
- "one-minus-src-alpha" => wgpu_types::BlendFactor::OneMinusSrcAlpha,
- "dst" => wgpu_types::BlendFactor::Dst,
- "one-minus-dst" => wgpu_types::BlendFactor::OneMinusDst,
- "dst-alpha" => wgpu_types::BlendFactor::DstAlpha,
- "one-minus-dst-alpha" => wgpu_types::BlendFactor::OneMinusDstAlpha,
- "src-alpha-saturated" => wgpu_types::BlendFactor::SrcAlphaSaturated,
- "constant" => wgpu_types::BlendFactor::Constant,
- "one-minus-constant" => wgpu_types::BlendFactor::OneMinusConstant,
- _ => unreachable!(),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuBlendOperation {
+ Add,
+ Subtract,
+ ReverseSubtract,
+ Min,
+ Max,
+}
+
+impl From<GpuBlendOperation> for wgpu_types::BlendOperation {
+ fn from(value: GpuBlendOperation) -> wgpu_types::BlendOperation {
+ match value {
+ GpuBlendOperation::Add => wgpu_types::BlendOperation::Add,
+ GpuBlendOperation::Subtract => wgpu_types::BlendOperation::Subtract,
+ GpuBlendOperation::ReverseSubtract => {
+ wgpu_types::BlendOperation::ReverseSubtract
+ }
+ GpuBlendOperation::Min => wgpu_types::BlendOperation::Min,
+ GpuBlendOperation::Max => wgpu_types::BlendOperation::Max,
+ }
}
}
-fn serialize_blend_state(state: GpuBlendState) -> wgpu_types::BlendState {
- wgpu_types::BlendState {
- alpha: serialize_blend_component(state.alpha),
- color: serialize_blend_component(state.color),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuPrimitiveTopology {
+ PointList,
+ LineList,
+ LineStrip,
+ TriangleList,
+ TriangleStrip,
+}
+
+impl From<GpuPrimitiveTopology> for wgpu_types::PrimitiveTopology {
+ fn from(value: GpuPrimitiveTopology) -> wgpu_types::PrimitiveTopology {
+ match value {
+ GpuPrimitiveTopology::PointList => {
+ wgpu_types::PrimitiveTopology::PointList
+ }
+ GpuPrimitiveTopology::LineList => wgpu_types::PrimitiveTopology::LineList,
+ GpuPrimitiveTopology::LineStrip => {
+ wgpu_types::PrimitiveTopology::LineStrip
+ }
+ GpuPrimitiveTopology::TriangleList => {
+ wgpu_types::PrimitiveTopology::TriangleList
+ }
+ GpuPrimitiveTopology::TriangleStrip => {
+ wgpu_types::PrimitiveTopology::TriangleStrip
+ }
+ }
}
}
-fn serialize_blend_component(
- blend: GpuBlendComponent,
-) -> wgpu_types::BlendComponent {
- wgpu_types::BlendComponent {
- src_factor: blend
- .src_factor
- .as_ref()
- .map_or(wgpu_types::BlendFactor::One, |factor| {
- serialize_blend_factor(factor)
- }),
- dst_factor: blend
- .dst_factor
- .as_ref()
- .map_or(wgpu_types::BlendFactor::Zero, |factor| {
- serialize_blend_factor(factor)
- }),
- operation: match &blend.operation {
- Some(operation) => match operation.as_str() {
- "add" => wgpu_types::BlendOperation::Add,
- "subtract" => wgpu_types::BlendOperation::Subtract,
- "reverse-subtract" => wgpu_types::BlendOperation::ReverseSubtract,
- "min" => wgpu_types::BlendOperation::Min,
- "max" => wgpu_types::BlendOperation::Max,
- _ => unreachable!(),
- },
- None => wgpu_types::BlendOperation::Add,
- },
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuFrontFace {
+ Ccw,
+ Cw,
+}
+
+impl From<GpuFrontFace> for wgpu_types::FrontFace {
+ fn from(value: GpuFrontFace) -> wgpu_types::FrontFace {
+ match value {
+ GpuFrontFace::Ccw => wgpu_types::FrontFace::Ccw,
+ GpuFrontFace::Cw => wgpu_types::FrontFace::Cw,
+ }
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuCullMode {
+ None,
+ Front,
+ Back,
+}
+
+impl From<GpuCullMode> for Option<wgpu_types::Face> {
+ fn from(value: GpuCullMode) -> Option<wgpu_types::Face> {
+ match value {
+ GpuCullMode::None => None,
+ GpuCullMode::Front => Some(wgpu_types::Face::Front),
+ GpuCullMode::Back => Some(wgpu_types::Face::Back),
+ }
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuProgrammableStage {
- module: u32,
+ module: ResourceId,
entry_point: String,
// constants: HashMap<String, GPUPipelineConstantValue>
}
@@ -162,7 +241,7 @@ struct GpuProgrammableStage {
pub struct CreateComputePipelineArgs {
device_rid: ResourceId,
label: Option<String>,
- layout: Option<u32>,
+ layout: Option<ResourceId>,
compute: GpuProgrammableStage,
}
@@ -264,58 +343,138 @@ pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuPrimitiveState {
- topology: Option<String>,
- strip_index_format: Option<String>,
- front_face: Option<String>,
- cull_mode: Option<String>,
+ topology: GpuPrimitiveTopology,
+ strip_index_format: Option<GpuIndexFormat>,
+ front_face: GpuFrontFace,
+ cull_mode: GpuCullMode,
clamp_depth: bool,
}
-#[derive(Deserialize, Clone)]
+impl From<GpuPrimitiveState> for wgpu_types::PrimitiveState {
+ fn from(value: GpuPrimitiveState) -> wgpu_types::PrimitiveState {
+ wgpu_types::PrimitiveState {
+ topology: value.topology.into(),
+ strip_index_format: value.strip_index_format.map(Into::into),
+ front_face: value.front_face.into(),
+ cull_mode: value.cull_mode.into(),
+ clamp_depth: value.clamp_depth,
+ polygon_mode: Default::default(), // native-only
+ conservative: false, // native-only
+ }
+ }
+}
+#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuBlendComponent {
- src_factor: Option<String>,
- dst_factor: Option<String>,
- operation: Option<String>,
+ src_factor: GpuBlendFactor,
+ dst_factor: GpuBlendFactor,
+ operation: GpuBlendOperation,
+}
+
+impl From<GpuBlendComponent> for wgpu_types::BlendComponent {
+ fn from(component: GpuBlendComponent) -> Self {
+ wgpu_types::BlendComponent {
+ src_factor: component.src_factor.into(),
+ dst_factor: component.dst_factor.into(),
+ operation: component.operation.into(),
+ }
+ }
}
-#[derive(Deserialize, Clone)]
+#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuBlendState {
color: GpuBlendComponent,
alpha: GpuBlendComponent,
}
+impl From<GpuBlendState> for wgpu_types::BlendState {
+ fn from(state: GpuBlendState) -> wgpu_types::BlendState {
+ wgpu_types::BlendState {
+ color: state.color.into(),
+ alpha: state.alpha.into(),
+ }
+ }
+}
+
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuColorTargetState {
- format: String,
+ format: GpuTextureFormat,
blend: Option<GpuBlendState>,
- write_mask: Option<u32>,
+ write_mask: u32,
+}
+
+impl TryFrom<GpuColorTargetState> for wgpu_types::ColorTargetState {
+ type Error = AnyError;
+ fn try_from(
+ state: GpuColorTargetState,
+ ) -> Result<wgpu_types::ColorTargetState, AnyError> {
+ Ok(wgpu_types::ColorTargetState {
+ format: state.format.try_into()?,
+ blend: state.blend.map(Into::into),
+ write_mask: wgpu_types::ColorWrites::from_bits_truncate(state.write_mask),
+ })
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuStencilFaceState {
- compare: Option<String>,
- fail_op: Option<String>,
- depth_fail_op: Option<String>,
- pass_op: Option<String>,
+ compare: GpuCompareFunction,
+ fail_op: GPUStencilOperation,
+ depth_fail_op: GPUStencilOperation,
+ pass_op: GPUStencilOperation,
+}
+
+impl From<GpuStencilFaceState> for wgpu_types::StencilFaceState {
+ fn from(state: GpuStencilFaceState) -> Self {
+ wgpu_types::StencilFaceState {
+ compare: state.compare.into(),
+ fail_op: state.fail_op.into(),
+ depth_fail_op: state.depth_fail_op.into(),
+ pass_op: state.pass_op.into(),
+ }
+ }
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuDepthStencilState {
- format: String,
- depth_write_enabled: Option<bool>,
- depth_compare: Option<String>,
- stencil_front: Option<GpuStencilFaceState>,
- stencil_back: Option<GpuStencilFaceState>,
- stencil_read_mask: Option<u32>,
- stencil_write_mask: Option<u32>,
- depth_bias: Option<i32>,
- depth_bias_slope_scale: Option<f32>,
- depth_bias_clamp: Option<f32>,
+ format: GpuTextureFormat,
+ depth_write_enabled: bool,
+ depth_compare: GpuCompareFunction,
+ stencil_front: GpuStencilFaceState,
+ stencil_back: GpuStencilFaceState,
+ stencil_read_mask: u32,
+ stencil_write_mask: u32,
+ depth_bias: i32,
+ depth_bias_slope_scale: f32,
+ depth_bias_clamp: f32,
+}
+
+impl TryFrom<GpuDepthStencilState> for wgpu_types::DepthStencilState {
+ type Error = AnyError;
+ fn try_from(
+ state: GpuDepthStencilState,
+ ) -> Result<wgpu_types::DepthStencilState, AnyError> {
+ Ok(wgpu_types::DepthStencilState {
+ format: state.format.try_into()?,
+ depth_write_enabled: state.depth_write_enabled,
+ depth_compare: state.depth_compare.into(),
+ stencil: wgpu_types::StencilState {
+ front: state.stencil_front.into(),
+ back: state.stencil_back.into(),
+ read_mask: state.stencil_read_mask,
+ write_mask: state.stencil_write_mask,
+ },
+ bias: wgpu_types::DepthBiasState {
+ constant: state.depth_bias,
+ slope_scale: state.depth_bias_slope_scale,
+ clamp: state.depth_bias_clamp,
+ },
+ })
+ }
}
#[derive(Deserialize)]
@@ -326,6 +485,16 @@ struct GpuVertexAttribute {
shader_location: u32,
}
+impl From<GpuVertexAttribute> for wgpu_types::VertexAttribute {
+ fn from(attribute: GpuVertexAttribute) -> Self {
+ wgpu_types::VertexAttribute {
+ format: attribute.format.into(),
+ offset: attribute.offset,
+ shader_location: attribute.shader_location,
+ }
+ }
+}
+
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum GpuVertexFormat {
@@ -409,26 +578,69 @@ impl From<GpuVertexFormat> for wgpu_types::VertexFormat {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
+enum GpuVertexStepMode {
+ Vertex,
+ Instance,
+}
+
+impl From<GpuVertexStepMode> for wgpu_types::VertexStepMode {
+ fn from(vsm: GpuVertexStepMode) -> wgpu_types::VertexStepMode {
+ use wgpu_types::VertexStepMode;
+ match vsm {
+ GpuVertexStepMode::Vertex => VertexStepMode::Vertex,
+ GpuVertexStepMode::Instance => VertexStepMode::Instance,
+ }
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
struct GpuVertexBufferLayout {
array_stride: u64,
- step_mode: Option<String>,
+ step_mode: GpuVertexStepMode,
attributes: Vec<GpuVertexAttribute>,
}
+impl<'a> From<GpuVertexBufferLayout>
+ for wgpu_core::pipeline::VertexBufferLayout<'a>
+{
+ fn from(
+ layout: GpuVertexBufferLayout,
+ ) -> wgpu_core::pipeline::VertexBufferLayout<'a> {
+ wgpu_core::pipeline::VertexBufferLayout {
+ array_stride: layout.array_stride,
+ step_mode: layout.step_mode.into(),
+ attributes: Cow::Owned(
+ layout.attributes.into_iter().map(Into::into).collect(),
+ ),
+ }
+ }
+}
+
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexState {
- module: u32,
+ module: ResourceId,
entry_point: String,
- buffers: Option<Vec<Option<GpuVertexBufferLayout>>>,
+ buffers: Vec<Option<GpuVertexBufferLayout>>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuMultisampleState {
- count: Option<u32>,
- mask: Option<u64>, // against spec, but future proof
- alpha_to_coverage_enabled: Option<bool>,
+ count: u32,
+ mask: u64,
+ alpha_to_coverage_enabled: bool,
+}
+
+impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
+ fn from(gms: GpuMultisampleState) -> wgpu_types::MultisampleState {
+ wgpu_types::MultisampleState {
+ count: gms.count,
+ mask: gms.mask,
+ alpha_to_coverage_enabled: gms.alpha_to_coverage_enabled,
+ }
+ }
}
#[derive(Deserialize)]
@@ -437,6 +649,7 @@ struct GpuFragmentState {
targets: Vec<GpuColorTargetState>,
module: u32,
entry_point: String,
+ // TODO(lucacasonato): constants
}
#[derive(Deserialize)]
@@ -444,11 +657,11 @@ struct GpuFragmentState {
pub struct CreateRenderPipelineArgs {
device_rid: ResourceId,
label: Option<String>,
- layout: Option<u32>,
+ layout: Option<ResourceId>,
vertex: GpuVertexState,
- primitive: Option<GpuPrimitiveState>,
+ primitive: GpuPrimitiveState,
depth_stencil: Option<GpuDepthStencilState>,
- multisample: Option<GpuMultisampleState>,
+ multisample: GpuMultisampleState,
fragment: Option<GpuFragmentState>,
}
@@ -476,149 +689,51 @@ pub fn op_webgpu_create_render_pipeline(
.resource_table
.get::<super::shader::WebGpuShaderModule>(args.vertex.module)?;
+ let fragment = if let Some(fragment) = args.fragment {
+ let fragment_shader_module_resource =
+ state
+ .resource_table
+ .get::<super::shader::WebGpuShaderModule>(fragment.module)?;
+
+ let mut targets = Vec::with_capacity(fragment.targets.len());
+
+ for target in fragment.targets {
+ targets.push(target.try_into()?);
+ }
+
+ Some(wgpu_core::pipeline::FragmentState {
+ stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
+ module: fragment_shader_module_resource.0,
+ entry_point: Cow::from(fragment.entry_point),
+ },
+ targets: Cow::from(targets),
+ })
+ } else {
+ None
+ };
+
+ let vertex_buffers = args
+ .vertex
+ .buffers
+ .into_iter()
+ .flatten()
+ .map(Into::into)
+ .collect();
+
let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor {
- label: args.label.map(Cow::from),
+ label: args.label.map(Cow::Owned),
layout,
vertex: wgpu_core::pipeline::VertexState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: vertex_shader_module_resource.0,
- entry_point: Cow::from(args.vertex.entry_point),
+ entry_point: Cow::Owned(args.vertex.entry_point),
},
- buffers: Cow::from(if let Some(buffers) = args.vertex.buffers {
- let mut return_buffers = vec![];
- for buffer in buffers.into_iter().flatten() {
- return_buffers.push(wgpu_core::pipeline::VertexBufferLayout {
- array_stride: buffer.array_stride,
- step_mode: match buffer.step_mode {
- Some(step_mode) => match step_mode.as_str() {
- "vertex" => wgpu_types::VertexStepMode::Vertex,
- "instance" => wgpu_types::VertexStepMode::Instance,
- _ => unreachable!(),
- },
- None => wgpu_types::VertexStepMode::Vertex,
- },
- attributes: Cow::from(
- buffer
- .attributes
- .into_iter()
- .map(|attribute| wgpu_types::VertexAttribute {
- format: attribute.format.into(),
- offset: attribute.offset,
- shader_location: attribute.shader_location,
- })
- .collect::<Vec<wgpu_types::VertexAttribute>>(),
- ),
- });
- }
- return_buffers
- } else {
- vec![]
- }),
+ buffers: Cow::Owned(vertex_buffers),
},
- primitive: args.primitive.map_or(Default::default(), |primitive| {
- wgpu_types::PrimitiveState {
- topology: match primitive.topology {
- Some(topology) => match topology.as_str() {
- "point-list" => wgpu_types::PrimitiveTopology::PointList,
- "line-list" => wgpu_types::PrimitiveTopology::LineList,
- "line-strip" => wgpu_types::PrimitiveTopology::LineStrip,
- "triangle-list" => wgpu_types::PrimitiveTopology::TriangleList,
- "triangle-strip" => wgpu_types::PrimitiveTopology::TriangleStrip,
- _ => unreachable!(),
- },
- None => wgpu_types::PrimitiveTopology::TriangleList,
- },
- strip_index_format: primitive
- .strip_index_format
- .map(serialize_index_format),
- front_face: match primitive.front_face {
- Some(front_face) => match front_face.as_str() {
- "ccw" => wgpu_types::FrontFace::Ccw,
- "cw" => wgpu_types::FrontFace::Cw,
- _ => unreachable!(),
- },
- None => wgpu_types::FrontFace::Ccw,
- },
- cull_mode: match primitive.cull_mode {
- Some(cull_mode) => match cull_mode.as_str() {
- "none" => None,
- "front" => Some(wgpu_types::Face::Front),
- "back" => Some(wgpu_types::Face::Back),
- _ => unreachable!(),
- },
- None => None,
- },
- polygon_mode: Default::default(), // native-only
- conservative: false, // native-only
- clamp_depth: primitive.clamp_depth,
- }
- }),
- depth_stencil: args.depth_stencil.map(|depth_stencil| {
- wgpu_types::DepthStencilState {
- format: super::texture::serialize_texture_format(&depth_stencil.format)
- .unwrap(),
- depth_write_enabled: depth_stencil.depth_write_enabled.unwrap_or(false),
- depth_compare: match depth_stencil.depth_compare {
- Some(depth_compare) => {
- super::sampler::serialize_compare_function(&depth_compare)
- }
- None => wgpu_types::CompareFunction::Always,
- },
- stencil: wgpu_types::StencilState {
- front: depth_stencil
- .stencil_front
- .map_or(Default::default(), serialize_stencil_face_state),
- back: depth_stencil
- .stencil_back
- .map_or(Default::default(), serialize_stencil_face_state),
- read_mask: depth_stencil.stencil_read_mask.unwrap_or(0xFFFFFFFF),
- write_mask: depth_stencil.stencil_write_mask.unwrap_or(0xFFFFFFFF),
- },
- bias: wgpu_types::DepthBiasState {
- constant: depth_stencil.depth_bias.unwrap_or(0),
- slope_scale: depth_stencil.depth_bias_slope_scale.unwrap_or(0.0),
- clamp: depth_stencil.depth_bias_clamp.unwrap_or(0.0),
- },
- }
- }),
- multisample: args.multisample.map_or(Default::default(), |multisample| {
- wgpu_types::MultisampleState {
- count: multisample.count.unwrap_or(1),
- mask: multisample.mask.unwrap_or(0xFFFFFFFF),
- alpha_to_coverage_enabled: multisample
- .alpha_to_coverage_enabled
- .unwrap_or(false),
- }
- }),
- fragment: args.fragment.map(|fragment| {
- let fragment_shader_module_resource = state
- .resource_table
- .get::<super::shader::WebGpuShaderModule>(fragment.module)
- .unwrap();
-
- wgpu_core::pipeline::FragmentState {
- stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
- module: fragment_shader_module_resource.0,
- entry_point: Cow::from(fragment.entry_point),
- },
- targets: Cow::from(
- fragment
- .targets
- .into_iter()
- .map(|target| wgpu_types::ColorTargetState {
- format: super::texture::serialize_texture_format(&target.format)
- .unwrap(),
- blend: target.blend.map(serialize_blend_state),
- write_mask: target
- .write_mask
- .map_or(Default::default(), |mask| {
- wgpu_types::ColorWrites::from_bits(mask).unwrap()
- }),
- })
- .collect::<Vec<wgpu_types::ColorTargetState>>(),
- ),
- }
- }),
+ primitive: args.primitive.into(),
+ depth_stencil: args.depth_stencil.map(TryInto::try_into).transpose()?,
+ multisample: args.multisample.into(),
+ fragment,
};
let implicit_pipelines = match args.layout {
diff --git a/ext/webgpu/queue.rs b/ext/webgpu/queue.rs
index da1f7a1ad..ddb653fca 100644
--- a/ext/webgpu/queue.rs
+++ b/ext/webgpu/queue.rs
@@ -17,7 +17,7 @@ type WebGpuQueue = super::WebGpuDevice;
#[serde(rename_all = "camelCase")]
pub struct QueueSubmitArgs {
queue_rid: ResourceId,
- command_buffers: Vec<u32>,
+ command_buffers: Vec<ResourceId>,
}
pub fn op_webgpu_queue_submit(
@@ -49,16 +49,26 @@ pub fn op_webgpu_queue_submit(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuImageDataLayout {
- offset: Option<u64>,
+ offset: u64,
bytes_per_row: Option<u32>,
rows_per_image: Option<u32>,
}
+impl From<GpuImageDataLayout> for wgpu_types::ImageDataLayout {
+ fn from(layout: GpuImageDataLayout) -> Self {
+ wgpu_types::ImageDataLayout {
+ offset: layout.offset,
+ bytes_per_row: NonZeroU32::new(layout.bytes_per_row.unwrap_or(0)),
+ rows_per_image: NonZeroU32::new(layout.rows_per_image.unwrap_or(0)),
+ }
+ }
+}
+
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QueueWriteBufferArgs {
queue_rid: ResourceId,
- buffer: u32,
+ buffer: ResourceId,
buffer_offset: u64,
data_offset: usize,
size: Option<usize>,
@@ -119,39 +129,17 @@ pub fn op_webgpu_write_texture(
let destination = wgpu_core::command::ImageCopyTexture {
texture: texture_resource.0,
- mip_level: args.destination.mip_level.unwrap_or(0),
- origin: args
- .destination
- .origin
- .map_or(Default::default(), |origin| wgpu_types::Origin3d {
- x: origin.x.unwrap_or(0),
- y: origin.y.unwrap_or(0),
- z: origin.z.unwrap_or(0),
- }),
- aspect: match args.destination.aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
- };
- let data_layout = wgpu_types::ImageDataLayout {
- offset: args.data_layout.offset.unwrap_or(0),
- bytes_per_row: NonZeroU32::new(args.data_layout.bytes_per_row.unwrap_or(0)),
- rows_per_image: NonZeroU32::new(
- args.data_layout.rows_per_image.unwrap_or(0),
- ),
+ mip_level: args.destination.mip_level,
+ origin: args.destination.origin.into(),
+ aspect: args.destination.aspect.into(),
};
+ let data_layout = args.data_layout.into();
gfx_ok!(queue => instance.queue_write_texture(
queue,
&destination,
&*zero_copy,
&data_layout,
- &wgpu_types::Extent3d {
- width: args.size.width.unwrap_or(1),
- height: args.size.height.unwrap_or(1),
- depth_or_array_layers: args.size.depth_or_array_layers.unwrap_or(1),
- }
+ &args.size.into()
))
}
diff --git a/ext/webgpu/render_pass.rs b/ext/webgpu/render_pass.rs
index e01a6d478..125579b52 100644
--- a/ext/webgpu/render_pass.rs
+++ b/ext/webgpu/render_pass.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::null_opbuf;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::ResourceId;
@@ -10,6 +9,8 @@ use serde::Deserialize;
use std::borrow::Cow;
use std::cell::RefCell;
+use crate::pipeline::GpuIndexFormat;
+
use super::error::WebGpuResult;
pub(crate) struct WebGpuRenderPass(
@@ -253,11 +254,13 @@ pub fn op_webgpu_render_pass_execute_bundles(
.resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?;
+ // SAFETY: the raw pointer and length are of the same slice, and that slice
+ // lives longer than the below function invocation.
unsafe {
wgpu_core::command::render_ffi::wgpu_render_pass_execute_bundles(
&mut render_pass_resource.0.borrow_mut(),
render_bundle_ids.as_ptr(),
- args.bundles.len(),
+ render_bundle_ids.len(),
);
}
@@ -297,7 +300,7 @@ pub struct RenderPassSetBindGroupArgs {
render_pass_rid: ResourceId,
index: u32,
bind_group: u32,
- dynamic_offsets_data: Option<Vec<u32>>,
+ dynamic_offsets_data: ZeroCopyBuf,
dynamic_offsets_data_start: usize,
dynamic_offsets_data_length: usize,
}
@@ -305,7 +308,7 @@ pub struct RenderPassSetBindGroupArgs {
pub fn op_webgpu_render_pass_set_bind_group(
state: &mut OpState,
args: RenderPassSetBindGroupArgs,
- zero_copy: Option<ZeroCopyBuf>,
+ _: (),
) -> Result<WebGpuResult, AnyError> {
let bind_group_resource =
state
@@ -315,37 +318,35 @@ pub fn op_webgpu_render_pass_set_bind_group(
.resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?;
- // I know this might look like it can be easily deduplicated, but it can not
- // be due to the lifetime of the args.dynamic_offsets_data slice. Because we
- // need to use a raw pointer here the slice can be freed before the pointer
- // is used in wgpu_render_pass_set_bind_group. See
- // https://matrix.to/#/!XFRnMvAfptAHthwBCx:matrix.org/$HgrlhD-Me1DwsGb8UdMu2Hqubgks8s7ILwWRwigOUAg
- match args.dynamic_offsets_data {
- Some(data) => unsafe {
- wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group(
- &mut render_pass_resource.0.borrow_mut(),
- args.index,
- bind_group_resource.0,
- data.as_slice().as_ptr(),
- args.dynamic_offsets_data_length,
- );
- },
- None => {
- let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
- let (prefix, data, suffix) = unsafe { zero_copy.align_to::<u32>() };
- assert!(prefix.is_empty());
- assert!(suffix.is_empty());
- unsafe {
- wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group(
- &mut render_pass_resource.0.borrow_mut(),
- args.index,
- bind_group_resource.0,
- data[args.dynamic_offsets_data_start..].as_ptr(),
- args.dynamic_offsets_data_length,
- );
- }
- }
- };
+ // Align the data
+ assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0);
+ // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a
+ // multiple of 4.
+ let (prefix, dynamic_offsets_data, suffix) =
+ unsafe { args.dynamic_offsets_data.align_to::<u32>() };
+ assert!(prefix.is_empty());
+ assert!(suffix.is_empty());
+
+ let start = args.dynamic_offsets_data_start;
+ let len = args.dynamic_offsets_data_length;
+
+ // Assert that length and start are both in bounds
+ assert!(start <= dynamic_offsets_data.len());
+ assert!(len <= dynamic_offsets_data.len() - start);
+
+ let dynamic_offsets_data: &[u32] = &dynamic_offsets_data[start..start + len];
+
+ // SAFETY: the raw pointer and length are of the same slice, and that slice
+ // lives longer than the below function invocation.
+ unsafe {
+ wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group(
+ &mut render_pass_resource.0.borrow_mut(),
+ args.index,
+ bind_group_resource.0,
+ dynamic_offsets_data.as_ptr(),
+ dynamic_offsets_data.len(),
+ );
+ }
Ok(WebGpuResult::empty())
}
@@ -366,8 +367,10 @@ pub fn op_webgpu_render_pass_push_debug_group(
.resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?;
+ let label = std::ffi::CString::new(args.group_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.group_label).unwrap();
wgpu_core::command::render_ffi::wgpu_render_pass_push_debug_group(
&mut render_pass_resource.0.borrow_mut(),
label.as_ptr(),
@@ -416,8 +419,10 @@ pub fn op_webgpu_render_pass_insert_debug_marker(
.resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?;
+ let label = std::ffi::CString::new(args.marker_label).unwrap();
+ // SAFETY: the string the raw pointer points to lives longer than the below
+ // function invocation.
unsafe {
- let label = std::ffi::CString::new(args.marker_label).unwrap();
wgpu_core::command::render_ffi::wgpu_render_pass_insert_debug_marker(
&mut render_pass_resource.0.borrow_mut(),
label.as_ptr(),
@@ -461,7 +466,7 @@ pub fn op_webgpu_render_pass_set_pipeline(
pub struct RenderPassSetIndexBufferArgs {
render_pass_rid: ResourceId,
buffer: u32,
- index_format: String,
+ index_format: GpuIndexFormat,
offset: u64,
size: Option<u64>,
}
@@ -489,7 +494,7 @@ pub fn op_webgpu_render_pass_set_index_buffer(
render_pass_resource.0.borrow_mut().set_index_buffer(
buffer_resource.0,
- super::pipeline::serialize_index_format(args.index_format),
+ args.index_format.into(),
args.offset,
size,
);
diff --git a/ext/webgpu/sampler.rs b/ext/webgpu/sampler.rs
index 63c475d37..95fb167ac 100644
--- a/ext/webgpu/sampler.rs
+++ b/ext/webgpu/sampler.rs
@@ -15,46 +15,67 @@ impl Resource for WebGpuSampler {
}
}
-fn serialize_address_mode(
- address_mode: Option<String>,
-) -> wgpu_types::AddressMode {
- match address_mode {
- Some(address_mode) => match address_mode.as_str() {
- "clamp-to-edge" => wgpu_types::AddressMode::ClampToEdge,
- "repeat" => wgpu_types::AddressMode::Repeat,
- "mirror-repeat" => wgpu_types::AddressMode::MirrorRepeat,
- _ => unreachable!(),
- },
- None => wgpu_types::AddressMode::ClampToEdge,
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuAddressMode {
+ ClampToEdge,
+ Repeat,
+ MirrorRepeat,
+}
+
+impl From<GpuAddressMode> for wgpu_types::AddressMode {
+ fn from(value: GpuAddressMode) -> wgpu_types::AddressMode {
+ match value {
+ GpuAddressMode::ClampToEdge => wgpu_types::AddressMode::ClampToEdge,
+ GpuAddressMode::Repeat => wgpu_types::AddressMode::Repeat,
+ GpuAddressMode::MirrorRepeat => wgpu_types::AddressMode::MirrorRepeat,
+ }
}
}
-fn serialize_filter_mode(
- filter_mode: Option<String>,
-) -> wgpu_types::FilterMode {
- match filter_mode {
- Some(filter_mode) => match filter_mode.as_str() {
- "nearest" => wgpu_types::FilterMode::Nearest,
- "linear" => wgpu_types::FilterMode::Linear,
- _ => unreachable!(),
- },
- None => wgpu_types::FilterMode::Nearest,
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+enum GpuFilterMode {
+ Nearest,
+ Linear,
+}
+
+impl From<GpuFilterMode> for wgpu_types::FilterMode {
+ fn from(value: GpuFilterMode) -> wgpu_types::FilterMode {
+ match value {
+ GpuFilterMode::Nearest => wgpu_types::FilterMode::Nearest,
+ GpuFilterMode::Linear => wgpu_types::FilterMode::Linear,
+ }
}
}
-pub fn serialize_compare_function(
- compare: &str,
-) -> wgpu_types::CompareFunction {
- match compare {
- "never" => wgpu_types::CompareFunction::Never,
- "less" => wgpu_types::CompareFunction::Less,
- "equal" => wgpu_types::CompareFunction::Equal,
- "less-equal" => wgpu_types::CompareFunction::LessEqual,
- "greater" => wgpu_types::CompareFunction::Greater,
- "not-equal" => wgpu_types::CompareFunction::NotEqual,
- "greater-equal" => wgpu_types::CompareFunction::GreaterEqual,
- "always" => wgpu_types::CompareFunction::Always,
- _ => unreachable!(),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuCompareFunction {
+ Never,
+ Less,
+ Equal,
+ LessEqual,
+ Greater,
+ NotEqual,
+ GreaterEqual,
+ Always,
+}
+
+impl From<GpuCompareFunction> for wgpu_types::CompareFunction {
+ fn from(value: GpuCompareFunction) -> wgpu_types::CompareFunction {
+ match value {
+ GpuCompareFunction::Never => wgpu_types::CompareFunction::Never,
+ GpuCompareFunction::Less => wgpu_types::CompareFunction::Less,
+ GpuCompareFunction::Equal => wgpu_types::CompareFunction::Equal,
+ GpuCompareFunction::LessEqual => wgpu_types::CompareFunction::LessEqual,
+ GpuCompareFunction::Greater => wgpu_types::CompareFunction::Greater,
+ GpuCompareFunction::NotEqual => wgpu_types::CompareFunction::NotEqual,
+ GpuCompareFunction::GreaterEqual => {
+ wgpu_types::CompareFunction::GreaterEqual
+ }
+ GpuCompareFunction::Always => wgpu_types::CompareFunction::Always,
+ }
}
}
@@ -63,16 +84,16 @@ pub fn serialize_compare_function(
pub struct CreateSamplerArgs {
device_rid: ResourceId,
label: Option<String>,
- address_mode_u: Option<String>,
- address_mode_v: Option<String>,
- address_mode_w: Option<String>,
- mag_filter: Option<String>,
- min_filter: Option<String>,
- mipmap_filter: Option<String>,
- lod_min_clamp: Option<f32>,
- lod_max_clamp: Option<f32>,
- compare: Option<String>,
- max_anisotropy: Option<u8>,
+ address_mode_u: GpuAddressMode,
+ address_mode_v: GpuAddressMode,
+ address_mode_w: GpuAddressMode,
+ mag_filter: GpuFilterMode,
+ min_filter: GpuFilterMode,
+ mipmap_filter: GpuFilterMode,
+ lod_min_clamp: f32,
+ lod_max_clamp: f32,
+ compare: Option<GpuCompareFunction>,
+ max_anisotropy: u8,
}
pub fn op_webgpu_create_sampler(
@@ -89,22 +110,17 @@ pub fn op_webgpu_create_sampler(
let descriptor = wgpu_core::resource::SamplerDescriptor {
label: args.label.map(Cow::from),
address_modes: [
- serialize_address_mode(args.address_mode_u),
- serialize_address_mode(args.address_mode_v),
- serialize_address_mode(args.address_mode_w),
+ args.address_mode_u.into(),
+ args.address_mode_v.into(),
+ args.address_mode_w.into(),
],
- mag_filter: serialize_filter_mode(args.mag_filter),
- min_filter: serialize_filter_mode(args.min_filter),
- mipmap_filter: serialize_filter_mode(args.mipmap_filter),
- lod_min_clamp: args.lod_min_clamp.unwrap_or(0.0),
- lod_max_clamp: args.lod_max_clamp.unwrap_or(32.0),
- compare: args
- .compare
- .as_ref()
- .map(|compare| serialize_compare_function(compare)),
- anisotropy_clamp: std::num::NonZeroU8::new(
- args.max_anisotropy.unwrap_or(0),
- ),
+ mag_filter: args.mag_filter.into(),
+ min_filter: args.min_filter.into(),
+ mipmap_filter: args.mipmap_filter.into(),
+ lod_min_clamp: args.lod_min_clamp,
+ lod_max_clamp: args.lod_max_clamp,
+ compare: args.compare.map(Into::into),
+ anisotropy_clamp: std::num::NonZeroU8::new(args.max_anisotropy),
border_color: None, // native-only
};
diff --git a/ext/webgpu/texture.rs b/ext/webgpu/texture.rs
index a0ea7a1bd..47e7a14d2 100644
--- a/ext/webgpu/texture.rs
+++ b/ext/webgpu/texture.rs
@@ -6,6 +6,8 @@ use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
+use std::convert::TryFrom;
+use std::convert::TryInto;
use super::error::WebGpuResult;
pub(crate) struct WebGpuTexture(pub(crate) wgpu_core::id::TextureId);
@@ -22,110 +24,310 @@ impl Resource for WebGpuTextureView {
}
}
-pub fn serialize_texture_format(
- format: &str,
-) -> Result<wgpu_types::TextureFormat, AnyError> {
- Ok(match format {
- // 8-bit formats
- "r8unorm" => wgpu_types::TextureFormat::R8Unorm,
- "r8snorm" => wgpu_types::TextureFormat::R8Snorm,
- "r8uint" => wgpu_types::TextureFormat::R8Uint,
- "r8sint" => wgpu_types::TextureFormat::R8Sint,
-
- // 16-bit formats
- "r16uint" => wgpu_types::TextureFormat::R16Uint,
- "r16sint" => wgpu_types::TextureFormat::R16Sint,
- "r16float" => wgpu_types::TextureFormat::R16Float,
- "rg8unorm" => wgpu_types::TextureFormat::Rg8Unorm,
- "rg8snorm" => wgpu_types::TextureFormat::Rg8Snorm,
- "rg8uint" => wgpu_types::TextureFormat::Rg8Uint,
- "rg8sint" => wgpu_types::TextureFormat::Rg8Sint,
-
- // 32-bit formats
- "r32uint" => wgpu_types::TextureFormat::R32Uint,
- "r32sint" => wgpu_types::TextureFormat::R32Sint,
- "r32float" => wgpu_types::TextureFormat::R32Float,
- "rg16uint" => wgpu_types::TextureFormat::Rg16Uint,
- "rg16sint" => wgpu_types::TextureFormat::Rg16Sint,
- "rg16float" => wgpu_types::TextureFormat::Rg16Float,
- "rgba8unorm" => wgpu_types::TextureFormat::Rgba8Unorm,
- "rgba8unorm-srgb" => wgpu_types::TextureFormat::Rgba8UnormSrgb,
- "rgba8snorm" => wgpu_types::TextureFormat::Rgba8Snorm,
- "rgba8uint" => wgpu_types::TextureFormat::Rgba8Uint,
- "rgba8sint" => wgpu_types::TextureFormat::Rgba8Sint,
- "bgra8unorm" => wgpu_types::TextureFormat::Bgra8Unorm,
- "bgra8unorm-srgb" => wgpu_types::TextureFormat::Bgra8UnormSrgb,
- // Packed 32-bit formats
- "rgb9e5ufloat" => return Err(not_supported()), // wgpu#967
- "rgb10a2unorm" => wgpu_types::TextureFormat::Rgb10a2Unorm,
- "rg11b10ufloat" => wgpu_types::TextureFormat::Rg11b10Float,
-
- // 64-bit formats
- "rg32uint" => wgpu_types::TextureFormat::Rg32Uint,
- "rg32sint" => wgpu_types::TextureFormat::Rg32Sint,
- "rg32float" => wgpu_types::TextureFormat::Rg32Float,
- "rgba16uint" => wgpu_types::TextureFormat::Rgba16Uint,
- "rgba16sint" => wgpu_types::TextureFormat::Rgba16Sint,
- "rgba16float" => wgpu_types::TextureFormat::Rgba16Float,
-
- // 128-bit formats
- "rgba32uint" => wgpu_types::TextureFormat::Rgba32Uint,
- "rgba32sint" => wgpu_types::TextureFormat::Rgba32Sint,
- "rgba32float" => wgpu_types::TextureFormat::Rgba32Float,
-
- // Depth and stencil formats
- "stencil8" => return Err(not_supported()), // wgpu#967
- "depth16unorm" => return Err(not_supported()), // wgpu#967
- "depth24plus" => wgpu_types::TextureFormat::Depth24Plus,
- "depth24plus-stencil8" => wgpu_types::TextureFormat::Depth24PlusStencil8,
- "depth32float" => wgpu_types::TextureFormat::Depth32Float,
-
- // BC compressed formats usable if "texture-compression-bc" is both
- // supported by the device/user agent and enabled in requestDevice.
- "bc1-rgba-unorm" => wgpu_types::TextureFormat::Bc1RgbaUnorm,
- "bc1-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc1RgbaUnormSrgb,
- "bc2-rgba-unorm" => wgpu_types::TextureFormat::Bc2RgbaUnorm,
- "bc2-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc2RgbaUnormSrgb,
- "bc3-rgba-unorm" => wgpu_types::TextureFormat::Bc3RgbaUnorm,
- "bc3-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc3RgbaUnormSrgb,
- "bc4-r-unorm" => wgpu_types::TextureFormat::Bc4RUnorm,
- "bc4-r-snorm" => wgpu_types::TextureFormat::Bc4RSnorm,
- "bc5-rg-unorm" => wgpu_types::TextureFormat::Bc5RgUnorm,
- "bc5-rg-snorm" => wgpu_types::TextureFormat::Bc5RgSnorm,
- "bc6h-rgb-ufloat" => wgpu_types::TextureFormat::Bc6hRgbUfloat,
- "bc6h-rgb-float" => wgpu_types::TextureFormat::Bc6hRgbSfloat, // wgpu#967
- "bc7-rgba-unorm" => wgpu_types::TextureFormat::Bc7RgbaUnorm,
- "bc7-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc7RgbaUnormSrgb,
-
- // "depth24unorm-stencil8" extension
- "depth24unorm-stencil8" => return Err(not_supported()), // wgpu#967
-
- // "depth32float-stencil8" extension
- "depth32float-stencil8" => return Err(not_supported()), // wgpu#967
- _ => unreachable!(),
- })
-}
-
-pub fn serialize_dimension(
- dimension: &str,
-) -> wgpu_types::TextureViewDimension {
- match dimension {
- "1d" => wgpu_types::TextureViewDimension::D1,
- "2d" => wgpu_types::TextureViewDimension::D2,
- "2d-array" => wgpu_types::TextureViewDimension::D2Array,
- "cube" => wgpu_types::TextureViewDimension::Cube,
- "cube-array" => wgpu_types::TextureViewDimension::CubeArray,
- "3d" => wgpu_types::TextureViewDimension::D3,
- _ => unreachable!(),
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuTextureFormat {
+ // 8-bit formats
+ #[serde(rename = "r8unorm")]
+ R8Unorm,
+ #[serde(rename = "r8snorm")]
+ R8Snorm,
+ #[serde(rename = "r8uint")]
+ R8Uint,
+ #[serde(rename = "r8sint")]
+ R8Sint,
+
+ // 16-bit formats
+ #[serde(rename = "r16uint")]
+ R16Uint,
+ #[serde(rename = "r16sint")]
+ R16Sint,
+ #[serde(rename = "r16float")]
+ R16Float,
+ #[serde(rename = "rg8unorm")]
+ Rg8Unorm,
+ #[serde(rename = "rg8snorm")]
+ Rg8Snorm,
+ #[serde(rename = "rg8uint")]
+ Rg8Uint,
+ #[serde(rename = "rg8sint")]
+ Rg8Sint,
+
+ // 32-bit formats
+ #[serde(rename = "r32uint")]
+ R32Uint,
+ #[serde(rename = "r32sint")]
+ R32Sint,
+ #[serde(rename = "r32float")]
+ R32Float,
+ #[serde(rename = "rg16uint")]
+ Rg16Uint,
+ #[serde(rename = "rg16sint")]
+ Rg16Sint,
+ #[serde(rename = "rg16float")]
+ Rg16Float,
+ #[serde(rename = "rgba8unorm")]
+ Rgba8Unorm,
+ #[serde(rename = "rgba8unorm-srgb")]
+ Rgba8UnormSrgb,
+ #[serde(rename = "rgba8snorm")]
+ Rgba8Snorm,
+ #[serde(rename = "rgba8uint")]
+ Rgba8Uint,
+ #[serde(rename = "rgba8sint")]
+ Rgba8Sint,
+ #[serde(rename = "bgra8unorm")]
+ Bgra8Unorm,
+ #[serde(rename = "bgra8unorm-srgb")]
+ Bgra8UnormSrgb,
+ // Packed 32-bit formats
+ #[serde(rename = "rgb9e5ufloat")]
+ RgB9E5UFloat,
+ #[serde(rename = "rgb10a2unorm")]
+ Rgb10a2Unorm,
+ #[serde(rename = "rg11b10ufloat")]
+ Rg11b10Float,
+
+ // 64-bit formats
+ #[serde(rename = "rg32uint")]
+ Rg32Uint,
+ #[serde(rename = "rg32sint")]
+ Rg32Sint,
+ #[serde(rename = "rg32float")]
+ Rg32Float,
+ #[serde(rename = "rgba16uint")]
+ Rgba16Uint,
+ #[serde(rename = "rgba16sint")]
+ Rgba16Sint,
+ #[serde(rename = "rgba16float")]
+ Rgba16Float,
+
+ // 128-bit formats
+ #[serde(rename = "rgba32uint")]
+ Rgba32Uint,
+ #[serde(rename = "rgba32sint")]
+ Rgba32Sint,
+ #[serde(rename = "rgba32float")]
+ Rgba32Float,
+
+ // Depth and stencil formats
+ #[serde(rename = "stencil8")]
+ Stencil8,
+ #[serde(rename = "depth16unorm")]
+ Depth16Unorm,
+ #[serde(rename = "depth24plus")]
+ Depth24Plus,
+ #[serde(rename = "depth24plus-stencil8")]
+ Depth24PlusStencil8,
+ #[serde(rename = "depth32float")]
+ Depth32Float,
+
+ // BC compressed formats usable if "texture-compression-bc" is both
+ // supported by the device/user agent and enabled in requestDevice.
+ #[serde(rename = "bc1-rgba-unorm")]
+ Bc1RgbaUnorm,
+ #[serde(rename = "bc1-rgba-unorm-srgb")]
+ Bc1RgbaUnormSrgb,
+ #[serde(rename = "bc2-rgba-unorm")]
+ Bc2RgbaUnorm,
+ #[serde(rename = "bc2-rgba-unorm-srgb")]
+ Bc2RgbaUnormSrgb,
+ #[serde(rename = "bc3-rgba-unorm")]
+ Bc3RgbaUnorm,
+ #[serde(rename = "bc3-rgba-unorm-srgb")]
+ Bc3RgbaUnormSrgb,
+ #[serde(rename = "bc4-r-unorm")]
+ Bc4RUnorm,
+ #[serde(rename = "bc4-r-snorm")]
+ Bc4RSnorm,
+ #[serde(rename = "bc5-rg-unorm")]
+ Bc5RgUnorm,
+ #[serde(rename = "bc5-rg-snorm")]
+ Bc5RgSnorm,
+ #[serde(rename = "bc6h-rgb-ufloat")]
+ Bc6hRgbUfloat,
+ #[serde(rename = "bc6h-rgb-float")]
+ Bc6HRgbFloat,
+ #[serde(rename = "bc7-rgba-unorm")]
+ Bc7RgbaUnorm,
+ #[serde(rename = "bc7-rgba-unorm-srgb")]
+ Bc7RgbaUnormSrgb,
+
+ // "depth24unorm-stencil8" feature
+ #[serde(rename = "depth24unorm-stencil8")]
+ Depth24UnormStencil8,
+
+ // "depth32float-stencil8" feature
+ #[serde(rename = "depth32float-stencil8")]
+ Depth32FloatStencil8,
+}
+
+impl TryFrom<GpuTextureFormat> for wgpu_types::TextureFormat {
+ type Error = AnyError;
+
+ fn try_from(value: GpuTextureFormat) -> Result<Self, Self::Error> {
+ use wgpu_types::TextureFormat;
+ match value {
+ GpuTextureFormat::R8Unorm => Ok(TextureFormat::R8Unorm),
+ GpuTextureFormat::R8Snorm => Ok(TextureFormat::R8Snorm),
+ GpuTextureFormat::R8Uint => Ok(TextureFormat::R8Uint),
+ GpuTextureFormat::R8Sint => Ok(TextureFormat::R8Sint),
+
+ GpuTextureFormat::R16Uint => Ok(TextureFormat::R16Uint),
+ GpuTextureFormat::R16Sint => Ok(TextureFormat::R16Sint),
+ GpuTextureFormat::R16Float => Ok(TextureFormat::R16Float),
+ GpuTextureFormat::Rg8Unorm => Ok(TextureFormat::Rg8Unorm),
+ GpuTextureFormat::Rg8Snorm => Ok(TextureFormat::Rg8Snorm),
+ GpuTextureFormat::Rg8Uint => Ok(TextureFormat::Rg8Uint),
+ GpuTextureFormat::Rg8Sint => Ok(TextureFormat::Rg8Sint),
+
+ GpuTextureFormat::R32Uint => Ok(TextureFormat::R32Uint),
+ GpuTextureFormat::R32Sint => Ok(TextureFormat::R32Sint),
+ GpuTextureFormat::R32Float => Ok(TextureFormat::R32Float),
+ GpuTextureFormat::Rg16Uint => Ok(TextureFormat::Rg16Uint),
+ GpuTextureFormat::Rg16Sint => Ok(TextureFormat::Rg16Sint),
+ GpuTextureFormat::Rg16Float => Ok(TextureFormat::Rg16Float),
+ GpuTextureFormat::Rgba8Unorm => Ok(TextureFormat::Rgba8Unorm),
+ GpuTextureFormat::Rgba8UnormSrgb => Ok(TextureFormat::Rgba8UnormSrgb),
+ GpuTextureFormat::Rgba8Snorm => Ok(TextureFormat::Rgba8Snorm),
+ GpuTextureFormat::Rgba8Uint => Ok(TextureFormat::Rgba8Uint),
+ GpuTextureFormat::Rgba8Sint => Ok(TextureFormat::Rgba8Sint),
+ GpuTextureFormat::Bgra8Unorm => Ok(TextureFormat::Bgra8Unorm),
+ GpuTextureFormat::Bgra8UnormSrgb => Ok(TextureFormat::Bgra8UnormSrgb),
+ GpuTextureFormat::RgB9E5UFloat => Err(not_supported()), // wgpu#967
+ GpuTextureFormat::Rgb10a2Unorm => Ok(TextureFormat::Rgb10a2Unorm),
+ GpuTextureFormat::Rg11b10Float => Ok(TextureFormat::Rg11b10Float),
+
+ GpuTextureFormat::Rg32Uint => Ok(TextureFormat::Rg32Uint),
+ GpuTextureFormat::Rg32Sint => Ok(TextureFormat::Rg32Sint),
+ GpuTextureFormat::Rg32Float => Ok(TextureFormat::Rg32Float),
+ GpuTextureFormat::Rgba16Uint => Ok(TextureFormat::Rgba16Uint),
+ GpuTextureFormat::Rgba16Sint => Ok(TextureFormat::Rgba16Sint),
+ GpuTextureFormat::Rgba16Float => Ok(TextureFormat::Rgba16Float),
+
+ GpuTextureFormat::Rgba32Uint => Ok(TextureFormat::Rgba32Uint),
+ GpuTextureFormat::Rgba32Sint => Ok(TextureFormat::Rgba32Sint),
+ GpuTextureFormat::Rgba32Float => Ok(TextureFormat::Rgba32Float),
+
+ GpuTextureFormat::Stencil8 => Err(not_supported()), // wgpu#967
+ GpuTextureFormat::Depth16Unorm => Err(not_supported()), // wgpu#967
+ GpuTextureFormat::Depth24Plus => Ok(TextureFormat::Depth24Plus),
+ GpuTextureFormat::Depth24PlusStencil8 => {
+ Ok(TextureFormat::Depth24PlusStencil8)
+ }
+ GpuTextureFormat::Depth32Float => Ok(TextureFormat::Depth32Float),
+
+ GpuTextureFormat::Bc1RgbaUnorm => Ok(TextureFormat::Bc1RgbaUnorm),
+ GpuTextureFormat::Bc1RgbaUnormSrgb => Ok(TextureFormat::Bc1RgbaUnormSrgb),
+ GpuTextureFormat::Bc2RgbaUnorm => Ok(TextureFormat::Bc2RgbaUnorm),
+ GpuTextureFormat::Bc2RgbaUnormSrgb => Ok(TextureFormat::Bc2RgbaUnormSrgb),
+ GpuTextureFormat::Bc3RgbaUnorm => Ok(TextureFormat::Bc3RgbaUnorm),
+ GpuTextureFormat::Bc3RgbaUnormSrgb => Ok(TextureFormat::Bc3RgbaUnormSrgb),
+ GpuTextureFormat::Bc4RUnorm => Ok(TextureFormat::Bc4RUnorm),
+ GpuTextureFormat::Bc4RSnorm => Ok(TextureFormat::Bc4RSnorm),
+ GpuTextureFormat::Bc5RgUnorm => Ok(TextureFormat::Bc5RgUnorm),
+ GpuTextureFormat::Bc5RgSnorm => Ok(TextureFormat::Bc5RgSnorm),
+ GpuTextureFormat::Bc6hRgbUfloat => Ok(TextureFormat::Bc6hRgbUfloat),
+ GpuTextureFormat::Bc6HRgbFloat => Ok(TextureFormat::Bc6hRgbSfloat), // wgpu#967
+ GpuTextureFormat::Bc7RgbaUnorm => Ok(TextureFormat::Bc7RgbaUnorm),
+ GpuTextureFormat::Bc7RgbaUnormSrgb => Ok(TextureFormat::Bc7RgbaUnormSrgb),
+
+ GpuTextureFormat::Depth24UnormStencil8 => Err(not_supported()), // wgpu#967,
+
+ GpuTextureFormat::Depth32FloatStencil8 => Err(not_supported()), // wgpu#967
+ }
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuTextureViewDimension {
+ #[serde(rename = "1d")]
+ D1,
+ #[serde(rename = "2d")]
+ D2,
+ #[serde(rename = "2d-array")]
+ D2Array,
+ #[serde(rename = "cube")]
+ Cube,
+ #[serde(rename = "cube-array")]
+ CubeArray,
+ #[serde(rename = "3d")]
+ D3,
+}
+
+impl From<GpuTextureViewDimension> for wgpu_types::TextureViewDimension {
+ fn from(view_dimension: GpuTextureViewDimension) -> Self {
+ match view_dimension {
+ GpuTextureViewDimension::D1 => wgpu_types::TextureViewDimension::D1,
+ GpuTextureViewDimension::D2 => wgpu_types::TextureViewDimension::D2,
+ GpuTextureViewDimension::D2Array => {
+ wgpu_types::TextureViewDimension::D2Array
+ }
+ GpuTextureViewDimension::Cube => wgpu_types::TextureViewDimension::Cube,
+ GpuTextureViewDimension::CubeArray => {
+ wgpu_types::TextureViewDimension::CubeArray
+ }
+ GpuTextureViewDimension::D3 => wgpu_types::TextureViewDimension::D3,
+ }
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuTextureDimension {
+ #[serde(rename = "1d")]
+ D1,
+ #[serde(rename = "2d")]
+ D2,
+ #[serde(rename = "3d")]
+ D3,
+}
+
+impl From<GpuTextureDimension> for wgpu_types::TextureDimension {
+ fn from(texture_dimension: GpuTextureDimension) -> Self {
+ match texture_dimension {
+ GpuTextureDimension::D1 => wgpu_types::TextureDimension::D1,
+ GpuTextureDimension::D2 => wgpu_types::TextureDimension::D2,
+ GpuTextureDimension::D3 => wgpu_types::TextureDimension::D3,
+ }
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum GpuTextureAspect {
+ All,
+ StencilOnly,
+ DepthOnly,
+}
+
+impl From<GpuTextureAspect> for wgpu_types::TextureAspect {
+ fn from(aspect: GpuTextureAspect) -> wgpu_types::TextureAspect {
+ match aspect {
+ GpuTextureAspect::All => wgpu_types::TextureAspect::All,
+ GpuTextureAspect::StencilOnly => wgpu_types::TextureAspect::StencilOnly,
+ GpuTextureAspect::DepthOnly => wgpu_types::TextureAspect::DepthOnly,
+ }
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuExtent3D {
- pub width: Option<u32>,
- pub height: Option<u32>,
- pub depth_or_array_layers: Option<u32>,
+ pub width: u32,
+ pub height: u32,
+ pub depth_or_array_layers: u32,
+}
+
+impl From<GpuExtent3D> for wgpu_types::Extent3d {
+ fn from(extent: GpuExtent3D) -> Self {
+ wgpu_types::Extent3d {
+ width: extent.width,
+ height: extent.height,
+ depth_or_array_layers: extent.depth_or_array_layers,
+ }
+ }
}
#[derive(Deserialize)]
@@ -134,10 +336,10 @@ pub struct CreateTextureArgs {
device_rid: ResourceId,
label: Option<String>,
size: GpuExtent3D,
- mip_level_count: Option<u32>,
- sample_count: Option<u32>,
- dimension: Option<String>,
- format: String,
+ mip_level_count: u32,
+ sample_count: u32,
+ dimension: GpuTextureDimension,
+ format: GpuTextureFormat,
usage: u32,
}
@@ -154,24 +356,12 @@ pub fn op_webgpu_create_texture(
let descriptor = wgpu_core::resource::TextureDescriptor {
label: args.label.map(Cow::from),
- size: wgpu_types::Extent3d {
- width: args.size.width.unwrap_or(1),
- height: args.size.height.unwrap_or(1),
- depth_or_array_layers: args.size.depth_or_array_layers.unwrap_or(1),
- },
- mip_level_count: args.mip_level_count.unwrap_or(1),
- sample_count: args.sample_count.unwrap_or(1),
- dimension: match args.dimension {
- Some(dimension) => match dimension.as_str() {
- "1d" => wgpu_types::TextureDimension::D1,
- "2d" => wgpu_types::TextureDimension::D2,
- "3d" => wgpu_types::TextureDimension::D3,
- _ => unreachable!(),
- },
- None => wgpu_types::TextureDimension::D2,
- },
- format: serialize_texture_format(&args.format)?,
- usage: wgpu_types::TextureUsages::from_bits(args.usage).unwrap(),
+ size: args.size.into(),
+ mip_level_count: args.mip_level_count,
+ sample_count: args.sample_count,
+ dimension: args.dimension.into(),
+ format: args.format.try_into()?,
+ usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage),
};
gfx_put!(device => instance.device_create_texture(
@@ -186,12 +376,12 @@ pub fn op_webgpu_create_texture(
pub struct CreateTextureViewArgs {
texture_rid: ResourceId,
label: Option<String>,
- format: Option<String>,
- dimension: Option<String>,
- aspect: Option<String>,
- base_mip_level: Option<u32>,
+ format: Option<GpuTextureFormat>,
+ dimension: Option<GpuTextureViewDimension>,
+ aspect: GpuTextureAspect,
+ base_mip_level: u32,
mip_level_count: Option<u32>,
- base_array_layer: Option<u32>,
+ base_array_layer: u32,
array_layer_count: Option<u32>,
}
@@ -208,26 +398,15 @@ pub fn op_webgpu_create_texture_view(
let descriptor = wgpu_core::resource::TextureViewDescriptor {
label: args.label.map(Cow::from),
- format: args
- .format
- .map(|s| serialize_texture_format(&s))
- .transpose()?,
- dimension: args.dimension.map(|s| serialize_dimension(&s)),
+ format: args.format.map(|s| s.try_into()).transpose()?,
+ dimension: args.dimension.map(|s| s.into()),
range: wgpu_types::ImageSubresourceRange {
- aspect: match args.aspect {
- Some(aspect) => match aspect.as_str() {
- "all" => wgpu_types::TextureAspect::All,
- "stencil-only" => wgpu_types::TextureAspect::StencilOnly,
- "depth-only" => wgpu_types::TextureAspect::DepthOnly,
- _ => unreachable!(),
- },
- None => wgpu_types::TextureAspect::All,
- },
- base_mip_level: args.base_mip_level.unwrap_or(0),
+ aspect: args.aspect.into(),
+ base_mip_level: args.base_mip_level,
mip_level_count: std::num::NonZeroU32::new(
args.mip_level_count.unwrap_or(0),
),
- base_array_layer: args.base_array_layer.unwrap_or(0),
+ base_array_layer: args.base_array_layer,
array_layer_count: std::num::NonZeroU32::new(
args.array_layer_count.unwrap_or(0),
),
diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js
index 40250afe1..b75616354 100644
--- a/ext/webidl/00_webidl.js
+++ b/ext/webidl/00_webidl.js
@@ -701,11 +701,11 @@
imvType === "string" || imvType === "bigint" ||
imvType === "undefined"
) {
- defaultValues[member.key] = idlMemberValue;
+ defaultValues[member.key] = member.converter(idlMemberValue, {});
} else {
ObjectDefineProperty(defaultValues, member.key, {
get() {
- return member.defaultValue;
+ return member.converter(idlMemberValue, member.defaultValue);
},
enumerable: true,
});