use std::{
ops::{Deref, DerefMut},
sync::Arc,
thread,
};
use crate::context::{DynContext, QueueWriteBuffer};
use crate::*;
#[derive(Debug)]
pub struct Queue {
pub(crate) context: Arc<C>,
pub(crate) data: Box<Data>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(Queue: Send, Sync);
impl Drop for Queue {
fn drop(&mut self) {
if !thread::panicking() {
self.context.queue_drop(self.data.as_ref());
}
}
}
#[derive(Debug, Clone)]
pub struct SubmissionIndex {
#[cfg_attr(not(native), allow(dead_code))]
pub(crate) data: Arc<crate::Data>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync);
pub use wgt::Maintain as MaintainBase;
pub type Maintain = wgt::Maintain<SubmissionIndex>;
#[cfg(send_sync)]
static_assertions::assert_impl_all!(Maintain: Send, Sync);
pub struct QueueWriteBufferView<'a> {
queue: &'a Queue,
buffer: &'a Buffer,
offset: BufferAddress,
inner: Box<dyn QueueWriteBuffer>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(QueueWriteBufferView<'_>: Send, Sync);
impl Deref for QueueWriteBufferView<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
log::warn!("Reading from a QueueWriteBufferView won't yield the contents of the buffer and may be slow.");
self.inner.slice()
}
}
impl DerefMut for QueueWriteBufferView<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.slice_mut()
}
}
impl<'a> AsMut<[u8]> for QueueWriteBufferView<'a> {
fn as_mut(&mut self) -> &mut [u8] {
self.inner.slice_mut()
}
}
impl<'a> Drop for QueueWriteBufferView<'a> {
fn drop(&mut self) {
DynContext::queue_write_staging_buffer(
&*self.queue.context,
self.queue.data.as_ref(),
self.buffer.data.as_ref(),
self.offset,
&*self.inner,
);
}
}
impl Queue {
pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) {
DynContext::queue_write_buffer(
&*self.context,
self.data.as_ref(),
buffer.data.as_ref(),
offset,
data,
)
}
#[must_use]
pub fn write_buffer_with<'a>(
&'a self,
buffer: &'a Buffer,
offset: BufferAddress,
size: BufferSize,
) -> Option<QueueWriteBufferView<'a>> {
profiling::scope!("Queue::write_buffer_with");
DynContext::queue_validate_write_buffer(
&*self.context,
self.data.as_ref(),
buffer.data.as_ref(),
offset,
size,
)?;
let staging_buffer =
DynContext::queue_create_staging_buffer(&*self.context, self.data.as_ref(), size)?;
Some(QueueWriteBufferView {
queue: self,
buffer,
offset,
inner: staging_buffer,
})
}
pub fn write_texture(
&self,
texture: ImageCopyTexture<'_>,
data: &[u8],
data_layout: ImageDataLayout,
size: Extent3d,
) {
DynContext::queue_write_texture(
&*self.context,
self.data.as_ref(),
texture,
data,
data_layout,
size,
)
}
#[cfg(any(webgpu, webgl))]
pub fn copy_external_image_to_texture(
&self,
source: &wgt::ImageCopyExternalImage,
dest: crate::ImageCopyTextureTagged<'_>,
size: Extent3d,
) {
DynContext::queue_copy_external_image_to_texture(
&*self.context,
self.data.as_ref(),
source,
dest,
size,
)
}
pub fn submit<I: IntoIterator<Item = CommandBuffer>>(
&self,
command_buffers: I,
) -> SubmissionIndex {
let mut command_buffers = command_buffers
.into_iter()
.map(|mut comb| comb.data.take().unwrap());
let data =
DynContext::queue_submit(&*self.context, self.data.as_ref(), &mut command_buffers);
SubmissionIndex { data }
}
pub fn get_timestamp_period(&self) -> f32 {
DynContext::queue_get_timestamp_period(&*self.context, self.data.as_ref())
}
pub fn on_submitted_work_done(&self, callback: impl FnOnce() + Send + 'static) {
DynContext::queue_on_submitted_work_done(
&*self.context,
self.data.as_ref(),
Box::new(callback),
)
}
}