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:
marc0246 2023-11-14 17:57:43 +01:00 committed by GitHub
parent 4d56fc38de
commit 43e2db0dbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 836 additions and 947 deletions

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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,
)

View File

@ -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 {

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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 {

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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 {

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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();

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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()

View File

@ -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,
/// )

View File

@ -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();
}
}

View File

@ -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()
}

View File

@ -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,
)

View File

@ -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>],

View File

@ -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,

View File

@ -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>,

View File

@ -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(&copy_buffer_info);
},
);
@ -206,7 +203,7 @@ where
]
})
.collect(),
move |out: &mut UnsafeCommandBufferBuilder<A>| {
move |out: &mut UnsafeCommandBufferBuilder| {
out.copy_image_unchecked(&copy_image_info);
},
);
@ -293,7 +290,7 @@ where
]
})
.collect(),
move |out: &mut UnsafeCommandBufferBuilder<A>| {
move |out: &mut UnsafeCommandBufferBuilder| {
out.copy_buffer_to_image_unchecked(&copy_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(&copy_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,

View File

@ -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,

View File

@ -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],

View File

@ -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]>,

View File

@ -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,

View File

@ -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],

View File

@ -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>],

View File

@ -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,

View File

@ -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

View File

@ -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()
}
}

View File

@ -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,
)