mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
Command buffer allocator API 2.0 (#2403)
* Make `CommandBufferAllocator` object-safe, remove the generics * Fix tests * Fix examples * Remove the panic * Remove outdated docs * Document `Send + Sync` impl of `UnsafeCommandBuffer`
This commit is contained in:
parent
4d56fc38de
commit
43e2db0dbd
@ -333,7 +333,7 @@ fn main() -> Result<(), impl Error> {
|
||||
// Initialize the textures.
|
||||
{
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
command_buffer_allocator.as_ref(),
|
||||
command_buffer_allocator.clone(),
|
||||
graphics_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -589,7 +589,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
command_buffer_allocator.as_ref(),
|
||||
command_buffer_allocator.clone(),
|
||||
graphics_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -763,7 +763,7 @@ fn run_worker(
|
||||
let texture = textures[!current_index as usize].clone();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
command_buffer_allocator.as_ref(),
|
||||
command_buffer_allocator.clone(),
|
||||
transfer_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -155,8 +155,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
// We start by creating the buffer that will store the data.
|
||||
let data_buffer = Buffer::from_iter(
|
||||
@ -194,7 +196,7 @@ fn main() {
|
||||
|
||||
// In order to execute our operation, we have to build a command buffer.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -269,8 +269,10 @@ fn main() -> Result<(), impl Error> {
|
||||
let mut recreate_swapchain = false;
|
||||
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
@ -368,7 +370,7 @@ fn main() -> Result<(), impl Error> {
|
||||
buffer.write().unwrap().copy_from_slice(&data);
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -138,8 +138,10 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut width = swapchain.image_extent()[0];
|
||||
let mut height = swapchain.image_extent()[1];
|
||||
@ -206,7 +208,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -183,7 +183,7 @@ impl AmbientLightingSystem {
|
||||
};
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -197,7 +197,7 @@ impl DirectionalLightingSystem {
|
||||
};
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -210,7 +210,7 @@ impl PointLightingSystem {
|
||||
};
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -339,7 +339,7 @@ impl FrameSystem {
|
||||
|
||||
// Start the command buffer builder that will be filled throughout the frame handling.
|
||||
let mut command_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -129,7 +129,7 @@ impl TriangleDrawSystem {
|
||||
/// Builds a secondary command buffer that draws the triangle on the current subpass.
|
||||
pub fn draw(&self, viewport_dimensions: [u32; 2]) -> Arc<SecondaryAutoCommandBuffer> {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -149,8 +149,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
// Create the input buffer. Data in a dynamic buffer **MUST** be aligned to
|
||||
// `min_uniform_buffer_offset_align` or `min_storage_buffer_offset_align`, depending on the
|
||||
@ -235,7 +237,7 @@ fn main() {
|
||||
|
||||
// Build the command buffer, using different offsets for each call.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -206,8 +206,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let image = Image::new(
|
||||
memory_allocator.clone(),
|
||||
@ -248,7 +250,7 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -273,8 +273,10 @@ mod linux {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
|
||||
@ -388,7 +390,7 @@ mod linux {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -205,10 +205,13 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -468,7 +471,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -205,10 +205,13 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -416,7 +419,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -211,10 +211,13 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -434,7 +437,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -365,8 +365,10 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
@ -466,7 +468,7 @@ fn main() -> Result<(), impl Error> {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -338,8 +338,10 @@ fn main() -> Result<(), impl Error> {
|
||||
let mut recreate_swapchain = false;
|
||||
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
@ -401,7 +403,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -149,7 +149,7 @@ impl FractalComputePipeline {
|
||||
)
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -205,7 +205,7 @@ impl PixelsDrawPipeline {
|
||||
image: Arc<ImageView>,
|
||||
) -> Arc<SecondaryAutoCommandBuffer> {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -89,7 +89,7 @@ impl RenderPassPlaceOverFrame {
|
||||
|
||||
// Create primary command buffer builder.
|
||||
let mut command_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -360,7 +360,10 @@ fn main() {
|
||||
depth_range: 0.0..=1.0,
|
||||
};
|
||||
|
||||
let command_buffer_allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let buf = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
@ -378,7 +381,7 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -131,7 +131,7 @@ impl GameOfLifeComputePipeline {
|
||||
dead_color: [f32; 4],
|
||||
) -> Box<dyn GpuFuture> {
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.compute_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -201,7 +201,7 @@ impl PixelsDrawPipeline {
|
||||
image: Arc<ImageView>,
|
||||
) -> Arc<SecondaryAutoCommandBuffer> {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
|
@ -79,7 +79,7 @@ impl RenderPassPlaceOverFrame {
|
||||
|
||||
// Create a primary command buffer builder.
|
||||
let mut command_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.as_ref(),
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.gfx_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -303,8 +303,10 @@ fn main() -> Result<(), impl Error> {
|
||||
depth_range: 0.0..=1.0,
|
||||
};
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
window_surfaces.insert(
|
||||
window_id,
|
||||
@ -446,7 +448,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -305,8 +305,10 @@ fn main() {
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let create_buffer = || {
|
||||
Buffer::from_iter(
|
||||
@ -329,7 +331,7 @@ fn main() {
|
||||
let buffer2 = create_buffer();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -351,8 +351,10 @@ fn main() -> Result<(), impl Error> {
|
||||
depth_range: 0.0..=1.0,
|
||||
};
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut framebuffers = window_size_dependent_setup(
|
||||
&images,
|
||||
@ -425,7 +427,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -137,8 +137,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let data_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
@ -179,7 +181,7 @@ fn main() {
|
||||
// Note that there is no type safety for the push constant data, so be careful to only pass an
|
||||
// instance of the struct generated by the `vulkano_shaders::shaders!` macro.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -197,10 +197,12 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -404,7 +406,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -265,10 +265,13 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -537,7 +540,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -284,8 +284,10 @@ fn main() -> Result<(), impl Error> {
|
||||
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut viewport);
|
||||
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
@ -347,7 +349,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
|
@ -129,8 +129,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let data_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
@ -161,7 +163,7 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -137,8 +137,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let data_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
@ -165,7 +167,7 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -180,8 +180,8 @@ fn main() {
|
||||
queue: Arc<Queue>,
|
||||
data_buffer: Subbuffer<[u32]>,
|
||||
parameters: shaders::Parameters,
|
||||
command_buffer_allocator: &StandardCommandBufferAllocator,
|
||||
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||
) {
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
let set = DescriptorSet::new(
|
||||
@ -224,12 +224,14 @@ fn main() {
|
||||
}
|
||||
|
||||
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
// Prepare test array `[0, 1, 2, 3....]`.
|
||||
let data_buffer = Buffer::from_iter(
|
||||
@ -301,8 +303,8 @@ fn main() {
|
||||
queue.clone(),
|
||||
data_buffer.clone(),
|
||||
shaders::Parameters { value: 2 },
|
||||
&command_buffer_allocator,
|
||||
descriptor_set_allocator.clone(),
|
||||
command_buffer_allocator.clone(),
|
||||
);
|
||||
|
||||
// Then add 1 to each value.
|
||||
@ -311,8 +313,8 @@ fn main() {
|
||||
queue.clone(),
|
||||
data_buffer.clone(),
|
||||
shaders::Parameters { value: 1 },
|
||||
&command_buffer_allocator,
|
||||
descriptor_set_allocator.clone(),
|
||||
command_buffer_allocator.clone(),
|
||||
);
|
||||
|
||||
// Then multiply each value by 3.
|
||||
@ -321,8 +323,8 @@ fn main() {
|
||||
queue,
|
||||
data_buffer.clone(),
|
||||
shaders::Parameters { value: 3 },
|
||||
&command_buffer_allocator,
|
||||
descriptor_set_allocator,
|
||||
command_buffer_allocator,
|
||||
);
|
||||
|
||||
let data_buffer_content = data_buffer.read().unwrap();
|
||||
|
@ -322,8 +322,10 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
#[derive(BufferContents, Vertex)]
|
||||
#[repr(C)]
|
||||
@ -385,7 +387,7 @@ fn main() -> Result<(), impl Error> {
|
||||
|
||||
// Create one-time command to copy between the buffers.
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -580,7 +582,7 @@ fn main() -> Result<(), impl Error> {
|
||||
};
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -138,8 +138,10 @@ fn main() {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let data_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
@ -166,7 +168,7 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -255,8 +255,10 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
match event {
|
||||
@ -364,7 +366,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -402,8 +402,10 @@ fn main() -> Result<(), impl Error> {
|
||||
};
|
||||
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut viewport);
|
||||
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
@ -465,7 +467,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -207,10 +207,13 @@ fn main() -> Result<(), impl Error> {
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -427,7 +430,7 @@ fn main() -> Result<(), impl Error> {
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -482,8 +482,10 @@ fn main() -> Result<(), impl Error> {
|
||||
// Before we can start creating and recording command buffers, we need a way of allocating
|
||||
// them. Vulkano provides a command buffer allocator, which manages raw Vulkan command pools
|
||||
// underneath and provides a safe interface for them.
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
// Initialization is finally finished!
|
||||
|
||||
@ -596,7 +598,7 @@ fn main() -> Result<(), impl Error> {
|
||||
// Note that we have to pass a queue family when we create the command buffer. The
|
||||
// command buffer will only be executable on that given queue family.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -479,8 +479,10 @@ fn main() -> Result<(), impl Error> {
|
||||
// Before we can start creating and recording command buffers, we need a way of allocating
|
||||
// them. Vulkano provides a command buffer allocator, which manages raw Vulkan command pools
|
||||
// underneath and provides a safe interface for them.
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
// Initialization is finally finished!
|
||||
|
||||
@ -598,7 +600,7 @@ fn main() -> Result<(), impl Error> {
|
||||
// Note that we have to pass a queue family when we create the command buffer. The
|
||||
// command buffer will only be executable on that given queue family.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&command_buffer_allocator,
|
||||
command_buffer_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
@ -87,7 +87,7 @@ const MAX_ARENAS: usize = 32;
|
||||
///
|
||||
/// # let queue: std::sync::Arc<vulkano::device::Queue> = return;
|
||||
/// # let memory_allocator: std::sync::Arc<vulkano::memory::allocator::StandardMemoryAllocator> = return;
|
||||
/// # let command_buffer_allocator: vulkano::command_buffer::allocator::StandardCommandBufferAllocator = return;
|
||||
/// # let command_buffer_allocator: std::sync::Arc<vulkano::command_buffer::allocator::StandardCommandBufferAllocator> = return;
|
||||
/// #
|
||||
/// // Create the buffer allocator.
|
||||
/// let buffer_allocator = SubbufferAllocator::new(
|
||||
@ -108,7 +108,7 @@ const MAX_ARENAS: usize = 32;
|
||||
///
|
||||
/// // You can then use `subbuffer` as if it was an entirely separate buffer.
|
||||
/// AutoCommandBufferBuilder::primary(
|
||||
/// &command_buffer_allocator,
|
||||
/// command_buffer_allocator.clone(),
|
||||
/// queue.queue_family_index(),
|
||||
/// CommandBufferUsage::OneTimeSubmit,
|
||||
/// )
|
||||
@ -117,7 +117,8 @@ const MAX_ARENAS: usize = 32;
|
||||
/// // it is pointless to do that.
|
||||
/// .update_buffer(subbuffer.clone(), &[0.2, 0.3, 0.4, 0.5])
|
||||
/// .unwrap()
|
||||
/// .build().unwrap()
|
||||
/// .build()
|
||||
/// .unwrap()
|
||||
/// .execute(queue.clone())
|
||||
/// .unwrap()
|
||||
/// .then_signal_fence_and_flush()
|
||||
|
@ -133,7 +133,7 @@ pub mod view;
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
/// # let queue: std::sync::Arc<vulkano::device::Queue> = return;
|
||||
/// # let memory_allocator: std::sync::Arc<vulkano::memory::allocator::StandardMemoryAllocator> = return;
|
||||
/// # let command_buffer_allocator: vulkano::command_buffer::allocator::StandardCommandBufferAllocator = return;
|
||||
/// # let command_buffer_allocator: std::sync::Arc<vulkano::command_buffer::allocator::StandardCommandBufferAllocator> = return;
|
||||
/// #
|
||||
/// // Simple iterator to construct test data.
|
||||
/// let data = (0..10_000).map(|i| i as f32);
|
||||
@ -175,7 +175,7 @@ pub mod view;
|
||||
///
|
||||
/// // Create a one-time command to copy between the buffers.
|
||||
/// let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
/// &command_buffer_allocator,
|
||||
/// command_buffer_allocator.clone(),
|
||||
/// queue.queue_family_index(),
|
||||
/// CommandBufferUsage::OneTimeSubmit,
|
||||
/// )
|
||||
|
@ -14,18 +14,16 @@ use super::{
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
instance::InstanceOwnedDebugWrapper,
|
||||
Validated, VulkanError,
|
||||
Validated, ValidationError, VulkanError,
|
||||
};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
use smallvec::{IntoIter, SmallVec};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
cell::{Cell, UnsafeCell},
|
||||
cell::UnsafeCell,
|
||||
error::Error,
|
||||
fmt::Display,
|
||||
marker::PhantomData,
|
||||
mem::ManuallyDrop,
|
||||
sync::Arc,
|
||||
thread,
|
||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||
mem, ptr,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use thread_local::ThreadLocal;
|
||||
|
||||
@ -36,66 +34,126 @@ const MAX_POOLS: usize = 32;
|
||||
/// # Safety
|
||||
///
|
||||
/// A Vulkan command pool must be externally synchronized as if it owned the command buffers that
|
||||
/// were allocated from it. This includes allocating from the pool, freeing from the pool, resetting
|
||||
/// the pool or individual command buffers, and most importantly recording commands to command
|
||||
/// buffers. The implementation of `CommandBufferAllocator` is expected to manage this.
|
||||
/// were allocated from it. This includes allocating from the pool, freeing from the pool,
|
||||
/// resetting the pool or individual command buffers, and most importantly recording commands to
|
||||
/// command buffers. The implementation of `CommandBufferAllocator` is expected to manage this.
|
||||
///
|
||||
/// The destructors of the [`CommandBufferBuilderAlloc`] and the [`CommandBufferAlloc`] are expected
|
||||
/// to free the command buffer, reset the command buffer, or add it to a pool so that it gets
|
||||
/// reused. If the implementation frees or resets the command buffer, it must not forget that this
|
||||
/// operation must be externally synchronized.
|
||||
pub unsafe trait CommandBufferAllocator: DeviceOwned {
|
||||
/// See [`allocate`](Self::allocate).
|
||||
type Iter: Iterator<Item = Self::Builder>;
|
||||
|
||||
/// Represents a command buffer that has been allocated and that is currently being built.
|
||||
type Builder: CommandBufferBuilderAlloc<Alloc = Self::Alloc>;
|
||||
|
||||
/// Represents a command buffer that has been allocated and that is pending execution or is
|
||||
/// being executed.
|
||||
type Alloc: CommandBufferAlloc;
|
||||
|
||||
/// Allocates command buffers.
|
||||
///
|
||||
/// Returns an iterator that contains the requested amount of allocated command buffers.
|
||||
/// The implementation of `allocate` must return a valid allocation that stays allocated until
|
||||
/// either `deallocate` is called on it or the allocator is dropped. If the allocator is cloned, it
|
||||
/// must produce the same allocator, and an allocation must stay allocated until either
|
||||
/// `deallocate` is called on any of the clones or all clones have been dropped.
|
||||
///
|
||||
/// The implementation of `deallocate` is expected to free the command buffer, reset the command
|
||||
/// buffer or its pool, or add it to a pool so that it gets reused. If the implementation frees the
|
||||
/// command buffer or resets the command buffer or pool, it must not forget that this operation
|
||||
/// must be externally synchronized. The implementation should not panic as it is used when
|
||||
/// dropping command buffers.
|
||||
///
|
||||
/// Command buffers in the recording state can never be sent between threads in vulkano, which
|
||||
/// means that the implementation of `allocate` can freely assume that the command buffer won't
|
||||
/// leave the thread it was allocated on until it has finished recording. Note however that after
|
||||
/// recording is finished, command buffers are free to be sent between threads, which means that
|
||||
/// `deallocate` must account for the possibility that a command buffer can be deallocated from a
|
||||
/// different thread than it was allocated from.
|
||||
pub unsafe trait CommandBufferAllocator: DeviceOwned + Send + Sync + 'static {
|
||||
/// Allocates a command buffer.
|
||||
fn allocate(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
command_buffer_count: u32,
|
||||
) -> Result<Self::Iter, VulkanError>;
|
||||
) -> Result<CommandBufferAlloc, Validated<VulkanError>>;
|
||||
|
||||
/// Deallocates the given `allocation`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `allocation` must refer to a **currently allocated** allocation of `self`.
|
||||
unsafe fn deallocate(&self, allocation: CommandBufferAlloc);
|
||||
}
|
||||
|
||||
/// A command buffer allocated from a pool and that can be recorded.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// See [`CommandBufferAllocator`] for information about safety.
|
||||
pub unsafe trait CommandBufferBuilderAlloc: DeviceOwned {
|
||||
/// Return type of `into_alloc`.
|
||||
type Alloc: CommandBufferAlloc;
|
||||
|
||||
/// Returns the internal object that contains the command buffer.
|
||||
fn inner(&self) -> &CommandPoolAlloc;
|
||||
|
||||
/// Turns this builder into a command buffer that is pending execution.
|
||||
fn into_alloc(self) -> Self::Alloc;
|
||||
|
||||
/// Returns the index of the queue family that the pool targets.
|
||||
fn queue_family_index(&self) -> u32;
|
||||
impl Debug for dyn CommandBufferAllocator {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
f.debug_struct("CommandBufferAllocator")
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
/// A command buffer allocated from a pool that has finished being recorded.
|
||||
/// An allocation made using a [command buffer allocator].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// See [`CommandBufferAllocator`] for information about safety.
|
||||
pub unsafe trait CommandBufferAlloc: DeviceOwned + Send + Sync + 'static {
|
||||
/// Returns the internal object that contains the command buffer.
|
||||
fn inner(&self) -> &CommandPoolAlloc;
|
||||
/// [command buffer allocator]: CommandBufferAllocator
|
||||
#[derive(Debug)]
|
||||
pub struct CommandBufferAlloc {
|
||||
/// The internal object that contains the command buffer.
|
||||
pub inner: CommandPoolAlloc,
|
||||
|
||||
/// Returns the index of the queue family that the pool targets.
|
||||
fn queue_family_index(&self) -> u32;
|
||||
/// The command pool that the command buffer was allocated from.
|
||||
///
|
||||
/// Using this for anything other than looking at the pool's metadata will lead to a Bad
|
||||
/// Time<sup>TM</sup>.
|
||||
pub pool: Arc<CommandPool>,
|
||||
|
||||
/// An opaque handle identifying the allocation inside the allocator.
|
||||
pub handle: AllocationHandle,
|
||||
}
|
||||
|
||||
/// An opaque handle identifying an allocation inside an allocator.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(not(doc), repr(transparent))]
|
||||
pub struct AllocationHandle(*mut ());
|
||||
|
||||
unsafe impl Send for AllocationHandle {}
|
||||
unsafe impl Sync for AllocationHandle {}
|
||||
|
||||
impl AllocationHandle {
|
||||
/// Creates a null `AllocationHandle`.
|
||||
///
|
||||
/// Use this if you don't have anything that you need to associate with the allocation.
|
||||
#[inline]
|
||||
pub const fn null() -> Self {
|
||||
AllocationHandle(ptr::null_mut())
|
||||
}
|
||||
|
||||
/// Stores a pointer in an `AllocationHandle`.
|
||||
///
|
||||
/// Use this if you want to associate an allocation with some (host) heap allocation.
|
||||
#[inline]
|
||||
pub const fn from_ptr(ptr: *mut ()) -> Self {
|
||||
AllocationHandle(ptr)
|
||||
}
|
||||
|
||||
/// Stores an index inside an `AllocationHandle`.
|
||||
///
|
||||
/// Use this if you want to associate an allocation with some index.
|
||||
#[allow(clippy::useless_transmute)]
|
||||
#[inline]
|
||||
pub const fn from_index(index: usize) -> Self {
|
||||
// SAFETY: `usize` and `*mut ()` have the same layout.
|
||||
AllocationHandle(unsafe { mem::transmute::<usize, *mut ()>(index) })
|
||||
}
|
||||
|
||||
/// Retrieves a previously-stored pointer from the `AllocationHandle`.
|
||||
///
|
||||
/// If this handle hasn't been created using [`from_ptr`] then this will return an invalid
|
||||
/// pointer, dereferencing which is undefined behavior.
|
||||
///
|
||||
/// [`from_ptr`]: Self::from_ptr
|
||||
#[inline]
|
||||
pub const fn as_ptr(self) -> *mut () {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Retrieves a previously-stored index from the `AllocationHandle`.
|
||||
///
|
||||
/// If this handle hasn't been created using [`from_index`] then this will return a bogus
|
||||
/// result.
|
||||
///
|
||||
/// [`from_index`]: Self::from_index
|
||||
#[allow(clippy::transmutes_expressible_as_ptr_casts)]
|
||||
#[inline]
|
||||
pub const fn as_index(self) -> usize {
|
||||
// SAFETY: `usize` and `*mut ()` have the same layout.
|
||||
unsafe { mem::transmute::<*mut (), usize>(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Standard implementation of a command buffer allocator.
|
||||
@ -115,25 +173,26 @@ pub unsafe trait CommandBufferAlloc: DeviceOwned + Send + Sync + 'static {
|
||||
///
|
||||
/// This allocator only needs to lock when a thread first allocates or when a thread that
|
||||
/// previously allocated exits. In all other cases, allocation is lock-free.
|
||||
///
|
||||
/// Command buffers can't be moved between threads during the building process, but finished command
|
||||
/// buffers can. When a command buffer is dropped, it is returned back to the pool for reuse.
|
||||
#[derive(Debug)]
|
||||
pub struct StandardCommandBufferAllocator {
|
||||
device: InstanceOwnedDebugWrapper<Arc<Device>>,
|
||||
// Each queue family index points directly to its entry.
|
||||
pools: ThreadLocal<SmallVec<[UnsafeCell<Option<Entry>>; 8]>>,
|
||||
create_info: StandardCommandBufferAllocatorCreateInfo,
|
||||
buffer_count: [usize; 2],
|
||||
}
|
||||
|
||||
impl StandardCommandBufferAllocator {
|
||||
/// Creates a new `StandardCommandBufferAllocator`.
|
||||
#[inline]
|
||||
pub fn new(device: Arc<Device>, create_info: StandardCommandBufferAllocatorCreateInfo) -> Self {
|
||||
let mut buffer_count = [0, 0];
|
||||
buffer_count[CommandBufferLevel::Primary as usize] = create_info.primary_buffer_count;
|
||||
buffer_count[CommandBufferLevel::Secondary as usize] = create_info.secondary_buffer_count;
|
||||
|
||||
StandardCommandBufferAllocator {
|
||||
device: InstanceOwnedDebugWrapper(device),
|
||||
pools: ThreadLocal::new(),
|
||||
create_info,
|
||||
buffer_count,
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,95 +252,92 @@ impl StandardCommandBufferAllocator {
|
||||
}
|
||||
|
||||
unsafe impl CommandBufferAllocator for StandardCommandBufferAllocator {
|
||||
type Iter = IntoIter<[StandardCommandBufferBuilderAlloc; 1]>;
|
||||
|
||||
type Builder = StandardCommandBufferBuilderAlloc;
|
||||
|
||||
type Alloc = StandardCommandBufferAlloc;
|
||||
|
||||
/// Allocates command buffers.
|
||||
///
|
||||
/// Returns an iterator that contains the requested amount of allocated command buffers.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the queue family index is not active on the device.
|
||||
/// - Panics if `command_buffer_count` exceeds the count configured for the pool corresponding
|
||||
/// to `level`.
|
||||
#[inline]
|
||||
fn allocate(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
command_buffer_count: u32,
|
||||
) -> Result<Self::Iter, VulkanError> {
|
||||
// VUID-vkCreateCommandPool-queueFamilyIndex-01937
|
||||
assert!(self
|
||||
) -> Result<CommandBufferAlloc, Validated<VulkanError>> {
|
||||
if !self
|
||||
.device
|
||||
.active_queue_family_indices()
|
||||
.contains(&queue_family_index));
|
||||
.contains(&queue_family_index)
|
||||
{
|
||||
Err(Box::new(ValidationError {
|
||||
context: "queue_family_index".into(),
|
||||
problem: "is not active on the device".into(),
|
||||
vuids: &["VUID-vkCreateCommandPool-queueFamilyIndex-01937"],
|
||||
..Default::default()
|
||||
}))?;
|
||||
}
|
||||
|
||||
let entry = unsafe { &mut *self.entry(queue_family_index) };
|
||||
|
||||
if entry.is_none() {
|
||||
let reserve = Arc::new(ArrayQueue::new(MAX_POOLS));
|
||||
*entry = Some(Entry {
|
||||
pool: Pool::new(
|
||||
*entry = Some(Entry::new(
|
||||
self.device.clone(),
|
||||
queue_family_index,
|
||||
reserve.clone(),
|
||||
&self.create_info,
|
||||
)?,
|
||||
reserve,
|
||||
});
|
||||
&self.buffer_count,
|
||||
Arc::new(ArrayQueue::new(MAX_POOLS)),
|
||||
)?);
|
||||
}
|
||||
|
||||
let entry = entry.as_mut().unwrap();
|
||||
|
||||
// First try to allocate from existing command buffers.
|
||||
if let Some(allocs) = entry.pool.allocate(level, command_buffer_count) {
|
||||
return Ok(allocs);
|
||||
Ok(entry.allocate(queue_family_index, level, &self.buffer_count)?)
|
||||
}
|
||||
|
||||
// Else try to reset the pool.
|
||||
if entry
|
||||
.try_reset_pool(CommandPoolResetFlags::empty())
|
||||
.is_err()
|
||||
{
|
||||
// If that fails too try to grab a pool from the reserve.
|
||||
entry.pool = if let Some(inner) = entry.reserve.pop() {
|
||||
Arc::new(Pool {
|
||||
inner: ManuallyDrop::new(inner),
|
||||
reserve: entry.reserve.clone(),
|
||||
})
|
||||
} else {
|
||||
// Else we are unfortunately forced to create a new pool.
|
||||
Pool::new(
|
||||
self.device.clone(),
|
||||
queue_family_index,
|
||||
entry.reserve.clone(),
|
||||
&self.create_info,
|
||||
)?
|
||||
};
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn deallocate(&self, allocation: CommandBufferAlloc) {
|
||||
let ptr = allocation.handle.as_ptr().cast::<Pool>();
|
||||
|
||||
Ok(entry.pool.allocate(level, command_buffer_count).unwrap())
|
||||
// SAFETY: The caller must guarantee that `allocation` refers to one allocated by `self`,
|
||||
// therefore `ptr` must be the same one we gave out on allocation. We also know that the
|
||||
// pointer must be valid, because the caller must guarantee that the same allocation isn't
|
||||
// deallocated more than once. That means that since we cloned the `Arc` on allocation, at
|
||||
// least that strong reference must still keep it alive, and we can safely drop this clone
|
||||
// at the end of the scope here.
|
||||
let pool = unsafe { Arc::from_raw(ptr) };
|
||||
|
||||
let level = allocation.inner.level();
|
||||
|
||||
// This cannot panic because in order to have allocated a command buffer with the level in
|
||||
// the first place, the size of the pool for that level must have been non-zero.
|
||||
let buffer_reserve = pool.buffer_reserve[level as usize].as_ref().unwrap();
|
||||
|
||||
// This cannot happen because every allocation is (supposed to be) returned to the pool
|
||||
// whence it came, so there must be enough room for it.
|
||||
debug_assert!(buffer_reserve.push(allocation.inner).is_ok());
|
||||
|
||||
// We have to make sure that we only reset the pool under this condition, because there
|
||||
// could be other references in other allocations.
|
||||
if Arc::strong_count(&pool) == 1 {
|
||||
// The pool reserve can be dropped from under us when an entry is cleared, in which
|
||||
// case we destroy the pool.
|
||||
if let Some(reserve) = pool.pool_reserve.upgrade() {
|
||||
// If there is not enough space in the reserve, we destroy the pool. The only way
|
||||
// this can happen is if something is resource hogging, forcing new pools to be
|
||||
// created such that the number exceeds `MAX_POOLS`, and then drops them all at
|
||||
// once.
|
||||
let _ = reserve.push(pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: CommandBufferAllocator> CommandBufferAllocator for Arc<T> {
|
||||
type Iter = T::Iter;
|
||||
|
||||
type Builder = T::Builder;
|
||||
|
||||
type Alloc = T::Alloc;
|
||||
|
||||
#[inline]
|
||||
fn allocate(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
command_buffer_count: u32,
|
||||
) -> Result<Self::Iter, VulkanError> {
|
||||
(**self).allocate(queue_family_index, level, command_buffer_count)
|
||||
) -> Result<CommandBufferAlloc, Validated<VulkanError>> {
|
||||
(**self).allocate(queue_family_index, level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn deallocate(&self, allocation: CommandBufferAlloc) {
|
||||
(**self).deallocate(allocation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,32 +352,108 @@ unsafe impl DeviceOwned for StandardCommandBufferAllocator {
|
||||
struct Entry {
|
||||
// Contains the actual Vulkan command pool that is currently in use.
|
||||
pool: Arc<Pool>,
|
||||
// When a `Pool` is dropped, it returns itself here for reuse.
|
||||
reserve: Arc<ArrayQueue<PoolInner>>,
|
||||
// How many command buffers have been allocated from `pool.buffer_reserve`.
|
||||
allocations: [usize; 2],
|
||||
// When a `Pool` is about to be dropped, it is returned here for reuse.
|
||||
pool_reserve: Arc<ArrayQueue<Arc<Pool>>>,
|
||||
}
|
||||
|
||||
// This is needed because of the blanket impl of `Send` on `Arc<T>`, which requires that `T` is
|
||||
// `Send + Sync`. `Pool` is `Send + !Sync` because `CommandPool` is `!Sync`. That's fine however
|
||||
// because we never access the Vulkan command pool concurrently. Same goes for the `Cell`s.
|
||||
// because we never access the Vulkan command pool concurrently.
|
||||
unsafe impl Send for Entry {}
|
||||
|
||||
impl Entry {
|
||||
fn new(
|
||||
device: Arc<Device>,
|
||||
queue_family_index: u32,
|
||||
buffer_count: &[usize; 2],
|
||||
pool_reserve: Arc<ArrayQueue<Arc<Pool>>>,
|
||||
) -> Result<Self, VulkanError> {
|
||||
Ok(Entry {
|
||||
pool: Pool::new(device, queue_family_index, buffer_count, &pool_reserve)?,
|
||||
allocations: [0; 2],
|
||||
pool_reserve,
|
||||
})
|
||||
}
|
||||
|
||||
fn allocate(
|
||||
&mut self,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
buffer_count: &[usize; 2],
|
||||
) -> Result<CommandBufferAlloc, VulkanError> {
|
||||
if self.allocations[level as usize] >= buffer_count[level as usize] {
|
||||
// This can happen if there's only ever one allocation alive at any point in time. In
|
||||
// that case, when deallocating the last command buffer before reaching `buffer_count`,
|
||||
// there will be 2 references to the pool (one here and one in the allocation) and so
|
||||
// the pool won't be returned to the reserve when deallocating. However, since there
|
||||
// are no other allocations alive, there would be no other allocations that could
|
||||
// return it to the reserve. To avoid dropping the pool unneccessarily, we simply
|
||||
// continue using it. In the case where there are other references, we drop ours, at
|
||||
// which point an allocation still holding a reference will be able to put the pool
|
||||
// into the reserve when deallocated.
|
||||
//
|
||||
// TODO: This can still run into the A/B/A problem causing the pool to be dropped.
|
||||
if Arc::strong_count(&self.pool) == 1 {
|
||||
// SAFETY: We checked that the pool has a single strong reference above, meaning
|
||||
// that all the allocations we gave out must have been deallocated.
|
||||
unsafe {
|
||||
self.pool
|
||||
.inner
|
||||
.reset_unchecked(CommandPoolResetFlags::empty())
|
||||
}?;
|
||||
|
||||
self.allocations = [0; 2];
|
||||
} else {
|
||||
if let Some(pool) = self.pool_reserve.pop() {
|
||||
// SAFETY: We checked that the pool has a single strong reference when
|
||||
// deallocating, meaning that all the allocations we gave out must have been
|
||||
// deallocated.
|
||||
unsafe { pool.inner.reset_unchecked(CommandPoolResetFlags::empty()) }?;
|
||||
|
||||
self.pool = pool;
|
||||
self.allocations = [0; 2];
|
||||
} else {
|
||||
*self = Entry::new(
|
||||
self.pool.inner.device().clone(),
|
||||
queue_family_index,
|
||||
buffer_count,
|
||||
self.pool_reserve.clone(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let buffer_reserve = self.pool.buffer_reserve[level as usize]
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"attempted to allocate a command buffer with level `{level:?}`, but the \
|
||||
command buffer pool for that level was configured to be empty",
|
||||
)
|
||||
});
|
||||
|
||||
self.allocations[level as usize] += 1;
|
||||
|
||||
Ok(CommandBufferAlloc {
|
||||
inner: buffer_reserve.pop().unwrap(),
|
||||
pool: self.pool.inner.clone(),
|
||||
handle: AllocationHandle::from_ptr(Arc::into_raw(self.pool.clone()) as _),
|
||||
})
|
||||
}
|
||||
|
||||
fn try_reset_pool(
|
||||
&mut self,
|
||||
flags: CommandPoolResetFlags,
|
||||
) -> Result<(), Validated<ResetCommandPoolError>> {
|
||||
if let Some(pool) = Arc::get_mut(&mut self.pool) {
|
||||
unsafe {
|
||||
pool.inner.inner.reset(flags).map_err(|err| match err {
|
||||
Validated::Error(err) => {
|
||||
Validated::Error(ResetCommandPoolError::VulkanError(err))
|
||||
}
|
||||
unsafe { pool.inner.reset(flags) }.map_err(|err| match err {
|
||||
Validated::Error(err) => Validated::Error(ResetCommandPoolError::VulkanError(err)),
|
||||
Validated::ValidationError(err) => err.into(),
|
||||
})?
|
||||
};
|
||||
})?;
|
||||
|
||||
*pool.inner.primary_allocations.get_mut() = 0;
|
||||
*pool.inner.secondary_allocations.get_mut() = 0;
|
||||
self.allocations = [0; 2];
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
@ -332,31 +464,20 @@ impl Entry {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Pool {
|
||||
inner: ManuallyDrop<PoolInner>,
|
||||
// Where we return the `PoolInner` in our `Drop` impl.
|
||||
reserve: Arc<ArrayQueue<PoolInner>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PoolInner {
|
||||
// The Vulkan pool specific to a device's queue family.
|
||||
inner: CommandPool,
|
||||
// List of existing primary command buffers that are available for reuse.
|
||||
primary_pool: Option<ArrayQueue<CommandPoolAlloc>>,
|
||||
// List of existing secondary command buffers that are available for reuse.
|
||||
secondary_pool: Option<ArrayQueue<CommandPoolAlloc>>,
|
||||
// How many command buffers have been allocated from `self.primary_pool`.
|
||||
primary_allocations: Cell<usize>,
|
||||
// How many command buffers have been allocated from `self.secondary_pool`.
|
||||
secondary_allocations: Cell<usize>,
|
||||
inner: Arc<CommandPool>,
|
||||
// List of existing command buffers that are available for reuse.
|
||||
buffer_reserve: [Option<ArrayQueue<CommandPoolAlloc>>; 2],
|
||||
// Where to return this pool once there are no more current allocations.
|
||||
pool_reserve: Weak<ArrayQueue<Arc<Self>>>,
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
fn new(
|
||||
device: Arc<Device>,
|
||||
queue_family_index: u32,
|
||||
reserve: Arc<ArrayQueue<PoolInner>>,
|
||||
create_info: &StandardCommandBufferAllocatorCreateInfo,
|
||||
buffer_counts: &[usize; 2],
|
||||
pool_reserve: &Arc<ArrayQueue<Arc<Self>>>,
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
let inner = CommandPool::new(
|
||||
device,
|
||||
@ -367,152 +488,33 @@ impl Pool {
|
||||
)
|
||||
.map_err(Validated::unwrap)?;
|
||||
|
||||
let primary_pool = if create_info.primary_buffer_count > 0 {
|
||||
let pool = ArrayQueue::new(create_info.primary_buffer_count);
|
||||
let levels = [CommandBufferLevel::Primary, CommandBufferLevel::Secondary];
|
||||
let mut buffer_reserve = [None, None];
|
||||
|
||||
for alloc in inner.allocate_command_buffers(CommandBufferAllocateInfo {
|
||||
level: CommandBufferLevel::Primary,
|
||||
command_buffer_count: create_info.primary_buffer_count as u32,
|
||||
..Default::default()
|
||||
})? {
|
||||
let _ = pool.push(alloc);
|
||||
for (level, &buffer_count) in levels.into_iter().zip(buffer_counts) {
|
||||
if buffer_count == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
Some(pool)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let pool = ArrayQueue::new(buffer_count);
|
||||
|
||||
let secondary_pool = if create_info.secondary_buffer_count > 0 {
|
||||
let pool = ArrayQueue::new(create_info.secondary_buffer_count);
|
||||
|
||||
for alloc in inner.allocate_command_buffers(CommandBufferAllocateInfo {
|
||||
level: CommandBufferLevel::Secondary,
|
||||
command_buffer_count: create_info.secondary_buffer_count as u32,
|
||||
for allocation in inner.allocate_command_buffers(CommandBufferAllocateInfo {
|
||||
level,
|
||||
command_buffer_count: buffer_count.try_into().unwrap(),
|
||||
..Default::default()
|
||||
})? {
|
||||
let _ = pool.push(alloc);
|
||||
let _ = pool.push(allocation);
|
||||
}
|
||||
|
||||
Some(pool)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
buffer_reserve[level as usize] = Some(pool);
|
||||
}
|
||||
|
||||
Ok(Arc::new(Pool {
|
||||
inner: ManuallyDrop::new(PoolInner {
|
||||
inner,
|
||||
primary_pool,
|
||||
secondary_pool,
|
||||
primary_allocations: Cell::new(0),
|
||||
secondary_allocations: Cell::new(0),
|
||||
}),
|
||||
reserve,
|
||||
inner: Arc::new(inner),
|
||||
buffer_reserve,
|
||||
pool_reserve: Arc::downgrade(pool_reserve),
|
||||
}))
|
||||
}
|
||||
|
||||
fn allocate(
|
||||
self: &Arc<Self>,
|
||||
level: CommandBufferLevel,
|
||||
command_buffer_count: u32,
|
||||
) -> Option<IntoIter<[StandardCommandBufferBuilderAlloc; 1]>> {
|
||||
let command_buffer_count = command_buffer_count as usize;
|
||||
|
||||
match level {
|
||||
CommandBufferLevel::Primary => {
|
||||
if let Some(pool) = &self.inner.primary_pool {
|
||||
let count = self.inner.primary_allocations.get();
|
||||
if count + command_buffer_count <= pool.capacity() {
|
||||
let mut output = SmallVec::<[_; 1]>::with_capacity(command_buffer_count);
|
||||
for _ in 0..command_buffer_count {
|
||||
output.push(StandardCommandBufferBuilderAlloc {
|
||||
inner: StandardCommandBufferAlloc {
|
||||
inner: ManuallyDrop::new(pool.pop().unwrap()),
|
||||
pool: self.clone(),
|
||||
},
|
||||
_marker: PhantomData,
|
||||
});
|
||||
}
|
||||
|
||||
self.inner
|
||||
.primary_allocations
|
||||
.set(count + command_buffer_count);
|
||||
|
||||
Some(output.into_iter())
|
||||
} else if command_buffer_count > pool.capacity() {
|
||||
panic!(
|
||||
"command buffer count ({}) exceeds the capacity of the primary command \
|
||||
buffer pool ({})",
|
||||
command_buffer_count, pool.capacity(),
|
||||
);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"attempted to allocate a primary command buffer when the primary command \
|
||||
buffer pool was configured to be empty",
|
||||
);
|
||||
}
|
||||
}
|
||||
CommandBufferLevel::Secondary => {
|
||||
if let Some(pool) = &self.inner.secondary_pool {
|
||||
let count = self.inner.secondary_allocations.get();
|
||||
if count + command_buffer_count <= pool.capacity() {
|
||||
let mut output = SmallVec::<[_; 1]>::with_capacity(command_buffer_count);
|
||||
for _ in 0..command_buffer_count {
|
||||
output.push(StandardCommandBufferBuilderAlloc {
|
||||
inner: StandardCommandBufferAlloc {
|
||||
inner: ManuallyDrop::new(pool.pop().unwrap()),
|
||||
pool: self.clone(),
|
||||
},
|
||||
_marker: PhantomData,
|
||||
});
|
||||
}
|
||||
|
||||
self.inner
|
||||
.secondary_allocations
|
||||
.set(count + command_buffer_count);
|
||||
|
||||
Some(output.into_iter())
|
||||
} else if command_buffer_count > pool.capacity() {
|
||||
panic!(
|
||||
"command buffer count ({}) exceeds the capacity of the secondary \
|
||||
command buffer pool ({})",
|
||||
command_buffer_count,
|
||||
pool.capacity(),
|
||||
);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"attempted to allocate a secondary command buffer when the secondary \
|
||||
command buffer pool was configured to be empty",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Pool {
|
||||
fn drop(&mut self) {
|
||||
let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
|
||||
|
||||
if thread::panicking() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe { inner.inner.reset(CommandPoolResetFlags::empty()) }.unwrap();
|
||||
inner.primary_allocations.set(0);
|
||||
inner.secondary_allocations.set(0);
|
||||
|
||||
// If there is not enough space in the reserve, we destroy the pool. The only way this can
|
||||
// happen is if something is resource hogging, forcing new pools to be created such that
|
||||
// the number exceeds `MAX_POOLS`, and then drops them all at once.
|
||||
let _ = self.reserve.push(inner);
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters to create a new [`StandardCommandBufferAllocator`].
|
||||
@ -552,89 +554,6 @@ impl Default for StandardCommandBufferAllocatorCreateInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Command buffer allocated from a [`StandardCommandBufferAllocator`] that is currently being
|
||||
/// built.
|
||||
pub struct StandardCommandBufferBuilderAlloc {
|
||||
// The only difference between a `StandardCommandBufferBuilder` and a
|
||||
// `StandardCommandBufferAlloc` is that the former must not implement `Send` and `Sync`.
|
||||
// Therefore we just share the structs.
|
||||
inner: StandardCommandBufferAlloc,
|
||||
// Unimplemented `Send` and `Sync` from the builder.
|
||||
_marker: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
unsafe impl CommandBufferBuilderAlloc for StandardCommandBufferBuilderAlloc {
|
||||
type Alloc = StandardCommandBufferAlloc;
|
||||
|
||||
#[inline]
|
||||
fn inner(&self) -> &CommandPoolAlloc {
|
||||
self.inner.inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_alloc(self) -> Self::Alloc {
|
||||
self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_family_index(&self) -> u32 {
|
||||
self.inner.queue_family_index()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for StandardCommandBufferBuilderAlloc {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
/// Command buffer allocated from a [`StandardCommandBufferAllocator`].
|
||||
pub struct StandardCommandBufferAlloc {
|
||||
// The actual command buffer. Extracted in the `Drop` implementation.
|
||||
inner: ManuallyDrop<CommandPoolAlloc>,
|
||||
// We hold a reference to the pool for our destructor.
|
||||
pool: Arc<Pool>,
|
||||
}
|
||||
|
||||
// It's fine to share `Pool` between threads because we never access the Vulkan command pool
|
||||
// concurrently. Same goes for the `Cell`s.
|
||||
unsafe impl Send for StandardCommandBufferAlloc {}
|
||||
unsafe impl Sync for StandardCommandBufferAlloc {}
|
||||
|
||||
unsafe impl CommandBufferAlloc for StandardCommandBufferAlloc {
|
||||
#[inline]
|
||||
fn inner(&self) -> &CommandPoolAlloc {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_family_index(&self) -> u32 {
|
||||
self.pool.inner.inner.queue_family_index()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for StandardCommandBufferAlloc {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.pool.inner.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StandardCommandBufferAlloc {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
|
||||
let pool = match inner.level() {
|
||||
CommandBufferLevel::Primary => &self.pool.inner.primary_pool,
|
||||
CommandBufferLevel::Secondary => &self.pool.inner.secondary_pool,
|
||||
};
|
||||
// This can't panic, because if an allocation from a particular kind of pool was made, then
|
||||
// the pool must exist.
|
||||
let _ = pool.as_ref().unwrap().push(inner);
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can be returned when resetting a [`CommandPool`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ResetCommandPoolError {
|
||||
@ -648,7 +567,7 @@ pub enum ResetCommandPoolError {
|
||||
impl Error for ResetCommandPoolError {}
|
||||
|
||||
impl Display for ResetCommandPoolError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
|
||||
Self::InUse => write!(f, "the command pool is still in use"),
|
||||
@ -667,44 +586,3 @@ impl From<ResetCommandPoolError> for Validated<ResetCommandPoolError> {
|
||||
Self::Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::VulkanObject;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn threads_use_different_pools() {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
|
||||
let pool1 = allocator
|
||||
.allocate(queue.queue_family_index(), CommandBufferLevel::Primary, 1)
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_alloc()
|
||||
.pool
|
||||
.inner
|
||||
.inner
|
||||
.handle();
|
||||
|
||||
thread::spawn(move || {
|
||||
let pool2 = allocator
|
||||
.allocate(queue.queue_family_index(), CommandBufferLevel::Primary, 1)
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_alloc()
|
||||
.pool
|
||||
.inner
|
||||
.inner
|
||||
.handle();
|
||||
assert_ne!(pool1, pool2);
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use super::{
|
||||
use crate::{
|
||||
buffer::{Buffer, IndexBuffer, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::{CommandBufferAllocator, StandardCommandBufferAllocator},
|
||||
allocator::CommandBufferAllocator,
|
||||
sys::{CommandBufferBeginInfo, UnsafeCommandBuffer, UnsafeCommandBufferBuilder},
|
||||
CommandBufferBufferRangeUsage, CommandBufferBufferUsage, CommandBufferImageRangeUsage,
|
||||
CommandBufferImageUsage, CommandBufferInheritanceInfo,
|
||||
@ -54,31 +54,24 @@ use std::{
|
||||
/// the `Send` and `Sync` traits. If you use this allocator, then the `AutoCommandBufferBuilder`
|
||||
/// will not implement `Send` and `Sync` either. Once a command buffer is built, however, it *does*
|
||||
/// implement `Send` and `Sync`.
|
||||
pub struct AutoCommandBufferBuilder<L, A = StandardCommandBufferAllocator>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
pub(in crate::command_buffer) inner: UnsafeCommandBufferBuilder<A>,
|
||||
pub struct AutoCommandBufferBuilder<L> {
|
||||
pub(in crate::command_buffer) inner: UnsafeCommandBufferBuilder,
|
||||
commands: Vec<(
|
||||
CommandInfo,
|
||||
Box<dyn Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static>,
|
||||
Box<dyn Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static>,
|
||||
)>,
|
||||
pub(in crate::command_buffer) builder_state: CommandBufferBuilderState,
|
||||
_data: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<A> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl AutoCommandBufferBuilder<PrimaryAutoCommandBuffer> {
|
||||
/// Starts recording a primary command buffer.
|
||||
#[inline]
|
||||
pub fn primary(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<A>, A>, Validated<VulkanError>>
|
||||
{
|
||||
) -> Result<AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
unsafe {
|
||||
AutoCommandBufferBuilder::begin(
|
||||
allocator,
|
||||
@ -96,10 +89,10 @@ where
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn primary_unchecked(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<A>, A>, VulkanError> {
|
||||
) -> Result<AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
AutoCommandBufferBuilder::begin_unchecked(
|
||||
allocator,
|
||||
queue_family_index,
|
||||
@ -113,19 +106,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer> {
|
||||
/// Starts recording a secondary command buffer.
|
||||
#[inline]
|
||||
pub fn secondary(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
usage: CommandBufferUsage,
|
||||
inheritance_info: CommandBufferInheritanceInfo,
|
||||
) -> Result<AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<A>, A>, Validated<VulkanError>>
|
||||
{
|
||||
) -> Result<AutoCommandBufferBuilder<SecondaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
unsafe {
|
||||
AutoCommandBufferBuilder::begin(
|
||||
allocator,
|
||||
@ -143,11 +132,11 @@ where
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn secondary_unchecked(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
usage: CommandBufferUsage,
|
||||
inheritance_info: CommandBufferInheritanceInfo,
|
||||
) -> Result<AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<A>, A>, VulkanError> {
|
||||
) -> Result<AutoCommandBufferBuilder<SecondaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
AutoCommandBufferBuilder::begin_unchecked(
|
||||
allocator,
|
||||
queue_family_index,
|
||||
@ -161,31 +150,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Actual constructor. Private.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `begin_info.inheritance_info` must match `level`.
|
||||
unsafe fn begin(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
begin_info: CommandBufferBeginInfo,
|
||||
) -> Result<AutoCommandBufferBuilder<L, A>, Validated<VulkanError>> {
|
||||
) -> Result<AutoCommandBufferBuilder<L>, Validated<VulkanError>> {
|
||||
Self::validate_begin(allocator.device(), queue_family_index, level, &begin_info)?;
|
||||
|
||||
unsafe {
|
||||
Ok(Self::begin_unchecked(
|
||||
allocator,
|
||||
queue_family_index,
|
||||
level,
|
||||
begin_info,
|
||||
)?)
|
||||
}
|
||||
unsafe { Self::begin_unchecked(allocator, queue_family_index, level, begin_info) }
|
||||
}
|
||||
|
||||
fn validate_begin(
|
||||
@ -203,11 +182,11 @@ where
|
||||
|
||||
#[inline]
|
||||
unsafe fn begin_unchecked(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
begin_info: CommandBufferBeginInfo,
|
||||
) -> Result<Self, VulkanError> {
|
||||
) -> Result<Self, Validated<VulkanError>> {
|
||||
let &CommandBufferBeginInfo {
|
||||
usage: _,
|
||||
ref inheritance_info,
|
||||
@ -244,8 +223,8 @@ where
|
||||
mut self,
|
||||
) -> Result<
|
||||
(
|
||||
UnsafeCommandBuffer<A>,
|
||||
Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static>>,
|
||||
UnsafeCommandBuffer,
|
||||
Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static>>,
|
||||
CommandBufferResourcesUsage,
|
||||
SecondaryCommandBufferResourcesUsage,
|
||||
),
|
||||
@ -327,12 +306,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<A>, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl AutoCommandBufferBuilder<PrimaryAutoCommandBuffer> {
|
||||
/// Builds the command buffer.
|
||||
pub fn build(self) -> Result<Arc<PrimaryAutoCommandBuffer<A>>, Validated<VulkanError>> {
|
||||
pub fn build(self) -> Result<Arc<PrimaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
if self.builder_state.render_pass.is_some() {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a render pass instance is still active".into(),
|
||||
@ -365,12 +341,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<A>, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer> {
|
||||
/// Builds the command buffer.
|
||||
pub fn build(self) -> Result<Arc<SecondaryAutoCommandBuffer<A>>, Validated<VulkanError>> {
|
||||
pub fn build(self) -> Result<Arc<SecondaryAutoCommandBuffer>, Validated<VulkanError>> {
|
||||
if !self.builder_state.queries.is_empty() {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a query is still active".into(),
|
||||
@ -401,15 +374,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
pub(in crate::command_buffer) fn add_command(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
used_resources: Vec<(ResourceUseRef2, Resource)>,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static,
|
||||
) {
|
||||
self.commands.push((
|
||||
CommandInfo {
|
||||
@ -425,7 +395,7 @@ where
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
used_resources: Vec<(ResourceUseRef2, Resource)>,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static,
|
||||
) {
|
||||
self.commands.push((
|
||||
CommandInfo {
|
||||
@ -441,7 +411,7 @@ where
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
used_resources: Vec<(ResourceUseRef2, Resource)>,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static,
|
||||
record_func: impl Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static,
|
||||
) {
|
||||
self.commands.push((
|
||||
CommandInfo {
|
||||
@ -454,10 +424,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<L, A> DeviceOwned for AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl<L> DeviceOwned for AutoCommandBufferBuilder<L> {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ pub(in crate::command_buffer) use self::builder::{
|
||||
RenderPassStateAttachments, RenderPassStateType, SetOrPush,
|
||||
};
|
||||
use super::{
|
||||
allocator::{CommandBufferAllocator, StandardCommandBufferAllocator},
|
||||
sys::{UnsafeCommandBuffer, UnsafeCommandBufferBuilder},
|
||||
CommandBufferInheritanceInfo, CommandBufferResourcesUsage, CommandBufferState,
|
||||
CommandBufferUsage, PrimaryCommandBufferAbstract, ResourceInCommand,
|
||||
@ -87,101 +86,86 @@ use std::{
|
||||
|
||||
mod builder;
|
||||
|
||||
pub struct PrimaryAutoCommandBuffer<A = StandardCommandBufferAllocator>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
inner: UnsafeCommandBuffer<A>,
|
||||
_keep_alive_objects:
|
||||
Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static>>,
|
||||
pub struct PrimaryAutoCommandBuffer {
|
||||
inner: UnsafeCommandBuffer,
|
||||
_keep_alive_objects: Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static>>,
|
||||
resources_usage: CommandBufferResourcesUsage,
|
||||
state: Mutex<CommandBufferState>,
|
||||
}
|
||||
|
||||
unsafe impl<A> VulkanObject for PrimaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl VulkanObject for PrimaryAutoCommandBuffer {
|
||||
type Handle = ash::vk::CommandBuffer;
|
||||
|
||||
#[inline]
|
||||
fn handle(&self) -> Self::Handle {
|
||||
self.inner.handle()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for PrimaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl DeviceOwned for PrimaryAutoCommandBuffer {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> PrimaryCommandBufferAbstract for PrimaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl PrimaryCommandBufferAbstract for PrimaryAutoCommandBuffer {
|
||||
#[inline]
|
||||
fn queue_family_index(&self) -> u32 {
|
||||
self.inner.queue_family_index()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn usage(&self) -> CommandBufferUsage {
|
||||
self.inner.usage()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn state(&self) -> MutexGuard<'_, CommandBufferState> {
|
||||
self.state.lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resources_usage(&self) -> &CommandBufferResourcesUsage {
|
||||
&self.resources_usage
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SecondaryAutoCommandBuffer<A = StandardCommandBufferAllocator>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
inner: UnsafeCommandBuffer<A>,
|
||||
_keep_alive_objects:
|
||||
Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder<A>) + Send + Sync + 'static>>,
|
||||
pub struct SecondaryAutoCommandBuffer {
|
||||
inner: UnsafeCommandBuffer,
|
||||
_keep_alive_objects: Vec<Box<dyn Fn(&mut UnsafeCommandBufferBuilder) + Send + Sync + 'static>>,
|
||||
resources_usage: SecondaryCommandBufferResourcesUsage,
|
||||
submit_state: SubmitState,
|
||||
}
|
||||
|
||||
unsafe impl<A> VulkanObject for SecondaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl VulkanObject for SecondaryAutoCommandBuffer {
|
||||
type Handle = ash::vk::CommandBuffer;
|
||||
|
||||
#[inline]
|
||||
fn handle(&self) -> Self::Handle {
|
||||
self.inner.handle()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for SecondaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl DeviceOwned for SecondaryAutoCommandBuffer {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> SecondaryCommandBufferAbstract for SecondaryAutoCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl SecondaryCommandBufferAbstract for SecondaryAutoCommandBuffer {
|
||||
#[inline]
|
||||
fn usage(&self) -> CommandBufferUsage {
|
||||
self.inner.usage()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inheritance_info(&self) -> &CommandBufferInheritanceInfo {
|
||||
self.inner.inheritance_info().as_ref().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lock_record(&self) -> Result<(), Box<ValidationError>> {
|
||||
match self.submit_state {
|
||||
SubmitState::OneTime {
|
||||
@ -218,6 +202,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unlock(&self) {
|
||||
match self.submit_state {
|
||||
SubmitState::OneTime {
|
||||
@ -233,6 +218,7 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resources_usage(&self) -> &SecondaryCommandBufferResourcesUsage {
|
||||
&self.resources_usage
|
||||
}
|
||||
@ -341,10 +327,13 @@ mod tests {
|
||||
fn basic_creation() {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
let allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
AutoCommandBufferBuilder::primary(
|
||||
&allocator,
|
||||
allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
@ -405,9 +394,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
Default::default(),
|
||||
));
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -443,17 +435,17 @@ mod tests {
|
||||
fn secondary_nonconcurrent_conflict() {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
StandardCommandBufferAllocatorCreateInfo {
|
||||
secondary_buffer_count: 1,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
));
|
||||
|
||||
// Make a secondary CB that doesn't support simultaneous use.
|
||||
let builder = AutoCommandBufferBuilder::secondary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
Default::default(),
|
||||
@ -463,7 +455,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
@ -479,7 +471,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
@ -488,7 +480,7 @@ mod tests {
|
||||
let cb1 = builder.build().unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
@ -525,9 +517,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
Default::default(),
|
||||
));
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -580,9 +575,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(device, Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device,
|
||||
Default::default(),
|
||||
));
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -607,15 +605,15 @@ mod tests {
|
||||
unsafe {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
StandardCommandBufferAllocatorCreateInfo {
|
||||
secondary_buffer_count: 1,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
));
|
||||
let cbb = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -651,7 +649,7 @@ mod tests {
|
||||
let secondary = (0..2)
|
||||
.map(|_| {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
Default::default(),
|
||||
@ -666,7 +664,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator.clone(),
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
@ -689,7 +687,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
@ -711,10 +709,12 @@ mod tests {
|
||||
unsafe {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let cb_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let mut sync = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
@ -748,10 +748,12 @@ mod tests {
|
||||
unsafe {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let cb_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let mut sync = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
|
@ -11,7 +11,6 @@ use crate::{
|
||||
},
|
||||
buffer::{BufferUsage, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator,
|
||||
auto::{Resource, ResourceUseRef2},
|
||||
sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, ResourceInCommand,
|
||||
@ -25,10 +24,7 @@ use smallvec::SmallVec;
|
||||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
/// # Commands to do operations on acceleration structures.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Builds or updates an acceleration structure.
|
||||
///
|
||||
/// # Safety
|
||||
@ -123,7 +119,7 @@ where
|
||||
self.add_command(
|
||||
"build_acceleration_structure",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.build_acceleration_structure_unchecked(&info, &build_range_infos);
|
||||
},
|
||||
);
|
||||
@ -255,7 +251,7 @@ where
|
||||
self.add_command(
|
||||
"build_acceleration_structure_indirect",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.build_acceleration_structure_indirect_unchecked(
|
||||
&info,
|
||||
&indirect_buffer,
|
||||
@ -344,7 +340,7 @@ where
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_acceleration_structure_unchecked(&info);
|
||||
},
|
||||
);
|
||||
@ -428,7 +424,7 @@ where
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_acceleration_structure_to_memory_unchecked(&info);
|
||||
},
|
||||
);
|
||||
@ -515,7 +511,7 @@ where
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_memory_to_acceleration_structure_unchecked(&info);
|
||||
},
|
||||
);
|
||||
@ -611,7 +607,7 @@ where
|
||||
},
|
||||
)
|
||||
}).collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.write_acceleration_structures_properties_unchecked(
|
||||
&acceleration_structures,
|
||||
&query_pool,
|
||||
@ -798,10 +794,8 @@ fn add_indirect_buffer_resources(
|
||||
));
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn build_acceleration_structure(
|
||||
&mut self,
|
||||
info: &AccelerationStructureBuildGeometryInfo,
|
||||
@ -1591,6 +1585,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn build_acceleration_structure_indirect(
|
||||
&mut self,
|
||||
info: &AccelerationStructureBuildGeometryInfo,
|
||||
@ -2212,6 +2207,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_acceleration_structure(
|
||||
&mut self,
|
||||
info: &CopyAccelerationStructureInfo,
|
||||
@ -2271,6 +2267,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_acceleration_structure_to_memory(
|
||||
&mut self,
|
||||
info: &CopyAccelerationStructureToMemoryInfo,
|
||||
@ -2341,6 +2338,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_memory_to_acceleration_structure(
|
||||
&mut self,
|
||||
info: &CopyMemoryToAccelerationStructureInfo,
|
||||
@ -2411,6 +2409,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn write_acceleration_structures_properties(
|
||||
&mut self,
|
||||
acceleration_structures: &[Arc<AccelerationStructure>],
|
||||
|
@ -1,9 +1,6 @@
|
||||
use crate::{
|
||||
buffer::{BufferContents, BufferUsage, IndexBuffer, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator, auto::SetOrPush, sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder,
|
||||
},
|
||||
command_buffer::{auto::SetOrPush, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder},
|
||||
descriptor_set::{
|
||||
layout::{DescriptorBindingFlags, DescriptorSetLayoutCreateFlags, DescriptorType},
|
||||
DescriptorBindingResources, DescriptorBufferInfo, DescriptorSetResources,
|
||||
@ -24,10 +21,7 @@ use std::{cmp::min, ffi::c_void, mem::size_of, sync::Arc};
|
||||
/// # Commands to bind or push state for pipeline execution commands.
|
||||
///
|
||||
/// These commands require a queue with a pipeline type that uses the given state.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Binds descriptor sets for future dispatch or draw calls.
|
||||
pub fn bind_descriptor_sets(
|
||||
&mut self,
|
||||
@ -101,7 +95,7 @@ where
|
||||
self.add_command(
|
||||
"bind_descriptor_sets",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.bind_descriptor_sets_unchecked(
|
||||
pipeline_bind_point,
|
||||
&pipeline_layout,
|
||||
@ -144,7 +138,7 @@ where
|
||||
self.add_command(
|
||||
"bind_index_buffer",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.bind_index_buffer_unchecked(&index_buffer);
|
||||
},
|
||||
);
|
||||
@ -180,7 +174,7 @@ where
|
||||
self.add_command(
|
||||
"bind_pipeline_compute",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.bind_pipeline_compute_unchecked(&pipeline);
|
||||
},
|
||||
);
|
||||
@ -223,7 +217,7 @@ where
|
||||
self.add_command(
|
||||
"bind_pipeline_graphics",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.bind_pipeline_graphics_unchecked(&pipeline);
|
||||
},
|
||||
);
|
||||
@ -271,7 +265,7 @@ where
|
||||
self.add_command(
|
||||
"bind_vertex_buffers",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.bind_vertex_buffers_unchecked(first_binding, &vertex_buffers);
|
||||
},
|
||||
);
|
||||
@ -335,7 +329,7 @@ where
|
||||
self.add_command(
|
||||
"push_constants",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.push_constants_unchecked(&pipeline_layout, offset, &push_constants);
|
||||
},
|
||||
);
|
||||
@ -420,7 +414,7 @@ where
|
||||
self.add_command(
|
||||
"push_descriptor_set",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.push_descriptor_set_unchecked(
|
||||
pipeline_bind_point,
|
||||
&pipeline_layout,
|
||||
@ -434,10 +428,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn bind_descriptor_sets(
|
||||
&mut self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
@ -708,6 +700,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bind_index_buffer(
|
||||
&mut self,
|
||||
index_buffer: &IndexBuffer,
|
||||
@ -787,6 +780,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bind_pipeline_compute(
|
||||
&mut self,
|
||||
pipeline: &ComputePipeline,
|
||||
@ -835,6 +829,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bind_pipeline_graphics(
|
||||
&mut self,
|
||||
pipeline: &GraphicsPipeline,
|
||||
@ -883,6 +878,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bind_vertex_buffers(
|
||||
&mut self,
|
||||
first_binding: u32,
|
||||
@ -975,6 +971,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn push_constants<Pc>(
|
||||
&mut self,
|
||||
pipeline_layout: &PipelineLayout,
|
||||
@ -1132,6 +1129,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn push_descriptor_set(
|
||||
&mut self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
buffer::{BufferContents, BufferUsage, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator, auto::Resource, sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, ResourceInCommand,
|
||||
auto::Resource, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder,
|
||||
ResourceInCommand,
|
||||
},
|
||||
device::{Device, DeviceOwned, QueueFlags},
|
||||
format::{ClearColorValue, ClearDepthStencilValue, FormatFeatures},
|
||||
@ -15,10 +15,7 @@ use smallvec::{smallvec, SmallVec};
|
||||
use std::{mem::size_of_val, sync::Arc};
|
||||
|
||||
/// # Commands to fill resources with new data.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Clears a color image with a specific value.
|
||||
pub fn clear_color_image(
|
||||
&mut self,
|
||||
@ -77,7 +74,7 @@ where
|
||||
)]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.clear_color_image_unchecked(&clear_info);
|
||||
},
|
||||
);
|
||||
@ -143,7 +140,7 @@ where
|
||||
)]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.clear_depth_stencil_image_unchecked(&clear_info);
|
||||
},
|
||||
);
|
||||
@ -201,7 +198,7 @@ where
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.fill_buffer_unchecked(&dst_buffer, data);
|
||||
},
|
||||
);
|
||||
@ -267,7 +264,7 @@ where
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.update_buffer_unchecked(&dst_buffer, &data);
|
||||
},
|
||||
);
|
||||
@ -276,10 +273,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn clear_color_image(
|
||||
&mut self,
|
||||
clear_info: &ClearColorImageInfo,
|
||||
@ -351,6 +346,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn clear_depth_stencil_image(
|
||||
&mut self,
|
||||
clear_info: &ClearDepthStencilImageInfo,
|
||||
@ -422,6 +418,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn fill_buffer(
|
||||
&mut self,
|
||||
dst_buffer: &Subbuffer<[u32]>,
|
||||
@ -516,6 +513,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn update_buffer<D>(
|
||||
&mut self,
|
||||
dst_buffer: &Subbuffer<D>,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
buffer::{BufferUsage, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator, auto::Resource, sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, ResourceInCommand,
|
||||
auto::Resource, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder,
|
||||
ResourceInCommand,
|
||||
},
|
||||
device::{Device, DeviceOwned, QueueFlags},
|
||||
format::{Format, FormatFeatures},
|
||||
@ -21,10 +21,7 @@ use std::{
|
||||
};
|
||||
|
||||
/// # Commands to transfer data between resources.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Copies data from a buffer to another buffer.
|
||||
///
|
||||
/// # Panics
|
||||
@ -103,7 +100,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_buffer_unchecked(©_buffer_info);
|
||||
},
|
||||
);
|
||||
@ -206,7 +203,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_image_unchecked(©_image_info);
|
||||
},
|
||||
);
|
||||
@ -293,7 +290,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_buffer_to_image_unchecked(©_buffer_to_image_info);
|
||||
},
|
||||
);
|
||||
@ -380,7 +377,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_image_to_buffer_unchecked(©_image_to_buffer_info);
|
||||
},
|
||||
);
|
||||
@ -493,7 +490,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.blit_image_unchecked(&blit_image_info);
|
||||
},
|
||||
);
|
||||
@ -585,7 +582,7 @@ where
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.resolve_image_unchecked(&resolve_image_info);
|
||||
},
|
||||
);
|
||||
@ -594,10 +591,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn copy_buffer(
|
||||
&mut self,
|
||||
copy_buffer_info: &CopyBufferInfo,
|
||||
@ -713,6 +708,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_image(
|
||||
&mut self,
|
||||
copy_image_info: &CopyImageInfo,
|
||||
@ -1136,6 +1132,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_buffer_to_image(
|
||||
&mut self,
|
||||
copy_buffer_to_image_info: &CopyBufferToImageInfo,
|
||||
@ -1478,6 +1475,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_image_to_buffer(
|
||||
&mut self,
|
||||
copy_image_to_buffer_info: &CopyImageToBufferInfo,
|
||||
@ -1799,6 +1797,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn blit_image(
|
||||
&mut self,
|
||||
blit_image_info: &BlitImageInfo,
|
||||
@ -1971,6 +1970,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn resolve_image(
|
||||
&mut self,
|
||||
resolve_image_info: &ResolveImageInfo,
|
||||
|
@ -1,8 +1,5 @@
|
||||
use crate::{
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator, sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder,
|
||||
},
|
||||
command_buffer::{sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder},
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
instance::debug::DebugUtilsLabel,
|
||||
Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject,
|
||||
@ -14,10 +11,7 @@ use std::ffi::CString;
|
||||
/// These commands all require the [`ext_debug_utils`] extension to be enabled on the instance.
|
||||
///
|
||||
/// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Opens a command buffer debug label region.
|
||||
pub fn begin_debug_utils_label(
|
||||
&mut self,
|
||||
@ -45,7 +39,7 @@ where
|
||||
self.add_command(
|
||||
"begin_debug_utils_label",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.begin_debug_utils_label_unchecked(&label_info);
|
||||
},
|
||||
);
|
||||
@ -81,7 +75,7 @@ where
|
||||
self.add_command(
|
||||
"end_debug_utils_label",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.end_debug_utils_label_unchecked();
|
||||
},
|
||||
);
|
||||
@ -116,7 +110,7 @@ where
|
||||
self.add_command(
|
||||
"insert_debug_utils_label",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.insert_debug_utils_label_unchecked(&label_info);
|
||||
},
|
||||
);
|
||||
@ -125,10 +119,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn begin_debug_utils_label(
|
||||
&mut self,
|
||||
label_info: &DebugUtilsLabel,
|
||||
@ -197,6 +189,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_end_debug_utils_label()?;
|
||||
|
||||
@ -243,6 +236,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn insert_debug_utils_label(
|
||||
&mut self,
|
||||
label_info: &DebugUtilsLabel,
|
||||
|
@ -1,8 +1,5 @@
|
||||
use crate::{
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator, sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder,
|
||||
},
|
||||
command_buffer::{sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder},
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
@ -22,10 +19,7 @@ use std::ops::RangeInclusive;
|
||||
/// # Commands to set dynamic state for pipelines.
|
||||
///
|
||||
/// These commands require a queue with a pipeline type that uses the given state.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
// Helper function for dynamic state setting.
|
||||
fn validate_graphics_pipeline_fixed_state(
|
||||
&self,
|
||||
@ -76,7 +70,7 @@ where
|
||||
self.add_command(
|
||||
"set_blend_constants",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_blend_constants_unchecked(constants);
|
||||
},
|
||||
);
|
||||
@ -133,7 +127,7 @@ where
|
||||
self.add_command(
|
||||
"set_color_write_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_color_write_enable_unchecked(&enables);
|
||||
},
|
||||
);
|
||||
@ -165,7 +159,7 @@ where
|
||||
self.add_command(
|
||||
"set_cull_mode",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_cull_mode_unchecked(cull_mode);
|
||||
},
|
||||
);
|
||||
@ -214,7 +208,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_bias",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_bias_unchecked(constant_factor, clamp, slope_factor);
|
||||
},
|
||||
);
|
||||
@ -246,7 +240,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_bias_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_bias_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -281,7 +275,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_bounds",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_bounds_unchecked(bounds.clone());
|
||||
},
|
||||
);
|
||||
@ -316,7 +310,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_bounds_test_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_bounds_test_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -351,7 +345,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_compare_op",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_compare_op_unchecked(compare_op);
|
||||
},
|
||||
);
|
||||
@ -383,7 +377,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_test_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_test_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -415,7 +409,7 @@ where
|
||||
self.add_command(
|
||||
"set_depth_write_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_depth_write_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -461,7 +455,7 @@ where
|
||||
self.add_command(
|
||||
"set_discard_rectangle",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_discard_rectangle_unchecked(first_rectangle, &rectangles);
|
||||
},
|
||||
);
|
||||
@ -490,7 +484,7 @@ where
|
||||
self.add_command(
|
||||
"set_front_face",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_front_face_unchecked(face);
|
||||
},
|
||||
);
|
||||
@ -527,7 +521,7 @@ where
|
||||
self.add_command(
|
||||
"set_line_stipple",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_line_stipple_unchecked(factor, pattern);
|
||||
},
|
||||
);
|
||||
@ -556,7 +550,7 @@ where
|
||||
self.add_command(
|
||||
"set_line_width",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_line_width_unchecked(line_width);
|
||||
},
|
||||
);
|
||||
@ -585,7 +579,7 @@ where
|
||||
self.add_command(
|
||||
"set_logic_op",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_logic_op_unchecked(logic_op);
|
||||
},
|
||||
);
|
||||
@ -617,7 +611,7 @@ where
|
||||
self.add_command(
|
||||
"set_patch_control_points",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_patch_control_points_unchecked(num);
|
||||
},
|
||||
);
|
||||
@ -652,7 +646,7 @@ where
|
||||
self.add_command(
|
||||
"set_primitive_restart_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_primitive_restart_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -690,7 +684,7 @@ where
|
||||
self.add_command(
|
||||
"set_primitive_topology",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_primitive_topology_unchecked(topology);
|
||||
},
|
||||
);
|
||||
@ -725,7 +719,7 @@ where
|
||||
self.add_command(
|
||||
"set_rasterizer_discard_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_rasterizer_discard_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -772,7 +766,7 @@ where
|
||||
self.add_command(
|
||||
"set_scissor",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_scissor_unchecked(first_scissor, &scissors);
|
||||
},
|
||||
);
|
||||
@ -810,7 +804,7 @@ where
|
||||
self.add_command(
|
||||
"set_scissor_with_count",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_scissor_with_count_unchecked(&scissors);
|
||||
},
|
||||
);
|
||||
@ -861,7 +855,7 @@ where
|
||||
self.add_command(
|
||||
"set_stencil_compare_mask",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_stencil_compare_mask_unchecked(faces, compare_mask);
|
||||
},
|
||||
);
|
||||
@ -933,7 +927,7 @@ where
|
||||
self.add_command(
|
||||
"set_stencil_op",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_stencil_op_unchecked(faces, fail_op, pass_op, depth_fail_op, compare_op);
|
||||
},
|
||||
);
|
||||
@ -984,7 +978,7 @@ where
|
||||
self.add_command(
|
||||
"set_stencil_reference",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_stencil_reference_unchecked(faces, reference);
|
||||
},
|
||||
);
|
||||
@ -1016,7 +1010,7 @@ where
|
||||
self.add_command(
|
||||
"set_stencil_test_enable",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_stencil_test_enable_unchecked(enable);
|
||||
},
|
||||
);
|
||||
@ -1067,7 +1061,7 @@ where
|
||||
self.add_command(
|
||||
"set_stencil_write_mask",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_stencil_write_mask_unchecked(faces, write_mask);
|
||||
},
|
||||
);
|
||||
@ -1113,7 +1107,7 @@ where
|
||||
self.add_command(
|
||||
"set_viewport",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_viewport_unchecked(first_viewport, &viewports);
|
||||
},
|
||||
);
|
||||
@ -1151,7 +1145,7 @@ where
|
||||
self.add_command(
|
||||
"set_viewport",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.set_viewport_with_count_unchecked(&viewports);
|
||||
},
|
||||
);
|
||||
@ -1160,10 +1154,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn set_blend_constants(
|
||||
&mut self,
|
||||
constants: [f32; 4],
|
||||
@ -1202,6 +1194,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_color_write_enable(
|
||||
&mut self,
|
||||
enables: &[bool],
|
||||
@ -1264,6 +1257,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_cull_mode(
|
||||
&mut self,
|
||||
cull_mode: CullMode,
|
||||
@ -1322,6 +1316,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_bias(
|
||||
&mut self,
|
||||
constant_factor: f32,
|
||||
@ -1380,6 +1375,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_bias_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -1434,6 +1430,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_bounds(
|
||||
&mut self,
|
||||
bounds: RangeInclusive<f32>,
|
||||
@ -1500,6 +1497,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_bounds_test_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -1557,6 +1555,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_compare_op(
|
||||
&mut self,
|
||||
compare_op: CompareOp,
|
||||
@ -1621,6 +1620,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_test_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -1677,6 +1677,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_depth_write_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -1731,6 +1732,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_discard_rectangle(
|
||||
&mut self,
|
||||
first_rectangle: u32,
|
||||
@ -1809,6 +1811,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_front_face(
|
||||
&mut self,
|
||||
face: FrontFace,
|
||||
@ -1867,6 +1870,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_line_stipple(
|
||||
&mut self,
|
||||
factor: u32,
|
||||
@ -1925,6 +1929,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_line_width(
|
||||
&mut self,
|
||||
line_width: f32,
|
||||
@ -1971,6 +1976,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_logic_op(
|
||||
&mut self,
|
||||
logic_op: LogicOp,
|
||||
@ -2025,6 +2031,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_patch_control_points(
|
||||
&mut self,
|
||||
num: u32,
|
||||
@ -2095,6 +2102,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_primitive_restart_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -2152,6 +2160,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_primitive_topology(
|
||||
&mut self,
|
||||
topology: PrimitiveTopology,
|
||||
@ -2264,6 +2273,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_rasterizer_discard_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -2321,6 +2331,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor(
|
||||
&mut self,
|
||||
first_scissor: u32,
|
||||
@ -2413,6 +2424,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor_with_count(
|
||||
&mut self,
|
||||
scissors: &[Scissor],
|
||||
@ -2507,6 +2519,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_stencil_compare_mask(
|
||||
&mut self,
|
||||
faces: StencilFaces,
|
||||
@ -2556,6 +2569,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_stencil_op(
|
||||
&mut self,
|
||||
faces: StencilFaces,
|
||||
@ -2668,6 +2682,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_stencil_reference(
|
||||
&mut self,
|
||||
faces: StencilFaces,
|
||||
@ -2717,6 +2732,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_stencil_test_enable(
|
||||
&mut self,
|
||||
enable: bool,
|
||||
@ -2771,6 +2787,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_stencil_write_mask(
|
||||
&mut self,
|
||||
faces: StencilFaces,
|
||||
@ -2820,6 +2837,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport(
|
||||
&mut self,
|
||||
first_viewport: u32,
|
||||
@ -2912,6 +2930,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport_with_count(
|
||||
&mut self,
|
||||
viewports: &[Viewport],
|
||||
|
@ -2,7 +2,6 @@ use crate::{
|
||||
acceleration_structure::AccelerationStructure,
|
||||
buffer::{view::BufferView, BufferUsage, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator,
|
||||
auto::{RenderPassState, RenderPassStateType, Resource, ResourceUseRef2},
|
||||
sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, DispatchIndirectCommand, DrawIndexedIndirectCommand,
|
||||
@ -44,10 +43,7 @@ macro_rules! vuids {
|
||||
/// # Commands to execute a bound pipeline.
|
||||
///
|
||||
/// Dispatch commands require a compute queue, draw commands require a graphics queue.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Perform a single compute operation using a compute pipeline.
|
||||
///
|
||||
/// A compute pipeline must have been bound using
|
||||
@ -105,7 +101,7 @@ where
|
||||
self.add_command(
|
||||
"dispatch",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.dispatch_unchecked(group_counts);
|
||||
},
|
||||
);
|
||||
@ -181,7 +177,7 @@ where
|
||||
self.add_command(
|
||||
"dispatch",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.dispatch_indirect_unchecked(&indirect_buffer);
|
||||
},
|
||||
);
|
||||
@ -358,7 +354,7 @@ where
|
||||
self.add_command(
|
||||
"draw",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.draw_unchecked(vertex_count, instance_count, first_vertex, first_instance);
|
||||
},
|
||||
);
|
||||
@ -460,7 +456,7 @@ where
|
||||
self.add_command(
|
||||
"draw_indirect",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.draw_indirect_unchecked(&indirect_buffer, draw_count, stride);
|
||||
},
|
||||
);
|
||||
@ -675,7 +671,7 @@ where
|
||||
self.add_command(
|
||||
"draw_indexed",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.draw_indexed_unchecked(
|
||||
index_count,
|
||||
instance_count,
|
||||
@ -797,7 +793,7 @@ where
|
||||
self.add_command(
|
||||
"draw_indexed_indirect",
|
||||
used_resources,
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.draw_indexed_indirect_unchecked(&indirect_buffer, draw_count, stride);
|
||||
},
|
||||
);
|
||||
@ -2711,10 +2707,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn dispatch(
|
||||
&mut self,
|
||||
group_counts: [u32; 3],
|
||||
@ -2784,6 +2778,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn dispatch_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DispatchIndirectCommand]>,
|
||||
@ -2858,6 +2853,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw(
|
||||
&mut self,
|
||||
vertex_count: u32,
|
||||
@ -2914,6 +2910,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndirectCommand]>,
|
||||
@ -3048,6 +3045,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indexed(
|
||||
&mut self,
|
||||
index_count: u32,
|
||||
@ -3120,6 +3118,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
buffer::{BufferUsage, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator,
|
||||
auto::{QueryState, Resource},
|
||||
sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, ResourceInCommand,
|
||||
@ -14,10 +13,7 @@ use crate::{
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
/// # Commands related to queries.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Begins a query.
|
||||
///
|
||||
/// The query will be active until [`end_query`](Self::end_query) is called for the same query.
|
||||
@ -101,7 +97,7 @@ where
|
||||
self.add_command(
|
||||
"begin_query",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.begin_query_unchecked(&query_pool, query, flags);
|
||||
},
|
||||
);
|
||||
@ -173,7 +169,7 @@ where
|
||||
self.add_command(
|
||||
"end_query",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.end_query_unchecked(&query_pool, query);
|
||||
},
|
||||
);
|
||||
@ -240,7 +236,7 @@ where
|
||||
self.add_command(
|
||||
"write_timestamp",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.write_timestamp_unchecked(&query_pool, query, stage);
|
||||
},
|
||||
);
|
||||
@ -323,7 +319,7 @@ where
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.copy_query_pool_results_unchecked(
|
||||
&query_pool,
|
||||
queries.clone(),
|
||||
@ -395,7 +391,7 @@ where
|
||||
self.add_command(
|
||||
"reset_query_pool",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.reset_query_pool_unchecked(&query_pool, queries.clone());
|
||||
},
|
||||
);
|
||||
@ -404,10 +400,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn begin_query(
|
||||
&mut self,
|
||||
query_pool: &QueryPool,
|
||||
@ -568,6 +562,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn end_query(
|
||||
&mut self,
|
||||
query_pool: &QueryPool,
|
||||
@ -624,6 +619,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn write_timestamp(
|
||||
&mut self,
|
||||
query_pool: &QueryPool,
|
||||
@ -883,6 +879,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn copy_query_pool_results<T>(
|
||||
&mut self,
|
||||
query_pool: &QueryPool,
|
||||
@ -1023,6 +1020,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reset_query_pool(
|
||||
&mut self,
|
||||
query_pool: &QueryPool,
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator,
|
||||
auto::{
|
||||
BeginRenderPassState, BeginRenderingState, RenderPassState, RenderPassStateAttachments,
|
||||
RenderPassStateType, Resource,
|
||||
@ -25,10 +24,7 @@ use std::{cmp::min, ops::Range, sync::Arc};
|
||||
/// # Commands for render passes.
|
||||
///
|
||||
/// These commands require a graphics queue.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Begins a render pass using a render pass object and framebuffer.
|
||||
///
|
||||
/// You must call this or `begin_rendering` before you can record draw commands.
|
||||
@ -140,7 +136,7 @@ where
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.begin_render_pass_unchecked(&render_pass_begin_info, &subpass_begin_info);
|
||||
},
|
||||
);
|
||||
@ -242,7 +238,7 @@ where
|
||||
self.add_command(
|
||||
"next_subpass",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.next_subpass_unchecked(&subpass_end_info, &subpass_begin_info);
|
||||
},
|
||||
);
|
||||
@ -323,7 +319,7 @@ where
|
||||
self.add_render_pass_end(
|
||||
"end_render_pass",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.end_render_pass_unchecked(&subpass_end_info);
|
||||
},
|
||||
);
|
||||
@ -332,10 +328,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Begins a render pass without a render pass object or framebuffer.
|
||||
///
|
||||
/// You must call this or `begin_render_pass` before you can record draw commands.
|
||||
@ -564,7 +557,7 @@ where
|
||||
.flatten()
|
||||
}))
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.begin_rendering_unchecked(&rendering_info);
|
||||
},
|
||||
);
|
||||
@ -631,7 +624,7 @@ where
|
||||
self.add_render_pass_end(
|
||||
"end_rendering",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.end_rendering_unchecked();
|
||||
},
|
||||
);
|
||||
@ -882,7 +875,7 @@ where
|
||||
self.add_command(
|
||||
"clear_attachments",
|
||||
Default::default(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.clear_attachments_unchecked(&attachments, &rects);
|
||||
},
|
||||
);
|
||||
@ -891,10 +884,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn begin_render_pass(
|
||||
&mut self,
|
||||
render_pass_begin_info: &RenderPassBeginInfo,
|
||||
@ -1315,6 +1306,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn next_subpass(
|
||||
&mut self,
|
||||
subpass_end_info: &SubpassEndInfo,
|
||||
@ -1408,6 +1400,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn end_render_pass(
|
||||
&mut self,
|
||||
subpass_end_info: &SubpassEndInfo,
|
||||
@ -1481,6 +1474,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn begin_rendering(
|
||||
&mut self,
|
||||
rendering_info: &RenderingInfo,
|
||||
@ -1653,6 +1647,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn end_rendering(&mut self) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_end_rendering()?;
|
||||
|
||||
@ -1690,6 +1685,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn clear_attachments(
|
||||
&mut self,
|
||||
attachments: &[ClearAttachment],
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
command_buffer::{
|
||||
allocator::CommandBufferAllocator,
|
||||
auto::{RenderPassStateType, Resource, ResourceUseRef2},
|
||||
sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, CommandBufferInheritanceRenderPassType, CommandBufferLevel,
|
||||
@ -18,10 +17,7 @@ use std::{cmp::min, iter, ops::Deref, sync::Arc};
|
||||
///
|
||||
/// These commands can be called on any queue that can execute the commands recorded in the
|
||||
/// secondary command buffer.
|
||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl<L> AutoCommandBufferBuilder<L> {
|
||||
/// Executes a secondary command buffer.
|
||||
///
|
||||
/// If the `flags` that `command_buffer` was created with are more restrictive than those of
|
||||
@ -543,7 +539,7 @@ where
|
||||
}))
|
||||
})
|
||||
.collect(),
|
||||
move |out: &mut UnsafeCommandBufferBuilder<A>| {
|
||||
move |out: &mut UnsafeCommandBufferBuilder| {
|
||||
out.execute_commands_locked(&command_buffers);
|
||||
},
|
||||
);
|
||||
@ -552,10 +548,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn execute_commands(
|
||||
&mut self,
|
||||
command_buffers: &[Arc<dyn SecondaryCommandBufferAbstract>],
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
command_buffer::{allocator::CommandBufferAllocator, sys::UnsafeCommandBufferBuilder},
|
||||
command_buffer::sys::UnsafeCommandBufferBuilder,
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
sync::{
|
||||
event::Event, BufferMemoryBarrier, DependencyFlags, DependencyInfo, ImageMemoryBarrier,
|
||||
@ -10,10 +10,8 @@ use crate::{
|
||||
use smallvec::SmallVec;
|
||||
use std::{ptr, sync::Arc};
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
pub unsafe fn pipeline_barrier(
|
||||
&mut self,
|
||||
dependency_info: &DependencyInfo,
|
||||
@ -454,6 +452,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_event(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
@ -808,6 +807,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wait_events(
|
||||
&mut self,
|
||||
events: &[(Arc<Event>, DependencyInfo)],
|
||||
@ -1315,6 +1315,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reset_event(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
|
@ -58,38 +58,38 @@
|
||||
//! the moment when the execution will end on the GPU.
|
||||
//!
|
||||
//! ```
|
||||
//! use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
//! use vulkano::command_buffer::CommandBufferUsage;
|
||||
//! use vulkano::command_buffer::PrimaryCommandBufferAbstract;
|
||||
//! use vulkano::command_buffer::SubpassContents;
|
||||
//! use vulkano::command_buffer::{
|
||||
//! AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
|
||||
//! SubpassContents,
|
||||
//! };
|
||||
//!
|
||||
//! # use vulkano::{buffer::BufferContents, pipeline::graphics::vertex_input::Vertex};
|
||||
//!
|
||||
//! # #[derive(BufferContents, Vertex)]
|
||||
//! # #[repr(C)]
|
||||
//! # struct PosVertex {
|
||||
//! # #[format(R32G32B32_SFLOAT)]
|
||||
//! # position: [f32; 3]
|
||||
//! # };
|
||||
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
//! # let queue: std::sync::Arc<vulkano::device::Queue> = return;
|
||||
//! # let vertex_buffer: vulkano::buffer::Subbuffer<[PosVertex]> = return;
|
||||
//! # let vertex_buffer: vulkano::buffer::Subbuffer<[u32]> = return;
|
||||
//! # let render_pass_begin_info: vulkano::command_buffer::RenderPassBeginInfo = return;
|
||||
//! # let graphics_pipeline: std::sync::Arc<vulkano::pipeline::graphics::GraphicsPipeline> = return;
|
||||
//! # let command_buffer_allocator: vulkano::command_buffer::allocator::StandardCommandBufferAllocator = return;
|
||||
//! # let command_buffer_allocator: std::sync::Arc<vulkano::command_buffer::allocator::StandardCommandBufferAllocator> = return;
|
||||
//! #
|
||||
//! let cb = AutoCommandBufferBuilder::primary(
|
||||
//! &command_buffer_allocator,
|
||||
//! command_buffer_allocator.clone(),
|
||||
//! queue.queue_family_index(),
|
||||
//! CommandBufferUsage::MultipleSubmit
|
||||
//! ).unwrap()
|
||||
//! .begin_render_pass(render_pass_begin_info, Default::default()).unwrap()
|
||||
//! .bind_pipeline_graphics(graphics_pipeline.clone()).unwrap()
|
||||
//! .bind_vertex_buffers(0, vertex_buffer.clone()).unwrap()
|
||||
//! .draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap()
|
||||
//! .end_render_pass(Default::default()).unwrap()
|
||||
//! .build().unwrap();
|
||||
//! CommandBufferUsage::MultipleSubmit,
|
||||
//! )
|
||||
//! .unwrap()
|
||||
//! .begin_render_pass(render_pass_begin_info, Default::default())
|
||||
//! .unwrap()
|
||||
//! .bind_pipeline_graphics(graphics_pipeline.clone())
|
||||
//! .unwrap()
|
||||
//! .bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
//! .unwrap()
|
||||
//! .draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
//! .unwrap()
|
||||
//! .end_render_pass(Default::default())
|
||||
//! .unwrap()
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! let _future = cb.execute(queue.clone());
|
||||
//! let future = cb.execute(queue.clone());
|
||||
//! ```
|
||||
//!
|
||||
//! [`StandardCommandBufferAllocator`]: self::allocator::StandardCommandBufferAllocator
|
||||
|
@ -1,8 +1,5 @@
|
||||
use super::{
|
||||
allocator::{
|
||||
CommandBufferAlloc, CommandBufferAllocator, CommandBufferBuilderAlloc,
|
||||
StandardCommandBufferAllocator,
|
||||
},
|
||||
allocator::{CommandBufferAlloc, CommandBufferAllocator},
|
||||
CommandBufferInheritanceInfo, CommandBufferLevel, CommandBufferUsage,
|
||||
};
|
||||
use crate::{
|
||||
@ -12,10 +9,10 @@ use crate::{
|
||||
},
|
||||
device::{Device, DeviceOwned, QueueFamilyProperties},
|
||||
query::QueryControlFlags,
|
||||
ValidationError, VulkanError, VulkanObject,
|
||||
Validated, ValidationError, VulkanError, VulkanObject,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{fmt::Debug, ptr, sync::Arc};
|
||||
use std::{fmt::Debug, mem::ManuallyDrop, ptr, sync::Arc};
|
||||
|
||||
/// Command buffer being built.
|
||||
///
|
||||
@ -24,22 +21,16 @@ use std::{fmt::Debug, ptr, sync::Arc};
|
||||
/// - All submitted commands must be valid and follow the requirements of the Vulkan specification.
|
||||
/// - Any resources used by submitted commands must outlive the returned builder and its created
|
||||
/// command buffer. They must be protected against data races through manual synchronization.
|
||||
pub struct UnsafeCommandBufferBuilder<A = StandardCommandBufferAllocator>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
builder_alloc: A::Builder,
|
||||
|
||||
pub struct UnsafeCommandBufferBuilder {
|
||||
allocation: ManuallyDrop<CommandBufferAlloc>,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
// Must be `None` in a primary command buffer and `Some` in a secondary command buffer.
|
||||
inheritance_info: Option<CommandBufferInheritanceInfo>,
|
||||
pub(super) usage: CommandBufferUsage,
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl UnsafeCommandBufferBuilder {
|
||||
/// Creates a new builder, for recording commands.
|
||||
///
|
||||
/// # Safety
|
||||
@ -47,15 +38,12 @@ where
|
||||
/// - `begin_info` must be valid.
|
||||
#[inline]
|
||||
pub unsafe fn new(
|
||||
allocator: &A,
|
||||
allocator: Arc<dyn CommandBufferAllocator>,
|
||||
queue_family_index: u32,
|
||||
level: CommandBufferLevel,
|
||||
begin_info: CommandBufferBeginInfo,
|
||||
) -> Result<Self, VulkanError> {
|
||||
let builder_alloc = allocator
|
||||
.allocate(queue_family_index, level, 1)?
|
||||
.next()
|
||||
.expect("requested one command buffer from the command pool, but got zero");
|
||||
) -> Result<Self, Validated<VulkanError>> {
|
||||
let allocation = allocator.allocate(queue_family_index, level)?;
|
||||
|
||||
let CommandBufferBeginInfo {
|
||||
usage,
|
||||
@ -161,14 +149,15 @@ where
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let fns = builder_alloc.device().fns();
|
||||
(fns.v1_0.begin_command_buffer)(builder_alloc.inner().handle(), &begin_info_vk)
|
||||
let fns = allocation.inner.device().fns();
|
||||
(fns.v1_0.begin_command_buffer)(allocation.inner.handle(), &begin_info_vk)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
}
|
||||
|
||||
Ok(UnsafeCommandBufferBuilder {
|
||||
builder_alloc,
|
||||
allocation: ManuallyDrop::new(allocation),
|
||||
allocator,
|
||||
inheritance_info,
|
||||
queue_family_index,
|
||||
usage,
|
||||
@ -177,20 +166,15 @@ where
|
||||
|
||||
/// Turns the builder into an actual command buffer.
|
||||
#[inline]
|
||||
pub fn build(self) -> Result<UnsafeCommandBuffer<A>, VulkanError> {
|
||||
pub fn build(self) -> Result<UnsafeCommandBuffer, VulkanError> {
|
||||
unsafe {
|
||||
let fns = self.device().fns();
|
||||
(fns.v1_0.end_command_buffer)(self.handle())
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(UnsafeCommandBuffer {
|
||||
alloc: self.builder_alloc.into_alloc(),
|
||||
inheritance_info: self.inheritance_info,
|
||||
queue_family_index: self.queue_family_index,
|
||||
usage: self.usage,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(UnsafeCommandBuffer { inner: self })
|
||||
}
|
||||
|
||||
/// Returns the queue family index that this command buffer was created for.
|
||||
@ -202,7 +186,7 @@ where
|
||||
/// Returns the level of the command buffer.
|
||||
#[inline]
|
||||
pub fn level(&self) -> CommandBufferLevel {
|
||||
self.builder_alloc.inner().level()
|
||||
self.allocation.inner.level()
|
||||
}
|
||||
|
||||
/// Returns the usage that the command buffer was created with.
|
||||
@ -222,32 +206,31 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> VulkanObject for UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl Drop for UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
let allocation = unsafe { ManuallyDrop::take(&mut self.allocation) };
|
||||
unsafe { self.allocator.deallocate(allocation) };
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl VulkanObject for UnsafeCommandBufferBuilder {
|
||||
type Handle = ash::vk::CommandBuffer;
|
||||
|
||||
#[inline]
|
||||
fn handle(&self) -> Self::Handle {
|
||||
self.builder_alloc.inner().handle()
|
||||
self.allocation.inner.handle()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl DeviceOwned for UnsafeCommandBufferBuilder {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.builder_alloc.device()
|
||||
self.allocation.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Debug for UnsafeCommandBufferBuilder<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
impl Debug for UnsafeCommandBufferBuilder {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("UnsafeCommandBufferBuilder")
|
||||
.field("handle", &self.level())
|
||||
@ -314,65 +297,57 @@ impl CommandBufferBeginInfo {
|
||||
/// The command buffer must not outlive the command pool that it was created from,
|
||||
/// nor the resources used by the recorded commands.
|
||||
#[derive(Debug)]
|
||||
pub struct UnsafeCommandBuffer<A = StandardCommandBufferAllocator>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
alloc: A::Alloc,
|
||||
|
||||
queue_family_index: u32,
|
||||
// Must be `None` in a primary command buffer and `Some` in a secondary command buffer.
|
||||
inheritance_info: Option<CommandBufferInheritanceInfo>,
|
||||
usage: CommandBufferUsage,
|
||||
pub struct UnsafeCommandBuffer {
|
||||
inner: UnsafeCommandBufferBuilder,
|
||||
}
|
||||
|
||||
impl<A> UnsafeCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
// `UnsafeCommandBufferBuilder` is `!Send + !Sync` so that the implementation of
|
||||
// `CommandBufferAllocator::allocate` can assume that a command buffer in the recording state
|
||||
// doesn't leave the thread it was allocated on. However, as the safety contract states,
|
||||
// `CommandBufferAllocator::deallocate` must acccount for the possibility that a command buffer is
|
||||
// moved between threads after the recording is finished, and thus deallocated from another thread.
|
||||
// That's why this is sound.
|
||||
unsafe impl Send for UnsafeCommandBuffer {}
|
||||
unsafe impl Sync for UnsafeCommandBuffer {}
|
||||
|
||||
impl UnsafeCommandBuffer {
|
||||
/// Returns the queue family index that this command buffer was created for.
|
||||
#[inline]
|
||||
pub fn queue_family_index(&self) -> u32 {
|
||||
self.queue_family_index
|
||||
self.inner.queue_family_index
|
||||
}
|
||||
|
||||
/// Returns the level of the command buffer.
|
||||
#[inline]
|
||||
pub fn level(&self) -> CommandBufferLevel {
|
||||
self.alloc.inner().level()
|
||||
self.inner.allocation.inner.level()
|
||||
}
|
||||
|
||||
/// Returns the usage that the command buffer was created with.
|
||||
#[inline]
|
||||
pub fn usage(&self) -> CommandBufferUsage {
|
||||
self.usage
|
||||
self.inner.usage
|
||||
}
|
||||
|
||||
/// Returns the inheritance info of the command buffer, if it is a secondary command buffer.
|
||||
#[inline]
|
||||
pub fn inheritance_info(&self) -> Option<&CommandBufferInheritanceInfo> {
|
||||
self.inheritance_info.as_ref()
|
||||
self.inner.inheritance_info.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> VulkanObject for UnsafeCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl VulkanObject for UnsafeCommandBuffer {
|
||||
type Handle = ash::vk::CommandBuffer;
|
||||
|
||||
#[inline]
|
||||
fn handle(&self) -> Self::Handle {
|
||||
self.alloc.inner().handle()
|
||||
self.inner.allocation.inner.handle()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for UnsafeCommandBuffer<A>
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
unsafe impl DeviceOwned for UnsafeCommandBuffer {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.alloc.device()
|
||||
self.inner.allocation.inner.device()
|
||||
}
|
||||
}
|
||||
|
@ -552,9 +552,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
@ -696,9 +699,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cb_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
let cb_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
&cb_allocator,
|
||||
cb_allocator,
|
||||
queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user