mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Implement GPUTexture and GPUTextureView
This commit is contained in:
parent
d9db350df5
commit
af95d92231
15 changed files with 638 additions and 15 deletions
|
@ -161,6 +161,7 @@ use webgpu::{
|
|||
wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout,
|
||||
WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
|
||||
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
|
||||
WebGPUTexture, WebGPUTextureView,
|
||||
};
|
||||
use webrender_api::{DocumentId, ImageKey};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
@ -561,6 +562,8 @@ unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
|
|||
unsafe_no_jsmanaged_fields!(WebGPUQueue);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUSampler);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUTexture);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUTextureView);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUDevice);
|
||||
|
|
|
@ -25,6 +25,11 @@ use crate::dom::bindings::codegen::Bindings::GPUSamplerBinding::{
|
|||
GPUAddressMode, GPUCompareFunction, GPUFilterMode, GPUSamplerDescriptor,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleDescriptor;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{
|
||||
GPUExtent3D, GPUExtent3DDict, GPUTextureComponentType, GPUTextureDescriptor,
|
||||
GPUTextureDimension, GPUTextureFormat,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewDimension;
|
||||
use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
|
@ -43,6 +48,7 @@ use crate::dom::gpuqueue::GPUQueue;
|
|||
use crate::dom::gpurenderpipeline::GPURenderPipeline;
|
||||
use crate::dom::gpusampler::GPUSampler;
|
||||
use crate::dom::gpushadermodule::GPUShaderModule;
|
||||
use crate::dom::gputexture::GPUTexture;
|
||||
use crate::script_runtime::JSContext as SafeJSContext;
|
||||
use arrayvec::ArrayVec;
|
||||
use dom_struct::dom_struct;
|
||||
|
@ -376,10 +382,16 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
ty,
|
||||
has_dynamic_offset: bind.hasDynamicOffset,
|
||||
multisampled: bind.multisampled,
|
||||
// Use as default for now
|
||||
texture_component_type: wgt::TextureComponentType::Float,
|
||||
storage_texture_format: wgt::TextureFormat::Rgba8UnormSrgb,
|
||||
view_dimension: wgt::TextureViewDimension::D2,
|
||||
texture_component_type: match bind.textureComponentType {
|
||||
GPUTextureComponentType::Float => wgt::TextureComponentType::Float,
|
||||
GPUTextureComponentType::Sint => wgt::TextureComponentType::Sint,
|
||||
GPUTextureComponentType::Uint => wgt::TextureComponentType::Uint,
|
||||
},
|
||||
storage_texture_format: match bind.storageTextureFormat {
|
||||
Some(s) => convert_texture_format(s),
|
||||
None => wgt::TextureFormat::Bgra8UnormSrgb,
|
||||
},
|
||||
view_dimension: convert_texture_view_dimension(bind.viewDimension),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<BindGroupLayoutEntry>>();
|
||||
|
@ -425,7 +437,9 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
multisampled: bind.multisampled,
|
||||
type_: bind.type_,
|
||||
visibility: bind.visibility,
|
||||
//texture_dimension: bind.texture_dimension
|
||||
viewDimension: bind.viewDimension,
|
||||
textureComponentType: bind.textureComponentType,
|
||||
storageTextureFormat: bind.storageTextureFormat,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -636,6 +650,62 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture
|
||||
fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> DomRoot<GPUTexture> {
|
||||
let mut valid = true;
|
||||
let size = convert_texture_size_to_dict(&descriptor.size);
|
||||
let desc = wgt::TextureDescriptor {
|
||||
label: Default::default(),
|
||||
size: convert_texture_size_to_wgt(&size),
|
||||
mip_level_count: descriptor.mipLevelCount,
|
||||
sample_count: descriptor.sampleCount,
|
||||
dimension: match descriptor.dimension {
|
||||
GPUTextureDimension::_1d => wgt::TextureDimension::D1,
|
||||
GPUTextureDimension::_2d => wgt::TextureDimension::D2,
|
||||
GPUTextureDimension::_3d => wgt::TextureDimension::D3,
|
||||
},
|
||||
format: convert_texture_format(descriptor.format),
|
||||
usage: match wgt::TextureUsage::from_bits(descriptor.usage) {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
valid = false;
|
||||
wgt::TextureUsage::empty()
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let texture_id = self
|
||||
.global()
|
||||
.wgpu_id_hub()
|
||||
.lock()
|
||||
.create_texture_id(self.device.0.backend());
|
||||
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::CreateTexture {
|
||||
device_id: self.device.0,
|
||||
texture_id,
|
||||
descriptor: desc,
|
||||
})
|
||||
.expect("Failed to create WebGPU Texture");
|
||||
|
||||
let texture = webgpu::WebGPUTexture(texture_id);
|
||||
|
||||
GPUTexture::new(
|
||||
&self.global(),
|
||||
texture,
|
||||
self.device,
|
||||
self.channel.clone(),
|
||||
size,
|
||||
descriptor.mipLevelCount,
|
||||
descriptor.sampleCount,
|
||||
descriptor.dimension,
|
||||
descriptor.format,
|
||||
descriptor.usage,
|
||||
valid,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler
|
||||
fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> {
|
||||
let sampler_id = self
|
||||
|
@ -727,7 +797,7 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
.colorStates
|
||||
.iter()
|
||||
.map(|state| wgt::ColorStateDescriptor {
|
||||
format: wgt::TextureFormat::Rgba8UnormSrgb, //TODO: Update this after implementing Texture
|
||||
format: convert_texture_format(state.format),
|
||||
alpha_blend: convert_blend_descriptor(&state.alphaBlend),
|
||||
color_blend: convert_blend_descriptor(&state.colorBlend),
|
||||
write_mask: match wgt::ColorWrite::from_bits(state.writeMask) {
|
||||
|
@ -742,7 +812,7 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
|
||||
let depth_stencil_state = if let Some(ref dss_desc) = descriptor.depthStencilState {
|
||||
Some(wgt::DepthStencilStateDescriptor {
|
||||
format: wgt::TextureFormat::Rgba8UnormSrgb, //TODO: Update this
|
||||
format: convert_texture_format(dss_desc.format),
|
||||
depth_write_enabled: dss_desc.depthWriteEnabled,
|
||||
depth_compare: convert_compare_function(dss_desc.depthCompare),
|
||||
stencil_front: wgt::StencilStateFaceDescriptor {
|
||||
|
@ -934,3 +1004,82 @@ fn convert_vertex_format(format: GPUVertexFormat) -> wgt::VertexFormat {
|
|||
GPUVertexFormat::Int4 => wgt::VertexFormat::Int4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_texture_format(format: GPUTextureFormat) -> wgt::TextureFormat {
|
||||
match format {
|
||||
GPUTextureFormat::R8unorm => wgt::TextureFormat::R8Unorm,
|
||||
GPUTextureFormat::R8snorm => wgt::TextureFormat::R8Snorm,
|
||||
GPUTextureFormat::R8uint => wgt::TextureFormat::R8Uint,
|
||||
GPUTextureFormat::R8sint => wgt::TextureFormat::R8Sint,
|
||||
GPUTextureFormat::R16uint => wgt::TextureFormat::R16Uint,
|
||||
GPUTextureFormat::R16sint => wgt::TextureFormat::R16Sint,
|
||||
GPUTextureFormat::R16float => wgt::TextureFormat::R16Float,
|
||||
GPUTextureFormat::Rg8unorm => wgt::TextureFormat::Rg8Unorm,
|
||||
GPUTextureFormat::Rg8snorm => wgt::TextureFormat::Rg8Snorm,
|
||||
GPUTextureFormat::Rg8uint => wgt::TextureFormat::Rg8Uint,
|
||||
GPUTextureFormat::Rg8sint => wgt::TextureFormat::Rg8Sint,
|
||||
GPUTextureFormat::R32uint => wgt::TextureFormat::R32Uint,
|
||||
GPUTextureFormat::R32sint => wgt::TextureFormat::R32Sint,
|
||||
GPUTextureFormat::R32float => wgt::TextureFormat::R32Float,
|
||||
GPUTextureFormat::Rg16uint => wgt::TextureFormat::Rg16Uint,
|
||||
GPUTextureFormat::Rg16sint => wgt::TextureFormat::Rg16Sint,
|
||||
GPUTextureFormat::Rg16float => wgt::TextureFormat::Rg16Float,
|
||||
GPUTextureFormat::Rgba8unorm => wgt::TextureFormat::Rgba8Unorm,
|
||||
GPUTextureFormat::Rgba8unorm_srgb => wgt::TextureFormat::Rgba8UnormSrgb,
|
||||
GPUTextureFormat::Rgba8snorm => wgt::TextureFormat::Rgba8Snorm,
|
||||
GPUTextureFormat::Rgba8uint => wgt::TextureFormat::Rgba8Uint,
|
||||
GPUTextureFormat::Rgba8sint => wgt::TextureFormat::Rgba8Sint,
|
||||
GPUTextureFormat::Bgra8unorm => wgt::TextureFormat::Bgra8Unorm,
|
||||
GPUTextureFormat::Bgra8unorm_srgb => wgt::TextureFormat::Bgra8UnormSrgb,
|
||||
GPUTextureFormat::Rgb10a2unorm => wgt::TextureFormat::Rgb10a2Unorm,
|
||||
GPUTextureFormat::Rg11b10float => wgt::TextureFormat::Rg11b10Float,
|
||||
GPUTextureFormat::Rg32uint => wgt::TextureFormat::Rg32Uint,
|
||||
GPUTextureFormat::Rg32sint => wgt::TextureFormat::Rg32Sint,
|
||||
GPUTextureFormat::Rg32float => wgt::TextureFormat::Rg32Float,
|
||||
GPUTextureFormat::Rgba16uint => wgt::TextureFormat::Rgba16Uint,
|
||||
GPUTextureFormat::Rgba16sint => wgt::TextureFormat::Rgba16Sint,
|
||||
GPUTextureFormat::Rgba16float => wgt::TextureFormat::Rgba16Float,
|
||||
GPUTextureFormat::Rgba32uint => wgt::TextureFormat::Rgba32Uint,
|
||||
GPUTextureFormat::Rgba32sint => wgt::TextureFormat::Rgba32Sint,
|
||||
GPUTextureFormat::Rgba32float => wgt::TextureFormat::Rgba32Float,
|
||||
GPUTextureFormat::Depth32float => wgt::TextureFormat::Depth32Float,
|
||||
GPUTextureFormat::Depth24plus => wgt::TextureFormat::Depth24Plus,
|
||||
GPUTextureFormat::Depth24plus_stencil8 => wgt::TextureFormat::Depth24PlusStencil8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_texture_view_dimension(
|
||||
dimension: GPUTextureViewDimension,
|
||||
) -> wgt::TextureViewDimension {
|
||||
match dimension {
|
||||
GPUTextureViewDimension::_1d => wgt::TextureViewDimension::D1,
|
||||
GPUTextureViewDimension::_2d => wgt::TextureViewDimension::D2,
|
||||
GPUTextureViewDimension::_2d_array => wgt::TextureViewDimension::D2Array,
|
||||
GPUTextureViewDimension::Cube => wgt::TextureViewDimension::Cube,
|
||||
GPUTextureViewDimension::Cube_array => wgt::TextureViewDimension::CubeArray,
|
||||
GPUTextureViewDimension::_3d => wgt::TextureViewDimension::D3,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_texture_size_to_dict(size: &GPUExtent3D) -> GPUExtent3DDict {
|
||||
match *size {
|
||||
GPUExtent3D::GPUExtent3DDict(ref dict) => GPUExtent3DDict {
|
||||
width: dict.width,
|
||||
height: dict.height,
|
||||
depth: dict.depth,
|
||||
},
|
||||
GPUExtent3D::RangeEnforcedUnsignedLongSequence(ref v) => GPUExtent3DDict {
|
||||
width: v[0],
|
||||
height: v[1],
|
||||
depth: v[2],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_texture_size_to_wgt(size: &GPUExtent3DDict) -> wgt::Extent3d {
|
||||
wgt::Extent3d {
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
depth: size.depth,
|
||||
}
|
||||
}
|
||||
|
|
188
components/script/dom/gputexture.rs
Normal file
188
components/script/dom/gputexture.rs
Normal file
|
@ -0,0 +1,188 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{
|
||||
GPUExtent3DDict, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{
|
||||
GPUTextureAspect, GPUTextureViewDescriptor,
|
||||
};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::gpudevice::{convert_texture_format, convert_texture_view_dimension};
|
||||
use crate::dom::gputextureview::GPUTextureView;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use webgpu::{wgt, WebGPU, WebGPUDevice, WebGPURequest, WebGPUTexture, WebGPUTextureView};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUTexture {
|
||||
reflector_: Reflector,
|
||||
texture: WebGPUTexture,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
device: WebGPUDevice,
|
||||
#[ignore_malloc_size_of = "channels are hard"]
|
||||
channel: WebGPU,
|
||||
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||
texture_size: GPUExtent3DDict,
|
||||
mip_level_count: u32,
|
||||
sample_count: u32,
|
||||
dimension: GPUTextureDimension,
|
||||
format: GPUTextureFormat,
|
||||
texture_usage: u32,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUTexture {
|
||||
fn new_inherited(
|
||||
texture: WebGPUTexture,
|
||||
device: WebGPUDevice,
|
||||
channel: WebGPU,
|
||||
texture_size: GPUExtent3DDict,
|
||||
mip_level_count: u32,
|
||||
sample_count: u32,
|
||||
dimension: GPUTextureDimension,
|
||||
format: GPUTextureFormat,
|
||||
texture_usage: u32,
|
||||
valid: bool,
|
||||
) -> GPUTexture {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
texture,
|
||||
label: DomRefCell::new(None),
|
||||
device,
|
||||
channel,
|
||||
texture_size,
|
||||
mip_level_count,
|
||||
sample_count,
|
||||
dimension,
|
||||
format,
|
||||
texture_usage,
|
||||
valid: Cell::new(valid),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
texture: WebGPUTexture,
|
||||
device: WebGPUDevice,
|
||||
channel: WebGPU,
|
||||
texture_size: GPUExtent3DDict,
|
||||
mip_level_count: u32,
|
||||
sample_count: u32,
|
||||
dimension: GPUTextureDimension,
|
||||
format: GPUTextureFormat,
|
||||
texture_usage: u32,
|
||||
valid: bool,
|
||||
) -> DomRoot<GPUTexture> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUTexture::new_inherited(
|
||||
texture,
|
||||
device,
|
||||
channel,
|
||||
texture_size,
|
||||
mip_level_count,
|
||||
sample_count,
|
||||
dimension,
|
||||
format,
|
||||
texture_usage,
|
||||
valid,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GPUTexture {
|
||||
fn drop(&mut self) {
|
||||
self.Destroy()
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUTextureMethods for GPUTexture {
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn GetLabel(&self) -> Option<DOMString> {
|
||||
self.label.borrow().clone()
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn SetLabel(&self, value: Option<DOMString>) {
|
||||
*self.label.borrow_mut() = value;
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-createview
|
||||
fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot<GPUTextureView> {
|
||||
let desc = wgt::TextureViewDescriptor {
|
||||
label: Default::default(),
|
||||
format: convert_texture_format(descriptor.format.unwrap_or(self.format)),
|
||||
dimension: match descriptor.dimension {
|
||||
Some(d) => convert_texture_view_dimension(d),
|
||||
None => match self.dimension {
|
||||
GPUTextureDimension::_1d => wgt::TextureViewDimension::D1,
|
||||
GPUTextureDimension::_2d => {
|
||||
if self.texture_size.depth > 1 && descriptor.arrayLayerCount == 0 {
|
||||
wgt::TextureViewDimension::D2Array
|
||||
} else {
|
||||
wgt::TextureViewDimension::D2
|
||||
}
|
||||
},
|
||||
GPUTextureDimension::_3d => wgt::TextureViewDimension::D3,
|
||||
},
|
||||
},
|
||||
aspect: match descriptor.aspect {
|
||||
GPUTextureAspect::All => wgt::TextureAspect::All,
|
||||
GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
|
||||
GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
|
||||
},
|
||||
base_mip_level: descriptor.baseMipLevel,
|
||||
level_count: if descriptor.mipLevelCount == 0 {
|
||||
self.mip_level_count - descriptor.baseMipLevel
|
||||
} else {
|
||||
descriptor.mipLevelCount
|
||||
},
|
||||
base_array_layer: descriptor.baseArrayLayer,
|
||||
array_layer_count: if descriptor.arrayLayerCount == 0 {
|
||||
self.texture_size.depth - descriptor.baseArrayLayer
|
||||
} else {
|
||||
descriptor.arrayLayerCount
|
||||
},
|
||||
};
|
||||
|
||||
let texture_view_id = self
|
||||
.global()
|
||||
.wgpu_id_hub()
|
||||
.lock()
|
||||
.create_texture_view_id(self.device.0.backend());
|
||||
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::CreateTextureView {
|
||||
texture_id: self.texture.0,
|
||||
texture_view_id,
|
||||
descriptor: desc,
|
||||
})
|
||||
.expect("Failed to create WebGPU texture view");
|
||||
|
||||
let texture_view = WebGPUTextureView(texture_view_id);
|
||||
|
||||
GPUTextureView::new(&self.global(), texture_view, self.device, true)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy
|
||||
fn Destroy(&self) {
|
||||
if let Err(e) = self
|
||||
.channel
|
||||
.0
|
||||
.send(WebGPURequest::DestroyTexture(self.texture.0))
|
||||
{
|
||||
warn!(
|
||||
"Failed to send WebGPURequest::DestroyTexture({:?}) ({})",
|
||||
self.texture.0, e
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
11
components/script/dom/gputextureusage.rs
Normal file
11
components/script/dom/gputextureusage.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::reflector::Reflector;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUTextureUsage {
|
||||
reflector_: Reflector,
|
||||
}
|
62
components/script/dom/gputextureview.rs
Normal file
62
components/script/dom/gputextureview.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewMethods;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use webgpu::{WebGPUDevice, WebGPUTextureView};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUTextureView {
|
||||
reflector_: Reflector,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
texture_view: WebGPUTextureView,
|
||||
device: WebGPUDevice,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUTextureView {
|
||||
fn new_inherited(
|
||||
texture_view: WebGPUTextureView,
|
||||
device: WebGPUDevice,
|
||||
valid: bool,
|
||||
) -> GPUTextureView {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
device,
|
||||
label: DomRefCell::new(None),
|
||||
texture_view,
|
||||
valid: Cell::new(valid),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
texture_view: WebGPUTextureView,
|
||||
device: WebGPUDevice,
|
||||
valid: bool,
|
||||
) -> DomRoot<GPUTextureView> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUTextureView::new_inherited(texture_view, device, valid)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUTextureViewMethods for GPUTextureView {
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn GetLabel(&self) -> Option<DOMString> {
|
||||
self.label.borrow().clone()
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn SetLabel(&self, value: Option<DOMString>) {
|
||||
*self.label.borrow_mut() = value;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,8 @@ use webgpu::wgpu::{
|
|||
hub::IdentityManager,
|
||||
id::{
|
||||
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId,
|
||||
DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId,
|
||||
DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, TextureId,
|
||||
TextureViewId,
|
||||
},
|
||||
};
|
||||
use webgpu::wgt::Backend;
|
||||
|
@ -23,6 +24,8 @@ pub struct IdentityHub {
|
|||
pipeline_layouts: IdentityManager,
|
||||
shader_modules: IdentityManager,
|
||||
command_encoders: IdentityManager,
|
||||
textures: IdentityManager,
|
||||
texture_views: IdentityManager,
|
||||
samplers: IdentityManager,
|
||||
render_pipelines: IdentityManager,
|
||||
}
|
||||
|
@ -39,6 +42,8 @@ impl IdentityHub {
|
|||
pipeline_layouts: IdentityManager::default(),
|
||||
shader_modules: IdentityManager::default(),
|
||||
command_encoders: IdentityManager::default(),
|
||||
textures: IdentityManager::default(),
|
||||
texture_views: IdentityManager::default(),
|
||||
samplers: IdentityManager::default(),
|
||||
render_pipelines: IdentityManager::default(),
|
||||
}
|
||||
|
@ -194,4 +199,20 @@ impl Identities {
|
|||
pub fn kill_render_pipeline_id(&mut self, id: RenderPipelineId) {
|
||||
self.select(id.backend()).render_pipelines.free(id);
|
||||
}
|
||||
|
||||
pub fn create_texture_id(&mut self, backend: Backend) -> TextureId {
|
||||
self.select(backend).textures.alloc(backend)
|
||||
}
|
||||
|
||||
pub fn kill_texture_id(&mut self, id: TextureId) {
|
||||
self.select(id.backend()).textures.free(id);
|
||||
}
|
||||
|
||||
pub fn create_texture_view_id(&mut self, backend: Backend) -> TextureViewId {
|
||||
self.select(backend).texture_views.alloc(backend)
|
||||
}
|
||||
|
||||
pub fn kill_texture_view_id(&mut self, id: TextureViewId) {
|
||||
self.select(id.backend()).texture_views.free(id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -337,6 +337,9 @@ pub mod gpurenderpipeline;
|
|||
pub mod gpusampler;
|
||||
pub mod gpushadermodule;
|
||||
pub mod gpushaderstage;
|
||||
pub mod gputexture;
|
||||
pub mod gputextureusage;
|
||||
pub mod gputextureview;
|
||||
pub mod hashchangeevent;
|
||||
pub mod headers;
|
||||
pub mod history;
|
||||
|
|
|
@ -13,11 +13,12 @@ dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
|
|||
};
|
||||
|
||||
dictionary GPUBindGroupLayoutEntry {
|
||||
required unsigned long binding;
|
||||
required GPUIndex32 binding;
|
||||
required GPUShaderStageFlags visibility;
|
||||
required GPUBindingType type;
|
||||
//GPUTextureViewDimension textureDimension = "2d";
|
||||
//GPUTextureComponentType textureComponentType = "float";
|
||||
GPUTextureViewDimension viewDimension = "2d";
|
||||
GPUTextureComponentType textureComponentType = "float";
|
||||
GPUTextureFormat storageTextureFormat;
|
||||
boolean multisampled = false;
|
||||
boolean hasDynamicOffset = false;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// https://gpuweb.github.io/gpuweb/#gpudevice
|
||||
[Exposed=(Window, DedicatedWorker)/*, Serializable */, Pref="dom.webgpu.enabled"]
|
||||
interface GPUDevice : EventTarget {
|
||||
/*[SameObject]*/ readonly attribute GPUAdapter adapter;
|
||||
[SameObject] readonly attribute GPUAdapter adapter;
|
||||
readonly attribute object extensions;
|
||||
readonly attribute object limits;
|
||||
|
||||
|
@ -13,7 +13,7 @@ interface GPUDevice : EventTarget {
|
|||
|
||||
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
|
||||
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
|
||||
// GPUTexture createTexture(GPUTextureDescriptor descriptor);
|
||||
GPUTexture createTexture(GPUTextureDescriptor descriptor);
|
||||
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
|
||||
|
||||
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
|
||||
|
|
|
@ -56,7 +56,7 @@ enum GPUCullMode {
|
|||
};
|
||||
|
||||
dictionary GPUColorStateDescriptor {
|
||||
//required GPUTextureFormat format;
|
||||
required GPUTextureFormat format;
|
||||
|
||||
GPUBlendDescriptor alphaBlend = {};
|
||||
GPUBlendDescriptor colorBlend = {};
|
||||
|
@ -107,7 +107,7 @@ enum GPUStencilOperation {
|
|||
typedef [EnforceRange] unsigned long GPUStencilValue;
|
||||
|
||||
dictionary GPUDepthStencilStateDescriptor {
|
||||
//required GPUTextureFormat format;
|
||||
required GPUTextureFormat format;
|
||||
|
||||
boolean depthWriteEnabled = false;
|
||||
GPUCompareFunction depthCompare = "always";
|
||||
|
|
94
components/script/dom/webidls/GPUTexture.webidl
Normal file
94
components/script/dom/webidls/GPUTexture.webidl
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#gputexture
|
||||
[Exposed=(Window, DedicatedWorker), Serializable , Pref="dom.webgpu.enabled"]
|
||||
interface GPUTexture {
|
||||
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
|
||||
|
||||
void destroy();
|
||||
};
|
||||
GPUTexture includes GPUObjectBase;
|
||||
|
||||
dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
|
||||
required GPUExtent3D size;
|
||||
GPUIntegerCoordinate mipLevelCount = 1;
|
||||
GPUSize32 sampleCount = 1;
|
||||
GPUTextureDimension dimension = "2d";
|
||||
required GPUTextureFormat format;
|
||||
required GPUTextureUsageFlags usage;
|
||||
};
|
||||
|
||||
enum GPUTextureDimension {
|
||||
"1d",
|
||||
"2d",
|
||||
"3d"
|
||||
};
|
||||
|
||||
enum GPUTextureFormat {
|
||||
// 8-bit formats
|
||||
"r8unorm",
|
||||
"r8snorm",
|
||||
"r8uint",
|
||||
"r8sint",
|
||||
|
||||
// 16-bit formats
|
||||
"r16uint",
|
||||
"r16sint",
|
||||
"r16float",
|
||||
"rg8unorm",
|
||||
"rg8snorm",
|
||||
"rg8uint",
|
||||
"rg8sint",
|
||||
|
||||
// 32-bit formats
|
||||
"r32uint",
|
||||
"r32sint",
|
||||
"r32float",
|
||||
"rg16uint",
|
||||
"rg16sint",
|
||||
"rg16float",
|
||||
"rgba8unorm",
|
||||
"rgba8unorm-srgb",
|
||||
"rgba8snorm",
|
||||
"rgba8uint",
|
||||
"rgba8sint",
|
||||
"bgra8unorm",
|
||||
"bgra8unorm-srgb",
|
||||
// Packed 32-bit formats
|
||||
"rgb10a2unorm",
|
||||
"rg11b10float",
|
||||
|
||||
// 64-bit formats
|
||||
"rg32uint",
|
||||
"rg32sint",
|
||||
"rg32float",
|
||||
"rgba16uint",
|
||||
"rgba16sint",
|
||||
"rgba16float",
|
||||
|
||||
// 128-bit formats
|
||||
"rgba32uint",
|
||||
"rgba32sint",
|
||||
"rgba32float",
|
||||
|
||||
// Depth and stencil formats
|
||||
"depth32float",
|
||||
"depth24plus",
|
||||
"depth24plus-stencil8"
|
||||
};
|
||||
|
||||
enum GPUTextureComponentType {
|
||||
"float",
|
||||
"sint",
|
||||
"uint"
|
||||
};
|
||||
|
||||
dictionary GPUExtent3DDict {
|
||||
required GPUIntegerCoordinate width;
|
||||
required GPUIntegerCoordinate height;
|
||||
required GPUIntegerCoordinate depth;
|
||||
};
|
||||
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
|
||||
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;
|
15
components/script/dom/webidls/GPUTextureUsage.webidl
Normal file
15
components/script/dom/webidls/GPUTextureUsage.webidl
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#gputextureusage
|
||||
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
|
||||
interface GPUTextureUsage {
|
||||
const GPUTextureUsageFlags COPY_SRC = 0x01;
|
||||
const GPUTextureUsageFlags COPY_DST = 0x02;
|
||||
const GPUTextureUsageFlags SAMPLED = 0x04;
|
||||
const GPUTextureUsageFlags STORAGE = 0x08;
|
||||
const GPUTextureUsageFlags OUTPUT_ATTACHMENT = 0x10;
|
||||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
|
34
components/script/dom/webidls/GPUTextureView.webidl
Normal file
34
components/script/dom/webidls/GPUTextureView.webidl
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#gputextureview
|
||||
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
|
||||
interface GPUTextureView {
|
||||
};
|
||||
GPUTextureView includes GPUObjectBase;
|
||||
|
||||
dictionary GPUTextureViewDescriptor : GPUObjectDescriptorBase {
|
||||
GPUTextureFormat format;
|
||||
GPUTextureViewDimension dimension;
|
||||
GPUTextureAspect aspect = "all";
|
||||
GPUIntegerCoordinate baseMipLevel = 0;
|
||||
GPUIntegerCoordinate mipLevelCount = 0;
|
||||
GPUIntegerCoordinate baseArrayLayer = 0;
|
||||
GPUIntegerCoordinate arrayLayerCount = 0;
|
||||
};
|
||||
|
||||
enum GPUTextureViewDimension {
|
||||
"1d",
|
||||
"2d",
|
||||
"2d-array",
|
||||
"cube",
|
||||
"cube-array",
|
||||
"3d"
|
||||
};
|
||||
|
||||
enum GPUTextureAspect {
|
||||
"all",
|
||||
"stencil-only",
|
||||
"depth-only"
|
||||
};
|
|
@ -1956,6 +1956,8 @@ impl ScriptThread {
|
|||
WebGPUMsg::FreeSampler(id) => self.gpu_id_hub.lock().kill_sampler_id(id),
|
||||
WebGPUMsg::FreeShaderModule(id) => self.gpu_id_hub.lock().kill_shader_module_id(id),
|
||||
WebGPUMsg::FreeRenderPipeline(id) => self.gpu_id_hub.lock().kill_render_pipeline_id(id),
|
||||
WebGPUMsg::FreeTexture(id) => self.gpu_id_hub.lock().kill_texture_id(id),
|
||||
WebGPUMsg::FreeTextureView(id) => self.gpu_id_hub.lock().kill_texture_view_id(id),
|
||||
WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None,
|
||||
_ => {},
|
||||
}
|
||||
|
|
|
@ -127,7 +127,18 @@ pub enum WebGPURequest {
|
|||
program_id: id::ShaderModuleId,
|
||||
program: Vec<u32>,
|
||||
},
|
||||
CreateTexture {
|
||||
device_id: id::DeviceId,
|
||||
texture_id: id::TextureId,
|
||||
descriptor: wgt::TextureDescriptor<String>,
|
||||
},
|
||||
CreateTextureView {
|
||||
texture_id: id::TextureId,
|
||||
texture_view_id: id::TextureViewId,
|
||||
descriptor: wgt::TextureViewDescriptor<String>,
|
||||
},
|
||||
DestroyBuffer(id::BufferId),
|
||||
DestroyTexture(id::TextureId),
|
||||
Exit(IpcSender<()>),
|
||||
RequestAdapter {
|
||||
sender: IpcSender<WebGPUResponseResult>,
|
||||
|
@ -457,10 +468,37 @@ impl WGPU {
|
|||
let _ = gfx_select!(program_id =>
|
||||
global.device_create_shader_module(device_id, &descriptor, program_id));
|
||||
},
|
||||
WebGPURequest::CreateTexture {
|
||||
device_id,
|
||||
texture_id,
|
||||
descriptor,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
let st = CString::new(descriptor.label.as_bytes()).unwrap();
|
||||
let _ = gfx_select!(texture_id =>
|
||||
global.device_create_texture(device_id, &descriptor.map_label(|_| st.as_ptr()), texture_id));
|
||||
},
|
||||
WebGPURequest::CreateTextureView {
|
||||
texture_id,
|
||||
texture_view_id,
|
||||
descriptor,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
let st = CString::new(descriptor.label.as_bytes()).unwrap();
|
||||
let _ = gfx_select!(texture_view_id => global.texture_create_view(
|
||||
texture_id,
|
||||
Some(&descriptor.map_label(|_| st.as_ptr())),
|
||||
texture_view_id
|
||||
));
|
||||
},
|
||||
WebGPURequest::DestroyBuffer(buffer) => {
|
||||
let global = &self.global;
|
||||
gfx_select!(buffer => global.buffer_destroy(buffer));
|
||||
},
|
||||
WebGPURequest::DestroyTexture(texture) => {
|
||||
let global = &self.global;
|
||||
gfx_select!(texture => global.texture_destroy(texture));
|
||||
},
|
||||
WebGPURequest::Exit(sender) => {
|
||||
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
|
||||
warn!("Failed to send WebGPUMsg::Exit to script ({})", e);
|
||||
|
@ -605,3 +643,5 @@ webgpu_resource!(WebGPUQueue, id::QueueId);
|
|||
webgpu_resource!(WebGPURenderPipeline, id::RenderPipelineId);
|
||||
webgpu_resource!(WebGPUSampler, id::SamplerId);
|
||||
webgpu_resource!(WebGPUShaderModule, id::ShaderModuleId);
|
||||
webgpu_resource!(WebGPUTexture, id::TextureId);
|
||||
webgpu_resource!(WebGPUTextureView, id::TextureViewId);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue