Skip to content

Commit 8c3879e

Browse files
committed
Move set_buffer_data and get_mapped_range out of Global
1 parent 4dbc32f commit 8c3879e

File tree

3 files changed

+146
-62
lines changed

3 files changed

+146
-62
lines changed

wgpu-core/src/device/global.rs

Lines changed: 4 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
},
1212
command::{self, CommandEncoder},
1313
conv,
14-
device::{bgl, life::WaitIdleError, DeviceError, DeviceLostClosure},
14+
device::{life::WaitIdleError, DeviceError, DeviceLostClosure},
1515
global::Global,
1616
id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
1717
instance::{self, Adapter, Surface},
@@ -222,51 +222,9 @@ impl Global {
222222
offset: BufferAddress,
223223
data: &[u8],
224224
) -> BufferAccessResult {
225-
use crate::resource::RawResourceAccess;
226-
227-
let hub = &self.hub;
228-
229-
let buffer = hub.buffers.get(buffer_id).get()?;
230-
225+
let buffer = self.hub.buffers.get(buffer_id).get()?;
231226
let device = &buffer.device;
232-
233-
device.check_is_valid()?;
234-
buffer.check_usage(wgt::BufferUsages::MAP_WRITE)?;
235-
236-
let last_submission = device.get_queue().and_then(|queue| {
237-
queue
238-
.lock_life()
239-
.get_buffer_latest_submission_index(&buffer)
240-
});
241-
242-
if let Some(last_submission) = last_submission {
243-
device.wait_for_submit(last_submission)?;
244-
}
245-
246-
let snatch_guard = device.snatchable_lock.read();
247-
let raw_buf = buffer.try_raw(&snatch_guard)?;
248-
249-
let mapping = unsafe {
250-
device
251-
.raw()
252-
.map_buffer(raw_buf, offset..offset + data.len() as u64)
253-
}
254-
.map_err(|e| device.handle_hal_error(e))?;
255-
256-
unsafe { core::ptr::copy_nonoverlapping(data.as_ptr(), mapping.ptr.as_ptr(), data.len()) };
257-
258-
if !mapping.is_coherent {
259-
#[allow(clippy::single_range_in_vec_init)]
260-
unsafe {
261-
device
262-
.raw()
263-
.flush_mapped_ranges(raw_buf, &[offset..offset + data.len() as u64])
264-
};
265-
}
266-
267-
unsafe { device.raw().unmap_buffer(raw_buf) };
268-
269-
Ok(())
227+
device.set_buffer_data(&buffer, offset, data)
270228
}
271229

272230
pub fn buffer_destroy(&self, buffer_id: id::BufferId) {
@@ -693,21 +651,7 @@ impl Global {
693651
break 'error e.into();
694652
}
695653

696-
let entry_map = match bgl::EntryMap::from_entries(&device.limits, &desc.entries) {
697-
Ok(map) => map,
698-
Err(e) => break 'error e,
699-
};
700-
701-
let bgl_result = device.bgl_pool.get_or_init(entry_map, |entry_map| {
702-
let bgl =
703-
device.create_bind_group_layout(&desc.label, entry_map, bgl::Origin::Pool)?;
704-
bgl.exclusive_pipeline
705-
.set(binding_model::ExclusivePipeline::None)
706-
.unwrap();
707-
Ok(bgl)
708-
});
709-
710-
let layout = match bgl_result {
654+
let layout = match device.create_bind_group_layout(desc) {
711655
Ok(layout) => layout,
712656
Err(e) => break 'error e,
713657
};

wgpu-core/src/device/resource.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,54 @@ impl Device {
10291029
Ok(buffer)
10301030
}
10311031

1032+
#[cfg(feature = "replay")]
1033+
pub fn set_buffer_data(
1034+
self: &Arc<Self>,
1035+
buffer: &Arc<Buffer>,
1036+
offset: wgt::BufferAddress,
1037+
data: &[u8],
1038+
) -> resource::BufferAccessResult {
1039+
use crate::resource::RawResourceAccess;
1040+
1041+
let device = &buffer.device;
1042+
1043+
device.check_is_valid()?;
1044+
buffer.check_usage(wgt::BufferUsages::MAP_WRITE)?;
1045+
1046+
let last_submission = device
1047+
.get_queue()
1048+
.and_then(|queue| queue.lock_life().get_buffer_latest_submission_index(buffer));
1049+
1050+
if let Some(last_submission) = last_submission {
1051+
device.wait_for_submit(last_submission)?;
1052+
}
1053+
1054+
let snatch_guard = device.snatchable_lock.read();
1055+
let raw_buf = buffer.try_raw(&snatch_guard)?;
1056+
1057+
let mapping = unsafe {
1058+
device
1059+
.raw()
1060+
.map_buffer(raw_buf, offset..offset + data.len() as u64)
1061+
}
1062+
.map_err(|e| device.handle_hal_error(e))?;
1063+
1064+
unsafe { core::ptr::copy_nonoverlapping(data.as_ptr(), mapping.ptr.as_ptr(), data.len()) };
1065+
1066+
if !mapping.is_coherent {
1067+
#[allow(clippy::single_range_in_vec_init)]
1068+
unsafe {
1069+
device
1070+
.raw()
1071+
.flush_mapped_ranges(raw_buf, &[offset..offset + data.len() as u64])
1072+
};
1073+
}
1074+
1075+
unsafe { device.raw().unmap_buffer(raw_buf) };
1076+
1077+
Ok(())
1078+
}
1079+
10321080
pub(crate) fn create_texture_from_hal(
10331081
self: &Arc<Self>,
10341082
hal_texture: Box<dyn hal::DynTexture>,
@@ -2279,7 +2327,33 @@ impl Device {
22792327
.collect()
22802328
}
22812329

2282-
pub(crate) fn create_bind_group_layout(
2330+
pub fn create_bind_group_layout(
2331+
self: &Arc<Self>,
2332+
desc: &binding_model::BindGroupLayoutDescriptor,
2333+
) -> Result<Arc<BindGroupLayout>, binding_model::CreateBindGroupLayoutError> {
2334+
// this check can't go in the body of `create_bind_group_layout_internal` since the closure might not get called
2335+
self.check_is_valid()?;
2336+
2337+
let entry_map = bgl::EntryMap::from_entries(&self.limits, &desc.entries)?;
2338+
2339+
let bgl_result = self.bgl_pool.get_or_init(entry_map, |entry_map| {
2340+
let bgl =
2341+
self.create_bind_group_layout_internal(&desc.label, entry_map, bgl::Origin::Pool)?;
2342+
bgl.exclusive_pipeline
2343+
.set(binding_model::ExclusivePipeline::None)
2344+
.unwrap();
2345+
Ok(bgl)
2346+
});
2347+
2348+
match bgl_result {
2349+
Ok(layout) => Ok(layout),
2350+
Err(e) => Err(e),
2351+
}
2352+
}
2353+
2354+
/// Internal function exposed for use by `player` crate only.
2355+
#[doc(hidden)]
2356+
pub fn create_bind_group_layout_internal(
22832357
self: &Arc<Self>,
22842358
label: &crate::Label,
22852359
entry_map: bgl::EntryMap,
@@ -3473,7 +3547,7 @@ impl Device {
34733547
match unique_bind_group_layouts.entry(bgl_entry_map) {
34743548
hashbrown::hash_map::Entry::Occupied(v) => Ok(Arc::clone(v.get())),
34753549
hashbrown::hash_map::Entry::Vacant(e) => {
3476-
match self.create_bind_group_layout(
3550+
match self.create_bind_group_layout_internal(
34773551
&None,
34783552
e.key().clone(),
34793553
bgl::Origin::Derived,

wgpu-core/src/resource.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,72 @@ impl Buffer {
677677
Ok(submit_index)
678678
}
679679

680+
pub fn get_mapped_range(
681+
self: &Arc<Self>,
682+
offset: wgt::BufferAddress,
683+
size: Option<wgt::BufferAddress>,
684+
) -> Result<(NonNull<u8>, u64), BufferAccessError> {
685+
{
686+
let snatch_guard = self.device.snatchable_lock.read();
687+
self.check_destroyed(&snatch_guard)?;
688+
}
689+
690+
let range_size = if let Some(size) = size {
691+
size
692+
} else {
693+
self.size.saturating_sub(offset)
694+
};
695+
696+
if offset % wgt::MAP_ALIGNMENT != 0 {
697+
return Err(BufferAccessError::UnalignedOffset { offset });
698+
}
699+
if range_size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
700+
return Err(BufferAccessError::UnalignedRangeSize { range_size });
701+
}
702+
let map_state = &*self.map_state.lock();
703+
match *map_state {
704+
BufferMapState::Init { ref staging_buffer } => {
705+
// offset (u64) can not be < 0, so no need to validate the lower bound
706+
if offset + range_size > self.size {
707+
return Err(BufferAccessError::OutOfBoundsOverrun {
708+
index: offset + range_size - 1,
709+
max: self.size,
710+
});
711+
}
712+
let ptr = unsafe { staging_buffer.ptr() };
713+
let ptr = unsafe { NonNull::new_unchecked(ptr.as_ptr().offset(offset as isize)) };
714+
Ok((ptr, range_size))
715+
}
716+
BufferMapState::Active {
717+
ref mapping,
718+
ref range,
719+
..
720+
} => {
721+
if offset < range.start {
722+
return Err(BufferAccessError::OutOfBoundsUnderrun {
723+
index: offset,
724+
min: range.start,
725+
});
726+
}
727+
if offset + range_size > range.end {
728+
return Err(BufferAccessError::OutOfBoundsOverrun {
729+
index: offset + range_size - 1,
730+
max: range.end,
731+
});
732+
}
733+
// ptr points to the beginning of the range we mapped in map_async
734+
// rather than the beginning of the buffer.
735+
let relative_offset = (offset - range.start) as isize;
736+
unsafe {
737+
Ok((
738+
NonNull::new_unchecked(mapping.ptr.as_ptr().offset(relative_offset)),
739+
range_size,
740+
))
741+
}
742+
}
743+
BufferMapState::Idle | BufferMapState::Waiting(_) => Err(BufferAccessError::NotMapped),
744+
}
745+
}
680746
/// This function returns [`None`] only if [`Self::map_state`] is not [`BufferMapState::Waiting`].
681747
#[must_use]
682748
pub(crate) fn map(&self, snatch_guard: &SnatchGuard) -> Option<BufferMapPendingClosure> {

0 commit comments

Comments
 (0)