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 GPUCommandEncoder #25702

Merged
merged 3 commits into from Feb 12, 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

Prev

Initial implementation of GPUCommandEncoder

Added WebIDL bindings for `GPUCommandEncoder`, `GPUCommandBuffer`, `GPUComputePassEncoder`, `GPUProgrammablePassEncoder`.
Implemented the `beginComputePass`, `copyBufferToBuffer` and `finish` functions of `GPUCommandEncoder`.
Implemented the `createCommandEncoder` function of `GPUDevice`.
  • Loading branch information
zakorgy authored and imiklos committed Feb 11, 2020
commit 4facd3d4d21d131a222d3f44d5e8d077612f30e7
@@ -153,7 +153,8 @@ use time::{Duration, Timespec, Tm};
use uuid::Uuid;
use webgpu::{
WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer,
WebGPUComputePipeline, WebGPUDevice, WebGPUPipelineLayout, WebGPUShaderModule,
WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
WebGPUPipelineLayout, WebGPUShaderModule,
};
use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
@@ -531,13 +532,16 @@ unsafe_no_jsmanaged_fields!(RefCell<Option<WebGPU>>);
unsafe_no_jsmanaged_fields!(RefCell<Identities>);
unsafe_no_jsmanaged_fields!(WebGPU);
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
unsafe_no_jsmanaged_fields!(WebGPUBuffer);
unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
unsafe_no_jsmanaged_fields!(WebGPUComputePipeline);
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
unsafe_no_jsmanaged_fields!(webgpu::wgpu::command::RawPass);
unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
@@ -99,8 +99,8 @@ use time::{get_time, Timespec};
use uuid::Uuid;
use webgpu::wgpu::{
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, DeviceId,
PipelineLayoutId, ShaderModuleId,
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId,
DeviceId, PipelineLayoutId, ShaderModuleId,
},
Backend,
};
@@ -2137,11 +2137,18 @@ impl GlobalScope {
.borrow_mut()
.create_shader_module_id(backend)
}

pub fn wgpu_create_compute_pipeline_id(&self, backend: Backend) -> ComputePipelineId {
self.gpu_id_hub
.borrow_mut()
.create_compute_pipeline_id(backend)
}

pub fn wgpu_create_command_encoder_id(&self, backend: Backend) -> CommandEncoderId {
self.gpu_id_hub
.borrow_mut()
.create_command_encoder_id(backend)
}
}

