Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of GPUComputePipeline #25700

Merged
merged 2 commits into from Feb 11, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Initial implementation of GPUShaderModule

Added WebIDL bindings for `GPUShaderModule`.
Implemented the `createShaderModule` function of `GPUDevice`.
  • Loading branch information
imiklos committed Feb 11, 2020
commit a8621c4ed9d87f6d168fd9b70e0cf501a4033632
@@ -153,7 +153,7 @@ use time::{Duration, Timespec, Tm};
use uuid::Uuid;
use webgpu::{
WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice,
WebGPUPipelineLayout,
WebGPUPipelineLayout, WebGPUShaderModule,
};
use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
@@ -536,6 +536,7 @@ unsafe_no_jsmanaged_fields!(WebGPUBuffer);
unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
@@ -98,7 +98,10 @@ use std::sync::Arc;
use time::{get_time, Timespec};
use uuid::Uuid;
use webgpu::wgpu::{
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend,
};

@@ -2128,6 +2131,12 @@ impl GlobalScope {
.borrow_mut()
.create_pipeline_layout_id(backend)
}

pub fn wgpu_create_shader_module_id(&self, backend: Backend) -> ShaderModuleId {

This comment has been minimized.

Copy link
@kvark

kvark Feb 8, 2020

Member

nit: perhaps it would be simpler to just have a function returning &mut GpuIdHub and let the users call the methods appropriately?

self.gpu_id_hub
.borrow_mut()
.create_shader_module_id(backend)
}
}

fn timestamp_in_ms(time: Timespec) -> u64 {
@@ -13,16 +13,20 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleDescriptor;
use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::gpubindgroup::GPUBindGroup;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpupipelinelayout::GPUPipelineLayout;
use crate::dom::gpushadermodule::GPUShaderModule;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use ipc_channel::ipc;
@@ -523,9 +527,36 @@ impl GPUDeviceMethods for GPUDevice {
descriptor.layout.id(),
bindings,
))
.expect("Failed to create WebGPU PipelineLayout");
.expect("Failed to create WebGPU BindGroup");

let bind_group = receiver.recv().unwrap();
GPUBindGroup::new(&self.global(), bind_group, valid)
}

