Skip to content

Commit

Permalink
Upgrade wgpu-core version to 0.5.0 and implement server-side logic fo…
Browse files Browse the repository at this point in the history
…r wgpu id recycling

Remove current implementation of MapReadAsync
  • Loading branch information
kunalmohan committed May 21, 2020
1 parent 1a74382 commit a4f9116
Show file tree
Hide file tree
Showing 15 changed files with 496 additions and 331 deletions.
372 changes: 260 additions & 112 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Expand Up @@ -30,6 +30,5 @@ opt-level = 3
mio = { git = "https://github.com/servo/mio.git", branch = "servo" }
# https://github.com/retep998/winapi-rs/pull/816
winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" }
spirv_cross = { git = "https://github.com/servo/spirv_cross", branch = "wgpu-servo" }
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
surfman = { git = "https://github.com/servo/surfman" }
17 changes: 9 additions & 8 deletions components/script/dom/gpu.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -109,19 +109,20 @@ 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();

let script_to_constellation_chan = global.script_to_constellation_chan();
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()
Expand Down
8 changes: 4 additions & 4 deletions components/script/dom/gpuadapter.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
},
};
Expand Down
99 changes: 2 additions & 97 deletions components/script/dom/gpubuffer.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -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()
Expand All @@ -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),
}
}
}
2 changes: 1 addition & 1 deletion components/script/dom/gpucommandencoder.rs
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion components/script/dom/gpucomputepassencoder.rs
Expand Up @@ -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),
}
}
Expand Down
53 changes: 30 additions & 23 deletions components/script/dom/gpudevice.rs
Expand Up @@ -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]
Expand Down Expand Up @@ -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;
Expand All @@ -119,6 +121,7 @@ impl GPUDevice {
BufferDescriptor {
size: descriptor.size,
usage: wgpu_usage.unwrap(),
label: Default::default(),
},
)
} else {
Expand All @@ -127,6 +130,7 @@ impl GPUDevice {
BufferDescriptor {
size: 0,
usage: BufferUsage::STORAGE,
label: Default::default(),
},
)
}
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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::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::StorageTexture
BindingType::WriteonlyStorageTexture
},
GPUBindingType::Sampler => {
if let Some(limit) = validation_map.get_mut(&visibility) {
Expand All @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/identityhub.rs
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion components/script/dom/webidls/GPUBindGroupLayout.webidl
Expand Up @@ -28,5 +28,7 @@ enum GPUBindingType {
"readonly-storage-buffer",
"sampler",
"sampled-texture",
"storage-texture"
"readonly-storage-texture",
"writeonly-storage-texture",
//"comparison-sampler",
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/GPUBuffer.webidl
Expand Up @@ -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();

Expand Down
5 changes: 3 additions & 2 deletions components/webgpu/Cargo.toml
Expand Up @@ -15,7 +15,8 @@ embedder_traits = {path = "../embedder_traits"}
ipc-channel = "0.14"
log = "0.4"
malloc_size_of = { path = "../malloc_size_of" }
serde = "1.0"
serde = { version = "1.0", features = ["serde_derive"] }
servo_config = {path = "../config"}
smallvec = { version = "0.6", features = ["serde"] }
wgpu-core = { version = "0.1.0", git = "https://github.com/gfx-rs/wgpu", features = ["serde"] }
wgpu-core = { version = "0.5.0", git = "https://github.com/gfx-rs/wgpu", features = ["trace", "replay"] }
wgpu-types = { version = "0.5.0", git = "https://github.com/gfx-rs/wgpu", features = ["trace", "replay"] }

0 comments on commit a4f9116

Please sign in to comment.