Skip to content

Commit a0c185a

Browse files
committed
[wgpu-core] fix trying to create 0 sized staging buffers when creating mapped_at_creation buffers
This issue was introduced by fabbca2.
1 parent 349f182 commit a0c185a

File tree

4 files changed

+38
-29
lines changed

4 files changed

+38
-29
lines changed

wgpu-core/src/device/queue.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -314,19 +314,19 @@ impl<A: HalApi> PendingWrites<A> {
314314

315315
pub(crate) fn prepare_staging_buffer<A: HalApi>(
316316
device: &Arc<Device<A>>,
317-
size: wgt::BufferAddress,
317+
size: wgt::BufferSize,
318318
instance_flags: wgt::InstanceFlags,
319319
) -> Result<(StagingBuffer<A>, NonNull<u8>), DeviceError> {
320320
profiling::scope!("prepare_staging_buffer");
321321
let stage_desc = hal::BufferDescriptor {
322322
label: hal_label(Some("(wgpu internal) Staging"), instance_flags),
323-
size,
323+
size: size.get(),
324324
usage: hal::BufferUses::MAP_WRITE | hal::BufferUses::COPY_SRC,
325325
memory_flags: hal::MemoryFlags::TRANSIENT,
326326
};
327327

328328
let buffer = unsafe { device.raw().create_buffer(&stage_desc)? };
329-
let mapping = unsafe { device.raw().map_buffer(&buffer, 0..size) }?;
329+
let mapping = unsafe { device.raw().map_buffer(&buffer, 0..size.get()) }?;
330330

331331
let staging_buffer = StagingBuffer {
332332
raw: Mutex::new(rank::STAGING_BUFFER_RAW, Some(buffer)),
@@ -344,7 +344,7 @@ impl<A: HalApi> StagingBuffer<A> {
344344
unsafe {
345345
device.flush_mapped_ranges(
346346
self.raw.lock().as_ref().unwrap(),
347-
iter::once(0..self.size),
347+
iter::once(0..self.size.get()),
348348
)
349349
};
350350
}
@@ -435,10 +435,12 @@ impl Global {
435435

436436
buffer.same_device_as(queue.as_ref())?;
437437

438-
if data_size == 0 {
438+
let data_size = if let Some(data_size) = wgt::BufferSize::new(data_size) {
439+
data_size
440+
} else {
439441
log::trace!("Ignoring write_buffer of size 0");
440442
return Ok(());
441-
}
443+
};
442444

443445
// Platform validation requires that the staging buffer always be
444446
// freed, even if an error occurs. All paths from here must call
@@ -450,7 +452,11 @@ impl Global {
450452

451453
if let Err(flush_error) = unsafe {
452454
profiling::scope!("copy");
453-
ptr::copy_nonoverlapping(data.as_ptr(), staging_buffer_ptr.as_ptr(), data.len());
455+
ptr::copy_nonoverlapping(
456+
data.as_ptr(),
457+
staging_buffer_ptr.as_ptr(),
458+
data_size.get() as usize,
459+
);
454460
staging_buffer.flush(device.raw())
455461
} {
456462
pending_writes.consume(staging_buffer);
@@ -487,7 +493,7 @@ impl Global {
487493
let device = &queue.device;
488494

489495
let (staging_buffer, staging_buffer_ptr) =
490-
prepare_staging_buffer(device, buffer_size.get(), device.instance_flags)?;
496+
prepare_staging_buffer(device, buffer_size, device.instance_flags)?;
491497

492498
let fid = hub.staging_buffers.prepare(id_in);
493499
let id = fid.assign(Arc::new(staging_buffer));
@@ -549,7 +555,7 @@ impl Global {
549555
_queue_id: QueueId,
550556
buffer_id: id::BufferId,
551557
buffer_offset: u64,
552-
buffer_size: u64,
558+
buffer_size: wgt::BufferSize,
553559
) -> Result<(), QueueWriteError> {
554560
profiling::scope!("Queue::validate_write_buffer");
555561
let hub = A::hub(self);
@@ -568,19 +574,19 @@ impl Global {
568574
&self,
569575
buffer: &Buffer<A>,
570576
buffer_offset: u64,
571-
buffer_size: u64,
577+
buffer_size: wgt::BufferSize,
572578
) -> Result<(), TransferError> {
573579
buffer.check_usage(wgt::BufferUsages::COPY_DST)?;
574-
if buffer_size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
575-
return Err(TransferError::UnalignedCopySize(buffer_size));
580+
if buffer_size.get() % wgt::COPY_BUFFER_ALIGNMENT != 0 {
581+
return Err(TransferError::UnalignedCopySize(buffer_size.get()));
576582
}
577583
if buffer_offset % wgt::COPY_BUFFER_ALIGNMENT != 0 {
578584
return Err(TransferError::UnalignedBufferOffset(buffer_offset));
579585
}
580-
if buffer_offset + buffer_size > buffer.size {
586+
if buffer_offset + buffer_size.get() > buffer.size {
581587
return Err(TransferError::BufferOverrun {
582588
start_offset: buffer_offset,
583-
end_offset: buffer_offset + buffer_size,
589+
end_offset: buffer_offset + buffer_size.get(),
584590
buffer_size: buffer.size,
585591
side: CopySide::Destination,
586592
});
@@ -615,16 +621,15 @@ impl Global {
615621

616622
dst.same_device_as(queue.as_ref())?;
617623

618-
let src_buffer_size = staging_buffer.size;
619-
self.queue_validate_write_buffer_impl(&dst, buffer_offset, src_buffer_size)?;
624+
self.queue_validate_write_buffer_impl(&dst, buffer_offset, staging_buffer.size)?;
620625

621626
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
622627

623-
let region = wgt::BufferSize::new(src_buffer_size).map(|size| hal::BufferCopy {
628+
let region = hal::BufferCopy {
624629
src_offset: 0,
625630
dst_offset: buffer_offset,
626-
size,
627-
});
631+
size: staging_buffer.size,
632+
};
628633
let inner_buffer = staging_buffer.raw.lock();
629634
let barriers = iter::once(hal::BufferBarrier {
630635
buffer: inner_buffer.as_ref().unwrap(),
@@ -637,7 +642,7 @@ impl Global {
637642
encoder.copy_buffer_to_buffer(
638643
inner_buffer.as_ref().unwrap(),
639644
dst_raw,
640-
region.into_iter(),
645+
iter::once(region),
641646
);
642647
}
643648

@@ -648,7 +653,7 @@ impl Global {
648653
{
649654
dst.initialization_status
650655
.write()
651-
.drain(buffer_offset..(buffer_offset + src_buffer_size));
656+
.drain(buffer_offset..(buffer_offset + staging_buffer.size.get()));
652657
}
653658

654659
Ok(())
@@ -760,7 +765,8 @@ impl Global {
760765

761766
let block_rows_in_copy =
762767
(size.depth_or_array_layers - 1) * block_rows_per_image + height_blocks;
763-
let stage_size = stage_bytes_per_row as u64 * block_rows_in_copy as u64;
768+
let stage_size =
769+
wgt::BufferSize::new(stage_bytes_per_row as u64 * block_rows_in_copy as u64).unwrap();
764770

765771
let mut pending_writes = device.pending_writes.lock();
766772
let pending_writes = pending_writes.as_mut().unwrap();
@@ -836,7 +842,7 @@ impl Global {
836842
ptr::copy_nonoverlapping(
837843
data.as_ptr().offset(data_layout.offset as isize),
838844
staging_buffer_ptr.as_ptr(),
839-
stage_size as usize,
845+
stage_size.get() as usize,
840846
);
841847
}
842848
} else {

wgpu-core/src/device/resource.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,13 +591,16 @@ impl<A: HalApi> Device<A> {
591591
};
592592
hal::BufferUses::MAP_WRITE
593593
} else {
594-
let (staging_buffer, staging_buffer_ptr) =
595-
queue::prepare_staging_buffer(self, desc.size, self.instance_flags)?;
594+
let (staging_buffer, staging_buffer_ptr) = queue::prepare_staging_buffer(
595+
self,
596+
wgt::BufferSize::new(aligned_size).unwrap(),
597+
self.instance_flags,
598+
)?;
596599

597600
// Zero initialize memory and then mark the buffer as initialized
598601
// (it's guaranteed that this is the case by the time the buffer is usable)
599-
unsafe { std::ptr::write_bytes(staging_buffer_ptr.as_ptr(), 0, buffer.size as usize) };
600-
buffer.initialization_status.write().drain(0..buffer.size);
602+
unsafe { std::ptr::write_bytes(staging_buffer_ptr.as_ptr(), 0, aligned_size as usize) };
603+
buffer.initialization_status.write().drain(0..aligned_size);
601604

602605
*buffer.map_state.lock() = resource::BufferMapState::Init {
603606
staging_buffer,

wgpu-core/src/resource.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ impl<A: HalApi> Drop for DestroyedBuffer<A> {
867867
pub struct StagingBuffer<A: HalApi> {
868868
pub(crate) raw: Mutex<Option<A::Buffer>>,
869869
pub(crate) device: Arc<Device<A>>,
870-
pub(crate) size: wgt::BufferAddress,
870+
pub(crate) size: wgt::BufferSize,
871871
pub(crate) is_coherent: bool,
872872
}
873873

wgpu/src/backend/wgpu_core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2203,7 +2203,7 @@ impl crate::Context for ContextWgpuCore {
22032203
size: wgt::BufferSize,
22042204
) -> Option<()> {
22052205
match wgc::gfx_select!(
2206-
*queue => self.0.queue_validate_write_buffer(*queue, *buffer, offset, size.get())
2206+
*queue => self.0.queue_validate_write_buffer(*queue, *buffer, offset, size)
22072207
) {
22082208
Ok(()) => Some(()),
22092209
Err(err) => {

0 commit comments

Comments
 (0)