Auto merge of #26742 - kunalmohan:gpu-texture, r=kvark

Implement GPUTexture and GPUTextureView

<!-- Please describe your changes on the following line: -->
This also include changes to CodegenRust.py to allow enum values starting with digits.

r?@kvark

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2020-06-01 20:53:20 -04:00 committed by GitHub
commit 2b24cfed10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 650 additions and 23 deletions

View file

@ -4328,7 +4328,7 @@ def getEnumValueName(value):
if re.match("[^\x20-\x7E]", value): if re.match("[^\x20-\x7E]", value):
raise SyntaxError('Enum value "' + value + '" contains non-ASCII characters') raise SyntaxError('Enum value "' + value + '" contains non-ASCII characters')
if re.match("^[0-9]", value): if re.match("^[0-9]", value):
raise SyntaxError('Enum value "' + value + '" starts with a digit') value = '_' + value
value = re.sub(r'[^0-9A-Za-z_]', '_', value) value = re.sub(r'[^0-9A-Za-z_]', '_', value)
if re.match("^_[A-Z]|__", value): if re.match("^_[A-Z]|__", value):
raise SyntaxError('Enum value "' + value + '" is reserved by the C++ spec') raise SyntaxError('Enum value "' + value + '" is reserved by the C++ spec')
@ -4650,20 +4650,24 @@ class CGUnionConversionStruct(CGThing):
# "object" is not distinguishable from other types # "object" is not distinguishable from other types
assert not object or not (interfaceObject or arrayObject or callbackObject or mozMapObject) assert not object or not (interfaceObject or arrayObject or callbackObject or mozMapObject)
templateBody = CGList([], "\n") templateBody = CGList([], "\n")
if object: if arrayObject or callbackObject:
templateBody.append(object) # An object can be both an sequence object and a callback or
# dictionary, but we shouldn't have both in the union's members
# because they are not distinguishable.
assert not (arrayObject and callbackObject)
templateBody.append(arrayObject if arrayObject else callbackObject)
if interfaceObject: if interfaceObject:
assert not object
templateBody.append(interfaceObject) templateBody.append(interfaceObject)
if arrayObject: elif object:
templateBody.append(arrayObject) templateBody.append(object)
if callbackObject:
templateBody.append(callbackObject)
if mozMapObject: if mozMapObject:
templateBody.append(mozMapObject) templateBody.append(mozMapObject)
conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) conversions.append(CGIfWrapper("value.get().is_object()", templateBody))
if dictionaryObject: if dictionaryObject:
assert not hasObjectTypes assert not object
conversions.append(dictionaryObject) conversions.append(dictionaryObject)
stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()] stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]

View file

@ -161,6 +161,7 @@ use webgpu::{
wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout,
WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule, WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
WebGPUTexture, WebGPUTextureView,
}; };
use webrender_api::{DocumentId, ImageKey}; use webrender_api::{DocumentId, ImageKey};
use webxr_api::SwapChainId as WebXRSwapChainId; use webxr_api::SwapChainId as WebXRSwapChainId;
@ -561,6 +562,8 @@ unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(WebGPUQueue); unsafe_no_jsmanaged_fields!(WebGPUQueue);
unsafe_no_jsmanaged_fields!(WebGPUShaderModule); unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(WebGPUSampler); unsafe_no_jsmanaged_fields!(WebGPUSampler);
unsafe_no_jsmanaged_fields!(WebGPUTexture);
unsafe_no_jsmanaged_fields!(WebGPUTextureView);
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer); unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder); unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
unsafe_no_jsmanaged_fields!(WebGPUDevice); unsafe_no_jsmanaged_fields!(WebGPUDevice);

View file

