mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Auto merge of #26564 - kunalmohan:gpu-id-rotation, r=jdm
Upgrade wgpu version to "0.5.0" and add server-side code for id recycling for WebGPU <!-- Please describe your changes on the following line: --> I have updated the cargo.lock to use a wgpu-core at a more recent commit where IdentityHandlerFactory was introduced. r?@kvark --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [ ] `./mach build -d` does not report any errors - [ ] `./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:
commit
94063d67a8
19 changed files with 509 additions and 344 deletions
|
@ -20,8 +20,8 @@ use ipc_channel::router::ROUTER;
|
|||
use js::jsapi::Heap;
|
||||
use script_traits::ScriptMsg;
|
||||
use std::rc::Rc;
|
||||
use webgpu::wgpu;
|
||||
use webgpu::{WebGPUResponse, WebGPUResponseResult};
|
||||
use webgpu::wgt::PowerPreference;
|
||||
use webgpu::{wgpu, WebGPUResponse, WebGPUResponseResult};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPU {
|
||||
|
@ -109,11 +109,9 @@ impl GPUMethods for GPU {
|
|||
let promise = Promise::new_in_current_realm(global, comp);
|
||||
let sender = response_async(&promise, self);
|
||||
let power_preference = match options.powerPreference {
|
||||
Some(GPUPowerPreference::Low_power) => wgpu::instance::PowerPreference::LowPower,
|
||||
Some(GPUPowerPreference::High_performance) => {
|
||||
wgpu::instance::PowerPreference::HighPerformance
|
||||
},
|
||||
None => wgpu::instance::PowerPreference::Default,
|
||||
Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower,
|
||||
Some(GPUPowerPreference::High_performance) => PowerPreference::HighPerformance,
|
||||
None => PowerPreference::Default,
|
||||
};
|
||||
let ids = global.wgpu_id_hub().lock().create_adapter_ids();
|
||||
|
||||
|
@ -121,7 +119,10 @@ impl GPUMethods for GPU {
|
|||
if script_to_constellation_chan
|
||||
.send(ScriptMsg::RequestAdapter(
|
||||
sender,
|
||||
wgpu::instance::RequestAdapterOptions { power_preference },
|
||||
wgpu::instance::RequestAdapterOptions {
|
||||
power_preference,
|
||||
compatible_surface: None,
|
||||
},
|
||||
ids,
|
||||
))
|
||||
.is_err()
|
||||
|
|
|
@ -20,7 +20,7 @@ use dom_struct::dom_struct;
|
|||
use js::jsapi::{Heap, JSObject};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use webgpu::{wgpu, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse};
|
||||
use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUAdapter {
|
||||
|
@ -80,11 +80,11 @@ impl GPUAdapterMethods for GPUAdapter {
|
|||
fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InRealm) -> Rc<Promise> {
|
||||
let promise = Promise::new_in_current_realm(&self.global(), comp);
|
||||
let sender = response_async(&promise, self);
|
||||
let desc = wgpu::instance::DeviceDescriptor {
|
||||
extensions: wgpu::instance::Extensions {
|
||||
let desc = wgt::DeviceDescriptor {
|
||||
extensions: wgt::Extensions {
|
||||
anisotropic_filtering: descriptor.extensions.anisotropicFiltering,
|
||||
},
|
||||
limits: wgpu::instance::Limits {
|
||||
limits: wgt::Limits {
|
||||
max_bind_groups: descriptor.limits.maxBindGroups,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -11,21 +11,14 @@ use crate::dom::bindings::root::DomRoot;
|
|||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::gpu::{response_async, AsyncWGPUListener};
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::realms::InRealm;
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::jsapi_wrapped::{DetachArrayBuffer, IsPromiseObject, RejectPromise};
|
||||
use js::rust::MutableHandle;
|
||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||
use js::typedarray::ArrayBuffer;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use webgpu::{
|
||||
wgpu::resource::BufferUsage, WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest, WebGPUResponse,
|
||||
};
|
||||
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#buffer-state
|
||||
#[derive(Clone, MallocSizeOf)]
|
||||
|
@ -193,72 +186,6 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
*self.state.borrow_mut() = GPUBufferState::Destroyed;
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapreadasync
|
||||
fn MapReadAsync(&self, comp: InRealm) -> Rc<Promise> {
|
||||
// Step 1 & 2
|
||||
let promise = Promise::new_in_current_realm(&self.global(), comp);
|
||||
match *self.state.borrow() {
|
||||
GPUBufferState::Unmapped => {
|
||||
match BufferUsage::from_bits(self.usage) {
|
||||
Some(usage) => {
|
||||
if !usage.contains(BufferUsage::MAP_READ) {
|
||||
// TODO: Record validation error on the current scope
|
||||
promise.reject_error(Error::Abort);
|
||||
return promise;
|
||||
};
|
||||
},
|
||||
None => {
|
||||
promise.reject_error(Error::Abort);
|
||||
return promise;
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
promise.reject_error(Error::Abort);
|
||||
return promise;
|
||||
},
|
||||
}
|
||||
// Step 3
|
||||
self.mapping.set(*promise.promise_obj());
|
||||
// Step 4
|
||||
*self.state.borrow_mut() = GPUBufferState::MappedPendingForReading;
|
||||
|
||||
// Step 5.1
|
||||
if unsafe {
|
||||
ArrayBuffer::create(
|
||||
*self.global().get_cx(),
|
||||
CreateWith::Length(self.size as u32),
|
||||
MutableHandle::from_raw(self.mapping.handle_mut()),
|
||||
)
|
||||
}
|
||||
.is_err()
|
||||
{
|
||||
promise.reject_error(Error::Operation);
|
||||
return promise;
|
||||
}
|
||||
|
||||
let sender = response_async(&promise, self);
|
||||
if self
|
||||
.channel
|
||||
.0
|
||||
.send(WebGPURequest::MapReadAsync {
|
||||
sender,
|
||||
buffer_id: self.buffer.0,
|
||||
device_id: self.device.0,
|
||||
usage: self.usage,
|
||||
size: self.size,
|
||||
})
|
||||
.is_err()
|
||||
{
|
||||
promise.reject_error(Error::Operation);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Step 6
|
||||
promise
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn GetLabel(&self) -> Option<DOMString> {
|
||||
self.label.borrow().clone()
|
||||
|
@ -269,25 +196,3 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
*self.label.borrow_mut() = value;
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWGPUListener for GPUBuffer {
|
||||
#[allow(unsafe_code)]
|
||||
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
|
||||
match response {
|
||||
WebGPUResponse::MapReadAsync(bytes) => unsafe {
|
||||
match ArrayBuffer::from(self.mapping.get()) {
|
||||
Ok(mut array_buffer) => {
|
||||
// Step 5.2
|
||||
array_buffer.update(&bytes);
|
||||
// Step 5.3
|
||||
*self.state.borrow_mut() = GPUBufferState::MappedForReading;
|
||||
// Step 5.4
|
||||
promise.resolve_native(&array_buffer);
|
||||
},
|
||||
_ => promise.reject_error(Error::Operation),
|
||||
};
|
||||
},
|
||||
_ => promise.reject_error(Error::Operation),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use dom_struct::dom_struct;
|
|||
use ipc_channel::ipc;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use webgpu::wgpu::resource::BufferUsage;
|
||||
use webgpu::wgt::BufferUsage;
|
||||
use webgpu::{WebGPU, WebGPUCommandEncoder, WebGPURequest};
|
||||
|
||||
const BUFFER_COPY_ALIGN_MASK: u64 = 3;
|
||||
|
|
|
@ -36,12 +36,13 @@ pub struct GPUComputePassEncoder {
|
|||
}
|
||||
|
||||
impl GPUComputePassEncoder {
|
||||
#[allow(unsafe_code)]
|
||||
fn new_inherited(channel: WebGPU, parent: &GPUCommandEncoder) -> GPUComputePassEncoder {
|
||||
GPUComputePassEncoder {
|
||||
channel,
|
||||
reflector_: Reflector::new(),
|
||||
label: DomRefCell::new(None),
|
||||
raw_pass: RefCell::new(Some(RawPass::new_compute(parent.id().0))),
|
||||
raw_pass: RefCell::new(Some(unsafe { RawPass::new_compute(parent.id().0) })),
|
||||
command_encoder: Dom::from_ref(parent),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,10 +42,12 @@ use js::typedarray::{ArrayBuffer, CreateWith};
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::ptr::{self, NonNull};
|
||||
use webgpu::wgpu::binding_model::{
|
||||
BindGroupBinding, BindGroupLayoutBinding, BindingResource, BindingType, BufferBinding,
|
||||
ShaderStage,
|
||||
BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding,
|
||||
};
|
||||
use webgpu::wgt::{
|
||||
BufferDescriptor, BufferUsage, ShaderStage, TextureComponentType, TextureFormat,
|
||||
TextureViewDimension,
|
||||
};
|
||||
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
|
||||
use webgpu::{WebGPU, WebGPUDevice, WebGPUQueue, WebGPURequest};
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -108,7 +110,7 @@ impl GPUDevice {
|
|||
fn validate_buffer_descriptor(
|
||||
&self,
|
||||
descriptor: &GPUBufferDescriptor,
|
||||
) -> (bool, BufferDescriptor) {
|
||||
) -> (bool, BufferDescriptor<std::string::String>) {
|
||||
// TODO: Record a validation error in the current scope if the descriptor is invalid.
|
||||
let wgpu_usage = BufferUsage::from_bits(descriptor.usage);
|
||||
let valid = wgpu_usage.is_some() && descriptor.size > 0;
|
||||
|
@ -119,6 +121,7 @@ impl GPUDevice {
|
|||
BufferDescriptor {
|
||||
size: descriptor.size,
|
||||
usage: wgpu_usage.unwrap(),
|
||||
label: Default::default(),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
|
@ -127,6 +130,7 @@ impl GPUDevice {
|
|||
BufferDescriptor {
|
||||
size: 0,
|
||||
usage: BufferUsage::STORAGE,
|
||||
label: Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -276,18 +280,9 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
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(),
|
||||
);
|
||||
validation_map.insert(ShaderStage::VERTEX, maxLimits.clone());
|
||||
validation_map.insert(ShaderStage::FRAGMENT, maxLimits.clone());
|
||||
validation_map.insert(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 =
|
||||
|
@ -344,14 +339,23 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
};
|
||||
BindingType::SampledTexture
|
||||
},
|
||||
GPUBindingType::Storage_texture => {
|
||||
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::StorageTexture
|
||||
BindingType::ReadonlyStorageTexture
|
||||
},
|
||||
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::Sampler => {
|
||||
if let Some(limit) = validation_map.get_mut(&visibility) {
|
||||
|
@ -364,16 +368,19 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
},
|
||||
};
|
||||
|
||||
BindGroupLayoutBinding {
|
||||
BindGroupLayoutEntry {
|
||||
binding: bind.binding,
|
||||
visibility,
|
||||
ty,
|
||||
dynamic: bind.hasDynamicOffset,
|
||||
has_dynamic_offset: bind.hasDynamicOffset,
|
||||
multisampled: bind.multisampled,
|
||||
texture_dimension: webgpu::wgpu::resource::TextureViewDimension::D2, // Use as default for now
|
||||
// Use as default for now
|
||||
texture_component_type: TextureComponentType::Float,
|
||||
storage_texture_format: TextureFormat::Rgba8UnormSrgb,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<BindGroupLayoutBinding>>();
|
||||
.collect::<Vec<BindGroupLayoutEntry>>();
|
||||
|
||||
// bindings are unique
|
||||
valid &= storeBindings.len() == bindings.len();
|
||||
|
@ -523,7 +530,7 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
let bindings = descriptor
|
||||
.entries
|
||||
.iter()
|
||||
.map(|bind| BindGroupBinding {
|
||||
.map(|bind| BindGroupEntry {
|
||||
binding: bind.binding,
|
||||
resource: BindingResource::Buffer(BufferBinding {
|
||||
buffer: bind.resource.buffer.id().0,
|
||||
|
|
|
@ -9,8 +9,8 @@ use webgpu::wgpu::{
|
|||
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId,
|
||||
DeviceId, PipelineLayoutId, ShaderModuleId,
|
||||
},
|
||||
Backend,
|
||||
};
|
||||
use webgpu::wgt::Backend;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IdentityHub {
|
||||
|
|
|
@ -239,7 +239,7 @@ impl BodyOperations for Response {
|
|||
match body {
|
||||
NetTraitsResponseBody::Done(bytes) => Some(bytes),
|
||||
body => {
|
||||
mem::replace(&mut *self.body.borrow_mut(), body);
|
||||
let _ = mem::replace(&mut *self.body.borrow_mut(), body);
|
||||
None
|
||||
},
|
||||
}
|
||||
|
|
|
@ -28,5 +28,7 @@ enum GPUBindingType {
|
|||
"readonly-storage-buffer",
|
||||
"sampler",
|
||||
"sampled-texture",
|
||||
"storage-texture"
|
||||
"readonly-storage-texture",
|
||||
"writeonly-storage-texture",
|
||||
//"comparison-sampler",
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// https://gpuweb.github.io/gpuweb/#gpubuffer
|
||||
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
|
||||
interface GPUBuffer {
|
||||
Promise<ArrayBuffer> mapReadAsync();
|
||||
//Promise<ArrayBuffer> mapReadAsync();
|
||||
// Promise<ArrayBuffer> mapWriteAsync();
|
||||
void unmap();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue