mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 09:02:25 +00:00
Document shader safety requirements, make draw/dispatch unsafe (#2429)
* Document shader safety requirements, make draw/dispatch unsafe * Extra docs * Doctests * Max index value * Small change * Update vulkano/src/command_buffer/mod.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/command_buffer/mod.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> --------- Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
This commit is contained in:
parent
94a8fb9a43
commit
289ec102e0
@ -602,6 +602,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -631,13 +632,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
acquire_future.wait(None).unwrap();
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
|
@ -206,14 +206,12 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Note that we clone the pipeline and the set. Since they are both wrapped in an `Arc`,
|
||||
// this only clones the `Arc` and not the whole pipeline or set (which aren't cloneable
|
||||
// anyway). In this example we would avoid cloning them since this is the last time we use
|
||||
// them, but in real code you would probably need to clone them.
|
||||
builder
|
||||
// The command buffer only does one thing: execute the compute pipeline. This is called a
|
||||
// *dispatch* operation.
|
||||
//
|
||||
// Note that we clone the pipeline and the set. Since they are both wrapped in an `Arc`,
|
||||
// this only clones the `Arc` and not the whole pipeline or set (which aren't cloneable
|
||||
// anyway). In this example we would avoid cloning them since this is the last time we use
|
||||
// them, but in real code you would probably need to clone them.
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
@ -222,10 +220,14 @@ fn main() {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
// The command buffer only does one thing: execute the compute pipeline. This is called a
|
||||
// *dispatch* operation.
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
// Finish building the command buffer by calling `build`.
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
|
@ -379,6 +379,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -396,13 +397,15 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, buffer)
|
||||
.unwrap()
|
||||
.draw(num_vertices, 1, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(num_vertices, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -197,6 +197,7 @@ impl AmbientLightingSystem {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.set_viewport(0, [viewport].into_iter().collect())
|
||||
.unwrap()
|
||||
@ -212,9 +213,14 @@ impl AmbientLightingSystem {
|
||||
.push_constants(self.pipeline.layout().clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +211,7 @@ impl DirectionalLightingSystem {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.set_viewport(0, [viewport].into_iter().collect())
|
||||
.unwrap()
|
||||
@ -226,9 +227,14 @@ impl DirectionalLightingSystem {
|
||||
.push_constants(self.pipeline.layout().clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +224,7 @@ impl PointLightingSystem {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.set_viewport(0, [viewport].into_iter().collect())
|
||||
.unwrap()
|
||||
@ -239,9 +240,14 @@ impl PointLightingSystem {
|
||||
.push_constants(self.pipeline.layout().clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ impl TriangleDrawSystem {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.set_viewport(
|
||||
0,
|
||||
@ -158,9 +159,14 @@ impl TriangleDrawSystem {
|
||||
.bind_pipeline_graphics(self.pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw(self.vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -248,37 +248,23 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
#[allow(clippy::erasing_op, clippy::identity_op)]
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set.clone().offsets([0 * align as u32]),
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([12, 1, 1])
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set.clone().offsets([1 * align as u32]),
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([12, 1, 1])
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set.offsets([2 * align as u32]),
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([12, 1, 1])
|
||||
.unwrap();
|
||||
builder.bind_pipeline_compute(pipeline.clone()).unwrap();
|
||||
|
||||
for index in 0..3 {
|
||||
builder
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set.clone().offsets([index * align as u32]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([12, 1, 1]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = sync::now(device)
|
||||
|
@ -259,6 +259,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
@ -268,12 +269,19 @@ fn main() {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
// Note that dispatch dimensions must be proportional to the local size.
|
||||
.dispatch([1024 / local_size_x, 1024 / local_size_y, 1])
|
||||
.unwrap()
|
||||
builder
|
||||
.dispatch([1024 / local_size_x, 1024 / local_size_y, 1])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo::image_buffer(image, buf.clone()))
|
||||
.unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = sync::now(device)
|
||||
|
@ -401,6 +401,7 @@ mod linux {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -424,13 +425,15 @@ mod linux {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end.take().unwrap().join(acquire_future);
|
||||
|
||||
let future = future
|
||||
|
@ -485,6 +485,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -508,13 +509,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -432,6 +432,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -455,13 +456,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -450,6 +450,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -473,13 +474,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -489,9 +489,13 @@ fn main() -> Result<(), impl Error> {
|
||||
0,
|
||||
cs_desciptor_set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1, 1, 1])
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
@ -507,13 +511,16 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_graphics(render_pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertices)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
// The indirect draw call is placed in the command buffer with a reference to
|
||||
// the buffer that will contain the arguments for the draw.
|
||||
.draw_indirect(indirect_buffer)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
builder.draw_indirect(indirect_buffer).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = previous_frame_end
|
||||
|
@ -412,6 +412,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -429,18 +430,22 @@ fn main() -> Result<(), impl Error> {
|
||||
.unwrap()
|
||||
// We pass both our lists of vertices here.
|
||||
.bind_vertex_buffers(0, (vertex_buffer.clone(), instance_buffer.clone()))
|
||||
.unwrap()
|
||||
.draw(
|
||||
vertex_buffer.len() as u32,
|
||||
instance_buffer.len() as u32,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw(
|
||||
vertex_buffer.len() as u32,
|
||||
instance_buffer.len() as u32,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -168,15 +168,21 @@ impl FractalComputePipeline {
|
||||
max_iters: max_iters as i32,
|
||||
is_julia: is_julia as u32,
|
||||
};
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(self.pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(PipelineBindPoint::Compute, pipeline_layout.clone(), 0, set)
|
||||
.unwrap()
|
||||
.push_constants(pipeline_layout.clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.dispatch([image_extent[0] / 8, image_extent[1] / 8, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.dispatch([image_extent[0] / 8, image_extent[1] / 8, 1])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let finished = command_buffer.execute(self.queue.clone()).unwrap();
|
||||
finished.then_signal_fence_and_flush().unwrap().boxed()
|
||||
|
@ -215,7 +215,7 @@ impl PixelsDrawPipeline {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let desc_set = self.create_descriptor_set(image);
|
||||
|
||||
builder
|
||||
.set_viewport(
|
||||
0,
|
||||
@ -234,15 +234,20 @@ impl PixelsDrawPipeline {
|
||||
PipelineBindPoint::Graphics,
|
||||
self.pipeline.layout().clone(),
|
||||
0,
|
||||
desc_set,
|
||||
self.create_descriptor_set(image),
|
||||
)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertices.clone())
|
||||
.unwrap()
|
||||
.bind_index_buffer(self.indices.clone())
|
||||
.unwrap()
|
||||
.draw_indexed(self.indices.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw_indexed(self.indices.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +390,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -404,15 +405,19 @@ fn main() {
|
||||
.bind_pipeline_graphics(pipeline)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap()
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo::image_buffer(image, buf.clone()))
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let finished = command_buffer.execute(queue).unwrap();
|
||||
finished
|
||||
.then_signal_fence_and_flush()
|
||||
|
@ -200,9 +200,13 @@ impl GameOfLifeComputePipeline {
|
||||
.bind_descriptor_sets(PipelineBindPoint::Compute, pipeline_layout.clone(), 0, set)
|
||||
.unwrap()
|
||||
.push_constants(pipeline_layout.clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.dispatch([image_extent[0] / 8, image_extent[1] / 8, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.dispatch([image_extent[0] / 8, image_extent[1] / 8, 1])
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ impl PixelsDrawPipeline {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let desc_set = self.create_image_sampler_nearest(image);
|
||||
|
||||
builder
|
||||
.set_viewport(
|
||||
0,
|
||||
@ -230,15 +230,20 @@ impl PixelsDrawPipeline {
|
||||
PipelineBindPoint::Graphics,
|
||||
self.pipeline.layout().clone(),
|
||||
0,
|
||||
desc_set,
|
||||
self.create_image_sampler_nearest(image),
|
||||
)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, self.vertices.clone())
|
||||
.unwrap()
|
||||
.bind_index_buffer(self.indices.clone())
|
||||
.unwrap()
|
||||
.draw_indexed(self.indices.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw_indexed(self.indices.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -474,13 +474,15 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -342,8 +342,6 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Drawing commands are broadcast to each view in the view mask of the active renderpass which
|
||||
// means only a single draw call is needed to draw to multiple layers of the framebuffer.
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -356,12 +354,16 @@ fn main() {
|
||||
.bind_pipeline_graphics(pipeline)
|
||||
.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();
|
||||
|
||||
unsafe {
|
||||
// Drawing commands are broadcast to each view in the view mask of the active renderpass which
|
||||
// means only a single draw call is needed to draw to multiple layers of the framebuffer.
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
// Copy the image layers to different buffers to save them as individual images to disk.
|
||||
builder
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo {
|
||||
|
@ -191,6 +191,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
@ -202,9 +203,12 @@ fn main() {
|
||||
)
|
||||
.unwrap()
|
||||
.push_constants(pipeline.layout().clone(), 0, push_constants)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = sync::now(device)
|
||||
|
@ -419,6 +419,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -449,13 +450,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -553,6 +553,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -576,13 +577,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -358,6 +358,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -374,13 +375,15 @@ fn main() -> Result<(), impl Error> {
|
||||
.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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -172,6 +172,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
// Copy from the first half to the second half (inside the same buffer) before we run the
|
||||
// computation.
|
||||
@ -194,9 +195,12 @@ fn main() {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = sync::now(device)
|
||||
|
@ -177,6 +177,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
@ -186,9 +187,12 @@ fn main() {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = sync::now(device)
|
||||
.then_execute(queue, command_buffer)
|
||||
|
@ -203,6 +203,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
@ -214,11 +215,13 @@ fn main() {
|
||||
)
|
||||
.unwrap()
|
||||
.push_constants(pipeline.layout().clone(), 0, parameters)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = sync::now(queue.device().clone())
|
||||
.then_execute(queue.clone(), command_buffer)
|
||||
.unwrap()
|
||||
|
@ -595,6 +595,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
// Push constants for compute shader.
|
||||
.push_constants(compute_pipeline.layout().clone(), 0, push_constants)
|
||||
@ -608,10 +609,16 @@ fn main() -> Result<(), impl Error> {
|
||||
0, // Bind this descriptor set to index 0.
|
||||
descriptor_set.clone(),
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([PARTICLE_COUNT as u32 / 128, 1, 1])
|
||||
.unwrap()
|
||||
// Use render-pass to draw particles to swapchain.
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.dispatch([PARTICLE_COUNT as u32 / 128, 1, 1])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Use render-pass to draw particles to swapchain.
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0., 0., 0., 1.].into())],
|
||||
@ -625,13 +632,15 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_graphics(graphics_pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(PARTICLE_COUNT as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(PARTICLE_COUNT as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_future
|
||||
.join(acquire_future)
|
||||
.then_execute(queue.clone(), command_buffer)
|
||||
|
@ -178,6 +178,7 @@ fn main() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
@ -187,9 +188,12 @@ fn main() {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1024, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.dispatch([1024, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = sync::now(device)
|
||||
|
@ -375,6 +375,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -401,13 +402,17 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_vertex_buffers(0, (vertex_buffer.clone(), normals_buffer.clone()))
|
||||
.unwrap()
|
||||
.bind_index_buffer(index_buffer.clone())
|
||||
.unwrap()
|
||||
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -476,6 +476,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -492,13 +493,15 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_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();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -443,6 +443,7 @@ fn main() -> Result<(), impl Error> {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
@ -466,13 +467,15 @@ fn main() -> Result<(), impl Error> {
|
||||
)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.unwrap()
|
||||
.draw(vertex_buffer.len() as u32, 3, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
unsafe {
|
||||
builder.draw(vertex_buffer.len() as u32, 3, 0, 0).unwrap();
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
|
||||
let command_buffer = builder.end().unwrap();
|
||||
let future = previous_frame_end
|
||||
.take()
|
||||
.unwrap()
|
||||
|
@ -588,10 +588,10 @@ fn main() -> Result<(), impl Error> {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
// In order to draw, we have to build a *command buffer*. The command buffer object
|
||||
// In order to draw, we have to record a *command buffer*. The command buffer object
|
||||
// holds the list of commands that are going to be executed.
|
||||
//
|
||||
// Building a command buffer is an expensive operation (usually a few hundred
|
||||
// Recording a command buffer is an expensive operation (usually a few hundred
|
||||
// microseconds), but it is known to be a hot path in the driver and is expected to
|
||||
// be optimized.
|
||||
//
|
||||
@ -645,15 +645,21 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.unwrap()
|
||||
// We add a draw command.
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
// We add a draw command.
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder
|
||||
// We leave the render pass.
|
||||
.end_rendering()
|
||||
.unwrap();
|
||||
|
||||
// Finish building the command buffer by calling `build`.
|
||||
// Finish recording the command buffer by calling `end`.
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = previous_frame_end
|
||||
|
@ -591,10 +591,10 @@ fn main() -> Result<(), impl Error> {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
// In order to draw, we have to build a *command buffer*. The command buffer object
|
||||
// In order to draw, we have to record a *command buffer*. The command buffer object
|
||||
// holds the list of commands that are going to be executed.
|
||||
//
|
||||
// Building a command buffer is an expensive operation (usually a few hundred
|
||||
// Recording a command buffer is an expensive operation (usually a few hundred
|
||||
// microseconds), but it is known to be a hot path in the driver and is expected to
|
||||
// be optimized.
|
||||
//
|
||||
@ -644,16 +644,22 @@ fn main() -> Result<(), impl Error> {
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.unwrap()
|
||||
// We add a draw command.
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
builder
|
||||
// We add a draw command.
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder
|
||||
// We leave the render pass. Note that if we had multiple subpasses we could
|
||||
// have called `next_subpass` to jump to the next subpass.
|
||||
.end_render_pass(Default::default())
|
||||
.unwrap();
|
||||
|
||||
// Finish building the command buffer by calling `build`.
|
||||
// Finish recording the command buffer by calling `end`.
|
||||
let command_buffer = builder.end().unwrap();
|
||||
|
||||
let future = previous_frame_end
|
||||
|
@ -1,3 +1,5 @@
|
||||
#[cfg(doc)]
|
||||
use crate::device::{Features, Properties};
|
||||
use crate::{
|
||||
acceleration_structure::AccelerationStructure,
|
||||
buffer::{view::BufferView, BufferUsage, Subbuffer},
|
||||
@ -50,7 +52,14 @@ impl RecordingCommandBuffer {
|
||||
/// A compute pipeline must have been bound using
|
||||
/// [`bind_pipeline_compute`](Self::bind_pipeline_compute). Any resources used by the compute
|
||||
/// pipeline, such as descriptor sets, must have been set beforehand.
|
||||
pub fn dispatch(&mut self, group_counts: [u32; 3]) -> Result<&mut Self, Box<ValidationError>> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
pub unsafe fn dispatch(
|
||||
&mut self,
|
||||
group_counts: [u32; 3],
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_dispatch(group_counts)?;
|
||||
|
||||
unsafe { Ok(self.dispatch_unchecked(group_counts)) }
|
||||
@ -116,7 +125,13 @@ impl RecordingCommandBuffer {
|
||||
/// A compute pipeline must have been bound using
|
||||
/// [`bind_pipeline_compute`](Self::bind_pipeline_compute). Any resources used by the compute
|
||||
/// pipeline, such as descriptor sets, must have been set beforehand.
|
||||
pub fn dispatch_indirect(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - The [safety requirements for `DispatchIndirectCommand`](DispatchIndirectCommand#safety)
|
||||
/// apply.
|
||||
pub unsafe fn dispatch_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DispatchIndirectCommand]>,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
@ -197,7 +212,11 @@ impl RecordingCommandBuffer {
|
||||
/// pipeline, such as descriptor sets, vertex buffers and dynamic state, must have been set
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the provided vertex and
|
||||
/// instance ranges must be in range of the bound vertex buffers.
|
||||
pub fn draw(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
pub unsafe fn draw(
|
||||
&mut self,
|
||||
vertex_count: u32,
|
||||
instance_count: u32,
|
||||
@ -373,9 +392,9 @@ impl RecordingCommandBuffer {
|
||||
///
|
||||
/// One draw is performed for each [`DrawIndirectCommand`] struct in `indirect_buffer`.
|
||||
/// The maximum number of draw commands in the buffer is limited by the
|
||||
/// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) limit.
|
||||
/// This limit is 1 unless the
|
||||
/// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
|
||||
/// [`multi_draw_indirect`](Features::multi_draw_indirect) feature has been
|
||||
/// enabled.
|
||||
///
|
||||
/// A graphics pipeline must have been bound using
|
||||
@ -384,7 +403,13 @@ impl RecordingCommandBuffer {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the vertex and instance
|
||||
/// ranges of each `DrawIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
pub fn draw_indirect(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - The [safety requirements for `DrawIndirectCommand`](DrawIndirectCommand#safety)
|
||||
/// apply.
|
||||
pub unsafe fn draw_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndirectCommand]>,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
@ -489,7 +514,16 @@ impl RecordingCommandBuffer {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the provided instance
|
||||
/// range must be in range of the bound vertex buffers. The vertex indices in the index buffer
|
||||
/// must be in range of the bound vertex buffers.
|
||||
pub fn draw_indexed(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - Every vertex number that is retrieved from the index buffer must fall within the range of
|
||||
/// the bound vertex-rate vertex buffers.
|
||||
/// - Every vertex number that is retrieved from the index buffer, if it is not the special
|
||||
/// primitive restart value, must be no greater than the
|
||||
/// [`max_draw_indexed_index_value`](Properties::max_draw_indexed_index_value) device limit.
|
||||
pub unsafe fn draw_indexed(
|
||||
&mut self,
|
||||
index_count: u32,
|
||||
instance_count: u32,
|
||||
@ -702,9 +736,9 @@ impl RecordingCommandBuffer {
|
||||
///
|
||||
/// One draw is performed for each [`DrawIndexedIndirectCommand`] struct in `indirect_buffer`.
|
||||
/// The maximum number of draw commands in the buffer is limited by the
|
||||
/// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) limit.
|
||||
/// This limit is 1 unless the
|
||||
/// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
|
||||
/// [`multi_draw_indirect`](Features::multi_draw_indirect) feature has been
|
||||
/// enabled.
|
||||
///
|
||||
/// An index buffer must have been bound using
|
||||
@ -718,7 +752,13 @@ impl RecordingCommandBuffer {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the instance ranges of
|
||||
/// each `DrawIndexedIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
pub fn draw_indexed_indirect(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - The [safety requirements for `DrawIndexedIndirectCommand`](DrawIndexedIndirectCommand#safety)
|
||||
/// apply.
|
||||
pub unsafe fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
@ -1070,7 +1110,7 @@ impl RecordingCommandBuffer {
|
||||
is not equal to the view type required by the pipeline"
|
||||
)
|
||||
.into(),
|
||||
// vuids?
|
||||
vuids: vuids!(vuid_type, "viewType-07752"),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
@ -1147,7 +1187,7 @@ impl RecordingCommandBuffer {
|
||||
`{view_numeric_type:?}` numeric type"
|
||||
)
|
||||
.into(),
|
||||
// vuids?
|
||||
vuids: vuids!(vuid_type, "format-07753"),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
@ -1196,7 +1236,7 @@ impl RecordingCommandBuffer {
|
||||
sampler YCbCr conversion"
|
||||
)
|
||||
.into(),
|
||||
// vuids?
|
||||
vuids: vuids!(vuid_type, "None-06550", "ConstOffset-06551"),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
@ -62,26 +62,29 @@
|
||||
//! # let graphics_pipeline: std::sync::Arc<vulkano::pipeline::graphics::GraphicsPipeline> = return;
|
||||
//! # let command_buffer_allocator: std::sync::Arc<vulkano::command_buffer::allocator::StandardCommandBufferAllocator> = return;
|
||||
//! #
|
||||
//! let cb = RecordingCommandBuffer::new(
|
||||
//! let mut cb = RecordingCommandBuffer::new(
|
||||
//! command_buffer_allocator.clone(),
|
||||
//! queue.queue_family_index(),
|
||||
//! CommandBufferLevel::Primary,
|
||||
//! CommandBufferBeginInfo::default(),
|
||||
//! )
|
||||
//! .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()
|
||||
//! .end()
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! cb.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();
|
||||
//!
|
||||
//! unsafe {
|
||||
//! cb.draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap();
|
||||
//! }
|
||||
//!
|
||||
//! cb.end_render_pass(Default::default()).unwrap();
|
||||
//!
|
||||
//! let cb = cb.end().unwrap();
|
||||
//!
|
||||
//! let future = cb.execute(queue.clone());
|
||||
//! ```
|
||||
//!
|
||||
@ -115,6 +118,11 @@ use crate::{
|
||||
},
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError,
|
||||
};
|
||||
#[cfg(doc)]
|
||||
use crate::{
|
||||
device::{Features, Properties},
|
||||
pipeline::graphics::vertex_input::VertexInputRate,
|
||||
};
|
||||
use ahash::HashMap;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
@ -126,6 +134,35 @@ pub mod pool;
|
||||
pub mod sys;
|
||||
mod traits;
|
||||
|
||||
/// Used as buffer contents to provide input for the
|
||||
/// [`RecordingCommandBuffer::dispatch_indirect`] command.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The `x`, `y` and `z` values must not be greater than the respective elements of the
|
||||
/// [`max_compute_work_group_count`](Properties::max_compute_work_group_count) device limit.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)]
|
||||
pub struct DispatchIndirectCommand {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub z: u32,
|
||||
}
|
||||
|
||||
/// Used as buffer contents to provide input for the
|
||||
/// [`RecordingCommandBuffer::draw_indirect`] command.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - Every vertex number within the specified range must fall within the range of
|
||||
/// the bound vertex-rate vertex buffers.
|
||||
/// - Every instance number within the specified range must fall within the range of
|
||||
/// the bound instance-rate vertex buffers.
|
||||
/// - If the [`draw_indirect_first_instance`](Features::draw_indirect_first_instance) feature
|
||||
/// is not enabled, then `first_instance` must be `0`.
|
||||
/// - If an [instance divisor](VertexInputRate::Instance) other than 1 is used, and
|
||||
/// the [`supports_non_zero_first_instance`](Properties::supports_non_zero_first_instance)
|
||||
/// device property is `false`, then `first_instance` must be `0`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)]
|
||||
pub struct DrawIndirectCommand {
|
||||
@ -135,6 +172,24 @@ pub struct DrawIndirectCommand {
|
||||
pub first_instance: u32,
|
||||
}
|
||||
|
||||
/// Used as buffer contents to provide input for the
|
||||
/// [`RecordingCommandBuffer::draw_indexed_indirect`] command.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - Every index within the specified range must fall within the range of the bound index buffer.
|
||||
/// - Every vertex number that is retrieved from the index buffer must fall within the range of
|
||||
/// the bound vertex-rate vertex buffers.
|
||||
/// - Every vertex number that is retrieved from the index buffer, if it is not the special
|
||||
/// primitive restart value, must be no greater than the
|
||||
/// [`max_draw_indexed_index_value`](Properties::max_draw_indexed_index_value) device limit.
|
||||
/// - Every instance number within the specified range must fall within the range of
|
||||
/// the bound instance-rate vertex buffers.
|
||||
/// - If the [`draw_indirect_first_instance`](Features::draw_indirect_first_instance) feature
|
||||
/// is not enabled, then `first_instance` must be `0`.
|
||||
/// - If an [instance divisor](VertexInputRate::Instance) other than 1 is used, and
|
||||
/// the [`supports_non_zero_first_instance`](Properties::supports_non_zero_first_instance)
|
||||
/// device property is `false`, then `first_instance` must be `0`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)]
|
||||
pub struct DrawIndexedIndirectCommand {
|
||||
@ -145,14 +200,6 @@ pub struct DrawIndexedIndirectCommand {
|
||||
pub first_instance: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)]
|
||||
pub struct DispatchIndirectCommand {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub z: u32,
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
#[non_exhaustive]
|
||||
|
||||
|
@ -567,6 +567,7 @@ mod tests {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
cbb.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
@ -575,9 +576,12 @@ mod tests {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([1, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
cbb.dispatch([1, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let cb = cbb.end().unwrap();
|
||||
|
||||
let future = now(device)
|
||||
@ -718,6 +722,7 @@ mod tests {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
cbb.bind_pipeline_compute(pipeline.clone())
|
||||
.unwrap()
|
||||
.bind_descriptor_sets(
|
||||
@ -726,9 +731,12 @@ mod tests {
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch([128, 1, 1])
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
cbb.dispatch([128, 1, 1]).unwrap();
|
||||
}
|
||||
|
||||
let cb = cbb.end().unwrap();
|
||||
|
||||
let future = now(device)
|
||||
|
@ -117,12 +117,141 @@
|
||||
//! of the alignments of its members. As with arrays, in the extended alignment, the alignment
|
||||
//! of a struct is at least 16.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! The following general safety requirements apply to the descriptors in a shader, and to the
|
||||
//! resources that were bound to them. They apply to all shader types, and must be met at the
|
||||
//! moment the shader executes on the device.
|
||||
//!
|
||||
//! Vulkano will validate many of these requirements, but it is only able to do so when the
|
||||
//! resources involved are statically known. This means that either the descriptor binding must not
|
||||
//! be arrayed, or if it is arrayed, that the array must be indexed only by constants. If the
|
||||
//! array index is dynamic (meaning that it depends on values that are inputs to the shader),
|
||||
//! then Vulkano cannot check these requirements, and you must ensure them yourself.
|
||||
//!
|
||||
//! Some requirements, such as the validity of pointers to device memory, cannot be validated
|
||||
//! by Vulkano at all.
|
||||
//!
|
||||
//! ## Descriptors
|
||||
//!
|
||||
//! - If a descriptor set binding was created with [`DescriptorBindingFlags::PARTIALLY_BOUND`],
|
||||
//! then if the shader accesses a descriptor in that binding, the descriptor must be initialized
|
||||
//! and contain a valid resource.
|
||||
//!
|
||||
//! ## Buffers
|
||||
//!
|
||||
//! - If the [`robust_buffer_access`](Features::robust_buffer_access) feature is not enabled
|
||||
//! on the device, then the shader must not access any values outside the range of the buffer,
|
||||
//! as specified when writing the descriptor set.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-uniformBuffers-06935)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-storageBuffers-06936)
|
||||
//! - If any `PhysicalStorageBuffer` pointers to device memory are dereferenced in the shader,
|
||||
//! then they must point to valid buffer memory of the correct type.
|
||||
//!
|
||||
//! ## Image views and buffer views
|
||||
//!
|
||||
//! - The [`view_type`](ImageView::view_type) of the bound image view
|
||||
//! must match the `Dim` operand of the `OpImageType`.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-viewType-07752)
|
||||
//! - The numeric type of the [`format`](ImageView::format) of the bound image view
|
||||
//! must match the `Sampled Type` operand of the `OpImageType`.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-format-07753)
|
||||
//! - For every `OpImageWrite` instruction, the type of the `Texel` operand must have at least
|
||||
//! as many components as the format of the bound image view or buffer view.
|
||||
//! If the bound image view's format is [`Format::A8_UNORM`], then the type of the `Texel`
|
||||
//! operand must have four components.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpImageWrite-04469)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpImageWrite-08795)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpImageWrite-08796)
|
||||
//! - The `Sampled Type` operand of the `OpTypeImage` declaration must have a `Width` of 64,
|
||||
//! if and only if the format of the bound image view or buffer view also has a 64-bit component.
|
||||
//! Otherwise, it must have a `Width` of 32.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-SampledType-04470)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-SampledType-04471)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-SampledType-04472)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-SampledType-04473)
|
||||
//! - For a storage image/texel buffer declared with `OpTypeImage` with an `Unknown` format:
|
||||
//! - If it is written to in the shader, the format of the bound image view or buffer view must
|
||||
//! have the [`FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT`] format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpTypeImage-07027)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpTypeImage-07029)
|
||||
//! - If it is read from in the shader, the format of the bound image view or buffer view must
|
||||
//! have the [`FormatFeatures::STORAGE_READ_WITHOUT_FORMAT`] format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpTypeImage-07028)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpTypeImage-07030)
|
||||
//! - If atomic operations are used on a storage image/texel buffer:
|
||||
//! - The bound image view's format must have the [`FormatFeatures::STORAGE_IMAGE_ATOMIC`]
|
||||
//! format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-02691)
|
||||
//! - The bound buffer view's format must have the [`FormatFeatures::STORAGE_TEXEL_BUFFER_ATOMIC`]
|
||||
//! format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-07888)
|
||||
//!
|
||||
//! ## Image sampling
|
||||
//!
|
||||
//! If the bound sampler uses [`Filter::Linear`] or [`SamplerMipmapMode::Linear`]:
|
||||
//! - The bound image view's format must have the [`FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR`]
|
||||
//! format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-magFilter-04553)
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-mipmapMode-04770)
|
||||
//!
|
||||
//! If the bound sampler uses [`Filter::Cubic`]:
|
||||
//! - The bound image view's format must have the [`FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC`]
|
||||
//! format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-02692)
|
||||
//! - The bound image view's type and format must support cubic filtering, as indicated in
|
||||
//! [`ImageFormatProperties::filter_cubic`] returned from
|
||||
//! [`PhysicalDevice::image_format_properties`].
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-filterCubic-02694)
|
||||
//! - If the sampler's reduction mode is [`SamplerReductionMode::Min`] or
|
||||
//! [`SamplerReductionMode::Max`], the image view type and format must support cubic minmax
|
||||
//! filtering, as indicated in [`ImageFormatProperties::filter_cubic_minmax`] returned from
|
||||
//! [`PhysicalDevice::image_format_properties`].
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-filterCubicMinmax-02695)
|
||||
//!
|
||||
//! If the bound sampler uses [depth comparison](SamplerCreateInfo::compare):
|
||||
//! - The bound image view's format must have the [`FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON`]
|
||||
//! format feature.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-06479)
|
||||
//!
|
||||
//! If the bound sampler uses [unnormalized coordinates](SamplerCreateInfo::unnormalized_coordinates):
|
||||
//! - The bound image view must have a type of [`ImageViewType::Dim1d`] or [`ImageViewType::Dim2d`].
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-08609)
|
||||
//! - The sampler must not be used in any `OpImageSample*` or `OpImageSparseSample*` instructions,
|
||||
//! that contain `ImplicitLod`, `Dref` or `Proj` in their name.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-08610)
|
||||
//! - The sampler must not be used in any `OpImageSample*` or `OpImageSparseSample*` instructions,
|
||||
//! that include an LOD bias or offset operand.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-08611)
|
||||
//!
|
||||
//! If the bound sampler has a [sampler YCbCr conversion](crate::image::sampler::ycbcr):
|
||||
//! - The sampler must only be used in `OpImageSample*` or `OpImageSparseSample*` instructions.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-None-06550)
|
||||
//! - The sampler must not be used with the `ConstOffset` or `Offset` image operands.
|
||||
//! [\[spec\]](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-ConstOffset-06551)
|
||||
//!
|
||||
//! ## Acceleration structures
|
||||
//!
|
||||
//! - In any top-level acceleration structure, the pointers that refer to the contained
|
||||
//! bottom-level acceleration structure instances must point to valid acceleration structures.
|
||||
//!
|
||||
//! [alignment rules]: <https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html#interfaces-resources-layout>
|
||||
//! [`GL_EXT_scalar_block_layout`]: <https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_scalar_block_layout.txt>
|
||||
//! [`scalar_block_layout`]: crate::device::Features::scalar_block_layout
|
||||
//! [`uniform_buffer_standard_layout`]: crate::device::Features::uniform_buffer_standard_layout
|
||||
|
||||
use self::spirv::{Id, Instruction};
|
||||
#[cfg(doc)]
|
||||
use crate::{
|
||||
descriptor_set::layout::DescriptorBindingFlags,
|
||||
device::{physical::PhysicalDevice, Features},
|
||||
format::FormatFeatures,
|
||||
image::{
|
||||
sampler::{Filter, Sampler, SamplerCreateInfo, SamplerMipmapMode, SamplerReductionMode},
|
||||
view::ImageView,
|
||||
ImageFormatProperties,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
descriptor_set::layout::DescriptorType,
|
||||
device::{Device, DeviceOwned},
|
||||
|
Loading…
Reference in New Issue
Block a user