@ -25,6 +25,11 @@ use crate::dom::bindings::codegen::Bindings::GPUSamplerBinding::{
GPUAddressMode, GPUCompareFunction, GPUFilterMode, GPUSamplerDescriptor, GPUAddressMode, GPUCompareFunction, GPUFilterMode, GPUSamplerDescriptor,
}; };
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleDescriptor; 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::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
@ -43,6 +48,7 @@ use crate::dom::gpuqueue::GPUQueue;
use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpurenderpipeline::GPURenderPipeline;
use crate::dom::gpusampler::GPUSampler; use crate::dom::gpusampler::GPUSampler;
use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gpushadermodule::GPUShaderModule;
use crate::dom::gputexture::GPUTexture;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext as SafeJSContext;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -376,10 +382,16 @@ impl GPUDeviceMethods for GPUDevice {
ty, ty,
has_dynamic_offset: bind.hasDynamicOffset, has_dynamic_offset: bind.hasDynamicOffset,
multisampled: bind.multisampled, multisampled: bind.multisampled,
// Use as default for now texture_component_type: match bind.textureComponentType {
texture_component_type: wgt::TextureComponentType::Float, GPUTextureComponentType::Float => wgt::TextureComponentType::Float,
storage_texture_format: wgt::TextureFormat::Rgba8UnormSrgb, GPUTextureComponentType::Sint => wgt::TextureComponentType::Sint,
view_dimension: wgt::TextureViewDimension::D2, 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>>(); .collect::<Vec<BindGroupLayoutEntry>>();
@ -425,7 +437,9 @@ impl GPUDeviceMethods for GPUDevice {
multisampled: bind.multisampled, multisampled: bind.multisampled,
type_: bind.type_, type_: bind.type_,
visibility: bind.visibility, visibility: bind.visibility,
//texture_dimension: bind.texture_dimension viewDimension: bind.viewDimension,
textureComponentType: bind.textureComponentType,
storageTextureFormat: bind.storageTextureFormat,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -636,6 +650,62 @@ impl GPUDeviceMethods for GPUDevice {
GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true) 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 /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler
fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> { fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> {
let sampler_id = self let sampler_id = self
@ -727,7 +797,7 @@ impl GPUDeviceMethods for GPUDevice {
.colorStates .colorStates
.iter() .iter()
.map(|state| wgt::ColorStateDescriptor { .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), alpha_blend: convert_blend_descriptor(&state.alphaBlend),
color_blend: convert_blend_descriptor(&state.colorBlend), color_blend: convert_blend_descriptor(&state.colorBlend),
write_mask: match wgt::ColorWrite::from_bits(state.writeMask) { 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 { let depth_stencil_state = if let Some(ref dss_desc) = descriptor.depthStencilState {
Some(wgt::DepthStencilStateDescriptor { Some(wgt::DepthStencilStateDescriptor {
format: wgt::TextureFormat::Rgba8UnormSrgb, //TODO: Update this format: convert_texture_format(dss_desc.format),
depth_write_enabled: dss_desc.depthWriteEnabled, depth_write_enabled: dss_desc.depthWriteEnabled,
depth_compare: convert_compare_function(dss_desc.depthCompare), depth_compare: convert_compare_function(dss_desc.depthCompare),
stencil_front: wgt::StencilStateFaceDescriptor { stencil_front: wgt::StencilStateFaceDescriptor {
@ -934,3 +1004,82 @@ fn convert_vertex_format(format: GPUVertexFormat) -> wgt::VertexFormat {
GPUVertexFormat::Int4 => wgt::VertexFormat::Int4, 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,
}
}

View 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
);
};
}
}

View 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,
}

View 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;
}
}

View file

@ -7,7 +7,8 @@ use webgpu::wgpu::{
hub::IdentityManager, hub::IdentityManager,
id::{ id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId, AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId,
DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, TextureId,
TextureViewId,
}, },
}; };
use webgpu::wgt::Backend; use webgpu::wgt::Backend;
@ -23,6 +24,8 @@ pub struct IdentityHub {
pipeline_layouts: IdentityManager, pipeline_layouts: IdentityManager,
shader_modules: IdentityManager, shader_modules: IdentityManager,
command_encoders: IdentityManager, command_encoders: IdentityManager,
textures: IdentityManager,
texture_views: IdentityManager,
samplers: IdentityManager, samplers: IdentityManager,
render_pipelines: IdentityManager, render_pipelines: IdentityManager,
} }
@ -39,6 +42,8 @@ impl IdentityHub {
pipeline_layouts: IdentityManager::default(), pipeline_layouts: IdentityManager::default(),
shader_modules: IdentityManager::default(), shader_modules: IdentityManager::default(),
command_encoders: IdentityManager::default(), command_encoders: IdentityManager::default(),
textures: IdentityManager::default(),
texture_views: IdentityManager::default(),
samplers: IdentityManager::default(), samplers: IdentityManager::default(),
render_pipelines: IdentityManager::default(), render_pipelines: IdentityManager::default(),
} }
@ -194,4 +199,20 @@ impl Identities {
pub fn kill_render_pipeline_id(&mut self, id: RenderPipelineId) { pub fn kill_render_pipeline_id(&mut self, id: RenderPipelineId) {
self.select(id.backend()).render_pipelines.free(id); 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);
}
} }

View file

@ -337,6 +337,9 @@ pub mod gpurenderpipeline;
pub mod gpusampler; pub mod gpusampler;
pub mod gpushadermodule; pub mod gpushadermodule;
pub mod gpushaderstage; pub mod gpushaderstage;
pub mod gputexture;
pub mod gputextureusage;
pub mod gputextureview;
pub mod hashchangeevent; pub mod hashchangeevent;
pub mod headers; pub mod headers;
pub mod history; pub mod history;

View file

@ -13,11 +13,12 @@ dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
}; };
dictionary GPUBindGroupLayoutEntry { dictionary GPUBindGroupLayoutEntry {
required unsigned long binding; required GPUIndex32 binding;
required GPUShaderStageFlags visibility; required GPUShaderStageFlags visibility;
required GPUBindingType type; required GPUBindingType type;
//GPUTextureViewDimension textureDimension = "2d"; GPUTextureViewDimension viewDimension = "2d";
//GPUTextureComponentType textureComponentType = "float"; GPUTextureComponentType textureComponentType = "float";
GPUTextureFormat storageTextureFormat;
boolean multisampled = false; boolean multisampled = false;
boolean hasDynamicOffset = false; boolean hasDynamicOffset = false;
}; };

