Skip to content

Commit 96fb99a

Browse files
refactor(gles): extract Buffer::{raw,data} into new enum BufferBacking
1 parent bf9f752 commit 96fb99a

File tree

4 files changed

+178
-92
lines changed

4 files changed

+178
-92
lines changed

wgpu-hal/src/gles/command.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use core::{mem, ops::Range};
33

44
use arrayvec::ArrayVec;
55

6-
use super::{conv, Command as C};
6+
use super::{conv, BufferBacking, Command as C};
77

88
#[derive(Clone, Copy, Debug, Default)]
99
struct TextureSlotDesc {
@@ -291,9 +291,13 @@ impl crate::CommandEncoder for super::CommandEncoder {
291291
if !bar.usage.from.contains(wgt::BufferUses::STORAGE_READ_WRITE) {
292292
continue;
293293
}
294+
let buffer = match &bar.buffer.backing {
295+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
296+
BufferBacking::Host { .. } => unreachable!(),
297+
};
294298
self.cmd_buffer
295299
.commands
296-
.push(C::BufferBarrier(bar.buffer.raw.unwrap(), bar.usage.to));
300+
.push(C::BufferBarrier(buffer, bar.usage.to));
297301
}
298302
}
299303

@@ -1001,9 +1005,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
10011005
) {
10021006
self.state.index_offset = binding.offset;
10031007
self.state.index_format = format;
1004-
self.cmd_buffer
1005-
.commands
1006-
.push(C::SetIndexBuffer(binding.buffer.raw.unwrap()));
1008+
let buffer = match &binding.buffer.backing {
1009+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1010+
BufferBacking::Host { .. } => unreachable!(),
1011+
};
1012+
self.cmd_buffer.commands.push(C::SetIndexBuffer(buffer));
10071013
}
10081014
unsafe fn set_vertex_buffer<'a>(
10091015
&mut self,
@@ -1012,8 +1018,12 @@ impl crate::CommandEncoder for super::CommandEncoder {
10121018
) {
10131019
self.state.dirty_vbuf_mask |= 1 << index;
10141020
let (_, ref mut vb) = self.state.vertex_buffers[index as usize];
1021+
let raw = match &binding.buffer.backing {
1022+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1023+
BufferBacking::Host { .. } => unreachable!(),
1024+
};
10151025
*vb = Some(super::BufferBinding {
1016-
raw: binding.buffer.raw.unwrap(),
1026+
raw,
10171027
offset: binding.offset,
10181028
});
10191029
}
@@ -1107,10 +1117,14 @@ impl crate::CommandEncoder for super::CommandEncoder {
11071117
for draw in 0..draw_count as wgt::BufferAddress {
11081118
let indirect_offset =
11091119
offset + draw * size_of::<wgt::DrawIndirectArgs>() as wgt::BufferAddress;
1120+
let indirect_buf = match &buffer.backing {
1121+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1122+
BufferBacking::Host { .. } => unreachable!(),
1123+
};
11101124
#[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation
11111125
self.cmd_buffer.commands.push(C::DrawIndirect {
11121126
topology: self.state.topology,
1113-
indirect_buf: buffer.raw.unwrap(),
1127+
indirect_buf,
11141128
indirect_offset,
11151129
first_instance_location: self.state.first_instance_location.clone(),
11161130
});
@@ -1130,11 +1144,15 @@ impl crate::CommandEncoder for super::CommandEncoder {
11301144
for draw in 0..draw_count as wgt::BufferAddress {
11311145
let indirect_offset =
11321146
offset + draw * size_of::<wgt::DrawIndexedIndirectArgs>() as wgt::BufferAddress;
1147+
let indirect_buf = match &buffer.backing {
1148+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1149+
BufferBacking::Host { .. } => unreachable!(),
1150+
};
11331151
#[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation
11341152
self.cmd_buffer.commands.push(C::DrawIndexedIndirect {
11351153
topology: self.state.topology,
11361154
index_type,
1137-
indirect_buf: buffer.raw.unwrap(),
1155+
indirect_buf,
11381156
indirect_offset,
11391157
first_instance_location: self.state.first_instance_location.clone(),
11401158
});
@@ -1221,8 +1239,12 @@ impl crate::CommandEncoder for super::CommandEncoder {
12211239
self.cmd_buffer.commands.push(C::Dispatch(count));
12221240
}
12231241
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {
1242+
let indirect_buf = match &buffer.backing {
1243+
&BufferBacking::Gl { raw } | &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1244+
BufferBacking::Host { .. } => unreachable!(),
1245+
};
12241246
self.cmd_buffer.commands.push(C::DispatchIndirect {
1225-
indirect_buf: buffer.raw.unwrap(),
1247+
indirect_buf,
12261248
indirect_offset: offset,
12271249
});
12281250
}

wgpu-hal/src/gles/device.rs

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use arrayvec::ArrayVec;
77
use glow::HasContext;
88
use naga::FastHashMap;
99

10-
use super::{conv, lock, MaybeMutex, PrivateCapabilities};
10+
use super::{conv, lock, BufferBacking, MaybeMutex, PrivateCapabilities};
1111
use crate::auxil::map_naga_stage;
1212
use crate::TlasInstance;
1313

@@ -526,13 +526,16 @@ impl crate::Device for super::Device {
526526
.private_caps
527527
.contains(PrivateCapabilities::BUFFER_ALLOCATION);
528528

529+
let host_backed_bytes = || Arc::new(MaybeMutex::new(vec![0; desc.size as usize]));
530+
529531
if emulate_map && desc.usage.intersects(wgt::BufferUses::MAP_WRITE) {
530532
return Ok(super::Buffer {
531-
raw: None,
533+
backing: BufferBacking::Host {
534+
data: host_backed_bytes(),
535+
},
532536
target,
533537
size: desc.size,
534538
map_flags: 0,
535-
data: Some(Arc::new(MaybeMutex::new(vec![0; desc.size as usize]))),
536539
offset_of_current_mapping: Arc::new(MaybeMutex::new(0)),
537540
});
538541
}
@@ -560,8 +563,8 @@ impl crate::Device for super::Device {
560563
map_flags |= glow::MAP_WRITE_BIT;
561564
}
562565

563-
let raw = Some(unsafe { gl.create_buffer() }.map_err(|_| crate::DeviceError::OutOfMemory)?);
564-
unsafe { gl.bind_buffer(target, raw) };
566+
let raw = unsafe { gl.create_buffer() }.map_err(|_| crate::DeviceError::OutOfMemory)?;
567+
unsafe { gl.bind_buffer(target, Some(raw)) };
565568
let raw_size = desc
566569
.size
567570
.try_into()
@@ -614,33 +617,38 @@ impl crate::Device for super::Device {
614617
.private_caps
615618
.contains(PrivateCapabilities::DEBUG_FNS)
616619
{
617-
let name = raw.map_or(0, |buf| buf.0.get());
620+
let name = raw.0.get();
618621
unsafe { gl.object_label(glow::BUFFER, name, Some(label)) };
619622
}
620623
}
621624

622-
let data = if emulate_map && desc.usage.contains(wgt::BufferUses::MAP_READ) {
623-
Some(Arc::new(MaybeMutex::new(vec![0; desc.size as usize])))
625+
let backing = if emulate_map && desc.usage.contains(wgt::BufferUses::MAP_READ) {
626+
BufferBacking::GlCachedOnHost {
627+
cache: host_backed_bytes(),
628+
raw,
629+
}
624630
} else {
625-
None
631+
BufferBacking::Gl { raw }
626632
};
627633

628634
self.counters.buffers.add(1);
629635

630636
Ok(super::Buffer {
631-
raw,
637+
backing,
632638
target,
633639
size: desc.size,
634640
map_flags,
635-
data,
636641
offset_of_current_mapping: Arc::new(MaybeMutex::new(0)),
637642
})
638643
}
639644

640645
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
641-
if let Some(raw) = buffer.raw {
642-
let gl = &self.shared.context.lock();
643-
unsafe { gl.delete_buffer(raw) };
646+
match buffer.backing {
647+
BufferBacking::Gl { raw } | BufferBacking::GlCachedOnHost { raw, cache: _ } => {
648+
let gl = &self.shared.context.lock();
649+
unsafe { gl.delete_buffer(raw) };
650+
}
651+
BufferBacking::Host { data: _ } => {}
644652
}
645653

646654
self.counters.buffers.sub(1);
@@ -656,33 +664,32 @@ impl crate::Device for super::Device {
656664
range: crate::MemoryRange,
657665
) -> Result<crate::BufferMapping, crate::DeviceError> {
658666
let is_coherent = buffer.map_flags & glow::MAP_COHERENT_BIT != 0;
659-
let ptr = match buffer.raw {
660-
None => {
661-
let mut vec = lock(buffer.data.as_ref().unwrap());
667+
let ptr = match &buffer.backing {
668+
BufferBacking::Host { data } => {
669+
let mut vec = lock(data);
662670
let slice = &mut vec.as_mut_slice()[range.start as usize..range.end as usize];
663671
slice.as_mut_ptr()
664672
}
665-
Some(raw) => {
673+
&BufferBacking::Gl { raw } => {
666674
let gl = &self.shared.context.lock();
667675
unsafe { gl.bind_buffer(buffer.target, Some(raw)) };
668-
let ptr = if let Some(ref map_read_allocation) = buffer.data {
669-
let mut guard = lock(map_read_allocation);
670-
let slice = guard.as_mut_slice();
671-
unsafe { self.shared.get_buffer_sub_data(gl, buffer.target, 0, slice) };
672-
slice.as_mut_ptr()
673-
} else {
674-
*lock(&buffer.offset_of_current_mapping) = range.start;
675-
unsafe {
676-
gl.map_buffer_range(
677-
buffer.target,
678-
range.start as i32,
679-
(range.end - range.start) as i32,
680-
buffer.map_flags,
681-
)
682-
}
683-
};
684-
unsafe { gl.bind_buffer(buffer.target, None) };
685-
ptr
676+
*lock(&buffer.offset_of_current_mapping) = range.start;
677+
unsafe {
678+
gl.map_buffer_range(
679+
buffer.target,
680+
range.start as i32,
681+
(range.end - range.start) as i32,
682+
buffer.map_flags,
683+
)
684+
}
685+
}
686+
&BufferBacking::GlCachedOnHost { raw, ref cache } => {
687+
let gl = &self.shared.context.lock();
688+
unsafe { gl.bind_buffer(buffer.target, Some(raw)) };
689+
let mut guard = lock(cache);
690+
let slice = guard.as_mut_slice();
691+
unsafe { self.shared.get_buffer_sub_data(gl, buffer.target, 0, slice) };
692+
slice.as_mut_ptr()
686693
}
687694
};
688695
Ok(crate::BufferMapping {
@@ -691,22 +698,23 @@ impl crate::Device for super::Device {
691698
})
692699
}
693700
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) {
694-
if let Some(raw) = buffer.raw {
695-
if buffer.data.is_none() {
701+
match &buffer.backing {
702+
&BufferBacking::Gl { raw } => {
696703
let gl = &self.shared.context.lock();
697704
unsafe { gl.bind_buffer(buffer.target, Some(raw)) };
698705
unsafe { gl.unmap_buffer(buffer.target) };
699706
unsafe { gl.bind_buffer(buffer.target, None) };
700707
*lock(&buffer.offset_of_current_mapping) = 0;
701708
}
709+
&BufferBacking::Host { .. } | &BufferBacking::GlCachedOnHost { .. } => {}
702710
}
703711
}
704712
unsafe fn flush_mapped_ranges<I>(&self, buffer: &super::Buffer, ranges: I)
705713
where
706714
I: Iterator<Item = crate::MemoryRange>,
707715
{
708-
if let Some(raw) = buffer.raw {
709-
if buffer.data.is_none() {
716+
match &buffer.backing {
717+
&BufferBacking::Gl { raw } => {
710718
let gl = &self.shared.context.lock();
711719
unsafe { gl.bind_buffer(buffer.target, Some(raw)) };
712720
for range in ranges {
@@ -720,6 +728,7 @@ impl crate::Device for super::Device {
720728
};
721729
}
722730
}
731+
&BufferBacking::Host { .. } | &BufferBacking::GlCachedOnHost { .. } => {}
723732
}
724733
}
725734
unsafe fn invalidate_mapped_ranges<I>(&self, _buffer: &super::Buffer, _ranges: I) {
@@ -1261,7 +1270,11 @@ impl crate::Device for super::Device {
12611270
wgt::BindingType::Buffer { .. } => {
12621271
let bb = &desc.buffers[entry.resource_index as usize];
12631272
super::RawBinding::Buffer {
1264-
raw: bb.buffer.raw.unwrap(),
1273+
raw: match &bb.buffer.backing {
1274+
&BufferBacking::Gl { raw }
1275+
| &BufferBacking::GlCachedOnHost { raw, .. } => raw,
1276+
&BufferBacking::Host { .. } => unreachable!(),
1277+
},
12651278
offset: bb.offset as i32,
12661279
size: match bb.size {
12671280
Some(s) => s.get() as i32,

wgpu-hal/src/gles/mod.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,44 @@ impl Drop for Queue {
342342

343343
#[derive(Clone, Debug)]
344344
pub struct Buffer {
345-
raw: Option<glow::Buffer>,
345+
backing: BufferBacking,
346346
target: BindTarget,
347347
size: wgt::BufferAddress,
348348
map_flags: u32,
349-
data: Option<Arc<MaybeMutex<Vec<u8>>>>,
350349
offset_of_current_mapping: Arc<MaybeMutex<wgt::BufferAddress>>,
351350
}
352351

352+
/// Storage backing a [`Buffer`]'s operations, possibly implemented with a host-side vector of
353+
/// bytes.
354+
///
355+
/// The [`Self::OnlyRaw`] variant is preferred, when supported. However, various workarounds for
356+
/// lack of support are needed to implement some operations. See [`Device::create_buffer`] for more
357+
/// details.
358+
#[derive(Clone, Debug)]
359+
enum BufferBacking {
360+
/// A single [`glow::Buffer`] backing all operations.
361+
Gl { raw: glow::Buffer },
362+
/// A synchronized vector of bytes on the host. When needed, a newly created buffer with the
363+
/// contents of `emulated_map_data` will be used for copy operations.
364+
///
365+
/// This variant is used for write-only buffers.
366+
Host { data: Arc<MaybeMutex<Vec<u8>>> },
367+
/// A [`glow::Buffer`] that does not support byte access, and so requires whole copies
368+
/// between a synchronized vector of bytes (`cache`) and a `raw` GL buffer.
369+
GlCachedOnHost {
370+
raw: glow::Buffer,
371+
cache: Arc<MaybeMutex<Vec<u8>>>,
372+
},
373+
}
374+
375+
// #[derive(Clone, Debug)]
376+
// enum MapState {
377+
// Mapped {
378+
// offset: Arc<MaybeMutex<wgt::BufferAddress>>,
379+
// },
380+
// Unmapped,
381+
// }
382+
353383
#[cfg(send_sync)]
354384
unsafe impl Sync for Buffer {}
355385
#[cfg(send_sync)]

0 commit comments

Comments
 (0)