mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-19 18:42:31 +00:00
Simplify handling of command buffer usage flags (#1563)
This commit is contained in:
parent
a83f0fe489
commit
0c1e0ff40d
@ -3,9 +3,12 @@
|
||||
Please add new changes at the bottom, preceded by a hyphen -.
|
||||
Breaking changes should be listed first, before other changes, and should be preceded by - **Breaking**.
|
||||
-->
|
||||
- **Breaking** `AutoCommandBuffer` and the `CommandBuffer` trait have been split in two, one for primary and the other for secondary command buffers. `AutoCommandBufferBuilder` remains one type, but has a type parameter for the level of command buffer it will be create, and some of its methods are only implemented for builders that create `PrimaryAutoCommandBuffer`.
|
||||
- **Breaking** `Kind` has been renamed to `CommandBufferLevel`, and for secondary command buffers it now contains a single `CommandBufferInheritance` value.
|
||||
- **Breaking** `CommandBufferInheritance::occlusion_query` and `UnsafeCommandBufferBuilder::begin_query` now take `QueryControlFlags` instead of a boolean.
|
||||
- **Breaking** Changes to command buffers:
|
||||
- `AutoCommandBuffer` and the `CommandBuffer` trait have been split in two, one for primary and the other for secondary command buffers. `AutoCommandBufferBuilder` remains one type, but has a type parameter for the level of command buffer it will be creating, and some of its methods are only implemented for builders that create `PrimaryAutoCommandBuffer`.
|
||||
- The `Flags` enum is renamed to `CommandBufferUsage`, and is exported from the main `command_buffer` module. The `None` variant is renamed to `MultipleSubmit`.
|
||||
- Simplified the number of constructors on `AutoCommandBufferBuilder` by adding a `CommandBufferUsage` parameter.
|
||||
- `Kind` has been renamed to `CommandBufferLevel`, and for secondary command buffers it now contains a single `CommandBufferInheritance` value.
|
||||
- `CommandBufferInheritance::occlusion_query` and `UnsafeCommandBufferBuilder::begin_query` now take `QueryControlFlags` instead of a boolean.
|
||||
- **Breaking** The non-default constructors of `ImageView` have been replaced with a builder, created with `ImageView::start(image)`.
|
||||
- **Breaking** Added support for component mapping/swizzling on image views.
|
||||
- `image::Swizzle` is moved and renamed to `image::view::ComponentMapping`. It now has an `is_identity` method.
|
||||
|
@ -13,8 +13,9 @@
|
||||
// been more or more used for general-purpose operations as well. This is called "General-Purpose
|
||||
// GPU", or *GPGPU*. This is what this example demonstrates.
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -23,8 +24,6 @@ use vulkano::pipeline::ComputePipeline;
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::GpuFuture;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
const DEVICE_EXTENSIONS: DeviceExtensions = DeviceExtensions {
|
||||
khr_storage_buffer_storage_class: true,
|
||||
..DeviceExtensions::none()
|
||||
@ -135,8 +134,12 @@ fn main() {
|
||||
);
|
||||
|
||||
// In order to execute our operation, we have to build a command buffer.
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
// The command buffer only does one thing: execute the compute pipeline.
|
||||
// This is called a *dispatch* operation.
|
||||
|
@ -19,8 +19,12 @@
|
||||
// See: https://github.com/vulkano-rs/vulkano/issues/1221
|
||||
// Finally, I have not profiled CpuBufferPool against CpuAccessibleBuffer
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use vulkano::buffer::CpuBufferPool;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::image::view::ImageView;
|
||||
use vulkano::image::{ImageUsage, SwapchainImage};
|
||||
@ -35,15 +39,11 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
struct Vertex {
|
||||
position: [f32; 2],
|
||||
@ -274,9 +274,10 @@ fn main() {
|
||||
|
||||
// Allocate a new chunk from buffer_pool
|
||||
let buffer = buffer_pool.chunk(data.to_vec()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary_one_time_submit(
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
use vulkano::buffer::BufferUsage;
|
||||
use vulkano::buffer::CpuAccessibleBuffer;
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::DynamicState;
|
||||
use vulkano::command_buffer::SecondaryAutoCommandBuffer;
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
@ -142,6 +142,7 @@ impl AmbientLightingSystem {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_graphics(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
self.pipeline.subpass().clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -10,9 +10,9 @@
|
||||
use cgmath::Vector3;
|
||||
use vulkano::buffer::BufferUsage;
|
||||
use vulkano::buffer::CpuAccessibleBuffer;
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::DynamicState;
|
||||
use vulkano::command_buffer::SecondaryAutoCommandBuffer;
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
@ -156,6 +156,7 @@ impl DirectionalLightingSystem {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_graphics(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
self.pipeline.subpass().clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -11,9 +11,9 @@ use cgmath::Matrix4;
|
||||
use cgmath::Vector3;
|
||||
use vulkano::buffer::BufferUsage;
|
||||
use vulkano::buffer::CpuAccessibleBuffer;
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::DynamicState;
|
||||
use vulkano::command_buffer::SecondaryAutoCommandBuffer;
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
@ -171,6 +171,7 @@ impl PointLightingSystem {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_graphics(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
self.pipeline.subpass().clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -14,10 +14,10 @@ use cgmath::Matrix4;
|
||||
use cgmath::SquareMatrix;
|
||||
use cgmath::Vector3;
|
||||
use std::sync::Arc;
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::PrimaryAutoCommandBuffer;
|
||||
use vulkano::command_buffer::SecondaryCommandBuffer;
|
||||
use vulkano::command_buffer::SubpassContents;
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, SecondaryCommandBuffer,
|
||||
SubpassContents,
|
||||
};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::format::Format;
|
||||
use vulkano::image::view::ImageView;
|
||||
@ -299,9 +299,10 @@ impl FrameSystem {
|
||||
);
|
||||
|
||||
// Start the command buffer builder that will be filled throughout the frame handling.
|
||||
let mut command_buffer_builder = AutoCommandBufferBuilder::primary_one_time_submit(
|
||||
let mut command_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
command_buffer_builder
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
use vulkano::buffer::BufferUsage;
|
||||
use vulkano::buffer::CpuAccessibleBuffer;
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::DynamicState;
|
||||
use vulkano::command_buffer::SecondaryAutoCommandBuffer;
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::pipeline::viewport::Viewport;
|
||||
use vulkano::pipeline::GraphicsPipeline;
|
||||
@ -83,6 +83,7 @@ impl TriangleDrawSystem {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_graphics(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
self.pipeline.subpass().clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -17,7 +17,7 @@
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::pipeline_layout::{PipelineLayoutDesc, PipelineLayoutDescTweaks};
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
@ -165,8 +165,12 @@ fn main() {
|
||||
);
|
||||
|
||||
// Build the command buffer, using different offsets for each call.
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch(
|
||||
[12, 1, 1],
|
||||
|
@ -19,7 +19,7 @@ use std::io::BufWriter;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -194,8 +194,12 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch(
|
||||
[
|
||||
|
@ -8,7 +8,9 @@
|
||||
// according to those terms.
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::format::Format;
|
||||
@ -28,16 +30,14 @@ use vulkano::swapchain::{
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use png;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use png;
|
||||
use std::io::Cursor;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
// The start of this example is exactly the same as `triangle`. You should read the
|
||||
// `triangle` example if you haven't done so yet.
|
||||
@ -274,9 +274,12 @@ fn main() {
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
// This example demonstrates how to initialize immutable buffers.
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, ImmutableBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -19,8 +20,6 @@ use vulkano::pipeline::ComputePipeline;
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::GpuFuture;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
// The most part of this example is exactly the same as `basic-compute-shader`. You should read the
|
||||
// `basic-compute-shader` example if you haven't done so yet.
|
||||
@ -91,9 +90,12 @@ void main() {
|
||||
};
|
||||
|
||||
// Build command buffer which initialize our buffer.
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Initializing a immutable buffer is done by coping data to
|
||||
// ImmutableBufferInitialization which is returned by a function we use to create buffer.
|
||||
@ -130,8 +132,12 @@ void main() {
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
|
@ -30,9 +30,12 @@ extern crate vulkano_shaders;
|
||||
extern crate vulkano_win;
|
||||
extern crate winit;
|
||||
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuBufferPool};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, DrawIndirectCommand, DynamicState, SubpassContents,
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DrawIndirectCommand, DynamicState,
|
||||
SubpassContents,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
@ -50,15 +53,11 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
|
||||
// # Vertex Types
|
||||
// `Vertex` is the vertex type that will be output from the compute shader and be input to the vertex shader.
|
||||
#[derive(Default, Debug, Clone)]
|
||||
@ -336,9 +335,10 @@ fn main() {
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary_one_time_submit(
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -19,7 +19,9 @@ extern crate vulkano_win;
|
||||
extern crate winit;
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::image::view::ImageView;
|
||||
use vulkano::image::{ImageUsage, SwapchainImage};
|
||||
@ -35,7 +37,6 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
@ -313,9 +314,10 @@ fn main() {
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary_one_time_submit(
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
|
@ -71,7 +71,8 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, DynamicState, PrimaryCommandBuffer, SubpassContents,
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, PrimaryCommandBuffer,
|
||||
SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::format::ClearValue;
|
||||
@ -269,8 +270,12 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffer.clone(),
|
||||
|
@ -16,8 +16,12 @@
|
||||
// and that you want to learn Vulkan. This means that for example it won't go into details about
|
||||
// what a vertex or a shader is.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::image::view::ImageView;
|
||||
use vulkano::image::{ImageUsage, SwapchainImage};
|
||||
@ -33,7 +37,6 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::ElementState;
|
||||
use winit::event::KeyboardInput;
|
||||
@ -41,9 +44,6 @@ use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
// A struct to contain resources related to a window
|
||||
struct WindowSurface {
|
||||
surface: Arc<Surface<Window>>,
|
||||
@ -367,9 +367,12 @@ fn main() {
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
|
@ -13,7 +13,9 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferAccess, BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions, DeviceOwned};
|
||||
use vulkano::format::Format;
|
||||
use vulkano::image::{view::ImageView, AttachmentImage, ImageUsage, SwapchainImage};
|
||||
@ -317,9 +319,12 @@ fn main() {
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into(), 1.0.into()];
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Beginning or resetting a query is unsafe for now.
|
||||
unsafe {
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
// TODO: Give a paragraph about what push constants are and what problems they solve
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -19,8 +20,6 @@ use vulkano::pipeline::ComputePipeline;
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::GpuFuture;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
|
||||
@ -101,8 +100,12 @@ fn main() {
|
||||
// For a graphics pipeline, push constants are passed to the `draw` and `draw_indexed` methods.
|
||||
// Note that there is no type safety for the push constants argument.
|
||||
// So be careful to only pass an instance of the struct generated by the `vulkano_shaders::shaders!` macro.
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch(
|
||||
[1024, 1, 1],
|
||||
|
@ -19,10 +19,17 @@
|
||||
// $ glslangValidator frag.glsl -V -S frag -o frag.spv
|
||||
// Vulkano uses glslangValidator to build your shaders internally.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::sync::Arc;
|
||||
use vulkano as vk;
|
||||
use vulkano::buffer::cpu_access::CpuAccessibleBuffer;
|
||||
use vulkano::buffer::BufferUsage;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::descriptor::descriptor::DescriptorDesc;
|
||||
use vulkano::descriptor::descriptor::ShaderStages;
|
||||
use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc;
|
||||
@ -47,18 +54,11 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct Vertex {
|
||||
pub position: [f32; 2],
|
||||
@ -517,8 +517,12 @@ fn main() {
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 0.0, 1.0].into()];
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
|
@ -11,8 +11,9 @@
|
||||
// shader source code. The boilerplate is taken from the "basic-compute-shader.rs" example, where
|
||||
// most of the boilerplate is explained.
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -21,8 +22,6 @@ use vulkano::pipeline::ComputePipeline;
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::GpuFuture;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
|
||||
@ -91,8 +90,12 @@ fn main() {
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.unwrap();
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
// TODO: Give a paragraph about what specialization are and what problems they solve
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
@ -19,8 +20,6 @@ use vulkano::pipeline::ComputePipeline;
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::GpuFuture;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
|
||||
@ -99,8 +98,12 @@ fn main() {
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.unwrap();
|
||||
|
@ -7,9 +7,16 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3};
|
||||
use examples::{Normal, Vertex, INDICES, NORMALS, VERTICES};
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use vulkano::buffer::cpu_pool::CpuBufferPool;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::format::Format;
|
||||
@ -29,20 +36,11 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3};
|
||||
|
||||
use examples::{Normal, Vertex, INDICES, NORMALS, VERTICES};
|
||||
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
// The start of this example is exactly the same as `triangle`. You should read the
|
||||
// `triangle` example if you haven't done so yet.
|
||||
@ -248,9 +246,10 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary_one_time_submit(
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
|
@ -18,8 +18,11 @@
|
||||
// * tessellation control shader and a tessellation evaluation shader
|
||||
// * tessellation_shaders(..), patch_list(3) and polygon_mode_line() are called on the pipeline builder
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::image::view::ImageView;
|
||||
use vulkano::image::{ImageUsage, SwapchainImage};
|
||||
@ -34,14 +37,11 @@ use vulkano::swapchain::{
|
||||
};
|
||||
use vulkano::sync;
|
||||
use vulkano::sync::{FlushError, GpuFuture};
|
||||
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
mod vs {
|
||||
vulkano_shaders::shader! {
|
||||
ty: "vertex",
|
||||
@ -346,9 +346,12 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
|
@ -17,7 +17,9 @@
|
||||
// what a vertex or a shader is.
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState, SubpassContents};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
|
||||
};
|
||||
use vulkano::device::{Device, DeviceExtensions};
|
||||
use vulkano::image::view::ImageView;
|
||||
use vulkano::image::{ImageUsage, SwapchainImage};
|
||||
@ -448,9 +450,10 @@ fn main() {
|
||||
//
|
||||
// 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_one_time_submit(
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -7,19 +7,6 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::cmp;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::MutexGuard;
|
||||
|
||||
use crate::buffer::sys::BufferCreationError;
|
||||
use crate::buffer::sys::SparseLevel;
|
||||
use crate::buffer::sys::UnsafeBuffer;
|
||||
@ -42,6 +29,18 @@ use crate::memory::DedicatedAlloc;
|
||||
use crate::memory::DeviceMemoryAllocError;
|
||||
use crate::sync::AccessError;
|
||||
use crate::sync::Sharing;
|
||||
use std::cmp;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::MutexGuard;
|
||||
|
||||
use crate::OomError;
|
||||
|
||||
@ -73,6 +72,7 @@ use crate::OomError;
|
||||
/// ```
|
||||
/// use vulkano::buffer::CpuBufferPool;
|
||||
/// use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
/// use vulkano::command_buffer::CommandBufferUsage;
|
||||
/// use vulkano::command_buffer::PrimaryCommandBuffer;
|
||||
/// use vulkano::sync::GpuFuture;
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
@ -87,7 +87,7 @@ use crate::OomError;
|
||||
/// let sub_buffer = buffer.next(data).unwrap();
|
||||
///
|
||||
/// // You can then use `sub_buffer` as if it was an entirely separate buffer.
|
||||
/// AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
/// AutoCommandBufferBuilder::primary(device.clone(), queue.family(), CommandBufferUsage::OneTimeSubmit)
|
||||
/// .unwrap()
|
||||
/// // For the sake of the example we just call `update_buffer` on the buffer, even though
|
||||
/// // it is pointless to do that.
|
||||
|
@ -28,6 +28,7 @@ use crate::buffer::BufferUsage;
|
||||
use crate::buffer::CpuAccessibleBuffer;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferExecFuture;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::PrimaryAutoCommandBuffer;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use crate::device::Device;
|
||||
@ -136,7 +137,11 @@ impl<T: ?Sized> ImmutableBuffer<T> {
|
||||
source.device().active_queue_families(),
|
||||
)?;
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(source.device().clone(), queue.family())?;
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
source.device().clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)?;
|
||||
cbb.copy_buffer(source, init).unwrap(); // TODO: return error?
|
||||
let cb = cbb.build().unwrap(); // TODO: return OomError
|
||||
|
||||
@ -534,6 +539,7 @@ mod tests {
|
||||
use crate::buffer::immutable::ImmutableBuffer;
|
||||
use crate::buffer::BufferUsage;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use crate::sync::GpuFuture;
|
||||
|
||||
@ -547,7 +553,12 @@ mod tests {
|
||||
let destination =
|
||||
CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), false, 0).unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, destination.clone()).unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
@ -580,7 +591,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, destination.clone()).unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
@ -605,7 +621,12 @@ mod tests {
|
||||
|
||||
assert_should_panic!({
|
||||
// TODO: check Result error instead of panicking
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.fill_buffer(buffer, 50).unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
@ -630,7 +651,12 @@ mod tests {
|
||||
|
||||
assert_should_panic!({
|
||||
// TODO: check Result error instead of panicking
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(source, buffer).unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
@ -653,7 +679,12 @@ mod tests {
|
||||
let source =
|
||||
CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), false, 0).unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(source.clone(), init)
|
||||
.unwrap()
|
||||
.copy_buffer(buffer, source.clone())
|
||||
@ -679,11 +710,21 @@ mod tests {
|
||||
let source =
|
||||
CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), false, 0).unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(source.clone(), init).unwrap();
|
||||
let cb1 = cbb.build().unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, source.clone()).unwrap();
|
||||
let cb2 = cbb.build().unwrap();
|
||||
|
||||
|
@ -16,7 +16,6 @@ use crate::command_buffer::pool::CommandPoolBuilderAlloc;
|
||||
use crate::command_buffer::synced::SyncCommandBuffer;
|
||||
use crate::command_buffer::synced::SyncCommandBufferBuilder;
|
||||
use crate::command_buffer::synced::SyncCommandBufferBuilderError;
|
||||
use crate::command_buffer::sys::Flags;
|
||||
use crate::command_buffer::sys::UnsafeCommandBuffer;
|
||||
use crate::command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
|
||||
use crate::command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
|
||||
@ -27,6 +26,7 @@ use crate::command_buffer::CommandBufferExecError;
|
||||
use crate::command_buffer::CommandBufferInheritance;
|
||||
use crate::command_buffer::CommandBufferInheritanceRenderPass;
|
||||
use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::DispatchIndirectCommand;
|
||||
use crate::command_buffer::DrawIndexedIndirectCommand;
|
||||
use crate::command_buffer::DrawIndirectCommand;
|
||||
@ -103,8 +103,8 @@ pub struct AutoCommandBufferBuilder<L, P = StandardCommandPoolBuilder> {
|
||||
// The inheritance for secondary command buffers.
|
||||
inheritance: Option<CommandBufferInheritance<Box<dyn FramebufferAbstract + Send + Sync>>>,
|
||||
|
||||
// Flags passed when creating the command buffer.
|
||||
flags: Flags,
|
||||
// Usage flags passed when creating the command buffer.
|
||||
usage: CommandBufferUsage,
|
||||
|
||||
// If we're inside a render pass, contains the render pass state.
|
||||
render_pass_state: Option<RenderPassState>,
|
||||
@ -132,132 +132,38 @@ struct QueryState {
|
||||
}
|
||||
|
||||
impl AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder> {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Starts building a primary command buffer.
|
||||
///
|
||||
/// The final command buffer can only be executed once at a time. In other words, it is as if
|
||||
/// executing the command buffer modifies it.
|
||||
#[inline]
|
||||
pub fn primary(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
AutoCommandBufferBuilder::with_flags(
|
||||
AutoCommandBufferBuilder::with_level(
|
||||
device,
|
||||
queue_family,
|
||||
usage,
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Starts building a primary command buffer.
|
||||
///
|
||||
/// Contrary to `primary`, the final command buffer can only be submitted once before being
|
||||
/// destroyed. This makes it possible for the implementation to perform additional
|
||||
/// optimizations.
|
||||
#[inline]
|
||||
pub fn primary_one_time_submit(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::OneTimeSubmit,
|
||||
)
|
||||
}
|
||||
|
||||
/// Starts building a primary command buffer.
|
||||
///
|
||||
/// Contrary to `primary`, the final command buffer can be executed multiple times in parallel
|
||||
/// in multiple different queues.
|
||||
#[inline]
|
||||
pub fn primary_simultaneous_use(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::SimultaneousUse,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder> {
|
||||
/// Starts building a secondary compute command buffer.
|
||||
///
|
||||
/// The final command buffer can only be executed once at a time. In other words, it is as if
|
||||
/// executing the command buffer modifies it.
|
||||
#[inline]
|
||||
pub fn secondary_compute(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
let level = CommandBufferLevel::secondary(None, QueryPipelineStatisticFlags::none());
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::None)
|
||||
}
|
||||
|
||||
/// Starts building a secondary compute command buffer.
|
||||
///
|
||||
/// Contrary to `secondary_compute`, the final command buffer can only be submitted once before
|
||||
/// being destroyed. This makes it possible for the implementation to perform additional
|
||||
/// optimizations.
|
||||
#[inline]
|
||||
pub fn secondary_compute_one_time_submit(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
let level = CommandBufferLevel::secondary(None, QueryPipelineStatisticFlags::none());
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::OneTimeSubmit)
|
||||
}
|
||||
|
||||
/// Starts building a secondary compute command buffer.
|
||||
///
|
||||
/// Contrary to `secondary_compute`, the final command buffer can be executed multiple times in
|
||||
/// parallel in multiple different queues.
|
||||
#[inline]
|
||||
pub fn secondary_compute_simultaneous_use(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
let level = CommandBufferLevel::secondary(None, QueryPipelineStatisticFlags::none());
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::SimultaneousUse)
|
||||
AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
|
||||
}
|
||||
|
||||
/// Same as `secondary_compute`, but allows specifying how queries are being inherited.
|
||||
@ -265,6 +171,7 @@ impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBui
|
||||
pub fn secondary_compute_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
) -> Result<
|
||||
@ -282,82 +189,20 @@ impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBui
|
||||
}
|
||||
|
||||
let level = CommandBufferLevel::secondary(occlusion_query, query_statistics_flags);
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
Ok(AutoCommandBufferBuilder::with_level(
|
||||
device,
|
||||
queue_family,
|
||||
usage,
|
||||
level,
|
||||
Flags::None,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Same as `secondary_compute_one_time_submit`, but allows specifying how queries are being inherited.
|
||||
#[inline]
|
||||
pub fn secondary_compute_one_time_submit_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
BeginError,
|
||||
> {
|
||||
if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
|
||||
return Err(BeginError::InheritedQueriesFeatureNotEnabled);
|
||||
}
|
||||
|
||||
if query_statistics_flags.count() > 0
|
||||
&& !device.enabled_features().pipeline_statistics_query
|
||||
{
|
||||
return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
|
||||
}
|
||||
|
||||
let level = CommandBufferLevel::secondary(occlusion_query, query_statistics_flags);
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
level,
|
||||
Flags::OneTimeSubmit,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Same as `secondary_compute_simultaneous_use`, but allows specifying how queries are being inherited.
|
||||
#[inline]
|
||||
pub fn secondary_compute_simultaneous_use_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
BeginError,
|
||||
> {
|
||||
if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
|
||||
return Err(BeginError::InheritedQueriesFeatureNotEnabled);
|
||||
}
|
||||
|
||||
if query_statistics_flags.count() > 0
|
||||
&& !device.enabled_features().pipeline_statistics_query
|
||||
{
|
||||
return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
|
||||
}
|
||||
|
||||
let level = CommandBufferLevel::secondary(occlusion_query, query_statistics_flags);
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
level,
|
||||
Flags::SimultaneousUse,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Starts building a secondary graphics command buffer.
|
||||
///
|
||||
/// The final command buffer can only be executed once at a time. In other words, it is as if
|
||||
/// executing the command buffer modifies it.
|
||||
#[inline]
|
||||
pub fn secondary_graphics(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
subpass: Subpass,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
@ -372,58 +217,7 @@ impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBui
|
||||
query_statistics_flags: QueryPipelineStatisticFlags::none(),
|
||||
});
|
||||
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::None)
|
||||
}
|
||||
|
||||
/// Starts building a secondary graphics command buffer.
|
||||
///
|
||||
/// Contrary to `secondary_graphics`, the final command buffer can only be submitted once
|
||||
/// before being destroyed. This makes it possible for the implementation to perform additional
|
||||
/// optimizations.
|
||||
#[inline]
|
||||
pub fn secondary_graphics_one_time_submit<R>(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
subpass: Subpass,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
|
||||
render_pass: Some(CommandBufferInheritanceRenderPass {
|
||||
subpass,
|
||||
framebuffer: None::<Arc<Framebuffer<()>>>,
|
||||
}),
|
||||
occlusion_query: None,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags::none(),
|
||||
});
|
||||
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::OneTimeSubmit)
|
||||
}
|
||||
|
||||
/// Starts building a secondary graphics command buffer.
|
||||
///
|
||||
/// Contrary to `secondary_graphics`, the final command buffer can be executed multiple times
|
||||
/// in parallel in multiple different queues.
|
||||
#[inline]
|
||||
pub fn secondary_graphics_simultaneous_use<R>(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
subpass: Subpass,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
OomError,
|
||||
> {
|
||||
let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
|
||||
render_pass: Some(CommandBufferInheritanceRenderPass {
|
||||
subpass,
|
||||
framebuffer: None::<Arc<Framebuffer<()>>>,
|
||||
}),
|
||||
occlusion_query: None,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags::none(),
|
||||
});
|
||||
|
||||
AutoCommandBufferBuilder::with_flags(device, queue_family, level, Flags::SimultaneousUse)
|
||||
AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
|
||||
}
|
||||
|
||||
/// Same as `secondary_graphics`, but allows specifying how queries are being inherited.
|
||||
@ -431,6 +225,7 @@ impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBui
|
||||
pub fn secondary_graphics_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
subpass: Subpass,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
@ -457,100 +252,22 @@ impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBui
|
||||
query_statistics_flags,
|
||||
});
|
||||
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
Ok(AutoCommandBufferBuilder::with_level(
|
||||
device,
|
||||
queue_family,
|
||||
usage,
|
||||
level,
|
||||
Flags::None,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Same as `secondary_graphics_one_time_submit`, but allows specifying how queries are being inherited.
|
||||
#[inline]
|
||||
pub fn secondary_graphics_one_time_submit_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
subpass: Subpass,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
BeginError,
|
||||
> {
|
||||
if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
|
||||
return Err(BeginError::InheritedQueriesFeatureNotEnabled);
|
||||
}
|
||||
|
||||
if query_statistics_flags.count() > 0
|
||||
&& !device.enabled_features().pipeline_statistics_query
|
||||
{
|
||||
return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
|
||||
}
|
||||
|
||||
let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
|
||||
render_pass: Some(CommandBufferInheritanceRenderPass {
|
||||
subpass,
|
||||
framebuffer: None::<Arc<Framebuffer<()>>>,
|
||||
}),
|
||||
occlusion_query,
|
||||
query_statistics_flags,
|
||||
});
|
||||
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
level,
|
||||
Flags::OneTimeSubmit,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Same as `secondary_graphics_simultaneous_use`, but allows specifying how queries are being inherited.
|
||||
#[inline]
|
||||
pub fn secondary_graphics_simultaneous_use_inherit_queries(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
subpass: Subpass,
|
||||
occlusion_query: Option<QueryControlFlags>,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
) -> Result<
|
||||
AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
|
||||
BeginError,
|
||||
> {
|
||||
if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
|
||||
return Err(BeginError::InheritedQueriesFeatureNotEnabled);
|
||||
}
|
||||
|
||||
if query_statistics_flags.count() > 0
|
||||
&& !device.enabled_features().pipeline_statistics_query
|
||||
{
|
||||
return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
|
||||
}
|
||||
|
||||
let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
|
||||
render_pass: Some(CommandBufferInheritanceRenderPass {
|
||||
subpass,
|
||||
framebuffer: None::<Arc<Framebuffer<()>>>,
|
||||
}),
|
||||
occlusion_query,
|
||||
query_statistics_flags,
|
||||
});
|
||||
|
||||
Ok(AutoCommandBufferBuilder::with_flags(
|
||||
device,
|
||||
queue_family,
|
||||
level,
|
||||
Flags::SimultaneousUse,
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
|
||||
// Actual constructor. Private.
|
||||
fn with_flags<F>(
|
||||
fn with_level<F>(
|
||||
device: Arc<Device>,
|
||||
queue_family: QueueFamily,
|
||||
usage: CommandBufferUsage,
|
||||
level: CommandBufferLevel<F>,
|
||||
flags: Flags,
|
||||
) -> Result<AutoCommandBufferBuilder<L, StandardCommandPoolBuilder>, OomError>
|
||||
where
|
||||
F: FramebufferAbstract + Clone + Send + Sync + 'static,
|
||||
@ -597,7 +314,7 @@ impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
|
||||
.alloc(!matches!(level, CommandBufferLevel::Primary), 1)?
|
||||
.next()
|
||||
.expect("Requested one command buffer from the command pool, but got zero.");
|
||||
let inner = SyncCommandBufferBuilder::new(pool_builder_alloc.inner(), level, flags)?;
|
||||
let inner = SyncCommandBufferBuilder::new(pool_builder_alloc.inner(), level, usage)?;
|
||||
|
||||
Ok(AutoCommandBufferBuilder {
|
||||
inner,
|
||||
@ -607,7 +324,7 @@ impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
|
||||
render_pass_state,
|
||||
query_state: FnvHashMap::default(),
|
||||
inheritance,
|
||||
flags,
|
||||
usage,
|
||||
_data: PhantomData,
|
||||
})
|
||||
}
|
||||
@ -677,12 +394,12 @@ where
|
||||
return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
|
||||
}
|
||||
|
||||
let submit_state = match self.flags {
|
||||
Flags::None => SubmitState::ExclusiveUse {
|
||||
let submit_state = match self.usage {
|
||||
CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
|
||||
in_use: AtomicBool::new(false),
|
||||
},
|
||||
Flags::SimultaneousUse => SubmitState::Concurrent,
|
||||
Flags::OneTimeSubmit => SubmitState::OneTime {
|
||||
CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
|
||||
CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
|
||||
already_submitted: AtomicBool::new(false),
|
||||
},
|
||||
};
|
||||
@ -706,12 +423,12 @@ where
|
||||
return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
|
||||
}
|
||||
|
||||
let submit_state = match self.flags {
|
||||
Flags::None => SubmitState::ExclusiveUse {
|
||||
let submit_state = match self.usage {
|
||||
CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
|
||||
in_use: AtomicBool::new(false),
|
||||
},
|
||||
Flags::SimultaneousUse => SubmitState::Concurrent,
|
||||
Flags::OneTimeSubmit => SubmitState::OneTime {
|
||||
CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
|
||||
CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
|
||||
already_submitted: AtomicBool::new(false),
|
||||
},
|
||||
};
|
||||
@ -2127,7 +1844,7 @@ where
|
||||
C: SecondaryCommandBuffer + Send + Sync + 'static,
|
||||
{
|
||||
self.check_command_buffer(&command_buffer)?;
|
||||
let secondary_flags = command_buffer.inner().flags();
|
||||
let secondary_usage = command_buffer.inner().usage();
|
||||
|
||||
unsafe {
|
||||
let mut builder = self.inner.execute_commands();
|
||||
@ -2139,7 +1856,7 @@ where
|
||||
self.state_cacher.invalidate();
|
||||
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as well.
|
||||
self.flags = std::cmp::min(self.flags, secondary_flags);
|
||||
self.usage = std::cmp::min(self.usage, secondary_usage);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
@ -2161,11 +1878,11 @@ where
|
||||
self.check_command_buffer(command_buffer)?;
|
||||
}
|
||||
|
||||
let mut secondary_flags = Flags::SimultaneousUse; // Most permissive flags
|
||||
let mut secondary_usage = CommandBufferUsage::SimultaneousUse; // Most permissive usage
|
||||
unsafe {
|
||||
let mut builder = self.inner.execute_commands();
|
||||
for command_buffer in command_buffers {
|
||||
secondary_flags = std::cmp::min(secondary_flags, command_buffer.inner().flags());
|
||||
secondary_usage = std::cmp::min(secondary_usage, command_buffer.inner().usage());
|
||||
builder.add(command_buffer);
|
||||
}
|
||||
builder.submit()?;
|
||||
@ -2175,7 +1892,7 @@ where
|
||||
self.state_cacher.invalidate();
|
||||
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as well.
|
||||
self.flags = std::cmp::min(self.flags, secondary_flags);
|
||||
self.usage = std::cmp::min(self.usage, secondary_usage);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
@ -3017,6 +2734,7 @@ mod tests {
|
||||
use crate::command_buffer::synced::SyncCommandBufferBuilderError;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferExecError;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::ExecuteCommandsError;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use crate::device::Device;
|
||||
@ -3066,9 +2784,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cbb =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
cbb.copy_buffer_dimensions(source.clone(), 0, destination.clone(), 1, 2)
|
||||
.unwrap();
|
||||
@ -3092,14 +2813,21 @@ mod tests {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
// Make a secondary CB that doesn't support simultaneous use.
|
||||
let builder =
|
||||
AutoCommandBufferBuilder::secondary_compute(device.clone(), queue.family()).unwrap();
|
||||
let builder = AutoCommandBufferBuilder::secondary_compute(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
let secondary = Arc::new(builder.build().unwrap());
|
||||
|
||||
{
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_simultaneous_use(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Add the secondary a first time
|
||||
builder.execute_commands(secondary.clone()).unwrap();
|
||||
@ -3117,15 +2845,21 @@ mod tests {
|
||||
}
|
||||
|
||||
{
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_simultaneous_use(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
builder.execute_commands(secondary.clone()).unwrap();
|
||||
let cb1 = builder.build().unwrap();
|
||||
|
||||
let mut builder =
|
||||
AutoCommandBufferBuilder::primary_simultaneous_use(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Recording the same non-concurrent secondary command buffer into multiple
|
||||
// primaries is an error.
|
||||
|
@ -37,25 +37,28 @@
|
||||
//! # The `AutoCommandBufferBuilder`
|
||||
//!
|
||||
//! The most basic (and recommended) way to create a command buffer is to create a
|
||||
//! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html). Then use the
|
||||
//! [`CommandBufferBuilder` trait](trait.CommandBufferBuilder.html) to add commands to it.
|
||||
//! When you are done adding commands, use
|
||||
//! [the `CommandBufferBuild` trait](trait.CommandBufferBuild.html) to obtain a
|
||||
//! `AutoCommandBuffer`.
|
||||
//! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html), then record commands to it.
|
||||
//! When you are done adding commands, build it to obtain either a `PrimaryAutoCommandBuffer` or
|
||||
//! `SecondAutoCommandBuffer`.
|
||||
//!
|
||||
//! Once built, use [the `CommandBuffer` trait](trait.CommandBuffer.html) to submit the command
|
||||
//! buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait and
|
||||
//! that represents the moment when the execution will end on the GPU.
|
||||
//! Once built, use [the `PrimaryCommandBuffer` trait](trait.PrimaryCommandBuffer.html) to submit the
|
||||
//! command buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait
|
||||
//! and that represents the moment when the execution will end on the GPU.
|
||||
//!
|
||||
//! ```
|
||||
//! use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
//! use vulkano::command_buffer::CommandBufferUsage;
|
||||
//! use vulkano::command_buffer::PrimaryCommandBuffer;
|
||||
//!
|
||||
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
//! # let queue: std::sync::Arc<vulkano::device::Queue> = return;
|
||||
//! let cb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap()
|
||||
//! // TODO: add an actual command to this example
|
||||
//! .build().unwrap();
|
||||
//! let cb = AutoCommandBufferBuilder::primary(
|
||||
//! device.clone(),
|
||||
//! queue.family(),
|
||||
//! CommandBufferUsage::MultipleSubmit
|
||||
//! ).unwrap()
|
||||
//! // TODO: add an actual command to this example
|
||||
//! .build().unwrap();
|
||||
//!
|
||||
//! let _future = cb.execute(queue.clone());
|
||||
//! ```
|
||||
@ -270,3 +273,35 @@ impl CommandBufferLevel<Framebuffer<()>> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Usage flags to pass when creating a command buffer.
|
||||
///
|
||||
/// The safest option is `SimultaneousUse`, but it may be slower than the other two.
|
||||
// NOTE: The ordering is important: the variants are listed from least to most permissive!
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum CommandBufferUsage {
|
||||
/// The command buffer can only be submitted once before being destroyed. Any further submit is
|
||||
/// forbidden. This makes it possible for the implementation to perform additional
|
||||
/// optimizations.
|
||||
OneTimeSubmit,
|
||||
|
||||
/// The command buffer can be used multiple times, but must not execute or record more than once
|
||||
/// simultaneously. In other words, it is as if executing the command buffer borrows it mutably.
|
||||
MultipleSubmit,
|
||||
|
||||
/// The command buffer can be executed multiple times in parallel on different queues.
|
||||
/// If it's a secondary command buffer, it can be recorded to multiple primary command buffers
|
||||
/// at once.
|
||||
SimultaneousUse,
|
||||
}
|
||||
|
||||
impl From<CommandBufferUsage> for vk::CommandBufferUsageFlags {
|
||||
#[inline]
|
||||
fn from(val: CommandBufferUsage) -> Self {
|
||||
match val {
|
||||
CommandBufferUsage::OneTimeSubmit => vk::COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
CommandBufferUsage::MultipleSubmit => 0,
|
||||
CommandBufferUsage::SimultaneousUse => vk::COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,12 @@
|
||||
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::command_buffer::pool::UnsafeCommandPoolAlloc;
|
||||
use crate::command_buffer::sys::Flags;
|
||||
use crate::command_buffer::sys::UnsafeCommandBuffer;
|
||||
use crate::command_buffer::sys::UnsafeCommandBufferBuilder;
|
||||
use crate::command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier;
|
||||
use crate::command_buffer::CommandBufferExecError;
|
||||
use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::device::Queue;
|
||||
@ -426,7 +426,7 @@ impl SyncCommandBufferBuilder {
|
||||
pub unsafe fn new<F>(
|
||||
pool_alloc: &UnsafeCommandPoolAlloc,
|
||||
level: CommandBufferLevel<F>,
|
||||
flags: Flags,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<SyncCommandBufferBuilder, OomError>
|
||||
where
|
||||
F: FramebufferAbstract,
|
||||
@ -438,7 +438,7 @@ impl SyncCommandBufferBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
let cmd = UnsafeCommandBufferBuilder::new(pool_alloc, level, flags)?;
|
||||
let cmd = UnsafeCommandBufferBuilder::new(pool_alloc, level, usage)?;
|
||||
Ok(SyncCommandBufferBuilder::from_unsafe_cmd(
|
||||
cmd,
|
||||
is_secondary,
|
||||
@ -1502,9 +1502,9 @@ mod tests {
|
||||
use crate::buffer::ImmutableBuffer;
|
||||
use crate::command_buffer::pool::CommandPool;
|
||||
use crate::command_buffer::pool::CommandPoolBuilderAlloc;
|
||||
use crate::command_buffer::sys::Flags;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::device::Device;
|
||||
use crate::sync::GpuFuture;
|
||||
use std::sync::Arc;
|
||||
@ -1520,7 +1520,7 @@ mod tests {
|
||||
SyncCommandBufferBuilder::new(
|
||||
&pool_builder_alloc.inner(),
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::None,
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
),
|
||||
Ok(_)
|
||||
));
|
||||
@ -1537,7 +1537,7 @@ mod tests {
|
||||
let mut sync = SyncCommandBufferBuilder::new(
|
||||
&pool_builder_alloc.inner(),
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::None,
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
let buf =
|
||||
@ -1571,9 +1571,10 @@ mod tests {
|
||||
// Two secondary command buffers that both write to the buffer
|
||||
let secondary = (0..2)
|
||||
.map(|_| {
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_compute_simultaneous_use(
|
||||
let mut builder = AutoCommandBufferBuilder::secondary_compute(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
builder.fill_buffer(buf.clone(), 42u32).unwrap();
|
||||
@ -1588,7 +1589,7 @@ mod tests {
|
||||
let mut builder = SyncCommandBufferBuilder::new(
|
||||
allocs[0].inner(),
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::SimultaneousUse,
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -1615,7 +1616,7 @@ mod tests {
|
||||
let mut builder = SyncCommandBufferBuilder::new(
|
||||
allocs[1].inner(),
|
||||
CommandBufferLevel::primary(),
|
||||
Flags::SimultaneousUse,
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -14,6 +14,7 @@ use crate::check_errors;
|
||||
use crate::command_buffer::pool::UnsafeCommandPoolAlloc;
|
||||
use crate::command_buffer::CommandBufferInheritance;
|
||||
use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor::descriptor::ShaderStages;
|
||||
@ -55,23 +56,6 @@ use std::ops::Range;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Flags to pass when creating a command buffer.
|
||||
///
|
||||
/// The safest option is `SimultaneousUse`, but it may be slower than the other two.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Flags {
|
||||
/// The command buffer can only be submitted once. Any further submit is forbidden.
|
||||
OneTimeSubmit,
|
||||
|
||||
/// The command buffer can be used multiple times, but must not execute or record more than once
|
||||
/// simultaneously.
|
||||
None,
|
||||
|
||||
/// The command buffer can be executed multiple times in parallel. If it's a secondary command
|
||||
/// buffer, it can be recorded to multiple primary command buffers at once.
|
||||
SimultaneousUse,
|
||||
}
|
||||
|
||||
/// Command buffer being built.
|
||||
///
|
||||
/// You can add commands to an `UnsafeCommandBufferBuilder` by using the `AddCommand` trait.
|
||||
@ -83,7 +67,7 @@ pub enum Flags {
|
||||
pub struct UnsafeCommandBufferBuilder {
|
||||
command_buffer: vk::CommandBuffer,
|
||||
device: Arc<Device>,
|
||||
flags: Flags,
|
||||
usage: CommandBufferUsage,
|
||||
}
|
||||
|
||||
impl fmt::Debug for UnsafeCommandBufferBuilder {
|
||||
@ -112,7 +96,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
pub unsafe fn new<F>(
|
||||
pool_alloc: &UnsafeCommandPoolAlloc,
|
||||
level: CommandBufferLevel<F>,
|
||||
flags: Flags,
|
||||
usage: CommandBufferUsage,
|
||||
) -> Result<UnsafeCommandBufferBuilder, OomError>
|
||||
where
|
||||
F: FramebufferAbstract,
|
||||
@ -126,12 +110,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
let vk = device.pointers();
|
||||
|
||||
let vk_flags = {
|
||||
let a = match flags {
|
||||
Flags::None => 0,
|
||||
Flags::SimultaneousUse => vk::COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
|
||||
Flags::OneTimeSubmit => vk::COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
};
|
||||
|
||||
let a = vk::CommandBufferUsageFlags::from(usage);
|
||||
let b = match level {
|
||||
CommandBufferLevel::Secondary(ref inheritance)
|
||||
if inheritance.render_pass.is_some() =>
|
||||
@ -211,7 +190,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
Ok(UnsafeCommandBufferBuilder {
|
||||
command_buffer: pool_alloc.internal_object(),
|
||||
device: device.clone(),
|
||||
flags,
|
||||
usage,
|
||||
})
|
||||
}
|
||||
|
||||
@ -225,7 +204,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
Ok(UnsafeCommandBuffer {
|
||||
command_buffer: self.command_buffer,
|
||||
device: self.device.clone(),
|
||||
flags: self.flags,
|
||||
usage: self.usage,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1953,13 +1932,13 @@ impl UnsafeCommandBufferBuilderPipelineBarrier {
|
||||
pub struct UnsafeCommandBuffer {
|
||||
command_buffer: vk::CommandBuffer,
|
||||
device: Arc<Device>,
|
||||
flags: Flags,
|
||||
usage: CommandBufferUsage,
|
||||
}
|
||||
|
||||
impl UnsafeCommandBuffer {
|
||||
#[inline]
|
||||
pub fn flags(&self) -> Flags {
|
||||
self.flags
|
||||
pub fn usage(&self) -> CommandBufferUsage {
|
||||
self.usage
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ use crate::buffer::CpuAccessibleBuffer;
|
||||
use crate::buffer::TypedBufferAccess;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferExecFuture;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::PrimaryAutoCommandBuffer;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use crate::device::Device;
|
||||
@ -388,7 +389,11 @@ impl ImmutableImage {
|
||||
ImageLayout::ShaderReadOnlyOptimal,
|
||||
);
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::new(source.device().clone(), queue.family())?;
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
source.device().clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)?;
|
||||
cbb.copy_buffer_to_image_dimensions(
|
||||
source,
|
||||
init,
|
||||
|
@ -206,7 +206,7 @@ impl<'a> DeviceMemoryBuilder<'a> {
|
||||
}
|
||||
|
||||
// Private function -- no doc comment needed! Copied shamelessly and poorly from Ash.
|
||||
fn push_next<T: ExtendsMemoryAllocateInfo>(mut self, next: &mut T) -> DeviceMemoryBuilder<'a> {
|
||||
fn push_next<T: ExtendsMemoryAllocateInfo>(self, next: &mut T) -> DeviceMemoryBuilder<'a> {
|
||||
unsafe {
|
||||
let next_ptr = next as *mut T as *mut BaseOutStructure;
|
||||
let mut prev = self.allocate.pNext as *mut BaseOutStructure;
|
||||
|
@ -7,14 +7,7 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::check_errors;
|
||||
use crate::descriptor::descriptor::DescriptorDesc;
|
||||
use crate::descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||
use crate::descriptor::pipeline_layout::PipelineLayout;
|
||||
@ -25,18 +18,23 @@ use crate::descriptor::pipeline_layout::PipelineLayoutDescPcRange;
|
||||
use crate::descriptor::pipeline_layout::PipelineLayoutNotSupersetError;
|
||||
use crate::descriptor::pipeline_layout::PipelineLayoutSuperset;
|
||||
use crate::descriptor::pipeline_layout::PipelineLayoutSys;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::pipeline::cache::PipelineCache;
|
||||
use crate::pipeline::shader::EntryPointAbstract;
|
||||
use crate::pipeline::shader::SpecializationConstants;
|
||||
|
||||
use crate::check_errors;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::vk;
|
||||
use crate::Error;
|
||||
use crate::OomError;
|
||||
use crate::SafeDeref;
|
||||
use crate::VulkanObject;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A pipeline object that describes to the Vulkan implementation how it should perform compute
|
||||
/// operations.
|
||||
@ -409,6 +407,7 @@ mod tests {
|
||||
use crate::buffer::BufferUsage;
|
||||
use crate::buffer::CpuAccessibleBuffer;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::descriptor::descriptor::DescriptorBufferDesc;
|
||||
use crate::descriptor::descriptor::DescriptorDesc;
|
||||
use crate::descriptor::descriptor::DescriptorDescTy;
|
||||
@ -555,9 +554,12 @@ mod tests {
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut cbb =
|
||||
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
.unwrap();
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.dispatch([1, 1, 1], pipeline.clone(), set, (), vec![])
|
||||
.unwrap();
|
||||
let cb = cbb.build().unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user