View file

@ -5,7 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpudevice // https://gpuweb.github.io/gpuweb/#gpudevice
[Exposed=(Window, DedicatedWorker)/*, Serializable */, Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker)/*, Serializable */, Pref="dom.webgpu.enabled"]
interface GPUDevice : EventTarget { interface GPUDevice : EventTarget {
/*[SameObject]*/ readonly attribute GPUAdapter adapter; [SameObject] readonly attribute GPUAdapter adapter;
readonly attribute object extensions; readonly attribute object extensions;
readonly attribute object limits; readonly attribute object limits;
@ -13,7 +13,7 @@ interface GPUDevice : EventTarget {
GPUBuffer createBuffer(GPUBufferDescriptor descriptor); GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor); GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
// GPUTexture createTexture(GPUTextureDescriptor descriptor); GPUTexture createTexture(GPUTextureDescriptor descriptor);
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {}); GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);

View file

@ -56,7 +56,7 @@ enum GPUCullMode {
}; };
dictionary GPUColorStateDescriptor { dictionary GPUColorStateDescriptor {
//required GPUTextureFormat format; required GPUTextureFormat format;
GPUBlendDescriptor alphaBlend = {}; GPUBlendDescriptor alphaBlend = {};
GPUBlendDescriptor colorBlend = {}; GPUBlendDescriptor colorBlend = {};
@ -107,7 +107,7 @@ enum GPUStencilOperation {
typedef [EnforceRange] unsigned long GPUStencilValue; typedef [EnforceRange] unsigned long GPUStencilValue;
dictionary GPUDepthStencilStateDescriptor { dictionary GPUDepthStencilStateDescriptor {
//required GPUTextureFormat format; required GPUTextureFormat format;
boolean depthWriteEnabled = false; boolean depthWriteEnabled = false;
GPUCompareFunction depthCompare = "always"; GPUCompareFunction depthCompare = "always";

View 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;

View 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;

View 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"
};

View file

@ -1956,6 +1956,8 @@ impl ScriptThread {
WebGPUMsg::FreeSampler(id) => self.gpu_id_hub.lock().kill_sampler_id(id), 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::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::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, WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None,
_ => {}, _ => {},
} }

View file

@ -127,7 +127,18 @@ pub enum WebGPURequest {
program_id: id::ShaderModuleId, program_id: id::ShaderModuleId,
program: Vec<u32>, 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), DestroyBuffer(id::BufferId),
DestroyTexture(id::TextureId),
Exit(IpcSender<()>), Exit(IpcSender<()>),
RequestAdapter { RequestAdapter {
sender: IpcSender<WebGPUResponseResult>, sender: IpcSender<WebGPUResponseResult>,
@ -457,10 +468,37 @@ impl WGPU {
let _ = gfx_select!(program_id => let _ = gfx_select!(program_id =>
global.device_create_shader_module(device_id, &descriptor, 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) => { WebGPURequest::DestroyBuffer(buffer) => {
let global = &self.global; let global = &self.global;
gfx_select!(buffer => global.buffer_destroy(buffer)); gfx_select!(buffer => global.buffer_destroy(buffer));
}, },
WebGPURequest::DestroyTexture(texture) => {
let global = &self.global;
gfx_select!(texture => global.texture_destroy(texture));
},
WebGPURequest::Exit(sender) => { WebGPURequest::Exit(sender) => {
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) { if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
warn!("Failed to send WebGPUMsg::Exit to script ({})", e); 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!(WebGPURenderPipeline, id::RenderPipelineId);
webgpu_resource!(WebGPUSampler, id::SamplerId); webgpu_resource!(WebGPUSampler, id::SamplerId);
webgpu_resource!(WebGPUShaderModule, id::ShaderModuleId); webgpu_resource!(WebGPUShaderModule, id::ShaderModuleId);
webgpu_resource!(WebGPUTexture, id::TextureId);
webgpu_resource!(WebGPUTextureView, id::TextureViewId);