Skip to content

Commit 671e393

Browse files
committed
Handle Multi-threaded EGL Context Access
Implements the synchronization necessary to use the GL backend from multiple threads.
1 parent 9ce884c commit 671e393

File tree

6 files changed

+181
-67
lines changed

6 files changed

+181
-67
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") {
@@ -333,10 +336,13 @@ impl super::Adapter {
333336

334337
let downlevel_defaults = wgt::DownlevelLimits {};
335338

339+
// Drop the GL guard so we can move the context into AdapterShared
340+
drop(gl);
341+
336342
Some(crate::ExposedAdapter {
337343
adapter: super::Adapter {
338344
shared: Arc::new(super::AdapterShared {
339-
context: gl,
345+
context,
340346
private_caps,
341347
workarounds,
342348
shading_language_version,
@@ -401,7 +407,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
401407
&self,
402408
features: wgt::Features,
403409
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
404-
let gl = &self.shared.context;
410+
let gl = &self.shared.context.lock();
405411
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
406412
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);
407413
let main_vao = gl

wgpu-hal/src/gles/device.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,11 @@ impl CompilationContext<'_> {
7373

7474
impl super::Device {
7575
unsafe fn compile_shader(
76-
&self,
76+
gl: &glow::Context,
7777
shader: &str,
7878
naga_stage: naga::ShaderStage,
7979
label: Option<&str>,
8080
) -> Result<glow::Shader, crate::PipelineError> {
81-
let gl = &self.shared.context;
8281
let target = match naga_stage {
8382
naga::ShaderStage::Vertex => glow::VERTEX_SHADER,
8483
naga::ShaderStage::Fragment => glow::FRAGMENT_SHADER,
@@ -111,7 +110,7 @@ impl super::Device {
111110
}
112111

113112
fn create_shader(
114-
&self,
113+
gl: &glow::Context,
115114
naga_stage: naga::ShaderStage,
116115
stage: &crate::ProgrammableStage<super::Api>,
117116
context: CompilationContext,
@@ -156,16 +155,16 @@ impl super::Device {
156155
reflection_info,
157156
);
158157

159-
unsafe { self.compile_shader(&output, naga_stage, stage.module.label.as_deref()) }
158+
unsafe { Self::compile_shader(gl, &output, naga_stage, stage.module.label.as_deref()) }
160159
}
161160

162161
unsafe fn create_pipeline<'a, I: Iterator<Item = ShaderStage<'a>>>(
163162
&self,
163+
gl: &glow::Context,
164164
shaders: I,
165165
layout: &super::PipelineLayout,
166166
label: crate::Label,
167167
) -> Result<super::PipelineInner, crate::PipelineError> {
168-
let gl = &self.shared.context;
169168
let program = gl.create_program().unwrap();
170169
if let Some(label) = label {
171170
if gl.supports_debug() {
@@ -186,7 +185,7 @@ impl super::Device {
186185
name_binding_map: &mut name_binding_map,
187186
};
188187

189-
let shader = self.create_shader(naga_stage, stage, context)?;
188+
let shader = Self::create_shader(gl, naga_stage, stage, context)?;
190189
shaders_to_delete.push(shader);
191190
}
192191

@@ -199,7 +198,7 @@ impl super::Device {
199198
let shader_src = format!("#version {} es \n void main(void) {{}}", version,);
200199
log::info!("Only vertex shader is present. Creating an empty fragment shader",);
201200
let shader =
202-
self.compile_shader(&shader_src, naga::ShaderStage::Fragment, Some("_dummy"))?;
201+
Self::compile_shader(gl, &shader_src, naga::ShaderStage::Fragment, Some("_dummy"))?;
203202
shaders_to_delete.push(shader);
204203
}
205204

@@ -292,7 +291,7 @@ impl super::Device {
292291

293292
impl crate::Device<super::Api> for super::Device {
294293
unsafe fn exit(self, queue: super::Queue) {
295-
let gl = &self.shared.context;
294+
let gl = &self.shared.context.lock();
296295
gl.delete_vertex_array(self.main_vao);
297296
gl.delete_framebuffer(queue.draw_fbo);
298297
gl.delete_framebuffer(queue.copy_fbo);
@@ -303,7 +302,7 @@ impl crate::Device<super::Api> for super::Device {
303302
&self,
304303
desc: &crate::BufferDescriptor,
305304
) -> Result<super::Buffer, crate::DeviceError> {
306-
let gl = &self.shared.context;
305+
let gl = &self.shared.context.lock();
307306

308307
let target = if desc.usage.contains(crate::BufferUses::INDEX) {
309308
glow::ELEMENT_ARRAY_BUFFER
@@ -360,7 +359,7 @@ impl crate::Device<super::Api> for super::Device {
360359
})
361360
}
362361
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
363-
let gl = &self.shared.context;
362+
let gl = &self.shared.context.lock();
364363
gl.delete_buffer(buffer.raw);
365364
}
366365

@@ -369,7 +368,7 @@ impl crate::Device<super::Api> for super::Device {
369368
buffer: &super::Buffer,
370369
range: crate::MemoryRange,
371370
) -> Result<crate::BufferMapping, crate::DeviceError> {
372-
let gl = &self.shared.context;
371+
let gl = &self.shared.context.lock();
373372

374373
let is_coherent = buffer.map_flags & glow::MAP_COHERENT_BIT != 0;
375374

@@ -388,7 +387,7 @@ impl crate::Device<super::Api> for super::Device {
388387
})
389388
}
390389
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
391-
let gl = &self.shared.context;
390+
let gl = &self.shared.context.lock();
392391
gl.bind_buffer(buffer.target, Some(buffer.raw));
393392
gl.unmap_buffer(buffer.target);
394393
gl.bind_buffer(buffer.target, None);
@@ -398,7 +397,7 @@ impl crate::Device<super::Api> for super::Device {
398397
where
399398
I: Iterator<Item = crate::MemoryRange>,
400399
{
401-
let gl = &self.shared.context;
400+
let gl = &self.shared.context.lock();
402401
gl.bind_buffer(buffer.target, Some(buffer.raw));
403402
for range in ranges {
404403
gl.flush_mapped_buffer_range(
@@ -416,7 +415,7 @@ impl crate::Device<super::Api> for super::Device {
416415
&self,
417416
desc: &crate::TextureDescriptor,
418417
) -> Result<super::Texture, crate::DeviceError> {
419-
let gl = &self.shared.context;
418+
let gl = &self.shared.context.lock();
420419

421420
let render_usage = crate::TextureUses::COLOR_TARGET
422421
| crate::TextureUses::DEPTH_STENCIL_WRITE
@@ -559,7 +558,7 @@ impl crate::Device<super::Api> for super::Device {
559558
})
560559
}
561560
unsafe fn destroy_texture(&self, texture: super::Texture) {
562-
let gl = &self.shared.context;
561+
let gl = &self.shared.context.lock();
563562
match texture.inner {
564563
super::TextureInner::Renderbuffer { raw, .. } => {
565564
gl.delete_renderbuffer(raw);
@@ -600,7 +599,7 @@ impl crate::Device<super::Api> for super::Device {
600599
&self,
601600
desc: &crate::SamplerDescriptor,
602601
) -> Result<super::Sampler, crate::DeviceError> {
603-
let gl = &self.shared.context;
602+
let gl = &self.shared.context.lock();
604603

605604
let raw = gl.create_sampler().unwrap();
606605

@@ -667,7 +666,7 @@ impl crate::Device<super::Api> for super::Device {
667666
Ok(super::Sampler { raw })
668667
}
669668
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
670-
let gl = &self.shared.context;
669+
let gl = &self.shared.context.lock();
671670
gl.delete_sampler(sampler.raw);
672671
}
673672

@@ -862,12 +861,13 @@ impl crate::Device<super::Api> for super::Device {
862861
&self,
863862
desc: &crate::RenderPipelineDescriptor<super::Api>,
864863
) -> Result<super::RenderPipeline, crate::PipelineError> {
864+
let gl = &self.shared.context.lock();
865865
let shaders = iter::once((naga::ShaderStage::Vertex, &desc.vertex_stage)).chain(
866866
desc.fragment_stage
867867
.as_ref()
868868
.map(|fs| (naga::ShaderStage::Fragment, fs)),
869869
);
870-
let inner = self.create_pipeline(shaders, desc.layout, desc.label)?;
870+
let inner = self.create_pipeline(gl, shaders, desc.layout, desc.label)?;
871871

872872
let (vertex_buffers, vertex_attributes) = {
873873
let mut buffers = Vec::new();
@@ -925,21 +925,22 @@ impl crate::Device<super::Api> for super::Device {
925925
})
926926
}
927927
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
928-
let gl = &self.shared.context;
928+
let gl = &self.shared.context.lock();
929929
gl.delete_program(pipeline.inner.program);
930930
}
931931

932932
unsafe fn create_compute_pipeline(
933933
&self,
934934
desc: &crate::ComputePipelineDescriptor<super::Api>,
935935
) -> Result<super::ComputePipeline, crate::PipelineError> {
936+
let gl = &self.shared.context.lock();
936937
let shaders = iter::once((naga::ShaderStage::Compute, &desc.stage));
937-
let inner = self.create_pipeline(shaders, desc.layout, desc.label)?;
938+
let inner = self.create_pipeline(gl, shaders, desc.layout, desc.label)?;
938939

939940
Ok(super::ComputePipeline { inner })
940941
}
941942
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
942-
let gl = &self.shared.context;
943+
let gl = &self.shared.context.lock();
943944
gl.delete_program(pipeline.inner.program);
944945
}
945946

@@ -948,7 +949,7 @@ impl crate::Device<super::Api> for super::Device {
948949
desc: &wgt::QuerySetDescriptor<crate::Label>,
949950
) -> Result<super::QuerySet, crate::DeviceError> {
950951
use std::fmt::Write;
951-
let gl = &self.shared.context;
952+
let gl = &self.shared.context.lock();
952953
let mut temp_string = String::new();
953954

954955
let mut queries = Vec::with_capacity(desc.count as usize);
@@ -975,7 +976,7 @@ impl crate::Device<super::Api> for super::Device {
975976
})
976977
}
977978
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
978-
let gl = &self.shared.context;
979+
let gl = &self.shared.context.lock();
979980
for &query in set.queries.iter() {
980981
gl.delete_query(query);
981982
}
@@ -987,7 +988,7 @@ impl crate::Device<super::Api> for super::Device {
987988
})
988989
}
989990
unsafe fn destroy_fence(&self, fence: super::Fence) {
990-
let gl = &self.shared.context;
991+
let gl = &self.shared.context.lock();
991992
for (_, sync) in fence.pending {
992993
gl.delete_sync(sync);
993994
}
@@ -996,7 +997,7 @@ impl crate::Device<super::Api> for super::Device {
996997
&self,
997998
fence: &super::Fence,
998999
) -> Result<crate::FenceValue, crate::DeviceError> {
999-
Ok(fence.get_latest(&self.shared.context))
1000+
Ok(fence.get_latest(&self.shared.context.lock()))
10001001
}
10011002
unsafe fn wait(
10021003
&self,
@@ -1005,7 +1006,7 @@ impl crate::Device<super::Api> for super::Device {
10051006
timeout_ms: u32,
10061007
) -> Result<bool, crate::DeviceError> {
10071008
if fence.last_completed < wait_value {
1008-
let gl = &self.shared.context;
1009+
let gl = &self.shared.context.lock();
10091010
let timeout_ns = (timeout_ms as u64 * 1_000_000).min(!0u32 as u64);
10101011
let &(_, sync) = fence
10111012
.pending

0 commit comments

Comments
 (0)