fn timestamp_in_ms(time: Timespec) -> u64 {
@@ -0,0 +1,58 @@
/* 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::GPUCommandBufferBinding::{
self, GPUCommandBufferMethods,
};
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::{WebGPU, WebGPUCommandBuffer};

#[dom_struct]
pub struct GPUCommandBuffer {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
command_buffer: WebGPUCommandBuffer,
}

impl GPUCommandBuffer {
pub fn new_inherited(channel: WebGPU, command_buffer: WebGPUCommandBuffer) -> GPUCommandBuffer {
GPUCommandBuffer {
channel,
reflector_: Reflector::new(),
label: DomRefCell::new(None),
command_buffer,
}
}

pub fn new(
global: &GlobalScope,
channel: WebGPU,
command_buffer: WebGPUCommandBuffer,
) -> DomRoot<GPUCommandBuffer> {
reflect_dom_object(
Box::new(GPUCommandBuffer::new_inherited(channel, command_buffer)),
global,
GPUCommandBufferBinding::Wrap,
)
}
}

impl GPUCommandBufferMethods for GPUCommandBuffer {
/// 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;
}
}
@@ -0,0 +1,114 @@
/* 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::GPUCommandEncoderBinding::{
self, GPUCommandBufferDescriptor, GPUCommandEncoderMethods, GPUComputePassDescriptor,
};
use crate::dom::bindings::reflector::DomObject;
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 crate::dom::gpubuffer::GPUBuffer;
use crate::dom::gpucommandbuffer::GPUCommandBuffer;
use crate::dom::gpucomputepassencoder::GPUComputePassEncoder;
use dom_struct::dom_struct;
use ipc_channel::ipc;
use webgpu::{wgpu::command::RawPass, WebGPU, WebGPUCommandEncoder, WebGPURequest};

#[dom_struct]
pub struct GPUCommandEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
encoder: WebGPUCommandEncoder,
}

impl GPUCommandEncoder {
pub fn new_inherited(channel: WebGPU, encoder: WebGPUCommandEncoder) -> GPUCommandEncoder {
GPUCommandEncoder {
channel,
reflector_: Reflector::new(),
label: DomRefCell::new(None),
encoder,
}
}

pub fn new(
global: &GlobalScope,
channel: WebGPU,
encoder: WebGPUCommandEncoder,
) -> DomRoot<GPUCommandEncoder> {
reflect_dom_object(
Box::new(GPUCommandEncoder::new_inherited(channel, encoder)),
global,
GPUCommandEncoderBinding::Wrap,
)
}
}

impl GPUCommandEncoderMethods for GPUCommandEncoder {
/// 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;
}

/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-begincomputepass
fn BeginComputePass(
&self,
_descriptor: &GPUComputePassDescriptor,
) -> DomRoot<GPUComputePassEncoder> {
GPUComputePassEncoder::new(
&self.global(),
self.channel.clone(),
RawPass::new_compute(self.encoder.0),
)
}

/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertobuffer
fn CopyBufferToBuffer(
&self,
source: &GPUBuffer,
source_offset: u64,
destination: &GPUBuffer,
destination_offset: u64,
size: u64,
) {
self.channel
.0
.send(WebGPURequest::CopyBufferToBuffer(
self.encoder.0,
source.id().0,
source_offset,
destination.id().0,
destination_offset,
size,
))
.expect("Failed to send CopyBufferToBuffer");
}

/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish
fn Finish(&self, _descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> {
let (sender, receiver) = ipc::channel().unwrap();
self.channel
.0
.send(WebGPURequest::CommandEncoderFinish(
sender,
self.encoder.0,
// TODO(zakorgy): We should use `_descriptor` here after it's not empty
// and the underlying wgpu-core struct is serializable
))
.expect("Failed to send CopyBufferToBuffer");

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

This comment has been minimized.

Copy link
@kvark

kvark Feb 10, 2020

Member

similarly to object creation, this shouldn't be blocking

This comment has been minimized.

Copy link
@imiklos

imiklos Feb 10, 2020

Author Contributor

I've responded here: #25700 (comment)

GPUCommandBuffer::new(&self.global(), self.channel.clone(), buffer)
}
}
@@ -0,0 +1,59 @@
/* 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::GPUComputePassEncoderBinding::{
self, GPUComputePassEncoderMethods,
};
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::{wgpu::command::RawPass, WebGPU};

#[dom_struct]
pub struct GPUComputePassEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
channel: WebGPU,
label: DomRefCell<Option<DOMString>>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
pass: RawPass,
}

impl GPUComputePassEncoder {
pub fn new_inherited(channel: WebGPU, pass: RawPass) -> GPUComputePassEncoder {
GPUComputePassEncoder {
channel,
reflector_: Reflector::new(),
label: DomRefCell::new(None),
pass,
}
}

pub fn new(
global: &GlobalScope,
channel: WebGPU,
pass: RawPass,
) -> DomRoot<GPUComputePassEncoder> {
reflect_dom_object(
Box::new(GPUComputePassEncoder::new_inherited(channel, pass)),
global,
GPUComputePassEncoderBinding::Wrap,
)
}
}

impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
/// 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;
}
}
@@ -12,7 +12,9 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
};
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{
self, GPUCommandEncoderDescriptor, 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};
@@ -26,6 +28,7 @@ use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::gpubindgroup::GPUBindGroup;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpucommandencoder::GPUCommandEncoder;
use crate::dom::gpucomputepipeline::GPUComputePipeline;
use crate::dom::gpupipelinelayout::GPUPipelineLayout;
use crate::dom::gpushadermodule::GPUShaderModule;
@@ -589,4 +592,21 @@ impl GPUDeviceMethods for GPUDevice {
let compute_pipeline = receiver.recv().unwrap();
GPUComputePipeline::new(&self.global(), compute_pipeline)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder
fn CreateCommandEncoder(
&self,
_descriptor: &GPUCommandEncoderDescriptor,
) -> DomRoot<GPUCommandEncoder> {
let (sender, receiver) = ipc::channel().unwrap();
let id = self
.global()
.wgpu_create_command_encoder_id(self.device.0.backend());
self.channel
.0
.send(WebGPURequest::CreateCommandEncoder(sender, self.device, id))
.expect("Failed to create WebGPU command encoder");
let encoder = receiver.recv().unwrap();

GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder)
}
}
@@ -6,8 +6,8 @@ use smallvec::SmallVec;
use webgpu::wgpu::{
hub::IdentityManager,
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, DeviceId,
PipelineLayoutId, ShaderModuleId,
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId,
DeviceId, PipelineLayoutId, ShaderModuleId,
},
Backend,
};
@@ -22,6 +22,7 @@ pub struct IdentityHub {
compute_pipelines: IdentityManager,
pipeline_layouts: IdentityManager,
shader_modules: IdentityManager,
command_encoders: IdentityManager,
backend: Backend,
}

@@ -36,6 +37,7 @@ impl IdentityHub {
compute_pipelines: IdentityManager::default(),
pipeline_layouts: IdentityManager::default(),
shader_modules: IdentityManager::default(),
command_encoders: IdentityManager::default(),
backend,
}
}
@@ -71,6 +73,10 @@ impl IdentityHub {
fn create_shader_module_id(&mut self) -> ShaderModuleId {
self.shader_modules.alloc(self.backend)
}

pub fn create_command_encoder_id(&mut self) -> CommandEncoderId {
self.command_encoders.alloc(self.backend)
}
}

#[derive(Debug)]
@@ -166,4 +172,8 @@ impl Identities {
pub fn create_shader_module_id(&mut self, backend: Backend) -> ShaderModuleId {
self.select(backend).create_shader_module_id()
}

pub fn create_command_encoder_id(&mut self, backend: Backend) -> CommandEncoderId {
self.select(backend).create_command_encoder_id()
}
}
@@ -322,6 +322,9 @@ pub mod gpubindgroup;
pub mod gpubindgrouplayout;
pub mod gpubuffer;
pub mod gpubufferusage;
pub mod gpucommandbuffer;
pub mod gpucommandencoder;
pub mod gpucomputepassencoder;
pub mod gpucomputepipeline;
pub mod gpudevice;
pub mod gpupipelinelayout;
@@ -0,0 +1,9 @@
/* 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/#gpucommandbuffer
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUCommandBuffer {
};
GPUCommandBuffer includes GPUObjectBase;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.