/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule
fn CreateShaderModule(
&self,
descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
) -> DomRoot<GPUShaderModule> {
let (sender, receiver) = ipc::channel().unwrap();
let program: Vec<u32> = match &descriptor.code {
Uint32Array(program) => program.to_vec(),
String(program) => program.chars().map(|c| c as u32).collect::<Vec<u32>>(),
};
let id = self
.global()
.wgpu_create_shader_module_id(self.device.0.backend());
self.channel
.0
.send(WebGPURequest::CreateShaderModule(
sender,
self.device,
id,
program,
))
.expect("Failed to create WebGPU ShaderModule");

let shader_module = receiver.recv().unwrap();

This comment has been minimized.

Copy link
@kvark

kvark Feb 8, 2020

Member

In all of the creation methods, we aren't expected to block on anything. Here, therefore, we can't recv(). Instead, we'd be creating a new ID and asking the GPU server side to create something associated with this ID, but never wait for it to do so.

This comment has been minimized.

Copy link
@imiklos

imiklos Feb 10, 2020

Author Contributor

Yes, We have an issue ( #25472 ) for this, we would like to address this in a separate pull request for all the call which has to be non-blocking.

GPUShaderModule::new(&self.global(), shader_module)
}
}
@@ -0,0 +1,54 @@
/* 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::GPUShaderModuleBinding::{
self, GPUShaderModuleMethods,
};
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 webgpu::WebGPUShaderModule;

#[dom_struct]
pub struct GPUShaderModule {
reflector_: Reflector,
label: DomRefCell<Option<DOMString>>,
shader_module: WebGPUShaderModule,
}

impl GPUShaderModule {
fn new_inherited(shader_module: WebGPUShaderModule) -> GPUShaderModule {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(None),
shader_module,
}
}

pub fn new(
global: &GlobalScope,
shader_module: WebGPUShaderModule,
) -> DomRoot<GPUShaderModule> {
reflect_dom_object(
Box::new(GPUShaderModule::new_inherited(shader_module)),
global,
GPUShaderModuleBinding::Wrap,
)
}
}

impl GPUShaderModuleMethods for GPUShaderModule {
/// 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,7 +5,10 @@
use smallvec::SmallVec;
use webgpu::wgpu::{
hub::IdentityManager,
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend,
};

@@ -17,6 +20,7 @@ pub struct IdentityHub {
bind_groups: IdentityManager,
bind_group_layouts: IdentityManager,
pipeline_layouts: IdentityManager,
shader_modules: IdentityManager,
backend: Backend,
}

@@ -29,6 +33,7 @@ impl IdentityHub {
bind_groups: IdentityManager::default(),
bind_group_layouts: IdentityManager::default(),
pipeline_layouts: IdentityManager::default(),
shader_modules: IdentityManager::default(),
backend,
}
}
@@ -56,6 +61,10 @@ impl IdentityHub {
fn create_pipeline_layout_id(&mut self) -> PipelineLayoutId {
self.pipeline_layouts.alloc(self.backend)
}

fn create_shader_module_id(&mut self) -> ShaderModuleId {
self.shader_modules.alloc(self.backend)
}
}

#[derive(Debug)]
@@ -133,17 +142,7 @@ impl Identities {
}

pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId {
match backend {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Backend::Vulkan => self.vk_hub.create_bind_group_id(),
#[cfg(target_os = "windows")]
Backend::Dx12 => self.dx12_hub.create_bind_group_id(),
#[cfg(target_os = "windows")]
Backend::Dx11 => self.dx11_hub.create_bind_group_id(),
#[cfg(any(target_os = "ios", target_os = "macos"))]
Backend::Metal => self.metal_hub.create_bind_group_id(),
_ => self.dummy_hub.create_bind_group_id(),
}
self.select(backend).create_bind_group_id()
}

pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId {
@@ -153,4 +152,8 @@ impl Identities {
pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId {
self.select(backend).create_pipeline_layout_id()
}

pub fn create_shader_module_id(&mut self, backend: Backend) -> ShaderModuleId {
self.select(backend).create_shader_module_id()
}
}
@@ -324,6 +324,7 @@ pub mod gpubuffer;
pub mod gpubufferusage;
pub mod gpudevice;
pub mod gpupipelinelayout;
pub mod gpushadermodule;
pub mod gpushaderstage;
pub mod hashchangeevent;
pub mod headers;
@@ -19,8 +19,8 @@ interface GPUDevice : EventTarget {
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);

/*GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
/*GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
@@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

// https://gpuweb.github.io/gpuweb/#gpushadermodule
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUShaderModule {
};
GPUShaderModule includes GPUObjectBase;

typedef (Uint32Array or DOMString) GPUShaderCode;

dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
required GPUShaderCode code;
};
@@ -65,6 +65,12 @@ pub enum WebGPURequest {
wgpu::id::PipelineLayoutId,
Vec<wgpu::id::BindGroupLayoutId>,
),
CreateShaderModule(
IpcSender<WebGPUShaderModule>,
WebGPUDevice,
wgpu::id::ShaderModuleId,
Vec<u32>,
),
UnmapBuffer(WebGPUBuffer),
DestroyBuffer(WebGPUBuffer),
}
@@ -286,6 +292,24 @@ impl WGPU {
)
}
},
WebGPURequest::CreateShaderModule(sender, device, id, program) => {
let global = &self.global;
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
code: wgpu_core::U32Array {
bytes: program.as_ptr(),
length: program.len(),
},
};
let sm_id = gfx_select!(id => global.device_create_shader_module(device.0, &descriptor, id));
let shader_module = WebGPUShaderModule(sm_id);

if let Err(e) = sender.send(shader_module) {
warn!(
"Failed to send response to WebGPURequest::CreateShaderModule ({})",
e
)
}
},
WebGPURequest::Exit(sender) => {
self.deinit();
if let Err(e) = sender.send(()) {
@@ -319,3 +343,4 @@ webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
webgpu_resource!(WebGPUBindGroup, wgpu::id::BindGroupId);
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId);
webgpu_resource!(WebGPUShaderModule, wgpu::id::ShaderModuleId);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.