mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
refactor(webgpu): use op interface idiomatically (#11835)
This commit is contained in:
parent
e10d30c8ea
commit
4853be20f2
14 changed files with 1425 additions and 1118 deletions
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
@ -217,10 +218,28 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
|
|||
return_features
|
||||
}
|
||||
|
||||
#[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,10 +427,116 @@ 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>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GpuRequiredFeatures(HashSet<String>);
|
||||
|
||||
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 required_features.0.contains("depth-clamping") {
|
||||
features.set(wgpu_types::Features::DEPTH_CLAMPING, true);
|
||||
}
|
||||
if required_features.0.contains("pipeline-statistics-query") {
|
||||
features.set(wgpu_types::Features::PIPELINE_STATISTICS_QUERY, true);
|
||||
}
|
||||
if required_features.0.contains("texture-compression-bc") {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_BC, true);
|
||||
}
|
||||
if required_features.0.contains("timestamp-query") {
|
||||
features.set(wgpu_types::Features::TIMESTAMP_QUERY, true);
|
||||
}
|
||||
|
||||
// extended from spec
|
||||
if required_features.0.contains("mappable-primary-buffers") {
|
||||
features.set(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS, true);
|
||||
}
|
||||
if required_features.0.contains("texture-binding-array") {
|
||||
features.set(wgpu_types::Features::TEXTURE_BINDING_ARRAY, true);
|
||||
}
|
||||
if required_features.0.contains("buffer-binding-array") {
|
||||
features.set(wgpu_types::Features::BUFFER_BINDING_ARRAY, true);
|
||||
}
|
||||
if required_features
|
||||
.0
|
||||
.contains("storage-resource-binding-array")
|
||||
{
|
||||
features.set(wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY, true);
|
||||
}
|
||||
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 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 required_features.0.contains("unsized-binding-array") {
|
||||
features.set(wgpu_types::Features::UNSIZED_BINDING_ARRAY, true);
|
||||
}
|
||||
if required_features.0.contains("multi-draw-indirect") {
|
||||
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT, true);
|
||||
}
|
||||
if required_features.0.contains("multi-draw-indirect-count") {
|
||||
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT, true);
|
||||
}
|
||||
if required_features.0.contains("push-constants") {
|
||||
features.set(wgpu_types::Features::PUSH_CONSTANTS, true);
|
||||
}
|
||||
if required_features.0.contains("address-mode-clamp-to-border") {
|
||||
features.set(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, true);
|
||||
}
|
||||
if required_features.0.contains("non-fill-polygon-mode") {
|
||||
features.set(wgpu_types::Features::NON_FILL_POLYGON_MODE, true);
|
||||
}
|
||||
if required_features.0.contains("texture-compression-etc2") {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2, true);
|
||||
}
|
||||
if required_features.0.contains("texture-compression-astc-ldr") {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR, true);
|
||||
}
|
||||
if required_features
|
||||
.0
|
||||
.contains("texture-adapter-specific-format-features")
|
||||
{
|
||||
features.set(
|
||||
wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
||||
true,
|
||||
);
|
||||
}
|
||||
if required_features.0.contains("shader-float64") {
|
||||
features.set(wgpu_types::Features::SHADER_FLOAT64, true);
|
||||
}
|
||||
if required_features.0.contains("vertex-attribute-64bit") {
|
||||
features.set(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, true);
|
||||
}
|
||||
if required_features.0.contains("conservative-rasterization") {
|
||||
features.set(wgpu_types::Features::CONSERVATIVE_RASTERIZATION, true);
|
||||
}
|
||||
if required_features.0.contains("vertex-writable-storage") {
|
||||
features.set(wgpu_types::Features::VERTEX_WRITABLE_STORAGE, true);
|
||||
}
|
||||
if required_features.0.contains("clear-commands") {
|
||||
features.set(wgpu_types::Features::CLEAR_COMMANDS, true);
|
||||
}
|
||||
if required_features.0.contains("spirv-shader-passthrough") {
|
||||
features.set(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH, true);
|
||||
}
|
||||
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,
|
||||
|
@ -428,108 +549,10 @@ pub async fn op_webgpu_request_device(
|
|||
let adapter = adapter_resource.0;
|
||||
let instance = state.borrow::<Instance>();
|
||||
|
||||
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()) {
|
||||
features.set(wgpu_types::Features::DEPTH_CLAMPING, true);
|
||||
}
|
||||
if passed_features.contains(&"pipeline-statistics-query".to_string()) {
|
||||
features.set(wgpu_types::Features::PIPELINE_STATISTICS_QUERY, true);
|
||||
}
|
||||
if passed_features.contains(&"texture-compression-bc".to_string()) {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_BC, true);
|
||||
}
|
||||
if passed_features.contains(&"timestamp-query".to_string()) {
|
||||
features.set(wgpu_types::Features::TIMESTAMP_QUERY, true);
|
||||
}
|
||||
|
||||
// extended from spec
|
||||
if passed_features.contains(&"mappable-primary-buffers".to_string()) {
|
||||
features.set(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS, true);
|
||||
}
|
||||
if passed_features.contains(&"texture-binding-array".to_string()) {
|
||||
features.set(wgpu_types::Features::TEXTURE_BINDING_ARRAY, true);
|
||||
}
|
||||
if passed_features.contains(&"buffer-binding-array".to_string()) {
|
||||
features.set(wgpu_types::Features::BUFFER_BINDING_ARRAY, true);
|
||||
}
|
||||
if passed_features.contains(&"storage-resource-binding-array".to_string()) {
|
||||
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(),
|
||||
) {
|
||||
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(),
|
||||
) {
|
||||
features.set(wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, true);
|
||||
}
|
||||
if passed_features.contains(&"unsized-binding-array".to_string()) {
|
||||
features.set(wgpu_types::Features::UNSIZED_BINDING_ARRAY, true);
|
||||
}
|
||||
if passed_features.contains(&"multi-draw-indirect".to_string()) {
|
||||
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT, true);
|
||||
}
|
||||
if passed_features.contains(&"multi-draw-indirect-count".to_string()) {
|
||||
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT, true);
|
||||
}
|
||||
if passed_features.contains(&"push-constants".to_string()) {
|
||||
features.set(wgpu_types::Features::PUSH_CONSTANTS, true);
|
||||
}
|
||||
if passed_features.contains(&"address-mode-clamp-to-border".to_string()) {
|
||||
features.set(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, true);
|
||||
}
|
||||
if passed_features.contains(&"non-fill-polygon-mode".to_string()) {
|
||||
features.set(wgpu_types::Features::NON_FILL_POLYGON_MODE, true);
|
||||
}
|
||||
if passed_features.contains(&"texture-compression-etc2".to_string()) {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2, true);
|
||||
}
|
||||
if passed_features.contains(&"texture-compression-astc-ldr".to_string()) {
|
||||
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR, true);
|
||||
}
|
||||
if passed_features
|
||||
.contains(&"texture-adapter-specific-format-features".to_string())
|
||||
{
|
||||
features.set(
|
||||
wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
||||
true,
|
||||
);
|
||||
}
|
||||
if passed_features.contains(&"shader-float64".to_string()) {
|
||||
features.set(wgpu_types::Features::SHADER_FLOAT64, true);
|
||||
}
|
||||
if passed_features.contains(&"vertex-attribute-64bit".to_string()) {
|
||||
features.set(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, true);
|
||||
}
|
||||
if passed_features.contains(&"conservative-rasterization".to_string()) {
|
||||
features.set(wgpu_types::Features::CONSERVATIVE_RASTERIZATION, true);
|
||||
}
|
||||
if passed_features.contains(&"vertex-writable-storage".to_string()) {
|
||||
features.set(wgpu_types::Features::VERTEX_WRITABLE_STORAGE, true);
|
||||
}
|
||||
if passed_features.contains(&"clear-commands".to_string()) {
|
||||
features.set(wgpu_types::Features::CLEAR_COMMANDS, true);
|
||||
}
|
||||
if passed_features.contains(&"spirv-shader-passthrough".to_string()) {
|
||||
features.set(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH, true);
|
||||
}
|
||||
if passed_features.contains(&"shader-primitive-index".to_string()) {
|
||||
features.set(wgpu_types::Features::SHADER_PRIMITIVE_INDEX, true);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
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)]
|
||||
#[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 {
|
||||
|
@ -407,28 +576,71 @@ 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 {
|
||||
|
|
|
@ -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()
|
||||
))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
#[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
|
||||
"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,
|
||||
// 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
|
||||
"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,
|
||||
// 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
|
||||
"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,
|
||||
// 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
|
||||
"rgba32uint" => wgpu_types::TextureFormat::Rgba32Uint,
|
||||
"rgba32sint" => wgpu_types::TextureFormat::Rgba32Sint,
|
||||
"rgba32float" => wgpu_types::TextureFormat::Rgba32Float,
|
||||
// 128-bit formats
|
||||
#[serde(rename = "rgba32uint")]
|
||||
Rgba32Uint,
|
||||
#[serde(rename = "rgba32sint")]
|
||||
Rgba32Sint,
|
||||
#[serde(rename = "rgba32float")]
|
||||
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,
|
||||
// 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.
|
||||
"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,
|
||||
// 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" extension
|
||||
"depth24unorm-stencil8" => return Err(not_supported()), // wgpu#967
|
||||
// "depth24unorm-stencil8" feature
|
||||
#[serde(rename = "depth24unorm-stencil8")]
|
||||
Depth24UnormStencil8,
|
||||
|
||||
// "depth32float-stencil8" extension
|
||||
"depth32float-stencil8" => return Err(not_supported()), // wgpu#967
|
||||
_ => unreachable!(),
|
||||
})
|
||||
// "depth32float-stencil8" feature
|
||||
#[serde(rename = "depth32float-stencil8")]
|
||||
Depth32FloatStencil8,
|
||||
}
|
||||
|
||||
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!(),
|
||||
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),
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue