Skip to content

Commit

Permalink
Implement GPUSwapChain and GPUCanvasContext and interface with Webrender
Browse files Browse the repository at this point in the history
  • Loading branch information
kunalmohan committed Jun 13, 2020
1 parent 73760ea commit 71401e0
Show file tree
Hide file tree
Showing 28 changed files with 882 additions and 91 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions components/canvas/webgl_mode/inprocess.rs
Expand Up @@ -22,7 +22,9 @@ use surfman_chains::SwapChains;
use surfman_chains_api::SwapChainAPI;
use surfman_chains_api::SwapChainsAPI;
use webrender_surfman::WebrenderSurfman;
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
use webrender_traits::{
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
};
use webxr_api::SwapChainId as WebXRSwapChainId;

pub struct WebGLComm {
Expand Down Expand Up @@ -138,9 +140,10 @@ impl WebGLExternalImages {
}

impl WebrenderExternalImageApi for WebGLExternalImages {
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
fn lock(&mut self, id: u64) -> (WebrenderImageSource, Size2D<i32>) {
let id = WebGLContextId(id);
self.lock_swap_chain(id).unwrap_or_default()
let (texture_id, size) = self.lock_swap_chain(id).unwrap_or_default();
(WebrenderImageSource::TextureHandle(texture_id), size)
}

fn unlock(&mut self, id: u64) {
Expand Down
1 change: 1 addition & 0 deletions components/constellation/Cargo.toml
Expand Up @@ -43,6 +43,7 @@ servo_url = { path = "../url" }
style_traits = { path = "../style_traits" }
webgpu = { path = "../webgpu" }
webrender_api = { git = "https://github.com/servo/webrender" }
webrender_traits = { path = "../webrender_traits" }
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }

[target.'cfg(all(not(target_os = "windows"), not(target_os = "ios"), not(target_os="android"), not(target_arch="arm"), not(target_arch="aarch64")))'.dependencies]
Expand Down
135 changes: 93 additions & 42 deletions components/constellation/constellation.rs
Expand Up @@ -172,11 +172,12 @@ use std::marker::PhantomData;
use std::mem::replace;
use std::process;
use std::rc::{Rc, Weak};
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::thread;
use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webgpu::{WebGPU, WebGPURequest};
use webgpu::{self, WebGPU, WebGPURequest};
use webrender_traits::WebrenderExternalImageRegistry;

type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;

Expand Down Expand Up @@ -216,6 +217,18 @@ struct MessagePortInfo {
entangled_with: Option<MessagePortId>,
}

/// Webrender related objects required by WebGPU threads
struct WebrenderWGPU {
/// Webrender API.
webrender_api: webrender_api::RenderApi,

/// List of Webrender external images
webrender_external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,

/// WebGPU data that supplied to Webrender for rendering
wgpu_image_map: Arc<Mutex<HashMap<u64, webgpu::PresentationData>>>,
}

/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
/// store browser specific data for bookkeeping.
struct Browser {
Expand Down Expand Up @@ -384,6 +397,9 @@ pub struct Constellation<Message, LTF, STF, SWF> {
/// A single WebRender document the constellation operates on.
webrender_document: webrender_api::DocumentId,

/// Webrender related objects required by WebGPU threads
webrender_wgpu: WebrenderWGPU,

/// A channel for content processes to send messages that will
/// be relayed to the WebRender thread.
webrender_api_ipc_sender: script_traits::WebrenderIpcSender,
Expand Down Expand Up @@ -533,6 +549,12 @@ pub struct InitialConstellationState {
/// Webrender document ID.
pub webrender_document: webrender_api::DocumentId,

/// Webrender API.
pub webrender_api_sender: webrender_api::RenderApiSender,

/// Webrender external images
pub webrender_external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,

/// Entry point to create and get channels to a WebGLThread.
pub webgl_threads: Option<WebGLThreads>,

Expand All @@ -549,6 +571,8 @@ pub struct InitialConstellationState {

/// User agent string to report in network requests.
pub user_agent: Cow<'static, str>,

pub wgpu_image_map: Arc<Mutex<HashMap<u64, webgpu::PresentationData>>>,
}

/// Data needed for webdriver
Expand Down Expand Up @@ -834,6 +858,12 @@ where
}),
);

let webrender_wgpu = WebrenderWGPU {
webrender_api: state.webrender_api_sender.create_api(),
webrender_external_images: state.webrender_external_images,
wgpu_image_map: state.wgpu_image_map,
};

let mut constellation: Constellation<Message, LTF, STF, SWF> = Constellation {
namespace_receiver,
namespace_sender,
Expand Down Expand Up @@ -889,6 +919,7 @@ where
webrender_image_api_sender: net_traits::WebrenderIpcSender::new(
webrender_image_ipc_sender,
),
webrender_wgpu,
shutting_down: false,
handled_warnings: VecDeque::new(),
random_pipeline_closure: random_pipeline_closure_probability.map(|prob| {
Expand Down Expand Up @@ -1899,12 +1930,16 @@ where
EmbedderMsg::MediaSessionEvent(event),
));
},
FromScriptMsg::RequestAdapter(sender, options, ids) => self
.handle_request_wgpu_adapter(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::RequestAdapter(sender, options, ids),
),
FromScriptMsg::RequestAdapter(sender, options, ids) => self.handle_wgpu_request(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::RequestAdapter(sender, options, ids),
),
FromScriptMsg::GetWebGPUChan(sender) => self.handle_wgpu_request(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::GetWebGPUChan(sender),
),
}
}

