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

Use EGL Sync Objects to ensure that shared WebGL textures are ready to be used #1407

Merged
merged 1 commit into from Jul 5, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Some generated files are not rendered by default. Learn more.

@@ -1,6 +1,6 @@
[package]
name = "webrender"
version = "0.45.0"
version = "0.46.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"
@@ -19,7 +19,7 @@ bit-set = "0.4"
byteorder = "1.0"
euclid = "0.15.1"
fnv = "1.0"
gleam = "0.4.6"
gleam = "0.4.7"
lazy_static = "0.2"
log = "0.3"
num-traits = "0.1.32"
@@ -10,7 +10,7 @@ use profiler::{BackendProfileCounters, GpuCacheProfileCounters, TextureCacheProf
use record::ApiRecordingReceiver;
use resource_cache::ResourceCache;
use scene::Scene;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use texture_cache::TextureCache;
@@ -60,6 +60,7 @@ pub struct RenderBackend {
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
webrender_context_handle: Option<GLContextHandleWrapper>,
webgl_contexts: HashMap<WebGLContextId, GLContextWrapper>,
dirty_webgl_contexts: HashSet<WebGLContextId>,
current_bound_webgl_context_id: Option<WebGLContextId>,
recorder: Option<Box<ApiRecordingReceiver>>,
main_thread_dispatcher: Arc<Mutex<Option<Box<RenderDispatcher>>>>,
@@ -114,6 +115,7 @@ impl RenderBackend {
notifier,
webrender_context_handle,
webgl_contexts: HashMap::new(),
dirty_webgl_contexts: HashSet::new(),
current_bound_webgl_context_id: None,
recorder,
main_thread_dispatcher,
@@ -357,6 +359,7 @@ impl RenderBackend {
self.resource_cache
.add_webgl_texture(id, SourceTexture::WebGL(texture_id),
real_size);
self.dirty_webgl_contexts.insert(id);

tx.send(Ok((id, limits))).unwrap();
},
@@ -381,6 +384,7 @@ impl RenderBackend {
self.resource_cache
.update_webgl_texture(context_id, SourceTexture::WebGL(texture_id),
real_size);
self.dirty_webgl_contexts.insert(context_id);
},
Err(msg) => {
error!("Error resizing WebGLContext: {}", msg);
@@ -396,6 +400,7 @@ impl RenderBackend {
self.current_bound_webgl_context_id = Some(context_id);
}
ctx.apply_command(command);
self.dirty_webgl_contexts.insert(context_id);
},

ApiMsg::VRCompositorCommand(context_id, command) => {
@@ -404,6 +409,7 @@ impl RenderBackend {
self.current_bound_webgl_context_id = Some(context_id);
}
self.handle_vr_compositor_command(context_id, command);
self.dirty_webgl_contexts.insert(context_id);
}
ApiMsg::GenerateFrame(property_bindings) => {
profile_scope!("GenerateFrame");
@@ -490,10 +496,18 @@ impl RenderBackend {
// implementations - a single flush for each webgl
// context at the start of a render frame should
// incur minimal cost.
for (_, webgl_context) in &self.webgl_contexts {
webgl_context.make_current();
webgl_context.apply_command(WebGLCommand::Flush);
webgl_context.unbind();
// glFlush is not enough in some GPUs.
// glFlush doesn't guarantee the completion of the GL commands when the shared texture is sampled.
// This leads to some graphic glitches on some demos or even nothing being rendered at all (GPU Mali-T880).
// glFinish guarantees the completion of the commands but it may hurt performance a lot.
// Sync Objects are the recommended way to ensure that textures are ready in OpenGL 3.0+.
// They are more performant than glFinish and guarantee the completion of the GL commands.
for (id, webgl_context) in &self.webgl_contexts {
if self.dirty_webgl_contexts.remove(&id) {
webgl_context.make_current();
webgl_context.apply_command(WebGLCommand::FenceAndWaitSync);
webgl_context.unbind();
}
}

let accumulated_scale_factor = self.accumulated_scale_factor();
@@ -1,6 +1,6 @@
[package]
name = "webrender_api"
version = "0.45.0"
version = "0.46.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"
@@ -117,7 +117,7 @@ pub struct GLLimits([u8; 0]);
#[cfg(not(feature = "webgl"))]
#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLCommand {
Flush,
FenceAndWaitSync,
}

#[repr(C)]
@@ -129,6 +129,7 @@ pub enum WebGLCommand {
CreateVertexArray(MsgSender<Option<WebGLVertexArrayId>>),
DeleteVertexArray(WebGLVertexArrayId),
BindVertexArray(Option<WebGLVertexArrayId>),
FenceAndWaitSync,
}

#[cfg(feature = "nightly")]
@@ -388,7 +389,8 @@ impl fmt::Debug for WebGLCommand {
GenerateMipmap(..) => "GenerateMipmap",
CreateVertexArray(..) => "CreateVertexArray",
DeleteVertexArray(..) => "DeleteVertexArray",
BindVertexArray(..) => "BindVertexArray"
BindVertexArray(..) => "BindVertexArray",
FenceAndWaitSync => "FenceAndWaitSync",
};

write!(f, "CanvasWebGLMsg::{}(..)", name)
@@ -631,6 +633,8 @@ impl WebGLCommand {
ctx.gl().delete_vertex_arrays(&[id.get()]),
WebGLCommand::BindVertexArray(id) =>
ctx.gl().bind_vertex_array(id.map_or(0, WebGLVertexArrayId::get)),
WebGLCommand::FenceAndWaitSync =>
Self::fence_and_wait_sync(ctx.gl()),
}

// FIXME: Use debug_assertions once tests are run with them
@@ -1040,4 +1044,13 @@ impl WebGLCommand {
gl.shader_source(shader_id.get(), &[source.as_bytes()]);
gl.compile_shader(shader_id.get());
}

fn fence_and_wait_sync(gl: &gl::Gl) {
// Call FenceSync and ClientWaitSync to ensure that textures are ready.
let sync = gl.fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
// SYNC_FLUSH_COMMANDS_BIT is used to automatically generate a glFlush before blocking on the sync object.
gl.wait_sync(sync, gl::SYNC_FLUSH_COMMANDS_BIT, gl::TIMEOUT_IGNORED);
// Release GLsync object
gl.delete_sync(sync);
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.