diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index 7aaaf7fcf9..f16468ad57 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -201,10 +201,9 @@ impl crate::CommandEncoder for super::CommandEncoder { if !bar.usage.start.contains(crate::BufferUses::STORAGE_WRITE) { continue; } - self.cmd_buffer.commands.push(C::BufferBarrier( - bar.buffer.inner.as_native().unwrap(), - bar.usage.end, - )); + self.cmd_buffer + .commands + .push(C::BufferBarrier(bar.buffer.raw.unwrap(), bar.usage.end)); } } @@ -239,7 +238,7 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn clear_buffer(&mut self, buffer: &super::Buffer, range: crate::MemoryRange) { self.cmd_buffer.commands.push(C::ClearBuffer { - dst: buffer.inner.clone(), + dst: buffer.clone(), dst_target: buffer.target, range, }); @@ -260,9 +259,9 @@ impl crate::CommandEncoder for super::CommandEncoder { }; for copy in regions { self.cmd_buffer.commands.push(C::CopyBufferToBuffer { - src: src.inner.clone(), + src: src.clone(), src_target, - dst: dst.inner.clone(), + dst: dst.clone(), dst_target, copy, }) @@ -305,7 +304,7 @@ impl crate::CommandEncoder for super::CommandEncoder { for mut copy in regions { copy.clamp_size_to_virtual(&dst.copy_size); self.cmd_buffer.commands.push(C::CopyBufferToTexture { - src: src.inner.clone(), + src: src.clone(), src_target: src.target, dst: dst_raw, dst_target, @@ -331,7 +330,7 @@ impl crate::CommandEncoder for super::CommandEncoder { src: src_raw, src_target, src_format: src.format, - dst: dst.inner.clone(), + dst: dst.clone(), dst_target: dst.target, copy, }) @@ -368,7 +367,7 @@ impl crate::CommandEncoder for super::CommandEncoder { let query_range = start as u32..self.cmd_buffer.queries.len() as u32; self.cmd_buffer.commands.push(C::CopyQueryResults { query_range, - dst: buffer.inner.clone(), + dst: buffer.clone(), dst_target: buffer.target, dst_offset: offset, }); @@ -742,7 +741,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.state.index_format = format; self.cmd_buffer .commands - .push(C::SetIndexBuffer(binding.buffer.inner.as_native().unwrap())); + .push(C::SetIndexBuffer(binding.buffer.raw.unwrap())); } unsafe fn set_vertex_buffer<'a>( &mut self, @@ -752,7 +751,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.state.dirty_vbuf_mask |= 1 << index; let (_, ref mut vb) = self.state.vertex_buffers[index as usize]; *vb = Some(super::BufferBinding { - raw: binding.buffer.inner.as_native().unwrap(), + raw: binding.buffer.raw.unwrap(), offset: binding.offset, }); } @@ -834,7 +833,7 @@ impl crate::CommandEncoder for super::CommandEncoder { offset + draw * mem::size_of::() as wgt::BufferAddress; self.cmd_buffer.commands.push(C::DrawIndirect { topology: self.state.topology, - indirect_buf: buffer.inner.as_native().unwrap(), + indirect_buf: buffer.raw.unwrap(), indirect_offset, }); } @@ -856,7 +855,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.cmd_buffer.commands.push(C::DrawIndexedIndirect { topology: self.state.topology, index_type, - indirect_buf: buffer.inner.as_native().unwrap(), + indirect_buf: buffer.raw.unwrap(), indirect_offset, }); } @@ -907,7 +906,7 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) { self.cmd_buffer.commands.push(C::DispatchIndirect { - indirect_buf: buffer.inner.as_native().unwrap(), + indirect_buf: buffer.raw.unwrap(), indirect_offset: offset, }); } diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 39dfc7d10d..12da76355e 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -1,7 +1,11 @@ -use super::{conv, BufferInner}; +use super::conv; use crate::auxil::map_naga_stage; use glow::HasContext; -use std::{convert::TryInto, iter, ptr, sync::Arc}; +use std::{ + convert::TryInto, + iter, ptr, + sync::{Arc, Mutex}, +}; #[cfg(not(target_arch = "wasm32"))] use std::mem; @@ -329,16 +333,13 @@ impl crate::Device for super::Device { .private_caps .contains(super::PrivateCapabilities::BUFFER_ALLOCATION); - if emulate_map - && desc - .usage - .intersects(crate::BufferUses::MAP_WRITE | crate::BufferUses::MAP_READ) - { + if emulate_map && desc.usage.intersects(crate::BufferUses::MAP_WRITE) { return Ok(super::Buffer { - inner: BufferInner::data_with_capacity(desc.size), + raw: None, target, size: desc.size, map_flags: 0, + data: Some(Arc::new(Mutex::new(vec![0; desc.size as usize]))), }); } @@ -365,8 +366,8 @@ impl crate::Device for super::Device { map_flags |= glow::MAP_WRITE_BIT; } - let raw = gl.create_buffer().unwrap(); - gl.bind_buffer(target, Some(raw)); + let raw = Some(gl.create_buffer().unwrap()); + gl.bind_buffer(target, raw); let raw_size = desc .size .try_into() @@ -412,15 +413,22 @@ impl crate::Device for super::Device { } } + let data = if emulate_map && desc.usage.contains(crate::BufferUses::MAP_READ) { + Some(Arc::new(Mutex::new(vec![0; desc.size as usize]))) + } else { + None + }; + Ok(super::Buffer { - inner: BufferInner::Buffer(raw), + raw, target, size: desc.size, map_flags, + data, }) } unsafe fn destroy_buffer(&self, buffer: super::Buffer) { - if let BufferInner::Buffer(raw) = buffer.inner { + if let Some(raw) = buffer.raw { let gl = &self.shared.context.lock(); gl.delete_buffer(raw); } @@ -432,21 +440,28 @@ impl crate::Device for super::Device { range: crate::MemoryRange, ) -> Result { let is_coherent = buffer.map_flags & glow::MAP_COHERENT_BIT != 0; - let ptr = match buffer.inner { - BufferInner::Data(ref data) => { - let mut vec = data.lock().unwrap(); + let ptr = match buffer.raw { + None => { + let mut vec = buffer.data.as_ref().unwrap().lock().unwrap(); let slice = &mut vec.as_mut_slice()[range.start as usize..range.end as usize]; slice.as_mut_ptr() } - BufferInner::Buffer(raw) => { + Some(raw) => { let gl = &self.shared.context.lock(); gl.bind_buffer(buffer.target, Some(raw)); - let ptr = gl.map_buffer_range( - buffer.target, - range.start as i32, - (range.end - range.start) as i32, - buffer.map_flags, - ); + let ptr = if let Some(ref map_read_allocation) = buffer.data { + let mut guard = map_read_allocation.lock().unwrap(); + let slice = guard.as_mut_slice(); + gl.get_buffer_sub_data(buffer.target, 0, slice); + slice.as_mut_ptr() + } else { + gl.map_buffer_range( + buffer.target, + range.start as i32, + (range.end - range.start) as i32, + buffer.map_flags, + ) + }; gl.bind_buffer(buffer.target, None); ptr } @@ -457,11 +472,17 @@ impl crate::Device for super::Device { }) } unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> { - if let BufferInner::Buffer(raw) = buffer.inner { - let gl = &self.shared.context.lock(); - gl.bind_buffer(buffer.target, Some(raw)); - gl.unmap_buffer(buffer.target); - gl.bind_buffer(buffer.target, None); + if let Some(raw) = buffer.raw { + if !self + .shared + .workarounds + .contains(super::Workarounds::EMULATE_BUFFER_MAP) + { + let gl = &self.shared.context.lock(); + gl.bind_buffer(buffer.target, Some(raw)); + gl.unmap_buffer(buffer.target); + gl.bind_buffer(buffer.target, None); + } } Ok(()) } @@ -469,7 +490,7 @@ impl crate::Device for super::Device { where I: Iterator, { - if let BufferInner::Buffer(raw) = buffer.inner { + if let Some(raw) = buffer.raw { let gl = &self.shared.context.lock(); gl.bind_buffer(buffer.target, Some(raw)); for range in ranges { @@ -862,7 +883,7 @@ impl crate::Device for super::Device { wgt::BindingType::Buffer { .. } => { let bb = &desc.buffers[entry.resource_index as usize]; super::RawBinding::Buffer { - raw: bb.buffer.inner.as_native().unwrap(), + raw: bb.buffer.raw.unwrap(), offset: bb.offset as i32, size: match bb.size { Some(s) => s.get() as i32, @@ -1094,15 +1115,25 @@ impl crate::Device for super::Device { wait_value: crate::FenceValue, timeout_ms: u32, ) -> Result { - if cfg!(not(target_arch = "wasm32")) && fence.last_completed < wait_value { + if fence.last_completed < wait_value { let gl = &self.shared.context.lock(); - let timeout_ns = (timeout_ms as u64 * 1_000_000).min(!0u32 as u64); + let timeout_ns = if cfg!(target_arch = "wasm32") { + 0 + } else { + (timeout_ms as u64 * 1_000_000).min(!0u32 as u64) + }; let &(_, sync) = fence .pending .iter() .find(|&&(value, _)| value >= wait_value) .unwrap(); match gl.client_wait_sync(sync, glow::SYNC_FLUSH_COMMANDS_BIT, timeout_ns as i32) { + // for some reason firefox returns WAIT_FAILED, to investigate + #[cfg(target_arch = "wasm32")] + glow::WAIT_FAILED => { + log::warn!("wait failed!"); + Ok(false) + } glow::TIMEOUT_EXPIRED => Ok(false), glow::CONDITION_SATISFIED | glow::ALREADY_SIGNALED => Ok(true), _ => Err(crate::DeviceError::Lost), diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 9330c1822c..df89f4c26e 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -210,30 +210,13 @@ pub struct Queue { current_index_buffer: Option, } -#[derive(Debug, Clone)] -pub enum BufferInner { - Buffer(glow::Buffer), - Data(Arc>>), -} - -impl BufferInner { - pub fn data_with_capacity(size: u64) -> BufferInner { - BufferInner::Data(Arc::new(std::sync::Mutex::new(vec![0; size as usize]))) - } - pub fn as_native(&self) -> Option { - match *self { - BufferInner::Buffer(ref buffer) => Some(*buffer), - BufferInner::Data(_) => None, - } - } -} - -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Buffer { - inner: BufferInner, + raw: Option, target: BindTarget, size: wgt::BufferAddress, map_flags: u32, + data: Option>>>, } // Safe: WASM doesn't have threads @@ -584,14 +567,14 @@ enum Command { indirect_offset: wgt::BufferAddress, }, ClearBuffer { - dst: BufferInner, + dst: Buffer, dst_target: BindTarget, range: crate::MemoryRange, }, CopyBufferToBuffer { - src: BufferInner, + src: Buffer, src_target: BindTarget, - dst: BufferInner, + dst: Buffer, dst_target: BindTarget, copy: crate::BufferCopy, }, @@ -603,7 +586,7 @@ enum Command { copy: crate::TextureCopy, }, CopyBufferToTexture { - src: BufferInner, + src: Buffer, #[allow(unused)] src_target: BindTarget, dst: glow::Texture, @@ -615,7 +598,7 @@ enum Command { src: glow::Texture, src_target: BindTarget, src_format: wgt::TextureFormat, - dst: BufferInner, + dst: Buffer, #[allow(unused)] dst_target: BindTarget, copy: crate::BufferTextureCopy, @@ -625,7 +608,7 @@ enum Command { EndQuery(BindTarget), CopyQueryResults { query_range: Range, - dst: BufferInner, + dst: Buffer, dst_target: BindTarget, dst_offset: wgt::BufferAddress, }, diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index 2bb3c61f04..f664bda055 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -205,8 +205,8 @@ impl super::Queue { ref dst, dst_target, ref range, - } => match *dst { - super::BufferInner::Buffer(buffer) => { + } => match dst.raw { + Some(buffer) => { gl.bind_buffer(glow::COPY_READ_BUFFER, Some(self.zero_buffer)); gl.bind_buffer(dst_target, Some(buffer)); let mut dst_offset = range.start; @@ -222,8 +222,9 @@ impl super::Queue { dst_offset += size; } } - super::BufferInner::Data(ref data) => { - data.lock().unwrap().as_mut_slice()[range.start as usize..range.end as usize] + None => { + dst.data.as_ref().unwrap().lock().unwrap().as_mut_slice() + [range.start as usize..range.end as usize] .fill(0); } }, @@ -249,11 +250,8 @@ impl super::Queue { glow::COPY_WRITE_BUFFER }; let size = copy.size.get() as usize; - match (src, dst) { - ( - &super::BufferInner::Buffer(ref src), - &super::BufferInner::Buffer(ref dst), - ) => { + match (src.raw, dst.raw) { + (Some(ref src), Some(ref dst)) => { gl.bind_buffer(copy_src_target, Some(*src)); gl.bind_buffer(copy_dst_target, Some(*dst)); gl.copy_buffer_sub_data( @@ -264,16 +262,16 @@ impl super::Queue { copy.size.get() as _, ); } - (&super::BufferInner::Buffer(src), &super::BufferInner::Data(ref data)) => { - let mut data = data.lock().unwrap(); + (Some(src), None) => { + let mut data = dst.data.as_ref().unwrap().lock().unwrap(); let dst_data = &mut data.as_mut_slice() [copy.dst_offset as usize..copy.dst_offset as usize + size]; gl.bind_buffer(copy_src_target, Some(src)); gl.get_buffer_sub_data(copy_src_target, copy.src_offset as i32, dst_data); } - (&super::BufferInner::Data(ref data), &super::BufferInner::Buffer(dst)) => { - let data = data.lock().unwrap(); + (None, Some(dst)) => { + let data = src.data.as_ref().unwrap().lock().unwrap(); let src_data = &data.as_slice() [copy.src_offset as usize..copy.src_offset as usize + size]; gl.bind_buffer(copy_dst_target, Some(dst)); @@ -283,7 +281,7 @@ impl super::Queue { src_data, ); } - (&super::BufferInner::Data(_), &super::BufferInner::Data(_)) => { + (None, None) => { todo!() } } @@ -374,14 +372,14 @@ impl super::Queue { let mut unbind_unpack_buffer = false; if format_info.block_dimensions == (1, 1) { let buffer_data; - let unpack_data = match *src { - super::BufferInner::Buffer(buffer) => { + let unpack_data = match src.raw { + Some(buffer) => { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(buffer)); unbind_unpack_buffer = true; glow::PixelUnpackData::BufferOffset(copy.buffer_layout.offset as u32) } - super::BufferInner::Data(ref data) => { - buffer_data = data.lock().unwrap(); + None => { + buffer_data = src.data.as_ref().unwrap().lock().unwrap(); let src_data = &buffer_data.as_slice()[copy.buffer_layout.offset as usize..]; glow::PixelUnpackData::Slice(src_data) @@ -454,16 +452,16 @@ impl super::Queue { let offset = copy.buffer_layout.offset as u32; let buffer_data; - let unpack_data = match *src { - super::BufferInner::Buffer(buffer) => { + let unpack_data = match src.raw { + Some(buffer) => { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(buffer)); unbind_unpack_buffer = true; glow::CompressedPixelUnpackData::BufferRange( offset..offset + bytes_per_image, ) } - super::BufferInner::Data(ref data) => { - buffer_data = data.lock().unwrap(); + None => { + buffer_data = src.data.as_ref().unwrap().lock().unwrap(); let src_data = &buffer_data.as_slice() [(offset as usize)..(offset + bytes_per_image) as usize]; glow::CompressedPixelUnpackData::Slice(src_data) @@ -578,14 +576,14 @@ impl super::Queue { ); } let mut buffer_data; - let unpack_data = match *dst { - super::BufferInner::Buffer(buffer) => { + let unpack_data = match dst.raw { + Some(buffer) => { gl.pixel_store_i32(glow::PACK_ROW_LENGTH, row_texels as i32); gl.bind_buffer(glow::PIXEL_PACK_BUFFER, Some(buffer)); glow::PixelPackData::BufferOffset(copy.buffer_layout.offset as u32) } - super::BufferInner::Data(ref data) => { - buffer_data = data.lock().unwrap(); + None => { + buffer_data = dst.data.as_ref().unwrap().lock().unwrap(); let dst_data = &mut buffer_data.as_mut_slice()[copy.buffer_layout.offset as usize..]; glow::PixelPackData::Slice(dst_data) @@ -626,13 +624,13 @@ impl super::Queue { self.temp_query_results.as_ptr() as *const u8, self.temp_query_results.len() * mem::size_of::(), ); - match *dst { - super::BufferInner::Buffer(buffer) => { + match dst.raw { + Some(buffer) => { gl.bind_buffer(dst_target, Some(buffer)); gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data); } - super::BufferInner::Data(ref data) => { - let data = &mut *data.lock().unwrap(); + None => { + let data = &mut dst.data.as_ref().unwrap().lock().unwrap(); let len = query_data.len().min(data.len()); data[..len].copy_from_slice(&query_data[..len]); }