Expand Down Expand Up @@ -2072,7 +2107,7 @@ where
}
}

fn handle_request_wgpu_adapter(
fn handle_wgpu_request(
&mut self,
source_pipeline_id: PipelineId,
browsing_context_id: BrowsingContextId,
Expand All @@ -2090,46 +2125,62 @@ where
Some(host) => host,
None => return warn!("Invalid host url"),
};
match self
let browsing_context_group = if let Some(bcg) = self
.browsing_context_group_set
.get_mut(&browsing_context_group_id)
{
Some(browsing_context_group) => {
let adapter_request =
if let FromScriptMsg::RequestAdapter(sender, options, ids) = request {
WebGPURequest::RequestAdapter {
sender,
options,
ids,
}
} else {
return warn!("Wrong message type in handle_request_wgpu_adapter");
};
let send = match browsing_context_group.webgpus.entry(host) {
Entry::Vacant(v) => v
.insert(match WebGPU::new() {
Some(webgpu) => {
let msg = ConstellationControlMsg::SetWebGPUPort(webgpu.1);
if let Err(e) = source_pipeline.event_loop.send(msg) {
warn!(
"Failed to send SetWebGPUPort to pipeline {} ({:?})",
source_pipeline_id, e
);
}
webgpu.0
},
None => return warn!("Failed to create new WebGPU thread"),
})
.0
.send(adapter_request),
Entry::Occupied(o) => o.get().0.send(adapter_request),
bcg
} else {
return warn!("Browsing context group not found");
};
let webgpu_chan = match browsing_context_group.webgpus.entry(host) {
Entry::Vacant(v) => v
.insert(
match WebGPU::new(
self.webrender_wgpu.webrender_api.create_sender(),
self.webrender_document,
self.webrender_wgpu.webrender_external_images.clone(),
self.webrender_wgpu.wgpu_image_map.clone(),
) {
Some(webgpu) => {
let msg = ConstellationControlMsg::SetWebGPUPort(webgpu.1);
if let Err(e) = source_pipeline.event_loop.send(msg) {
warn!(
"Failed to send SetWebGPUPort to pipeline {} ({:?})",
source_pipeline_id, e
);
}
webgpu.0
},
None => {
return warn!("Failed to create new WebGPU thread");
},
},
)
.clone(),
Entry::Occupied(o) => o.get().clone(),
};
match request {
FromScriptMsg::RequestAdapter(sender, options, ids) => {
let adapter_request = WebGPURequest::RequestAdapter {
sender,
options,
ids,
};
if send.is_err() {
if webgpu_chan.0.send(adapter_request).is_err() {
return warn!("Failed to send request adapter message on WebGPU channel");
}
},
None => return warn!("Browsing context group not found"),
};
FromScriptMsg::GetWebGPUChan(sender) => {
if sender.send(webgpu_chan).is_err() {
return warn!(
"Failed to send WebGPU channel to Pipeline {:?}",
source_pipeline_id
);
}
},
_ => return warn!("Wrong message type in handle_wgpu_request"),
}
}

fn handle_request_from_layout(&mut self, message: FromLayoutMsg) {
Expand Down
1 change: 1 addition & 0 deletions components/layout/display_list/builder.rs
Expand Up @@ -1905,6 +1905,7 @@ impl Fragment {

let image_key = match canvas_fragment_info.source {
CanvasFragmentSource::WebGL(image_key) => image_key,
CanvasFragmentSource::WebGPU(image_key) => image_key,
CanvasFragmentSource::Image(ref ipc_renderer) => match *ipc_renderer {
Some(ref ipc_renderer) => {
let ipc_renderer = ipc_renderer.lock().unwrap();
Expand Down
2 changes: 2 additions & 0 deletions components/layout/fragment.rs
Expand Up @@ -338,6 +338,7 @@ impl InlineAbsoluteFragmentInfo {
pub enum CanvasFragmentSource {
WebGL(webrender_api::ImageKey),
Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>),
WebGPU(webrender_api::ImageKey),
}

#[derive(Clone)]
Expand All @@ -355,6 +356,7 @@ impl CanvasFragmentInfo {
HTMLCanvasDataSource::Image(ipc_sender) => CanvasFragmentSource::Image(
ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer))),
),
HTMLCanvasDataSource::WebGPU(image_key) => CanvasFragmentSource::WebGPU(image_key),
};

CanvasFragmentInfo {
Expand Down
8 changes: 5 additions & 3 deletions components/media/lib.rs
Expand Up @@ -20,7 +20,9 @@ use crate::media_thread::GLPlayerThread;
use euclid::default::Size2D;
use servo_media::player::context::{GlApi, GlContext, NativeDisplay, PlayerGLContext};
use std::sync::{Arc, Mutex};
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
use webrender_traits::{
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
};

/// These are the messages that the GLPlayer thread will forward to
/// the video player which lives in htmlmediaelement
Expand Down Expand Up @@ -146,7 +148,7 @@ impl GLPlayerExternalImages {
}

impl WebrenderExternalImageApi for GLPlayerExternalImages {
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
fn lock(&mut self, id: u64) -> (WebrenderImageSource, Size2D<i32>) {
// The GLPlayerMsgForward::Lock message inserts a fence in the
// GLPlayer command queue.
self.glplayer_channel
Expand All @@ -160,7 +162,7 @@ impl WebrenderExternalImageApi for GLPlayerExternalImages {
// internal OpenGL subsystem.
//self.webrender_gl
// .wait_sync(gl_sync as gl::GLsync, 0, gl::TIMEOUT_IGNORED);
(image_id, size)
(WebrenderImageSource::TextureHandle(image_id), size)
}

fn unlock(&mut self, id: u64) {
Expand Down
5 changes: 4 additions & 1 deletion components/script/dom/bindings/trace.rs
Expand Up @@ -37,6 +37,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::utils::WindowProxyHandler;
use crate::dom::gpubuffer::GPUBufferState;
use crate::dom::gpucanvascontext::WebGPUContextId;
use crate::dom::gpucommandencoder::GPUCommandEncoderState;
use crate::dom::htmlimageelement::SourceSet;
use crate::dom::htmlmediaelement::{HTMLMediaElementFetchContext, MediaFrameRenderer};
Expand Down Expand Up @@ -168,7 +169,7 @@ use webgpu::{
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
WebGPUTexture, WebGPUTextureView,
};
use webrender_api::{DocumentId, ImageKey};
use webrender_api::{DocumentId, ExternalImageId, ImageKey};
use webxr_api::SwapChainId as WebXRSwapChainId;
use webxr_api::{Finger, Hand, Ray, View};

Expand Down Expand Up @@ -541,6 +542,7 @@ unsafe_no_jsmanaged_fields!(PathBuf);
unsafe_no_jsmanaged_fields!(DrawAPaintImageResult);
unsafe_no_jsmanaged_fields!(DocumentId);
unsafe_no_jsmanaged_fields!(ImageKey);
unsafe_no_jsmanaged_fields!(ExternalImageId);
unsafe_no_jsmanaged_fields!(WebGLBufferId);
unsafe_no_jsmanaged_fields!(WebGLChan);
unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
Expand Down Expand Up @@ -572,6 +574,7 @@ unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(WebGPUSampler);
unsafe_no_jsmanaged_fields!(WebGPUTexture);
unsafe_no_jsmanaged_fields!(WebGPUTextureView);
unsafe_no_jsmanaged_fields!(WebGPUContextId);
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
Expand Down

0 comments on commit 71401e0

Please sign in to comment.