0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-31 09:14:20 -04:00
denoland-deno/extensions/webgpu/texture.rs
2021-04-30 15:51:48 -04:00

249 lines
8.8 KiB
Rust

// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::error::{bad_resource_id, not_supported};
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use super::error::WebGpuResult;
pub(crate) struct WebGpuTexture(pub(crate) wgpu_core::id::TextureId);
impl Resource for WebGpuTexture {
fn name(&self) -> Cow<str> {
"webGPUTexture".into()
}
}
pub(crate) struct WebGpuTextureView(pub(crate) wgpu_core::id::TextureViewId);
impl Resource for WebGpuTextureView {
fn name(&self) -> Cow<str> {
"webGPUTextureView".into()
}
}
pub fn serialize_texture_format(
format: &str,
) -> Result<wgpu_types::TextureFormat, AnyError> {
Ok(match format {
// 8-bit formats
"r8unorm" => wgpu_types::TextureFormat::R8Unorm,
"r8snorm" => wgpu_types::TextureFormat::R8Snorm,
"r8uint" => wgpu_types::TextureFormat::R8Uint,
"r8sint" => wgpu_types::TextureFormat::R8Sint,
// 16-bit formats
"r16uint" => wgpu_types::TextureFormat::R16Uint,
"r16sint" => wgpu_types::TextureFormat::R16Sint,
"r16float" => wgpu_types::TextureFormat::R16Float,
"rg8unorm" => wgpu_types::TextureFormat::Rg8Unorm,
"rg8snorm" => wgpu_types::TextureFormat::Rg8Snorm,
"rg8uint" => wgpu_types::TextureFormat::Rg8Uint,
"rg8sint" => wgpu_types::TextureFormat::Rg8Sint,
// 32-bit formats
"r32uint" => wgpu_types::TextureFormat::R32Uint,
"r32sint" => wgpu_types::TextureFormat::R32Sint,
"r32float" => wgpu_types::TextureFormat::R32Float,
"rg16uint" => wgpu_types::TextureFormat::Rg16Uint,
"rg16sint" => wgpu_types::TextureFormat::Rg16Sint,
"rg16float" => wgpu_types::TextureFormat::Rg16Float,
"rgba8unorm" => wgpu_types::TextureFormat::Rgba8Unorm,
"rgba8unorm-srgb" => wgpu_types::TextureFormat::Rgba8UnormSrgb,
"rgba8snorm" => wgpu_types::TextureFormat::Rgba8Snorm,
"rgba8uint" => wgpu_types::TextureFormat::Rgba8Uint,
"rgba8sint" => wgpu_types::TextureFormat::Rgba8Sint,
"bgra8unorm" => wgpu_types::TextureFormat::Bgra8Unorm,
"bgra8unorm-srgb" => wgpu_types::TextureFormat::Bgra8UnormSrgb,
// Packed 32-bit formats
"rgb9e5ufloat" => return Err(not_supported()), // wgpu#967
"rgb10a2unorm" => wgpu_types::TextureFormat::Rgb10a2Unorm,
"rg11b10ufloat" => wgpu_types::TextureFormat::Rg11b10Float,
// 64-bit formats
"rg32uint" => wgpu_types::TextureFormat::Rg32Uint,
"rg32sint" => wgpu_types::TextureFormat::Rg32Sint,
"rg32float" => wgpu_types::TextureFormat::Rg32Float,
"rgba16uint" => wgpu_types::TextureFormat::Rgba16Uint,
"rgba16sint" => wgpu_types::TextureFormat::Rgba16Sint,
"rgba16float" => wgpu_types::TextureFormat::Rgba16Float,
// 128-bit formats
"rgba32uint" => wgpu_types::TextureFormat::Rgba32Uint,
"rgba32sint" => wgpu_types::TextureFormat::Rgba32Sint,
"rgba32float" => wgpu_types::TextureFormat::Rgba32Float,
// Depth and stencil formats
"stencil8" => return Err(not_supported()), // wgpu#967
"depth16unorm" => return Err(not_supported()), // wgpu#967
"depth24plus" => wgpu_types::TextureFormat::Depth24Plus,
"depth24plus-stencil8" => wgpu_types::TextureFormat::Depth24PlusStencil8,
"depth32float" => wgpu_types::TextureFormat::Depth32Float,
// BC compressed formats usable if "texture-compression-bc" is both
// supported by the device/user agent and enabled in requestDevice.
"bc1-rgba-unorm" => wgpu_types::TextureFormat::Bc1RgbaUnorm,
"bc1-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc1RgbaUnormSrgb,
"bc2-rgba-unorm" => wgpu_types::TextureFormat::Bc2RgbaUnorm,
"bc2-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc2RgbaUnormSrgb,
"bc3-rgba-unorm" => wgpu_types::TextureFormat::Bc3RgbaUnorm,
"bc3-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc3RgbaUnormSrgb,
"bc4-r-unorm" => wgpu_types::TextureFormat::Bc4RUnorm,
"bc4-r-snorm" => wgpu_types::TextureFormat::Bc4RSnorm,
"bc5-rg-unorm" => wgpu_types::TextureFormat::Bc5RgUnorm,
"bc5-rg-snorm" => wgpu_types::TextureFormat::Bc5RgSnorm,
"bc6h-rgb-ufloat" => wgpu_types::TextureFormat::Bc6hRgbUfloat,
"bc6h-rgb-float" => wgpu_types::TextureFormat::Bc6hRgbSfloat, // wgpu#967
"bc7-rgba-unorm" => wgpu_types::TextureFormat::Bc7RgbaUnorm,
"bc7-rgba-unorm-srgb" => wgpu_types::TextureFormat::Bc7RgbaUnormSrgb,
// "depth24unorm-stencil8" extension
"depth24unorm-stencil8" => return Err(not_supported()), // wgpu#967
// "depth32float-stencil8" extension
"depth32float-stencil8" => return Err(not_supported()), // wgpu#967
_ => unreachable!(),
})
}
pub fn serialize_dimension(
dimension: &str,
) -> wgpu_types::TextureViewDimension {
match dimension {
"1d" => wgpu_types::TextureViewDimension::D1,
"2d" => wgpu_types::TextureViewDimension::D2,
"2d-array" => wgpu_types::TextureViewDimension::D2Array,
"cube" => wgpu_types::TextureViewDimension::Cube,
"cube-array" => wgpu_types::TextureViewDimension::CubeArray,
"3d" => wgpu_types::TextureViewDimension::D3,
_ => unreachable!(),
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuExtent3D {
pub width: Option<u32>,
pub height: Option<u32>,
pub depth: Option<u32>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
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,
usage: u32,
}
pub fn op_webgpu_create_texture(
state: &mut OpState,
args: CreateTextureArgs,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)
.ok_or_else(bad_resource_id)?;
let device = device_resource.0;
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: args.size.depth.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::TextureUsage::from_bits(args.usage).unwrap(),
};
let (texture, maybe_err) = gfx_select!(device => instance.device_create_texture(
device,
&descriptor,
std::marker::PhantomData
));
let rid = state.resource_table.add(WebGpuTexture(texture));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTextureViewArgs {
texture_rid: ResourceId,
label: Option<String>,
format: Option<String>,
dimension: Option<String>,
aspect: Option<String>,
base_mip_level: Option<u32>,
mip_level_count: Option<u32>,
base_array_layer: Option<u32>,
array_layer_count: Option<u32>,
}
pub fn op_webgpu_create_texture_view(
state: &mut OpState,
args: CreateTextureViewArgs,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let texture_resource = state
.resource_table
.get::<WebGpuTexture>(args.texture_rid)
.ok_or_else(bad_resource_id)?;
let texture = texture_resource.0;
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)),
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),
level_count: std::num::NonZeroU32::new(args.mip_level_count.unwrap_or(0)),
base_array_layer: args.base_array_layer.unwrap_or(0),
array_layer_count: std::num::NonZeroU32::new(
args.array_layer_count.unwrap_or(0),
),
};
let (texture_view, maybe_err) = gfx_select!(texture => instance.texture_create_view(
texture,
&descriptor,
std::marker::PhantomData
));
let rid = state.resource_table.add(WebGpuTextureView(texture_view));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}