use super::context::{Device, Execution};
use crate::{CommandBufferHandle, PresentKey, QueueHandle, SynchronizerHandle};
pub struct Queue {
pub(crate) device: std::ptr::NonNull<Device>,
pub(crate) queue_handle: QueueHandle,
}
unsafe impl Send for Queue {}
pub struct QueueReference<'a> {
pub(crate) device: &'a mut Device,
pub(crate) queue_handle: QueueHandle,
}
impl Queue {
fn device_mut(&mut self) -> &mut Device {
unsafe { self.device.as_mut() }
}
}
impl<'a> crate::queue::QueueExecution<'a> for Execution<'a> {
type Frame = super::Frame<'a>;
fn frame(&mut self) -> Option<&mut Self::Frame> {
self.frame.as_mut()
}
fn completed_frame(&self) -> Option<crate::FrameKey> {
self.completed_frame
}
fn record<'record>(
&'record mut self,
command_buffer_handle: CommandBufferHandle,
record: impl FnOnce(&mut <Self::Frame as crate::frame::Frame<'a>>::CBR<'record>),
) where
Self::Frame: 'record,
{
self.record_with_present_keys(command_buffer_handle, &[], record);
}
fn record_with_present_keys<'record>(
&'record mut self,
command_buffer_handle: CommandBufferHandle,
present_keys: &[PresentKey],
record: impl FnOnce(&mut <Self::Frame as crate::frame::Frame<'a>>::CBR<'record>),
) where
Self::Frame: 'record,
{
let frame = self.frame.as_mut().expect(
"Frame is required to record a DX12 frame command buffer. The most likely cause is that Queue::execute was called without a frame request.",
);
let mut command_buffer = frame.create_command_buffer_recording(command_buffer_handle);
record(&mut command_buffer);
command_buffer.record_present_preparation(present_keys);
self.command_buffers.push(command_buffer_handle);
}
}
impl crate::queue::Queue for Queue {
type Frame<'a> = super::Frame<'a>;
type Execution<'a> = Execution<'a>;
fn create_command_buffer(&mut self, name: Option<&str>) -> CommandBufferHandle {
let queue_handle = self.queue_handle;
self.device_mut().create_command_buffer(name, queue_handle)
}
fn start_frame<'a>(
&'a mut self,
index: u32,
synchronizer_handle: SynchronizerHandle,
) -> crate::queue::StartedFrame<Self::Frame<'a>> {
let frames = self.device_mut().frames;
crate::queue::StartedFrame::new(
self.device_mut().start_frame(index, synchronizer_handle),
crate::queue::completed_frame_key(index, frames),
)
}
fn execute<'a, P>(
&'a mut self,
frame: Option<crate::queue::FrameRequest>,
_wait_for: &[SynchronizerHandle],
_synchronizer: SynchronizerHandle,
execute: impl FnOnce(&mut Self::Execution<'a>) -> P,
) where
P: AsRef<[PresentKey]>,
{
let mut device_pointer = self.device;
let device = self.device_mut();
for &wait_synchronizer in _wait_for {
device.wait_for_synchronizer(wait_synchronizer);
}
let frame_sequence_index = frame.as_ref().map(|frame| (frame.index % device.frames as u32) as u8);
let frame = frame.map(|frame| {
let frames = device.frames;
crate::queue::StartedFrame::new(
device.start_frame(frame.index, frame.synchronizer),
crate::queue::completed_frame_key(frame.index, frames),
)
});
let completed_frame = frame.as_ref().and_then(|frame| frame.completed_frame);
let frame = frame.map(|frame| frame.frame);
let mut execution = Execution {
frame,
completed_frame,
command_buffers: smallvec::SmallVec::new(),
};
let present_keys = execute(&mut execution);
let should_complete_empty_frame = execution.frame.is_some() && execution.command_buffers.is_empty();
let command_buffers = std::mem::take(&mut execution.command_buffers);
drop(execution);
if command_buffers.is_empty() {
if should_complete_empty_frame {
if let Some(sequence_index) = frame_sequence_index {
unsafe {
device_pointer
.as_mut()
.complete_synchronizer_for_sequence_from_cpu(_synchronizer, sequence_index);
}
}
}
return;
}
for command_buffer in command_buffers {
unsafe {
device_pointer.as_mut().submit_command_buffer(command_buffer, _synchronizer);
}
}
for present_key in present_keys.as_ref() {
unsafe {
device_pointer.as_mut().present_swapchain(*present_key);
}
}
}
}
impl crate::queue::Queue for QueueReference<'_> {
type Frame<'a> = super::Frame<'a>;
type Execution<'a> = Execution<'a>;
fn create_command_buffer(&mut self, name: Option<&str>) -> CommandBufferHandle {
self.device.create_command_buffer(name, self.queue_handle)
}
fn start_frame<'a>(
&'a mut self,
index: u32,
synchronizer_handle: SynchronizerHandle,
) -> crate::queue::StartedFrame<Self::Frame<'a>> {
let frames = self.device.frames;
crate::queue::StartedFrame::new(
self.device.start_frame(index, synchronizer_handle),
crate::queue::completed_frame_key(index, frames),
)
}
fn execute<'a, P>(
&'a mut self,
frame: Option<crate::queue::FrameRequest>,
_wait_for: &[SynchronizerHandle],
_synchronizer: SynchronizerHandle,
execute: impl FnOnce(&mut Self::Execution<'a>) -> P,
) where
P: AsRef<[PresentKey]>,
{
let mut device_pointer = std::ptr::NonNull::from(&mut *self.device);
for &wait_synchronizer in _wait_for {
self.device.wait_for_synchronizer(wait_synchronizer);
}
let frames = self.device.frames;
let frame_sequence_index = frame.as_ref().map(|frame| (frame.index % frames as u32) as u8);
let frame = frame.map(|frame| {
crate::queue::StartedFrame::new(
self.device.start_frame(frame.index, frame.synchronizer),
crate::queue::completed_frame_key(frame.index, frames),
)
});
let completed_frame = frame.as_ref().and_then(|frame| frame.completed_frame);
let frame = frame.map(|frame| frame.frame);
let mut execution = Execution {
frame,
completed_frame,
command_buffers: smallvec::SmallVec::new(),
};
let present_keys = execute(&mut execution);
let should_complete_empty_frame = execution.frame.is_some() && execution.command_buffers.is_empty();
let command_buffers = std::mem::take(&mut execution.command_buffers);
drop(execution);
if command_buffers.is_empty() {
if should_complete_empty_frame {
if let Some(sequence_index) = frame_sequence_index {
unsafe {
device_pointer
.as_mut()
.complete_synchronizer_for_sequence_from_cpu(_synchronizer, sequence_index);
}
}
}
return;
}
for command_buffer in command_buffers {
unsafe {
device_pointer.as_mut().submit_command_buffer(command_buffer, _synchronizer);
}
}
for present_key in present_keys.as_ref() {
unsafe {
device_pointer.as_mut().present_swapchain(*present_key);
}
}
}
}