Auto merge of #26984 - kunalmohan:gpu-bind-group, r=kvark

Add GPUSampler and GPUTextureView to BindingResources and update wgpu-core

<!-- Please describe your changes on the following line: -->
This also completes validation for `GPUBindGroup` and `GPUBindGroupLayout`.
`entry_map` is stored in `GPUBindGroupLayout` for validating `createBindGroup()`.

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-22 13:40:29 -04:00 committed by GitHub
commit 77a75403db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 313 additions and 396 deletions

23
Cargo.lock generated
View file

@ -1787,9 +1787,9 @@ dependencies = [
[[package]]
name = "gfx-backend-dx12"
version = "0.5.4"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69af46bd4fc5479cc7d90bf77ccee0da5dd88d4d27b87986a582f9eec97d02d4"
checksum = "6e1a979a793023717bcaa7511c8cbb449bab550c093737c98674a659a2bbaf73"
dependencies = [
"bitflags",
"d3d12",
@ -1815,9 +1815,9 @@ dependencies = [
[[package]]
name = "gfx-backend-metal"
version = "0.5.2"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "205f3ca8e74ed814ea2c0206d47d8925077673cab2e21f9b12d48ff781cf87ee"
checksum = "412a1e0e53e9e325a7c2e0316f1a4e8a14cbe8d8bfb5f030bc3895692f8a8254"
dependencies = [
"arrayvec 0.5.1",
"bitflags",
@ -1842,9 +1842,9 @@ dependencies = [
[[package]]
name = "gfx-backend-vulkan"
version = "0.5.6"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45ff36feae801fa23d29acd74082603a0145a697a23595757dd4e78828ab33da"
checksum = "04af900c2597587b35e801e9d3f91fd8078cc06067421a22caa640ad2b1bc53e"
dependencies = [
"arrayvec 0.5.1",
"ash",
@ -1872,9 +1872,9 @@ dependencies = [
[[package]]
name = "gfx-hal"
version = "0.5.0"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc96180204064c9493e0fe4a9efeb721e0ac59fe8e1906d0c659142a93114fb1"
checksum = "f13e8fd6aaa8f50146b9519999432e097da43466749d8863c53409322c705339"
dependencies = [
"bitflags",
"raw-window-handle",
@ -1883,8 +1883,7 @@ dependencies = [
[[package]]
name = "gfx-memory"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2eed6cda674d9cd4d92229102dbd544292124533d236904f987e9afab456137"
source = "git+https://github.com/gfx-rs/gfx-extras?rev=438353c3f75368c12024ad2fc03cbeb15f351fd9#438353c3f75368c12024ad2fc03cbeb15f351fd9"
dependencies = [
"fxhash",
"gfx-hal",
@ -6563,7 +6562,7 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.5.0"
source = "git+https://github.com/gfx-rs/wgpu#ac9587e9ced5b043abad68e260cb8c9e812cffb5"
source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
dependencies = [
"arrayvec 0.5.1",
"bitflags",
@ -6592,7 +6591,7 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "0.5.0"
source = "git+https://github.com/gfx-rs/wgpu#ac9587e9ced5b043abad68e260cb8c9e812cffb5"
source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
dependencies = [
"bitflags",
"peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -165,10 +165,10 @@ use tendril::{StrTendril, TendrilSink};
use time::{Duration, Timespec, Tm};
use uuid::Uuid;
use webgpu::{
wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout,
WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
WebGPUTexture, WebGPUTextureView,
wgpu::command::RawPass, wgpu::id, WebGPU, WebGPUAdapter, WebGPUBindGroup,
WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder,
WebGPUComputePipeline, WebGPUDevice, WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline,
WebGPUSampler, WebGPUShaderModule, WebGPUTexture, WebGPUTextureView,
};
use webrender_api::{DocumentId, ExternalImageId, ImageKey};
use webxr_api::SwapChainId as WebXRSwapChainId;
@ -581,7 +581,7 @@ unsafe_no_jsmanaged_fields!(WebGPUContextId);
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
unsafe_no_jsmanaged_fields!(Option<RawPass>);
unsafe_no_jsmanaged_fields!(Option<RawPass<id::CommandEncoderId>>);
unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(GPUCommandEncoderState);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);

View file

@ -84,7 +84,9 @@ impl GPUAdapterMethods for GPUAdapter {
extensions: wgt::Extensions::empty(),
limits: wgt::Limits {
max_bind_groups: descriptor.limits.maxBindGroups,
..Default::default()
},
shader_validation: true,
};
let id = self
.global()

View file

@ -5,34 +5,52 @@
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use dom_struct::dom_struct;
use std::cell::Cell;
use webgpu::WebGPUBindGroup;
use webgpu::{WebGPUBindGroup, WebGPUDevice};
#[dom_struct]
pub struct GPUBindGroup {
reflector_: Reflector,
label: DomRefCell<Option<DOMString>>,
bind_group: WebGPUBindGroup,
device: WebGPUDevice,
layout: Dom<GPUBindGroupLayout>,
valid: Cell<bool>,
}
impl GPUBindGroup {
fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> Self {
fn new_inherited(
bind_group: WebGPUBindGroup,
device: WebGPUDevice,
valid: bool,
layout: &GPUBindGroupLayout,
) -> Self {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(None),
bind_group,
device,
valid: Cell::new(valid),
layout: Dom::from_ref(layout),
}
}
pub fn new(global: &GlobalScope, bind_group: WebGPUBindGroup, valid: bool) -> DomRoot<Self> {
pub fn new(
global: &GlobalScope,
bind_group: WebGPUBindGroup,
device: WebGPUDevice,
valid: bool,
layout: &GPUBindGroupLayout,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUBindGroup::new_inherited(bind_group, valid)),
Box::new(GPUBindGroup::new_inherited(
bind_group, device, valid, layout,
)),
global,
)
}

View file

@ -3,60 +3,40 @@
* 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::{
GPUBindGroupLayoutEntry, GPUBindGroupLayoutMethods,
};
use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::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};
use 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<GPUBindGroupLayoutEntry>,
#[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<GPUBindGroupLayoutEntry>,
valid: bool,
) -> Self {
fn new_inherited(bind_group_layout: WebGPUBindGroupLayout, valid: bool) -> Self {
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<GPUBindGroupLayoutEntry>,
valid: bool,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUBindGroupLayout::new_inherited(
channel,
bind_group_layout,
bindings,
valid,
)),
Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout, valid)),
global,
)
}
@ -70,10 +50,6 @@ impl GPUBindGroupLayout {
pub fn id(&self) -> WebGPUBindGroupLayout {
self.bind_group_layout
}
pub fn bindings(&self) -> &[GPUBindGroupLayoutEntry] {
&self.bindings
}
}
impl GPUBindGroupLayoutMethods for GPUBindGroupLayout {

View file

@ -110,7 +110,7 @@ impl GPUBuffer {
self.state.borrow()
}
pub fn valid(&self) -> bool {
pub fn is_valid(&self) -> bool {
self.valid.get()
}
}

View file

@ -240,8 +240,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
None => false,
};
valid &= (*self.state.borrow() == GPUCommandEncoderState::Open) &&
source.valid() &&
destination.valid() &
source.is_valid() &&
destination.is_valid() &
!(size & BUFFER_COPY_ALIGN_MASK == 0) &
!(source_offset & BUFFER_COPY_ALIGN_MASK == 0) &
!(destination_offset & BUFFER_COPY_ALIGN_MASK == 0) &

View file

@ -22,6 +22,7 @@ use webgpu::{
},
RawPass,
},
wgpu::id,
WebGPU, WebGPURequest,
};
@ -32,7 +33,7 @@ pub struct GPUComputePassEncoder {
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
raw_pass: DomRefCell<Option<RawPass>>,
raw_pass: DomRefCell<Option<RawPass<id::CommandEncoderId>>>,
command_encoder: Dom<GPUCommandEncoder>,
}

View file

@ -10,6 +10,7 @@ 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::WebGPUComputePipeline;
#[dom_struct]
@ -17,20 +18,26 @@ pub struct GPUComputePipeline {
reflector_: Reflector,
label: DomRefCell<Option<DOMString>>,
compute_pipeline: WebGPUComputePipeline,
valid: Cell<bool>,
}
impl GPUComputePipeline {
fn new_inherited(compute_pipeline: WebGPUComputePipeline) -> Self {
fn new_inherited(compute_pipeline: WebGPUComputePipeline, valid: bool) -> Self {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(None),
compute_pipeline,
valid: Cell::new(valid),
}
}
pub fn new(global: &GlobalScope, compute_pipeline: WebGPUComputePipeline) -> DomRoot<Self> {
pub fn new(
global: &GlobalScope,
compute_pipeline: WebGPUComputePipeline,
valid: bool,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUComputePipeline::new_inherited(compute_pipeline)),
Box::new(GPUComputePipeline::new_inherited(compute_pipeline, valid)),
global,
)
}

View file

@ -5,10 +5,11 @@
#![allow(unsafe_code)]
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits;
use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{
GPUBindGroupDescriptor, GPUBindingResource,
};
use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
GPUBindGroupLayoutDescriptor, GPUBindGroupLayoutEntry, GPUBindingType,
GPUBindGroupLayoutDescriptor, GPUBindingType,
};
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineDescriptor;
@ -55,12 +56,10 @@ use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject};
use js::jsval::{JSVal, ObjectValue};
use js::typedarray::{ArrayBuffer, CreateWith};
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;
use std::ptr::{self, NonNull};
use webgpu::wgpu::binding_model::{
BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding,
};
use webgpu::{self, wgpu, wgt, WebGPU, WebGPURequest};
use webgpu::wgpu::binding_model::BufferBinding;
use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest};
#[dom_struct]
pub struct GPUDevice {
@ -274,149 +273,93 @@ impl GPUDeviceMethods for GPUDevice {
&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(wgt::ShaderStage::VERTEX, maxLimits.clone());
validation_map.insert(wgt::ShaderStage::FRAGMENT, maxLimits.clone());
validation_map.insert(wgt::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
let entries = descriptor
.entries
.iter()
.map(|bind| {
// TODO: binding must be >= 0
storeBindings.insert(bind.binding);
let visibility = match wgt::ShaderStage::from_bits(bind.visibility) {
Some(visibility) => visibility,
None => {
valid = false;
wgt::ShaderStage::from_bits(0).unwrap()
},
None => wgt::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::Uniform_buffer => wgt::BindingType::UniformBuffer {
dynamic: bind.hasDynamicOffset,
min_binding_size: if bind.minBufferBindingSize == 0 {
None
} else {
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
},
},
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::Storage_buffer => wgt::BindingType::StorageBuffer {
dynamic: bind.hasDynamicOffset,
min_binding_size: if bind.minBufferBindingSize == 0 {
None
} else {
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
},
readonly: false,
},
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::Readonly_storage_buffer => wgt::BindingType::StorageBuffer {
dynamic: bind.hasDynamicOffset,
min_binding_size: if bind.minBufferBindingSize == 0 {
None
} else {
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
},
readonly: true,
},
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::Sampled_texture => wgt::BindingType::SampledTexture {
dimension: bind
.viewDimension
.map_or(wgt::TextureViewDimension::D2, |v| {
convert_texture_view_dimension(v)
}),
component_type: if let Some(c) = bind.textureComponentType {
match c {
GPUTextureComponentType::Float => wgt::TextureComponentType::Float,
GPUTextureComponentType::Sint => wgt::TextureComponentType::Sint,
GPUTextureComponentType::Uint => wgt::TextureComponentType::Uint,
}
} else {
wgt::TextureComponentType::Float
},
multisampled: bind.multisampled,
},
GPUBindingType::Readonly_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::ReadonlyStorageTexture
GPUBindingType::Readonly_storage_texture => wgt::BindingType::StorageTexture {
dimension: bind
.viewDimension
.map_or(wgt::TextureViewDimension::D2, |v| {
convert_texture_view_dimension(v)
}),
format: bind
.storageTextureFormat
.map_or(wgt::TextureFormat::Bgra8UnormSrgb, |f| {
convert_texture_format(f)
}),
readonly: true,
},
GPUBindingType::Writeonly_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::WriteonlyStorageTexture
GPUBindingType::Writeonly_storage_texture => wgt::BindingType::StorageTexture {
dimension: bind
.viewDimension
.map_or(wgt::TextureViewDimension::D2, |v| {
convert_texture_view_dimension(v)
}),
format: bind
.storageTextureFormat
.map_or(wgt::TextureFormat::Bgra8UnormSrgb, |f| {
convert_texture_format(f)
}),
readonly: true,
},
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
GPUBindingType::Sampler => wgt::BindingType::Sampler { comparison: false },
GPUBindingType::Comparison_sampler => {
wgt::BindingType::Sampler { comparison: true }
},
};
BindGroupLayoutEntry {
binding: bind.binding,
visibility,
ty,
has_dynamic_offset: bind.hasDynamicOffset,
multisampled: bind.multisampled,
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),
}
wgt::BindGroupLayoutEntry::new(bind.binding, visibility, ty)
})
.collect::<Vec<BindGroupLayoutEntry>>();
// 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;
.collect::<Vec<_>>();
let bind_group_layout_id = self
.global()
@ -428,28 +371,13 @@ impl GPUDeviceMethods for GPUDevice {
.send(WebGPURequest::CreateBindGroupLayout {
device_id: self.device.0,
bind_group_layout_id,
bindings: bindings.clone(),
entries,
})
.expect("Failed to create WebGPU BindGroupLayout");
let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id);
let binds = descriptor
.entries
.iter()
.map(|bind| GPUBindGroupLayoutEntry {
binding: bind.binding,
hasDynamicOffset: bind.hasDynamicOffset,
multisampled: bind.multisampled,
type_: bind.type_,
visibility: bind.visibility,
viewDimension: bind.viewDimension,
textureComponentType: bind.textureComponentType,
storageTextureFormat: bind.storageTextureFormat,
})
.collect::<Vec<_>>();
GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid)
GPUBindGroupLayout::new(&self.global(), bgl, true)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout
@ -457,47 +385,13 @@ impl GPUDeviceMethods for GPUDevice {
&self,
descriptor: &GPUPipelineLayoutDescriptor,
) -> DomRoot<GPUPipelineLayout> {
// TODO: We should have these limits on device creation
let limits = GPULimits::empty();
let mut bind_group_layouts = Vec::new();
let mut bgl_ids = Vec::new();
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;
descriptor.bindGroupLayouts.iter().for_each(|each| {
if each.is_valid() {
let id = each.id();
bind_group_layouts.push(id);
bgl_ids.push(id.0);
bgl_ids.push(each.id().0);
}
each.bindings().iter().for_each(|bind| {
match bind.type_ {
GPUBindingType::Uniform_buffer => {
if bind.hasDynamicOffset {
max_dynamic_uniform_buffers_per_pipeline_layout -= 1;
};
},
GPUBindingType::Storage_buffer => {
if bind.hasDynamicOffset {
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
};
},
GPUBindingType::Readonly_storage_buffer => {
if bind.hasDynamicOffset {
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
};
},
_ => {},
};
});
});
let valid = descriptor.bindGroupLayouts.len() <= limits.maxBindGroups as usize &&
descriptor.bindGroupLayouts.len() == bind_group_layouts.len() &&
max_dynamic_uniform_buffers_per_pipeline_layout >= 0 &&
max_dynamic_storage_buffers_per_pipeline_layout >= 0;
let pipeline_layout_id = self
.global()
.wgpu_id_hub()
@ -513,50 +407,41 @@ impl GPUDeviceMethods for GPUDevice {
.expect("Failed to create WebGPU PipelineLayout");
let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id);
GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid)
GPUPipelineLayout::new(&self.global(), pipeline_layout, true)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup
fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot<GPUBindGroup> {
let alignment: u64 = 256;
let mut valid = descriptor.layout.bindings().len() == descriptor.entries.len();
valid &= descriptor.entries.iter().all(|bind| {
let buffer_size = bind.resource.buffer.size();
let resource_size = bind.resource.size.unwrap_or(buffer_size);
let length = bind.resource.offset.checked_add(resource_size);
let usage = wgt::BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap();
length.is_some() &&
buffer_size >= length.unwrap() && // check buffer OOB
bind.resource.offset % alignment == 0 && // check alignment
bind.resource.offset < buffer_size && // on Vulkan offset must be less than size of buffer
descriptor.layout.bindings().iter().any(|layout_bind| {
let ty = match layout_bind.type_ {
GPUBindingType::Storage_buffer => wgt::BufferUsage::STORAGE,
// GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ,
GPUBindingType::Uniform_buffer => wgt::BufferUsage::UNIFORM,
_ => unimplemented!(),
};
// binding must be present in layout
layout_bind.binding == bind.binding &&
// binding must contain one buffer of its type
usage.contains(ty)
})
});
let bindings = descriptor
let mut valid = descriptor.layout.is_valid();
let entries = descriptor
.entries
.iter()
.map(|bind| BindGroupEntry {
binding: bind.binding,
resource: BindingResource::Buffer(BufferBinding {
buffer: bind.resource.buffer.id().0,
offset: bind.resource.offset,
size: wgt::BufferSize(
bind.resource.size.unwrap_or(bind.resource.buffer.size()),
),
}),
.map(|bind| {
(
bind.binding,
match bind.resource {
GPUBindingResource::GPUSampler(ref s) => {
valid &= s.is_valid();
WebGPUBindings::Sampler(s.id().0)
},
GPUBindingResource::GPUTextureView(ref t) => {
valid &= t.is_valid();
WebGPUBindings::TextureView(t.id().0)
},
GPUBindingResource::GPUBufferBindings(ref b) => {
valid &= b.buffer.is_valid();
WebGPUBindings::Buffer(BufferBinding {
buffer_id: b.buffer.id().0,
offset: b.offset,
size: if let Some(s) = b.size {
wgt::BufferSize(s)
} else {
wgt::BufferSize::WHOLE
},
})
},
},
)
})
.collect::<Vec<_>>();
@ -571,12 +456,18 @@ impl GPUDeviceMethods for GPUDevice {
device_id: self.device.0,
bind_group_id,
bind_group_layout_id: descriptor.layout.id().0,
bindings,
entries,
})
.expect("Failed to create WebGPU BindGroup");
let bind_group = webgpu::WebGPUBindGroup(bind_group_id);
GPUBindGroup::new(&self.global(), bind_group, valid)
GPUBindGroup::new(
&self.global(),
bind_group,
self.device,
valid,
&*descriptor.layout,
)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule
@ -611,6 +502,7 @@ impl GPUDeviceMethods for GPUDevice {
&self,
descriptor: &GPUComputePipelineDescriptor,
) -> DomRoot<GPUComputePipeline> {
let valid = descriptor.parent.layout.is_valid();
let pipeline = descriptor.parent.layout.id();
let program = descriptor.computeStage.module.id();
let entry_point = descriptor.computeStage.entryPoint.to_string();
@ -632,7 +524,7 @@ impl GPUDeviceMethods for GPUDevice {
.expect("Failed to create WebGPU ComputePipeline");
let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id);
GPUComputePipeline::new(&self.global(), compute_pipeline)
GPUComputePipeline::new(&self.global(), compute_pipeline, valid)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder
@ -740,6 +632,7 @@ impl GPUDeviceMethods for GPUDevice {
lod_max_clamp: *descriptor.lodMaxClamp,
compare: descriptor.compare.map(|c| convert_compare_function(c)),
anisotropy_clamp: None,
..Default::default()
};
self.channel
.0
@ -752,14 +645,7 @@ impl GPUDeviceMethods for GPUDevice {
let sampler = webgpu::WebGPUSampler(sampler_id);
GPUSampler::new(
&self.global(),
self.channel.clone(),
self.device,
compare_enable,
sampler,
true,
)
GPUSampler::new(&self.global(), self.device, compare_enable, sampler, true)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline
@ -767,12 +653,7 @@ impl GPUDeviceMethods for GPUDevice {
&self,
descriptor: &GPURenderPipelineDescriptor,
) -> DomRoot<GPURenderPipeline> {
let mut valid = descriptor.parent.layout.is_valid();
valid &= descriptor.colorStates.len() <= wgpu::device::MAX_COLOR_TARGETS;
if descriptor.alphaToCoverageEnabled {
valid &= descriptor.sampleCount > 1;
}
let valid = descriptor.parent.layout.is_valid();
let vertex_module = descriptor.vertexStage.module.id().0;
let vertex_entry_point = descriptor.vertexStage.entryPoint.to_string();
let (fragment_module, fragment_entry_point) = match descriptor.fragmentStage {
@ -813,10 +694,7 @@ impl GPUDeviceMethods for GPUDevice {
color_blend: convert_blend_descriptor(&state.colorBlend),
write_mask: match wgt::ColorWrite::from_bits(state.writeMask) {
Some(mask) => mask,
None => {
valid = false;
wgt::ColorWrite::empty()
},
None => wgt::ColorWrite::empty(),
},
})
.collect::<ArrayVec<_>>();

View file

@ -10,26 +10,20 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use std::cell::Cell;
use webgpu::{WebGPUBindGroupLayout, WebGPUPipelineLayout};
use webgpu::WebGPUPipelineLayout;
#[dom_struct]
pub struct GPUPipelineLayout {
reflector_: Reflector,
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
label: DomRefCell<Option<DOMString>>,
pipeline_layout: WebGPUPipelineLayout,
valid: Cell<bool>,
}
impl GPUPipelineLayout {
fn new_inherited(
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
pipeline_layout: WebGPUPipelineLayout,
valid: bool,
) -> Self {
fn new_inherited(pipeline_layout: WebGPUPipelineLayout, valid: bool) -> Self {
Self {
reflector_: Reflector::new(),
bind_group_layouts,
label: DomRefCell::new(None),
pipeline_layout,
valid: Cell::new(valid),
@ -38,16 +32,11 @@ impl GPUPipelineLayout {
pub fn new(
global: &GlobalScope,
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
pipeline_layout: WebGPUPipelineLayout,
valid: bool,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUPipelineLayout::new_inherited(
bind_group_layouts,
pipeline_layout,
valid,
)),
Box::new(GPUPipelineLayout::new_inherited(pipeline_layout, valid)),
global,
)
}

View file

@ -19,6 +19,7 @@ use crate::dom::gpurenderpipeline::GPURenderPipeline;
use dom_struct::dom_struct;
use webgpu::{
wgpu::command::{render_ffi as wgpu_render, RawPass},
wgpu::id,
wgt, WebGPU, WebGPURequest,
};
@ -29,12 +30,16 @@ pub struct GPURenderPassEncoder {
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
raw_pass: DomRefCell<Option<RawPass>>,
raw_pass: DomRefCell<Option<RawPass<id::CommandEncoderId>>>,
command_encoder: Dom<GPUCommandEncoder>,
}
impl GPURenderPassEncoder {
fn new_inherited(channel: WebGPU, raw_pass: RawPass, parent: &GPUCommandEncoder) -> Self {
fn new_inherited(
channel: WebGPU,
raw_pass: RawPass<id::CommandEncoderId>,
parent: &GPUCommandEncoder,
) -> Self {
Self {
channel,
reflector_: Reflector::new(),
@ -47,7 +52,7 @@ impl GPURenderPassEncoder {
pub fn new(
global: &GlobalScope,
channel: WebGPU,
raw_pass: RawPass,
raw_pass: RawPass<id::CommandEncoderId>,
parent: &GPUCommandEncoder,
) -> DomRoot<Self> {
reflect_dom_object(

View file

@ -10,13 +10,11 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use std::cell::Cell;
use webgpu::{WebGPU, WebGPUDevice, WebGPUSampler};
use webgpu::{WebGPUDevice, WebGPUSampler};
#[dom_struct]
pub struct GPUSampler {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
device: WebGPUDevice,
compare_enable: bool,
@ -26,7 +24,6 @@ pub struct GPUSampler {
impl GPUSampler {
fn new_inherited(
channel: WebGPU,
device: WebGPUDevice,
compare_enable: bool,
sampler: WebGPUSampler,
@ -34,7 +31,6 @@ impl GPUSampler {
) -> Self {
Self {
reflector_: Reflector::new(),
channel,
label: DomRefCell::new(None),
valid: Cell::new(valid),
device,
@ -45,7 +41,6 @@ impl GPUSampler {
pub fn new(
global: &GlobalScope,
channel: WebGPU,
device: WebGPUDevice,
compare_enable: bool,
sampler: WebGPUSampler,
@ -53,7 +48,6 @@ impl GPUSampler {
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUSampler::new_inherited(
channel,
device,
compare_enable,
sampler,
@ -64,6 +58,16 @@ impl GPUSampler {
}
}
impl GPUSampler {
pub fn id(&self) -> WebGPUSampler {
self.sampler
}
pub fn is_valid(&self) -> bool {
self.valid.get()
}
}
impl GPUSamplerMethods for GPUSampler {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<DOMString> {

View file

@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{
GPUExtent3DDict, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods,
};
use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{
GPUTextureAspect, GPUTextureViewDescriptor,
GPUTextureAspect, GPUTextureViewDescriptor, GPUTextureViewDimension,
};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot;
@ -122,23 +122,28 @@ impl GPUTextureMethods for GPUTexture {
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-createview
fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot<GPUTextureView> {
let dimension = if let Some(d) = descriptor.dimension {
d
} else {
match self.dimension {
GPUTextureDimension::_1d => GPUTextureViewDimension::_1d,
GPUTextureDimension::_2d => {
if self.texture_size.depth > 1 && descriptor.arrayLayerCount == 0 {
GPUTextureViewDimension::_2d_array
} else {
GPUTextureViewDimension::_2d
}
},
GPUTextureDimension::_3d => GPUTextureViewDimension::_3d,
}
};
let format = descriptor.format.unwrap_or(self.format);
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,
},
},
format: convert_texture_format(format),
dimension: convert_texture_view_dimension(dimension),
aspect: match descriptor.aspect {
GPUTextureAspect::All => wgt::TextureAspect::All,
GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
@ -175,7 +180,7 @@ impl GPUTextureMethods for GPUTexture {
let texture_view = WebGPUTextureView(texture_view_id);
GPUTextureView::new(&self.global(), texture_view, self.device, true)
GPUTextureView::new(&self.global(), texture_view, &self, self.valid.get())
}
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy

View file

@ -5,27 +5,32 @@
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::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gputexture::GPUTexture;
use dom_struct::dom_struct;
use std::cell::Cell;
use webgpu::{WebGPUDevice, WebGPUTextureView};
use webgpu::WebGPUTextureView;
#[dom_struct]
pub struct GPUTextureView {
reflector_: Reflector,
label: DomRefCell<Option<DOMString>>,
texture_view: WebGPUTextureView,
device: WebGPUDevice,
texture: Dom<GPUTexture>,
valid: Cell<bool>,
}
impl GPUTextureView {
fn new_inherited(texture_view: WebGPUTextureView, device: WebGPUDevice, valid: bool) -> Self {
fn new_inherited(
texture_view: WebGPUTextureView,
texture: &GPUTexture,
valid: bool,
) -> GPUTextureView {
Self {
reflector_: Reflector::new(),
device,
texture: Dom::from_ref(texture),
label: DomRefCell::new(None),
texture_view,
valid: Cell::new(valid),
@ -35,11 +40,11 @@ impl GPUTextureView {
pub fn new(
global: &GlobalScope,
texture_view: WebGPUTextureView,
device: WebGPUDevice,
texture: &GPUTexture,
valid: bool,
) -> DomRoot<Self> {
) -> DomRoot<GPUTextureView> {
reflect_dom_object(
Box::new(GPUTextureView::new_inherited(texture_view, device, valid)),
Box::new(GPUTextureView::new_inherited(texture_view, texture, valid)),
global,
)
}
@ -49,6 +54,10 @@ impl GPUTextureView {
pub fn id(&self) -> WebGPUTextureView {
self.texture_view
}
pub fn is_valid(&self) -> bool {
self.valid.get()
}
}
impl GPUTextureViewMethods for GPUTextureView {

View file

@ -24,12 +24,13 @@ enum GPUExtensionName {
};
dictionary GPULimits {
unsigned long maxBindGroups = 4;
unsigned long maxDynamicUniformBuffersPerPipelineLayout = 8;
unsigned long maxDynamicStorageBuffersPerPipelineLayout = 4;
unsigned long maxSampledTexturesPerShaderStage = 16;
unsigned long maxSamplersPerShaderStage = 16;
unsigned long maxStorageBuffersPerShaderStage = 4;
unsigned long maxStorageTexturesPerShaderStage = 4;
unsigned long maxUniformBuffersPerShaderStage = 12;
GPUSize32 maxBindGroups = 4;
GPUSize32 maxDynamicUniformBuffersPerPipelineLayout = 8;
GPUSize32 maxDynamicStorageBuffersPerPipelineLayout = 4;
GPUSize32 maxSampledTexturesPerShaderStage = 16;
GPUSize32 maxSamplersPerShaderStage = 16;
GPUSize32 maxStorageBuffersPerShaderStage = 4;
GPUSize32 maxStorageTexturesPerShaderStage = 4;
GPUSize32 maxUniformBuffersPerShaderStage = 12;
GPUSize32 maxUniformBufferBindingSize = 16384;
};

View file

@ -3,7 +3,7 @@
* 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"]
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUBindGroup {
};
GPUBindGroup includes GPUObjectBase;
@ -13,10 +13,10 @@ dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupEntry> entries;
};
typedef /*(GPUSampler or GPUTextureView or*/ GPUBufferBindings/*)*/ GPUBindingResource;
typedef (GPUSampler or GPUTextureView or GPUBufferBindings) GPUBindingResource;
dictionary GPUBindGroupEntry {
required unsigned long binding;
required GPUIndex32 binding;
required GPUBindingResource resource;
};

View file

@ -16,11 +16,12 @@ dictionary GPUBindGroupLayoutEntry {
required GPUIndex32 binding;
required GPUShaderStageFlags visibility;
required GPUBindingType type;
GPUTextureViewDimension viewDimension = "2d";
GPUTextureComponentType textureComponentType = "float";
GPUTextureFormat storageTextureFormat;
boolean multisampled = false;
boolean hasDynamicOffset = false;
GPUSize64 minBufferBindingSize = 0;
GPUTextureViewDimension viewDimension;
GPUTextureComponentType textureComponentType;
boolean multisampled = false;
GPUTextureFormat storageTextureFormat;
};
enum GPUBindingType {
@ -28,8 +29,8 @@ enum GPUBindingType {
"storage-buffer",
"readonly-storage-buffer",
"sampler",
"comparison-sampler",
"sampled-texture",
"readonly-storage-texture",
"writeonly-storage-texture",
//"comparison-sampler",
"writeonly-storage-texture"
};

View file

@ -8,8 +8,8 @@ use wgpu::{
hub::{GlobalIdentityHandlerFactory, IdentityHandler, IdentityHandlerFactory},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, ComputePipelineId,
DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, SurfaceId,
SwapChainId, TextureId, TextureViewId, TypedId,
DeviceId, PipelineLayoutId, RenderBundleId, RenderPipelineId, SamplerId, ShaderModuleId,
SurfaceId, SwapChainId, TextureId, TextureViewId, TypedId,
},
};
use wgt::Backend;
@ -31,6 +31,7 @@ pub enum WebGPUMsg {
FreeSampler(SamplerId),
FreeSurface(SurfaceId),
FreeShaderModule(ShaderModuleId),
FreeRenderBundle(RenderBundleId),
Exit,
}
@ -73,6 +74,7 @@ impl_identity_handler!(BufferId, "buffer", WebGPUMsg::FreeBuffer);
impl_identity_handler!(BindGroupId, "bind_group", WebGPUMsg::FreeBindGroup);
impl_identity_handler!(SwapChainId, "swap_chain", WebGPUMsg::FreeSwapChain);
impl_identity_handler!(ShaderModuleId, "shader_module", WebGPUMsg::FreeShaderModule);
impl_identity_handler!(RenderBundleId, "render_bundle", WebGPUMsg::FreeRenderBundle);
impl_identity_handler!(
RenderPipelineId,
"render_pipeline",

View file

@ -28,9 +28,7 @@ use webrender_traits::{
WebrenderImageSource,
};
use wgpu::{
binding_model::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry,
},
binding_model::{BindGroupDescriptor, BindGroupEntry, BindingResource, BufferBinding},
command::{BufferCopyView, TextureCopyView},
device::HostMap,
id,
@ -73,12 +71,12 @@ pub enum WebGPURequest {
device_id: id::DeviceId,
bind_group_id: id::BindGroupId,
bind_group_layout_id: id::BindGroupLayoutId,
bindings: Vec<BindGroupEntry>,
entries: Vec<(u32, WebGPUBindings)>,
},
CreateBindGroupLayout {
device_id: id::DeviceId,
bind_group_layout_id: id::BindGroupLayoutId,
bindings: Vec<BindGroupLayoutEntry>,
entries: Vec<wgt::BindGroupLayoutEntry>,
},
CreateBuffer {
device_id: id::DeviceId,
@ -195,6 +193,13 @@ pub enum WebGPURequest {
},
}
#[derive(Debug, Deserialize, Serialize)]
pub enum WebGPUBindings {
Buffer(BufferBinding),
Sampler(id::SamplerId),
TextureView(id::TextureViewId),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WebGPU(pub IpcSender<WebGPURequest>);
@ -334,14 +339,27 @@ impl WGPU {
device_id,
bind_group_id,
bind_group_layout_id,
bindings,
mut entries,
} => {
let global = &self.global;
let bindings = entries
.drain(..)
.map(|(bind, res)| {
let resource = match res {
WebGPUBindings::Sampler(s) => BindingResource::Sampler(s),
WebGPUBindings::TextureView(t) => BindingResource::TextureView(t),
WebGPUBindings::Buffer(b) => BindingResource::Buffer(b),
};
BindGroupEntry {
binding: bind,
resource,
}
})
.collect::<Vec<_>>();
let descriptor = BindGroupDescriptor {
label: None,
layout: bind_group_layout_id,
entries: bindings.as_ptr(),
entries_length: bindings.len(),
label: ptr::null(),
bindings: bindings.as_slice(),
};
let _ = gfx_select!(bind_group_id =>
global.device_create_bind_group(device_id, &descriptor, bind_group_id));
@ -349,13 +367,12 @@ impl WGPU {
WebGPURequest::CreateBindGroupLayout {
device_id,
bind_group_layout_id,
bindings,
entries,
} => {
let global = &self.global;
let descriptor = BindGroupLayoutDescriptor {
entries: bindings.as_ptr(),
entries_length: bindings.len(),
label: ptr::null(),
let descriptor = wgt::BindGroupLayoutDescriptor {
bindings: entries.as_slice(),
label: None,
};
let _ = gfx_select!(bind_group_layout_id =>
global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id));
@ -375,18 +392,9 @@ impl WGPU {
command_encoder_id,
} => {
let global = &self.global;
let desc = wgt::CommandEncoderDescriptor { label: ptr::null() };
let _ = gfx_select!(command_encoder_id =>
global.device_create_command_encoder(device_id, &Default::default(), command_encoder_id));
},
WebGPURequest::CreateContext(sender) => {
let id = self
.external_images
.lock()
.expect("Lock poisoned?")
.next_id(WebrenderImageHandlerType::WebGPU);
if let Err(e) = sender.send(id) {
warn!("Failed to send ExternalImageId to new context ({})", e);
};
global.device_create_command_encoder(device_id, &desc, command_encoder_id));
},
WebGPURequest::CreateComputePipeline {
device_id,
@ -407,6 +415,16 @@ impl WGPU {
let _ = gfx_select!(compute_pipeline_id =>
global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id));
},
WebGPURequest::CreateContext(sender) => {
let id = self
.external_images
.lock()
.expect("Lock poisoned?")
.next_id(WebrenderImageHandlerType::WebGPU);
if let Err(e) = sender.send(id) {
warn!("Failed to send ExternalImageId to new context ({})", e);
};
},
WebGPURequest::CreatePipelineLayout {
device_id,
pipeline_layout_id,
@ -631,6 +649,7 @@ impl WGPU {
} => {
let adapter_id = match self.global.pick_adapter(
&options,
wgt::UnsafeExtensions::disallow(),
wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()),
) {
Some(id) => id,
@ -749,9 +768,10 @@ impl WGPU {
}
let buffer_size = (size.height as u32 * buffer_stride) as wgt::BufferAddress;
let comm_desc = wgt::CommandEncoderDescriptor { label: ptr::null() };
let _ = gfx_select!(encoder_id => global.device_create_command_encoder(
device_id,
&wgt::CommandEncoderDescriptor::default(),
&comm_desc,
encoder_id
));