Skip to content

Commit 5a45663

Browse files
committed
Handle Multi-threaded EGL Context Access
Implements the synchronization necessary to use the GL backend from multiple threads.
1 parent 6cfe8bd commit 5a45663

File tree

5 files changed

+150
-48
lines changed

5 files changed

+150
-48
lines changed

wgpu-hal/src/gles/adapter.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ impl super::Adapter {
163163
}
164164
}
165165

166-
pub(super) unsafe fn expose(gl: glow::Context) -> Option<crate::ExposedAdapter<super::Api>> {
166+
pub(super) unsafe fn expose(
167+
context: super::AdapterContext,
168+
) -> Option<crate::ExposedAdapter<super::Api>> {
169+
let gl = context.lock();
167170
let extensions = gl.supported_extensions();
168171

169172
let (vendor_const, renderer_const) = if extensions.contains("WEBGL_debug_renderer_info") {
@@ -326,10 +329,13 @@ impl super::Adapter {
326329

327330
let downlevel_defaults = wgt::DownlevelLimits {};
328331

332+
// Drop the GL guard so we can move the context into AdapterShared
333+
drop(gl);
334+
329335
Some(crate::ExposedAdapter {
330336
adapter: super::Adapter {
331337
shared: Arc::new(super::AdapterShared {
332-
context: gl,
338+
context,
333339
private_caps,
334340
workarounds,
335341
shading_language_version,
@@ -394,7 +400,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
394400
&self,
395401
features: wgt::Features,
396402
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
397-
let gl = &self.shared.context;
403+
let gl = &self.shared.context.lock();
398404
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
399405
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);
400406
let main_vao = gl

wgpu-hal/src/gles/device.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ impl CompilationContext<'_> {
7474
impl super::Device {
7575
unsafe fn compile_shader(
7676
&self,
77+
gl: &glow::Context,
7778
shader: &str,
7879
naga_stage: naga::ShaderStage,
7980
label: Option<&str>,
8081
) -> Result<glow::Shader, crate::PipelineError> {
81-
let gl = &self.shared.context;
8282
let target = match naga_stage {
8383
naga::ShaderStage::Vertex => glow::VERTEX_SHADER,
8484
naga::ShaderStage::Fragment => glow::FRAGMENT_SHADER,
@@ -112,6 +112,7 @@ impl super::Device {
112112

113113
fn create_shader(
114114
&self,
115+
gl: &glow::Context,
115116
naga_stage: naga::ShaderStage,
116117
stage: &crate::ProgrammableStage<super::Api>,
117118
context: CompilationContext,
@@ -156,16 +157,16 @@ impl super::Device {
156157
reflection_info,
157158
);
158159

159-
unsafe { self.compile_shader(&output, naga_stage, stage.module.label.as_deref()) }
160+
unsafe { self.compile_shader(gl, &output, naga_stage, stage.module.label.as_deref()) }
160161
}
161162

162163
unsafe fn create_pipeline<'a, I: Iterator<Item = ShaderStage<'a>>>(
163164
&self,
165+
gl: &glow::Context,
164166
shaders: I,
165167
layout: &super::PipelineLayout,
166168
label: crate::Label,
167169
) -> Result<super::PipelineInner, crate::PipelineError> {
168-
let gl = &self.shared.context;
169170
let program = gl.create_program().unwrap();
170171
if let Some(label) = label {
171172
if gl.supports_debug() {
@@ -186,7 +187,7 @@ impl super::Device {
186187
name_binding_map: &mut name_binding_map,
187188
};
188189

189-
let shader = self.create_shader(naga_stage, stage, context)?;
190+
let shader = self.create_shader(gl, naga_stage, stage, context)?;
190191
shaders_to_delete.push(shader);
191192
}
192193

@@ -199,7 +200,7 @@ impl super::Device {
199200
let shader_src = format!("#version {} es \n void main(void) {{}}", version,);
200201
log::info!("Only vertex shader is present. Creating an empty fragment shader",);
201202
let shader =
202-
self.compile_shader(&shader_src, naga::ShaderStage::Fragment, Some("_dummy"))?;
203+
self.compile_shader(gl, &shader_src, naga::ShaderStage::Fragment, Some("_dummy"))?;
203204
shaders_to_delete.push(shader);
204205
}
205206

@@ -292,7 +293,7 @@ impl super::Device {
292293

293294
impl crate::Device<super::Api> for super::Device {
294295
unsafe fn exit(self, queue: super::Queue) {
295-
let gl = &self.shared.context;
296+
let gl = &self.shared.context.lock();
296297
gl.delete_vertex_array(self.main_vao);
297298
gl.delete_framebuffer(queue.draw_fbo);
298299
gl.delete_framebuffer(queue.copy_fbo);
@@ -303,7 +304,7 @@ impl crate::Device<super::Api> for super::Device {
303304
&self,
304305
desc: &crate::BufferDescriptor,
305306
) -> Result<super::Buffer, crate::DeviceError> {
306-
let gl = &self.shared.context;
307+
let gl = &self.shared.context.lock();
307308

308309
let target = if desc.usage.contains(crate::BufferUses::INDEX) {
309310
glow::ELEMENT_ARRAY_BUFFER
@@ -360,7 +361,7 @@ impl crate::Device<super::Api> for super::Device {
360361
})
361362
}
362363
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
363-
let gl = &self.shared.context;
364+
let gl = &self.shared.context.lock();
364365
gl.delete_buffer(buffer.raw);
365366
}
366367

@@ -369,7 +370,7 @@ impl crate::Device<super::Api> for super::Device {
369370
buffer: &super::Buffer,
370371
range: crate::MemoryRange,
371372
) -> Result<crate::BufferMapping, crate::DeviceError> {
372-
let gl = &self.shared.context;
373+
let gl = &self.shared.context.lock();
373374

374375
let is_coherent = buffer.map_flags & glow::MAP_COHERENT_BIT != 0;
375376

@@ -388,7 +389,7 @@ impl crate::Device<super::Api> for super::Device {
388389
})
389390
}
390391
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
391-
let gl = &self.shared.context;
392+
let gl = &self.shared.context.lock();
392393
gl.bind_buffer(buffer.target, Some(buffer.raw));
393394
gl.unmap_buffer(buffer.target);
394395
gl.bind_buffer(buffer.target, None);
@@ -398,7 +399,7 @@ impl crate::Device<super::Api> for super::Device {
398399
where
399400
I: Iterator<Item = crate::MemoryRange>,
400401
{
401-
let gl = &self.shared.context;
402+
let gl = &self.shared.context.lock();
402403
gl.bind_buffer(buffer.target, Some(buffer.raw));
403404
for range in ranges {
404405
gl.flush_mapped_buffer_range(
@@ -416,7 +417,7 @@ impl crate::Device<super::Api> for super::Device {
416417
&self,
417418
desc: &crate::TextureDescriptor,
418419
) -> Result<super::Texture, crate::DeviceError> {
419-
let gl = &self.shared.context;
420+
let gl = &self.shared.context.lock();
420421

421422
let render_usage = crate::TextureUses::COLOR_TARGET
422423
| crate::TextureUses::DEPTH_STENCIL_WRITE
@@ -559,7 +560,7 @@ impl crate::Device<super::Api> for super::Device {
559560
})
560561
}
561562
unsafe fn destroy_texture(&self, texture: super::Texture) {
562-
let gl = &self.shared.context;
563+
let gl = &self.shared.context.lock();
563564
match texture.inner {
564565
super::TextureInner::Renderbuffer { raw, .. } => {
565566
gl.delete_renderbuffer(raw);
@@ -600,7 +601,7 @@ impl crate::Device<super::Api> for super::Device {
600601
&self,
601602
desc: &crate::SamplerDescriptor,
602603
) -> Result<super::Sampler, crate::DeviceError> {
603-
let gl = &self.shared.context;
604+
let gl = &self.shared.context.lock();
604605

605606
let raw = gl.create_sampler().unwrap();
606607

@@ -667,7 +668,7 @@ impl crate::Device<super::Api> for super::Device {
667668
Ok(super::Sampler { raw })
668669
}
669670
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
670-
let gl = &self.shared.context;
671+
let gl = &self.shared.context.lock();
671672
gl.delete_sampler(sampler.raw);
672673
}
673674

@@ -862,12 +863,13 @@ impl crate::Device<super::Api> for super::Device {
862863
&self,
863864
desc: &crate::RenderPipelineDescriptor<super::Api>,
864865
) -> Result<super::RenderPipeline, crate::PipelineError> {
866+
let gl = &self.shared.context.lock();
865867
let shaders = iter::once((naga::ShaderStage::Vertex, &desc.vertex_stage)).chain(
866868
desc.fragment_stage
867869
.as_ref()
868870
.map(|fs| (naga::ShaderStage::Fragment, fs)),
869871
);
870-
let inner = self.create_pipeline(shaders, desc.layout, desc.label)?;
872+
let inner = self.create_pipeline(gl, shaders, desc.layout, desc.label)?;
871873

872874
let (vertex_buffers, vertex_attributes) = {
873875
let mut buffers = Vec::new();
@@ -925,21 +927,22 @@ impl crate::Device<super::Api> for super::Device {
925927
})
926928
}
927929
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
928-
let gl = &self.shared.context;
930+
let gl = &self.shared.context.lock();
929931
gl.delete_program(pipeline.inner.program);
930932
}
931933

932934
unsafe fn create_compute_pipeline(
933935
&self,
934936
desc: &crate::ComputePipelineDescriptor<super::Api>,
935937
) -> Result<super::ComputePipeline, crate::PipelineError> {
938+
let gl = &self.shared.context.lock();
936939
let shaders = iter::once((naga::ShaderStage::Compute, &desc.stage));
937-
let inner = self.create_pipeline(shaders, desc.layout, desc.label)?;
940+
let inner = self.create_pipeline(gl, shaders, desc.layout, desc.label)?;
938941

939942
Ok(super::ComputePipeline { inner })
940943
}
941944
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
942-
let gl = &self.shared.context;
945+
let gl = &self.shared.context.lock();
943946
gl.delete_program(pipeline.inner.program);
944947
}
945948

@@ -948,7 +951,7 @@ impl crate::Device<super::Api> for super::Device {
948951
desc: &wgt::QuerySetDescriptor<crate::Label>,
949952
) -> Result<super::QuerySet, crate::DeviceError> {
950953
use std::fmt::Write;
951-
let gl = &self.shared.context;
954+
let gl = &self.shared.context.lock();
952955
let mut temp_string = String::new();
953956

954957
let mut queries = Vec::with_capacity(desc.count as usize);
@@ -975,7 +978,7 @@ impl crate::Device<super::Api> for super::Device {
975978
})
976979
}
977980
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
978-
let gl = &self.shared.context;
981+
let gl = &self.shared.context.lock();
979982
for &query in set.queries.iter() {
980983
gl.delete_query(query);
981984
}
@@ -987,7 +990,7 @@ impl crate::Device<super::Api> for super::Device {
987990
})
988991
}
989992
unsafe fn destroy_fence(&self, fence: super::Fence) {
990-
let gl = &self.shared.context;
993+
let gl = &self.shared.context.lock();
991994
for (_, sync) in fence.pending {
992995
gl.delete_sync(sync);
993996
}
@@ -996,7 +999,7 @@ impl crate::Device<super::Api> for super::Device {
996999
&self,
9971000
fence: &super::Fence,
9981001
) -> Result<crate::FenceValue, crate::DeviceError> {
999-
Ok(fence.get_latest(&self.shared.context))
1002+
Ok(fence.get_latest(&self.shared.context.lock()))
10001003
}
10011004
unsafe fn wait(
10021005
&self,
@@ -1005,7 +1008,7 @@ impl crate::Device<super::Api> for super::Device {
10051008
timeout_ms: u32,
10061009
) -> Result<bool, crate::DeviceError> {
10071010
if fence.last_completed < wait_value {
1008-
let gl = &self.shared.context;
1011+
let gl = &self.shared.context.lock();
10091012
let timeout_ns = (timeout_ms as u64 * 1_000_000).min(!0u32 as u64);
10101013
let &(_, sync) = fence
10111014
.pending

0 commit comments

Comments
 (0)