mirror of
https://github.com/servo/servo.git
synced 2025-06-08 08:33:26 +00:00
Auto merge of #25526 - szeged:bind_group_wgpu, r=jdm
Initial implementation of GPUBindGroupLayout for WebGPU Added WebIDL bindings for `GPUBindGroupLayout`, `GPUBindGroupLayoutDescriptor`, `GPUBindingType`, `GPUShaderStage` and `GPUBindGroupLayoutBinding` (Note: The servo's codegen doesn't like the name, because its already occupied). Implemented the `createBindGroupLayout` function of `GPUDevice`. <!-- Please describe your changes on the following line: --> --- <!-- 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 - [X] These changes addresses a part of #24706 cc @kvark @jdm @zakorgy <!-- 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:
commit
90b0a7fcc5
13 changed files with 397 additions and 11 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -4027,7 +4027,25 @@ version = "0.2.0"
|
||||||
source = "git+https://github.com/servo/webrender#edac864107cf43732ec66a9d3288e869a70ce1de"
|
source = "git+https://github.com/servo/webrender#edac864107cf43732ec66a9d3288e869a70ce1de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"peek-poke-derive",
|
"peek-poke-derive 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "peek-poke"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075#969bd7fe2be1a83f87916dc8b388c63cfd457075"
|
||||||
|
dependencies = [
|
||||||
|
"peek-poke-derive 0.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "peek-poke-derive"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075#969bd7fe2be1a83f87916dc8b388c63cfd457075"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.1",
|
||||||
|
"quote 1.0.2",
|
||||||
|
"syn 1.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -6651,7 +6669,7 @@ dependencies = [
|
||||||
"derive_more 0.13.0",
|
"derive_more 0.13.0",
|
||||||
"euclid",
|
"euclid",
|
||||||
"malloc_size_of_derive",
|
"malloc_size_of_derive",
|
||||||
"peek-poke",
|
"peek-poke 0.2.0 (git+https://github.com/servo/webrender)",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
@ -6740,7 +6758,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu-core"
|
name = "wgpu-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/gfx-rs/wgpu#c0fa61a064c3572ee60d6c4c6a59ca0571394200"
|
source = "git+https://github.com/gfx-rs/wgpu#881222a9477036e9e3504045452d88abfe5ae177"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.5.1",
|
"arrayvec 0.5.1",
|
||||||
"battery",
|
"battery",
|
||||||
|
@ -6755,6 +6773,7 @@ dependencies = [
|
||||||
"gfx-hal",
|
"gfx-hal",
|
||||||
"log",
|
"log",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"peek-poke 0.2.0 (git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075)",
|
||||||
"rendy-descriptor",
|
"rendy-descriptor",
|
||||||
"rendy-memory",
|
"rendy-memory",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -151,7 +151,7 @@ use tendril::stream::LossyDecoder;
|
||||||
use tendril::{StrTendril, TendrilSink};
|
use tendril::{StrTendril, TendrilSink};
|
||||||
use time::{Duration, Timespec, Tm};
|
use time::{Duration, Timespec, Tm};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use webgpu::{WebGPU, WebGPUAdapter, WebGPUBuffer, WebGPUDevice};
|
use webgpu::{WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice};
|
||||||
use webrender_api::{DocumentId, ImageKey};
|
use webrender_api::{DocumentId, ImageKey};
|
||||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
|
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
|
||||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||||
|
@ -530,6 +530,7 @@ unsafe_no_jsmanaged_fields!(WebGPU);
|
||||||
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
|
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
|
||||||
unsafe_no_jsmanaged_fields!(WebGPUDevice);
|
unsafe_no_jsmanaged_fields!(WebGPUDevice);
|
||||||
unsafe_no_jsmanaged_fields!(WebGPUBuffer);
|
unsafe_no_jsmanaged_fields!(WebGPUBuffer);
|
||||||
|
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
|
||||||
unsafe_no_jsmanaged_fields!(GPUBufferState);
|
unsafe_no_jsmanaged_fields!(GPUBufferState);
|
||||||
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
||||||
unsafe_no_jsmanaged_fields!(MediaList);
|
unsafe_no_jsmanaged_fields!(MediaList);
|
||||||
|
|
75
components/script/dom/gpubindgrouplayout.rs
Normal file
75
components/script/dom/gpubindgrouplayout.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* 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::GPUBindGroupLayoutBinding::{
|
||||||
|
self, GPUBindGroupLayoutBindings, GPUBindGroupLayoutMethods,
|
||||||
|
};
|
||||||
|
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::{WebGPU, WebGPUBindGroupLayout};
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct GPUBindGroupLayout {
|
||||||
|
reflector_: Reflector,
|
||||||
|
label: DomRefCell<Option<DOMString>>,
|
||||||
|
bind_group_layout: WebGPUBindGroupLayout,
|
||||||
|
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||||
|
bindings: Vec<GPUBindGroupLayoutBindings>,
|
||||||
|
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||||
|
channel: WebGPU,
|
||||||
|
valid: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GPUBindGroupLayout {
|
||||||
|
fn new_inherited(
|
||||||
|
channel: WebGPU,
|
||||||
|
bind_group_layout: WebGPUBindGroupLayout,
|
||||||
|
bindings: Vec<GPUBindGroupLayoutBindings>,
|
||||||
|
valid: bool,
|
||||||
|
) -> GPUBindGroupLayout {
|
||||||
|
Self {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
channel,
|
||||||
|
label: DomRefCell::new(None),
|
||||||
|
bind_group_layout,
|
||||||
|
bindings,
|
||||||
|
valid: Cell::new(valid),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
channel: WebGPU,
|
||||||
|
bind_group_layout: WebGPUBindGroupLayout,
|
||||||
|
bindings: Vec<GPUBindGroupLayoutBindings>,
|
||||||
|
valid: bool,
|
||||||
|
) -> DomRoot<GPUBindGroupLayout> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(GPUBindGroupLayout::new_inherited(
|
||||||
|
channel,
|
||||||
|
bind_group_layout,
|
||||||
|
bindings,
|
||||||
|
valid,
|
||||||
|
)),
|
||||||
|
global,
|
||||||
|
GPUBindGroupLayoutBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GPUBindGroupLayoutMethods for GPUBindGroupLayout {
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,10 @@
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
|
||||||
|
GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType,
|
||||||
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
|
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
|
||||||
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
|
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||||
|
@ -15,6 +19,7 @@ use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::gpuadapter::GPUAdapter;
|
use crate::dom::gpuadapter::GPUAdapter;
|
||||||
|
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
|
||||||
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
|
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::JSContext as SafeJSContext;
|
use crate::script_runtime::JSContext as SafeJSContext;
|
||||||
|
@ -23,7 +28,9 @@ use ipc_channel::ipc;
|
||||||
use js::jsapi::{Heap, JSObject};
|
use js::jsapi::{Heap, JSObject};
|
||||||
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
|
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
|
||||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ptr::{self, NonNull};
|
use std::ptr::{self, NonNull};
|
||||||
|
use webgpu::wgpu::binding_model::{BindGroupLayoutBinding, BindingType, ShaderStage};
|
||||||
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
|
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
|
||||||
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
|
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
|
||||||
|
|
||||||
|
@ -229,4 +236,177 @@ impl GPUDeviceMethods for GPUDevice {
|
||||||
self.resolve_create_buffer_mapped(cx, buffer, array_buffer, wgpu_descriptor, valid)
|
self.resolve_create_buffer_mapped(cx, buffer, array_buffer, wgpu_descriptor, valid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout
|
||||||
|
fn CreateBindGroupLayout(
|
||||||
|
&self,
|
||||||
|
descriptor: &GPUBindGroupLayoutDescriptor,
|
||||||
|
) -> DomRoot<GPUBindGroupLayout> {
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct MaxLimits {
|
||||||
|
max_uniform_buffers_per_shader_stage: i32,
|
||||||
|
max_storage_buffers_per_shader_stage: i32,
|
||||||
|
max_sampled_textures_per_shader_stage: i32,
|
||||||
|
max_storage_textures_per_shader_stage: i32,
|
||||||
|
max_samplers_per_shader_stage: i32,
|
||||||
|
}
|
||||||
|
let mut storeBindings = HashSet::new();
|
||||||
|
// TODO: We should have these limits on device creation
|
||||||
|
let limits = GPULimits::empty();
|
||||||
|
|
||||||
|
let mut validation_map = HashMap::new();
|
||||||
|
let maxLimits = MaxLimits {
|
||||||
|
max_uniform_buffers_per_shader_stage: limits.maxUniformBuffersPerShaderStage as i32,
|
||||||
|
max_storage_buffers_per_shader_stage: limits.maxStorageBuffersPerShaderStage as i32,
|
||||||
|
max_sampled_textures_per_shader_stage: limits.maxSampledTexturesPerShaderStage as i32,
|
||||||
|
max_storage_textures_per_shader_stage: limits.maxStorageTexturesPerShaderStage as i32,
|
||||||
|
max_samplers_per_shader_stage: limits.maxSamplersPerShaderStage as i32,
|
||||||
|
};
|
||||||
|
validation_map.insert(
|
||||||
|
webgpu::wgpu::binding_model::ShaderStage::VERTEX,
|
||||||
|
maxLimits.clone(),
|
||||||
|
);
|
||||||
|
validation_map.insert(
|
||||||
|
webgpu::wgpu::binding_model::ShaderStage::FRAGMENT,
|
||||||
|
maxLimits.clone(),
|
||||||
|
);
|
||||||
|
validation_map.insert(
|
||||||
|
webgpu::wgpu::binding_model::ShaderStage::COMPUTE,
|
||||||
|
maxLimits.clone(),
|
||||||
|
);
|
||||||
|
let mut max_dynamic_uniform_buffers_per_pipeline_layout =
|
||||||
|
limits.maxDynamicUniformBuffersPerPipelineLayout as i32;
|
||||||
|
let mut max_dynamic_storage_buffers_per_pipeline_layout =
|
||||||
|
limits.maxDynamicStorageBuffersPerPipelineLayout as i32;
|
||||||
|
let mut valid = true;
|
||||||
|
|
||||||
|
let bindings = descriptor
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|bind| {
|
||||||
|
// TODO: binding must be >= 0
|
||||||
|
storeBindings.insert(bind.binding);
|
||||||
|
let visibility = match ShaderStage::from_bits(bind.visibility) {
|
||||||
|
Some(visibility) => visibility,
|
||||||
|
None => {
|
||||||
|
valid = false;
|
||||||
|
ShaderStage::from_bits(0).unwrap()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let ty = match bind.type_ {
|
||||||
|
GPUBindingType::Uniform_buffer => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_uniform_buffers_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
max_dynamic_uniform_buffers_per_pipeline_layout -= 1;
|
||||||
|
};
|
||||||
|
BindingType::UniformBuffer
|
||||||
|
},
|
||||||
|
GPUBindingType::Storage_buffer => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_storage_buffers_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
|
||||||
|
};
|
||||||
|
BindingType::StorageBuffer
|
||||||
|
},
|
||||||
|
GPUBindingType::Readonly_storage_buffer => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_storage_buffers_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
|
||||||
|
};
|
||||||
|
BindingType::ReadonlyStorageBuffer
|
||||||
|
},
|
||||||
|
GPUBindingType::Sampled_texture => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_sampled_textures_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
valid = false
|
||||||
|
};
|
||||||
|
BindingType::SampledTexture
|
||||||
|
},
|
||||||
|
GPUBindingType::Storage_texture => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_storage_textures_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
valid = false
|
||||||
|
};
|
||||||
|
BindingType::StorageTexture
|
||||||
|
},
|
||||||
|
GPUBindingType::Sampler => {
|
||||||
|
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||||
|
limit.max_samplers_per_shader_stage -= 1;
|
||||||
|
}
|
||||||
|
if bind.hasDynamicOffset {
|
||||||
|
valid = false
|
||||||
|
};
|
||||||
|
BindingType::Sampler
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
BindGroupLayoutBinding {
|
||||||
|
binding: bind.binding,
|
||||||
|
visibility,
|
||||||
|
ty,
|
||||||
|
dynamic: bind.hasDynamicOffset,
|
||||||
|
multisampled: bind.multisampled,
|
||||||
|
texture_dimension: webgpu::wgpu::resource::TextureViewDimension::D2, // Use as default for now
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<BindGroupLayoutBinding>>();
|
||||||
|
|
||||||
|
// bindings are unique
|
||||||
|
valid &= storeBindings.len() == bindings.len();
|
||||||
|
|
||||||
|
// Ensure that values do not exceed the max limit for each ShaderStage.
|
||||||
|
valid &= validation_map.values().all(|stage| {
|
||||||
|
stage.max_uniform_buffers_per_shader_stage >= 0 &&
|
||||||
|
stage.max_storage_buffers_per_shader_stage >= 0 &&
|
||||||
|
stage.max_sampled_textures_per_shader_stage >= 0 &&
|
||||||
|
stage.max_storage_textures_per_shader_stage >= 0 &&
|
||||||
|
stage.max_samplers_per_shader_stage >= 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// DynamicValues does not exceed the max limit for the pipeline
|
||||||
|
valid &= max_dynamic_uniform_buffers_per_pipeline_layout >= 0 &&
|
||||||
|
max_dynamic_storage_buffers_per_pipeline_layout >= 0;
|
||||||
|
|
||||||
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
if let Some(window) = self.global().downcast::<Window>() {
|
||||||
|
let id = window
|
||||||
|
.Navigator()
|
||||||
|
.create_bind_group_layout_id(self.device.0.backend());
|
||||||
|
self.channel
|
||||||
|
.0
|
||||||
|
.send(WebGPURequest::CreateBindGroupLayout(
|
||||||
|
sender,
|
||||||
|
self.device,
|
||||||
|
id,
|
||||||
|
bindings.clone(),
|
||||||
|
))
|
||||||
|
.expect("Failed to create WebGPU BindGroupLayout");
|
||||||
|
}
|
||||||
|
let bgl = receiver.recv().unwrap();
|
||||||
|
|
||||||
|
let binds = descriptor
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|bind| GPUBindGroupLayoutBindings {
|
||||||
|
binding: bind.binding,
|
||||||
|
hasDynamicOffset: bind.hasDynamicOffset,
|
||||||
|
multisampled: bind.multisampled,
|
||||||
|
type_: bind.type_,
|
||||||
|
visibility: bind.visibility,
|
||||||
|
//texture_dimension: bind.texture_dimension
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
11
components/script/dom/gpushaderstage.rs
Normal file
11
components/script/dom/gpushaderstage.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 GPUShaderStage {
|
||||||
|
reflector_: Reflector,
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use webgpu::wgpu::{
|
use webgpu::wgpu::{
|
||||||
hub::IdentityManager,
|
hub::IdentityManager,
|
||||||
id::{AdapterId, BufferId, DeviceId},
|
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId},
|
||||||
Backend,
|
Backend,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ pub struct IdentityHub {
|
||||||
adapters: IdentityManager,
|
adapters: IdentityManager,
|
||||||
devices: IdentityManager,
|
devices: IdentityManager,
|
||||||
buffers: IdentityManager,
|
buffers: IdentityManager,
|
||||||
|
bind_group_layouts: IdentityManager,
|
||||||
backend: Backend,
|
backend: Backend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ impl IdentityHub {
|
||||||
adapters: IdentityManager::default(),
|
adapters: IdentityManager::default(),
|
||||||
devices: IdentityManager::default(),
|
devices: IdentityManager::default(),
|
||||||
buffers: IdentityManager::default(),
|
buffers: IdentityManager::default(),
|
||||||
|
bind_group_layouts: IdentityManager::default(),
|
||||||
backend,
|
backend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,9 +37,13 @@ impl IdentityHub {
|
||||||
self.devices.alloc(self.backend)
|
self.devices.alloc(self.backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_buffer_id(&mut self) -> BufferId {
|
fn create_buffer_id(&mut self) -> BufferId {
|
||||||
self.buffers.alloc(self.backend)
|
self.buffers.alloc(self.backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId {
|
||||||
|
self.bind_group_layouts.alloc(self.backend)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -119,4 +125,18 @@ impl Identities {
|
||||||
_ => self.dummy_hub.create_buffer_id(),
|
_ => self.dummy_hub.create_buffer_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId {
|
||||||
|
match backend {
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
|
Backend::Vulkan => self.vk_hub.create_bind_group_layout_id(),
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
Backend::Dx12 => self.dx12_hub.create_bind_group_layout_id(),
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
Backend::Dx11 => self.dx11_hub.create_bind_group_layout_id(),
|
||||||
|
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||||
|
Backend::Metal => self.metal_hub.create_bind_group_layout_id(),
|
||||||
|
_ => self.dummy_hub.create_bind_group_layout_id(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,9 +318,11 @@ pub mod gamepadlist;
|
||||||
pub mod globalscope;
|
pub mod globalscope;
|
||||||
pub mod gpu;
|
pub mod gpu;
|
||||||
pub mod gpuadapter;
|
pub mod gpuadapter;
|
||||||
|
pub mod gpubindgrouplayout;
|
||||||
pub mod gpubuffer;
|
pub mod gpubuffer;
|
||||||
pub mod gpubufferusage;
|
pub mod gpubufferusage;
|
||||||
pub mod gpudevice;
|
pub mod gpudevice;
|
||||||
|
pub mod gpushaderstage;
|
||||||
pub mod hashchangeevent;
|
pub mod hashchangeevent;
|
||||||
pub mod headers;
|
pub mod headers;
|
||||||
pub mod history;
|
pub mod history;
|
||||||
|
|
|
@ -28,7 +28,7 @@ use smallvec::SmallVec;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use webgpu::wgpu::{
|
use webgpu::wgpu::{
|
||||||
id::{AdapterId, BufferId, DeviceId},
|
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId},
|
||||||
Backend,
|
Backend,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,6 +88,12 @@ impl Navigator {
|
||||||
pub fn create_buffer_id(&self, backend: Backend) -> BufferId {
|
pub fn create_buffer_id(&self, backend: Backend) -> BufferId {
|
||||||
self.gpu_id_hub.borrow_mut().create_buffer_id(backend)
|
self.gpu_id_hub.borrow_mut().create_buffer_id(backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId {
|
||||||
|
self.gpu_id_hub
|
||||||
|
.borrow_mut()
|
||||||
|
.create_bind_group_layout_id(backend)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatorMethods for Navigator {
|
impl NavigatorMethods for Navigator {
|
||||||
|
|
34
components/script/dom/webidls/GPUBindGroupLayout.webidl
Normal file
34
components/script/dom/webidls/GPUBindGroupLayout.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/#gpubindgrouplayout
|
||||||
|
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
|
||||||
|
interface GPUBindGroupLayout {
|
||||||
|
};
|
||||||
|
GPUBindGroupLayout includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required sequence<GPUBindGroupLayoutBindings> bindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: Servo codegen doesn't like the name `GPUBindGroupLayoutBinding` because it's already occupied
|
||||||
|
// dictionary GPUBindGroupLayoutBinding {
|
||||||
|
dictionary GPUBindGroupLayoutBindings {
|
||||||
|
required unsigned long binding;
|
||||||
|
required GPUShaderStageFlags visibility;
|
||||||
|
required GPUBindingType type;
|
||||||
|
//GPUTextureViewDimension textureDimension = "2d";
|
||||||
|
//GPUTextureComponentType textureComponentType = "float";
|
||||||
|
boolean multisampled = false;
|
||||||
|
boolean hasDynamicOffset = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUBindingType {
|
||||||
|
"uniform-buffer",
|
||||||
|
"storage-buffer",
|
||||||
|
"readonly-storage-buffer",
|
||||||
|
"sampler",
|
||||||
|
"sampled-texture",
|
||||||
|
"storage-texture"
|
||||||
|
};
|
|
@ -11,12 +11,12 @@ interface GPUDevice : EventTarget {
|
||||||
|
|
||||||
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
|
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
|
||||||
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
|
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
|
||||||
/*Promise<GPUMappedBuffer> createBufferMappedAsync(GPUBufferDescriptor descriptor);
|
//Promise<GPUMappedBuffer> createBufferMappedAsync(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);
|
||||||
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
|
/*GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
|
||||||
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
|
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
|
||||||
|
|
||||||
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
|
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
|
||||||
|
|
13
components/script/dom/webidls/GPUShaderStage.webidl
Normal file
13
components/script/dom/webidls/GPUShaderStage.webidl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* 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/#typedefdef-gpushaderstageflags
|
||||||
|
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
|
||||||
|
interface GPUShaderStage {
|
||||||
|
const GPUShaderStageFlags VERTEX = 0x1;
|
||||||
|
const GPUShaderStageFlags FRAGMENT = 0x2;
|
||||||
|
const GPUShaderStageFlags COMPUTE = 0x4;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned long GPUShaderStageFlags;
|
|
@ -48,6 +48,12 @@ pub enum WebGPURequest {
|
||||||
wgpu::id::BufferId,
|
wgpu::id::BufferId,
|
||||||
wgpu::resource::BufferDescriptor,
|
wgpu::resource::BufferDescriptor,
|
||||||
),
|
),
|
||||||
|
CreateBindGroupLayout(
|
||||||
|
IpcSender<WebGPUBindGroupLayout>,
|
||||||
|
WebGPUDevice,
|
||||||
|
wgpu::id::BindGroupLayoutId,
|
||||||
|
Vec<wgpu::binding_model::BindGroupLayoutBinding>,
|
||||||
|
),
|
||||||
UnmapBuffer(WebGPUBuffer),
|
UnmapBuffer(WebGPUBuffer),
|
||||||
DestroyBuffer(WebGPUBuffer),
|
DestroyBuffer(WebGPUBuffer),
|
||||||
}
|
}
|
||||||
|
@ -220,6 +226,22 @@ impl WGPU {
|
||||||
let global = &self.global;
|
let global = &self.global;
|
||||||
gfx_select!(buffer.0 => global.buffer_destroy(buffer.0));
|
gfx_select!(buffer.0 => global.buffer_destroy(buffer.0));
|
||||||
},
|
},
|
||||||
|
WebGPURequest::CreateBindGroupLayout(sender, device, id, bindings) => {
|
||||||
|
let global = &self.global;
|
||||||
|
let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor {
|
||||||
|
bindings: bindings.as_ptr(),
|
||||||
|
bindings_length: bindings.len(),
|
||||||
|
};
|
||||||
|
let bgl_id = gfx_select!(id => global.device_create_bind_group_layout(device.0, &descriptor, id));
|
||||||
|
let bgl = WebGPUBindGroupLayout(bgl_id);
|
||||||
|
|
||||||
|
if let Err(e) = sender.send(bgl) {
|
||||||
|
warn!(
|
||||||
|
"Failed to send response to WebGPURequest::CreateBufferMapped ({})",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
WebGPURequest::Exit(sender) => {
|
WebGPURequest::Exit(sender) => {
|
||||||
self.deinit();
|
self.deinit();
|
||||||
if let Err(e) = sender.send(()) {
|
if let Err(e) = sender.send(()) {
|
||||||
|
@ -250,3 +272,4 @@ macro_rules! webgpu_resource {
|
||||||
webgpu_resource!(WebGPUAdapter, wgpu::id::AdapterId);
|
webgpu_resource!(WebGPUAdapter, wgpu::id::AdapterId);
|
||||||
webgpu_resource!(WebGPUDevice, wgpu::id::DeviceId);
|
webgpu_resource!(WebGPUDevice, wgpu::id::DeviceId);
|
||||||
webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
|
webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
|
||||||
|
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
|
||||||
|
|
|
@ -33,6 +33,8 @@ packages = [
|
||||||
"gleam",
|
"gleam",
|
||||||
"mach",
|
"mach",
|
||||||
"nix",
|
"nix",
|
||||||
|
"peek-poke",
|
||||||
|
"peek-poke-derive",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
|
|
||||||
# https://github.com/servo/servo/pull/23288#issuecomment-494687746
|
# https://github.com/servo/servo/pull/23288#issuecomment-494687746
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue